diff --git a/ci/rustfmt.sh b/ci/rustfmt.sh index 973f79ebe5c..82de394169c 100755 --- a/ci/rustfmt.sh +++ b/ci/rustfmt.sh @@ -13,9 +13,4 @@ VERS="" [ "$(which rustup)" != "" ] && VERS="+1.63.0" # Run fmt -TMP_FILE=$(mktemp) -git ls-files | grep '.rs$' | sort >"$TMP_FILE" -for file in $(comm -23 "$TMP_FILE" rustfmt_excluded_files); do - echo "Checking formatting of $file" - rustfmt $VERS --edition 2021 --check "$file" -done +cargo $VERS fmt --check diff --git a/contrib/run-rustfmt.sh b/contrib/run-rustfmt.sh deleted file mode 100755 index 2ef82c5a3e4..00000000000 --- a/contrib/run-rustfmt.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -eo pipefail - -export LC_ALL=C - -# Generate initial exclusion list -#find . -name '*.rs' -type f |sort >rustfmt_excluded_files - -# The +rustversion syntax only works with rustup-installed rust toolchains, -# not with any distro-provided ones. Thus, we check for a rustup install and -# only pass +1.63.0 if we find one. -VERS="" -[ "$(which rustup)" != "" ] && VERS="+1.63.0" - -# Run fmt -TMP_FILE=$(mktemp) -git ls-files | grep '.rs$' | sort >"$TMP_FILE" -for file in $(comm -23 "$TMP_FILE" rustfmt_excluded_files); do - echo "Formatting $file..." - rustfmt $VERS --edition 2021 "$file" -done diff --git a/lightning/src/chain/chaininterface.rs b/lightning/src/chain/chaininterface.rs index ebef21657b7..b6198215bcb 100644 --- a/lightning/src/chain/chaininterface.rs +++ b/lightning/src/chain/chaininterface.rs @@ -187,25 +187,29 @@ pub const FEERATE_FLOOR_SATS_PER_KW: u32 = 253; /// /// Note that this does *not* implement [`FeeEstimator`] to make it harder to accidentally mix the /// two. -pub(crate) struct LowerBoundedFeeEstimator(pub F) where F::Target: FeeEstimator; - -impl LowerBoundedFeeEstimator where F::Target: FeeEstimator { +pub(crate) struct LowerBoundedFeeEstimator(pub F) +where + F::Target: FeeEstimator; + +impl LowerBoundedFeeEstimator +where + F::Target: FeeEstimator, +{ /// Creates a new `LowerBoundedFeeEstimator` which wraps the provided fee_estimator pub fn new(fee_estimator: F) -> Self { LowerBoundedFeeEstimator(fee_estimator) } pub fn bounded_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 { - cmp::max( - self.0.get_est_sat_per_1000_weight(confirmation_target), - FEERATE_FLOOR_SATS_PER_KW, - ) + cmp::max(self.0.get_est_sat_per_1000_weight(confirmation_target), FEERATE_FLOOR_SATS_PER_KW) } } #[cfg(test)] mod tests { - use super::{FEERATE_FLOOR_SATS_PER_KW, LowerBoundedFeeEstimator, ConfirmationTarget, FeeEstimator}; + use super::{ + ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator, FEERATE_FLOOR_SATS_PER_KW, + }; struct TestFeeEstimator { sat_per_kw: u32, @@ -223,7 +227,10 @@ mod tests { let test_fee_estimator = &TestFeeEstimator { sat_per_kw }; let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator); - assert_eq!(fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee), FEERATE_FLOOR_SATS_PER_KW); + assert_eq!( + fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee), + FEERATE_FLOOR_SATS_PER_KW + ); } #[test] @@ -232,6 +239,9 @@ mod tests { let test_fee_estimator = &TestFeeEstimator { sat_per_kw }; let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator); - assert_eq!(fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee), sat_per_kw); + assert_eq!( + fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee), + sat_per_kw + ); } } diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index c2b0a62e2d5..b87ec0a4733 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -24,27 +24,30 @@ //! servicing [`ChannelMonitor`] updates from the client. use bitcoin::block::Header; -use bitcoin::hash_types::{Txid, BlockHash}; +use bitcoin::hash_types::{BlockHash, Txid}; use crate::chain; -use crate::chain::{ChannelMonitorUpdateStatus, Filter, WatchedOutput}; use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, Balance, MonitorEvent, TransactionOutputs, WithChannelMonitor}; +use crate::chain::channelmonitor::{ + Balance, ChannelMonitor, ChannelMonitorUpdate, MonitorEvent, TransactionOutputs, + WithChannelMonitor, +}; use crate::chain::transaction::{OutPoint, TransactionData}; +use crate::chain::{ChannelMonitorUpdateStatus, Filter, WatchedOutput}; +use crate::events::{self, Event, EventHandler, ReplayEvent}; +use crate::ln::channel_state::ChannelDetails; use crate::ln::types::ChannelId; use crate::sign::ecdsa::EcdsaChannelSigner; -use crate::events::{self, Event, EventHandler, ReplayEvent}; -use crate::util::logger::{Logger, WithContext}; use crate::util::errors::APIError; +use crate::util::logger::{Logger, WithContext}; use crate::util::persist::MonitorName; use crate::util::wakers::{Future, Notifier}; -use crate::ln::channel_state::ChannelDetails; use crate::prelude::*; -use crate::sync::{RwLock, RwLockReadGuard, Mutex, MutexGuard}; +use crate::sync::{Mutex, MutexGuard, RwLock, RwLockReadGuard}; +use bitcoin::secp256k1::PublicKey; use core::ops::Deref; use core::sync::atomic::{AtomicUsize, Ordering}; -use bitcoin::secp256k1::PublicKey; /// `Persist` defines behavior for persisting channel monitors: this could mean /// writing once to disk, and/or uploading to one or more backup services. @@ -120,7 +123,9 @@ pub trait Persist { /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [`Writeable::write`]: crate::util::ser::Writeable::write - fn persist_new_channel(&self, monitor_name: MonitorName, monitor: &ChannelMonitor) -> ChannelMonitorUpdateStatus; + fn persist_new_channel( + &self, monitor_name: MonitorName, monitor: &ChannelMonitor, + ) -> ChannelMonitorUpdateStatus; /// Update one channel's data. The provided [`ChannelMonitor`] has already applied the given /// update. @@ -159,7 +164,10 @@ pub trait Persist { /// [`ChannelMonitorUpdateStatus`] for requirements when returning errors. /// /// [`Writeable::write`]: crate::util::ser::Writeable::write - fn update_persisted_channel(&self, monitor_name: MonitorName, monitor_update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor) -> ChannelMonitorUpdateStatus; + fn update_persisted_channel( + &self, monitor_name: MonitorName, monitor_update: Option<&ChannelMonitorUpdate>, + monitor: &ChannelMonitor, + ) -> ChannelMonitorUpdateStatus; /// Prevents the channel monitor from being loaded on startup. /// /// Archiving the data in a backup location (rather than deleting it fully) is useful for @@ -231,12 +239,19 @@ impl Deref for LockedChannelMonitor<'_, Chann /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [module-level documentation]: crate::chain::chainmonitor /// [`rebroadcast_pending_claims`]: Self::rebroadcast_pending_claims -pub struct ChainMonitor - where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +pub struct ChainMonitor< + ChannelSigner: EcdsaChannelSigner, + C: Deref, + T: Deref, + F: Deref, + L: Deref, + P: Deref, +> where + C::Target: chain::Filter, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, { monitors: RwLock>>, chain_source: Option, @@ -255,12 +270,14 @@ pub struct ChainMonitor ChainMonitor -where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +impl + ChainMonitor +where + C::Target: chain::Filter, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, { /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view /// of a channel and reacting accordingly based on transactions in the given chain data. See @@ -273,9 +290,10 @@ where C::Target: chain::Filter, /// updated `txdata`. /// /// Calls which represent a new blockchain tip height should set `best_height`. - fn process_chain_data(&self, header: &Header, best_height: Option, txdata: &TransactionData, process: FN) - where - FN: Fn(&ChannelMonitor, &TransactionData) -> Vec + fn process_chain_data( + &self, header: &Header, best_height: Option, txdata: &TransactionData, process: FN, + ) where + FN: Fn(&ChannelMonitor, &TransactionData) -> Vec, { let err_str = "ChannelMonitor[Update] persistence failed unrecoverably. This indicates we cannot continue normal operation and must shut down."; let channel_ids = hash_set_from_iter(self.monitors.read().unwrap().keys().cloned()); @@ -283,7 +301,18 @@ where C::Target: chain::Filter, for channel_id in channel_ids.iter() { let monitor_lock = self.monitors.read().unwrap(); if let Some(monitor_state) = monitor_lock.get(channel_id) { - if self.update_monitor_with_chain_data(header, best_height, txdata, &process, channel_id, &monitor_state, channel_count).is_err() { + if self + .update_monitor_with_chain_data( + header, + best_height, + txdata, + &process, + channel_id, + &monitor_state, + channel_count, + ) + .is_err() + { // Take the monitors lock for writing so that we poison it and any future // operations going forward fail immediately. core::mem::drop(monitor_lock); @@ -298,7 +327,18 @@ where C::Target: chain::Filter, let monitor_states = self.monitors.write().unwrap(); for (channel_id, monitor_state) in monitor_states.iter() { if !channel_ids.contains(channel_id) { - if self.update_monitor_with_chain_data(header, best_height, txdata, &process, channel_id, &monitor_state, channel_count).is_err() { + if self + .update_monitor_with_chain_data( + header, + best_height, + txdata, + &process, + channel_id, + &monitor_state, + channel_count, + ) + .is_err() + { log_error!(self.logger, "{}", err_str); panic!("{}", err_str); } @@ -317,9 +357,12 @@ where C::Target: chain::Filter, } fn update_monitor_with_chain_data( - &self, header: &Header, best_height: Option, txdata: &TransactionData, process: FN, channel_id: &ChannelId, - monitor_state: &MonitorHolder, channel_count: usize, - ) -> Result<(), ()> where FN: Fn(&ChannelMonitor, &TransactionData) -> Vec { + &self, header: &Header, best_height: Option, txdata: &TransactionData, process: FN, + channel_id: &ChannelId, monitor_state: &MonitorHolder, channel_count: usize, + ) -> Result<(), ()> + where + FN: Fn(&ChannelMonitor, &TransactionData) -> Vec, + { let monitor = &monitor_state.monitor; let logger = WithChannelMonitor::from(&self.logger, &monitor, None); @@ -327,7 +370,12 @@ where C::Target: chain::Filter, let get_partition_key = |channel_id: &ChannelId| { let channel_id_bytes = channel_id.0; - let channel_id_u32 = u32::from_be_bytes([channel_id_bytes[0], channel_id_bytes[1], channel_id_bytes[2], channel_id_bytes[3]]); + let channel_id_u32 = u32::from_be_bytes([ + channel_id_bytes[0], + channel_id_bytes[1], + channel_id_bytes[2], + channel_id_bytes[3], + ]); channel_id_u32.wrapping_add(best_height.unwrap_or_default()) }; @@ -339,23 +387,33 @@ where C::Target: chain::Filter, let has_pending_claims = monitor_state.monitor.has_pending_claims(); if has_pending_claims || get_partition_key(channel_id) % partition_factor == 0 { - log_trace!(logger, "Syncing Channel Monitor for channel {}", log_funding_info!(monitor)); + log_trace!( + logger, + "Syncing Channel Monitor for channel {}", + log_funding_info!(monitor) + ); // Even though we don't track monitor updates from chain-sync as pending, we still want // updates per-channel to be well-ordered so that users don't see a // `ChannelMonitorUpdate` after a channel persist for a channel with the same // `latest_update_id`. let _pending_monitor_updates = monitor_state.pending_monitor_updates.lock().unwrap(); - match self.persister.update_persisted_channel(monitor.persistence_key(), None, monitor) { - ChannelMonitorUpdateStatus::Completed => - log_trace!(logger, "Finished syncing Channel Monitor for channel {} for block-data", - log_funding_info!(monitor) - ), + match self.persister.update_persisted_channel(monitor.persistence_key(), None, monitor) + { + ChannelMonitorUpdateStatus::Completed => log_trace!( + logger, + "Finished syncing Channel Monitor for channel {} for block-data", + log_funding_info!(monitor) + ), ChannelMonitorUpdateStatus::InProgress => { - log_trace!(logger, "Channel Monitor sync for channel {} in progress.", log_funding_info!(monitor)); - } + log_trace!( + logger, + "Channel Monitor sync for channel {} in progress.", + log_funding_info!(monitor) + ); + }, ChannelMonitorUpdateStatus::UnrecoverableError => { return Err(()); - } + }, } } @@ -371,7 +429,11 @@ where C::Target: chain::Filter, outpoint: OutPoint { txid, index: idx as u16 }, script_pubkey: output.script_pubkey, }; - log_trace!(logger, "Adding monitoring for spends of outpoint {} to the filter", output.outpoint); + log_trace!( + logger, + "Adding monitoring for spends of outpoint {} to the filter", + output.outpoint + ); chain_source.register_output(output); } } @@ -386,7 +448,9 @@ where C::Target: chain::Filter, /// pre-filter blocks or only fetch blocks matching a compact filter. Otherwise, clients may /// always need to fetch full blocks absent another means for determining which blocks contain /// transactions relevant to the watched channels. - pub fn new(chain_source: Option, broadcaster: T, logger: L, feeest: F, persister: P) -> Self { + pub fn new( + chain_source: Option, broadcaster: T, logger: L, feeest: F, persister: P, + ) -> Self { Self { monitors: RwLock::new(new_hash_map()), chain_source, @@ -429,7 +493,9 @@ where C::Target: chain::Filter, /// /// Note that the result holds a mutex over our monitor set, and should not be held /// indefinitely. - pub fn get_monitor(&self, channel_id: ChannelId) -> Result, ()> { + pub fn get_monitor( + &self, channel_id: ChannelId, + ) -> Result, ()> { let lock = self.monitors.read().unwrap(); if lock.get(&channel_id).is_some() { Ok(LockedChannelMonitor { lock, channel_id }) @@ -463,12 +529,16 @@ where C::Target: chain::Filter, /// that have not yet been fully persisted. Note that if a full monitor is persisted all the pending /// monitor updates must be individually marked completed by calling [`ChainMonitor::channel_monitor_updated`]. pub fn list_pending_monitor_updates(&self) -> Vec<(ChannelId, Vec)> { - self.monitors.read().unwrap().iter().map(|(channel_id, holder)| { - (*channel_id, holder.pending_monitor_updates.lock().unwrap().clone()) - }).collect() + self.monitors + .read() + .unwrap() + .iter() + .map(|(channel_id, holder)| { + (*channel_id, holder.pending_monitor_updates.lock().unwrap().clone()) + }) + .collect() } - #[cfg(any(test, feature = "_test_utils"))] pub fn remove_monitor(&self, channel_id: &ChannelId) -> ChannelMonitor { self.monitors.write().unwrap().remove(channel_id).unwrap().monitor @@ -494,10 +564,16 @@ where C::Target: chain::Filter, /// /// Returns an [`APIError::APIMisuseError`] if `funding_txo` does not match any currently /// registered [`ChannelMonitor`]s. - pub fn channel_monitor_updated(&self, channel_id: ChannelId, completed_update_id: u64) -> Result<(), APIError> { + pub fn channel_monitor_updated( + &self, channel_id: ChannelId, completed_update_id: u64, + ) -> Result<(), APIError> { let monitors = self.monitors.read().unwrap(); - let monitor_data = if let Some(mon) = monitors.get(&channel_id) { mon } else { - return Err(APIError::APIMisuseError { err: format!("No ChannelMonitor matching channel ID {} found", channel_id) }); + let monitor_data = if let Some(mon) = monitors.get(&channel_id) { + mon + } else { + return Err(APIError::APIMisuseError { + err: format!("No ChannelMonitor matching channel ID {} found", channel_id), + }); }; let mut pending_monitor_updates = monitor_data.pending_monitor_updates.lock().unwrap(); pending_monitor_updates.retain(|update_id| *update_id != completed_update_id); @@ -505,25 +581,33 @@ where C::Target: chain::Filter, // Note that we only check for pending non-chainsync monitor updates and we don't track monitor // updates resulting from chainsync in `pending_monitor_updates`. let monitor_is_pending_updates = monitor_data.has_pending_updates(&pending_monitor_updates); - log_debug!(self.logger, "Completed off-chain monitor update {} for channel with channel ID {}, {}", + log_debug!( + self.logger, + "Completed off-chain monitor update {} for channel with channel ID {}, {}", completed_update_id, channel_id, if monitor_is_pending_updates { "still have pending off-chain updates" } else { "all off-chain updates complete, returning a MonitorEvent" - }); + } + ); if monitor_is_pending_updates { // If there are still monitor updates pending, we cannot yet construct a // Completed event. return Ok(()); } let funding_txo = monitor_data.monitor.get_funding_txo(); - self.pending_monitor_events.lock().unwrap().push((funding_txo, channel_id, vec![MonitorEvent::Completed { + self.pending_monitor_events.lock().unwrap().push(( funding_txo, channel_id, - monitor_update_id: monitor_data.monitor.get_latest_update_id(), - }], monitor_data.monitor.get_counterparty_node_id())); + vec![MonitorEvent::Completed { + funding_txo, + channel_id, + monitor_update_id: monitor_data.monitor.get_latest_update_id(), + }], + monitor_data.monitor.get_counterparty_node_id(), + )); self.event_notifier.notify(); Ok(()) @@ -538,11 +622,12 @@ where C::Target: chain::Filter, let monitor = &monitors.get(&channel_id).unwrap().monitor; let counterparty_node_id = monitor.get_counterparty_node_id(); let funding_txo = monitor.get_funding_txo(); - self.pending_monitor_events.lock().unwrap().push((funding_txo, channel_id, vec![MonitorEvent::Completed { + self.pending_monitor_events.lock().unwrap().push(( funding_txo, channel_id, - monitor_update_id, - }], counterparty_node_id)); + vec![MonitorEvent::Completed { funding_txo, channel_id, monitor_update_id }], + counterparty_node_id, + )); self.event_notifier.notify(); } @@ -561,8 +646,11 @@ where C::Target: chain::Filter, /// See the trait-level documentation of [`EventsProvider`] for requirements. /// /// [`EventsProvider`]: crate::events::EventsProvider - pub async fn process_pending_events_async>, H: Fn(Event) -> Future>( - &self, handler: H + pub async fn process_pending_events_async< + Future: core::future::Future>, + H: Fn(Event) -> Future, + >( + &self, handler: H, ) { // Sadly we can't hold the monitors read lock through an async call. Thus we have to do a // crazy dance to process a monitor's events then only remove them once we've done so. @@ -570,11 +658,15 @@ where C::Target: chain::Filter, for channel_id in mons_to_process { let mut ev; match super::channelmonitor::process_events_body!( - self.monitors.read().unwrap().get(&channel_id).map(|m| &m.monitor), self.logger, ev, handler(ev).await) { + self.monitors.read().unwrap().get(&channel_id).map(|m| &m.monitor), + self.logger, + ev, + handler(ev).await + ) { Ok(()) => {}, - Err(ReplayEvent ()) => { + Err(ReplayEvent()) => { self.event_notifier.notify(); - } + }, } } } @@ -600,7 +692,9 @@ where C::Target: chain::Filter, let monitors = self.monitors.read().unwrap(); for (_, monitor_holder) in &*monitors { monitor_holder.monitor.rebroadcast_pending_claims( - &*self.broadcaster, &*self.fee_estimator, &self.logger + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, ) } } @@ -614,13 +708,17 @@ where C::Target: chain::Filter, if let Some(channel_id) = monitor_opt { if let Some(monitor_holder) = monitors.get(&channel_id) { monitor_holder.monitor.signer_unblocked( - &*self.broadcaster, &*self.fee_estimator, &self.logger + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, ) } } else { for (_, monitor_holder) in &*monitors { monitor_holder.monitor.signer_unblocked( - &*self.broadcaster, &*self.fee_estimator, &self.logger + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, ) } } @@ -639,25 +737,33 @@ where C::Target: chain::Filter, let mut have_monitors_to_prune = false; for monitor_holder in self.monitors.read().unwrap().values() { let logger = WithChannelMonitor::from(&self.logger, &monitor_holder.monitor, None); - let (is_fully_resolved, needs_persistence) = monitor_holder.monitor.check_and_update_full_resolution_status(&logger); + let (is_fully_resolved, needs_persistence) = + monitor_holder.monitor.check_and_update_full_resolution_status(&logger); if is_fully_resolved { have_monitors_to_prune = true; } if needs_persistence { - self.persister.update_persisted_channel(monitor_holder.monitor.persistence_key(), None, &monitor_holder.monitor); + self.persister.update_persisted_channel( + monitor_holder.monitor.persistence_key(), + None, + &monitor_holder.monitor, + ); } } if have_monitors_to_prune { let mut monitors = self.monitors.write().unwrap(); monitors.retain(|channel_id, monitor_holder| { let logger = WithChannelMonitor::from(&self.logger, &monitor_holder.monitor, None); - let (is_fully_resolved, _) = monitor_holder.monitor.check_and_update_full_resolution_status(&logger); + let (is_fully_resolved, _) = + monitor_holder.monitor.check_and_update_full_resolution_status(&logger); if is_fully_resolved { - log_info!(logger, + log_info!( + logger, "Archiving fully resolved ChannelMonitor for channel ID {}", channel_id ); - self.persister.archive_persisted_channel(monitor_holder.monitor.persistence_key()); + self.persister + .archive_persisted_channel(monitor_holder.monitor.persistence_key()); false } else { true @@ -668,7 +774,7 @@ where C::Target: chain::Filter, } impl -chain::Listen for ChainMonitor + chain::Listen for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, @@ -677,10 +783,21 @@ where P::Target: Persist, { fn filtered_block_connected(&self, header: &Header, txdata: &TransactionData, height: u32) { - log_debug!(self.logger, "New best block {} at height {} provided via block_connected", header.block_hash(), height); + log_debug!( + self.logger, + "New best block {} at height {} provided via block_connected", + header.block_hash(), + height + ); self.process_chain_data(header, Some(height), &txdata, |monitor, txdata| { monitor.block_connected( - header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &self.logger) + header, + txdata, + height, + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, + ) }); // Assume we may have some new events and wake the event processor self.event_notifier.notify(); @@ -688,16 +805,26 @@ where fn block_disconnected(&self, header: &Header, height: u32) { let monitor_states = self.monitors.read().unwrap(); - log_debug!(self.logger, "Latest block {} at height {} removed via block_disconnected", header.block_hash(), height); + log_debug!( + self.logger, + "Latest block {} at height {} removed via block_disconnected", + header.block_hash(), + height + ); for monitor_state in monitor_states.values() { monitor_state.monitor.block_disconnected( - header, height, &*self.broadcaster, &*self.fee_estimator, &self.logger); + header, + height, + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, + ); } } } impl -chain::Confirm for ChainMonitor + chain::Confirm for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, @@ -706,10 +833,22 @@ where P::Target: Persist, { fn transactions_confirmed(&self, header: &Header, txdata: &TransactionData, height: u32) { - log_debug!(self.logger, "{} provided transactions confirmed at height {} in block {}", txdata.len(), height, header.block_hash()); + log_debug!( + self.logger, + "{} provided transactions confirmed at height {} in block {}", + txdata.len(), + height, + header.block_hash() + ); self.process_chain_data(header, None, txdata, |monitor, txdata| { monitor.transactions_confirmed( - header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &self.logger) + header, + txdata, + height, + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, + ) }); // Assume we may have some new events and wake the event processor self.event_notifier.notify(); @@ -719,18 +858,32 @@ where log_debug!(self.logger, "Transaction {} reorganized out of chain", txid); let monitor_states = self.monitors.read().unwrap(); for monitor_state in monitor_states.values() { - monitor_state.monitor.transaction_unconfirmed(txid, &*self.broadcaster, &*self.fee_estimator, &self.logger); + monitor_state.monitor.transaction_unconfirmed( + txid, + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, + ); } } fn best_block_updated(&self, header: &Header, height: u32) { - log_debug!(self.logger, "New best block {} at height {} provided via best_block_updated", header.block_hash(), height); + log_debug!( + self.logger, + "New best block {} at height {} provided via best_block_updated", + header.block_hash(), + height + ); self.process_chain_data(header, Some(height), &[], |monitor, txdata| { // While in practice there shouldn't be any recursive calls when given empty txdata, // it's still possible if a chain::Filter implementation returns a transaction. debug_assert!(txdata.is_empty()); monitor.best_block_updated( - header, height, &*self.broadcaster, &*self.fee_estimator, &self.logger + header, + height, + &*self.broadcaster, + &*self.fee_estimator, + &self.logger, ) }); // Assume we may have some new events and wake the event processor @@ -750,15 +903,18 @@ where } } -impl -chain::Watch for ChainMonitor -where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +impl + chain::Watch for ChainMonitor +where + C::Target: chain::Filter, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, { - fn watch_channel(&self, channel_id: ChannelId, monitor: ChannelMonitor) -> Result { + fn watch_channel( + &self, channel_id: ChannelId, monitor: ChannelMonitor, + ) -> Result { let logger = WithChannelMonitor::from(&self.logger, &monitor, None); let mut monitors = self.monitors.write().unwrap(); let entry = match monitors.entry(channel_id) { @@ -774,11 +930,19 @@ where C::Target: chain::Filter, let persist_res = self.persister.persist_new_channel(monitor.persistence_key(), &monitor); match persist_res { ChannelMonitorUpdateStatus::InProgress => { - log_info!(logger, "Persistence of new ChannelMonitor for channel {} in progress", log_funding_info!(monitor)); + log_info!( + logger, + "Persistence of new ChannelMonitor for channel {} in progress", + log_funding_info!(monitor) + ); pending_monitor_updates.push(update_id); }, ChannelMonitorUpdateStatus::Completed => { - log_info!(logger, "Persistence of new ChannelMonitor for channel {} completed", log_funding_info!(monitor)); + log_info!( + logger, + "Persistence of new ChannelMonitor for channel {} completed", + log_funding_info!(monitor) + ); }, ChannelMonitorUpdateStatus::UnrecoverableError => { let err_str = "ChannelMonitor[Update] persistence failed unrecoverably. This indicates we cannot continue normal operation and must shut down."; @@ -787,7 +951,7 @@ where C::Target: chain::Filter, }, } if let Some(ref chain_source) = self.chain_source { - monitor.load_outputs_to_watch(chain_source , &self.logger); + monitor.load_outputs_to_watch(chain_source, &self.logger); } entry.insert(MonitorHolder { monitor, @@ -796,7 +960,9 @@ where C::Target: chain::Filter, Ok(persist_res) } - fn update_channel(&self, channel_id: ChannelId, update: &ChannelMonitorUpdate) -> ChannelMonitorUpdateStatus { + fn update_channel( + &self, channel_id: ChannelId, update: &ChannelMonitorUpdate, + ) -> ChannelMonitorUpdateStatus { // `ChannelMonitorUpdate`'s `channel_id` is `None` prior to 0.0.121 and all channels in those // versions are V1-established. For 0.0.121+ the `channel_id` fields is always `Some`. debug_assert_eq!(update.channel_id.unwrap(), channel_id); @@ -818,13 +984,24 @@ where C::Target: chain::Filter, Some(monitor_state) => { let monitor = &monitor_state.monitor; let logger = WithChannelMonitor::from(&self.logger, &monitor, None); - log_trace!(logger, "Updating ChannelMonitor to id {} for channel {}", update.update_id, log_funding_info!(monitor)); + log_trace!( + logger, + "Updating ChannelMonitor to id {} for channel {}", + update.update_id, + log_funding_info!(monitor) + ); // We hold a `pending_monitor_updates` lock through `update_monitor` to ensure we // have well-ordered updates from the users' point of view. See the // `pending_monitor_updates` docs for more. - let mut pending_monitor_updates = monitor_state.pending_monitor_updates.lock().unwrap(); - let update_res = monitor.update_monitor(update, &self.broadcaster, &self.fee_estimator, &self.logger); + let mut pending_monitor_updates = + monitor_state.pending_monitor_updates.lock().unwrap(); + let update_res = monitor.update_monitor( + update, + &self.broadcaster, + &self.fee_estimator, + &self.logger, + ); let update_id = update.update_id; let persist_res = if update_res.is_err() { @@ -834,9 +1011,17 @@ where C::Target: chain::Filter, // while reading `channel_monitor` with updates from storage. Instead, we should persist // the entire `channel_monitor` here. log_warn!(logger, "Failed to update ChannelMonitor for channel {}. Going ahead and persisting the entire ChannelMonitor", log_funding_info!(monitor)); - self.persister.update_persisted_channel(monitor.persistence_key(), None, monitor) + self.persister.update_persisted_channel( + monitor.persistence_key(), + None, + monitor, + ) } else { - self.persister.update_persisted_channel(monitor.persistence_key(), Some(update), monitor) + self.persister.update_persisted_channel( + monitor.persistence_key(), + Some(update), + monitor, + ) }; match persist_res { ChannelMonitorUpdateStatus::InProgress => { @@ -848,7 +1033,8 @@ where C::Target: chain::Filter, ); }, ChannelMonitorUpdateStatus::Completed => { - log_debug!(logger, + log_debug!( + logger, "Persistence of ChannelMonitorUpdate id {:?} for channel {} completed", update_id, log_funding_info!(monitor) @@ -870,11 +1056,13 @@ where C::Target: chain::Filter, } else { persist_res } - } + }, } } - fn release_pending_monitor_events(&self) -> Vec<(OutPoint, ChannelId, Vec, PublicKey)> { + fn release_pending_monitor_events( + &self, + ) -> Vec<(OutPoint, ChannelId, Vec, PublicKey)> { let mut pending_monitor_events = self.pending_monitor_events.lock().unwrap().split_off(0); for monitor_state in self.monitors.read().unwrap().values() { let monitor_events = monitor_state.monitor.get_and_clear_pending_monitor_events(); @@ -882,19 +1070,26 @@ where C::Target: chain::Filter, let monitor_funding_txo = monitor_state.monitor.get_funding_txo(); let monitor_channel_id = monitor_state.monitor.channel_id(); let counterparty_node_id = monitor_state.monitor.get_counterparty_node_id(); - pending_monitor_events.push((monitor_funding_txo, monitor_channel_id, monitor_events, counterparty_node_id)); + pending_monitor_events.push(( + monitor_funding_txo, + monitor_channel_id, + monitor_events, + counterparty_node_id, + )); } } pending_monitor_events } } -impl events::EventsProvider for ChainMonitor - where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +impl + events::EventsProvider for ChainMonitor +where + C::Target: chain::Filter, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, { /// Processes [`SpendableOutputs`] events produced from each [`ChannelMonitor`] upon maturity. /// @@ -909,13 +1104,16 @@ impl(&self, handler: H) where H::Target: EventHandler { + fn process_pending_events(&self, handler: H) + where + H::Target: EventHandler, + { for monitor_state in self.monitors.read().unwrap().values() { match monitor_state.monitor.process_pending_events(&handler, &self.logger) { Ok(()) => {}, - Err(ReplayEvent ()) => { + Err(ReplayEvent()) => { self.event_notifier.notify(); - } + }, } } } @@ -923,14 +1121,14 @@ impl())); + let mut updates = Vec::with_capacity(cmp::min( + len as usize, + MAX_ALLOC_SIZE / ::core::mem::size_of::(), + )); for _ in 0..len { if let Some(upd) = MaybeReadable::read(r)? { updates.push(upd); @@ -317,7 +338,8 @@ impl HolderCommitment { let delayed_payment_key = &tx_keys.broadcaster_delayed_payment_key; let per_commitment_point = &tx_keys.per_commitment_point; - let mut nondust_htlcs = self.tx.nondust_htlcs().iter().zip(self.tx.counterparty_htlc_sigs.iter()); + let mut nondust_htlcs = + self.tx.nondust_htlcs().iter().zip(self.tx.counterparty_htlc_sigs.iter()); let mut sources = self.nondust_htlc_sources.iter(); // Use an iterator to write `htlc_outputs` to avoid allocations. @@ -340,7 +362,10 @@ impl HolderCommitment { }); // Dust HTLCs go last. - let dust_htlcs = self.dust_htlcs.iter().map(|(htlc, source)| (htlc, None::<&Signature>, source.as_ref())); + let dust_htlcs = self + .dust_htlcs + .iter() + .map(|(htlc, source)| (htlc, None::<&Signature>, source.as_ref())); let htlc_outputs = crate::util::ser::IterableOwned(nondust_htlcs.chain(dust_htlcs)); write_tlv_fields!(writer, { @@ -402,7 +427,9 @@ impl Readable for CounterpartyCommitmentParameters { (4, on_counterparty_tx_csv, required), }); CounterpartyCommitmentParameters { - counterparty_delayed_payment_base_key: counterparty_delayed_payment_base_key.0.unwrap(), + counterparty_delayed_payment_base_key: counterparty_delayed_payment_base_key + .0 + .unwrap(), counterparty_htlc_base_key: counterparty_htlc_base_key.0.unwrap(), on_counterparty_tx_csv, } @@ -429,14 +456,15 @@ impl OnchainEventEntry { let mut conf_threshold = self.height + ANTI_REORG_DELAY - 1; match self.event { OnchainEvent::MaturingOutput { - descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor) + descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor), } => { // A CSV'd transaction is confirmable in block (input height) + CSV delay, which means // it's broadcastable when we see the previous block. - conf_threshold = cmp::max(conf_threshold, self.height + descriptor.to_self_delay as u32 - 1); + conf_threshold = + cmp::max(conf_threshold, self.height + descriptor.to_self_delay as u32 - 1); }, - OnchainEvent::FundingSpendConfirmation { on_local_output_csv: Some(csv), .. } | - OnchainEvent::HTLCSpendConfirmation { on_to_local_output_csv: Some(csv), .. } => { + OnchainEvent::FundingSpendConfirmation { on_local_output_csv: Some(csv), .. } + | OnchainEvent::HTLCSpendConfirmation { on_to_local_output_csv: Some(csv), .. } => { // A CSV'd transaction is confirmable in block (input height) + CSV delay, which means // it's broadcastable when we see the previous block. conf_threshold = cmp::max(conf_threshold, self.height + csv as u32 - 1); @@ -476,9 +504,7 @@ enum OnchainEvent { }, /// An output waiting on [`ANTI_REORG_DELAY`] confirmations before we hand the user the /// [`SpendableOutputDescriptor`]. - MaturingOutput { - descriptor: SpendableOutputDescriptor, - }, + MaturingOutput { descriptor: SpendableOutputDescriptor }, /// A spend of the funding output, either a commitment transaction or a cooperative closing /// transaction. FundingSpendConfirmation { @@ -541,7 +567,13 @@ impl MaybeReadable for OnchainEventEntry { (3, block_hash, option), (4, event, upgradable_required), }); - Ok(Some(Self { txid, transaction, height, block_hash, event: _init_tlv_based_struct_field!(event, upgradable_required) })) + Ok(Some(Self { + txid, + transaction, + height, + block_hash, + event: _init_tlv_based_struct_field!(event, upgradable_required), + })) } } @@ -622,9 +654,15 @@ pub(crate) enum ChannelMonitorUpdateStep { impl ChannelMonitorUpdateStep { fn variant_name(&self) -> &'static str { match self { - ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } => "LatestHolderCommitmentTXInfo", - ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } => "LatestCounterpartyCommitmentTXInfo", - ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. } => "LatestCounterpartyCommitmentTX", + ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } => { + "LatestHolderCommitmentTXInfo" + }, + ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } => { + "LatestCounterpartyCommitmentTXInfo" + }, + ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. } => { + "LatestCounterpartyCommitmentTX" + }, ChannelMonitorUpdateStep::PaymentPreimage { .. } => "PaymentPreimage", ChannelMonitorUpdateStep::CommitmentSecret { .. } => "CommitmentSecret", ChannelMonitorUpdateStep::ChannelForceClosed { .. } => "ChannelForceClosed", @@ -832,13 +870,17 @@ impl Balance { /// On-chain fees required to claim the balance are not included in this amount. pub fn claimable_amount_satoshis(&self) -> u64 { match self { - Balance::ClaimableOnChannelClose { amount_satoshis, .. }| - Balance::ClaimableAwaitingConfirmations { amount_satoshis, .. }| - Balance::ContentiousClaimable { amount_satoshis, .. }| - Balance::CounterpartyRevokedOutputClaimable { amount_satoshis, .. } - => *amount_satoshis, - Balance::MaybeTimeoutClaimableHTLC { amount_satoshis, outbound_payment, .. } - => if *outbound_payment { 0 } else { *amount_satoshis }, + Balance::ClaimableOnChannelClose { amount_satoshis, .. } + | Balance::ClaimableAwaitingConfirmations { amount_satoshis, .. } + | Balance::ContentiousClaimable { amount_satoshis, .. } + | Balance::CounterpartyRevokedOutputClaimable { amount_satoshis, .. } => *amount_satoshis, + Balance::MaybeTimeoutClaimableHTLC { amount_satoshis, outbound_payment, .. } => { + if *outbound_payment { + 0 + } else { + *amount_satoshis + } + }, Balance::MaybePreimageClaimableHTLC { .. } => 0, } } @@ -887,7 +929,11 @@ impl Readable for IrrevocablyResolvedHTLC { (3, resolving_tx, option), }); Ok(Self { - commitment_tx_output_idx: if mapped_commitment_tx_output_idx == u32::MAX { None } else { Some(mapped_commitment_tx_output_idx) }, + commitment_tx_output_idx: if mapped_commitment_tx_output_idx == u32::MAX { + None + } else { + Some(mapped_commitment_tx_output_idx) + }, resolving_txid, payment_preimage, resolving_tx, @@ -910,7 +956,10 @@ pub struct ChannelMonitor { pub(crate) inner: Mutex>, } -impl Clone for ChannelMonitor where Signer: Clone { +impl Clone for ChannelMonitor +where + Signer: Clone, +{ fn clone(&self) -> Self { let inner = self.inner.lock().unwrap().clone(); ChannelMonitor::from_impl(inner) @@ -937,31 +986,32 @@ impl TryFrom<(HolderCommitmentTransaction, HolderSignedTx)> for HolderCommitment // HTLC sources, separately. All offered, non-dust HTLCs must have a source available. let mut missing_nondust_source = false; - let mut nondust_htlc_sources = Vec::with_capacity(holder_commitment_tx.nondust_htlcs().len()); - let dust_htlcs = holder_signed_tx.htlc_outputs.into_iter().filter_map(|(htlc, _, source)| { - // Filter our non-dust HTLCs, while at the same time pushing their sources into - // `nondust_htlc_sources`. - if htlc.transaction_output_index.is_none() { - return Some((htlc, source)) - } - if htlc.offered { - if let Some(source) = source { - nondust_htlc_sources.push(source); - } else { - missing_nondust_source = true; + let mut nondust_htlc_sources = + Vec::with_capacity(holder_commitment_tx.nondust_htlcs().len()); + let dust_htlcs = holder_signed_tx + .htlc_outputs + .into_iter() + .filter_map(|(htlc, _, source)| { + // Filter our non-dust HTLCs, while at the same time pushing their sources into + // `nondust_htlc_sources`. + if htlc.transaction_output_index.is_none() { + return Some((htlc, source)); } - } - None - }).collect(); + if htlc.offered { + if let Some(source) = source { + nondust_htlc_sources.push(source); + } else { + missing_nondust_source = true; + } + } + None + }) + .collect(); if missing_nondust_source { return Err(()); } - Ok(Self { - tx: holder_commitment_tx, - nondust_htlc_sources, - dust_htlcs, - }) + Ok(Self { tx: holder_commitment_tx, nondust_htlc_sources, dust_htlcs }) } } @@ -974,7 +1024,9 @@ impl HolderCommitment { self.tx.nondust_htlcs().iter().chain(self.dust_htlcs.iter().map(|(htlc, _)| htlc)) } - fn htlcs_with_sources(&self) -> impl Iterator)> { + fn htlcs_with_sources( + &self, + ) -> impl Iterator)> { let mut sources = self.nondust_htlc_sources.iter(); let nondust_htlcs = self.tx.nondust_htlcs().iter().map(move |htlc| { let mut source = None; @@ -1009,7 +1061,8 @@ struct FundingScope { // consistent across all commitments. Unfortunately, doing so requires that our HTLCs are not // tied to their respective commitment transaction via `transaction_output_index`, as those may // not be consistent across all commitments. - counterparty_claimable_outpoints: HashMap>)>>, + counterparty_claimable_outpoints: + HashMap>)>>, // We store two holder commitment transactions to avoid any race conditions where we may update // some monitors (potentially on watchtowers) but then fail to update others, resulting in the @@ -1187,14 +1240,25 @@ pub(crate) struct ChannelMonitorImpl { /// Transaction outputs to watch for on-chain spends. pub type TransactionOutputs = (Txid, Vec<(u32, TxOut)>); -impl PartialEq for ChannelMonitor where Signer: PartialEq { +impl PartialEq for ChannelMonitor +where + Signer: PartialEq, +{ fn eq(&self, other: &Self) -> bool { // We need some kind of total lockorder. Absent a better idea, we sort by position in // memory and take locks in that order (assuming that we can't move within memory while a // lock is held). let ord = ((self as *const _) as usize) < ((other as *const _) as usize); - let a = if ord { self.inner.unsafe_well_ordered_double_lock_self() } else { other.inner.unsafe_well_ordered_double_lock_self() }; - let b = if ord { other.inner.unsafe_well_ordered_double_lock_self() } else { self.inner.unsafe_well_ordered_double_lock_self() }; + let a = if ord { + self.inner.unsafe_well_ordered_double_lock_self() + } else { + other.inner.unsafe_well_ordered_double_lock_self() + }; + let b = if ord { + other.inner.unsafe_well_ordered_double_lock_self() + } else { + self.inner.unsafe_well_ordered_double_lock_self() + }; a.eq(&b) } } @@ -1219,7 +1283,9 @@ impl Writeable for ChannelMonitorImpl { U48(self.commitment_transaction_number_obscure_factor).write(writer)?; self.destination_script.write(writer)?; - if let Some(ref broadcasted_holder_revokable_script) = self.broadcasted_holder_revokable_script { + if let Some(ref broadcasted_holder_revokable_script) = + self.broadcasted_holder_revokable_script + { writer.write_all(&[0; 1])?; broadcasted_holder_revokable_script.0.write(writer)?; broadcasted_holder_revokable_script.1.write(writer)?; @@ -1276,30 +1342,37 @@ impl Writeable for ChannelMonitorImpl { writer.write_all(&$htlc_output.cltv_expiry.to_be_bytes())?; writer.write_all(&$htlc_output.payment_hash.0[..])?; $htlc_output.transaction_output_index.write(writer)?; - } + }; } - writer.write_all(&(self.funding.counterparty_claimable_outpoints.len() as u64).to_be_bytes())?; + writer.write_all( + &(self.funding.counterparty_claimable_outpoints.len() as u64).to_be_bytes(), + )?; for (ref txid, ref htlc_infos) in self.funding.counterparty_claimable_outpoints.iter() { writer.write_all(&txid[..])?; writer.write_all(&(htlc_infos.len() as u64).to_be_bytes())?; for &(ref htlc_output, ref htlc_source) in htlc_infos.iter() { - debug_assert!(htlc_source.is_none() || Some(**txid) == self.funding.current_counterparty_commitment_txid + debug_assert!( + htlc_source.is_none() + || Some(**txid) == self.funding.current_counterparty_commitment_txid || Some(**txid) == self.funding.prev_counterparty_commitment_txid, - "HTLC Sources for all revoked commitment transactions should be none!"); + "HTLC Sources for all revoked commitment transactions should be none!" + ); serialize_htlc_in_commitment!(htlc_output); htlc_source.as_ref().map(|b| b.as_ref()).write(writer)?; } } - writer.write_all(&(self.counterparty_commitment_txn_on_chain.len() as u64).to_be_bytes())?; + writer + .write_all(&(self.counterparty_commitment_txn_on_chain.len() as u64).to_be_bytes())?; for (ref txid, commitment_number) in self.counterparty_commitment_txn_on_chain.iter() { writer.write_all(&txid[..])?; writer.write_all(&byte_utils::be48_to_array(*commitment_number))?; } writer.write_all(&(self.counterparty_hash_commitment_number.len() as u64).to_be_bytes())?; - for (ref payment_hash, commitment_number) in self.counterparty_hash_commitment_number.iter() { + for (ref payment_hash, commitment_number) in self.counterparty_hash_commitment_number.iter() + { writer.write_all(&payment_hash.0[..])?; writer.write_all(&byte_utils::be48_to_array(*commitment_number))?; } @@ -1313,7 +1386,8 @@ impl Writeable for ChannelMonitorImpl { self.funding.current_holder_commitment.write_as_legacy(writer)?; - writer.write_all(&byte_utils::be48_to_array(self.current_counterparty_commitment_number))?; + writer + .write_all(&byte_utils::be48_to_array(self.current_counterparty_commitment_number))?; writer.write_all(&byte_utils::be48_to_array(self.current_holder_commitment_number))?; writer.write_all(&(self.payment_preimages.len() as u64).to_be_bytes())?; @@ -1321,12 +1395,19 @@ impl Writeable for ChannelMonitorImpl { writer.write_all(&payment_preimage.0[..])?; } - writer.write_all(&(self.pending_monitor_events.iter().filter(|ev| match ev { - MonitorEvent::HTLCEvent(_) => true, - MonitorEvent::HolderForceClosed(_) => true, - MonitorEvent::HolderForceClosedWithInfo { .. } => true, - _ => false, - }).count() as u64).to_be_bytes())?; + writer.write_all( + &(self + .pending_monitor_events + .iter() + .filter(|ev| match ev { + MonitorEvent::HTLCEvent(_) => true, + MonitorEvent::HolderForceClosed(_) => true, + MonitorEvent::HolderForceClosedWithInfo { .. } => true, + _ => false, + }) + .count() as u64) + .to_be_bytes(), + )?; for event in self.pending_monitor_events.iter() { match event { MonitorEvent::HTLCEvent(upd) => { @@ -1350,7 +1431,8 @@ impl Writeable for ChannelMonitorImpl { self.best_block.block_hash.write(writer)?; writer.write_all(&self.best_block.height.to_be_bytes())?; - writer.write_all(&(self.onchain_events_awaiting_threshold_conf.len() as u64).to_be_bytes())?; + writer + .write_all(&(self.onchain_events_awaiting_threshold_conf.len() as u64).to_be_bytes())?; for ref entry in self.onchain_events_awaiting_threshold_conf.iter() { entry.write(writer)?; } @@ -1378,7 +1460,7 @@ impl Writeable for ChannelMonitorImpl { let mut pending_monitor_events = self.pending_monitor_events.clone(); pending_monitor_events.push(MonitorEvent::HolderForceClosed(*outpoint)); pending_monitor_events - } + }, _ => self.pending_monitor_events.clone(), }; @@ -1419,7 +1501,9 @@ macro_rules! _process_events_body { pending_events = inner.pending_events.clone(); repeated_events = inner.get_repeated_events(); - } else { break handling_res; } + } else { + break handling_res; + } let mut num_handled_events = 0; for event in pending_events { @@ -1434,7 +1518,7 @@ macro_rules! _process_events_body { // any unhandled events on the next invocation. handling_res = Err(e); break; - } + }, } } @@ -1459,18 +1543,24 @@ macro_rules! _process_events_body { } break handling_res; } - } + }; } pub(super) use _process_events_body as process_events_body; -pub(crate) struct WithChannelMonitor<'a, L: Deref> where L::Target: Logger { +pub(crate) struct WithChannelMonitor<'a, L: Deref> +where + L::Target: Logger, +{ logger: &'a L, peer_id: Option, channel_id: Option, payment_hash: Option, } -impl<'a, L: Deref> Logger for WithChannelMonitor<'a, L> where L::Target: Logger { +impl<'a, L: Deref> Logger for WithChannelMonitor<'a, L> +where + L::Target: Logger, +{ fn log(&self, mut record: Record) { record.peer_id = self.peer_id; record.channel_id = self.channel_id; @@ -1479,17 +1569,22 @@ impl<'a, L: Deref> Logger for WithChannelMonitor<'a, L> where L::Target: Logger } } -impl<'a, L: Deref> WithChannelMonitor<'a, L> where L::Target: Logger { - pub(crate) fn from(logger: &'a L, monitor: &ChannelMonitor, payment_hash: Option) -> Self { +impl<'a, L: Deref> WithChannelMonitor<'a, L> +where + L::Target: Logger, +{ + pub(crate) fn from( + logger: &'a L, monitor: &ChannelMonitor, payment_hash: Option, + ) -> Self { Self::from_impl(logger, &*monitor.inner.lock().unwrap(), payment_hash) } - pub(crate) fn from_impl(logger: &'a L, monitor_impl: &ChannelMonitorImpl, payment_hash: Option) -> Self { + pub(crate) fn from_impl( + logger: &'a L, monitor_impl: &ChannelMonitorImpl, payment_hash: Option, + ) -> Self { let peer_id = Some(monitor_impl.counterparty_node_id); let channel_id = Some(monitor_impl.channel_id()); - WithChannelMonitor { - logger, peer_id, channel_id, payment_hash, - } + WithChannelMonitor { logger, peer_id, channel_id, payment_hash } } } @@ -1509,17 +1604,23 @@ impl ChannelMonitor { initial_holder_commitment_tx: HolderCommitmentTransaction, best_block: BestBlock, counterparty_node_id: PublicKey, channel_id: ChannelId, ) -> ChannelMonitor { - assert!(commitment_transaction_number_obscure_factor <= (1 << 48)); let holder_pubkeys = &channel_parameters.holder_pubkeys; let counterparty_payment_script = chan_utils::get_counterparty_payment_script( - &channel_parameters.channel_type_features, &holder_pubkeys.payment_point + &channel_parameters.channel_type_features, + &holder_pubkeys.payment_point, ); - let counterparty_channel_parameters = channel_parameters.counterparty_parameters.as_ref().unwrap(); - let counterparty_delayed_payment_base_key = counterparty_channel_parameters.pubkeys.delayed_payment_basepoint; + let counterparty_channel_parameters = + channel_parameters.counterparty_parameters.as_ref().unwrap(); + let counterparty_delayed_payment_base_key = + counterparty_channel_parameters.pubkeys.delayed_payment_basepoint; let counterparty_htlc_base_key = counterparty_channel_parameters.pubkeys.htlc_basepoint; - let counterparty_commitment_params = CounterpartyCommitmentParameters { counterparty_delayed_payment_base_key, counterparty_htlc_base_key, on_counterparty_tx_csv }; + let counterparty_commitment_params = CounterpartyCommitmentParameters { + counterparty_delayed_payment_base_key, + counterparty_htlc_base_key, + on_counterparty_tx_csv, + }; let channel_keys_id = keys.channel_keys_id(); let holder_revocation_basepoint = holder_pubkeys.revocation_basepoint; @@ -1528,17 +1629,24 @@ impl ChannelMonitor { initial_holder_commitment_tx.trust().commitment_number(); let onchain_tx_handler = OnchainTxHandler::new( - channel_parameters.channel_value_satoshis, channel_keys_id, destination_script.into(), - keys, channel_parameters.clone(), initial_holder_commitment_tx.clone(), secp_ctx + channel_parameters.channel_value_satoshis, + channel_keys_id, + destination_script.into(), + keys, + channel_parameters.clone(), + initial_holder_commitment_tx.clone(), + secp_ctx, ); - let funding_outpoint = channel_parameters.funding_outpoint + let funding_outpoint = channel_parameters + .funding_outpoint .expect("Funding outpoint must be known during initialization"); let funding_redeem_script = channel_parameters.make_funding_redeemscript(); let funding_script = funding_redeem_script.to_p2wsh(); let mut outputs_to_watch = new_hash_map(); outputs_to_watch.insert( - funding_outpoint.txid, vec![(funding_outpoint.index as u32, funding_script.clone())], + funding_outpoint.txid, + vec![(funding_outpoint.index as u32, funding_script.clone())], ); Self::from_impl(ChannelMonitorImpl { @@ -1606,7 +1714,7 @@ impl ChannelMonitor { spendable_txids_confirmed: Vec::new(), best_block, - counterparty_node_id: counterparty_node_id, + counterparty_node_id, initial_counterparty_commitment_info: None, initial_counterparty_commitment_tx: None, balances_empty_height: None, @@ -1649,7 +1757,8 @@ impl ChannelMonitor { /// before the initial persistence of a new channel. pub(crate) fn provide_initial_counterparty_commitment_tx( &self, commitment_tx: CommitmentTransaction, logger: &L, - ) where L::Target: Logger + ) where + L::Target: Logger, { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); @@ -1662,17 +1771,20 @@ impl ChannelMonitor { /// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers. #[cfg(test)] fn provide_latest_counterparty_commitment_tx( - &self, - txid: Txid, - htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, - commitment_number: u64, - their_per_commitment_point: PublicKey, - logger: &L, - ) where L::Target: Logger { + &self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, + commitment_number: u64, their_per_commitment_point: PublicKey, logger: &L, + ) where + L::Target: Logger, + { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); inner.provide_latest_counterparty_commitment_tx( - txid, htlc_outputs, commitment_number, their_per_commitment_point, &logger) + txid, + htlc_outputs, + commitment_number, + their_per_commitment_point, + &logger, + ) } #[cfg(test)] @@ -1680,7 +1792,12 @@ impl ChannelMonitor { &self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, ) { - self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs, &Vec::new(), Vec::new()) + self.inner.lock().unwrap().provide_latest_holder_commitment_tx( + holder_commitment_tx, + htlc_outputs, + &Vec::new(), + Vec::new(), + ) } /// This is used to provide payment preimage(s) out-of-band during startup without updating the @@ -1694,12 +1811,8 @@ impl ChannelMonitor { /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager pub(crate) fn provide_payment_preimage_unsafe_legacy( - &self, - payment_hash: &PaymentHash, - payment_preimage: &PaymentPreimage, - broadcaster: &B, - fee_estimator: &LowerBoundedFeeEstimator, - logger: &L, + &self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -1711,7 +1824,13 @@ impl ChannelMonitor { // case is acceptable as we only call this method from `ChannelManager` deserialization in // cases where we are replaying a claim started on a previous version of LDK. inner.provide_payment_preimage( - payment_hash, payment_preimage, &None, broadcaster, fee_estimator, &logger) + payment_hash, + payment_preimage, + &None, + broadcaster, + fee_estimator, + &logger, + ) } /// Updates a ChannelMonitor on the basis of some new information provided by the Channel @@ -1719,11 +1838,7 @@ impl ChannelMonitor { /// /// panics if the given update is not the next update by update_id. pub fn update_monitor( - &self, - updates: &ChannelMonitorUpdate, - broadcaster: &B, - fee_estimator: &F, - logger: &L, + &self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &L, ) -> Result<(), ()> where B::Target: BroadcasterInterface, @@ -1766,8 +1881,13 @@ impl ChannelMonitor { /// Gets a list of txids, with their output scripts (in the order they appear in the /// transaction), which we must learn about spends of via block_connected(). pub fn get_outputs_to_watch(&self) -> Vec<(Txid, Vec<(u32, ScriptBuf)>)> { - self.inner.lock().unwrap().get_outputs_to_watch() - .iter().map(|(txid, outputs)| (*txid, outputs.clone())).collect() + self.inner + .lock() + .unwrap() + .get_outputs_to_watch() + .iter() + .map(|(txid, outputs)| (*txid, outputs.clone())) + .collect() } /// Loads the funding txo and outputs to watch into the given `chain::Filter` by repeatedly @@ -1775,7 +1895,8 @@ impl ChannelMonitor { /// have been registered. pub fn load_outputs_to_watch(&self, filter: &F, logger: &L) where - F::Target: chain::Filter, L::Target: Logger, + F::Target: chain::Filter, + L::Target: Logger, { let lock = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*lock, None); @@ -1786,7 +1907,11 @@ impl ChannelMonitor { for (index, script_pubkey) in outputs.iter() { assert!(*index <= u16::MAX as u32); let outpoint = OutPoint { txid: *txid, index: *index as u16 }; - log_trace!(logger, "Registering outpoint {} with the filter for monitoring spends", outpoint); + log_trace!( + logger, + "Registering outpoint {} with the filter for monitoring spends", + outpoint + ); filter.register_output(WatchedOutput { block_hash: None, outpoint, @@ -1817,8 +1942,13 @@ impl ChannelMonitor { /// /// [`SpendableOutputs`]: crate::events::Event::SpendableOutputs /// [`BumpTransaction`]: crate::events::Event::BumpTransaction - pub fn process_pending_events(&self, handler: &H, logger: &L) - -> Result<(), ReplayEvent> where H::Target: EventHandler, L::Target: Logger { + pub fn process_pending_events( + &self, handler: &H, logger: &L, + ) -> Result<(), ReplayEvent> + where + H::Target: EventHandler, + L::Target: Logger, + { let mut ev; process_events_body!(Some(self), logger, ev, handler.handle_event(ev)) } @@ -1827,11 +1957,15 @@ impl ChannelMonitor { /// /// See [`Self::process_pending_events`] for more information. pub async fn process_pending_events_async< - Future: core::future::Future>, H: Fn(Event) -> Future, + Future: core::future::Future>, + H: Fn(Event) -> Future, L: Deref, >( &self, handler: &H, logger: &L, - ) -> Result<(), ReplayEvent> where L::Target: Logger { + ) -> Result<(), ReplayEvent> + where + L::Target: Logger, + { let mut ev; process_events_body!(Some(self), logger, ev, { handler(ev).await }) } @@ -1881,7 +2015,9 @@ impl ChannelMonitor { /// may have been created prior to upgrading. /// /// [`Persist::update_persisted_channel`]: crate::chain::chainmonitor::Persist::update_persisted_channel - pub fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec { + pub fn counterparty_commitment_txs_from_update( + &self, update: &ChannelMonitorUpdate, + ) -> Vec { self.inner.lock().unwrap().counterparty_commitment_txs_from_update(update) } @@ -1902,8 +2038,15 @@ impl ChannelMonitor { /// /// [`EcdsaChannelSigner::sign_justice_revoked_output`]: crate::sign::ecdsa::EcdsaChannelSigner::sign_justice_revoked_output /// [`Persist`]: crate::chain::chainmonitor::Persist - pub fn sign_to_local_justice_tx(&self, justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64) -> Result { - self.inner.lock().unwrap().sign_to_local_justice_tx(justice_tx, input_idx, value, commitment_number) + pub fn sign_to_local_justice_tx( + &self, justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64, + ) -> Result { + self.inner.lock().unwrap().sign_to_local_justice_tx( + justice_tx, + input_idx, + value, + commitment_number, + ) } pub(crate) fn get_min_seen_secret(&self) -> u64 { @@ -1943,17 +2086,20 @@ impl ChannelMonitor { /// may be to contact the other node operator out-of-band to coordinate other options available /// to you. pub fn broadcast_latest_holder_commitment_txn( - &self, broadcaster: &B, fee_estimator: &F, logger: &L - ) - where + &self, broadcaster: &B, fee_estimator: &F, logger: &L, + ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, - L::Target: Logger + L::Target: Logger, { let mut inner = self.inner.lock().unwrap(); let fee_estimator = LowerBoundedFeeEstimator::new(&**fee_estimator); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); - inner.queue_latest_holder_commitment_txn_for_broadcast(broadcaster, &fee_estimator, &logger); + inner.queue_latest_holder_commitment_txn_for_broadcast( + broadcaster, + &fee_estimator, + &logger, + ); } /// Unsafe test-only version of `broadcast_latest_holder_commitment_txn` used by our test framework @@ -1961,7 +2107,9 @@ impl ChannelMonitor { /// revoked commitment transaction. #[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))] pub fn unsafe_get_latest_holder_commitment_txn(&self, logger: &L) -> Vec - where L::Target: Logger { + where + L::Target: Logger, + { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); inner.unsafe_get_latest_holder_commitment_txn(&logger) @@ -1979,13 +2127,8 @@ impl ChannelMonitor { /// /// [`get_outputs_to_watch`]: #method.get_outputs_to_watch pub fn block_connected( - &self, - header: &Header, - txdata: &TransactionData, - height: u32, - broadcaster: B, - fee_estimator: F, - logger: &L, + &self, header: &Header, txdata: &TransactionData, height: u32, broadcaster: B, + fee_estimator: F, logger: &L, ) -> Vec where B::Target: BroadcasterInterface, @@ -1994,19 +2137,13 @@ impl ChannelMonitor { { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); - inner.block_connected( - header, txdata, height, broadcaster, fee_estimator, &logger) + inner.block_connected(header, txdata, height, broadcaster, fee_estimator, &logger) } /// Determines if the disconnected block contained any transactions of interest and updates /// appropriately. pub fn block_disconnected( - &self, - header: &Header, - height: u32, - broadcaster: B, - fee_estimator: F, - logger: &L, + &self, header: &Header, height: u32, broadcaster: B, fee_estimator: F, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -2014,8 +2151,7 @@ impl ChannelMonitor { { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); - inner.block_disconnected( - header, height, broadcaster, fee_estimator, &logger) + inner.block_disconnected(header, height, broadcaster, fee_estimator, &logger) } /// Processes transactions confirmed in a block with the given header and height, returning new @@ -2026,13 +2162,8 @@ impl ChannelMonitor { /// /// [`block_connected`]: Self::block_connected pub fn transactions_confirmed( - &self, - header: &Header, - txdata: &TransactionData, - height: u32, - broadcaster: B, - fee_estimator: F, - logger: &L, + &self, header: &Header, txdata: &TransactionData, height: u32, broadcaster: B, + fee_estimator: F, logger: &L, ) -> Vec where B::Target: BroadcasterInterface, @@ -2043,7 +2174,13 @@ impl ChannelMonitor { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); inner.transactions_confirmed( - header, txdata, height, broadcaster, &bounded_fee_estimator, &logger) + header, + txdata, + height, + broadcaster, + &bounded_fee_estimator, + &logger, + ) } /// Processes a transaction that was reorganized out of the chain. @@ -2053,11 +2190,7 @@ impl ChannelMonitor { /// /// [`block_disconnected`]: Self::block_disconnected pub fn transaction_unconfirmed( - &self, - txid: &Txid, - broadcaster: B, - fee_estimator: F, - logger: &L, + &self, txid: &Txid, broadcaster: B, fee_estimator: F, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -2066,9 +2199,7 @@ impl ChannelMonitor { let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); - inner.transaction_unconfirmed( - txid, broadcaster, &bounded_fee_estimator, &logger - ); + inner.transaction_unconfirmed(txid, broadcaster, &bounded_fee_estimator, &logger); } /// Updates the monitor with the current best chain tip, returning new outputs to watch. See @@ -2079,12 +2210,7 @@ impl ChannelMonitor { /// /// [`block_connected`]: Self::block_connected pub fn best_block_updated( - &self, - header: &Header, - height: u32, - broadcaster: B, - fee_estimator: F, - logger: &L, + &self, header: &Header, height: u32, broadcaster: B, fee_estimator: F, logger: &L, ) -> Vec where B::Target: BroadcasterInterface, @@ -2094,15 +2220,14 @@ impl ChannelMonitor { let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner, None); - inner.best_block_updated( - header, height, broadcaster, &bounded_fee_estimator, &logger - ) + inner.best_block_updated(header, height, broadcaster, &bounded_fee_estimator, &logger) } /// Returns the set of txids that should be monitored for re-organization out of the chain. pub fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option)> { let inner = self.inner.lock().unwrap(); - let mut txids: Vec<(Txid, u32, Option)> = inner.onchain_events_awaiting_threshold_conf + let mut txids: Vec<(Txid, u32, Option)> = inner + .onchain_events_awaiting_threshold_conf .iter() .map(|entry| (entry.txid, entry.height, entry.block_hash)) .chain(inner.onchain_tx_handler.get_relevant_txids().into_iter()) @@ -2125,8 +2250,7 @@ impl ChannelMonitor { /// connections, like on mobile. pub fn rebroadcast_pending_claims( &self, broadcaster: B, fee_estimator: F, logger: &L, - ) - where + ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, @@ -2138,14 +2262,18 @@ impl ChannelMonitor { let current_height = inner.best_block.height; let conf_target = inner.closure_conf_target(); inner.onchain_tx_handler.rebroadcast_pending_claims( - current_height, FeerateStrategy::HighestOfPreviousOrNew, &broadcaster, conf_target, - &inner.destination_script, &fee_estimator, &logger, + current_height, + FeerateStrategy::HighestOfPreviousOrNew, + &broadcaster, + conf_target, + &inner.destination_script, + &fee_estimator, + &logger, ); } /// Returns true if the monitor has pending claim requests that are not fully confirmed yet. - pub fn has_pending_claims(&self) -> bool - { + pub fn has_pending_claims(&self) -> bool { self.inner.lock().unwrap().onchain_tx_handler.has_pending_claims() } @@ -2153,8 +2281,7 @@ impl ChannelMonitor { /// signature generation failure. pub fn signer_unblocked( &self, broadcaster: B, fee_estimator: F, logger: &L, - ) - where + ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, @@ -2166,8 +2293,13 @@ impl ChannelMonitor { let current_height = inner.best_block.height; let conf_target = inner.closure_conf_target(); inner.onchain_tx_handler.rebroadcast_pending_claims( - current_height, FeerateStrategy::RetryPrevious, &broadcaster, conf_target, - &inner.destination_script, &fee_estimator, &logger, + current_height, + FeerateStrategy::RetryPrevious, + &broadcaster, + conf_target, + &inner.destination_script, + &fee_estimator, + &logger, ); } @@ -2189,15 +2321,19 @@ impl ChannelMonitor { /// outputs which can be spent by us are found, at least one descriptor is returned. /// /// `confirmation_height` must be the height of the block in which `tx` was included in. - pub fn get_spendable_outputs(&self, tx: &Transaction, confirmation_height: u32) -> Vec { + pub fn get_spendable_outputs( + &self, tx: &Transaction, confirmation_height: u32, + ) -> Vec { let inner = self.inner.lock().unwrap(); let current_height = inner.best_block.height; let mut spendable_outputs = inner.get_spendable_outputs(tx); spendable_outputs.retain(|descriptor| { let mut conf_threshold = current_height.saturating_sub(ANTI_REORG_DELAY) + 1; if let SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) = descriptor { - conf_threshold = cmp::min(conf_threshold, - current_height.saturating_sub(descriptor.to_self_delay as u32) + 1); + conf_threshold = cmp::min( + conf_threshold, + current_height.saturating_sub(descriptor.to_self_delay as u32) + 1, + ); } conf_threshold >= confirmation_height }); @@ -2238,13 +2374,15 @@ impl ChannelMonitor { // Claimed all funds, check if reached the blocks threshold. (current_height >= balances_empty_height + ARCHIVAL_DELAY_BLOCKS, false) }, - (Some(_), false, _)|(Some(_), _, false) => { + (Some(_), false, _) | (Some(_), _, false) => { // previously assumed we claimed all funds, but we have new funds to claim or // preimages are suddenly needed (because of a duplicate-hash HTLC). // This should never happen as once the `Balance`s and preimages are clear, we // should never create new ones. - debug_assert!(false, - "Thought we were done claiming funds, but claimable_balances now has entries"); + debug_assert!( + false, + "Thought we were done claiming funds, but claimable_balances now has entries" + ); log_error!(logger, "WARNING: LDK thought it was done claiming all the available funds in the ChannelMonitor for channel {}, but later decided it had more to claim. This is potentially an important bug in LDK, please report it at https://github.com/lightningdevkit/rust-lightning/issues/new", inner.get_funding_txo()); @@ -2260,7 +2398,7 @@ impl ChannelMonitor { inner.balances_empty_height = Some(current_height); (false, true) }, - (None, false, _)|(None, _, false) => { + (None, false, _) | (None, _, false) => { // Have funds to claim or our preimages are still needed. (false, false) }, @@ -2287,9 +2425,9 @@ impl ChannelMonitor { impl ChannelMonitorImpl { /// Helper for get_claimable_balances which does the work for an individual HTLC, generating up /// to one `Balance` for the HTLC. - fn get_htlc_balance(&self, htlc: &HTLCOutputInCommitment, source: Option<&HTLCSource>, - holder_commitment: bool, counterparty_revoked_commitment: bool, - confirmed_txid: Option + fn get_htlc_balance( + &self, htlc: &HTLCOutputInCommitment, source: Option<&HTLCSource>, holder_commitment: bool, + counterparty_revoked_commitment: bool, confirmed_txid: Option, ) -> Option { let htlc_commitment_tx_output_idx = htlc.transaction_output_index?; @@ -2300,8 +2438,9 @@ impl ChannelMonitorImpl { let mut holder_delayed_output_pending = None; for event in self.onchain_events_awaiting_threshold_conf.iter() { match event.event { - OnchainEvent::HTLCUpdate { commitment_tx_output_idx, htlc_value_satoshis, .. } - if commitment_tx_output_idx == Some(htlc_commitment_tx_output_idx) => { + OnchainEvent::HTLCUpdate { + commitment_tx_output_idx, htlc_value_satoshis, .. + } if commitment_tx_output_idx == Some(htlc_commitment_tx_output_idx) => { debug_assert!(htlc_spend_txid_opt.is_none()); htlc_spend_txid_opt = Some(&event.txid); debug_assert!(htlc_spend_tx_opt.is_none()); @@ -2310,8 +2449,9 @@ impl ChannelMonitorImpl { debug_assert_eq!(htlc_value_satoshis.unwrap(), htlc.amount_msat / 1000); holder_timeout_spend_pending = Some(event.confirmation_threshold()); }, - OnchainEvent::HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } - if commitment_tx_output_idx == htlc_commitment_tx_output_idx => { + OnchainEvent::HTLCSpendConfirmation { + commitment_tx_output_idx, preimage, .. + } if commitment_tx_output_idx == htlc_commitment_tx_output_idx => { debug_assert!(htlc_spend_txid_opt.is_none()); htlc_spend_txid_opt = Some(&event.txid); debug_assert!(htlc_spend_tx_opt.is_none()); @@ -2320,10 +2460,13 @@ impl ChannelMonitorImpl { htlc_spend_pending = Some((event.confirmation_threshold(), preimage.is_some())); }, OnchainEvent::MaturingOutput { - descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor) } - if event.transaction.as_ref().map(|tx| tx.input.iter().enumerate() - .any(|(input_idx, inp)| - Some(inp.previous_output.txid) == confirmed_txid && + descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor), + } if event + .transaction + .as_ref() + .map(|tx| { + tx.input.iter().enumerate().any(|(input_idx, inp)| { + Some(inp.previous_output.txid) == confirmed_txid && inp.previous_output.vout == htlc_commitment_tx_output_idx && // A maturing output for an HTLC claim will always be at the same // index as the HTLC input. This is true pre-anchors, as there's @@ -2331,46 +2474,59 @@ impl ChannelMonitorImpl { // because we have a SIGHASH_SINGLE|ANYONECANPAY signature from our // channel counterparty. descriptor.outpoint.index as usize == input_idx - )) - .unwrap_or(false) - => { + }) + }) + .unwrap_or(false) => + { debug_assert!(holder_delayed_output_pending.is_none()); holder_delayed_output_pending = Some(event.confirmation_threshold()); }, _ => {}, } } - let htlc_resolved = self.htlcs_resolved_on_chain.iter() - .any(|v| if v.commitment_tx_output_idx == Some(htlc_commitment_tx_output_idx) { + let htlc_resolved = self.htlcs_resolved_on_chain.iter().any(|v| { + if v.commitment_tx_output_idx == Some(htlc_commitment_tx_output_idx) { debug_assert!(htlc_spend_txid_opt.is_none()); htlc_spend_txid_opt = v.resolving_txid.as_ref(); debug_assert!(htlc_spend_tx_opt.is_none()); htlc_spend_tx_opt = v.resolving_tx.as_ref(); true - } else { false }); - debug_assert!(holder_timeout_spend_pending.is_some() as u8 + htlc_spend_pending.is_some() as u8 + htlc_resolved as u8 <= 1); - - let htlc_commitment_outpoint = BitcoinOutPoint::new(confirmed_txid.unwrap(), htlc_commitment_tx_output_idx); - let htlc_output_to_spend = - if let Some(txid) = htlc_spend_txid_opt { - // Because HTLC transactions either only have 1 input and 1 output (pre-anchors) or - // are signed with SIGHASH_SINGLE|ANYONECANPAY under BIP-0143 (post-anchors), we can - // locate the correct output by ensuring its adjacent input spends the HTLC output - // in the commitment. - if let Some(ref tx) = htlc_spend_tx_opt { - let htlc_input_idx_opt = tx.input.iter().enumerate() - .find(|(_, input)| input.previous_output == htlc_commitment_outpoint) - .map(|(idx, _)| idx as u32); - debug_assert!(htlc_input_idx_opt.is_some()); - BitcoinOutPoint::new(*txid, htlc_input_idx_opt.unwrap_or(0)) - } else { - debug_assert!(!self.channel_type_features().supports_anchors_zero_fee_htlc_tx()); - BitcoinOutPoint::new(*txid, 0) - } } else { - htlc_commitment_outpoint - }; - let htlc_output_spend_pending = self.onchain_tx_handler.is_output_spend_pending(&htlc_output_to_spend); + false + } + }); + debug_assert!( + holder_timeout_spend_pending.is_some() as u8 + + htlc_spend_pending.is_some() as u8 + + htlc_resolved as u8 + <= 1 + ); + + let htlc_commitment_outpoint = + BitcoinOutPoint::new(confirmed_txid.unwrap(), htlc_commitment_tx_output_idx); + let htlc_output_to_spend = if let Some(txid) = htlc_spend_txid_opt { + // Because HTLC transactions either only have 1 input and 1 output (pre-anchors) or + // are signed with SIGHASH_SINGLE|ANYONECANPAY under BIP-0143 (post-anchors), we can + // locate the correct output by ensuring its adjacent input spends the HTLC output + // in the commitment. + if let Some(ref tx) = htlc_spend_tx_opt { + let htlc_input_idx_opt = tx + .input + .iter() + .enumerate() + .find(|(_, input)| input.previous_output == htlc_commitment_outpoint) + .map(|(idx, _)| idx as u32); + debug_assert!(htlc_input_idx_opt.is_some()); + BitcoinOutPoint::new(*txid, htlc_input_idx_opt.unwrap_or(0)) + } else { + debug_assert!(!self.channel_type_features().supports_anchors_zero_fee_htlc_tx()); + BitcoinOutPoint::new(*txid, 0) + } + } else { + htlc_commitment_outpoint + }; + let htlc_output_spend_pending = + self.onchain_tx_handler.is_output_spend_pending(&htlc_output_to_spend); if let Some(conf_thresh) = holder_delayed_output_pending { debug_assert!(holder_commitment); @@ -2387,30 +2543,42 @@ impl ChannelMonitorImpl { // ANTI_REORG_DELAY confirmations. debug_assert!(holder_commitment || self.funding_spend_confirmed.is_some()); } else if counterparty_revoked_commitment { - let htlc_output_claim_pending = self.onchain_events_awaiting_threshold_conf.iter().any(|event| { - if let OnchainEvent::MaturingOutput { - descriptor: SpendableOutputDescriptor::StaticOutput { .. } - } = &event.event { - event.transaction.as_ref().map(|tx| tx.input.iter().any(|inp| { - if let Some(htlc_spend_txid) = htlc_spend_txid_opt { - tx.compute_txid() == *htlc_spend_txid || inp.previous_output.txid == *htlc_spend_txid - } else { - Some(inp.previous_output.txid) == confirmed_txid && - inp.previous_output.vout == htlc_commitment_tx_output_idx - } - })).unwrap_or(false) - } else { - false - } - }); + let htlc_output_claim_pending = + self.onchain_events_awaiting_threshold_conf.iter().any(|event| { + if let OnchainEvent::MaturingOutput { + descriptor: SpendableOutputDescriptor::StaticOutput { .. }, + } = &event.event + { + event + .transaction + .as_ref() + .map(|tx| { + tx.input.iter().any(|inp| { + if let Some(htlc_spend_txid) = htlc_spend_txid_opt { + tx.compute_txid() == *htlc_spend_txid + || inp.previous_output.txid == *htlc_spend_txid + } else { + Some(inp.previous_output.txid) == confirmed_txid + && inp.previous_output.vout + == htlc_commitment_tx_output_idx + } + }) + }) + .unwrap_or(false) + } else { + false + } + }); if htlc_output_claim_pending { // We already push `Balance`s onto the `res` list for every // `StaticOutput` in a `MaturingOutput` in the revoked // counterparty commitment transaction case generally, so don't // need to do so again here. } else { - debug_assert!(holder_timeout_spend_pending.is_none(), - "HTLCUpdate OnchainEvents should never appear for preimage claims"); + debug_assert!( + holder_timeout_spend_pending.is_none(), + "HTLCUpdate OnchainEvents should never appear for preimage claims" + ); debug_assert!(!htlc.offered || htlc_spend_pending.is_none() || !htlc_spend_pending.unwrap().1, "We don't (currently) generate preimage claims against revoked outputs, where did you get one?!"); return Some(Balance::CounterpartyRevokedOutputClaimable { @@ -2494,14 +2662,19 @@ impl ChannelMonitor { let mut confirmed_txid = us.funding_spend_confirmed; let mut confirmed_counterparty_output = us.confirmed_commitment_tx_counterparty_output; let mut pending_commitment_tx_conf_thresh = None; - let funding_spend_pending = us.onchain_events_awaiting_threshold_conf.iter().find_map(|event| { - if let OnchainEvent::FundingSpendConfirmation { commitment_tx_to_counterparty_output, .. } = - event.event - { - confirmed_counterparty_output = commitment_tx_to_counterparty_output; - Some((event.txid, event.confirmation_threshold())) - } else { None } - }); + let funding_spend_pending = + us.onchain_events_awaiting_threshold_conf.iter().find_map(|event| { + if let OnchainEvent::FundingSpendConfirmation { + commitment_tx_to_counterparty_output, + .. + } = event.event + { + confirmed_counterparty_output = commitment_tx_to_counterparty_output; + Some((event.txid, event.confirmation_threshold())) + } else { + None + } + }); if let Some((txid, conf_thresh)) = funding_spend_pending { debug_assert!(us.funding_spend_confirmed.is_none(), "We have a pending funding spend awaiting anti-reorg confirmation, we can't have confirmed it already!"); @@ -2513,29 +2686,39 @@ impl ChannelMonitor { ($holder_commitment: expr, $counterparty_revoked_commitment: expr, $htlc_iter: expr) => { for (htlc, source) in $htlc_iter { if htlc.transaction_output_index.is_some() { - if let Some(bal) = us.get_htlc_balance( - htlc, source, $holder_commitment, $counterparty_revoked_commitment, confirmed_txid + htlc, + source, + $holder_commitment, + $counterparty_revoked_commitment, + confirmed_txid, ) { res.push(bal); } } } - } + }; } if let Some(txid) = confirmed_txid { let mut found_commitment_tx = false; - if let Some(counterparty_tx_htlcs) = us.funding.counterparty_claimable_outpoints.get(&txid) { + if let Some(counterparty_tx_htlcs) = + us.funding.counterparty_claimable_outpoints.get(&txid) + { // First look for the to_remote output back to us. if let Some(conf_thresh) = pending_commitment_tx_conf_thresh { - if let Some(value) = us.onchain_events_awaiting_threshold_conf.iter().find_map(|event| { - if let OnchainEvent::MaturingOutput { - descriptor: SpendableOutputDescriptor::StaticPaymentOutput(descriptor) - } = &event.event { - Some(descriptor.output.value) - } else { None } - }) { + if let Some(value) = + us.onchain_events_awaiting_threshold_conf.iter().find_map(|event| { + if let OnchainEvent::MaturingOutput { + descriptor: + SpendableOutputDescriptor::StaticPaymentOutput(descriptor), + } = &event.event + { + Some(descriptor.output.value) + } else { + None + } + }) { res.push(Balance::ClaimableAwaitingConfirmations { amount_satoshis: value.to_sat(), confirmation_height: conf_thresh, @@ -2547,10 +2730,20 @@ impl ChannelMonitor { // confirmation with the same height or have never met our dust amount. } } - if Some(txid) == us.funding.current_counterparty_commitment_txid || Some(txid) == us.funding.prev_counterparty_commitment_txid { - walk_htlcs!(false, false, counterparty_tx_htlcs.iter().map(|(a, b)| (a, b.as_ref().map(|b| &**b)))); + if Some(txid) == us.funding.current_counterparty_commitment_txid + || Some(txid) == us.funding.prev_counterparty_commitment_txid + { + walk_htlcs!( + false, + false, + counterparty_tx_htlcs.iter().map(|(a, b)| (a, b.as_ref().map(|b| &**b))) + ); } else { - walk_htlcs!(false, true, counterparty_tx_htlcs.iter().map(|(a, b)| (a, b.as_ref().map(|b| &**b)))); + walk_htlcs!( + false, + true, + counterparty_tx_htlcs.iter().map(|(a, b)| (a, b.as_ref().map(|b| &**b))) + ); // The counterparty broadcasted a revoked state! // Look for any StaticOutputs first, generating claimable balances for those. // If any match the confirmed counterparty revoked to_self output, skip @@ -2558,17 +2751,27 @@ impl ChannelMonitor { let mut spent_counterparty_output = false; for event in us.onchain_events_awaiting_threshold_conf.iter() { if let OnchainEvent::MaturingOutput { - descriptor: SpendableOutputDescriptor::StaticOutput { output, .. } - } = &event.event { + descriptor: SpendableOutputDescriptor::StaticOutput { output, .. }, + } = &event.event + { res.push(Balance::ClaimableAwaitingConfirmations { amount_satoshis: output.value.to_sat(), confirmation_height: event.confirmation_threshold(), source: BalanceSource::CounterpartyForceClosed, }); - if let Some(confirmed_to_self_idx) = confirmed_counterparty_output.map(|(idx, _)| idx) { - if event.transaction.as_ref().map(|tx| - tx.input.iter().any(|inp| inp.previous_output.vout == confirmed_to_self_idx) - ).unwrap_or(false) { + if let Some(confirmed_to_self_idx) = + confirmed_counterparty_output.map(|(idx, _)| idx) + { + if event + .transaction + .as_ref() + .map(|tx| { + tx.input.iter().any(|inp| { + inp.previous_output.vout == confirmed_to_self_idx + }) + }) + .unwrap_or(false) + { spent_counterparty_output = true; } } @@ -2576,9 +2779,11 @@ impl ChannelMonitor { } if spent_counterparty_output { - } else if let Some((confirmed_to_self_idx, amt)) = confirmed_counterparty_output { - let output_spendable = us.onchain_tx_handler - .is_output_spend_pending(&BitcoinOutPoint::new(txid, confirmed_to_self_idx)); + } else if let Some((confirmed_to_self_idx, amt)) = confirmed_counterparty_output + { + let output_spendable = us.onchain_tx_handler.is_output_spend_pending( + &BitcoinOutPoint::new(txid, confirmed_to_self_idx), + ); if output_spendable { res.push(Balance::CounterpartyRevokedOutputClaimable { amount_satoshis: amt.to_sat(), @@ -2595,7 +2800,11 @@ impl ChannelMonitor { walk_htlcs!(true, false, htlcs_with_sources); if let Some(conf_thresh) = pending_commitment_tx_conf_thresh { res.push(Balance::ClaimableAwaitingConfirmations { - amount_satoshis: us.funding.current_holder_commitment.tx.to_broadcaster_value_sat(), + amount_satoshis: us + .funding + .current_holder_commitment + .tx + .to_broadcaster_value_sat(), confirmation_height: conf_thresh, source: BalanceSource::HolderForceClosed, }); @@ -2621,7 +2830,11 @@ impl ChannelMonitor { // neither us nor our counterparty misbehaved. At worst we've under-estimated // the amount we can claim as we'll punish a misbehaving counterparty. res.push(Balance::ClaimableAwaitingConfirmations { - amount_satoshis: us.funding.current_holder_commitment.tx.to_broadcaster_value_sat(), + amount_satoshis: us + .funding + .current_holder_commitment + .tx + .to_broadcaster_value_sat(), confirmation_height: conf_thresh, source: BalanceSource::CoopClose, }); @@ -2640,7 +2853,9 @@ impl ChannelMonitor { } let rounded_value_msat = if htlc.transaction_output_index.is_none() { htlc.amount_msat - } else { htlc.amount_msat % 1000 }; + } else { + htlc.amount_msat % 1000 + }; if htlc.offered { let outbound_payment = match source { None => panic!("Outbound HTLCs should have a source"), @@ -2678,15 +2893,19 @@ impl ChannelMonitor { } } } - let to_self_value_sat = us.funding.current_holder_commitment.tx.to_broadcaster_value_sat(); + let to_self_value_sat = + us.funding.current_holder_commitment.tx.to_broadcaster_value_sat(); res.push(Balance::ClaimableOnChannelClose { amount_satoshis: to_self_value_sat + claimable_inbound_htlc_value_sat, transaction_fee_satoshis: if us.holder_pays_commitment_tx_fee.unwrap_or(true) { chan_utils::commit_tx_fee_sat( - us.funding.current_holder_commitment.tx.feerate_per_kw(), nondust_htlc_count, + us.funding.current_holder_commitment.tx.feerate_per_kw(), + nondust_htlc_count, us.channel_type_features(), ) - } else { 0 }, + } else { + 0 + }, outbound_payment_htlc_rounded_msat, outbound_forwarded_htlc_rounded_msat, inbound_claiming_htlc_rounded_msat, @@ -2704,22 +2923,33 @@ impl ChannelMonitor { /// This is similar to [`Self::get_pending_or_resolved_outbound_htlcs`] except it includes /// HTLCs which were resolved on-chain (i.e. where the final HTLC resolution was done by an /// event from this `ChannelMonitor`). - pub(crate) fn get_all_current_outbound_htlcs(&self) -> HashMap)> { + pub(crate) fn get_all_current_outbound_htlcs( + &self, + ) -> HashMap)> { let mut res = new_hash_map(); // Just examine the available counterparty commitment transactions. See docs on // `fail_unbroadcast_htlcs`, below, for justification. let us = self.inner.lock().unwrap(); macro_rules! walk_counterparty_commitment { ($txid: expr) => { - if let Some(ref latest_outpoints) = us.funding.counterparty_claimable_outpoints.get($txid) { + if let Some(ref latest_outpoints) = + us.funding.counterparty_claimable_outpoints.get($txid) + { for &(ref htlc, ref source_option) in latest_outpoints.iter() { if let &Some(ref source) = source_option { - res.insert((**source).clone(), (htlc.clone(), - us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).cloned())); + res.insert( + (**source).clone(), + ( + htlc.clone(), + us.counterparty_fulfilled_htlcs + .get(&SentHTLCId::from_source(source)) + .cloned(), + ), + ); } } } - } + }; } if let Some(ref txid) = us.funding.current_counterparty_commitment_txid { walk_counterparty_commitment!(txid); @@ -2737,7 +2967,9 @@ impl ChannelMonitor { /// /// Currently, the preimage is unused, however if it is present in the relevant internal state /// an HTLC is always included even if it has been resolved. - pub(crate) fn get_pending_or_resolved_outbound_htlcs(&self) -> HashMap)> { + pub(crate) fn get_pending_or_resolved_outbound_htlcs( + &self, + ) -> HashMap)> { let us = self.inner.lock().unwrap(); // We're only concerned with the confirmation count of HTLC transactions, and don't // actually care how many confirmations a commitment transaction may or may not have. Thus, @@ -2746,7 +2978,9 @@ impl ChannelMonitor { us.onchain_events_awaiting_threshold_conf.iter().find_map(|event| { if let OnchainEvent::FundingSpendConfirmation { .. } = event.event { Some(event.txid) - } else { None } + } else { + None + } }) }); @@ -2761,7 +2995,11 @@ impl ChannelMonitor { macro_rules! walk_htlcs { ($holder_commitment: expr, $htlc_iter: expr) => { for (htlc, source) in $htlc_iter { - if us.htlcs_resolved_on_chain.iter().any(|v| v.commitment_tx_output_idx == htlc.transaction_output_index) { + if us + .htlcs_resolved_on_chain + .iter() + .any(|v| v.commitment_tx_output_idx == htlc.transaction_output_index) + { // We should assert that funding_spend_confirmed is_some() here, but we // have some unit tests which violate HTLC transaction CSVs entirely and // would fail. @@ -2771,41 +3009,67 @@ impl ChannelMonitor { // If the payment was outbound, check if there's an HTLCUpdate // indicating we have spent this HTLC with a timeout, claiming it back // and awaiting confirmations on it. - let htlc_update_confd = us.onchain_events_awaiting_threshold_conf.iter().any(|event| { - if let OnchainEvent::HTLCUpdate { commitment_tx_output_idx: Some(commitment_tx_output_idx), .. } = event.event { - // If the HTLC was timed out, we wait for ANTI_REORG_DELAY blocks - // before considering it "no longer pending" - this matches when we - // provide the ChannelManager an HTLC failure event. - Some(commitment_tx_output_idx) == htlc.transaction_output_index && - us.best_block.height >= event.height + ANTI_REORG_DELAY - 1 - } else if let OnchainEvent::HTLCSpendConfirmation { commitment_tx_output_idx, .. } = event.event { - // If the HTLC was fulfilled with a preimage, we consider the HTLC - // immediately non-pending, matching when we provide ChannelManager - // the preimage. - Some(commitment_tx_output_idx) == htlc.transaction_output_index - } else { false } - }); + let htlc_update_confd = + us.onchain_events_awaiting_threshold_conf.iter().any(|event| { + if let OnchainEvent::HTLCUpdate { + commitment_tx_output_idx: Some(commitment_tx_output_idx), + .. + } = event.event + { + // If the HTLC was timed out, we wait for ANTI_REORG_DELAY blocks + // before considering it "no longer pending" - this matches when we + // provide the ChannelManager an HTLC failure event. + Some(commitment_tx_output_idx) == htlc.transaction_output_index + && us.best_block.height + >= event.height + ANTI_REORG_DELAY - 1 + } else if let OnchainEvent::HTLCSpendConfirmation { + commitment_tx_output_idx, + .. + } = event.event + { + // If the HTLC was fulfilled with a preimage, we consider the HTLC + // immediately non-pending, matching when we provide ChannelManager + // the preimage. + Some(commitment_tx_output_idx) == htlc.transaction_output_index + } else { + false + } + }); if let Some(source) = source { - let counterparty_resolved_preimage_opt = - us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).cloned(); + let counterparty_resolved_preimage_opt = us + .counterparty_fulfilled_htlcs + .get(&SentHTLCId::from_source(source)) + .cloned(); if !htlc_update_confd || counterparty_resolved_preimage_opt.is_some() { - res.insert(source.clone(), (htlc.clone(), counterparty_resolved_preimage_opt)); + res.insert( + source.clone(), + (htlc.clone(), counterparty_resolved_preimage_opt), + ); } } else { panic!("Outbound HTLCs should have a source"); } } } - } + }; } let txid = confirmed_txid.unwrap(); - if Some(txid) == us.funding.current_counterparty_commitment_txid || Some(txid) == us.funding.prev_counterparty_commitment_txid { - walk_htlcs!(false, us.funding.counterparty_claimable_outpoints.get(&txid).unwrap().iter().filter_map(|(a, b)| { - if let &Some(ref source) = b { - Some((a, Some(&**source))) - } else { None } - })); + if Some(txid) == us.funding.current_counterparty_commitment_txid + || Some(txid) == us.funding.prev_counterparty_commitment_txid + { + walk_htlcs!( + false, + us.funding.counterparty_claimable_outpoints.get(&txid).unwrap().iter().filter_map( + |(a, b)| { + if let &Some(ref source) = b { + Some((a, Some(&**source))) + } else { + None + } + } + ) + ); } else if txid == us.funding.current_holder_commitment.tx.trust().txid() { let htlcs = us.funding.current_holder_commitment.htlcs_with_sources(); walk_htlcs!(true, htlcs); @@ -2819,7 +3083,9 @@ impl ChannelMonitor { res } - pub(crate) fn get_stored_preimages(&self) -> HashMap)> { + pub(crate) fn get_stored_preimages( + &self, + ) -> HashMap)> { self.inner.lock().unwrap().payment_preimages.clone() } } @@ -2932,7 +3198,14 @@ pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec { #[cfg(any(test, feature = "_test_utils"))] pub fn deliberately_bogus_accepted_htlc_witness() -> Vec> { - vec![Vec::new(), Vec::new(), Vec::new(), Vec::new(), deliberately_bogus_accepted_htlc_witness_program().into()].into() + vec![ + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + deliberately_bogus_accepted_htlc_witness_program().into(), + ] + .into() } impl ChannelMonitorImpl { @@ -2973,22 +3246,34 @@ impl ChannelMonitorImpl { // events for now-revoked/fulfilled HTLCs. if let Some(txid) = self.funding.prev_counterparty_commitment_txid.take() { if self.funding.current_counterparty_commitment_txid.unwrap() != txid { - let cur_claimables = self.funding.counterparty_claimable_outpoints.get( - &self.funding.current_counterparty_commitment_txid.unwrap()).unwrap(); - for (_, ref source_opt) in self.funding.counterparty_claimable_outpoints.get(&txid).unwrap() { + let cur_claimables = self + .funding + .counterparty_claimable_outpoints + .get(&self.funding.current_counterparty_commitment_txid.unwrap()) + .unwrap(); + for (_, ref source_opt) in + self.funding.counterparty_claimable_outpoints.get(&txid).unwrap() + { if let Some(source) = source_opt { - if !cur_claimables.iter() + if !cur_claimables + .iter() .any(|(_, cur_source_opt)| cur_source_opt == source_opt) { - self.counterparty_fulfilled_htlcs.remove(&SentHTLCId::from_source(source)); + self.counterparty_fulfilled_htlcs + .remove(&SentHTLCId::from_source(source)); } } } - for &mut (_, ref mut source_opt) in self.funding.counterparty_claimable_outpoints.get_mut(&txid).unwrap() { + for &mut (_, ref mut source_opt) in + self.funding.counterparty_claimable_outpoints.get_mut(&txid).unwrap() + { *source_opt = None; } } else { - assert!(cfg!(fuzzing), "Commitment txids are unique outside of fuzzing, where hashes can collide"); + assert!( + cfg!(fuzzing), + "Commitment txids are unique outside of fuzzing, where hashes can collide" + ); } } @@ -3001,22 +3286,24 @@ impl ChannelMonitorImpl { self.payment_preimages.retain(|&k, _| { for htlc in cur_holder_commitment.htlcs() { if k == htlc.payment_hash { - return true + return true; } } if let Some(prev_holder_commitment) = prev_holder_commitment { for htlc in prev_holder_commitment.htlcs() { if k == htlc.payment_hash { - return true + return true; } } } let contains = if let Some(cn) = counterparty_hash_commitment_number.get(&k) { if *cn < min_idx { - return true + return true; } true - } else { false }; + } else { + false + }; if contains { counterparty_hash_commitment_number.remove(&k); } @@ -3029,18 +3316,30 @@ impl ChannelMonitorImpl { fn provide_initial_counterparty_commitment_tx( &mut self, commitment_tx: CommitmentTransaction, logger: &WithChannelMonitor, - ) where L::Target: Logger { + ) where + L::Target: Logger, + { // We populate this field for downgrades - self.initial_counterparty_commitment_info = Some((commitment_tx.per_commitment_point(), - commitment_tx.feerate_per_kw(), commitment_tx.to_broadcaster_value_sat(), commitment_tx.to_countersignatory_value_sat())); + self.initial_counterparty_commitment_info = Some(( + commitment_tx.per_commitment_point(), + commitment_tx.feerate_per_kw(), + commitment_tx.to_broadcaster_value_sat(), + commitment_tx.to_countersignatory_value_sat(), + )); - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let rebuilt_commitment_tx = self.initial_counterparty_commitment_tx().unwrap(); debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), commitment_tx.trust().txid()); } - self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), Vec::new(), commitment_tx.commitment_number(), - commitment_tx.per_commitment_point(), logger); + self.provide_latest_counterparty_commitment_tx( + commitment_tx.trust().txid(), + Vec::new(), + commitment_tx.commitment_number(), + commitment_tx.per_commitment_point(), + logger, + ); // Soon, we will only populate this field self.initial_counterparty_commitment_tx = Some(commitment_tx); } @@ -3048,8 +3347,11 @@ impl ChannelMonitorImpl { fn provide_latest_counterparty_commitment_tx( &mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, - commitment_number: u64, their_per_commitment_point: PublicKey, logger: &WithChannelMonitor, - ) where L::Target: Logger { + commitment_number: u64, their_per_commitment_point: PublicKey, + logger: &WithChannelMonitor, + ) where + L::Target: Logger, + { // TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction // so that a remote monitor doesn't learn anything unless there is a malicious close. // (only maybe, sadly we cant do the same for local info, as we need to be aware of @@ -3059,7 +3361,8 @@ impl ChannelMonitorImpl { } log_trace!(logger, "Tracking new counterparty commitment transaction with txid {} at commitment number {} with {} HTLC outputs", txid, commitment_number, htlc_outputs.len()); - self.funding.prev_counterparty_commitment_txid = self.funding.current_counterparty_commitment_txid.take(); + self.funding.prev_counterparty_commitment_txid = + self.funding.current_counterparty_commitment_txid.take(); self.funding.current_counterparty_commitment_txid = Some(txid); self.funding.counterparty_claimable_outpoints.insert(txid, htlc_outputs.clone()); self.current_counterparty_commitment_number = commitment_number; @@ -3067,20 +3370,28 @@ impl ChannelMonitorImpl { match self.their_cur_per_commitment_points { Some(old_points) => { if old_points.0 == commitment_number + 1 { - self.their_cur_per_commitment_points = Some((old_points.0, old_points.1, Some(their_per_commitment_point))); + self.their_cur_per_commitment_points = + Some((old_points.0, old_points.1, Some(their_per_commitment_point))); } else if old_points.0 == commitment_number + 2 { if let Some(old_second_point) = old_points.2 { - self.their_cur_per_commitment_points = Some((old_points.0 - 1, old_second_point, Some(their_per_commitment_point))); + self.their_cur_per_commitment_points = Some(( + old_points.0 - 1, + old_second_point, + Some(their_per_commitment_point), + )); } else { - self.their_cur_per_commitment_points = Some((commitment_number, their_per_commitment_point, None)); + self.their_cur_per_commitment_points = + Some((commitment_number, their_per_commitment_point, None)); } } else { - self.their_cur_per_commitment_points = Some((commitment_number, their_per_commitment_point, None)); + self.their_cur_per_commitment_points = + Some((commitment_number, their_per_commitment_point, None)); } }, None => { - self.their_cur_per_commitment_points = Some((commitment_number, their_per_commitment_point, None)); - } + self.their_cur_per_commitment_points = + Some((commitment_number, their_per_commitment_point, None)); + }, } } @@ -3098,29 +3409,48 @@ impl ChannelMonitorImpl { // If we have non-dust HTLCs in htlc_outputs, ensure they match the HTLCs in the // `holder_commitment_tx`. In the future, we'll no longer provide the redundant data // and just pass in source data via `nondust_htlc_sources`. - debug_assert_eq!(htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).count(), holder_commitment_tx.trust().nondust_htlcs().len()); - for (a, b) in htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).map(|(h, _, _)| h).zip(holder_commitment_tx.trust().nondust_htlcs().iter()) { + debug_assert_eq!( + htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).count(), + holder_commitment_tx.trust().nondust_htlcs().len() + ); + for (a, b) in htlc_outputs + .iter() + .filter(|(_, s, _)| s.is_some()) + .map(|(h, _, _)| h) + .zip(holder_commitment_tx.trust().nondust_htlcs().iter()) + { debug_assert_eq!(a, b); } - debug_assert_eq!(htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).count(), holder_commitment_tx.counterparty_htlc_sigs.len()); - for (a, b) in htlc_outputs.iter().filter_map(|(_, s, _)| s.as_ref()).zip(holder_commitment_tx.counterparty_htlc_sigs.iter()) { + debug_assert_eq!( + htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).count(), + holder_commitment_tx.counterparty_htlc_sigs.len() + ); + for (a, b) in htlc_outputs + .iter() + .filter_map(|(_, s, _)| s.as_ref()) + .zip(holder_commitment_tx.counterparty_htlc_sigs.iter()) + { debug_assert_eq!(a, b); } // Backfill the non-dust HTLC sources. debug_assert!(nondust_htlc_sources.is_empty()); nondust_htlc_sources.reserve_exact(holder_commitment_tx.nondust_htlcs().len()); - let dust_htlcs = htlc_outputs.into_iter().filter_map(|(htlc, _, source)| { - // Filter our non-dust HTLCs, while at the same time pushing their sources into - // `nondust_htlc_sources`. - if htlc.transaction_output_index.is_none() { - return Some((htlc, source)); - } - if htlc.offered { - nondust_htlc_sources.push(source.expect("Outbound HTLCs should have a source")); - } - None - }).collect(); + let dust_htlcs = htlc_outputs + .into_iter() + .filter_map(|(htlc, _, source)| { + // Filter our non-dust HTLCs, while at the same time pushing their sources into + // `nondust_htlc_sources`. + if htlc.transaction_output_index.is_none() { + return Some((htlc, source)); + } + if htlc.offered { + nondust_htlc_sources + .push(source.expect("Outbound HTLCs should have a source")); + } + None + }) + .collect(); dust_htlcs } else { @@ -3135,14 +3465,20 @@ impl ChannelMonitorImpl { } } - debug_assert!(htlc_outputs.iter().all(|(htlc, _, _)| htlc.transaction_output_index.is_none())); + debug_assert!(htlc_outputs + .iter() + .all(|(htlc, _, _)| htlc.transaction_output_index.is_none())); debug_assert!(htlc_outputs.iter().all(|(_, sig_opt, _)| sig_opt.is_none())); - debug_assert_eq!(holder_commitment_tx.trust().nondust_htlcs().len(), holder_commitment_tx.counterparty_htlc_sigs.len()); + debug_assert_eq!( + holder_commitment_tx.trust().nondust_htlcs().len(), + holder_commitment_tx.counterparty_htlc_sigs.len() + ); let mut sources = nondust_htlc_sources.iter(); for htlc in holder_commitment_tx.trust().nondust_htlcs().iter() { if htlc.offered { - let source = sources.next().expect("Non-dust HTLC sources didn't match commitment tx"); + let source = + sources.next().expect("Non-dust HTLC sources didn't match commitment tx"); assert!(source.possibly_matches_output(htlc)); } } @@ -3154,21 +3490,24 @@ impl ChannelMonitorImpl { self.current_holder_commitment_number = holder_commitment_tx.trust().commitment_number(); self.onchain_tx_handler.provide_latest_holder_tx(holder_commitment_tx.clone()); - let mut holder_commitment = HolderCommitment { - tx: holder_commitment_tx, - nondust_htlc_sources, - dust_htlcs, - }; + let mut holder_commitment = + HolderCommitment { tx: holder_commitment_tx, nondust_htlc_sources, dust_htlcs }; mem::swap(&mut holder_commitment, &mut self.funding.current_holder_commitment); self.funding.prev_holder_commitment = Some(holder_commitment); for (claimed_htlc_id, claimed_preimage) in claimed_htlcs { - #[cfg(debug_assertions)] { - let cur_counterparty_htlcs = self.funding.counterparty_claimable_outpoints.get( - &self.funding.current_counterparty_commitment_txid.unwrap()).unwrap(); + #[cfg(debug_assertions)] + { + let cur_counterparty_htlcs = self + .funding + .counterparty_claimable_outpoints + .get(&self.funding.current_counterparty_commitment_txid.unwrap()) + .unwrap(); assert!(cur_counterparty_htlcs.iter().any(|(_, source_opt)| { if let Some(source) = source_opt { SentHTLCId::from_source(source) == *claimed_htlc_id - } else { false } + } else { + false + } })); } self.counterparty_fulfilled_htlcs.insert(*claimed_htlc_id, *claimed_preimage); @@ -3182,12 +3521,14 @@ impl ChannelMonitorImpl { fn provide_payment_preimage( &mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, payment_info: &Option, broadcaster: &B, - fee_estimator: &LowerBoundedFeeEstimator, logger: &WithChannelMonitor) - where B::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, + fee_estimator: &LowerBoundedFeeEstimator, logger: &WithChannelMonitor, + ) where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, { - self.payment_preimages.entry(payment_hash.clone()) + self.payment_preimages + .entry(payment_hash.clone()) .and_modify(|(_, payment_infos)| { if let Some(payment_info) = payment_info { if !payment_infos.contains(&payment_info) { @@ -3215,18 +3556,35 @@ impl ChannelMonitorImpl { // First check if a counterparty commitment transaction has been broadcasted: macro_rules! claim_htlcs { ($commitment_number: expr, $txid: expr, $htlcs: expr) => { - let (htlc_claim_reqs, _) = self.get_counterparty_output_claim_info($commitment_number, $txid, None, $htlcs); + let (htlc_claim_reqs, _) = self.get_counterparty_output_claim_info( + $commitment_number, + $txid, + None, + $htlcs, + ); let conf_target = self.closure_conf_target(); self.onchain_tx_handler.update_claims_view_from_requests( - htlc_claim_reqs, self.best_block.height, self.best_block.height, broadcaster, - conf_target, &self.destination_script, fee_estimator, logger, + htlc_claim_reqs, + self.best_block.height, + self.best_block.height, + broadcaster, + conf_target, + &self.destination_script, + fee_estimator, + logger, ); - } + }; } if let Some(txid) = self.funding.current_counterparty_commitment_txid { if txid == confirmed_spend_txid { - if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { - claim_htlcs!(*commitment_number, txid, self.funding.counterparty_claimable_outpoints.get(&txid)); + if let Some(commitment_number) = + self.counterparty_commitment_txn_on_chain.get(&txid) + { + claim_htlcs!( + *commitment_number, + txid, + self.funding.counterparty_claimable_outpoints.get(&txid) + ); } else { debug_assert!(false); log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number"); @@ -3236,8 +3594,14 @@ impl ChannelMonitorImpl { } if let Some(txid) = self.funding.prev_counterparty_commitment_txid { if txid == confirmed_spend_txid { - if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { - claim_htlcs!(*commitment_number, txid, self.funding.counterparty_claimable_outpoints.get(&txid)); + if let Some(commitment_number) = + self.counterparty_commitment_txn_on_chain.get(&txid) + { + claim_htlcs!( + *commitment_number, + txid, + self.funding.counterparty_claimable_outpoints.get(&txid) + ); } else { debug_assert!(false); log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number"); @@ -3252,7 +3616,9 @@ impl ChannelMonitorImpl { // *we* sign a holder commitment transaction, not when e.g. a watchtower broadcasts one of our // holder commitment transactions. if self.broadcasted_holder_revokable_script.is_some() { - let holder_commitment = if self.funding.current_holder_commitment.tx.trust().txid() == confirmed_spend_txid { + let holder_commitment = if self.funding.current_holder_commitment.tx.trust().txid() + == confirmed_spend_txid + { Some(&self.funding.current_holder_commitment) } else if let Some(prev_holder_commitment) = &self.funding.prev_holder_commitment { if prev_holder_commitment.tx.trust().txid() == confirmed_spend_txid { @@ -3267,24 +3633,34 @@ impl ChannelMonitorImpl { // Assume that the broadcasted commitment transaction confirmed in the current best // block. Even if not, its a reasonable metric for the bump criteria on the HTLC // transactions. - let (claim_reqs, _) = self.get_broadcasted_holder_claims(&holder_commitment.tx, self.best_block.height); + let (claim_reqs, _) = self + .get_broadcasted_holder_claims(&holder_commitment.tx, self.best_block.height); let conf_target = self.closure_conf_target(); self.onchain_tx_handler.update_claims_view_from_requests( - claim_reqs, self.best_block.height, self.best_block.height, broadcaster, - conf_target, &self.destination_script, fee_estimator, logger, + claim_reqs, + self.best_block.height, + self.best_block.height, + broadcaster, + conf_target, + &self.destination_script, + fee_estimator, + logger, ); } } } - fn generate_claimable_outpoints_and_watch_outputs(&mut self, reason: ClosureReason) -> (Vec, Vec) { + fn generate_claimable_outpoints_and_watch_outputs( + &mut self, reason: ClosureReason, + ) -> (Vec, Vec) { let funding_outp = HolderFundingOutput::build( self.funding.current_holder_commitment.tx.clone(), self.funding.channel_parameters.clone(), ); let funding_outpoint = self.get_funding_txo(); let commitment_package = PackageTemplate::build_package( - funding_outpoint.txid.clone(), funding_outpoint.index as u32, + funding_outpoint.txid.clone(), + funding_outpoint.index as u32, PackageSolvingData::HolderFundingOutput(funding_outp), self.best_block.height, ); @@ -3309,13 +3685,14 @@ impl ChannelMonitorImpl { // assuming it gets confirmed in the next block. Sadly, we have code which considers // "not yet confirmed" things as discardable, so we cannot do that here. let (mut new_outpoints, _) = self.get_broadcasted_holder_claims( - &self.funding.current_holder_commitment.tx, self.best_block.height, - ); - let new_outputs = self.get_broadcasted_holder_watch_outputs( - &self.funding.current_holder_commitment.tx + &self.funding.current_holder_commitment.tx, + self.best_block.height, ); + let new_outputs = self + .get_broadcasted_holder_watch_outputs(&self.funding.current_holder_commitment.tx); if !new_outputs.is_empty() { - watch_outputs.push((self.funding.current_holder_commitment.tx.trust().txid(), new_outputs)); + watch_outputs + .push((self.funding.current_holder_commitment.tx.trust().txid(), new_outputs)); } claimable_outpoints.append(&mut new_outpoints); } @@ -3323,34 +3700,55 @@ impl ChannelMonitorImpl { } pub(crate) fn queue_latest_holder_commitment_txn_for_broadcast( - &mut self, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &WithChannelMonitor - ) - where + &mut self, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, + logger: &WithChannelMonitor, + ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, { - let (claimable_outpoints, _) = self.generate_claimable_outpoints_and_watch_outputs(ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }); + let (claimable_outpoints, _) = + self.generate_claimable_outpoints_and_watch_outputs(ClosureReason::HolderForceClosed { + broadcasted_latest_txn: Some(true), + }); let conf_target = self.closure_conf_target(); self.onchain_tx_handler.update_claims_view_from_requests( - claimable_outpoints, self.best_block.height, self.best_block.height, broadcaster, - conf_target, &self.destination_script, fee_estimator, logger, + claimable_outpoints, + self.best_block.height, + self.best_block.height, + broadcaster, + conf_target, + &self.destination_script, + fee_estimator, + logger, ); } fn update_monitor( - &mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &WithChannelMonitor + &mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, + logger: &WithChannelMonitor, ) -> Result<(), ()> - where B::Target: BroadcasterInterface, + where + B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, { - if self.latest_update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID && updates.update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID { - log_info!(logger, "Applying pre-0.1 post-force-closed update to monitor {} with {} change(s).", - log_funding_info!(self), updates.updates.len()); + if self.latest_update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID + && updates.update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID + { + log_info!( + logger, + "Applying pre-0.1 post-force-closed update to monitor {} with {} change(s).", + log_funding_info!(self), + updates.updates.len() + ); } else if updates.update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID { - log_info!(logger, "Applying pre-0.1 force close update to monitor {} with {} change(s).", - log_funding_info!(self), updates.updates.len()); + log_info!( + logger, + "Applying pre-0.1 force close update to monitor {} with {} change(s).", + log_funding_info!(self), + updates.updates.len() + ); } else { log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} change(s).", log_funding_info!(self), self.latest_update_id, updates.update_id, updates.updates.len()); @@ -3370,10 +3768,15 @@ impl ChannelMonitorImpl { ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {}, // We should have already seen a `ChannelForceClosed` update if we're trying to // provide a preimage at this point. - ChannelMonitorUpdateStep::PaymentPreimage { .. } => - debug_assert!(self.lockdown_from_offchain), + ChannelMonitorUpdateStep::PaymentPreimage { .. } => { + debug_assert!(self.lockdown_from_offchain) + }, _ => { - log_error!(logger, "Attempted to apply post-force-close ChannelMonitorUpdate of type {}", updates.updates[0].variant_name()); + log_error!( + logger, + "Attempted to apply post-force-close ChannelMonitorUpdate of type {}", + updates.updates[0].variant_name() + ); panic!("Attempted to apply post-force-close ChannelMonitorUpdate that wasn't providing a payment preimage"); }, } @@ -3387,53 +3790,112 @@ impl ChannelMonitorImpl { let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&**fee_estimator); for update in updates.updates.iter() { match update { - ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs, nondust_htlc_sources } => { - log_trace!(logger, "Updating ChannelMonitor with latest holder commitment transaction info"); - if self.lockdown_from_offchain { panic!(); } - self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs, nondust_htlc_sources.clone()); - } + ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { + commitment_tx, + htlc_outputs, + claimed_htlcs, + nondust_htlc_sources, + } => { + log_trace!( + logger, + "Updating ChannelMonitor with latest holder commitment transaction info" + ); + if self.lockdown_from_offchain { + panic!(); + } + self.provide_latest_holder_commitment_tx( + commitment_tx.clone(), + htlc_outputs.clone(), + &claimed_htlcs, + nondust_htlc_sources.clone(), + ); + }, // Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitmentTX`. // For now we just add the code to handle the new updates. // Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant. - ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_per_commitment_point, .. } => { + ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { + commitment_txid, + htlc_outputs, + commitment_number, + their_per_commitment_point, + .. + } => { log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info"); - self.provide_latest_counterparty_commitment_tx(*commitment_txid, htlc_outputs.clone(), *commitment_number, *their_per_commitment_point, logger) + self.provide_latest_counterparty_commitment_tx( + *commitment_txid, + htlc_outputs.clone(), + *commitment_number, + *their_per_commitment_point, + logger, + ) }, - ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { htlc_outputs, commitment_tx } => { + ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { + htlc_outputs, + commitment_tx, + } => { log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info"); - self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), htlc_outputs.clone(), commitment_tx.commitment_number(), commitment_tx.per_commitment_point(), logger) + self.provide_latest_counterparty_commitment_tx( + commitment_tx.trust().txid(), + htlc_outputs.clone(), + commitment_tx.commitment_number(), + commitment_tx.per_commitment_point(), + logger, + ) }, ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage, payment_info } => { log_trace!(logger, "Updating ChannelMonitor with payment preimage"); - self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()), &payment_preimage, payment_info, broadcaster, &bounded_fee_estimator, logger) + self.provide_payment_preimage( + &PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()), + &payment_preimage, + payment_info, + broadcaster, + &bounded_fee_estimator, + logger, + ) }, ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => { log_trace!(logger, "Updating ChannelMonitor with commitment secret"); if let Err(e) = self.provide_secret(*idx, *secret) { debug_assert!(false, "Latest counterparty commitment secret was invalid"); - log_error!(logger, "Providing latest counterparty commitment secret failed/was refused:"); + log_error!( + logger, + "Providing latest counterparty commitment secret failed/was refused:" + ); log_error!(logger, " {}", e); ret = Err(()); } }, ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } => { - log_trace!(logger, "Updating ChannelMonitor: channel force closed, should broadcast: {}", should_broadcast); + log_trace!( + logger, + "Updating ChannelMonitor: channel force closed, should broadcast: {}", + should_broadcast + ); self.lockdown_from_offchain = true; if *should_broadcast { // There's no need to broadcast our commitment transaction if we've seen one // confirmed (even with 1 confirmation) as it'll be rejected as // duplicate/conflicting. - let detected_funding_spend = self.funding_spend_confirmed.is_some() || - self.onchain_events_awaiting_threshold_conf.iter().any( - |event| matches!(event.event, OnchainEvent::FundingSpendConfirmation { .. })); + let detected_funding_spend = self.funding_spend_confirmed.is_some() + || self.onchain_events_awaiting_threshold_conf.iter().any(|event| { + matches!(event.event, OnchainEvent::FundingSpendConfirmation { .. }) + }); if detected_funding_spend { log_trace!(logger, "Avoiding commitment broadcast, already detected confirmed spend onchain"); continue; } - self.queue_latest_holder_commitment_txn_for_broadcast(broadcaster, &bounded_fee_estimator, logger); + self.queue_latest_holder_commitment_txn_for_broadcast( + broadcaster, + &bounded_fee_estimator, + logger, + ); } else if !self.holder_tx_signed { log_error!(logger, "WARNING: You have a potentially-unsafe holder commitment transaction available to broadcast"); - log_error!(logger, " in channel monitor for channel {}!", &self.channel_id()); + log_error!( + logger, + " in channel monitor for channel {}!", + &self.channel_id() + ); log_error!(logger, " Read the docs for ChannelMonitor::broadcast_latest_holder_commitment_txn to take manual action!"); } else { // If we generated a MonitorEvent::HolderForceClosed, the ChannelManager @@ -3444,14 +3906,20 @@ impl ChannelMonitorImpl { }, ChannelMonitorUpdateStep::ShutdownScript { scriptpubkey } => { log_trace!(logger, "Updating ChannelMonitor with shutdown script"); - if let Some(shutdown_script) = self.shutdown_script.replace(scriptpubkey.clone()) { - panic!("Attempted to replace shutdown script {} with {}", shutdown_script, scriptpubkey); + if let Some(shutdown_script) = + self.shutdown_script.replace(scriptpubkey.clone()) + { + panic!( + "Attempted to replace shutdown script {} with {}", + shutdown_script, scriptpubkey + ); } }, } } - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { self.counterparty_commitment_txs_from_update(updates); } @@ -3464,11 +3932,10 @@ impl ChannelMonitorImpl { for update in updates.updates.iter() { match update { ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } - |ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } - |ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. } - |ChannelMonitorUpdateStep::ShutdownScript { .. } - |ChannelMonitorUpdateStep::CommitmentSecret { .. } => - is_pre_close_update = true, + | ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } + | ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. } + | ChannelMonitorUpdateStep::ShutdownScript { .. } + | ChannelMonitorUpdateStep::CommitmentSecret { .. } => is_pre_close_update = true, // After a channel is closed, we don't communicate with our peer about it, so the // only things we will update is getting a new preimage (from a different channel) // or being told that the channel is closed. All other updates are generated while @@ -3481,7 +3948,9 @@ impl ChannelMonitorImpl { if ret.is_ok() && self.no_further_updates_allowed() && is_pre_close_update { log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent"); Err(()) - } else { ret } + } else { + ret + } } fn no_further_updates_allowed(&self) -> bool { @@ -3493,7 +3962,9 @@ impl ChannelMonitorImpl { } fn get_funding_txo(&self) -> OutPoint { - self.funding.channel_parameters.funding_outpoint + self.funding + .channel_parameters + .funding_outpoint .expect("Funding outpoint must be set for active monitor") } @@ -3530,8 +4001,11 @@ impl ChannelMonitorImpl { for (claim_id, claim_event) in pending_claim_events { match claim_event { ClaimEvent::BumpCommitment { - package_target_feerate_sat_per_1000_weight, commitment_tx, - commitment_tx_fee_satoshis, pending_nondust_htlcs, anchor_output_idx, + package_target_feerate_sat_per_1000_weight, + commitment_tx, + commitment_tx_fee_satoshis, + pending_nondust_htlcs, + anchor_output_idx, channel_parameters, } => { let channel_id = self.channel_id; @@ -3559,7 +4033,9 @@ impl ChannelMonitorImpl { })); }, ClaimEvent::BumpHTLC { - target_feerate_sat_per_1000_weight, htlcs, tx_lock_time, + target_feerate_sat_per_1000_weight, + htlcs, + tx_lock_time, } => { let channel_id = self.channel_id; let counterparty_node_id = self.counterparty_node_id; @@ -3571,7 +4047,7 @@ impl ChannelMonitorImpl { htlc_descriptors: htlcs, tx_lock_time, })); - } + }, } } ret @@ -3609,68 +4085,107 @@ impl ChannelMonitorImpl { fn build_counterparty_commitment_tx( &self, commitment_number: u64, their_per_commitment_point: &PublicKey, to_broadcaster_value: u64, to_countersignatory_value: u64, feerate_per_kw: u32, - nondust_htlcs: Vec + nondust_htlcs: Vec, ) -> CommitmentTransaction { let channel_parameters = &self.funding.channel_parameters.as_counterparty_broadcastable(); - CommitmentTransaction::new(commitment_number, their_per_commitment_point, - to_broadcaster_value, to_countersignatory_value, feerate_per_kw, nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx) + CommitmentTransaction::new( + commitment_number, + their_per_commitment_point, + to_broadcaster_value, + to_countersignatory_value, + feerate_per_kw, + nondust_htlcs, + channel_parameters, + &self.onchain_tx_handler.secp_ctx, + ) } - fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec { - update.updates.iter().filter_map(|update| { - // Soon we will drop the first branch here in favor of the second. - // In preparation, we just add the second branch without deleting the first. - // Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant. - match update { - &ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, - ref htlc_outputs, commitment_number, their_per_commitment_point, - feerate_per_kw: Some(feerate_per_kw), - to_broadcaster_value_sat: Some(to_broadcaster_value), - to_countersignatory_value_sat: Some(to_countersignatory_value) } => { - - let nondust_htlcs = htlc_outputs.iter().filter_map(|(htlc, _)| { - htlc.transaction_output_index.map(|_| htlc).cloned() - }).collect::>(); - - let commitment_tx = self.build_counterparty_commitment_tx(commitment_number, - &their_per_commitment_point, to_broadcaster_value, - to_countersignatory_value, feerate_per_kw, nondust_htlcs); + fn counterparty_commitment_txs_from_update( + &self, update: &ChannelMonitorUpdate, + ) -> Vec { + update + .updates + .iter() + .filter_map(|update| { + // Soon we will drop the first branch here in favor of the second. + // In preparation, we just add the second branch without deleting the first. + // Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant. + match update { + &ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { + commitment_txid, + ref htlc_outputs, + commitment_number, + their_per_commitment_point, + feerate_per_kw: Some(feerate_per_kw), + to_broadcaster_value_sat: Some(to_broadcaster_value), + to_countersignatory_value_sat: Some(to_countersignatory_value), + } => { + let nondust_htlcs = htlc_outputs + .iter() + .filter_map(|(htlc, _)| { + htlc.transaction_output_index.map(|_| htlc).cloned() + }) + .collect::>(); + + let commitment_tx = self.build_counterparty_commitment_tx( + commitment_number, + &their_per_commitment_point, + to_broadcaster_value, + to_countersignatory_value, + feerate_per_kw, + nondust_htlcs, + ); - debug_assert_eq!(commitment_tx.trust().txid(), commitment_txid); + debug_assert_eq!(commitment_tx.trust().txid(), commitment_txid); - Some(commitment_tx) - }, - &ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { - htlc_outputs: _, ref commitment_tx, - } => { - Some(commitment_tx.clone()) - }, - _ => None, - } - }).collect() + Some(commitment_tx) + }, + &ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { + htlc_outputs: _, + ref commitment_tx, + } => Some(commitment_tx.clone()), + _ => None, + } + }) + .collect() } fn sign_to_local_justice_tx( - &self, mut justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64 + &self, mut justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64, ) -> Result { let secret = self.get_secret(commitment_number).ok_or(())?; let per_commitment_key = SecretKey::from_slice(&secret).map_err(|_| ())?; - let their_per_commitment_point = PublicKey::from_secret_key( - &self.onchain_tx_handler.secp_ctx, &per_commitment_key); + let their_per_commitment_point = + PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key); - let revocation_pubkey = RevocationKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, - &self.holder_revocation_basepoint, &their_per_commitment_point); - let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, - &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &their_per_commitment_point); - let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, - self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key); + let revocation_pubkey = RevocationKey::from_basepoint( + &self.onchain_tx_handler.secp_ctx, + &self.holder_revocation_basepoint, + &their_per_commitment_point, + ); + let delayed_key = DelayedPaymentKey::from_basepoint( + &self.onchain_tx_handler.secp_ctx, + &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, + &their_per_commitment_point, + ); + let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript( + &revocation_pubkey, + self.counterparty_commitment_params.on_counterparty_tx_csv, + &delayed_key, + ); let channel_parameters = &self.funding.channel_parameters; let sig = self.onchain_tx_handler.signer.sign_justice_revoked_output( - &channel_parameters, &justice_tx, input_idx, value, &per_commitment_key, + &channel_parameters, + &justice_tx, + input_idx, + value, + &per_commitment_key, &self.onchain_tx_handler.secp_ctx, )?; - justice_tx.input[input_idx].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(sig)); + justice_tx.input[input_idx] + .witness + .push_ecdsa_signature(&BitcoinSignature::sighash_all(sig)); justice_tx.input[input_idx].witness.push(&[1u8]); justice_tx.input[input_idx].witness.push(revokeable_redeemscript.as_bytes()); Ok(justice_tx) @@ -3700,53 +4215,81 @@ impl ChannelMonitorImpl { /// /// Returns packages to claim the revoked output(s) and general information about the output that /// is to the counterparty in the commitment transaction. - fn check_spend_counterparty_transaction(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L) - -> (Vec, CommitmentTxCounterpartyOutputInfo) - where L::Target: Logger { + fn check_spend_counterparty_transaction( + &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L, + ) -> (Vec, CommitmentTxCounterpartyOutputInfo) + where + L::Target: Logger, + { // Most secp and related errors trying to create keys means we have no hope of constructing // a spend transaction...so we return no transactions to broadcast let mut claimable_outpoints = Vec::new(); let mut to_counterparty_output_info = None; let commitment_txid = tx.compute_txid(); //TODO: This is gonna be a performance bottleneck for watchtowers! - let per_commitment_option = self.funding.counterparty_claimable_outpoints.get(&commitment_txid); + let per_commitment_option = + self.funding.counterparty_claimable_outpoints.get(&commitment_txid); macro_rules! ignore_error { ( $thing : expr ) => { match $thing { Ok(a) => a, - Err(_) => return (claimable_outpoints, to_counterparty_output_info) + Err(_) => return (claimable_outpoints, to_counterparty_output_info), } }; } - let commitment_number = 0xffffffffffff - ((((tx.input[0].sequence.0 as u64 & 0xffffff) << 3*8) | (tx.lock_time.to_consensus_u32() as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor); + let commitment_number = 0xffffffffffff + - ((((tx.input[0].sequence.0 as u64 & 0xffffff) << 3 * 8) + | (tx.lock_time.to_consensus_u32() as u64 & 0xffffff)) + ^ self.commitment_transaction_number_obscure_factor); if commitment_number >= self.get_min_seen_secret() { let secret = self.get_secret(commitment_number).unwrap(); let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret)); - let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key); - let revocation_pubkey = RevocationKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.holder_revocation_basepoint, &per_commitment_point,); - let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key)); + let per_commitment_point = + PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key); + let revocation_pubkey = RevocationKey::from_basepoint( + &self.onchain_tx_handler.secp_ctx, + &self.holder_revocation_basepoint, + &per_commitment_point, + ); + let delayed_key = DelayedPaymentKey::from_basepoint( + &self.onchain_tx_handler.secp_ctx, + &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, + &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key), + ); - let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key); + let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript( + &revocation_pubkey, + self.counterparty_commitment_params.on_counterparty_tx_csv, + &delayed_key, + ); let revokeable_p2wsh = revokeable_redeemscript.to_p2wsh(); // First, process non-htlc outputs (to_holder & to_counterparty) for (idx, outp) in tx.output.iter().enumerate() { if outp.script_pubkey == revokeable_p2wsh { let revk_outp = RevokedOutput::build( - per_commitment_point, per_commitment_key, outp.value, - self.funding.channel_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx(), + per_commitment_point, + per_commitment_key, + outp.value, + self.funding + .channel_parameters + .channel_type_features + .supports_anchors_zero_fee_htlc_tx(), self.funding.channel_parameters.clone(), ); let justice_package = PackageTemplate::build_package( - commitment_txid, idx as u32, + commitment_txid, + idx as u32, PackageSolvingData::RevokedOutput(revk_outp), height + self.counterparty_commitment_params.on_counterparty_tx_csv as u32, ); claimable_outpoints.push(justice_package); - to_counterparty_output_info = - Some((idx.try_into().expect("Txn can't have more than 2^32 outputs"), outp.value)); + to_counterparty_output_info = Some(( + idx.try_into().expect("Txn can't have more than 2^32 outputs"), + outp.value, + )); } } @@ -3754,20 +4297,21 @@ impl ChannelMonitorImpl { if let Some(per_commitment_claimable_data) = per_commitment_option { for (htlc, _) in per_commitment_claimable_data { if let Some(transaction_output_index) = htlc.transaction_output_index { - if transaction_output_index as usize >= tx.output.len() || - tx.output[transaction_output_index as usize].value != htlc.to_bitcoin_amount() { + if transaction_output_index as usize >= tx.output.len() + || tx.output[transaction_output_index as usize].value + != htlc.to_bitcoin_amount() + { // per_commitment_data is corrupt or our commitment signing key leaked! return (claimable_outpoints, to_counterparty_output_info); } let revk_htlc_outp = RevokedHTLCOutput::build( - per_commitment_point, per_commitment_key, htlc.clone(), + per_commitment_point, + per_commitment_key, + htlc.clone(), self.funding.channel_parameters.clone(), ); - let counterparty_spendable_height = if htlc.offered { - htlc.cltv_expiry - } else { - height - }; + let counterparty_spendable_height = + if htlc.offered { htlc.cltv_expiry } else { height }; let justice_package = PackageTemplate::build_package( commitment_txid, transaction_output_index, @@ -3780,24 +4324,43 @@ impl ChannelMonitorImpl { } // Last, track onchain revoked commitment transaction and fail backward outgoing HTLCs as payment path is broken - if !claimable_outpoints.is_empty() || per_commitment_option.is_some() { // ie we're confident this is actually ours + if !claimable_outpoints.is_empty() || per_commitment_option.is_some() { + // ie we're confident this is actually ours // We're definitely a counterparty commitment transaction! log_error!(logger, "Got broadcast of revoked counterparty commitment transaction, going to generate general spend tx with {} inputs", claimable_outpoints.len()); - self.counterparty_commitment_txn_on_chain.insert(commitment_txid, commitment_number); + self.counterparty_commitment_txn_on_chain + .insert(commitment_txid, commitment_number); if let Some(per_commitment_claimable_data) = per_commitment_option { - fail_unbroadcast_htlcs!(self, "revoked_counterparty", commitment_txid, tx, height, - block_hash, per_commitment_claimable_data.iter().map(|(htlc, htlc_source)| - (htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref())) - ), logger); + fail_unbroadcast_htlcs!( + self, + "revoked_counterparty", + commitment_txid, + tx, + height, + block_hash, + per_commitment_claimable_data.iter().map(|(htlc, htlc_source)| ( + htlc, + htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()) + )), + logger + ); } else { // Our fuzzers aren't constrained by pesky things like valid signatures, so can // spend our funding output with a transaction which doesn't match our past // commitment transactions. Thus, we can only debug-assert here when not // fuzzing. debug_assert!(cfg!(fuzzing), "We should have per-commitment option for any recognized old commitment txn"); - fail_unbroadcast_htlcs!(self, "revoked counterparty", commitment_txid, tx, height, - block_hash, [].iter().map(|reference| *reference), logger); + fail_unbroadcast_htlcs!( + self, + "revoked counterparty", + commitment_txid, + tx, + height, + block_hash, + [].iter().map(|reference| *reference), + logger + ); } } } else if let Some(per_commitment_claimable_data) = per_commitment_option { @@ -3810,25 +4373,44 @@ impl ChannelMonitorImpl { // insert it here. self.counterparty_commitment_txn_on_chain.insert(commitment_txid, commitment_number); - log_info!(logger, "Got broadcast of non-revoked counterparty commitment transaction {}", commitment_txid); - fail_unbroadcast_htlcs!(self, "counterparty", commitment_txid, tx, height, block_hash, - per_commitment_claimable_data.iter().map(|(htlc, htlc_source)| - (htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref())) - ), logger); - let (htlc_claim_reqs, counterparty_output_info) = - self.get_counterparty_output_claim_info(commitment_number, commitment_txid, Some(tx), per_commitment_option); + log_info!( + logger, + "Got broadcast of non-revoked counterparty commitment transaction {}", + commitment_txid + ); + fail_unbroadcast_htlcs!( + self, + "counterparty", + commitment_txid, + tx, + height, + block_hash, + per_commitment_claimable_data.iter().map(|(htlc, htlc_source)| ( + htlc, + htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()) + )), + logger + ); + let (htlc_claim_reqs, counterparty_output_info) = self + .get_counterparty_output_claim_info( + commitment_number, + commitment_txid, + Some(tx), + per_commitment_option, + ); to_counterparty_output_info = counterparty_output_info; for req in htlc_claim_reqs { claimable_outpoints.push(req); } - } (claimable_outpoints, to_counterparty_output_info) } /// Returns the HTLC claim package templates and the counterparty output info - fn get_counterparty_output_claim_info(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>, per_commitment_option: Option<&Vec<(HTLCOutputInCommitment, Option>)>>) - -> (Vec, CommitmentTxCounterpartyOutputInfo) { + fn get_counterparty_output_claim_info( + &self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>, + per_commitment_option: Option<&Vec<(HTLCOutputInCommitment, Option>)>>, + ) -> (Vec, CommitmentTxCounterpartyOutputInfo) { let mut claimable_outpoints = Vec::new(); let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None; @@ -3856,13 +4438,23 @@ impl ChannelMonitorImpl { if let Some(transaction) = tx { let revocation_pubkey = RevocationKey::from_basepoint( - &self.onchain_tx_handler.secp_ctx, &self.holder_revocation_basepoint, &per_commitment_point); + &self.onchain_tx_handler.secp_ctx, + &self.holder_revocation_basepoint, + &per_commitment_point, + ); - let delayed_key = DelayedPaymentKey::from_basepoint(&self.onchain_tx_handler.secp_ctx, &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, &per_commitment_point); + let delayed_key = DelayedPaymentKey::from_basepoint( + &self.onchain_tx_handler.secp_ctx, + &self.counterparty_commitment_params.counterparty_delayed_payment_base_key, + &per_commitment_point, + ); - let revokeable_p2wsh = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, + let revokeable_p2wsh = chan_utils::get_revokeable_redeemscript( + &revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, - &delayed_key).to_p2wsh(); + &delayed_key, + ) + .to_p2wsh(); for (idx, outp) in transaction.output.iter().enumerate() { if outp.script_pubkey == revokeable_p2wsh { to_counterparty_output_info = @@ -3871,33 +4463,51 @@ impl ChannelMonitorImpl { } } - for &(ref htlc, _) in per_commitment_claimable_data.iter() { + for &(ref htlc, _) in per_commitment_claimable_data.iter() { if let Some(transaction_output_index) = htlc.transaction_output_index { if let Some(transaction) = tx { - if transaction_output_index as usize >= transaction.output.len() || - transaction.output[transaction_output_index as usize].value != htlc.to_bitcoin_amount() { - // per_commitment_data is corrupt or our commitment signing key leaked! - return (claimable_outpoints, to_counterparty_output_info); - } + if transaction_output_index as usize >= transaction.output.len() + || transaction.output[transaction_output_index as usize].value + != htlc.to_bitcoin_amount() + { + // per_commitment_data is corrupt or our commitment signing key leaked! + return (claimable_outpoints, to_counterparty_output_info); + } } - let preimage = if htlc.offered { if let Some((p, _)) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None }; + let preimage = if htlc.offered { + if let Some((p, _)) = self.payment_preimages.get(&htlc.payment_hash) { + Some(*p) + } else { + None + } + } else { + None + }; if preimage.is_some() || !htlc.offered { let counterparty_htlc_outp = if htlc.offered { PackageSolvingData::CounterpartyOfferedHTLCOutput( CounterpartyOfferedHTLCOutput::build( - *per_commitment_point, preimage.unwrap(), htlc.clone(), + *per_commitment_point, + preimage.unwrap(), + htlc.clone(), self.funding.channel_parameters.clone(), - ) + ), ) } else { PackageSolvingData::CounterpartyReceivedHTLCOutput( CounterpartyReceivedHTLCOutput::build( - *per_commitment_point, htlc.clone(), + *per_commitment_point, + htlc.clone(), self.funding.channel_parameters.clone(), - ) + ), ) }; - let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, counterparty_htlc_outp, htlc.cltv_expiry); + let counterparty_package = PackageTemplate::build_package( + commitment_txid, + transaction_output_index, + counterparty_htlc_outp, + htlc.cltv_expiry, + ); claimable_outpoints.push(counterparty_package); } } @@ -3908,14 +4518,23 @@ impl ChannelMonitorImpl { /// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key fn check_spend_counterparty_htlc( - &mut self, tx: &Transaction, commitment_number: u64, commitment_txid: &Txid, height: u32, logger: &L - ) -> (Vec, Option) where L::Target: Logger { - let secret = if let Some(secret) = self.get_secret(commitment_number) { secret } else { return (Vec::new(), None); }; + &mut self, tx: &Transaction, commitment_number: u64, commitment_txid: &Txid, height: u32, + logger: &L, + ) -> (Vec, Option) + where + L::Target: Logger, + { + let secret = if let Some(secret) = self.get_secret(commitment_number) { + secret + } else { + return (Vec::new(), None); + }; let per_commitment_key = match SecretKey::from_slice(&secret) { Ok(key) => key, - Err(_) => return (Vec::new(), None) + Err(_) => return (Vec::new(), None), }; - let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key); + let per_commitment_point = + PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key); let htlc_txid = tx.compute_txid(); let mut claimable_outpoints = vec![]; @@ -3931,14 +4550,27 @@ impl ChannelMonitorImpl { // and claim those which spend the commitment transaction, have a witness of 5 elements, and // have a corresponding output at the same index within the transaction. for (idx, input) in tx.input.iter().enumerate() { - if input.previous_output.txid == *commitment_txid && input.witness.len() == 5 && tx.output.get(idx).is_some() { - log_error!(logger, "Got broadcast of revoked counterparty HTLC transaction, spending {}:{}", htlc_txid, idx); + if input.previous_output.txid == *commitment_txid + && input.witness.len() == 5 + && tx.output.get(idx).is_some() + { + log_error!( + logger, + "Got broadcast of revoked counterparty HTLC transaction, spending {}:{}", + htlc_txid, + idx + ); let revk_outp = RevokedOutput::build( - per_commitment_point, per_commitment_key, tx.output[idx].value, false, + per_commitment_point, + per_commitment_key, + tx.output[idx].value, + false, self.funding.channel_parameters.clone(), ); let justice_package = PackageTemplate::build_package( - htlc_txid, idx as u32, PackageSolvingData::RevokedOutput(revk_outp), + htlc_txid, + idx as u32, + PackageSolvingData::RevokedOutput(revk_outp), height + self.counterparty_commitment_params.on_counterparty_tx_csv as u32, ); claimable_outpoints.push(justice_package); @@ -3957,8 +4589,13 @@ impl ChannelMonitorImpl { let tx = holder_tx.trust(); let mut htlcs = Vec::with_capacity(holder_tx.nondust_htlcs().len()); debug_assert_eq!(holder_tx.nondust_htlcs().len(), holder_tx.counterparty_htlc_sigs.len()); - for (htlc, counterparty_sig) in holder_tx.nondust_htlcs().iter().zip(holder_tx.counterparty_htlc_sigs.iter()) { - assert!(htlc.transaction_output_index.is_some(), "Expected transaction output index for non-dust HTLC"); + for (htlc, counterparty_sig) in + holder_tx.nondust_htlcs().iter().zip(holder_tx.counterparty_htlc_sigs.iter()) + { + assert!( + htlc.transaction_output_index.is_some(), + "Expected transaction output index for non-dust HTLC" + ); let preimage = if htlc.offered { None @@ -3998,23 +4635,32 @@ impl ChannelMonitorImpl { let tx = holder_tx.trust(); let keys = tx.keys(); let redeem_script = chan_utils::get_revokeable_redeemscript( - &keys.revocation_key, self.on_holder_tx_csv, &keys.broadcaster_delayed_payment_key, + &keys.revocation_key, + self.on_holder_tx_csv, + &keys.broadcaster_delayed_payment_key, ); let broadcasted_holder_revokable_script = Some(( - redeem_script.to_p2wsh(), holder_tx.per_commitment_point(), keys.revocation_key.clone(), + redeem_script.to_p2wsh(), + holder_tx.per_commitment_point(), + keys.revocation_key.clone(), )); - let claim_requests = self.get_broadcasted_holder_htlc_descriptors(holder_tx).into_iter() + let claim_requests = self + .get_broadcasted_holder_htlc_descriptors(holder_tx) + .into_iter() .map(|htlc_descriptor| { let counterparty_spendable_height = if htlc_descriptor.htlc.offered { conf_height } else { htlc_descriptor.htlc.cltv_expiry }; - let transaction_output_index = htlc_descriptor.htlc.transaction_output_index + let transaction_output_index = htlc_descriptor + .htlc + .transaction_output_index .expect("Expected transaction output index for non-dust HTLC"); PackageTemplate::build_package( - tx.txid(), transaction_output_index, + tx.txid(), + transaction_output_index, PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build(htlc_descriptor)), counterparty_spendable_height, ) @@ -4025,14 +4671,17 @@ impl ChannelMonitorImpl { } // Returns holder HTLC outputs to watch and react to in case of spending. - fn get_broadcasted_holder_watch_outputs(&self, holder_tx: &HolderCommitmentTransaction) -> Vec<(u32, TxOut)> { + fn get_broadcasted_holder_watch_outputs( + &self, holder_tx: &HolderCommitmentTransaction, + ) -> Vec<(u32, TxOut)> { let mut watch_outputs = Vec::with_capacity(holder_tx.nondust_htlcs().len()); let tx = holder_tx.trust(); for htlc in holder_tx.nondust_htlcs() { if let Some(transaction_output_index) = htlc.transaction_output_index { watch_outputs.push(( transaction_output_index, - tx.built_transaction().transaction.output[transaction_output_index as usize].clone(), + tx.built_transaction().transaction.output[transaction_output_index as usize] + .clone(), )); } else { debug_assert!(false, "Expected transaction output index for non-dust HTLC"); @@ -4045,7 +4694,12 @@ impl ChannelMonitorImpl { /// revoked using data in holder_claimable_outpoints. /// Should not be used if check_spend_revoked_transaction succeeds. /// Returns None unless the transaction is definitely one of our commitment transactions. - fn check_spend_holder_transaction(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L) -> Option<(Vec, TransactionOutputs)> where L::Target: Logger { + fn check_spend_holder_transaction( + &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L, + ) -> Option<(Vec, TransactionOutputs)> + where + L::Target: Logger, + { let commitment_txid = tx.compute_txid(); let mut claim_requests = Vec::new(); let mut watch_outputs = Vec::new(); @@ -4055,7 +4709,7 @@ impl ChannelMonitorImpl { claim_requests = $updates.0; self.broadcasted_holder_revokable_script = $updates.1; watch_outputs.append(&mut $to_watch); - } + }; } // HTLCs set may differ between last and previous holder commitment txn, in case of one them hitting chain, ensure we cancel all HTLCs backward @@ -4064,12 +4718,20 @@ impl ChannelMonitorImpl { if self.funding.current_holder_commitment.tx.trust().txid() == commitment_txid { is_holder_tx = true; log_info!(logger, "Got broadcast of latest holder commitment tx {}, searching for available HTLCs to claim", commitment_txid); - let res = self.get_broadcasted_holder_claims(&self.funding.current_holder_commitment.tx, height); - let mut to_watch = self.get_broadcasted_holder_watch_outputs(&self.funding.current_holder_commitment.tx); + let res = self + .get_broadcasted_holder_claims(&self.funding.current_holder_commitment.tx, height); + let mut to_watch = self + .get_broadcasted_holder_watch_outputs(&self.funding.current_holder_commitment.tx); append_onchain_update!(res, to_watch); fail_unbroadcast_htlcs!( - self, "latest holder", commitment_txid, tx, height, block_hash, - self.funding.current_holder_commitment.htlcs_with_sources(), logger + self, + "latest holder", + commitment_txid, + tx, + height, + block_hash, + self.funding.current_holder_commitment.htlcs_with_sources(), + logger ); } else if let &Some(ref holder_commitment) = &self.funding.prev_holder_commitment { if holder_commitment.tx.trust().txid() == commitment_txid { @@ -4079,8 +4741,14 @@ impl ChannelMonitorImpl { let mut to_watch = self.get_broadcasted_holder_watch_outputs(&holder_commitment.tx); append_onchain_update!(res, to_watch); fail_unbroadcast_htlcs!( - self, "previous holder", commitment_txid, tx, height, block_hash, - holder_commitment.htlcs_with_sources(), logger + self, + "previous holder", + commitment_txid, + tx, + height, + block_hash, + holder_commitment.htlcs_with_sources(), + logger ); } } @@ -4095,8 +4763,10 @@ impl ChannelMonitorImpl { /// Cancels any existing pending claims for a commitment that previously confirmed and has now /// been replaced by another. pub fn cancel_prev_commitment_claims( - &mut self, logger: &L, confirmed_commitment_txid: &Txid - ) where L::Target: Logger { + &mut self, logger: &L, confirmed_commitment_txid: &Txid, + ) where + L::Target: Logger, + { for (counterparty_commitment_txid, _) in &self.counterparty_commitment_txn_on_chain { // Cancel any pending claims for counterparty commitments we've seen confirm. if counterparty_commitment_txid == confirmed_commitment_txid { @@ -4104,9 +4774,17 @@ impl ChannelMonitorImpl { } // If we have generated claims for counterparty_commitment_txid earlier, we can rely on always // having claim related htlcs for counterparty_commitment_txid in counterparty_claimable_outpoints. - for (htlc, _) in self.funding.counterparty_claimable_outpoints.get(counterparty_commitment_txid).unwrap_or(&vec![]) { - log_trace!(logger, "Canceling claims for previously confirmed counterparty commitment {}", - counterparty_commitment_txid); + for (htlc, _) in self + .funding + .counterparty_claimable_outpoints + .get(counterparty_commitment_txid) + .unwrap_or(&vec![]) + { + log_trace!( + logger, + "Canceling claims for previously confirmed counterparty commitment {}", + counterparty_commitment_txid + ); let mut outpoint = BitcoinOutPoint { txid: *counterparty_commitment_txid, vout: 0 }; if let Some(vout) = htlc.transaction_output_index { outpoint.vout = vout; @@ -4119,7 +4797,11 @@ impl ChannelMonitorImpl { // waiting for confirmation). if self.funding.current_holder_commitment.tx.trust().txid() != *confirmed_commitment_txid { let txid = self.funding.current_holder_commitment.tx.trust().txid(); - log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}", txid); + log_trace!( + logger, + "Canceling claims for previously broadcast holder commitment {}", + txid + ); let mut outpoint = BitcoinOutPoint { txid, vout: 0 }; for htlc in self.funding.current_holder_commitment.tx.nondust_htlcs() { if let Some(vout) = htlc.transaction_output_index { @@ -4133,7 +4815,11 @@ impl ChannelMonitorImpl { if let Some(prev_holder_commitment) = &self.funding.prev_holder_commitment { let txid = prev_holder_commitment.tx.trust().txid(); if txid != *confirmed_commitment_txid { - log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}", txid); + log_trace!( + logger, + "Canceling claims for previously broadcast holder commitment {}", + txid + ); let mut outpoint = BitcoinOutPoint { txid, vout: 0 }; for htlc in prev_holder_commitment.tx.nondust_htlcs() { if let Some(vout) = htlc.transaction_output_index { @@ -4150,15 +4836,26 @@ impl ChannelMonitorImpl { #[cfg(any(test, feature = "_test_utils", feature = "unsafe_revoked_tx_signing"))] /// Note that this includes possibly-locktimed-in-the-future transactions! fn unsafe_get_latest_holder_commitment_txn( - &mut self, logger: &WithChannelMonitor - ) -> Vec where L::Target: Logger { + &mut self, logger: &WithChannelMonitor, + ) -> Vec + where + L::Target: Logger, + { log_debug!(logger, "Getting signed copy of latest holder commitment transaction!"); let commitment_tx = { - let sig = self.onchain_tx_handler.signer.unsafe_sign_holder_commitment( - &self.funding.channel_parameters, &self.funding.current_holder_commitment.tx, - &self.onchain_tx_handler.secp_ctx, - ).expect("sign holder commitment"); - self.funding.current_holder_commitment.tx.add_holder_sig(&self.funding.redeem_script, sig) + let sig = self + .onchain_tx_handler + .signer + .unsafe_sign_holder_commitment( + &self.funding.channel_parameters, + &self.funding.current_holder_commitment.tx, + &self.onchain_tx_handler.secp_ctx, + ) + .expect("sign holder commitment"); + self.funding + .current_holder_commitment + .tx + .add_holder_sig(&self.funding.redeem_script, sig) }; let mut holder_transactions = vec![commitment_tx]; // When anchor outputs are present, the HTLC transactions are only final once the commitment @@ -4171,11 +4868,14 @@ impl ChannelMonitorImpl { .into_iter() .for_each(|htlc_descriptor| { let txid = self.funding.current_holder_commitment.tx.trust().txid(); - let vout = htlc_descriptor.htlc.transaction_output_index + let vout = htlc_descriptor + .htlc + .transaction_output_index .expect("Expected transaction output index for non-dust HTLC"); let htlc_output = HolderHTLCOutput::build(htlc_descriptor); if let Some(htlc_tx) = htlc_output.get_maybe_signed_htlc_tx( - &mut self.onchain_tx_handler, &::bitcoin::OutPoint { txid, vout }, + &mut self.onchain_tx_handler, + &::bitcoin::OutPoint { txid, vout }, ) { if htlc_tx.is_fully_signed() { holder_transactions.push(htlc_tx.0); @@ -4190,24 +4890,28 @@ impl ChannelMonitorImpl { &mut self, header: &Header, txdata: &TransactionData, height: u32, broadcaster: B, fee_estimator: F, logger: &WithChannelMonitor, ) -> Vec - where B::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, { let block_hash = header.block_hash(); self.best_block = BestBlock::new(block_hash, height); let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); - self.transactions_confirmed(header, txdata, height, broadcaster, &bounded_fee_estimator, logger) + self.transactions_confirmed( + header, + txdata, + height, + broadcaster, + &bounded_fee_estimator, + logger, + ) } fn best_block_updated( - &mut self, - header: &Header, - height: u32, - broadcaster: B, - fee_estimator: &LowerBoundedFeeEstimator, - logger: &WithChannelMonitor, + &mut self, header: &Header, height: u32, broadcaster: B, + fee_estimator: &LowerBoundedFeeEstimator, logger: &WithChannelMonitor, ) -> Vec where B::Target: BroadcasterInterface, @@ -4219,27 +4923,43 @@ impl ChannelMonitorImpl { if height > self.best_block.height { self.best_block = BestBlock::new(block_hash, height); log_trace!(logger, "Connecting new block {} at height {}", block_hash, height); - self.block_confirmed(height, block_hash, vec![], vec![], vec![], &broadcaster, &fee_estimator, logger) + self.block_confirmed( + height, + block_hash, + vec![], + vec![], + vec![], + &broadcaster, + &fee_estimator, + logger, + ) } else if block_hash != self.best_block.block_hash { self.best_block = BestBlock::new(block_hash, height); - log_trace!(logger, "Best block re-orged, replaced with new block {} at height {}", block_hash, height); + log_trace!( + logger, + "Best block re-orged, replaced with new block {} at height {}", + block_hash, + height + ); self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.height <= height); let conf_target = self.closure_conf_target(); self.onchain_tx_handler.block_disconnected( - height + 1, broadcaster, conf_target, &self.destination_script, fee_estimator, logger, + height + 1, + broadcaster, + conf_target, + &self.destination_script, + fee_estimator, + logger, ); Vec::new() - } else { Vec::new() } + } else { + Vec::new() + } } fn transactions_confirmed( - &mut self, - header: &Header, - txdata: &TransactionData, - height: u32, - broadcaster: B, - fee_estimator: &LowerBoundedFeeEstimator, - logger: &WithChannelMonitor, + &mut self, header: &Header, txdata: &TransactionData, height: u32, broadcaster: B, + fee_estimator: &LowerBoundedFeeEstimator, logger: &WithChannelMonitor, ) -> Vec where B::Target: BroadcasterInterface, @@ -4250,9 +4970,13 @@ impl ChannelMonitorImpl { for tx in &txn_matched { let mut output_val = Amount::ZERO; for out in tx.output.iter() { - if out.value > Amount::MAX_MONEY { panic!("Value-overflowing transaction provided to block connected"); } + if out.value > Amount::MAX_MONEY { + panic!("Value-overflowing transaction provided to block connected"); + } output_val += out.value; - if output_val > Amount::MAX_MONEY { panic!("Value-overflowing transaction provided to block connected"); } + if output_val > Amount::MAX_MONEY { + panic!("Value-overflowing transaction provided to block connected"); + } } } @@ -4262,7 +4986,7 @@ impl ChannelMonitorImpl { let mut claimable_outpoints = Vec::new(); 'tx_iter: for tx in &txn_matched { let txid = tx.compute_txid(); - log_trace!(logger, "Transaction {} confirmed in block {}", txid , block_hash); + log_trace!(logger, "Transaction {} confirmed in block {}", txid, block_hash); // If a transaction has already been confirmed, ensure we don't bother processing it duplicatively. if Some(txid) == self.funding_spend_confirmed { log_debug!(logger, "Skipping redundant processing of funding-spend tx {} as it was previously confirmed", txid); @@ -4299,14 +5023,24 @@ impl ChannelMonitorImpl { // way to filter out any potential non-matching txn for lazy filters. let prevout = &tx.input[0].previous_output; let funding_outpoint = self.get_funding_txo(); - if prevout.txid == funding_outpoint.txid && prevout.vout == funding_outpoint.index as u32 { + if prevout.txid == funding_outpoint.txid + && prevout.vout == funding_outpoint.index as u32 + { let mut balance_spendable_csv = None; - log_info!(logger, "Channel {} closed by funding output spend in txid {}.", - &self.channel_id(), txid); + log_info!( + logger, + "Channel {} closed by funding output spend in txid {}.", + &self.channel_id(), + txid + ); self.funding_spend_seen = true; let mut commitment_tx_to_counterparty_output = None; - if (tx.input[0].sequence.0 >> 8*3) as u8 == 0x80 && (tx.lock_time.to_consensus_u32() >> 8*3) as u8 == 0x20 { - if let Some((mut new_outpoints, new_outputs)) = self.check_spend_holder_transaction(&tx, height, &block_hash, &logger) { + if (tx.input[0].sequence.0 >> 8 * 3) as u8 == 0x80 + && (tx.lock_time.to_consensus_u32() >> 8 * 3) as u8 == 0x20 + { + if let Some((mut new_outpoints, new_outputs)) = + self.check_spend_holder_transaction(&tx, height, &block_hash, &logger) + { if !new_outputs.1.is_empty() { watch_outputs.push(new_outputs); } @@ -4320,8 +5054,13 @@ impl ChannelMonitorImpl { } watch_outputs.push((txid, new_watch_outputs)); - let (mut new_outpoints, counterparty_output_idx_sats) = - self.check_spend_counterparty_transaction(&tx, height, &block_hash, &logger); + let (mut new_outpoints, counterparty_output_idx_sats) = self + .check_spend_counterparty_transaction( + &tx, + height, + &block_hash, + &logger, + ); commitment_tx_to_counterparty_output = counterparty_output_idx_sats; claimable_outpoints.append(&mut new_outpoints); @@ -4349,10 +5088,17 @@ impl ChannelMonitorImpl { // other ways which can have more than one output. for tx_input in &tx.input { let commitment_txid = tx_input.previous_output.txid; - if let Some(&commitment_number) = self.counterparty_commitment_txn_on_chain.get(&commitment_txid) { - let (mut new_outpoints, new_outputs_option) = self.check_spend_counterparty_htlc( - &tx, commitment_number, &commitment_txid, height, &logger - ); + if let Some(&commitment_number) = + self.counterparty_commitment_txn_on_chain.get(&commitment_txid) + { + let (mut new_outpoints, new_outputs_option) = self + .check_spend_counterparty_htlc( + &tx, + commitment_number, + &commitment_txid, + height, + &logger, + ); claimable_outpoints.append(&mut new_outpoints); if let Some(new_outputs) = new_outputs_option { watch_outputs.push(new_outputs); @@ -4374,7 +5120,16 @@ impl ChannelMonitorImpl { self.best_block = BestBlock::new(block_hash, height); } - self.block_confirmed(height, block_hash, txn_matched, watch_outputs, claimable_outpoints, &broadcaster, &fee_estimator, logger) + self.block_confirmed( + height, + block_hash, + txn_matched, + watch_outputs, + claimable_outpoints, + &broadcaster, + &fee_estimator, + logger, + ) } /// Update state for new block(s)/transaction(s) confirmed. Note that the caller must update @@ -4386,14 +5141,9 @@ impl ChannelMonitorImpl { /// `conf_height` should be set to the height at which any new transaction(s)/block(s) were /// confirmed at, even if it is not the current best height. fn block_confirmed( - &mut self, - conf_height: u32, - conf_hash: BlockHash, - txn_matched: Vec<&Transaction>, - mut watch_outputs: Vec, - mut claimable_outpoints: Vec, - broadcaster: &B, - fee_estimator: &LowerBoundedFeeEstimator, + &mut self, conf_height: u32, conf_hash: BlockHash, txn_matched: Vec<&Transaction>, + mut watch_outputs: Vec, mut claimable_outpoints: Vec, + broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &WithChannelMonitor, ) -> Vec where @@ -4401,25 +5151,36 @@ impl ChannelMonitorImpl { F::Target: FeeEstimator, L::Target: Logger, { - log_trace!(logger, "Processing {} matched transactions for block at height {}.", txn_matched.len(), conf_height); + log_trace!( + logger, + "Processing {} matched transactions for block at height {}.", + txn_matched.len(), + conf_height + ); debug_assert!(self.best_block.height >= conf_height); let should_broadcast = self.should_broadcast_holder_commitment_txn(logger); if should_broadcast { - let (mut new_outpoints, mut new_outputs) = self.generate_claimable_outpoints_and_watch_outputs(ClosureReason::HTLCsTimedOut); + let (mut new_outpoints, mut new_outputs) = + self.generate_claimable_outpoints_and_watch_outputs(ClosureReason::HTLCsTimedOut); claimable_outpoints.append(&mut new_outpoints); watch_outputs.append(&mut new_outputs); } // Find which on-chain events have reached their confirmation threshold. - let (onchain_events_reaching_threshold_conf, onchain_events_awaiting_threshold_conf): (Vec<_>, Vec<_>) = - self.onchain_events_awaiting_threshold_conf.drain(..).partition( - |entry| entry.has_reached_confirmation_threshold(&self.best_block)); + let (onchain_events_reaching_threshold_conf, onchain_events_awaiting_threshold_conf): ( + Vec<_>, + Vec<_>, + ) = self + .onchain_events_awaiting_threshold_conf + .drain(..) + .partition(|entry| entry.has_reached_confirmation_threshold(&self.best_block)); self.onchain_events_awaiting_threshold_conf = onchain_events_awaiting_threshold_conf; // Used to check for duplicate HTLC resolutions. #[cfg(debug_assertions)] - let unmatured_htlcs: Vec<_> = self.onchain_events_awaiting_threshold_conf + let unmatured_htlcs: Vec<_> = self + .onchain_events_awaiting_threshold_conf .iter() .filter_map(|entry| match &entry.event { OnchainEvent::HTLCUpdate { source, .. } => Some(source), @@ -4432,7 +5193,12 @@ impl ChannelMonitorImpl { // Produce actionable events from on-chain events having reached their threshold. for entry in onchain_events_reaching_threshold_conf { match entry.event { - OnchainEvent::HTLCUpdate { source, payment_hash, htlc_value_satoshis, commitment_tx_output_idx } => { + OnchainEvent::HTLCUpdate { + source, + payment_hash, + htlc_value_satoshis, + commitment_tx_output_idx, + } => { // Check for duplicate HTLC resolutions. #[cfg(debug_assertions)] { @@ -4445,7 +5211,8 @@ impl ChannelMonitorImpl { !matured_htlcs.contains(&source), "A matured HTLC transaction conflicts with a maturing one; failed to \ call either transaction_unconfirmed for the conflicting transaction \ - or block_disconnected for a block containing it."); + or block_disconnected for a block containing it." + ); matured_htlcs.push(source.clone()); } @@ -4465,14 +5232,20 @@ impl ChannelMonitorImpl { }); }, OnchainEvent::MaturingOutput { descriptor } => { - log_debug!(logger, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor)); + log_debug!( + logger, + "Descriptor {} has got enough confirmations to be passed upstream", + log_spendable!(descriptor) + ); self.pending_events.push(Event::SpendableOutputs { outputs: vec![descriptor], channel_id: Some(self.channel_id()), }); self.spendable_txids_confirmed.push(entry.txid); }, - OnchainEvent::HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => { + OnchainEvent::HTLCSpendConfirmation { + commitment_tx_output_idx, preimage, .. + } => { self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC { commitment_tx_output_idx: Some(commitment_tx_output_idx), resolving_txid: Some(entry.txid), @@ -4480,9 +5253,13 @@ impl ChannelMonitorImpl { payment_preimage: preimage, }); }, - OnchainEvent::FundingSpendConfirmation { commitment_tx_to_counterparty_output, .. } => { + OnchainEvent::FundingSpendConfirmation { + commitment_tx_to_counterparty_output, + .. + } => { self.funding_spend_confirmed = Some(entry.txid); - self.confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output; + self.confirmed_commitment_tx_counterparty_output = + commitment_tx_to_counterparty_output; }, } } @@ -4495,17 +5272,43 @@ impl ChannelMonitorImpl { // HTLC, so we might as well fail it back instead of having our counterparty force-close // the inbound channel. let current_holder_htlcs = self.funding.current_holder_commitment.htlcs_with_sources(); - let current_counterparty_htlcs = if let Some(txid) = self.funding.current_counterparty_commitment_txid { - if let Some(htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(&txid) { - Some(htlc_outputs.iter().map(|&(ref a, ref b)| (a, b.as_ref().map(|boxed| &**boxed)))) - } else { None } - } else { None }.into_iter().flatten(); - - let prev_counterparty_htlcs = if let Some(txid) = self.funding.prev_counterparty_commitment_txid { - if let Some(htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(&txid) { - Some(htlc_outputs.iter().map(|&(ref a, ref b)| (a, b.as_ref().map(|boxed| &**boxed)))) - } else { None } - } else { None }.into_iter().flatten(); + let current_counterparty_htlcs = if let Some(txid) = + self.funding.current_counterparty_commitment_txid + { + if let Some(htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(&txid) + { + Some( + htlc_outputs + .iter() + .map(|&(ref a, ref b)| (a, b.as_ref().map(|boxed| &**boxed))), + ) + } else { + None + } + } else { + None + } + .into_iter() + .flatten(); + + let prev_counterparty_htlcs = if let Some(txid) = + self.funding.prev_counterparty_commitment_txid + { + if let Some(htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(&txid) + { + Some( + htlc_outputs + .iter() + .map(|&(ref a, ref b)| (a, b.as_ref().map(|boxed| &**boxed))), + ) + } else { + None + } + } else { + None + } + .into_iter() + .flatten(); let htlcs = current_holder_htlcs .chain(current_counterparty_htlcs) @@ -4526,10 +5329,13 @@ impl ChannelMonitorImpl { if inbound_htlc_expiry > max_expiry_height { continue; } - let duplicate_event = self.pending_monitor_events.iter().any( - |update| if let &MonitorEvent::HTLCEvent(ref upd) = update { + let duplicate_event = self.pending_monitor_events.iter().any(|update| { + if let &MonitorEvent::HTLCEvent(ref upd) = update { upd.source == *source - } else { false }); + } else { + false + } + }); if duplicate_event { continue; } @@ -4537,9 +5343,14 @@ impl ChannelMonitorImpl { continue; } if !duplicate_event { - log_error!(logger, "Failing back HTLC {} upstream to preserve the \ + log_error!( + logger, + "Failing back HTLC {} upstream to preserve the \ channel as the forward HTLC hasn't resolved and our backward HTLC \ - expires soon at {}", log_bytes!(htlc.payment_hash.0), inbound_htlc_expiry); + expires soon at {}", + log_bytes!(htlc.payment_hash.0), + inbound_htlc_expiry + ); self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate { source: source.clone(), payment_preimage: None, @@ -4552,12 +5363,25 @@ impl ChannelMonitorImpl { let conf_target = self.closure_conf_target(); self.onchain_tx_handler.update_claims_view_from_requests( - claimable_outpoints, conf_height, self.best_block.height, broadcaster, conf_target, - &self.destination_script, fee_estimator, logger, + claimable_outpoints, + conf_height, + self.best_block.height, + broadcaster, + conf_target, + &self.destination_script, + fee_estimator, + logger, ); self.onchain_tx_handler.update_claims_view_from_matched_txn( - &txn_matched, conf_height, conf_hash, self.best_block.height, broadcaster, conf_target, - &self.destination_script, fee_estimator, logger, + &txn_matched, + conf_height, + conf_hash, + self.best_block.height, + broadcaster, + conf_target, + &self.destination_script, + fee_estimator, + logger, ); // Determine new outputs to watch by comparing against previously known outputs to watch, @@ -4575,7 +5399,10 @@ impl ChannelMonitorImpl { if let Some(outputs) = self.get_outputs_to_watch().get(&tx.compute_txid()) { for idx_and_script in outputs.iter() { assert!((idx_and_script.0 as usize) < tx.output.len()); - assert_eq!(tx.output[idx_and_script.0 as usize].script_pubkey, idx_and_script.1); + assert_eq!( + tx.output[idx_and_script.0 as usize].script_pubkey, + idx_and_script.1 + ); } } } @@ -4584,8 +5411,10 @@ impl ChannelMonitorImpl { } fn block_disconnected( - &mut self, header: &Header, height: u32, broadcaster: B, fee_estimator: F, logger: &WithChannelMonitor - ) where B::Target: BroadcasterInterface, + &mut self, header: &Header, height: u32, broadcaster: B, fee_estimator: F, + logger: &WithChannelMonitor, + ) where + B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, { @@ -4599,17 +5428,19 @@ impl ChannelMonitorImpl { let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); let conf_target = self.closure_conf_target(); self.onchain_tx_handler.block_disconnected( - height, broadcaster, conf_target, &self.destination_script, &bounded_fee_estimator, logger + height, + broadcaster, + conf_target, + &self.destination_script, + &bounded_fee_estimator, + logger, ); self.best_block = BestBlock::new(header.prev_blockhash, height - 1); } fn transaction_unconfirmed( - &mut self, - txid: &Txid, - broadcaster: B, - fee_estimator: &LowerBoundedFeeEstimator, + &mut self, txid: &Txid, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator, logger: &WithChannelMonitor, ) where B::Target: BroadcasterInterface, @@ -4625,18 +5456,35 @@ impl ChannelMonitorImpl { } if let Some(removed_height) = removed_height { - log_info!(logger, "transaction_unconfirmed of txid {} implies height {} was reorg'd out", txid, removed_height); - self.onchain_events_awaiting_threshold_conf.retain(|ref entry| if entry.height >= removed_height { - log_info!(logger, "Transaction {} reorg'd out", entry.txid); - false - } else { true }); + log_info!( + logger, + "transaction_unconfirmed of txid {} implies height {} was reorg'd out", + txid, + removed_height + ); + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| { + if entry.height >= removed_height { + log_info!(logger, "Transaction {} reorg'd out", entry.txid); + false + } else { + true + } + }); } - debug_assert!(!self.onchain_events_awaiting_threshold_conf.iter().any(|ref entry| entry.txid == *txid)); + debug_assert!(!self + .onchain_events_awaiting_threshold_conf + .iter() + .any(|ref entry| entry.txid == *txid)); let conf_target = self.closure_conf_target(); self.onchain_tx_handler.transaction_unconfirmed( - txid, broadcaster, conf_target, &self.destination_script, fee_estimator, logger + txid, + broadcaster, + conf_target, + &self.destination_script, + fee_estimator, + logger, ); } @@ -4644,19 +5492,25 @@ impl ChannelMonitorImpl { /// transactions thereof. fn filter_block<'a>(&self, txdata: &TransactionData<'a>) -> Vec<&'a Transaction> { let mut matched_txn = new_hash_set(); - txdata.iter().filter(|&&(_, tx)| { - let mut matches = self.spends_watched_output(tx); - for input in tx.input.iter() { - if matches { break; } - if matched_txn.contains(&input.previous_output.txid) { - matches = true; + txdata + .iter() + .filter(|&&(_, tx)| { + let mut matches = self.spends_watched_output(tx); + for input in tx.input.iter() { + if matches { + break; + } + if matched_txn.contains(&input.previous_output.txid) { + matches = true; + } } - } - if matches { - matched_txn.insert(tx.compute_txid()); - } - matches - }).map(|(_, tx)| *tx).collect() + if matches { + matched_txn.insert(tx.compute_txid()); + } + matches + }) + .map(|(_, tx)| *tx) + .collect() } /// Checks if a given transaction spends any watched outputs. @@ -4671,17 +5525,41 @@ impl ChannelMonitorImpl { // appears to be spending the correct type (ie that the match would // actually succeed in BIP 158/159-style filters). if _script_pubkey.is_p2wsh() { - if input.witness.last().unwrap().to_vec() == deliberately_bogus_accepted_htlc_witness_program() { + if input.witness.last().unwrap().to_vec() + == deliberately_bogus_accepted_htlc_witness_program() + { // In at least one test we use a deliberately bogus witness // script which hit an old panic. Thus, we check for that here // and avoid the assert if its the expected bogus script. return true; } - assert_eq!(&bitcoin::Address::p2wsh(&ScriptBuf::from(input.witness.last().unwrap().to_vec()), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey); + assert_eq!( + &bitcoin::Address::p2wsh( + &ScriptBuf::from(input.witness.last().unwrap().to_vec()), + bitcoin::Network::Bitcoin + ) + .script_pubkey(), + _script_pubkey + ); } else if _script_pubkey.is_p2wpkh() { - assert_eq!(&bitcoin::Address::p2wpkh(&bitcoin::CompressedPublicKey(bitcoin::PublicKey::from_slice(&input.witness.last().unwrap()).unwrap().inner), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey); - } else { panic!(); } + assert_eq!( + &bitcoin::Address::p2wpkh( + &bitcoin::CompressedPublicKey( + bitcoin::PublicKey::from_slice( + &input.witness.last().unwrap() + ) + .unwrap() + .inner + ), + bitcoin::Network::Bitcoin + ) + .script_pubkey(), + _script_pubkey + ); + } else { + panic!(); + } } return true; } @@ -4693,15 +5571,22 @@ impl ChannelMonitorImpl { } fn should_broadcast_holder_commitment_txn( - &self, logger: &WithChannelMonitor - ) -> bool where L::Target: Logger { + &self, logger: &WithChannelMonitor, + ) -> bool + where + L::Target: Logger, + { // There's no need to broadcast our commitment transaction if we've seen one confirmed (even // with 1 confirmation) as it'll be rejected as duplicate/conflicting. - if self.funding_spend_confirmed.is_some() || - self.onchain_events_awaiting_threshold_conf.iter().find(|event| match event.event { - OnchainEvent::FundingSpendConfirmation { .. } => true, - _ => false, - }).is_some() + if self.funding_spend_confirmed.is_some() + || self + .onchain_events_awaiting_threshold_conf + .iter() + .find(|event| match event.event { + OnchainEvent::FundingSpendConfirmation { .. } => true, + _ => false, + }) + .is_some() { return false; } @@ -4731,24 +5616,34 @@ impl ChannelMonitorImpl { // we give ourselves a few blocks of headroom after expiration before going // on-chain for an expired HTLC. let htlc_outbound = $holder_tx == htlc.offered; - if ( htlc_outbound && htlc.cltv_expiry + LATENCY_GRACE_PERIOD_BLOCKS <= height) || - (!htlc_outbound && htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER && self.payment_preimages.contains_key(&htlc.payment_hash)) { - log_info!(logger, "Force-closing channel due to {} HTLC timeout, HTLC expiry is {}", if htlc_outbound { "outbound" } else { "inbound "}, htlc.cltv_expiry); + if (htlc_outbound && htlc.cltv_expiry + LATENCY_GRACE_PERIOD_BLOCKS <= height) + || (!htlc_outbound + && htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER + && self.payment_preimages.contains_key(&htlc.payment_hash)) + { + log_info!( + logger, + "Force-closing channel due to {} HTLC timeout, HTLC expiry is {}", + if htlc_outbound { "outbound" } else { "inbound " }, + htlc.cltv_expiry + ); return true; } } - } + }; } scan_commitment!(self.funding.current_holder_commitment.htlcs(), true); if let Some(ref txid) = self.funding.current_counterparty_commitment_txid { - if let Some(ref htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(txid) { + if let Some(ref htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(txid) + { scan_commitment!(htlc_outputs.iter().map(|&(ref a, _)| a), false); } } if let Some(ref txid) = self.funding.prev_counterparty_commitment_txid { - if let Some(ref htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(txid) { + if let Some(ref htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(txid) + { scan_commitment!(htlc_outputs.iter().map(|&(ref a, _)| a), false); } } @@ -4759,8 +5654,11 @@ impl ChannelMonitorImpl { /// Check if any transaction broadcasted is resolving HTLC output by a success or timeout on a holder /// or counterparty commitment tx, if so send back the source, preimage if found and payment_hash of resolved HTLC fn is_resolving_htlc_output( - &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &WithChannelMonitor, - ) where L::Target: Logger { + &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, + logger: &WithChannelMonitor, + ) where + L::Target: Logger, + { 'outer_loop: for input in &tx.input { let mut payment_data = None; let htlc_claim = HTLCClaim::from_witness(&input.witness); @@ -4809,22 +5707,34 @@ impl ChannelMonitorImpl { macro_rules! check_htlc_valid_counterparty { ($htlc_output: expr, $per_commitment_data: expr) => { - for &(ref pending_htlc, ref pending_source) in $per_commitment_data { - if pending_htlc.payment_hash == $htlc_output.payment_hash && pending_htlc.amount_msat == $htlc_output.amount_msat { - if let &Some(ref source) = pending_source { - log_claim!("revoked counterparty commitment tx", false, pending_htlc, true); - payment_data = Some(((**source).clone(), $htlc_output.payment_hash, $htlc_output.amount_msat)); - break; - } + for &(ref pending_htlc, ref pending_source) in $per_commitment_data { + if pending_htlc.payment_hash == $htlc_output.payment_hash + && pending_htlc.amount_msat == $htlc_output.amount_msat + { + if let &Some(ref source) = pending_source { + log_claim!( + "revoked counterparty commitment tx", + false, + pending_htlc, + true + ); + payment_data = Some(( + (**source).clone(), + $htlc_output.payment_hash, + $htlc_output.amount_msat, + )); + break; } } - } + } + }; } macro_rules! scan_commitment { ($htlcs: expr, $tx_info: expr, $holder_tx: expr) => { for (ref htlc_output, source_option) in $htlcs { - if Some(input.previous_output.vout) == htlc_output.transaction_output_index { + if Some(input.previous_output.vout) == htlc_output.transaction_output_index + { if let Some(ref source) = source_option { log_claim!($tx_info, $holder_tx, htlc_output, true); // We have a resolution of an HTLC either from one of our latest @@ -4832,43 +5742,81 @@ impl ChannelMonitorImpl { // transaction. This implies we either learned a preimage, the HTLC // has timed out, or we screwed up. In any case, we should now // resolve the source HTLC with the original sender. - payment_data = Some(((*source).clone(), htlc_output.payment_hash, htlc_output.amount_msat)); + payment_data = Some(( + (*source).clone(), + htlc_output.payment_hash, + htlc_output.amount_msat, + )); } else if !$holder_tx { - if let Some(current_counterparty_commitment_txid) = &self.funding.current_counterparty_commitment_txid { - check_htlc_valid_counterparty!(htlc_output, self.funding.counterparty_claimable_outpoints.get(current_counterparty_commitment_txid).unwrap()); + if let Some(current_counterparty_commitment_txid) = + &self.funding.current_counterparty_commitment_txid + { + check_htlc_valid_counterparty!( + htlc_output, + self.funding + .counterparty_claimable_outpoints + .get(current_counterparty_commitment_txid) + .unwrap() + ); } if payment_data.is_none() { - if let Some(prev_counterparty_commitment_txid) = &self.funding.prev_counterparty_commitment_txid { - check_htlc_valid_counterparty!(htlc_output, self.funding.counterparty_claimable_outpoints.get(prev_counterparty_commitment_txid).unwrap()); + if let Some(prev_counterparty_commitment_txid) = + &self.funding.prev_counterparty_commitment_txid + { + check_htlc_valid_counterparty!( + htlc_output, + self.funding + .counterparty_claimable_outpoints + .get(prev_counterparty_commitment_txid) + .unwrap() + ); } } } if payment_data.is_none() { log_claim!($tx_info, $holder_tx, htlc_output, false); let outbound_htlc = $holder_tx == htlc_output.offered; - self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry { - txid: tx.compute_txid(), height, block_hash: Some(*block_hash), transaction: Some(tx.clone()), - event: OnchainEvent::HTLCSpendConfirmation { - commitment_tx_output_idx: input.previous_output.vout, - preimage: if accepted_preimage_claim || offered_preimage_claim { - Some(payment_preimage) } else { None }, - // If this is a payment to us (ie !outbound_htlc), wait for - // the CSV delay before dropping the HTLC from claimable - // balance if the claim was an HTLC-Success transaction (ie - // accepted_preimage_claim). - on_to_local_output_csv: if accepted_preimage_claim && !outbound_htlc { - Some(self.on_holder_tx_csv) } else { None }, + self.onchain_events_awaiting_threshold_conf.push( + OnchainEventEntry { + txid: tx.compute_txid(), + height, + block_hash: Some(*block_hash), + transaction: Some(tx.clone()), + event: OnchainEvent::HTLCSpendConfirmation { + commitment_tx_output_idx: input.previous_output.vout, + preimage: if accepted_preimage_claim + || offered_preimage_claim + { + Some(payment_preimage) + } else { + None + }, + // If this is a payment to us (ie !outbound_htlc), wait for + // the CSV delay before dropping the HTLC from claimable + // balance if the claim was an HTLC-Success transaction (ie + // accepted_preimage_claim). + on_to_local_output_csv: if accepted_preimage_claim + && !outbound_htlc + { + Some(self.on_holder_tx_csv) + } else { + None + }, + }, }, - }); + ); continue 'outer_loop; } } } - } + }; } - if input.previous_output.txid == self.funding.current_holder_commitment.tx.trust().txid() { - let htlcs_with_sources = self.funding.current_holder_commitment.htlcs_with_sources(); + if input.previous_output.txid + == self.funding.current_holder_commitment.tx.trust().txid() + { + let htlcs_with_sources = + self.funding.current_holder_commitment.htlcs_with_sources(); scan_commitment!(htlcs_with_sources, "our latest holder commitment tx", true); } if let Some(ref prev_holder_commitment) = self.funding.prev_holder_commitment { @@ -4877,17 +5825,29 @@ impl ChannelMonitorImpl { scan_commitment!(htlcs_with_sources, "our previous holder commitment tx", true); } } - if let Some(ref htlc_outputs) = self.funding.counterparty_claimable_outpoints.get(&input.previous_output.txid) { - scan_commitment!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, b.as_ref().map(|boxed| &**boxed))), - "counterparty commitment tx", false); + if let Some(ref htlc_outputs) = + self.funding.counterparty_claimable_outpoints.get(&input.previous_output.txid) + { + scan_commitment!( + htlc_outputs + .iter() + .map(|&(ref a, ref b)| (a, b.as_ref().map(|boxed| &**boxed))), + "counterparty commitment tx", + false + ); } // Check that scan_commitment, above, decided there is some source worth relaying an // HTLC resolution backwards to and figure out whether we learned a preimage from it. if let Some((source, payment_hash, amount_msat)) = payment_data { if accepted_preimage_claim { - if !self.pending_monitor_events.iter().any( - |update| if let &MonitorEvent::HTLCEvent(ref upd) = update { upd.source == source } else { false }) { + if !self.pending_monitor_events.iter().any(|update| { + if let &MonitorEvent::HTLCEvent(ref upd) = update { + upd.source == source + } else { + false + } + }) { self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry { txid: tx.compute_txid(), height, @@ -4907,10 +5867,13 @@ impl ChannelMonitorImpl { })); } } else if offered_preimage_claim { - if !self.pending_monitor_events.iter().any( - |update| if let &MonitorEvent::HTLCEvent(ref upd) = update { + if !self.pending_monitor_events.iter().any(|update| { + if let &MonitorEvent::HTLCEvent(ref upd) = update { upd.source == source - } else { false }) { + } else { + false + } + }) { self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry { txid: tx.compute_txid(), transaction: Some(tx.clone()), @@ -4931,7 +5894,9 @@ impl ChannelMonitorImpl { } } else { self.onchain_events_awaiting_threshold_conf.retain(|ref entry| { - if entry.height != height { return true; } + if entry.height != height { + return true; + } match entry.event { OnchainEvent::HTLCUpdate { source: ref htlc_source, .. } => { *htlc_source != source @@ -4968,28 +5933,44 @@ impl ChannelMonitorImpl { channel_keys_id: Some(self.channel_keys_id), }); } - if let Some(ref broadcasted_holder_revokable_script) = self.broadcasted_holder_revokable_script { + if let Some(ref broadcasted_holder_revokable_script) = + self.broadcasted_holder_revokable_script + { if broadcasted_holder_revokable_script.0 == outp.script_pubkey { - spendable_outputs.push(SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor { - outpoint: OutPoint { txid: tx.compute_txid(), index: i as u16 }, - per_commitment_point: broadcasted_holder_revokable_script.1, - to_self_delay: self.on_holder_tx_csv, - output: outp.clone(), - revocation_pubkey: broadcasted_holder_revokable_script.2, - channel_keys_id: self.channel_keys_id, - channel_value_satoshis: self.funding.channel_parameters.channel_value_satoshis, - channel_transaction_parameters: Some(self.funding.channel_parameters.clone()), - })); + spendable_outputs.push(SpendableOutputDescriptor::DelayedPaymentOutput( + DelayedPaymentOutputDescriptor { + outpoint: OutPoint { txid: tx.compute_txid(), index: i as u16 }, + per_commitment_point: broadcasted_holder_revokable_script.1, + to_self_delay: self.on_holder_tx_csv, + output: outp.clone(), + revocation_pubkey: broadcasted_holder_revokable_script.2, + channel_keys_id: self.channel_keys_id, + channel_value_satoshis: self + .funding + .channel_parameters + .channel_value_satoshis, + channel_transaction_parameters: Some( + self.funding.channel_parameters.clone(), + ), + }, + )); } } if self.counterparty_payment_script == outp.script_pubkey { - spendable_outputs.push(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor { - outpoint: OutPoint { txid: tx.compute_txid(), index: i as u16 }, - output: outp.clone(), - channel_keys_id: self.channel_keys_id, - channel_value_satoshis: self.funding.channel_parameters.channel_value_satoshis, - channel_transaction_parameters: Some(self.funding.channel_parameters.clone()), - })); + spendable_outputs.push(SpendableOutputDescriptor::StaticPaymentOutput( + StaticPaymentOutputDescriptor { + outpoint: OutPoint { txid: tx.compute_txid(), index: i as u16 }, + output: outp.clone(), + channel_keys_id: self.channel_keys_id, + channel_value_satoshis: self + .funding + .channel_parameters + .channel_value_satoshis, + channel_transaction_parameters: Some( + self.funding.channel_parameters.clone(), + ), + }, + )); } if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) { spendable_outputs.push(SpendableOutputDescriptor::StaticOutput { @@ -5005,8 +5986,11 @@ impl ChannelMonitorImpl { /// Checks if the confirmed transaction is paying funds back to some address we can assume to /// own. fn check_tx_and_push_spendable_outputs( - &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &WithChannelMonitor, - ) where L::Target: Logger { + &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, + logger: &WithChannelMonitor, + ) where + L::Target: Logger, + { for spendable_output in self.get_spendable_outputs(tx) { let entry = OnchainEventEntry { txid: tx.compute_txid(), @@ -5015,7 +5999,12 @@ impl ChannelMonitorImpl { block_hash: Some(*block_hash), event: OnchainEvent::MaturingOutput { descriptor: spendable_output.clone() }, }; - log_info!(logger, "Received spendable output {}, spendable at height {}", log_spendable!(spendable_output), entry.confirmation_threshold()); + log_info!( + logger, + "Received spendable output {}, spendable at height {}", + log_spendable!(spendable_output), + entry.confirmation_threshold() + ); self.onchain_events_awaiting_threshold_conf.push(entry); } } @@ -5025,7 +6014,8 @@ impl ChannelMonitorImpl { } } -impl chain::Listen for (ChannelMonitor, T, F, L) +impl chain::Listen + for (ChannelMonitor, T, F, L) where T::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -5064,10 +6054,11 @@ where } } -const MAX_ALLOC_SIZE: usize = 64*1024; +const MAX_ALLOC_SIZE: usize = 64 * 1024; impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)> - for (BlockHash, ChannelMonitor) { + for (BlockHash, ChannelMonitor) +{ fn read(reader: &mut R, args: (&'a ES, &'b SP)) -> Result { macro_rules! unwrap_obj { ($key: expr) => { @@ -5075,7 +6066,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP Ok(res) => res, Err(_) => return Err(DecodeError::InvalidValue), } - } + }; } let (entropy_source, signer_provider) = args; @@ -5093,23 +6084,24 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let revokable_script = Readable::read(reader)?; Some((revokable_address, per_commitment_point, revokable_script)) }, - 1 => { None }, + 1 => None, _ => return Err(DecodeError::InvalidValue), }; let mut counterparty_payment_script: ScriptBuf = Readable::read(reader)?; let shutdown_script = { let script = ::read(reader)?; - if script.is_empty() { None } else { Some(script) } + if script.is_empty() { + None + } else { + Some(script) + } }; let channel_keys_id = Readable::read(reader)?; let holder_revocation_basepoint = Readable::read(reader)?; // Technically this can fail and serialize fail a round-trip, but only for serialization of // barely-init'd ChannelMonitors that we can't do anything with. - let outpoint = OutPoint { - txid: Readable::read(reader)?, - index: Readable::read(reader)?, - }; + let outpoint = OutPoint { txid: Readable::read(reader)?, index: Readable::read(reader)? }; let funding_script = Readable::read(reader)?; let current_counterparty_commitment_txid = Readable::read(reader)?; let prev_counterparty_commitment_txid = Readable::read(reader)?; @@ -5128,7 +6120,11 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP if second_point_slice[0..32] == [0; 32] && second_point_slice[32] == 0 { Some((first_idx, first_point, None)) } else { - Some((first_idx, first_point, Some(unwrap_obj!(PublicKey::from_slice(&second_point_slice))))) + Some(( + first_idx, + first_point, + Some(unwrap_obj!(PublicKey::from_slice(&second_point_slice))), + )) } } }; @@ -5138,29 +6134,38 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let commitment_secrets = Readable::read(reader)?; macro_rules! read_htlc_in_commitment { - () => { - { - let offered: bool = Readable::read(reader)?; - let amount_msat: u64 = Readable::read(reader)?; - let cltv_expiry: u32 = Readable::read(reader)?; - let payment_hash: PaymentHash = Readable::read(reader)?; - let transaction_output_index: Option = Readable::read(reader)?; - - HTLCOutputInCommitment { - offered, amount_msat, cltv_expiry, payment_hash, transaction_output_index - } + () => {{ + let offered: bool = Readable::read(reader)?; + let amount_msat: u64 = Readable::read(reader)?; + let cltv_expiry: u32 = Readable::read(reader)?; + let payment_hash: PaymentHash = Readable::read(reader)?; + let transaction_output_index: Option = Readable::read(reader)?; + + HTLCOutputInCommitment { + offered, + amount_msat, + cltv_expiry, + payment_hash, + transaction_output_index, } - } + }}; } let counterparty_claimable_outpoints_len: u64 = Readable::read(reader)?; - let mut counterparty_claimable_outpoints = hash_map_with_capacity(cmp::min(counterparty_claimable_outpoints_len as usize, MAX_ALLOC_SIZE / 64)); + let mut counterparty_claimable_outpoints = hash_map_with_capacity(cmp::min( + counterparty_claimable_outpoints_len as usize, + MAX_ALLOC_SIZE / 64, + )); for _ in 0..counterparty_claimable_outpoints_len { let txid: Txid = Readable::read(reader)?; let htlcs_count: u64 = Readable::read(reader)?; let mut htlcs = Vec::with_capacity(cmp::min(htlcs_count as usize, MAX_ALLOC_SIZE / 32)); for _ in 0..htlcs_count { - htlcs.push((read_htlc_in_commitment!(), as Readable>::read(reader)?.map(|o: HTLCSource| Box::new(o)))); + htlcs.push(( + read_htlc_in_commitment!(), + as Readable>::read(reader)? + .map(|o: HTLCSource| Box::new(o)), + )); } if counterparty_claimable_outpoints.insert(txid, htlcs).is_some() { return Err(DecodeError::InvalidValue); @@ -5168,7 +6173,10 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP } let counterparty_commitment_txn_on_chain_len: u64 = Readable::read(reader)?; - let mut counterparty_commitment_txn_on_chain = hash_map_with_capacity(cmp::min(counterparty_commitment_txn_on_chain_len as usize, MAX_ALLOC_SIZE / 32)); + let mut counterparty_commitment_txn_on_chain = hash_map_with_capacity(cmp::min( + counterparty_commitment_txn_on_chain_len as usize, + MAX_ALLOC_SIZE / 32, + )); for _ in 0..counterparty_commitment_txn_on_chain_len { let txid: Txid = Readable::read(reader)?; let commitment_number = ::read(reader)?.0; @@ -5178,28 +6186,32 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP } let counterparty_hash_commitment_number_len: u64 = Readable::read(reader)?; - let mut counterparty_hash_commitment_number = hash_map_with_capacity(cmp::min(counterparty_hash_commitment_number_len as usize, MAX_ALLOC_SIZE / 32)); + let mut counterparty_hash_commitment_number = hash_map_with_capacity(cmp::min( + counterparty_hash_commitment_number_len as usize, + MAX_ALLOC_SIZE / 32, + )); for _ in 0..counterparty_hash_commitment_number_len { let payment_hash: PaymentHash = Readable::read(reader)?; let commitment_number = ::read(reader)?.0; - if counterparty_hash_commitment_number.insert(payment_hash, commitment_number).is_some() { + if counterparty_hash_commitment_number.insert(payment_hash, commitment_number).is_some() + { return Err(DecodeError::InvalidValue); } } - let prev_holder_signed_tx: Option = - match ::read(reader)? { - 0 => None, - 1 => Some(Readable::read(reader)?), - _ => return Err(DecodeError::InvalidValue), - }; + let prev_holder_signed_tx: Option = match ::read(reader)? { + 0 => None, + 1 => Some(Readable::read(reader)?), + _ => return Err(DecodeError::InvalidValue), + }; let current_holder_signed_tx: HolderSignedTx = Readable::read(reader)?; let current_counterparty_commitment_number = ::read(reader)?.0; let current_holder_commitment_number = ::read(reader)?.0; let payment_preimages_len: u64 = Readable::read(reader)?; - let mut payment_preimages = hash_map_with_capacity(cmp::min(payment_preimages_len as usize, MAX_ALLOC_SIZE / 32)); + let mut payment_preimages = + hash_map_with_capacity(cmp::min(payment_preimages_len as usize, MAX_ALLOC_SIZE / 32)); for _ in 0..payment_preimages_len { let preimage: PaymentPreimage = Readable::read(reader)?; let hash = PaymentHash(Sha256::hash(&preimage.0[..]).to_byte_array()); @@ -5209,19 +6221,24 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP } let pending_monitor_events_len: u64 = Readable::read(reader)?; - let mut pending_monitor_events = Some( - Vec::with_capacity(cmp::min(pending_monitor_events_len as usize, MAX_ALLOC_SIZE / (32 + 8*3)))); + let mut pending_monitor_events = Some(Vec::with_capacity(cmp::min( + pending_monitor_events_len as usize, + MAX_ALLOC_SIZE / (32 + 8 * 3), + ))); for _ in 0..pending_monitor_events_len { let ev = match ::read(reader)? { 0 => MonitorEvent::HTLCEvent(Readable::read(reader)?), 1 => MonitorEvent::HolderForceClosed(outpoint), - _ => return Err(DecodeError::InvalidValue) + _ => return Err(DecodeError::InvalidValue), }; pending_monitor_events.as_mut().unwrap().push(ev); } let pending_events_len: u64 = Readable::read(reader)?; - let mut pending_events = Vec::with_capacity(cmp::min(pending_events_len as usize, MAX_ALLOC_SIZE / mem::size_of::())); + let mut pending_events = Vec::with_capacity(cmp::min( + pending_events_len as usize, + MAX_ALLOC_SIZE / mem::size_of::(), + )); for _ in 0..pending_events_len { if let Some(event) = MaybeReadable::read(reader)? { pending_events.push(event); @@ -5231,7 +6248,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let best_block = BestBlock::new(Readable::read(reader)?, Readable::read(reader)?); let waiting_threshold_conf_len: u64 = Readable::read(reader)?; - let mut onchain_events_awaiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); + let mut onchain_events_awaiting_threshold_conf = + Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..waiting_threshold_conf_len { if let Some(val) = MaybeReadable::read(reader)? { onchain_events_awaiting_threshold_conf.push(val); @@ -5239,11 +6257,20 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP } let outputs_to_watch_len: u64 = Readable::read(reader)?; - let mut outputs_to_watch = hash_map_with_capacity(cmp::min(outputs_to_watch_len as usize, MAX_ALLOC_SIZE / (mem::size_of::() + mem::size_of::() + mem::size_of::>()))); + let mut outputs_to_watch = hash_map_with_capacity(cmp::min( + outputs_to_watch_len as usize, + MAX_ALLOC_SIZE + / (mem::size_of::() + + mem::size_of::() + + mem::size_of::>()), + )); for _ in 0..outputs_to_watch_len { let txid = Readable::read(reader)?; let outputs_len: u64 = Readable::read(reader)?; - let mut outputs = Vec::with_capacity(cmp::min(outputs_len as usize, MAX_ALLOC_SIZE / (mem::size_of::() + mem::size_of::()))); + let mut outputs = Vec::with_capacity(cmp::min( + outputs_len as usize, + MAX_ALLOC_SIZE / (mem::size_of::() + mem::size_of::()), + )); for _ in 0..outputs_len { outputs.push((Readable::read(reader)?, Readable::read(reader)?)); } @@ -5252,7 +6279,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP } } let onchain_tx_handler: OnchainTxHandler = ReadableArgs::read( - reader, (entropy_source, signer_provider, channel_value_satoshis, channel_keys_id) + reader, + (entropy_source, signer_provider, channel_value_satoshis, channel_keys_id), )?; let lockdown_from_offchain = Readable::read(reader)?; @@ -5311,33 +6339,40 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP // `HolderForceClosedWithInfo` replaced `HolderForceClosed` in v0.0.122. If we have both // events, we can remove the `HolderForceClosed` event and just keep the `HolderForceClosedWithInfo`. if let Some(ref mut pending_monitor_events) = pending_monitor_events { - if pending_monitor_events.iter().any(|e| matches!(e, MonitorEvent::HolderForceClosed(_))) && - pending_monitor_events.iter().any(|e| matches!(e, MonitorEvent::HolderForceClosedWithInfo { .. })) + if pending_monitor_events + .iter() + .any(|e| matches!(e, MonitorEvent::HolderForceClosed(_))) + && pending_monitor_events + .iter() + .any(|e| matches!(e, MonitorEvent::HolderForceClosedWithInfo { .. })) { pending_monitor_events.retain(|e| !matches!(e, MonitorEvent::HolderForceClosed(_))); } } - let channel_parameters = channel_parameters.unwrap_or_else(|| { - onchain_tx_handler.channel_parameters().clone() - }); + let channel_parameters = + channel_parameters.unwrap_or_else(|| onchain_tx_handler.channel_parameters().clone()); // Monitors for anchor outputs channels opened in v0.0.116 suffered from a bug in which the // wrong `counterparty_payment_script` was being tracked. Fix it now on deserialization to // give them a chance to recognize the spendable output. - if channel_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx() && - counterparty_payment_script.is_p2wpkh() + if channel_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx() + && counterparty_payment_script.is_p2wpkh() { let payment_point = channel_parameters.holder_pubkeys.payment_point; counterparty_payment_script = - chan_utils::get_to_countersigner_keyed_anchor_redeemscript(&payment_point).to_p2wsh(); + chan_utils::get_to_countersigner_keyed_anchor_redeemscript(&payment_point) + .to_p2wsh(); } let channel_id = channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(outpoint)); if counterparty_node_id.is_none() { - panic!("Found monitor for channel {} with no updates since v0.0.118.\ + panic!( + "Found monitor for channel {} with no updates since v0.0.118.\ These monitors are no longer supported.\ - To continue, run a v0.1 release, send/route a payment over the channel or close it.", channel_id); + To continue, run a v0.1 release, send/route a payment over the channel or close it.", + channel_id + ); } let current_holder_commitment = { @@ -5347,12 +6382,17 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let holder_signed_tx_copy = current_holder_signed_tx.clone(); let holder_commitment = HolderCommitment::try_from(( - holder_commitment_tx.clone(), current_holder_signed_tx, - )).map_err(|_| DecodeError::InvalidValue)?; + holder_commitment_tx.clone(), + current_holder_signed_tx, + )) + .map_err(|_| DecodeError::InvalidValue)?; - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let mut stream = crate::util::ser::VecWriter(Vec::new()); - holder_commitment.write_as_legacy(&mut stream).map_err(|_| DecodeError::InvalidValue)?; + holder_commitment + .write_as_legacy(&mut stream) + .map_err(|_| DecodeError::InvalidValue)?; let mut cursor = crate::io::Cursor::new(stream.0); if holder_signed_tx_copy != ::read(&mut cursor)? { return Err(DecodeError::InvalidValue); @@ -5372,12 +6412,17 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let holder_signed_tx_copy = prev_holder_signed_tx.clone(); let holder_commitment = HolderCommitment::try_from(( - holder_commitment_tx.cloned().unwrap(), prev_holder_signed_tx, - )).map_err(|_| DecodeError::InvalidValue)?; + holder_commitment_tx.cloned().unwrap(), + prev_holder_signed_tx, + )) + .map_err(|_| DecodeError::InvalidValue)?; - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let mut stream = crate::util::ser::VecWriter(Vec::new()); - holder_commitment.write_as_legacy(&mut stream).map_err(|_| DecodeError::InvalidValue)?; + holder_commitment + .write_as_legacy(&mut stream) + .map_err(|_| DecodeError::InvalidValue)?; let mut cursor = crate::io::Cursor::new(stream.0); if holder_signed_tx_copy != ::read(&mut cursor)? { return Err(DecodeError::InvalidValue); @@ -5389,116 +6434,132 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP None }; - Ok((best_block.block_hash, ChannelMonitor::from_impl(ChannelMonitorImpl { - funding: FundingScope { - script_pubkey: funding_script, - redeem_script: funding_redeemscript, - channel_parameters, - - current_counterparty_commitment_txid, - prev_counterparty_commitment_txid, - counterparty_claimable_outpoints, - - current_holder_commitment, - prev_holder_commitment, - }, - - latest_update_id, - commitment_transaction_number_obscure_factor, - - destination_script, - broadcasted_holder_revokable_script, - counterparty_payment_script, - shutdown_script, - - channel_keys_id, - holder_revocation_basepoint, - channel_id, - first_confirmed_funding_txo: first_confirmed_funding_txo.0.unwrap(), - - counterparty_commitment_params, - their_cur_per_commitment_points, - - on_holder_tx_csv, - - commitment_secrets, - counterparty_commitment_txn_on_chain, - counterparty_hash_commitment_number, - counterparty_fulfilled_htlcs: counterparty_fulfilled_htlcs.unwrap(), - - current_counterparty_commitment_number, - current_holder_commitment_number, - - payment_preimages, - pending_monitor_events: pending_monitor_events.unwrap(), - pending_events, - is_processing_pending_events: false, - - onchain_events_awaiting_threshold_conf, - outputs_to_watch, + Ok(( + best_block.block_hash, + ChannelMonitor::from_impl(ChannelMonitorImpl { + funding: FundingScope { + script_pubkey: funding_script, + redeem_script: funding_redeemscript, + channel_parameters, - onchain_tx_handler, + current_counterparty_commitment_txid, + prev_counterparty_commitment_txid, + counterparty_claimable_outpoints, - lockdown_from_offchain, - holder_tx_signed, - holder_pays_commitment_tx_fee, - funding_spend_seen: funding_spend_seen.unwrap(), - funding_spend_confirmed, - confirmed_commitment_tx_counterparty_output, - htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(), - spendable_txids_confirmed: spendable_txids_confirmed.unwrap(), + current_holder_commitment, + prev_holder_commitment, + }, - best_block, - counterparty_node_id: counterparty_node_id.unwrap(), - initial_counterparty_commitment_info, - initial_counterparty_commitment_tx, - balances_empty_height, - failed_back_htlc_ids: new_hash_set(), - }))) + latest_update_id, + commitment_transaction_number_obscure_factor, + + destination_script, + broadcasted_holder_revokable_script, + counterparty_payment_script, + shutdown_script, + + channel_keys_id, + holder_revocation_basepoint, + channel_id, + first_confirmed_funding_txo: first_confirmed_funding_txo.0.unwrap(), + + counterparty_commitment_params, + their_cur_per_commitment_points, + + on_holder_tx_csv, + + commitment_secrets, + counterparty_commitment_txn_on_chain, + counterparty_hash_commitment_number, + counterparty_fulfilled_htlcs: counterparty_fulfilled_htlcs.unwrap(), + + current_counterparty_commitment_number, + current_holder_commitment_number, + + payment_preimages, + pending_monitor_events: pending_monitor_events.unwrap(), + pending_events, + is_processing_pending_events: false, + + onchain_events_awaiting_threshold_conf, + outputs_to_watch, + + onchain_tx_handler, + + lockdown_from_offchain, + holder_tx_signed, + holder_pays_commitment_tx_fee, + funding_spend_seen: funding_spend_seen.unwrap(), + funding_spend_confirmed, + confirmed_commitment_tx_counterparty_output, + htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(), + spendable_txids_confirmed: spendable_txids_confirmed.unwrap(), + + best_block, + counterparty_node_id: counterparty_node_id.unwrap(), + initial_counterparty_commitment_info, + initial_counterparty_commitment_tx, + balances_empty_height, + failed_back_htlc_ids: new_hash_set(), + }), + )) } } #[cfg(test)] mod tests { use bitcoin::amount::Amount; - use bitcoin::locktime::absolute::LockTime; - use bitcoin::script::{ScriptBuf, Builder}; - use bitcoin::opcodes; - use bitcoin::transaction::{Transaction, TxIn, TxOut, Version}; - use bitcoin::transaction::OutPoint as BitcoinOutPoint; - use bitcoin::sighash; - use bitcoin::sighash::EcdsaSighashType; - use bitcoin::hashes::Hash; + use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::hashes::sha256::Hash as Sha256; + use bitcoin::hashes::Hash; use bitcoin::hex::FromHex; - use bitcoin::hash_types::{BlockHash, Txid}; + use bitcoin::locktime::absolute::LockTime; use bitcoin::network::Network; - use bitcoin::secp256k1::{SecretKey,PublicKey}; + use bitcoin::opcodes; + use bitcoin::script::{Builder, ScriptBuf}; use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + use bitcoin::sighash; + use bitcoin::sighash::EcdsaSighashType; + use bitcoin::transaction::OutPoint as BitcoinOutPoint; + use bitcoin::transaction::{Transaction, TxIn, TxOut, Version}; use bitcoin::{Sequence, Witness}; use crate::chain::chaininterface::LowerBoundedFeeEstimator; use super::ChannelMonitorUpdateStep; - use crate::{check_added_monitors, check_spends, get_local_commitment_txn, get_monitor, get_route_and_payment_hash}; - use crate::chain::{BestBlock, Confirm}; use crate::chain::channelmonitor::{ChannelMonitor, WithChannelMonitor}; - use crate::chain::package::{weight_offered_htlc, weight_received_htlc, weight_revoked_offered_htlc, weight_revoked_received_htlc, WEIGHT_REVOKED_OUTPUT}; + use crate::chain::package::{ + weight_offered_htlc, weight_received_htlc, weight_revoked_offered_htlc, + weight_revoked_received_htlc, WEIGHT_REVOKED_OUTPUT, + }; use crate::chain::transaction::OutPoint; - use crate::sign::InMemorySigner; - use crate::ln::types::ChannelId; - use crate::types::payment::{PaymentPreimage, PaymentHash}; - use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, RevocationBasepoint, RevocationKey}; - use crate::ln::chan_utils::{self,HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; + use crate::chain::{BestBlock, Confirm}; + use crate::io; + use crate::ln::chan_utils::{ + self, ChannelPublicKeys, ChannelTransactionParameters, + CounterpartyChannelTransactionParameters, HTLCOutputInCommitment, + HolderCommitmentTransaction, + }; + use crate::ln::channel_keys::{ + DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, RevocationBasepoint, + RevocationKey, + }; use crate::ln::channelmanager::{HTLCSource, PaymentId, RecipientOnionFields}; use crate::ln::functional_test_utils::*; use crate::ln::script::ShutdownScript; - use crate::util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator}; - use crate::util::ser::{ReadableArgs, Writeable}; - use crate::util::logger::Logger; + use crate::ln::types::ChannelId; + use crate::sign::InMemorySigner; use crate::sync::Arc; - use crate::io; use crate::types::features::ChannelTypeFeatures; + use crate::types::payment::{PaymentHash, PaymentPreimage}; + use crate::util::logger::Logger; + use crate::util::ser::{ReadableArgs, Writeable}; + use crate::util::test_utils::{TestBroadcaster, TestFeeEstimator, TestLogger}; + use crate::{ + check_added_monitors, check_spends, get_local_commitment_txn, get_monitor, + get_route_and_payment_hash, + }; #[allow(unused_imports)] use crate::prelude::*; @@ -5543,48 +6604,75 @@ mod tests { // channel is now closed, but the ChannelManager doesn't know that yet. let new_header = create_dummy_header(nodes[0].best_block_info().0, 0); let conf_height = nodes[0].best_block_info().1 + 1; - nodes[1].chain_monitor.chain_monitor.transactions_confirmed(&new_header, - &[(0, broadcast_tx)], conf_height); + nodes[1].chain_monitor.chain_monitor.transactions_confirmed( + &new_header, + &[(0, broadcast_tx)], + conf_height, + ); let (_, pre_update_monitor) = <(BlockHash, ChannelMonitor<_>)>::read( - &mut io::Cursor::new(&get_monitor!(nodes[1], channel.2).encode()), - (&nodes[1].keys_manager.backing, &nodes[1].keys_manager.backing)).unwrap(); + &mut io::Cursor::new(&get_monitor!(nodes[1], channel.2).encode()), + (&nodes[1].keys_manager.backing, &nodes[1].keys_manager.backing), + ) + .unwrap(); // If the ChannelManager tries to update the channel, however, the ChainMonitor will pass // the update through to the ChannelMonitor which will refuse it (as the channel is closed). - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 100_000); - nodes[1].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 100_000); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); // Build a new ChannelMonitorUpdate which contains both the failing commitment tx update // and provides the claim preimages for the two pending HTLCs. The first update generates // an error, but the point of this test is to ensure the later updates are still applied. let monitor_updates = nodes[1].chain_monitor.monitor_updates.lock().unwrap(); - let mut replay_update = monitor_updates.get(&channel.2).unwrap().iter().rev().next().unwrap().clone(); + let mut replay_update = + monitor_updates.get(&channel.2).unwrap().iter().rev().next().unwrap().clone(); assert_eq!(replay_update.updates.len(), 1); - if let ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } = replay_update.updates[0] { - } else { panic!(); } + if let ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } = + replay_update.updates[0] + { + } else { + panic!(); + } replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { - payment_preimage: payment_preimage_1, payment_info: None, + payment_preimage: payment_preimage_1, + payment_info: None, }); replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { - payment_preimage: payment_preimage_2, payment_info: None, + payment_preimage: payment_preimage_2, + payment_info: None, }); let broadcaster = TestBroadcaster::with_blocks(Arc::clone(&nodes[1].blocks)); - assert!( - pre_update_monitor.update_monitor(&replay_update, &&broadcaster, &&chanmon_cfgs[1].fee_estimator, &nodes[1].logger) + assert!(pre_update_monitor + .update_monitor( + &replay_update, + &&broadcaster, + &&chanmon_cfgs[1].fee_estimator, + &nodes[1].logger + ) .is_err()); // Even though we error'd on the first update, we should still have generated an HTLC claim // transaction let txn_broadcasted = broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert!(txn_broadcasted.len() >= 2); - let htlc_txn = txn_broadcasted.iter().filter(|tx| { - assert_eq!(tx.input.len(), 1); - tx.input[0].previous_output.txid == broadcast_tx.compute_txid() - }).collect::>(); + let htlc_txn = txn_broadcasted + .iter() + .filter(|tx| { + assert_eq!(tx.input.len(), 1); + tx.input[0].previous_output.txid == broadcast_tx.compute_txid() + }) + .collect::>(); assert_eq!(htlc_txn.len(), 2); check_spends!(htlc_txn[0], broadcast_tx); check_spends!(htlc_txn[1], broadcast_tx); @@ -5602,7 +6690,8 @@ mod tests { let broadcaster = Arc::new(TestBroadcaster::new(Network::Testnet)); let fee_estimator = TestFeeEstimator::new(253); - let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let dummy_key = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut preimages = Vec::new(); { @@ -5616,37 +6705,45 @@ mod tests { let dummy_source = HTLCSource::dummy(); macro_rules! preimages_slice_to_htlcs { - ($preimages_slice: expr) => { - { - let mut res = Vec::new(); - for (idx, preimage) in $preimages_slice.iter().enumerate() { - res.push(HTLCOutputInCommitment { - offered: true, - amount_msat: 0, - cltv_expiry: 0, - payment_hash: preimage.1.clone(), - transaction_output_index: Some(idx as u32), - }); - } - res + ($preimages_slice: expr) => {{ + let mut res = Vec::new(); + for (idx, preimage) in $preimages_slice.iter().enumerate() { + res.push(HTLCOutputInCommitment { + offered: true, + amount_msat: 0, + cltv_expiry: 0, + payment_hash: preimage.1.clone(), + transaction_output_index: Some(idx as u32), + }); } - } + res + }}; } macro_rules! preimages_slice_to_htlc_outputs { ($preimages_slice: expr) => { - preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|htlc| (htlc, None)).collect() - } + preimages_slice_to_htlcs!($preimages_slice) + .into_iter() + .map(|htlc| (htlc, None)) + .collect() + }; } - let dummy_sig = crate::crypto::utils::sign(&secp_ctx, + let dummy_sig = crate::crypto::utils::sign( + &secp_ctx, &bitcoin::secp256k1::Message::from_digest([42; 32]), - &SecretKey::from_slice(&[42; 32]).unwrap()); + &SecretKey::from_slice(&[42; 32]).unwrap(), + ); macro_rules! test_preimages_exist { ($preimages_slice: expr, $monitor: expr) => { for preimage in $preimages_slice { - assert!($monitor.inner.lock().unwrap().payment_preimages.contains_key(&preimage.1)); + assert!($monitor + .inner + .lock() + .unwrap() + .payment_preimages + .contains_key(&preimage.1)); } - } + }; } let keys = InMemorySigner::new( @@ -5662,11 +6759,26 @@ mod tests { ); let counterparty_pubkeys = ChannelPublicKeys { - funding_pubkey: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[44; 32]).unwrap()), - revocation_basepoint: RevocationBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap())), - payment_point: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap()), - delayed_payment_basepoint: DelayedPaymentBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[47; 32]).unwrap())), - htlc_basepoint: HtlcBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[48; 32]).unwrap())) + funding_pubkey: PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[44; 32]).unwrap(), + ), + revocation_basepoint: RevocationBasepoint::from(PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[45; 32]).unwrap(), + )), + payment_point: PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[46; 32]).unwrap(), + ), + delayed_payment_basepoint: DelayedPaymentBasepoint::from(PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[47; 32]).unwrap(), + )), + htlc_basepoint: HtlcBasepoint::from(PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[48; 32]).unwrap(), + )), }; let funding_outpoint = OutPoint { txid: Txid::all_zeros(), index: u16::MAX }; let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint); @@ -5685,13 +6797,23 @@ mod tests { }; // Prune with one old state and a holder commitment tx holding a few overlaps with the // old state. - let shutdown_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let shutdown_pubkey = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let shutdown_script = ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey); let best_block = BestBlock::from_network(Network::Testnet); let monitor = ChannelMonitor::new( - Secp256k1::new(), keys, Some(shutdown_script.into_inner()), 0, &ScriptBuf::new(), - &channel_parameters, true, 0, HolderCommitmentTransaction::dummy(0, Vec::new()), - best_block, dummy_key, channel_id, + Secp256k1::new(), + keys, + Some(shutdown_script.into_inner()), + 0, + &ScriptBuf::new(), + &channel_parameters, + true, + 0, + HolderCommitmentTransaction::dummy(0, Vec::new()), + best_block, + dummy_key, + channel_id, ); let nondust_htlcs = preimages_slice_to_htlcs!(preimages[0..10]); @@ -5699,39 +6821,78 @@ mod tests { // These HTLCs now have their output indices assigned let nondust_htlcs = dummy_commitment_tx.nondust_htlcs(); - monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(), - nondust_htlcs.into_iter().map(|htlc| (htlc.clone(), Some(dummy_sig), Some(dummy_source.clone()))).collect()); - monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"1").to_byte_array()), - preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger); - monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"2").to_byte_array()), - preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key, &logger); + monitor.provide_latest_holder_commitment_tx( + dummy_commitment_tx.clone(), + nondust_htlcs + .into_iter() + .map(|htlc| (htlc.clone(), Some(dummy_sig), Some(dummy_source.clone()))) + .collect(), + ); + monitor.provide_latest_counterparty_commitment_tx( + Txid::from_byte_array(Sha256::hash(b"1").to_byte_array()), + preimages_slice_to_htlc_outputs!(preimages[5..15]), + 281474976710655, + dummy_key, + &logger, + ); + monitor.provide_latest_counterparty_commitment_tx( + Txid::from_byte_array(Sha256::hash(b"2").to_byte_array()), + preimages_slice_to_htlc_outputs!(preimages[15..20]), + 281474976710654, + dummy_key, + &logger, + ); for &(ref preimage, ref hash) in preimages.iter() { let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator); monitor.provide_payment_preimage_unsafe_legacy( - hash, preimage, &broadcaster, &bounded_fee_estimator, &logger + hash, + preimage, + &broadcaster, + &bounded_fee_estimator, + &logger, ); } // Now provide a secret, pruning preimages 10-15 let mut secret = [0; 32]; - secret[0..32].clone_from_slice(&>::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + secret[0..32].clone_from_slice( + &>::from_hex( + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secret.clone()).unwrap(); assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 15); test_preimages_exist!(&preimages[0..10], monitor); test_preimages_exist!(&preimages[15..20], monitor); - monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"3").to_byte_array()), - preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger); + monitor.provide_latest_counterparty_commitment_tx( + Txid::from_byte_array(Sha256::hash(b"3").to_byte_array()), + preimages_slice_to_htlc_outputs!(preimages[17..20]), + 281474976710653, + dummy_key, + &logger, + ); // Now provide a further secret, pruning preimages 15-17 - secret[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + secret[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secret.clone()).unwrap(); assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 13); test_preimages_exist!(&preimages[0..10], monitor); test_preimages_exist!(&preimages[17..20], monitor); - monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"4").to_byte_array()), - preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger); + monitor.provide_latest_counterparty_commitment_tx( + Txid::from_byte_array(Sha256::hash(b"4").to_byte_array()), + preimages_slice_to_htlc_outputs!(preimages[18..20]), + 281474976710652, + dummy_key, + &logger, + ); // Now update holder commitment tx info, pruning only element 18 as we still care about the // previous commitment tx's preimages too @@ -5739,9 +6900,19 @@ mod tests { let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, nondust_htlcs); // These HTLCs now have their output indices assigned let nondust_htlcs = dummy_commitment_tx.nondust_htlcs(); - monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(), - nondust_htlcs.into_iter().map(|htlc| (htlc.clone(), Some(dummy_sig), Some(dummy_source.clone()))).collect()); - secret[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor.provide_latest_holder_commitment_tx( + dummy_commitment_tx.clone(), + nondust_htlcs + .into_iter() + .map(|htlc| (htlc.clone(), Some(dummy_sig), Some(dummy_source.clone()))) + .collect(), + ); + secret[0..32].clone_from_slice( + &>::from_hex( + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secret.clone()).unwrap(); assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 12); test_preimages_exist!(&preimages[0..10], monitor); @@ -5752,9 +6923,19 @@ mod tests { let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, nondust_htlcs); // These HTLCs now have their output indices assigned let nondust_htlcs = dummy_commitment_tx.nondust_htlcs(); - monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(), - nondust_htlcs.into_iter().map(|htlc| (htlc.clone(), Some(dummy_sig), Some(dummy_source.clone()))).collect()); - secret[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + monitor.provide_latest_holder_commitment_tx( + dummy_commitment_tx.clone(), + nondust_htlcs + .into_iter() + .map(|htlc| (htlc.clone(), Some(dummy_sig), Some(dummy_source.clone()))) + .collect(), + ); + secret[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); monitor.provide_secret(281474976710652, secret.clone()).unwrap(); assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 5); test_preimages_exist!(&preimages[0..5], monitor); @@ -5766,21 +6947,63 @@ mod tests { // not actual case to avoid sigs and time-lock delays hell variances. let secp_ctx = Secp256k1::new(); - let privkey = SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap(); + let privkey = SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap()[..], + ) + .unwrap(); let pubkey = PublicKey::from_secret_key(&secp_ctx, &privkey); - use crate::ln::channel_keys::{HtlcKey, HtlcBasepoint}; + use crate::ln::channel_keys::{HtlcBasepoint, HtlcKey}; macro_rules! sign_input { ($sighash_parts: expr, $idx: expr, $amount: expr, $weight: expr, $sum_actual_sigs: expr, $opt_anchors: expr) => { let htlc = HTLCOutputInCommitment { - offered: if *$weight == weight_revoked_offered_htlc($opt_anchors) || *$weight == weight_offered_htlc($opt_anchors) { true } else { false }, + offered: if *$weight == weight_revoked_offered_htlc($opt_anchors) + || *$weight == weight_offered_htlc($opt_anchors) + { + true + } else { + false + }, amount_msat: 0, cltv_expiry: 2 << 16, payment_hash: PaymentHash([1; 32]), transaction_output_index: Some($idx as u32), }; - let redeem_script = if *$weight == WEIGHT_REVOKED_OUTPUT { chan_utils::get_revokeable_redeemscript(&RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(pubkey), &pubkey), 256, &DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(pubkey), &pubkey)) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, $opt_anchors, &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), &RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(pubkey), &pubkey)) }; - let sighash = hash_to_message!(&$sighash_parts.p2wsh_signature_hash($idx, &redeem_script, $amount, EcdsaSighashType::All).unwrap()[..]); + let redeem_script = if *$weight == WEIGHT_REVOKED_OUTPUT { + chan_utils::get_revokeable_redeemscript( + &RevocationKey::from_basepoint( + &secp_ctx, + &RevocationBasepoint::from(pubkey), + &pubkey, + ), + 256, + &DelayedPaymentKey::from_basepoint( + &secp_ctx, + &DelayedPaymentBasepoint::from(pubkey), + &pubkey, + ), + ) + } else { + chan_utils::get_htlc_redeemscript_with_explicit_keys( + &htlc, + $opt_anchors, + &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), + &HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(pubkey), &pubkey), + &RevocationKey::from_basepoint( + &secp_ctx, + &RevocationBasepoint::from(pubkey), + &pubkey, + ), + ) + }; + let sighash = hash_to_message!( + &$sighash_parts + .p2wsh_signature_hash($idx, &redeem_script, $amount, EcdsaSighashType::All) + .unwrap()[..] + ); let sig = secp_ctx.sign_ecdsa(&sighash, &privkey); let mut ser_sig = sig.serialize_der().to_vec(); ser_sig.push(EcdsaSighashType::All as u8); @@ -5788,8 +7011,10 @@ mod tests { let witness = $sighash_parts.witness_mut($idx).unwrap(); witness.push(ser_sig); if *$weight == WEIGHT_REVOKED_OUTPUT { - witness.push(vec!(1)); - } else if *$weight == weight_revoked_offered_htlc($opt_anchors) || *$weight == weight_revoked_received_htlc($opt_anchors) { + witness.push(vec![1]); + } else if *$weight == weight_revoked_offered_htlc($opt_anchors) + || *$weight == weight_revoked_received_htlc($opt_anchors) + { witness.push(pubkey.clone().serialize().to_vec()); } else if *$weight == weight_received_htlc($opt_anchors) { witness.push(vec![0]); @@ -5801,104 +7026,164 @@ mod tests { println!("witness[0] {}", witness[0].len()); println!("witness[1] {}", witness[1].len()); println!("witness[2] {}", witness[2].len()); - } + }; } let script_pubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(); - let txid = Txid::from_str("56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d").unwrap(); + let txid = + Txid::from_str("56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d") + .unwrap(); // Justice tx with 1 to_holder, 2 revoked offered HTLCs, 1 revoked received HTLCs - for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() { - let mut claim_tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + for channel_type_features in [ + ChannelTypeFeatures::only_static_remote_key(), + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + ] + .iter() + { + let mut claim_tx = Transaction { + version: Version(0), + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }; let mut sum_actual_sigs = 0; for i in 0..4 { claim_tx.input.push(TxIn { - previous_output: BitcoinOutPoint { - txid, - vout: i, - }, + previous_output: BitcoinOutPoint { txid, vout: i }, script_sig: ScriptBuf::new(), sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, witness: Witness::new(), }); } - claim_tx.output.push(TxOut { - script_pubkey: script_pubkey.clone(), - value: Amount::ZERO, - }); + claim_tx + .output + .push(TxOut { script_pubkey: script_pubkey.clone(), value: Amount::ZERO }); let base_weight = claim_tx.weight().to_wu(); - let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT, weight_revoked_offered_htlc(channel_type_features), weight_revoked_offered_htlc(channel_type_features), weight_revoked_received_htlc(channel_type_features)]; + let inputs_weight = vec![ + WEIGHT_REVOKED_OUTPUT, + weight_revoked_offered_htlc(channel_type_features), + weight_revoked_offered_htlc(channel_type_features), + weight_revoked_received_htlc(channel_type_features), + ]; let mut inputs_total_weight = 2; // count segwit flags { let mut sighash_parts = sighash::SighashCache::new(&mut claim_tx); for (idx, inp) in inputs_weight.iter().enumerate() { - sign_input!(sighash_parts, idx, Amount::ZERO, inp, sum_actual_sigs, channel_type_features); + sign_input!( + sighash_parts, + idx, + Amount::ZERO, + inp, + sum_actual_sigs, + channel_type_features + ); inputs_total_weight += inp; } } - assert_eq!(base_weight + inputs_total_weight, claim_tx.weight().to_wu() + /* max_length_sig */ (73 * inputs_weight.len() as u64 - sum_actual_sigs)); + assert_eq!( + base_weight + inputs_total_weight, + claim_tx.weight().to_wu() + /* max_length_sig */ (73 * inputs_weight.len() as u64 - sum_actual_sigs) + ); } // Claim tx with 1 offered HTLCs, 3 received HTLCs - for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() { - let mut claim_tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + for channel_type_features in [ + ChannelTypeFeatures::only_static_remote_key(), + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + ] + .iter() + { + let mut claim_tx = Transaction { + version: Version(0), + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }; let mut sum_actual_sigs = 0; for i in 0..4 { claim_tx.input.push(TxIn { - previous_output: BitcoinOutPoint { - txid, - vout: i, - }, + previous_output: BitcoinOutPoint { txid, vout: i }, script_sig: ScriptBuf::new(), sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, witness: Witness::new(), }); } - claim_tx.output.push(TxOut { - script_pubkey: script_pubkey.clone(), - value: Amount::ZERO, - }); + claim_tx + .output + .push(TxOut { script_pubkey: script_pubkey.clone(), value: Amount::ZERO }); let base_weight = claim_tx.weight().to_wu(); - let inputs_weight = vec![weight_offered_htlc(channel_type_features), weight_received_htlc(channel_type_features), weight_received_htlc(channel_type_features), weight_received_htlc(channel_type_features)]; + let inputs_weight = vec![ + weight_offered_htlc(channel_type_features), + weight_received_htlc(channel_type_features), + weight_received_htlc(channel_type_features), + weight_received_htlc(channel_type_features), + ]; let mut inputs_total_weight = 2; // count segwit flags { let mut sighash_parts = sighash::SighashCache::new(&mut claim_tx); for (idx, inp) in inputs_weight.iter().enumerate() { - sign_input!(sighash_parts, idx, Amount::ZERO, inp, sum_actual_sigs, channel_type_features); + sign_input!( + sighash_parts, + idx, + Amount::ZERO, + inp, + sum_actual_sigs, + channel_type_features + ); inputs_total_weight += inp; } } - assert_eq!(base_weight + inputs_total_weight, claim_tx.weight().to_wu() + /* max_length_sig */ (73 * inputs_weight.len() as u64 - sum_actual_sigs)); + assert_eq!( + base_weight + inputs_total_weight, + claim_tx.weight().to_wu() + /* max_length_sig */ (73 * inputs_weight.len() as u64 - sum_actual_sigs) + ); } // Justice tx with 1 revoked HTLC-Success tx output - for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() { - let mut claim_tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + for channel_type_features in [ + ChannelTypeFeatures::only_static_remote_key(), + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + ] + .iter() + { + let mut claim_tx = Transaction { + version: Version(0), + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }; let mut sum_actual_sigs = 0; claim_tx.input.push(TxIn { - previous_output: BitcoinOutPoint { - txid, - vout: 0, - }, + previous_output: BitcoinOutPoint { txid, vout: 0 }, script_sig: ScriptBuf::new(), sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, witness: Witness::new(), }); - claim_tx.output.push(TxOut { - script_pubkey: script_pubkey.clone(), - value: Amount::ZERO, - }); + claim_tx + .output + .push(TxOut { script_pubkey: script_pubkey.clone(), value: Amount::ZERO }); let base_weight = claim_tx.weight().to_wu(); let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT]; let mut inputs_total_weight = 2; // count segwit flags { let mut sighash_parts = sighash::SighashCache::new(&mut claim_tx); for (idx, inp) in inputs_weight.iter().enumerate() { - sign_input!(sighash_parts, idx, Amount::ZERO, inp, sum_actual_sigs, channel_type_features); + sign_input!( + sighash_parts, + idx, + Amount::ZERO, + inp, + sum_actual_sigs, + channel_type_features + ); inputs_total_weight += inp; } } - assert_eq!(base_weight + inputs_total_weight, claim_tx.weight().to_wu() + /* max_length_isg */ (73 * inputs_weight.len() as u64 - sum_actual_sigs)); + assert_eq!( + base_weight + inputs_total_weight, + claim_tx.weight().to_wu() + /* max_length_isg */ (73 * inputs_weight.len() as u64 - sum_actual_sigs) + ); } } @@ -5907,7 +7192,8 @@ mod tests { let secp_ctx = Secp256k1::new(); let logger = Arc::new(TestLogger::new()); - let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let dummy_key = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let keys = InMemorySigner::new( &secp_ctx, @@ -5922,11 +7208,26 @@ mod tests { ); let counterparty_pubkeys = ChannelPublicKeys { - funding_pubkey: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[44; 32]).unwrap()), - revocation_basepoint: RevocationBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap())), - payment_point: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap()), - delayed_payment_basepoint: DelayedPaymentBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[47; 32]).unwrap())), - htlc_basepoint: HtlcBasepoint::from(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[48; 32]).unwrap())), + funding_pubkey: PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[44; 32]).unwrap(), + ), + revocation_basepoint: RevocationBasepoint::from(PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[45; 32]).unwrap(), + )), + payment_point: PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[46; 32]).unwrap(), + ), + delayed_payment_basepoint: DelayedPaymentBasepoint::from(PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[47; 32]).unwrap(), + )), + htlc_basepoint: HtlcBasepoint::from(PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&[48; 32]).unwrap(), + )), }; let funding_outpoint = OutPoint { txid: Txid::all_zeros(), index: u16::MAX }; let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint); @@ -5943,13 +7244,23 @@ mod tests { channel_type_features: ChannelTypeFeatures::only_static_remote_key(), channel_value_satoshis: 0, }; - let shutdown_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let shutdown_pubkey = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let shutdown_script = ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey); let best_block = BestBlock::from_network(Network::Testnet); let monitor = ChannelMonitor::new( - Secp256k1::new(), keys, Some(shutdown_script.into_inner()), 0, &ScriptBuf::new(), - &channel_parameters, true, 0, HolderCommitmentTransaction::dummy(0, Vec::new()), - best_block, dummy_key, channel_id, + Secp256k1::new(), + keys, + Some(shutdown_script.into_inner()), + 0, + &ScriptBuf::new(), + &channel_parameters, + true, + 0, + HolderCommitmentTransaction::dummy(0, Vec::new()), + best_block, + dummy_key, + channel_id, ); let chan_id = monitor.inner.lock().unwrap().channel_id(); @@ -5961,7 +7272,12 @@ mod tests { log_trace!(context_logger, "This is an error"); log_gossip!(context_logger, "This is an error"); log_info!(context_logger, "This is an error"); - logger.assert_log_context_contains("lightning::chain::channelmonitor::tests", Some(dummy_key), Some(chan_id), 6); + logger.assert_log_context_contains( + "lightning::chain::channelmonitor::tests", + Some(dummy_key), + Some(chan_id), + 6, + ); } // Further testing is done in the ChannelManager integration tests. } diff --git a/lightning/src/chain/mod.rs b/lightning/src/chain/mod.rs index 21fceb09cab..22b9bdc9535 100644 --- a/lightning/src/chain/mod.rs +++ b/lightning/src/chain/mod.rs @@ -11,16 +11,16 @@ use bitcoin::block::{Block, Header}; use bitcoin::constants::genesis_block; -use bitcoin::script::{Script, ScriptBuf}; use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::network::Network; +use bitcoin::script::{Script, ScriptBuf}; use bitcoin::secp256k1::PublicKey; use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, MonitorEvent}; -use crate::ln::types::ChannelId; -use crate::sign::ecdsa::EcdsaChannelSigner; use crate::chain::transaction::{OutPoint, TransactionData}; use crate::impl_writeable_tlv_based; +use crate::ln::types::ChannelId; +use crate::sign::ecdsa::EcdsaChannelSigner; #[allow(unused_imports)] use crate::prelude::*; @@ -28,9 +28,9 @@ use crate::prelude::*; pub mod chaininterface; pub mod chainmonitor; pub mod channelmonitor; -pub mod transaction; pub(crate) mod onchaintx; pub(crate) mod package; +pub mod transaction; /// The best known block as identified by its hash and height. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] @@ -45,10 +45,7 @@ impl BestBlock { /// Constructs a `BestBlock` that represents the genesis block at height 0 of the given /// network. pub fn from_network(network: Network) -> Self { - BestBlock { - block_hash: genesis_block(network).header.block_hash(), - height: 0, - } + BestBlock { block_hash: genesis_block(network).header.block_hash(), height: 0 } } /// Returns a `BestBlock` as identified by the given block hash and height. @@ -65,7 +62,6 @@ impl_writeable_tlv_based!(BestBlock, { (2, height, required), }); - /// The `Listen` trait is used to notify when blocks have been connected or disconnected from the /// chain. /// @@ -276,7 +272,9 @@ pub trait Watch { /// [`get_outputs_to_watch`]: channelmonitor::ChannelMonitor::get_outputs_to_watch /// [`block_connected`]: channelmonitor::ChannelMonitor::block_connected /// [`block_disconnected`]: channelmonitor::ChannelMonitor::block_disconnected - fn watch_channel(&self, channel_id: ChannelId, monitor: ChannelMonitor) -> Result; + fn watch_channel( + &self, channel_id: ChannelId, monitor: ChannelMonitor, + ) -> Result; /// Updates a channel identified by `channel_id` by applying `update` to its monitor. /// @@ -293,7 +291,9 @@ pub trait Watch { /// [`ChannelMonitorUpdateStatus::UnrecoverableError`], see its documentation for more info. /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager - fn update_channel(&self, channel_id: ChannelId, update: &ChannelMonitorUpdate) -> ChannelMonitorUpdateStatus; + fn update_channel( + &self, channel_id: ChannelId, update: &ChannelMonitorUpdate, + ) -> ChannelMonitorUpdateStatus; /// Returns any monitor events since the last call. Subsequent calls must only return new /// events. @@ -304,7 +304,9 @@ pub trait Watch { /// /// For details on asynchronous [`ChannelMonitor`] updating and returning /// [`MonitorEvent::Completed`] here, see [`ChannelMonitorUpdateStatus::InProgress`]. - fn release_pending_monitor_events(&self) -> Vec<(OutPoint, ChannelId, Vec, PublicKey)>; + fn release_pending_monitor_events( + &self, + ) -> Vec<(OutPoint, ChannelId, Vec, PublicKey)>; } /// The `Filter` trait defines behavior for indicating chain activity of interest pertaining to diff --git a/lightning/src/chain/onchaintx.rs b/lightning/src/chain/onchaintx.rs index 00deb99f678..01bafbdf8c8 100644 --- a/lightning/src/chain/onchaintx.rs +++ b/lightning/src/chain/onchaintx.rs @@ -13,37 +13,41 @@ //! building, tracking, bumping and notifications functions. use bitcoin::amount::Amount; +use bitcoin::hash_types::{BlockHash, Txid}; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::locktime::absolute::LockTime; -use bitcoin::transaction::Transaction; -use bitcoin::transaction::OutPoint as BitcoinOutPoint; use bitcoin::script::{Script, ScriptBuf}; -use bitcoin::hashes::{Hash, HashEngine}; -use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hash_types::{Txid, BlockHash}; -use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; use bitcoin::secp256k1; +use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1}; +use bitcoin::transaction::OutPoint as BitcoinOutPoint; +use bitcoin::transaction::Transaction; -use crate::chain::chaininterface::{ConfirmationTarget, compute_feerate_sat_per_1000_weight}; -use crate::sign::{EntropySource, HTLCDescriptor, SignerProvider, ecdsa::EcdsaChannelSigner}; -use crate::ln::msgs::DecodeError; -use crate::ln::chan_utils::{self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction}; -use crate::chain::ClaimId; -use crate::chain::chaininterface::{FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator}; +use crate::chain::chaininterface::{compute_feerate_sat_per_1000_weight, ConfirmationTarget}; +use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator}; use crate::chain::channelmonitor::ANTI_REORG_DELAY; use crate::chain::package::{PackageSolvingData, PackageTemplate}; use crate::chain::transaction::MaybeSignedTransaction; +use crate::chain::ClaimId; +use crate::ln::chan_utils::{ + self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction, +}; +use crate::ln::msgs::DecodeError; +use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, HTLCDescriptor, SignerProvider}; use crate::util::logger::Logger; -use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, UpgradableRequired, Writer, Writeable}; +use crate::util::ser::{ + MaybeReadable, Readable, ReadableArgs, UpgradableRequired, Writeable, Writer, +}; use crate::io; use crate::prelude::*; use alloc::collections::BTreeMap; use core::cmp; -use core::ops::Deref; use core::mem::replace; use core::mem::swap; +use core::ops::Deref; -const MAX_ALLOC_SIZE: usize = 64*1024; +const MAX_ALLOC_SIZE: usize = 64 * 1024; /// An entry for an [`OnchainEvent`], stating the block height when the event was observed and the /// transaction causing it. @@ -75,18 +79,14 @@ enum OnchainEvent { /// as the request. This claim can either be ours or from the counterparty. Once the claiming /// transaction has met [`ANTI_REORG_DELAY`] confirmations, we consider it final and remove the /// pending request. - Claim { - claim_id: ClaimId, - }, + Claim { claim_id: ClaimId }, /// The counterparty has claimed an outpoint from one of our pending requests through a /// different transaction than ours. If our transaction was attempting to claim multiple /// outputs, we need to drop the outpoint claimed by the counterparty and regenerate a new claim /// transaction for ourselves. We keep tracking, separately, the outpoint claimed by the /// counterparty up to [`ANTI_REORG_DELAY`] confirmations to ensure we attempt to re-claim it /// if the counterparty's claim is reorged from the chain. - ContentiousOutpoint { - package: PackageTemplate, - } + ContentiousOutpoint { package: PackageTemplate }, } impl Writeable for OnchainEventEntry { @@ -113,7 +113,12 @@ impl MaybeReadable for OnchainEventEntry { (2, height, required), (4, event, upgradable_required), }); - Ok(Some(Self { txid, height, block_hash, event: _init_tlv_based_struct_field!(event, upgradable_required) })) + Ok(Some(Self { + txid, + height, + block_hash, + event: _init_tlv_based_struct_field!(event, upgradable_required), + })) } } @@ -132,12 +137,18 @@ impl Readable for Option>> { 0u8 => Ok(None), 1u8 => { let vlen: u64 = Readable::read(reader)?; - let mut ret = Vec::with_capacity(cmp::min(vlen as usize, MAX_ALLOC_SIZE / ::core::mem::size_of::>())); + let mut ret = Vec::with_capacity(cmp::min( + vlen as usize, + MAX_ALLOC_SIZE / ::core::mem::size_of::>(), + )); for _ in 0..vlen { ret.push(match Readable::read(reader)? { 0u8 => None, - 1u8 => Some((::read(reader)? as usize, Readable::read(reader)?)), - _ => return Err(DecodeError::InvalidValue) + 1u8 => Some(( + ::read(reader)? as usize, + Readable::read(reader)?, + )), + _ => return Err(DecodeError::InvalidValue), }); } Ok(Some(ret)) @@ -219,8 +230,8 @@ pub(crate) enum FeerateStrategy { /// do RBF bumping if possible. #[derive(Clone)] pub struct OnchainTxHandler { - channel_value_satoshis: u64, // Deprecated as of 0.2. - channel_keys_id: [u8; 32], // Deprecated as of 0.2. + channel_value_satoshis: u64, // Deprecated as of 0.2. + channel_keys_id: [u8; 32], // Deprecated as of 0.2. destination_script: ScriptBuf, // Deprecated as of 0.2. holder_commitment: HolderCommitmentTransaction, prev_holder_commitment: Option, @@ -277,16 +288,17 @@ pub struct OnchainTxHandler { impl PartialEq for OnchainTxHandler { fn eq(&self, other: &Self) -> bool { // `signer`, `secp_ctx`, and `pending_claim_events` are excluded on purpose. - self.channel_value_satoshis == other.channel_value_satoshis && - self.channel_keys_id == other.channel_keys_id && - self.destination_script == other.destination_script && - self.holder_commitment == other.holder_commitment && - self.prev_holder_commitment == other.prev_holder_commitment && - self.channel_transaction_parameters == other.channel_transaction_parameters && - self.pending_claim_requests == other.pending_claim_requests && - self.claimable_outpoints == other.claimable_outpoints && - self.locktimed_packages == other.locktimed_packages && - self.onchain_events_awaiting_threshold_conf == other.onchain_events_awaiting_threshold_conf + self.channel_value_satoshis == other.channel_value_satoshis + && self.channel_keys_id == other.channel_keys_id + && self.destination_script == other.destination_script + && self.holder_commitment == other.holder_commitment + && self.prev_holder_commitment == other.prev_holder_commitment + && self.channel_transaction_parameters == other.channel_transaction_parameters + && self.pending_claim_requests == other.pending_claim_requests + && self.claimable_outpoints == other.claimable_outpoints + && self.locktimed_packages == other.locktimed_packages + && self.onchain_events_awaiting_threshold_conf + == other.onchain_events_awaiting_threshold_conf } } @@ -331,7 +343,8 @@ impl OnchainTxHandler { } } - writer.write_all(&(self.onchain_events_awaiting_threshold_conf.len() as u64).to_be_bytes())?; + writer + .write_all(&(self.onchain_events_awaiting_threshold_conf.len() as u64).to_be_bytes())?; for ref entry in self.onchain_events_awaiting_threshold_conf.iter() { entry.write(writer)?; } @@ -341,8 +354,12 @@ impl OnchainTxHandler { } } -impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP, u64, [u8; 32])> for OnchainTxHandler { - fn read(reader: &mut R, args: (&'a ES, &'b SP, u64, [u8; 32])) -> Result { +impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP, u64, [u8; 32])> + for OnchainTxHandler +{ + fn read( + reader: &mut R, args: (&'a ES, &'b SP, u64, [u8; 32]), + ) -> Result { let entropy_source = args.0; let signer_provider = args.1; let channel_value_satoshis = args.2; @@ -355,9 +372,11 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let holder_commitment = Readable::read(reader)?; let _holder_htlc_sigs: Option>> = Readable::read(reader)?; let prev_holder_commitment = Readable::read(reader)?; - let _prev_holder_htlc_sigs: Option>> = Readable::read(reader)?; + let _prev_holder_htlc_sigs: Option>> = + Readable::read(reader)?; - let channel_parameters = ReadableArgs::>::read(reader, Some(channel_value_satoshis))?; + let channel_parameters = + ReadableArgs::>::read(reader, Some(channel_value_satoshis))?; // Read the serialized signer bytes, but don't deserialize them, as we'll obtain our signer // by re-deriving the private key material. @@ -375,13 +394,19 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let signer = signer_provider.derive_channel_signer(channel_keys_id); let pending_claim_requests_len: u64 = Readable::read(reader)?; - let mut pending_claim_requests = hash_map_with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); + let mut pending_claim_requests = hash_map_with_capacity(cmp::min( + pending_claim_requests_len as usize, + MAX_ALLOC_SIZE / 128, + )); for _ in 0..pending_claim_requests_len { pending_claim_requests.insert(Readable::read(reader)?, Readable::read(reader)?); } let claimable_outpoints_len: u64 = Readable::read(reader)?; - let mut claimable_outpoints = hash_map_with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); + let mut claimable_outpoints = hash_map_with_capacity(cmp::min( + pending_claim_requests_len as usize, + MAX_ALLOC_SIZE / 128, + )); for _ in 0..claimable_outpoints_len { let outpoint = Readable::read(reader)?; let ancestor_claim_txid = Readable::read(reader)?; @@ -394,7 +419,10 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP for _ in 0..locktimed_packages_len { let locktime = Readable::read(reader)?; let packages_len: u64 = Readable::read(reader)?; - let mut packages = Vec::with_capacity(cmp::min(packages_len as usize, MAX_ALLOC_SIZE / core::mem::size_of::())); + let mut packages = Vec::with_capacity(cmp::min( + packages_len as usize, + MAX_ALLOC_SIZE / core::mem::size_of::(), + )); for _ in 0..packages_len { packages.push(Readable::read(reader)?); } @@ -402,7 +430,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP } let waiting_threshold_conf_len: u64 = Readable::read(reader)?; - let mut onchain_events_awaiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); + let mut onchain_events_awaiting_threshold_conf = + Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..waiting_threshold_conf_len { if let Some(val) = MaybeReadable::read(reader)? { onchain_events_awaiting_threshold_conf.push(val); @@ -436,7 +465,7 @@ impl OnchainTxHandler { pub(crate) fn new( channel_value_satoshis: u64, channel_keys_id: [u8; 32], destination_script: ScriptBuf, signer: ChannelSigner, channel_parameters: ChannelTransactionParameters, - holder_commitment: HolderCommitmentTransaction, secp_ctx: Secp256k1 + holder_commitment: HolderCommitmentTransaction, secp_ctx: Secp256k1, ) -> Self { OnchainTxHandler { channel_value_satoshis, @@ -478,60 +507,84 @@ impl OnchainTxHandler { &mut self, current_height: u32, feerate_strategy: FeerateStrategy, broadcaster: &B, conf_target: ConfirmationTarget, destination_script: &Script, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, - ) - where + ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, { let mut bump_requests = Vec::with_capacity(self.pending_claim_requests.len()); for (claim_id, request) in self.pending_claim_requests.iter() { let inputs = request.outpoints(); - log_info!(logger, "Triggering rebroadcast/fee-bump for request with inputs {:?}", inputs); + log_info!( + logger, + "Triggering rebroadcast/fee-bump for request with inputs {:?}", + inputs + ); bump_requests.push((*claim_id, request.clone())); } for (claim_id, request) in bump_requests { self.generate_claim( - current_height, &request, &feerate_strategy, conf_target, destination_script, - fee_estimator, logger, + current_height, + &request, + &feerate_strategy, + conf_target, + destination_script, + fee_estimator, + logger, ) - .map(|(_, new_feerate, claim)| { - let mut feerate_was_bumped = false; - if let Some(mut_request) = self.pending_claim_requests.get_mut(&claim_id) { - feerate_was_bumped = new_feerate > request.previous_feerate(); - mut_request.set_feerate(new_feerate); - } - match claim { - OnchainClaim::Tx(tx) => { - if tx.is_fully_signed() { - let log_start = if feerate_was_bumped { "Broadcasting RBF-bumped" } else { "Rebroadcasting" }; - log_info!(logger, "{} onchain {}", log_start, log_tx!(tx.0)); - broadcaster.broadcast_transactions(&[&tx.0]); + .map(|(_, new_feerate, claim)| { + let mut feerate_was_bumped = false; + if let Some(mut_request) = self.pending_claim_requests.get_mut(&claim_id) { + feerate_was_bumped = new_feerate > request.previous_feerate(); + mut_request.set_feerate(new_feerate); + } + match claim { + OnchainClaim::Tx(tx) => { + if tx.is_fully_signed() { + let log_start = if feerate_was_bumped { + "Broadcasting RBF-bumped" } else { - log_info!(logger, "Waiting for signature of unsigned onchain transaction {}", tx.0.compute_txid()); - } - }, - OnchainClaim::Event(event) => { - let log_start = if feerate_was_bumped { "Yielding fee-bumped" } else { "Replaying" }; - log_info!(logger, "{} onchain event to spend inputs {:?}", log_start, - request.outpoints()); - #[cfg(debug_assertions)] { - debug_assert!(request.requires_external_funding()); - let num_existing = self.pending_claim_events.iter() - .filter(|entry| entry.0 == claim_id).count(); - assert!(num_existing == 0 || num_existing == 1); - } - self.pending_claim_events.retain(|event| event.0 != claim_id); - self.pending_claim_events.push((claim_id, event)); + "Rebroadcasting" + }; + log_info!(logger, "{} onchain {}", log_start, log_tx!(tx.0)); + broadcaster.broadcast_transactions(&[&tx.0]); + } else { + log_info!( + logger, + "Waiting for signature of unsigned onchain transaction {}", + tx.0.compute_txid() + ); } - } - }); + }, + OnchainClaim::Event(event) => { + let log_start = + if feerate_was_bumped { "Yielding fee-bumped" } else { "Replaying" }; + log_info!( + logger, + "{} onchain event to spend inputs {:?}", + log_start, + request.outpoints() + ); + #[cfg(debug_assertions)] + { + debug_assert!(request.requires_external_funding()); + let num_existing = self + .pending_claim_events + .iter() + .filter(|entry| entry.0 == claim_id) + .count(); + assert!(num_existing == 0 || num_existing == 1); + } + self.pending_claim_events.retain(|event| event.0 != claim_id); + self.pending_claim_events.push((claim_id, event)); + }, + } + }); } } /// Returns true if we are currently tracking any pending claim requests that are not fully /// confirmed yet. - pub(super) fn has_pending_claims(&self) -> bool - { + pub(super) fn has_pending_claims(&self) -> bool { self.pending_claim_requests.len() != 0 } @@ -548,7 +601,8 @@ impl OnchainTxHandler { feerate_strategy: &FeerateStrategy, conf_target: ConfirmationTarget, destination_script: &Script, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Option<(u32, u64, OnchainClaim)> - where F::Target: FeeEstimator, + where + F::Target: FeeEstimator, { let request_outpoints = cached_request.outpoints(); if request_outpoints.is_empty() { @@ -567,14 +621,14 @@ impl OnchainTxHandler { if let Some((request_claim_id, _)) = self.claimable_outpoints.get(*outpoint) { // We check for outpoint spends within claims individually rather than as a set // since requests can have outpoints split off. - if !self.onchain_events_awaiting_threshold_conf.iter() - .any(|event_entry| if let OnchainEvent::Claim { claim_id } = event_entry.event { + if !self.onchain_events_awaiting_threshold_conf.iter().any(|event_entry| { + if let OnchainEvent::Claim { claim_id } = event_entry.event { *request_claim_id == claim_id } else { // The onchain event is not a claim, keep seeking until we find one. false - }) - { + } + }) { // Either we had no `OnchainEvent::Claim`, or we did but none matched the // outpoint's registered spend. all_inputs_have_confirmed_spend = false; @@ -594,30 +648,45 @@ impl OnchainTxHandler { if cached_request.is_malleable() { if cached_request.requires_external_funding() { let target_feerate_sat_per_1000_weight = cached_request.compute_package_feerate( - fee_estimator, conf_target, feerate_strategy, + fee_estimator, + conf_target, + feerate_strategy, ); - let htlcs = cached_request.construct_malleable_package_with_external_funding(self)?; + let htlcs = + cached_request.construct_malleable_package_with_external_funding(self)?; return Some(( new_timer, target_feerate_sat_per_1000_weight as u64, OnchainClaim::Event(ClaimEvent::BumpHTLC { target_feerate_sat_per_1000_weight, htlcs, - tx_lock_time: LockTime::from_consensus(cached_request.package_locktime(cur_height)), + tx_lock_time: LockTime::from_consensus( + cached_request.package_locktime(cur_height), + ), }), )); } let predicted_weight = cached_request.package_weight(destination_script); if let Some((output_value, new_feerate)) = cached_request.compute_package_output( - predicted_weight, destination_script.minimal_non_dust().to_sat(), - feerate_strategy, conf_target, fee_estimator, logger, + predicted_weight, + destination_script.minimal_non_dust().to_sat(), + feerate_strategy, + conf_target, + fee_estimator, + logger, ) { assert!(new_feerate != 0); - let transaction = cached_request.maybe_finalize_malleable_package( - cur_height, self, Amount::from_sat(output_value), destination_script.into(), logger - ).unwrap(); + let transaction = cached_request + .maybe_finalize_malleable_package( + cur_height, + self, + Amount::from_sat(output_value), + destination_script.into(), + logger, + ) + .unwrap(); assert!(predicted_weight >= transaction.0.weight().to_wu()); return Some((new_timer, new_feerate, OnchainClaim::Tx(transaction))); } @@ -629,8 +698,9 @@ impl OnchainTxHandler { debug_assert_eq!(inputs.len(), 1); if !cached_request.requires_external_funding() { - return cached_request.maybe_finalize_untractable_package(self, logger) - .map(|tx| (new_timer, 0, OnchainClaim::Tx(tx))) + return cached_request + .maybe_finalize_untractable_package(self, logger) + .map(|tx| (new_timer, 0, OnchainClaim::Tx(tx))); } return inputs.find_map(|input| match input { @@ -706,16 +776,19 @@ impl OnchainTxHandler { debug_assert!(false, "Only HolderFundingOutput inputs should be untractable and require external funding"); None }, - }) + }); } None } pub fn abandon_claim(&mut self, outpoint: &BitcoinOutPoint) { - let claim_id = self.claimable_outpoints.get(outpoint).map(|(claim_id, _)| *claim_id) - .or_else(|| { - self.pending_claim_requests.iter() - .find(|(_, claim)| claim.outpoints().iter().any(|claim_outpoint| *claim_outpoint == outpoint)) + let claim_id = + self.claimable_outpoints.get(outpoint).map(|(claim_id, _)| *claim_id).or_else(|| { + self.pending_claim_requests + .iter() + .find(|(_, claim)| { + claim.outpoints().iter().any(|claim_outpoint| *claim_outpoint == outpoint) + }) .map(|(claim_id, _)| *claim_id) }); if let Some(claim_id) = claim_id { @@ -725,8 +798,11 @@ impl OnchainTxHandler { } } } else { - self.locktimed_packages.values_mut().for_each(|claims| - claims.retain(|claim| !claim.outpoints().iter().any(|claim_outpoint| *claim_outpoint == outpoint))); + self.locktimed_packages.values_mut().for_each(|claims| { + claims.retain(|claim| { + !claim.outpoints().iter().any(|claim_outpoint| *claim_outpoint == outpoint) + }) + }); } } @@ -742,13 +818,18 @@ impl OnchainTxHandler { pub(super) fn update_claims_view_from_requests( &mut self, mut requests: Vec, conf_height: u32, cur_height: u32, broadcaster: &B, conf_target: ConfirmationTarget, destination_script: &Script, - fee_estimator: &LowerBoundedFeeEstimator, logger: &L + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, { if !requests.is_empty() { - log_debug!(logger, "Updating claims view at height {} with {} claim requests", cur_height, requests.len()); + log_debug!( + logger, + "Updating claims view at height {} with {} claim requests", + cur_height, + requests.len() + ); } // First drop any duplicate claims. @@ -814,13 +895,19 @@ impl OnchainTxHandler { // Claim everything up to and including `cur_height`. let remaining_locked_packages = self.locktimed_packages.split_off(&(cur_height + 1)); if !self.locktimed_packages.is_empty() { - log_debug!(logger, + log_debug!( + logger, "Updating claims view at height {} with {} locked packages available for claim", cur_height, - self.locktimed_packages.len()); + self.locktimed_packages.len() + ); } for (pop_height, mut entry) in self.locktimed_packages.iter_mut() { - log_trace!(logger, "Restoring delayed claim of package(s) at their timelock at {}.", pop_height); + log_trace!( + logger, + "Restoring delayed claim of package(s) at their timelock at {}.", + pop_height + ); preprocessed_requests.append(&mut entry); } self.locktimed_packages = remaining_locked_packages; @@ -829,8 +916,13 @@ impl OnchainTxHandler { // height timer expiration (i.e in how many blocks we're going to take action). for mut req in preprocessed_requests { if let Some((new_timer, new_feerate, claim)) = self.generate_claim( - cur_height, &req, &FeerateStrategy::ForceBump, conf_target, destination_script, - &*fee_estimator, &*logger, + cur_height, + &req, + &FeerateStrategy::ForceBump, + conf_target, + destination_script, + &*fee_estimator, + &*logger, ) { req.set_timer(new_timer); req.set_feerate(new_feerate); @@ -843,17 +935,27 @@ impl OnchainTxHandler { log_info!(logger, "Broadcasting onchain {}", log_tx!(tx.0)); broadcaster.broadcast_transactions(&[&tx.0]); } else { - log_info!(logger, "Waiting for signature of unsigned onchain transaction {}", tx.0.compute_txid()); + log_info!( + logger, + "Waiting for signature of unsigned onchain transaction {}", + tx.0.compute_txid() + ); } ClaimId(tx.0.compute_txid().to_byte_array()) }, OnchainClaim::Event(claim_event) => { - log_info!(logger, "Yielding onchain event to spend inputs {:?}", req.outpoints()); + log_info!( + logger, + "Yielding onchain event to spend inputs {:?}", + req.outpoints() + ); let claim_id = match claim_event { ClaimEvent::BumpCommitment { ref commitment_tx, .. } => - // For commitment claims, we can just use their txid as it should - // already be unique. - ClaimId(commitment_tx.compute_txid().to_byte_array()), + // For commitment claims, we can just use their txid as it should + // already be unique. + { + ClaimId(commitment_tx.compute_txid().to_byte_array()) + }, ClaimEvent::BumpHTLC { ref htlcs, .. } => { // For HTLC claims, commit to the entire set of HTLC outputs to // claim, which will always be unique per request. Once a claim ID @@ -862,20 +964,30 @@ impl OnchainTxHandler { let mut engine = Sha256::engine(); for htlc in htlcs { engine.input(&htlc.commitment_txid.to_byte_array()); - engine.input(&htlc.htlc.transaction_output_index.unwrap().to_be_bytes()); + engine.input( + &htlc.htlc.transaction_output_index.unwrap().to_be_bytes(), + ); } ClaimId(Sha256::from_engine(engine).to_byte_array()) }, }; debug_assert!(self.pending_claim_requests.get(&claim_id).is_none()); - debug_assert_eq!(self.pending_claim_events.iter().filter(|entry| entry.0 == claim_id).count(), 0); + debug_assert_eq!( + self.pending_claim_events + .iter() + .filter(|entry| entry.0 == claim_id) + .count(), + 0 + ); self.pending_claim_events.push((claim_id, claim_event)); claim_id }, }; // Because fuzzing can cause hash collisions, we can end up with conflicting claim // ids here, so we only assert when not fuzzing. - debug_assert!(cfg!(fuzzing) || self.pending_claim_requests.get(&claim_id).is_none()); + debug_assert!( + cfg!(fuzzing) || self.pending_claim_requests.get(&claim_id).is_none() + ); for k in req.outpoints() { log_info!(logger, "Registering claiming request for {}:{}", k.txid, k.vout); self.claimable_outpoints.insert(k.clone(), (claim_id, conf_height)); @@ -896,7 +1008,7 @@ impl OnchainTxHandler { pub(super) fn update_claims_view_from_matched_txn( &mut self, txn_matched: &[&Transaction], conf_height: u32, conf_hash: BlockHash, cur_height: u32, broadcaster: &B, conf_target: ConfirmationTarget, - destination_script: &Script, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + destination_script: &Script, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -904,12 +1016,20 @@ impl OnchainTxHandler { let mut have_logged_intro = false; let mut maybe_log_intro = || { if !have_logged_intro { - log_debug!(logger, "Updating claims view at height {} with {} matched transactions in block {}", cur_height, txn_matched.len(), conf_height); + log_debug!( + logger, + "Updating claims view at height {} with {} matched transactions in block {}", + cur_height, + txn_matched.len(), + conf_height + ); have_logged_intro = true; } }; let mut bump_candidates = new_hash_map(); - if !txn_matched.is_empty() { maybe_log_intro(); } + if !txn_matched.is_empty() { + maybe_log_intro(); + } for tx in txn_matched { // Scan all input to verify is one of the outpoint spent is of interest for us let mut claimed_outputs_material = Vec::new(); @@ -922,7 +1042,8 @@ impl OnchainTxHandler { // after ANTI_REORG_DELAY blocks, otherwise we need to split it and retry // claiming the remaining outputs. let mut is_claim_subset_of_tx = true; - let mut tx_inputs = tx.input.iter().map(|input| &input.previous_output).collect::>(); + let mut tx_inputs = + tx.input.iter().map(|input| &input.previous_output).collect::>(); tx_inputs.sort_unstable(); for request_input in request.outpoints() { if tx_inputs.binary_search(&request_input).is_err() { @@ -937,12 +1058,12 @@ impl OnchainTxHandler { txid: tx.compute_txid(), height: conf_height, block_hash: Some(conf_hash), - event: OnchainEvent::Claim { claim_id: *claim_id } + event: OnchainEvent::Claim { claim_id: *claim_id }, }; if !self.onchain_events_awaiting_threshold_conf.contains(&entry) { self.onchain_events_awaiting_threshold_conf.push(entry); } - } + }; } // If this is our transaction (or our counterparty spent all the outputs @@ -950,10 +1071,12 @@ impl OnchainTxHandler { // ANTI_REORG_DELAY and clean the RBF tracking map. if is_claim_subset_of_tx { clean_claim_request_after_safety_delay!(); - } else { // If false, generate new claim request with update outpoint set + } else { + // If false, generate new claim request with update outpoint set let mut at_least_one_drop = false; for input in tx.input.iter() { - if let Some(package) = request.split_package(&input.previous_output) { + if let Some(package) = request.split_package(&input.previous_output) + { claimed_outputs_material.push(package); at_least_one_drop = true; } @@ -971,9 +1094,13 @@ impl OnchainTxHandler { // input(s) that already have a confirmed spend. If such spend is // reorged out of the chain, then we'll attempt to re-spend the // inputs once we see it. - #[cfg(debug_assertions)] { - let existing = self.pending_claim_events.iter() - .filter(|entry| entry.0 == *claim_id).count(); + #[cfg(debug_assertions)] + { + let existing = self + .pending_claim_events + .iter() + .filter(|entry| entry.0 == *claim_id) + .count(); assert!(existing == 0 || existing == 1); } self.pending_claim_events.retain(|entry| entry.0 != *claim_id); @@ -1013,19 +1140,26 @@ impl OnchainTxHandler { outpoint, log_bytes!(claim_id.0)); self.claimable_outpoints.remove(outpoint); } - #[cfg(debug_assertions)] { - let num_existing = self.pending_claim_events.iter() - .filter(|entry| entry.0 == claim_id).count(); + #[cfg(debug_assertions)] + { + let num_existing = self + .pending_claim_events + .iter() + .filter(|entry| entry.0 == claim_id) + .count(); assert!(num_existing == 0 || num_existing == 1); } self.pending_claim_events.retain(|(id, _)| *id != claim_id); } }, OnchainEvent::ContentiousOutpoint { package } => { - log_debug!(logger, "Removing claim tracking due to maturation of claim tx for outpoints:"); + log_debug!( + logger, + "Removing claim tracking due to maturation of claim tx for outpoints:" + ); log_debug!(logger, " {:?}", package.outpoints()); self.claimable_outpoints.remove(package.outpoints()[0]); - } + }, } } else { self.onchain_events_awaiting_threshold_conf.push(entry); @@ -1047,13 +1181,22 @@ impl OnchainTxHandler { for (claim_id, request) in bump_candidates.iter() { if let Some((new_timer, new_feerate, bump_claim)) = self.generate_claim( - cur_height, &request, &FeerateStrategy::ForceBump, conf_target, destination_script, - &*fee_estimator, &*logger, + cur_height, + &request, + &FeerateStrategy::ForceBump, + conf_target, + destination_script, + &*fee_estimator, + &*logger, ) { match bump_claim { OnchainClaim::Tx(bump_tx) => { if bump_tx.is_fully_signed() { - log_info!(logger, "Broadcasting RBF-bumped onchain {}", log_tx!(bump_tx.0)); + log_info!( + logger, + "Broadcasting RBF-bumped onchain {}", + log_tx!(bump_tx.0) + ); broadcaster.broadcast_transactions(&[&bump_tx.0]); } else { log_info!(logger, "Waiting for signature of RBF-bumped unsigned onchain transaction {}", @@ -1061,10 +1204,18 @@ impl OnchainTxHandler { } }, OnchainClaim::Event(claim_event) => { - log_info!(logger, "Yielding RBF-bumped onchain event to spend inputs {:?}", request.outpoints()); - #[cfg(debug_assertions)] { - let num_existing = self.pending_claim_events.iter(). - filter(|entry| entry.0 == *claim_id).count(); + log_info!( + logger, + "Yielding RBF-bumped onchain event to spend inputs {:?}", + request.outpoints() + ); + #[cfg(debug_assertions)] + { + let num_existing = self + .pending_claim_events + .iter() + .filter(|entry| entry.0 == *claim_id) + .count(); assert!(num_existing == 0 || num_existing == 1); } self.pending_claim_events.retain(|event| event.0 != *claim_id); @@ -1080,13 +1231,8 @@ impl OnchainTxHandler { } pub(super) fn transaction_unconfirmed( - &mut self, - txid: &Txid, - broadcaster: B, - conf_target: ConfirmationTarget, - destination_script: &Script, - fee_estimator: &LowerBoundedFeeEstimator, - logger: &L, + &mut self, txid: &Txid, broadcaster: B, conf_target: ConfirmationTarget, + destination_script: &Script, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -1101,7 +1247,12 @@ impl OnchainTxHandler { if let Some(height) = height { self.block_disconnected( - height, broadcaster, conf_target, destination_script, fee_estimator, logger, + height, + broadcaster, + conf_target, + destination_script, + fee_estimator, + logger, ); } } @@ -1109,9 +1260,9 @@ impl OnchainTxHandler { pub(super) fn block_disconnected( &mut self, height: u32, broadcaster: B, conf_target: ConfirmationTarget, destination_script: &Script, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, - ) - where B::Target: BroadcasterInterface, - F::Target: FeeEstimator, + ) where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, { let mut bump_candidates = new_hash_map(); let onchain_events_awaiting_threshold_conf = @@ -1122,8 +1273,12 @@ impl OnchainTxHandler { //- resurect outpoint back in its claimable set and regenerate tx match entry.event { OnchainEvent::ContentiousOutpoint { package } => { - if let Some(pending_claim) = self.claimable_outpoints.get(package.outpoints()[0]) { - if let Some(request) = self.pending_claim_requests.get_mut(&pending_claim.0) { + if let Some(pending_claim) = + self.claimable_outpoints.get(package.outpoints()[0]) + { + if let Some(request) = + self.pending_claim_requests.get_mut(&pending_claim.0) + { assert!(request.merge_package(package, height).is_ok()); // Using a HashMap guarantee us than if we have multiple outpoints getting // resurrected only one bump claim tx is going to be broadcast @@ -1141,8 +1296,13 @@ impl OnchainTxHandler { // `height` is the height being disconnected, so our `current_height` is 1 lower. let current_height = height - 1; if let Some((new_timer, new_feerate, bump_claim)) = self.generate_claim( - current_height, &request, &FeerateStrategy::ForceBump, conf_target, - destination_script, fee_estimator, logger + current_height, + &request, + &FeerateStrategy::ForceBump, + conf_target, + destination_script, + fee_estimator, + logger, ) { request.set_timer(new_timer); request.set_feerate(new_feerate); @@ -1152,14 +1312,26 @@ impl OnchainTxHandler { log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx.0)); broadcaster.broadcast_transactions(&[&bump_tx.0]); } else { - log_info!(logger, "Waiting for signature of unsigned onchain transaction {}", bump_tx.0.compute_txid()); + log_info!( + logger, + "Waiting for signature of unsigned onchain transaction {}", + bump_tx.0.compute_txid() + ); } }, OnchainClaim::Event(claim_event) => { - log_info!(logger, "Yielding onchain event after reorg to spend inputs {:?}", request.outpoints()); - #[cfg(debug_assertions)] { - let num_existing = self.pending_claim_events.iter() - .filter(|entry| entry.0 == *_claim_id).count(); + log_info!( + logger, + "Yielding onchain event after reorg to spend inputs {:?}", + request.outpoints() + ); + #[cfg(debug_assertions)] + { + let num_existing = self + .pending_claim_events + .iter() + .filter(|entry| entry.0 == *_claim_id) + .count(); assert!(num_existing == 0 || num_existing == 1); } self.pending_claim_events.retain(|event| event.0 != *_claim_id); @@ -1174,11 +1346,14 @@ impl OnchainTxHandler { //TODO: if we implement cross-block aggregated claim transaction we need to refresh set of outpoints and regenerate tx but // right now if one of the outpoint get disconnected, just erase whole pending claim request. let mut remove_request = Vec::new(); - self.claimable_outpoints.retain(|_, ref v| + self.claimable_outpoints.retain(|_, ref v| { if v.1 >= height { - remove_request.push(v.0.clone()); - false - } else { true }); + remove_request.push(v.0.clone()); + false + } else { + true + } + }); for req in remove_request { self.pending_claim_requests.remove(&req); } @@ -1189,7 +1364,8 @@ impl OnchainTxHandler { } pub(crate) fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option)> { - let mut txids: Vec<(Txid, u32, Option)> = self.onchain_events_awaiting_threshold_conf + let mut txids: Vec<(Txid, u32, Option)> = self + .onchain_events_awaiting_threshold_conf .iter() .map(|entry| (entry.txid, entry.height, entry.block_hash)) .collect(); @@ -1300,15 +1476,13 @@ mod tests { for i in 0..3 { let preimage = PaymentPreimage([i; 32]); let hash = PaymentHash(Sha256::hash(&preimage.0[..]).to_byte_array()); - nondust_htlcs.push( - HTLCOutputInCommitment { - offered: true, - amount_msat: 10000, - cltv_expiry: i as u32, - payment_hash: hash, - transaction_output_index: Some(i as u32), - } - ); + nondust_htlcs.push(HTLCOutputInCommitment { + offered: true, + amount_msat: 10000, + cltv_expiry: i as u32, + payment_hash: hash, + transaction_output_index: Some(i as u32), + }); } let holder_commit = HolderCommitmentTransaction::dummy(1000000, nondust_htlcs); let destination_script = ScriptBuf::new(); @@ -1338,7 +1512,9 @@ mod tests { let holder_commit = tx_handler.current_holder_commitment_tx(); let holder_commit_txid = holder_commit.trust().txid(); let mut requests = Vec::new(); - for (htlc, counterparty_sig) in holder_commit.nondust_htlcs().iter().zip(holder_commit.counterparty_htlc_sigs.iter()) { + for (htlc, counterparty_sig) in + holder_commit.nondust_htlcs().iter().zip(holder_commit.counterparty_htlc_sigs.iter()) + { requests.push(PackageTemplate::build_package( holder_commit_txid, htlc.transaction_output_index.unwrap(), diff --git a/lightning/src/chain/package.rs b/lightning/src/chain/package.rs index a4e4c8d4a38..ab7eee21218 100644 --- a/lightning/src/chain/package.rs +++ b/lightning/src/chain/package.rs @@ -11,36 +11,38 @@ //! packages are attached metadata, guiding their aggregable or fee-bumping re-schedule. This file //! also includes witness weight computation and fee computation methods. - -use bitcoin::{Sequence, Witness}; use bitcoin::amount::Amount; use bitcoin::constants::WITNESS_SCALE_FACTOR; +use bitcoin::hash_types::Txid; use bitcoin::locktime::absolute::LockTime; -use bitcoin::transaction::{TxOut,TxIn, Transaction}; -use bitcoin::transaction::OutPoint as BitcoinOutPoint; use bitcoin::script::{Script, ScriptBuf}; -use bitcoin::hash_types::Txid; -use bitcoin::secp256k1::{SecretKey, PublicKey}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::sighash::EcdsaSighashType; +use bitcoin::transaction::OutPoint as BitcoinOutPoint; use bitcoin::transaction::Version; +use bitcoin::transaction::{Transaction, TxIn, TxOut}; +use bitcoin::{Sequence, Witness}; -use crate::sign::{ChannelDerivationParameters, HTLCDescriptor}; -use crate::types::payment::PaymentPreimage; +use crate::chain::chaininterface::{ + compute_feerate_sat_per_1000_weight, ConfirmationTarget, FeeEstimator, + FEERATE_FLOOR_SATS_PER_KW, INCREMENTAL_RELAY_FEE_SAT_PER_1000_WEIGHT, +}; +use crate::chain::channelmonitor::COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; +use crate::chain::onchaintx::{FeerateStrategy, OnchainTxHandler}; +use crate::chain::transaction::MaybeSignedTransaction; use crate::ln::chan_utils::{ - self, ChannelTransactionParameters, HolderCommitmentTransaction, TxCreationKeys, - HTLCOutputInCommitment, + self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction, + TxCreationKeys, }; -use crate::types::features::ChannelTypeFeatures; use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint}; use crate::ln::channelmanager::MIN_CLTV_EXPIRY_DELTA; use crate::ln::msgs::DecodeError; -use crate::chain::channelmonitor::COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; -use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, INCREMENTAL_RELAY_FEE_SAT_PER_1000_WEIGHT, compute_feerate_sat_per_1000_weight, FEERATE_FLOOR_SATS_PER_KW}; -use crate::chain::transaction::MaybeSignedTransaction; use crate::sign::ecdsa::EcdsaChannelSigner; -use crate::chain::onchaintx::{FeerateStrategy, OnchainTxHandler}; +use crate::sign::{ChannelDerivationParameters, HTLCDescriptor}; +use crate::types::features::ChannelTypeFeatures; +use crate::types::payment::PaymentPreimage; use crate::util::logger::Logger; -use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable, RequiredWrapper}; +use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, Writeable, Writer}; use crate::io; use core::cmp; @@ -51,45 +53,64 @@ use crate::prelude::*; use super::chaininterface::LowerBoundedFeeEstimator; -const MAX_ALLOC_SIZE: usize = 64*1024; - +const MAX_ALLOC_SIZE: usize = 64 * 1024; pub(crate) fn weight_revoked_offered_htlc(channel_type_features: &ChannelTypeFeatures) -> u64 { // number_of_witness_elements + sig_length + revocation_sig + pubkey_length + revocationpubkey + witness_script_length + witness_script const WEIGHT_REVOKED_OFFERED_HTLC: u64 = 1 + 1 + 73 + 1 + 33 + 1 + 133; const WEIGHT_REVOKED_OFFERED_HTLC_ANCHORS: u64 = WEIGHT_REVOKED_OFFERED_HTLC + 3; // + OP_1 + OP_CSV + OP_DROP - if channel_type_features.supports_anchors_zero_fee_htlc_tx() { WEIGHT_REVOKED_OFFERED_HTLC_ANCHORS } else { WEIGHT_REVOKED_OFFERED_HTLC } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + WEIGHT_REVOKED_OFFERED_HTLC_ANCHORS + } else { + WEIGHT_REVOKED_OFFERED_HTLC + } } pub(crate) fn weight_revoked_received_htlc(channel_type_features: &ChannelTypeFeatures) -> u64 { // number_of_witness_elements + sig_length + revocation_sig + pubkey_length + revocationpubkey + witness_script_length + witness_script - const WEIGHT_REVOKED_RECEIVED_HTLC: u64 = 1 + 1 + 73 + 1 + 33 + 1 + 139; + const WEIGHT_REVOKED_RECEIVED_HTLC: u64 = 1 + 1 + 73 + 1 + 33 + 1 + 139; const WEIGHT_REVOKED_RECEIVED_HTLC_ANCHORS: u64 = WEIGHT_REVOKED_RECEIVED_HTLC + 3; // + OP_1 + OP_CSV + OP_DROP - if channel_type_features.supports_anchors_zero_fee_htlc_tx() { WEIGHT_REVOKED_RECEIVED_HTLC_ANCHORS } else { WEIGHT_REVOKED_RECEIVED_HTLC } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + WEIGHT_REVOKED_RECEIVED_HTLC_ANCHORS + } else { + WEIGHT_REVOKED_RECEIVED_HTLC + } } pub(crate) fn weight_offered_htlc(channel_type_features: &ChannelTypeFeatures) -> u64 { // number_of_witness_elements + sig_length + counterpartyhtlc_sig + preimage_length + preimage + witness_script_length + witness_script const WEIGHT_OFFERED_HTLC: u64 = 1 + 1 + 73 + 1 + 32 + 1 + 133; const WEIGHT_OFFERED_HTLC_ANCHORS: u64 = WEIGHT_OFFERED_HTLC + 3; // + OP_1 + OP_CSV + OP_DROP - if channel_type_features.supports_anchors_zero_fee_htlc_tx() { WEIGHT_OFFERED_HTLC_ANCHORS } else { WEIGHT_OFFERED_HTLC } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + WEIGHT_OFFERED_HTLC_ANCHORS + } else { + WEIGHT_OFFERED_HTLC + } } pub(crate) fn weight_received_htlc(channel_type_features: &ChannelTypeFeatures) -> u64 { // number_of_witness_elements + sig_length + counterpartyhtlc_sig + empty_vec_length + empty_vec + witness_script_length + witness_script const WEIGHT_RECEIVED_HTLC: u64 = 1 + 1 + 73 + 1 + 1 + 1 + 139; const WEIGHT_RECEIVED_HTLC_ANCHORS: u64 = WEIGHT_RECEIVED_HTLC + 3; // + OP_1 + OP_CSV + OP_DROP - if channel_type_features.supports_anchors_zero_fee_htlc_tx() { WEIGHT_RECEIVED_HTLC_ANCHORS } else { WEIGHT_RECEIVED_HTLC } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + WEIGHT_RECEIVED_HTLC_ANCHORS + } else { + WEIGHT_RECEIVED_HTLC + } } /// Verifies deserializable channel type features -pub(crate) fn verify_channel_type_features(channel_type_features: &Option, additional_permitted_features: Option<&ChannelTypeFeatures>) -> Result<(), DecodeError> { +pub(crate) fn verify_channel_type_features( + channel_type_features: &Option, + additional_permitted_features: Option<&ChannelTypeFeatures>, +) -> Result<(), DecodeError> { if let Some(features) = channel_type_features.as_ref() { if features.requires_unknown_bits() { return Err(DecodeError::UnknownRequiredFeature); } - let mut supported_feature_set = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + let mut supported_feature_set = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); supported_feature_set.set_scid_privacy_required(); supported_feature_set.set_zero_conf_required(); @@ -157,7 +178,11 @@ impl RevokedOutput { weight: WEIGHT_REVOKED_OUTPUT, amount, on_counterparty_tx_csv, - is_counterparty_balance_on_anchors: if is_counterparty_balance_on_anchors { Some(()) } else { None }, + is_counterparty_balance_on_anchors: if is_counterparty_balance_on_anchors { + Some(()) + } else { + None + }, channel_parameters: Some(channel_parameters), } } @@ -276,7 +301,10 @@ impl CounterpartyOfferedHTLCOutput { impl Writeable for CounterpartyOfferedHTLCOutput { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let legacy_deserialization_prevention_marker = chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features(&self.channel_type_features); + let legacy_deserialization_prevention_marker = + chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features( + &self.channel_type_features, + ); write_tlv_fields!(writer, { (0, self.per_commitment_point, required), (2, self.counterparty_delayed_payment_base_key, required), @@ -368,7 +396,10 @@ impl CounterpartyReceivedHTLCOutput { impl Writeable for CounterpartyReceivedHTLCOutput { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let legacy_deserialization_prevention_marker = chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features(&self.channel_type_features); + let legacy_deserialization_prevention_marker = + chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features( + &self.channel_type_features, + ); write_tlv_fields!(writer, { (0, self.per_commitment_point, required), (2, self.counterparty_delayed_payment_base_key, required), @@ -436,13 +467,20 @@ pub(crate) struct HolderHTLCOutput { impl HolderHTLCOutput { pub(crate) fn build(htlc_descriptor: HTLCDescriptor) -> Self { let amount_msat = htlc_descriptor.htlc.amount_msat; - let channel_type_features = htlc_descriptor.channel_derivation_parameters - .transaction_parameters.channel_type_features.clone(); + let channel_type_features = htlc_descriptor + .channel_derivation_parameters + .transaction_parameters + .channel_type_features + .clone(); Self { preimage: if htlc_descriptor.htlc.offered { None } else { - Some(htlc_descriptor.preimage.expect("Preimage required for accepted holder HTLC claim")) + Some( + htlc_descriptor + .preimage + .expect("Preimage required for accepted holder HTLC claim"), + ) }, amount_msat, cltv_expiry: if htlc_descriptor.htlc.offered { @@ -471,10 +509,12 @@ impl HolderHTLCOutput { return None; } - let (htlc, counterparty_sig) = - trusted_tx.nondust_htlcs().iter().zip(holder_commitment.counterparty_htlc_sigs.iter()) - .find(|(htlc, _)| htlc.transaction_output_index.unwrap() == outp.vout) - .unwrap(); + let (htlc, counterparty_sig) = trusted_tx + .nondust_htlcs() + .iter() + .zip(holder_commitment.counterparty_htlc_sigs.iter()) + .find(|(htlc, _)| htlc.transaction_output_index.unwrap() == outp.vout) + .unwrap(); Some(HTLCDescriptor { channel_derivation_parameters: ChannelDerivationParameters { @@ -493,38 +533,54 @@ impl HolderHTLCOutput { }; // Check if the HTLC spends from the current holder commitment or the previous one otherwise. - get_htlc_descriptor(onchain_tx_handler.current_holder_commitment_tx()) - .or_else(|| onchain_tx_handler.prev_holder_commitment_tx().and_then(|c| get_htlc_descriptor(c))) + get_htlc_descriptor(onchain_tx_handler.current_holder_commitment_tx()).or_else(|| { + onchain_tx_handler.prev_holder_commitment_tx().and_then(|c| get_htlc_descriptor(c)) + }) } pub(crate) fn get_maybe_signed_htlc_tx( &self, onchain_tx_handler: &mut OnchainTxHandler, outp: &::bitcoin::OutPoint, ) -> Option { let htlc_descriptor = self.get_htlc_descriptor(onchain_tx_handler, outp)?; - let channel_parameters = &htlc_descriptor.channel_derivation_parameters.transaction_parameters; + let channel_parameters = + &htlc_descriptor.channel_derivation_parameters.transaction_parameters; let directed_parameters = channel_parameters.as_holder_broadcastable(); let keys = TxCreationKeys::from_channel_static_keys( - &htlc_descriptor.per_commitment_point, directed_parameters.broadcaster_pubkeys(), - directed_parameters.countersignatory_pubkeys(), &onchain_tx_handler.secp_ctx, + &htlc_descriptor.per_commitment_point, + directed_parameters.broadcaster_pubkeys(), + directed_parameters.countersignatory_pubkeys(), + &onchain_tx_handler.secp_ctx, ); let mut htlc_tx = chan_utils::build_htlc_transaction( - &htlc_descriptor.commitment_txid, htlc_descriptor.feerate_per_kw, - directed_parameters.contest_delay(), &htlc_descriptor.htlc, - &channel_parameters.channel_type_features, &keys.broadcaster_delayed_payment_key, - &keys.revocation_key + &htlc_descriptor.commitment_txid, + htlc_descriptor.feerate_per_kw, + directed_parameters.contest_delay(), + &htlc_descriptor.htlc, + &channel_parameters.channel_type_features, + &keys.broadcaster_delayed_payment_key, + &keys.revocation_key, ); if let Ok(htlc_sig) = onchain_tx_handler.signer.sign_holder_htlc_transaction( - &htlc_tx, 0, &htlc_descriptor, &onchain_tx_handler.secp_ctx, + &htlc_tx, + 0, + &htlc_descriptor, + &onchain_tx_handler.secp_ctx, ) { let htlc_redeem_script = chan_utils::get_htlc_redeemscript_with_explicit_keys( - &htlc_descriptor.htlc, &channel_parameters.channel_type_features, - &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key, + &htlc_descriptor.htlc, + &channel_parameters.channel_type_features, + &keys.broadcaster_htlc_key, + &keys.countersignatory_htlc_key, + &keys.revocation_key, ); htlc_tx.input[0].witness = chan_utils::build_htlc_input_witness( - &htlc_sig, &htlc_descriptor.counterparty_sig, &htlc_descriptor.preimage, - &htlc_redeem_script, &channel_parameters.channel_type_features, + &htlc_sig, + &htlc_descriptor.counterparty_sig, + &htlc_descriptor.preimage, + &htlc_redeem_script, + &channel_parameters.channel_type_features, ); } @@ -534,7 +590,10 @@ impl HolderHTLCOutput { impl Writeable for HolderHTLCOutput { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let legacy_deserialization_prevention_marker = chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features(&self.channel_type_features); + let legacy_deserialization_prevention_marker = + chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features( + &self.channel_type_features, + ); write_tlv_fields!(writer, { (0, self.amount_msat, required), (2, self.cltv_expiry, required), @@ -593,10 +652,10 @@ pub(crate) struct HolderFundingOutput { pub(crate) channel_parameters: Option, } - impl HolderFundingOutput { pub(crate) fn build( - commitment_tx: HolderCommitmentTransaction, channel_parameters: ChannelTransactionParameters, + commitment_tx: HolderCommitmentTransaction, + channel_parameters: ChannelTransactionParameters, ) -> Self { let funding_redeemscript = channel_parameters.make_funding_redeemscript(); let funding_amount_sats = channel_parameters.channel_value_satoshis; @@ -613,25 +672,27 @@ impl HolderFundingOutput { pub(crate) fn get_maybe_signed_commitment_tx( &self, onchain_tx_handler: &mut OnchainTxHandler, ) -> MaybeSignedTransaction { - let channel_parameters = self.channel_parameters.as_ref() - .unwrap_or(onchain_tx_handler.channel_parameters()); - let commitment_tx = self.commitment_tx.as_ref() + let channel_parameters = + self.channel_parameters.as_ref().unwrap_or(onchain_tx_handler.channel_parameters()); + let commitment_tx = self + .commitment_tx + .as_ref() .unwrap_or(onchain_tx_handler.current_holder_commitment_tx()); - let maybe_signed_tx = onchain_tx_handler.signer + let maybe_signed_tx = onchain_tx_handler + .signer .sign_holder_commitment(channel_parameters, commitment_tx, &onchain_tx_handler.secp_ctx) - .map(|holder_sig| { - commitment_tx.add_holder_sig(&self.funding_redeemscript, holder_sig) - }) - .unwrap_or_else(|_| { - commitment_tx.trust().built_transaction().transaction.clone() - }); + .map(|holder_sig| commitment_tx.add_holder_sig(&self.funding_redeemscript, holder_sig)) + .unwrap_or_else(|_| commitment_tx.trust().built_transaction().transaction.clone()); MaybeSignedTransaction(maybe_signed_tx) } } impl Writeable for HolderFundingOutput { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let legacy_deserialization_prevention_marker = chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features(&self.channel_type_features); + let legacy_deserialization_prevention_marker = + chan_utils::legacy_deserialization_prevention_marker_for_channel_type_features( + &self.channel_type_features, + ); write_tlv_fields!(writer, { (0, self.funding_redeemscript, required), (1, self.channel_type_features, required), @@ -695,8 +756,12 @@ impl PackageSolvingData { let amt = match self { PackageSolvingData::RevokedOutput(ref outp) => outp.amount.to_sat(), PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.amount, - PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000, - PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000, + PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => { + outp.htlc.amount_msat / 1000 + }, + PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { + outp.htlc.amount_msat / 1000 + }, PackageSolvingData::HolderHTLCOutput(ref outp) => { debug_assert!(outp.channel_type_features.supports_anchors_zero_fee_htlc_tx()); outp.amount_msat / 1000 @@ -704,7 +769,7 @@ impl PackageSolvingData { PackageSolvingData::HolderFundingOutput(ref outp) => { debug_assert!(outp.channel_type_features.supports_anchors_zero_fee_htlc_tx()); outp.funding_amount_sats.unwrap() - } + }, }; amt } @@ -712,8 +777,12 @@ impl PackageSolvingData { match self { PackageSolvingData::RevokedOutput(ref outp) => outp.weight as usize, PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.weight as usize, - PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => weight_offered_htlc(&outp.channel_type_features) as usize, - PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => weight_received_htlc(&outp.channel_type_features) as usize, + PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => { + weight_offered_htlc(&outp.channel_type_features) as usize + }, + PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { + weight_received_htlc(&outp.channel_type_features) as usize + }, PackageSolvingData::HolderHTLCOutput(ref outp) => { debug_assert!(outp.channel_type_features.supports_anchors_zero_fee_htlc_tx()); if outp.preimage.is_none() { @@ -733,28 +802,24 @@ impl PackageSolvingData { /// double-spend. fn is_possibly_from_same_tx_tree(&self, other: &PackageSolvingData) -> bool { match self { - PackageSolvingData::RevokedOutput(_)|PackageSolvingData::RevokedHTLCOutput(_) => { + PackageSolvingData::RevokedOutput(_) | PackageSolvingData::RevokedHTLCOutput(_) => { match other { - PackageSolvingData::RevokedOutput(_)| - PackageSolvingData::RevokedHTLCOutput(_) => true, + PackageSolvingData::RevokedOutput(_) + | PackageSolvingData::RevokedHTLCOutput(_) => true, _ => false, } }, - PackageSolvingData::CounterpartyOfferedHTLCOutput(_)| - PackageSolvingData::CounterpartyReceivedHTLCOutput(_) => { - match other { - PackageSolvingData::CounterpartyOfferedHTLCOutput(_)| - PackageSolvingData::CounterpartyReceivedHTLCOutput(_) => true, - _ => false, - } + PackageSolvingData::CounterpartyOfferedHTLCOutput(_) + | PackageSolvingData::CounterpartyReceivedHTLCOutput(_) => match other { + PackageSolvingData::CounterpartyOfferedHTLCOutput(_) + | PackageSolvingData::CounterpartyReceivedHTLCOutput(_) => true, + _ => false, }, - PackageSolvingData::HolderHTLCOutput(_)| - PackageSolvingData::HolderFundingOutput(_) => { - match other { - PackageSolvingData::HolderHTLCOutput(_)| - PackageSolvingData::HolderFundingOutput(_) => true, - _ => false, - } + PackageSolvingData::HolderHTLCOutput(_) + | PackageSolvingData::HolderFundingOutput(_) => match other { + PackageSolvingData::HolderHTLCOutput(_) + | PackageSolvingData::HolderFundingOutput(_) => true, + _ => false, }, } } @@ -763,33 +828,36 @@ impl PackageSolvingData { let sequence = match self { PackageSolvingData::RevokedOutput(_) => Sequence::ENABLE_RBF_NO_LOCKTIME, PackageSolvingData::RevokedHTLCOutput(_) => Sequence::ENABLE_RBF_NO_LOCKTIME, - PackageSolvingData::CounterpartyOfferedHTLCOutput(outp) => if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { - Sequence::from_consensus(1) - } else { - Sequence::ENABLE_RBF_NO_LOCKTIME + PackageSolvingData::CounterpartyOfferedHTLCOutput(outp) => { + if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { + Sequence::from_consensus(1) + } else { + Sequence::ENABLE_RBF_NO_LOCKTIME + } }, - PackageSolvingData::CounterpartyReceivedHTLCOutput(outp) => if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { - Sequence::from_consensus(1) - } else { - Sequence::ENABLE_RBF_NO_LOCKTIME + PackageSolvingData::CounterpartyReceivedHTLCOutput(outp) => { + if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { + Sequence::from_consensus(1) + } else { + Sequence::ENABLE_RBF_NO_LOCKTIME + } }, _ => { debug_assert!(false, "This should not be reachable by 'untractable' or 'malleable with external funding' packages"); Sequence::ENABLE_RBF_NO_LOCKTIME }, }; - TxIn { - previous_output, - script_sig: ScriptBuf::new(), - sequence, - witness: Witness::new(), - } + TxIn { previous_output, script_sig: ScriptBuf::new(), sequence, witness: Witness::new() } } - fn finalize_input(&self, bumped_tx: &mut Transaction, i: usize, onchain_handler: &mut OnchainTxHandler) -> bool { + fn finalize_input( + &self, bumped_tx: &mut Transaction, i: usize, + onchain_handler: &mut OnchainTxHandler, + ) -> bool { let channel_parameters = onchain_handler.channel_parameters(); match self { PackageSolvingData::RevokedOutput(ref outp) => { - let channel_parameters = outp.channel_parameters.as_ref().unwrap_or(channel_parameters); + let channel_parameters = + outp.channel_parameters.as_ref().unwrap_or(channel_parameters); let directed_parameters = channel_parameters.as_counterparty_broadcastable(); debug_assert_eq!( directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint, @@ -800,21 +868,37 @@ impl PackageSolvingData { outp.counterparty_htlc_base_key, ); let chan_keys = TxCreationKeys::from_channel_static_keys( - &outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(), - directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx, + &outp.per_commitment_point, + directed_parameters.broadcaster_pubkeys(), + directed_parameters.countersignatory_pubkeys(), + &onchain_handler.secp_ctx, + ); + let witness_script = chan_utils::get_revokeable_redeemscript( + &chan_keys.revocation_key, + outp.on_counterparty_tx_csv, + &chan_keys.broadcaster_delayed_payment_key, ); - let witness_script = chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, outp.on_counterparty_tx_csv, &chan_keys.broadcaster_delayed_payment_key); //TODO: should we panic on signer failure ? - if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output(channel_parameters, &bumped_tx, i, outp.amount.to_sat(), &outp.per_commitment_key, &onchain_handler.secp_ctx) { + if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output( + channel_parameters, + &bumped_tx, + i, + outp.amount.to_sat(), + &outp.per_commitment_key, + &onchain_handler.secp_ctx, + ) { let mut ser_sig = sig.serialize_der().to_vec(); ser_sig.push(EcdsaSighashType::All as u8); bumped_tx.input[i].witness.push(ser_sig); - bumped_tx.input[i].witness.push(vec!(1)); + bumped_tx.input[i].witness.push(vec![1]); bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); - } else { return false; } + } else { + return false; + } }, PackageSolvingData::RevokedHTLCOutput(ref outp) => { - let channel_parameters = outp.channel_parameters.as_ref().unwrap_or(channel_parameters); + let channel_parameters = + outp.channel_parameters.as_ref().unwrap_or(channel_parameters); let directed_parameters = channel_parameters.as_counterparty_broadcastable(); debug_assert_eq!( directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint, @@ -825,23 +909,40 @@ impl PackageSolvingData { outp.counterparty_htlc_base_key, ); let chan_keys = TxCreationKeys::from_channel_static_keys( - &outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(), - directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx, + &outp.per_commitment_point, + directed_parameters.broadcaster_pubkeys(), + directed_parameters.countersignatory_pubkeys(), + &onchain_handler.secp_ctx, ); let witness_script = chan_utils::get_htlc_redeemscript( - &outp.htlc, &channel_parameters.channel_type_features, &chan_keys + &outp.htlc, + &channel_parameters.channel_type_features, + &chan_keys, ); //TODO: should we panic on signer failure ? - if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_htlc(channel_parameters, &bumped_tx, i, outp.amount, &outp.per_commitment_key, &outp.htlc, &onchain_handler.secp_ctx) { + if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_htlc( + channel_parameters, + &bumped_tx, + i, + outp.amount, + &outp.per_commitment_key, + &outp.htlc, + &onchain_handler.secp_ctx, + ) { let mut ser_sig = sig.serialize_der().to_vec(); ser_sig.push(EcdsaSighashType::All as u8); bumped_tx.input[i].witness.push(ser_sig); - bumped_tx.input[i].witness.push(chan_keys.revocation_key.to_public_key().serialize().to_vec()); + bumped_tx.input[i] + .witness + .push(chan_keys.revocation_key.to_public_key().serialize().to_vec()); bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); - } else { return false; } + } else { + return false; + } }, PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => { - let channel_parameters = outp.channel_parameters.as_ref().unwrap_or(channel_parameters); + let channel_parameters = + outp.channel_parameters.as_ref().unwrap_or(channel_parameters); let directed_parameters = channel_parameters.as_counterparty_broadcastable(); debug_assert_eq!( directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint, @@ -852,14 +953,26 @@ impl PackageSolvingData { outp.counterparty_htlc_base_key, ); let chan_keys = TxCreationKeys::from_channel_static_keys( - &outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(), - directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx, + &outp.per_commitment_point, + directed_parameters.broadcaster_pubkeys(), + directed_parameters.countersignatory_pubkeys(), + &onchain_handler.secp_ctx, ); let witness_script = chan_utils::get_htlc_redeemscript( - &outp.htlc, &channel_parameters.channel_type_features, &chan_keys, + &outp.htlc, + &channel_parameters.channel_type_features, + &chan_keys, ); - if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(channel_parameters, &bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) { + if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction( + channel_parameters, + &bumped_tx, + i, + &outp.htlc.amount_msat / 1000, + &outp.per_commitment_point, + &outp.htlc, + &onchain_handler.secp_ctx, + ) { let mut ser_sig = sig.serialize_der().to_vec(); ser_sig.push(EcdsaSighashType::All as u8); bumped_tx.input[i].witness.push(ser_sig); @@ -868,7 +981,8 @@ impl PackageSolvingData { } }, PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { - let channel_parameters = outp.channel_parameters.as_ref().unwrap_or(channel_parameters); + let channel_parameters = + outp.channel_parameters.as_ref().unwrap_or(channel_parameters); let directed_parameters = channel_parameters.as_counterparty_broadcastable(); debug_assert_eq!( directed_parameters.broadcaster_pubkeys().delayed_payment_basepoint, @@ -879,14 +993,26 @@ impl PackageSolvingData { outp.counterparty_htlc_base_key, ); let chan_keys = TxCreationKeys::from_channel_static_keys( - &outp.per_commitment_point, directed_parameters.broadcaster_pubkeys(), - directed_parameters.countersignatory_pubkeys(), &onchain_handler.secp_ctx, + &outp.per_commitment_point, + directed_parameters.broadcaster_pubkeys(), + directed_parameters.countersignatory_pubkeys(), + &onchain_handler.secp_ctx, ); let witness_script = chan_utils::get_htlc_redeemscript( - &outp.htlc, &channel_parameters.channel_type_features, &chan_keys, + &outp.htlc, + &channel_parameters.channel_type_features, + &chan_keys, ); - if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(channel_parameters, &bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) { + if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction( + channel_parameters, + &bumped_tx, + i, + &outp.htlc.amount_msat / 1000, + &outp.per_commitment_point, + &outp.htlc, + &onchain_handler.secp_ctx, + ) { let mut ser_sig = sig.serialize_der().to_vec(); ser_sig.push(EcdsaSighashType::All as u8); bumped_tx.input[i].witness.push(ser_sig); @@ -895,27 +1021,35 @@ impl PackageSolvingData { bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); } }, - _ => { panic!("API Error!"); } + _ => { + panic!("API Error!"); + }, } true } - fn get_maybe_finalized_tx(&self, outpoint: &BitcoinOutPoint, onchain_handler: &mut OnchainTxHandler) -> Option { + fn get_maybe_finalized_tx( + &self, outpoint: &BitcoinOutPoint, onchain_handler: &mut OnchainTxHandler, + ) -> Option { match self { PackageSolvingData::HolderHTLCOutput(ref outp) => { debug_assert!(!outp.channel_type_features.supports_anchors_zero_fee_htlc_tx()); outp.get_maybe_signed_htlc_tx(onchain_handler, outpoint) - } + }, PackageSolvingData::HolderFundingOutput(ref outp) => { Some(outp.get_maybe_signed_commitment_tx(onchain_handler)) - } - _ => { panic!("API Error!"); } + }, + _ => { + panic!("API Error!"); + }, } } /// Some output types are locked with CHECKLOCKTIMEVERIFY and the spending transaction must /// have a minimum locktime, which is returned here. fn minimum_locktime(&self) -> Option { match self { - PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => Some(outp.htlc.cltv_expiry), + PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { + Some(outp.htlc.cltv_expiry) + }, _ => None, } } @@ -940,8 +1074,9 @@ impl PackageSolvingData { // also claim the transaction right now) or unpinnable (where only we can claim this // output). We assume we are claiming in a timely manner. match self { - PackageSolvingData::RevokedOutput(RevokedOutput { .. }) => - PackageMalleability::Malleable(AggregationCluster::Unpinnable), + PackageSolvingData::RevokedOutput(RevokedOutput { .. }) => { + PackageMalleability::Malleable(AggregationCluster::Unpinnable) + }, PackageSolvingData::RevokedHTLCOutput(RevokedHTLCOutput { htlc, .. }) => { if htlc.offered { PackageMalleability::Malleable(AggregationCluster::Unpinnable) @@ -949,11 +1084,15 @@ impl PackageSolvingData { PackageMalleability::Malleable(AggregationCluster::Pinnable) } }, - PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => - PackageMalleability::Malleable(AggregationCluster::Unpinnable), - PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => - PackageMalleability::Malleable(AggregationCluster::Pinnable), - PackageSolvingData::HolderHTLCOutput(ref outp) if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() => { + PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => { + PackageMalleability::Malleable(AggregationCluster::Unpinnable) + }, + PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => { + PackageMalleability::Malleable(AggregationCluster::Pinnable) + }, + PackageSolvingData::HolderHTLCOutput(ref outp) + if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() => + { if outp.preimage.is_some() { PackageMalleability::Malleable(AggregationCluster::Unpinnable) } else { @@ -1040,7 +1179,10 @@ impl PackageTemplate { match (self.malleability, other.malleability) { (PackageMalleability::Untractable, _) => false, (_, PackageMalleability::Untractable) => false, - (PackageMalleability::Malleable(self_cluster), PackageMalleability::Malleable(other_cluster)) => { + ( + PackageMalleability::Malleable(self_cluster), + PackageMalleability::Malleable(other_cluster), + ) => { if self.inputs.is_empty() { return false; } @@ -1057,12 +1199,16 @@ impl PackageTemplate { { for i in 0..self.inputs.len() { for j in 0..i { - debug_assert!(self.inputs[i].1.is_possibly_from_same_tx_tree(&self.inputs[j].1)); + debug_assert!(self.inputs[i] + .1 + .is_possibly_from_same_tx_tree(&self.inputs[j].1)); } } for i in 0..other.inputs.len() { for j in 0..i { - assert!(other.inputs[i].1.is_possibly_from_same_tx_tree(&other.inputs[j].1)); + assert!(other.inputs[i] + .1 + .is_possibly_from_same_tx_tree(&other.inputs[j].1)); } } } @@ -1083,18 +1229,22 @@ impl PackageTemplate { // Now check that we only merge packages if they are both unpinnable or both // pinnable. - let self_pinnable = self_cluster == AggregationCluster::Pinnable || - self.counterparty_spendable_height <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; - let other_pinnable = other_cluster == AggregationCluster::Pinnable || - other.counterparty_spendable_height <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; + let self_pinnable = self_cluster == AggregationCluster::Pinnable + || self.counterparty_spendable_height + <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; + let other_pinnable = other_cluster == AggregationCluster::Pinnable + || other.counterparty_spendable_height + <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; if self_pinnable && other_pinnable { return true; } - let self_unpinnable = self_cluster == AggregationCluster::Unpinnable && - self.counterparty_spendable_height > cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; - let other_unpinnable = other_cluster == AggregationCluster::Unpinnable && - other.counterparty_spendable_height > cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; + let self_unpinnable = self_cluster == AggregationCluster::Unpinnable + && self.counterparty_spendable_height + > cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; + let other_unpinnable = other_cluster == AggregationCluster::Unpinnable + && other.counterparty_spendable_height + > cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE; if self_unpinnable && other_unpinnable { return true; } @@ -1123,7 +1273,9 @@ impl PackageTemplate { pub(crate) fn inputs(&self) -> impl ExactSizeIterator { self.inputs.iter().map(|(_, i)| i) } - pub(crate) fn split_package(&mut self, split_outp: &BitcoinOutPoint) -> Option { + pub(crate) fn split_package( + &mut self, split_outp: &BitcoinOutPoint, + ) -> Option { match self.malleability { PackageMalleability::Malleable(cluster) => { let mut split_package = None; @@ -1151,10 +1303,12 @@ impl PackageTemplate { // We should refactor OnchainTxHandler::block_connected to // only test equality on competing claims. return None; - } + }, } } - pub(crate) fn merge_package(&mut self, mut merge_from: PackageTemplate, cur_height: u32) -> Result<(), PackageTemplate> { + pub(crate) fn merge_package( + &mut self, mut merge_from: PackageTemplate, cur_height: u32, + ) -> Result<(), PackageTemplate> { if !self.can_merge_with(&merge_from, cur_height) { return Err(merge_from); } @@ -1184,12 +1338,15 @@ impl PackageTemplate { let signed_locktime = self.inputs.iter().find_map(|(_, outp)| outp.signed_locktime()); #[cfg(debug_assertions)] for (_, outp) in &self.inputs { - debug_assert!(outp.signed_locktime().is_none() || outp.signed_locktime() == signed_locktime); + debug_assert!( + outp.signed_locktime().is_none() || outp.signed_locktime() == signed_locktime + ); } signed_locktime } pub(crate) fn package_locktime(&self, current_height: u32) -> u32 { - let minimum_locktime = self.inputs.iter().filter_map(|(_, outp)| outp.minimum_locktime()).max(); + let minimum_locktime = + self.inputs.iter().filter_map(|(_, outp)| outp.minimum_locktime()).max(); if let Some(signed_locktime) = self.signed_locktime() { debug_assert!(minimum_locktime.is_none()); @@ -1222,34 +1379,43 @@ impl PackageTemplate { PackageSolvingData::HolderHTLCOutput(ref outp) => { debug_assert!(outp.channel_type_features.supports_anchors_zero_fee_htlc_tx()); outp.get_htlc_descriptor(onchain_handler, &previous_output).map(|htlc| { - htlcs.get_or_insert_with(|| Vec::with_capacity(self.inputs.len())).push(htlc); + htlcs + .get_or_insert_with(|| Vec::with_capacity(self.inputs.len())) + .push(htlc); }); - } - _ => debug_assert!(false, "Expected HolderHTLCOutputs to not be aggregated with other input types"), + }, + _ => debug_assert!( + false, + "Expected HolderHTLCOutputs to not be aggregated with other input types" + ), } } htlcs } pub(crate) fn maybe_finalize_malleable_package( &self, current_height: u32, onchain_handler: &mut OnchainTxHandler, value: Amount, - destination_script: ScriptBuf, logger: &L + destination_script: ScriptBuf, logger: &L, ) -> Option { debug_assert!(self.is_malleable()); let mut bumped_tx = Transaction { version: Version::TWO, lock_time: LockTime::from_consensus(self.package_locktime(current_height)), input: vec![], - output: vec![TxOut { - script_pubkey: destination_script, - value, - }], + output: vec![TxOut { script_pubkey: destination_script, value }], }; for (outpoint, outp) in self.inputs.iter() { bumped_tx.input.push(outp.as_tx_input(*outpoint)); } for (i, (outpoint, out)) in self.inputs.iter().enumerate() { - log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout); - if !out.finalize_input(&mut bumped_tx, i, onchain_handler) { continue; } + log_debug!( + logger, + "Adding claiming input for outpoint {}:{}", + outpoint.txid, + outpoint.vout + ); + if !out.finalize_input(&mut bumped_tx, i, onchain_handler) { + continue; + } } Some(MaybeSignedTransaction(bumped_tx)) } @@ -1259,11 +1425,18 @@ impl PackageTemplate { debug_assert!(!self.is_malleable()); if let Some((outpoint, outp)) = self.inputs.first() { if let Some(final_tx) = outp.get_maybe_finalized_tx(outpoint, onchain_handler) { - log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout); + log_debug!( + logger, + "Adding claiming input for outpoint {}:{}", + outpoint.txid, + outpoint.vout + ); return Some(final_tx); } return None; - } else { panic!("API Error: Package must not be inputs empty"); } + } else { + panic!("API Error: Package must not be inputs empty"); + } } /// Gets the next height at which we should fee-bump this package, assuming we can do so and /// the package is last fee-bumped at `current_height`. @@ -1301,10 +1474,8 @@ impl PackageTemplate { PackageSolvingData::CounterpartyOfferedHTLCOutput(outp) => { // Incoming HTLCs being claimed by preimage should be claimed by the time their // CLTV unlocks. - height_timer = cmp::min( - height_timer, - timer_for_target_conf(outp.htlc.cltv_expiry), - ); + height_timer = + cmp::min(height_timer, timer_for_target_conf(outp.htlc.cltv_expiry)); }, PackageSolvingData::HolderHTLCOutput(outp) if outp.preimage.is_some() => { // We have the same deadline here as for `CounterpartyOfferedHTLCOutput`. Note @@ -1351,23 +1522,44 @@ impl PackageTemplate { &self, predicted_weight: u64, dust_limit_sats: u64, feerate_strategy: &FeerateStrategy, conf_target: ConfirmationTarget, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Option<(u64, u64)> - where F::Target: FeeEstimator, + where + F::Target: FeeEstimator, { - debug_assert!(matches!(self.malleability, PackageMalleability::Malleable(..)), - "The package output is fixed for non-malleable packages"); + debug_assert!( + matches!(self.malleability, PackageMalleability::Malleable(..)), + "The package output is fixed for non-malleable packages" + ); let input_amounts = self.package_amount(); - assert!(dust_limit_sats as i64 > 0, "Output script must be broadcastable/have a 'real' dust limit."); + assert!( + dust_limit_sats as i64 > 0, + "Output script must be broadcastable/have a 'real' dust limit." + ); // If old feerate is 0, first iteration of this claim, use normal fee calculation if self.feerate_previous != 0 { if let Some((new_fee, feerate)) = feerate_bump( - predicted_weight, input_amounts, dust_limit_sats, self.feerate_previous, - feerate_strategy, conf_target, fee_estimator, logger, + predicted_weight, + input_amounts, + dust_limit_sats, + self.feerate_previous, + feerate_strategy, + conf_target, + fee_estimator, + logger, ) { return Some((input_amounts.saturating_sub(new_fee), feerate)); } } else { - if let Some((new_fee, feerate)) = compute_fee_from_spent_amounts(input_amounts, predicted_weight, conf_target, fee_estimator, logger) { - return Some((cmp::max(input_amounts as i64 - new_fee as i64, dust_limit_sats as i64) as u64, feerate)); + if let Some((new_fee, feerate)) = compute_fee_from_spent_amounts( + input_amounts, + predicted_weight, + conf_target, + fee_estimator, + logger, + ) { + return Some(( + cmp::max(input_amounts as i64 - new_fee as i64, dust_limit_sats as i64) as u64, + feerate, + )); } } None @@ -1377,27 +1569,35 @@ impl PackageTemplate { pub(crate) fn compute_package_feerate( &self, fee_estimator: &LowerBoundedFeeEstimator, conf_target: ConfirmationTarget, feerate_strategy: &FeerateStrategy, - ) -> u32 where F::Target: FeeEstimator { + ) -> u32 + where + F::Target: FeeEstimator, + { let feerate_estimate = fee_estimator.bounded_sat_per_1000_weight(conf_target); if self.feerate_previous != 0 { let previous_feerate = self.feerate_previous.try_into().unwrap_or(u32::max_value()); match feerate_strategy { FeerateStrategy::RetryPrevious => previous_feerate, - FeerateStrategy::HighestOfPreviousOrNew => cmp::max(previous_feerate, feerate_estimate), - FeerateStrategy::ForceBump => if feerate_estimate > previous_feerate { - feerate_estimate - } else { - // Our fee estimate has decreased, but our transaction remains unconfirmed after - // using our previous fee estimate. This may point to an unreliable fee estimator, - // so we choose to bump our previous feerate by 25%, making sure we don't use a - // lower feerate or overpay by a large margin by limiting it to 5x the new fee - // estimate. - let previous_feerate = self.feerate_previous.try_into().unwrap_or(u32::max_value()); - let mut new_feerate = previous_feerate.saturating_add(previous_feerate / 4); - if new_feerate > feerate_estimate * 5 { - new_feerate = cmp::max(feerate_estimate * 5, previous_feerate); + FeerateStrategy::HighestOfPreviousOrNew => { + cmp::max(previous_feerate, feerate_estimate) + }, + FeerateStrategy::ForceBump => { + if feerate_estimate > previous_feerate { + feerate_estimate + } else { + // Our fee estimate has decreased, but our transaction remains unconfirmed after + // using our previous fee estimate. This may point to an unreliable fee estimator, + // so we choose to bump our previous feerate by 25%, making sure we don't use a + // lower feerate or overpay by a large margin by limiting it to 5x the new fee + // estimate. + let previous_feerate = + self.feerate_previous.try_into().unwrap_or(u32::max_value()); + let mut new_feerate = previous_feerate.saturating_add(previous_feerate / 4); + if new_feerate > feerate_estimate * 5 { + new_feerate = cmp::max(feerate_estimate * 5, previous_feerate); + } + new_feerate } - new_feerate }, } } else { @@ -1408,14 +1608,24 @@ impl PackageTemplate { /// Determines whether a package contains an input which must have additional external inputs /// attached to help the spending transaction reach confirmation. pub(crate) fn requires_external_funding(&self) -> bool { - self.inputs.iter().find(|input| match input.1 { - PackageSolvingData::HolderFundingOutput(ref outp) => outp.channel_type_features.supports_anchors_zero_fee_htlc_tx(), - PackageSolvingData::HolderHTLCOutput(ref outp) => outp.channel_type_features.supports_anchors_zero_fee_htlc_tx(), - _ => false, - }).is_some() + self.inputs + .iter() + .find(|input| match input.1 { + PackageSolvingData::HolderFundingOutput(ref outp) => { + outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() + }, + PackageSolvingData::HolderHTLCOutput(ref outp) => { + outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() + }, + _ => false, + }) + .is_some() } - pub (crate) fn build_package(txid: Txid, vout: u32, input_solving_data: PackageSolvingData, counterparty_spendable_height: u32) -> Self { + pub(crate) fn build_package( + txid: Txid, vout: u32, input_solving_data: PackageSolvingData, + counterparty_spendable_height: u32, + ) -> Self { let malleability = PackageSolvingData::map_output_type_flags(&input_solving_data); let inputs = vec![(BitcoinOutPoint { txid, vout }, input_solving_data)]; PackageTemplate { @@ -1449,7 +1659,8 @@ impl Writeable for PackageTemplate { impl Readable for PackageTemplate { fn read(reader: &mut R) -> Result { let inputs_count = ::read(reader)?; - let mut inputs: Vec<(BitcoinOutPoint, PackageSolvingData)> = Vec::with_capacity(cmp::min(inputs_count as usize, MAX_ALLOC_SIZE / 128)); + let mut inputs: Vec<(BitcoinOutPoint, PackageSolvingData)> = + Vec::with_capacity(cmp::min(inputs_count as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..inputs_count { let outpoint = Readable::read(reader)?; let rev_outp = Readable::read(reader)?; @@ -1457,7 +1668,9 @@ impl Readable for PackageTemplate { } let malleability = if let Some((_, lead_input)) = inputs.first() { PackageSolvingData::map_output_type_flags(&lead_input) - } else { return Err(DecodeError::InvalidValue); }; + } else { + return Err(DecodeError::InvalidValue); + }; let mut counterparty_spendable_height = 0; let mut feerate_previous = 0; let mut height_timer = None; @@ -1498,12 +1711,17 @@ impl Readable for PackageTemplate { /// fee and the corresponding updated feerate. If fee is under [`FEERATE_FLOOR_SATS_PER_KW`], /// we return nothing. fn compute_fee_from_spent_amounts( - input_amounts: u64, predicted_weight: u64, conf_target: ConfirmationTarget, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + input_amounts: u64, predicted_weight: u64, conf_target: ConfirmationTarget, + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Option<(u64, u64)> - where F::Target: FeeEstimator, +where + F::Target: FeeEstimator, { let sweep_feerate = fee_estimator.bounded_sat_per_1000_weight(conf_target); - let fee_rate = cmp::min(sweep_feerate, compute_feerate_sat_per_1000_weight(input_amounts / 2, predicted_weight)); + let fee_rate = cmp::min( + sweep_feerate, + compute_feerate_sat_per_1000_weight(input_amounts / 2, predicted_weight), + ); let fee = fee_rate as u64 * (predicted_weight) / 1000; // if the fee rate is below the floor, we don't sweep @@ -1534,32 +1752,53 @@ where // If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee... let (new_fee, new_feerate) = if let Some((new_fee, new_feerate)) = - compute_fee_from_spent_amounts(input_amounts, predicted_weight, conf_target, fee_estimator, logger) - { - log_debug!(logger, "Initiating fee rate bump from {} s/kWU ({} s) to {} s/kWU ({} s) using {:?} strategy", previous_feerate, previous_fee, new_feerate, new_fee, feerate_strategy); + compute_fee_from_spent_amounts( + input_amounts, + predicted_weight, + conf_target, + fee_estimator, + logger, + ) { + log_debug!( + logger, + "Initiating fee rate bump from {} s/kWU ({} s) to {} s/kWU ({} s) using {:?} strategy", + previous_feerate, + previous_fee, + new_feerate, + new_fee, + feerate_strategy + ); match feerate_strategy { FeerateStrategy::RetryPrevious => { let previous_fee = previous_feerate * predicted_weight / 1000; (previous_fee, previous_feerate) }, - FeerateStrategy::HighestOfPreviousOrNew => if new_feerate > previous_feerate { - (new_fee, new_feerate) - } else { - let previous_fee = previous_feerate * predicted_weight / 1000; - (previous_fee, previous_feerate) + FeerateStrategy::HighestOfPreviousOrNew => { + if new_feerate > previous_feerate { + (new_fee, new_feerate) + } else { + let previous_fee = previous_feerate * predicted_weight / 1000; + (previous_fee, previous_feerate) + } }, - FeerateStrategy::ForceBump => if new_feerate > previous_feerate { - (new_fee, new_feerate) - } else { - // ...else just increase the previous feerate by 25% (because that's a nice number) - let bumped_feerate = previous_feerate + (previous_feerate / 4); - let bumped_fee = bumped_feerate * predicted_weight / 1000; + FeerateStrategy::ForceBump => { + if new_feerate > previous_feerate { + (new_fee, new_feerate) + } else { + // ...else just increase the previous feerate by 25% (because that's a nice number) + let bumped_feerate = previous_feerate + (previous_feerate / 4); + let bumped_fee = bumped_feerate * predicted_weight / 1000; - (bumped_fee, bumped_feerate) + (bumped_fee, bumped_feerate) + } }, } } else { - log_warn!(logger, "Can't bump new claiming tx, input amount {} is too small", input_amounts); + log_warn!( + logger, + "Can't bump new claiming tx, input amount {} is too small", + input_amounts + ); return None; }; @@ -1578,29 +1817,51 @@ where let new_fee = cmp::max(new_fee, previous_fee + min_relay_fee); if new_fee > naive_new_fee { - log_debug!(logger, "Naive fee bump of {}s does not meet min relay fee requirements of {}s", naive_new_fee - previous_fee, min_relay_fee); + log_debug!( + logger, + "Naive fee bump of {}s does not meet min relay fee requirements of {}s", + naive_new_fee - previous_fee, + min_relay_fee + ); } let remaining_output_amount = input_amounts.saturating_sub(new_fee); if remaining_output_amount < dust_limit_sats { - log_warn!(logger, "Can't bump new claiming tx, output amount {} would end up below dust threshold {}", remaining_output_amount, dust_limit_sats); + log_warn!( + logger, + "Can't bump new claiming tx, output amount {} would end up below dust threshold {}", + remaining_output_amount, + dust_limit_sats + ); return None; } let new_feerate = new_fee * 1000 / predicted_weight; - log_debug!(logger, "Fee rate bumped by {}s from {} s/KWU ({} s) to {} s/KWU ({} s)", new_fee - previous_fee, previous_feerate, previous_fee, new_feerate, new_fee); + log_debug!( + logger, + "Fee rate bumped by {}s from {} s/KWU ({} s) to {} s/KWU ({} s)", + new_fee - previous_fee, + previous_feerate, + previous_fee, + new_feerate, + new_fee + ); Some((new_fee, new_feerate)) } #[cfg(test)] mod tests { - use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageTemplate, PackageSolvingData, RevokedHTLCOutput, RevokedOutput, WEIGHT_REVOKED_OUTPUT, weight_offered_htlc, weight_received_htlc, feerate_bump}; + use crate::chain::package::{ + feerate_bump, weight_offered_htlc, weight_received_htlc, CounterpartyOfferedHTLCOutput, + CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, + PackageTemplate, RevokedHTLCOutput, RevokedOutput, WEIGHT_REVOKED_OUTPUT, + }; use crate::chain::Txid; use crate::ln::chan_utils::{ - ChannelTransactionParameters, HolderCommitmentTransaction, HTLCOutputInCommitment, + ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction, }; - use crate::types::payment::{PaymentPreimage, PaymentHash}; use crate::sign::{ChannelDerivationParameters, HTLCDescriptor}; + use crate::types::payment::{PaymentHash, PaymentPreimage}; use bitcoin::absolute::LockTime; use bitcoin::amount::Amount; @@ -1612,180 +1873,221 @@ mod tests { use bitcoin::hex::FromHex; - use bitcoin::secp256k1::{PublicKey,SecretKey}; - use bitcoin::secp256k1::Secp256k1; - use crate::chain::chaininterface::{ConfirmationTarget, FeeEstimator, FEERATE_FLOOR_SATS_PER_KW, LowerBoundedFeeEstimator}; + use crate::chain::chaininterface::{ + ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator, FEERATE_FLOOR_SATS_PER_KW, + }; use crate::chain::onchaintx::FeerateStrategy; use crate::types::features::ChannelTypeFeatures; use crate::util::test_utils::TestLogger; + use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; fn fake_txid(n: u64) -> Txid { Transaction { version: Version(0), lock_time: LockTime::ZERO, input: vec![], - output: vec![TxOut { - value: Amount::from_sat(n), - script_pubkey: ScriptBuf::new(), - }], - }.compute_txid() + output: vec![TxOut { value: Amount::from_sat(n), script_pubkey: ScriptBuf::new() }], + } + .compute_txid() } macro_rules! dumb_revk_output { - ($is_counterparty_balance_on_anchors: expr) => { - { - let secp_ctx = Secp256k1::new(); - let dumb_scalar = SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap(); - let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); - let channel_parameters = ChannelTransactionParameters::test_dummy(0); - PackageSolvingData::RevokedOutput(RevokedOutput::build( - dumb_point, dumb_scalar, Amount::ZERO, $is_counterparty_balance_on_anchors, - channel_parameters, - )) - } - } + ($is_counterparty_balance_on_anchors: expr) => {{ + let secp_ctx = Secp256k1::new(); + let dumb_scalar = SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap()[..], + ) + .unwrap(); + let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); + let channel_parameters = ChannelTransactionParameters::test_dummy(0); + PackageSolvingData::RevokedOutput(RevokedOutput::build( + dumb_point, + dumb_scalar, + Amount::ZERO, + $is_counterparty_balance_on_anchors, + channel_parameters, + )) + }}; } macro_rules! dumb_revk_htlc_output { - () => { - { - let secp_ctx = Secp256k1::new(); - let dumb_scalar = SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap(); - let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); - let hash = PaymentHash([1; 32]); - let htlc = HTLCOutputInCommitment { offered: false, amount_msat: 1_000_000, cltv_expiry: 0, payment_hash: hash, transaction_output_index: None }; - let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); - channel_parameters.channel_type_features = - ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); - PackageSolvingData::RevokedHTLCOutput(RevokedHTLCOutput::build( - dumb_point, dumb_scalar, htlc, channel_parameters - )) - } - } + () => {{ + let secp_ctx = Secp256k1::new(); + let dumb_scalar = SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap()[..], + ) + .unwrap(); + let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); + let hash = PaymentHash([1; 32]); + let htlc = HTLCOutputInCommitment { + offered: false, + amount_msat: 1_000_000, + cltv_expiry: 0, + payment_hash: hash, + transaction_output_index: None, + }; + let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); + channel_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + PackageSolvingData::RevokedHTLCOutput(RevokedHTLCOutput::build( + dumb_point, + dumb_scalar, + htlc, + channel_parameters, + )) + }}; } macro_rules! dumb_counterparty_received_output { - ($amt: expr, $expiry: expr, $features: expr) => { - { - let secp_ctx = Secp256k1::new(); - let dumb_scalar = SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap(); - let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); - let hash = PaymentHash([1; 32]); - let htlc = HTLCOutputInCommitment { offered: true, amount_msat: $amt, cltv_expiry: $expiry, payment_hash: hash, transaction_output_index: None }; - let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); - channel_parameters.channel_type_features = $features; - PackageSolvingData::CounterpartyReceivedHTLCOutput( - CounterpartyReceivedHTLCOutput::build(dumb_point, htlc, channel_parameters) + ($amt: expr, $expiry: expr, $features: expr) => {{ + let secp_ctx = Secp256k1::new(); + let dumb_scalar = SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", ) - } - } + .unwrap()[..], + ) + .unwrap(); + let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); + let hash = PaymentHash([1; 32]); + let htlc = HTLCOutputInCommitment { + offered: true, + amount_msat: $amt, + cltv_expiry: $expiry, + payment_hash: hash, + transaction_output_index: None, + }; + let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); + channel_parameters.channel_type_features = $features; + PackageSolvingData::CounterpartyReceivedHTLCOutput( + CounterpartyReceivedHTLCOutput::build(dumb_point, htlc, channel_parameters), + ) + }}; } macro_rules! dumb_counterparty_offered_output { - ($amt: expr, $features: expr) => { - { - let secp_ctx = Secp256k1::new(); - let dumb_scalar = SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap(); - let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); - let hash = PaymentHash([1; 32]); - let preimage = PaymentPreimage([2;32]); - let htlc = HTLCOutputInCommitment { offered: false, amount_msat: $amt, cltv_expiry: 0, payment_hash: hash, transaction_output_index: None }; - let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); - channel_parameters.channel_type_features = $features; - PackageSolvingData::CounterpartyOfferedHTLCOutput( - CounterpartyOfferedHTLCOutput::build(dumb_point, preimage, htlc, channel_parameters) + ($amt: expr, $features: expr) => {{ + let secp_ctx = Secp256k1::new(); + let dumb_scalar = SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", ) - } - } + .unwrap()[..], + ) + .unwrap(); + let dumb_point = PublicKey::from_secret_key(&secp_ctx, &dumb_scalar); + let hash = PaymentHash([1; 32]); + let preimage = PaymentPreimage([2; 32]); + let htlc = HTLCOutputInCommitment { + offered: false, + amount_msat: $amt, + cltv_expiry: 0, + payment_hash: hash, + transaction_output_index: None, + }; + let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); + channel_parameters.channel_type_features = $features; + PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build( + dumb_point, + preimage, + htlc, + channel_parameters, + )) + }}; } macro_rules! dumb_accepted_htlc_output { - ($features: expr) => { - { - let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); - channel_parameters.channel_type_features = $features; - let preimage = PaymentPreimage([2;32]); - let htlc = HTLCOutputInCommitment { - offered: false, - amount_msat: 1337000, - cltv_expiry: 420, - payment_hash: PaymentHash::from(preimage), - transaction_output_index: None, - }; - let commitment_tx = HolderCommitmentTransaction::dummy(0, vec![htlc.clone()]); - let trusted_tx = commitment_tx.trust(); - PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build( - HTLCDescriptor { - channel_derivation_parameters: ChannelDerivationParameters { - value_satoshis: channel_parameters.channel_value_satoshis, - keys_id: [0; 32], - transaction_parameters: channel_parameters, - }, - commitment_txid: trusted_tx.txid(), - per_commitment_number: trusted_tx.commitment_number(), - per_commitment_point: trusted_tx.per_commitment_point(), - feerate_per_kw: trusted_tx.feerate_per_kw(), - htlc, - preimage: Some(preimage), - counterparty_sig: commitment_tx.counterparty_htlc_sigs[0].clone(), - }, - )) - } - } + ($features: expr) => {{ + let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); + channel_parameters.channel_type_features = $features; + let preimage = PaymentPreimage([2; 32]); + let htlc = HTLCOutputInCommitment { + offered: false, + amount_msat: 1337000, + cltv_expiry: 420, + payment_hash: PaymentHash::from(preimage), + transaction_output_index: None, + }; + let commitment_tx = HolderCommitmentTransaction::dummy(0, vec![htlc.clone()]); + let trusted_tx = commitment_tx.trust(); + PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build(HTLCDescriptor { + channel_derivation_parameters: ChannelDerivationParameters { + value_satoshis: channel_parameters.channel_value_satoshis, + keys_id: [0; 32], + transaction_parameters: channel_parameters, + }, + commitment_txid: trusted_tx.txid(), + per_commitment_number: trusted_tx.commitment_number(), + per_commitment_point: trusted_tx.per_commitment_point(), + feerate_per_kw: trusted_tx.feerate_per_kw(), + htlc, + preimage: Some(preimage), + counterparty_sig: commitment_tx.counterparty_htlc_sigs[0].clone(), + })) + }}; } macro_rules! dumb_offered_htlc_output { - ($cltv_expiry: expr, $features: expr) => { - { - let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); - channel_parameters.channel_type_features = $features; - let htlc = HTLCOutputInCommitment { - offered: true, - amount_msat: 1337000, - cltv_expiry: $cltv_expiry, - payment_hash: PaymentHash::from(PaymentPreimage([2;32])), - transaction_output_index: None, - }; - let commitment_tx = HolderCommitmentTransaction::dummy(0, vec![htlc.clone()]); - let trusted_tx = commitment_tx.trust(); - PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build( - HTLCDescriptor { - channel_derivation_parameters: ChannelDerivationParameters { - value_satoshis: channel_parameters.channel_value_satoshis, - keys_id: [0; 32], - transaction_parameters: channel_parameters, - }, - commitment_txid: trusted_tx.txid(), - per_commitment_number: trusted_tx.commitment_number(), - per_commitment_point: trusted_tx.per_commitment_point(), - feerate_per_kw: trusted_tx.feerate_per_kw(), - htlc, - preimage: None, - counterparty_sig: commitment_tx.counterparty_htlc_sigs[0].clone(), - }, - )) - } - } + ($cltv_expiry: expr, $features: expr) => {{ + let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); + channel_parameters.channel_type_features = $features; + let htlc = HTLCOutputInCommitment { + offered: true, + amount_msat: 1337000, + cltv_expiry: $cltv_expiry, + payment_hash: PaymentHash::from(PaymentPreimage([2; 32])), + transaction_output_index: None, + }; + let commitment_tx = HolderCommitmentTransaction::dummy(0, vec![htlc.clone()]); + let trusted_tx = commitment_tx.trust(); + PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build(HTLCDescriptor { + channel_derivation_parameters: ChannelDerivationParameters { + value_satoshis: channel_parameters.channel_value_satoshis, + keys_id: [0; 32], + transaction_parameters: channel_parameters, + }, + commitment_txid: trusted_tx.txid(), + per_commitment_number: trusted_tx.commitment_number(), + per_commitment_point: trusted_tx.per_commitment_point(), + feerate_per_kw: trusted_tx.feerate_per_kw(), + htlc, + preimage: None, + counterparty_sig: commitment_tx.counterparty_htlc_sigs[0].clone(), + })) + }}; } macro_rules! dumb_funding_output { () => {{ let commitment_tx = HolderCommitmentTransaction::dummy(0, Vec::new()); let mut channel_parameters = ChannelTransactionParameters::test_dummy(0); - channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key(); + channel_parameters.channel_type_features = + ChannelTypeFeatures::only_static_remote_key(); PackageSolvingData::HolderFundingOutput(HolderFundingOutput::build( - commitment_tx, channel_parameters, + commitment_tx, + channel_parameters, )) - }} + }}; } #[test] fn test_merge_package_untractable_funding_output() { let funding_outp = dumb_funding_output!(); - let htlc_outp = dumb_accepted_htlc_output!(ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); + let htlc_outp = dumb_accepted_htlc_output!( + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); - let mut untractable_package = PackageTemplate::build_package(fake_txid(1), 0, funding_outp.clone(), 0); - let mut malleable_package = PackageTemplate::build_package(fake_txid(2), 0, htlc_outp.clone(), 1100); + let mut untractable_package = + PackageTemplate::build_package(fake_txid(1), 0, funding_outp.clone(), 0); + let mut malleable_package = + PackageTemplate::build_package(fake_txid(2), 0, htlc_outp.clone(), 1100); assert!(!untractable_package.can_merge_with(&malleable_package, 1000)); assert!(untractable_package.merge_package(malleable_package.clone(), 1000).is_err()); @@ -1798,7 +2100,8 @@ mod tests { fn test_merge_empty_package() { let revk_outp = dumb_revk_htlc_output!(); - let mut empty_package = PackageTemplate::build_package(fake_txid(1), 0, revk_outp.clone(), 0); + let mut empty_package = + PackageTemplate::build_package(fake_txid(1), 0, revk_outp.clone(), 0); empty_package.inputs = vec![]; let mut package = PackageTemplate::build_package(fake_txid(1), 1, revk_outp.clone(), 1100); assert!(empty_package.merge_package(package.clone(), 1000).is_err()); @@ -1809,18 +2112,33 @@ mod tests { fn test_merge_package_different_signed_locktimes() { // Malleable HTLC transactions are signed over the locktime, and can't be aggregated with // different locktimes. - let offered_htlc_1 = dumb_offered_htlc_output!(900, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); - let offered_htlc_2 = dumb_offered_htlc_output!(901, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); - let accepted_htlc = dumb_accepted_htlc_output!(ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); + let offered_htlc_1 = dumb_offered_htlc_output!( + 900, + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); + let offered_htlc_2 = dumb_offered_htlc_output!( + 901, + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); + let accepted_htlc = dumb_accepted_htlc_output!( + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); - let mut offered_htlc_1_package = PackageTemplate::build_package(fake_txid(1), 0, offered_htlc_1.clone(), 0); - let mut offered_htlc_2_package = PackageTemplate::build_package(fake_txid(1), 1, offered_htlc_2.clone(), 0); - let mut accepted_htlc_package = PackageTemplate::build_package(fake_txid(1), 2, accepted_htlc.clone(), 1001); + let mut offered_htlc_1_package = + PackageTemplate::build_package(fake_txid(1), 0, offered_htlc_1.clone(), 0); + let mut offered_htlc_2_package = + PackageTemplate::build_package(fake_txid(1), 1, offered_htlc_2.clone(), 0); + let mut accepted_htlc_package = + PackageTemplate::build_package(fake_txid(1), 2, accepted_htlc.clone(), 1001); assert!(!offered_htlc_2_package.can_merge_with(&offered_htlc_1_package, 1000)); - assert!(offered_htlc_2_package.merge_package(offered_htlc_1_package.clone(), 1000).is_err()); + assert!(offered_htlc_2_package + .merge_package(offered_htlc_1_package.clone(), 1000) + .is_err()); assert!(!offered_htlc_1_package.can_merge_with(&offered_htlc_2_package, 1000)); - assert!(offered_htlc_1_package.merge_package(offered_htlc_2_package.clone(), 1000).is_err()); + assert!(offered_htlc_1_package + .merge_package(offered_htlc_2_package.clone(), 1000) + .is_err()); assert!(!accepted_htlc_package.can_merge_with(&offered_htlc_1_package, 1000)); assert!(accepted_htlc_package.merge_package(offered_htlc_1_package.clone(), 1000).is_err()); @@ -1832,15 +2150,35 @@ mod tests { fn test_merge_package_different_effective_locktimes() { // Spends of outputs can have different minimum locktimes, and are not mergeable if they are in the // future. - let old_outp_1 = dumb_counterparty_received_output!(1_000_000, 900, ChannelTypeFeatures::only_static_remote_key()); - let old_outp_2 = dumb_counterparty_received_output!(1_000_000, 901, ChannelTypeFeatures::only_static_remote_key()); - let future_outp_1 = dumb_counterparty_received_output!(1_000_000, 1001, ChannelTypeFeatures::only_static_remote_key()); - let future_outp_2 = dumb_counterparty_received_output!(1_000_000, 1002, ChannelTypeFeatures::only_static_remote_key()); + let old_outp_1 = dumb_counterparty_received_output!( + 1_000_000, + 900, + ChannelTypeFeatures::only_static_remote_key() + ); + let old_outp_2 = dumb_counterparty_received_output!( + 1_000_000, + 901, + ChannelTypeFeatures::only_static_remote_key() + ); + let future_outp_1 = dumb_counterparty_received_output!( + 1_000_000, + 1001, + ChannelTypeFeatures::only_static_remote_key() + ); + let future_outp_2 = dumb_counterparty_received_output!( + 1_000_000, + 1002, + ChannelTypeFeatures::only_static_remote_key() + ); - let old_outp_1_package = PackageTemplate::build_package(fake_txid(1), 0, old_outp_1.clone(), 0); - let old_outp_2_package = PackageTemplate::build_package(fake_txid(1), 1, old_outp_2.clone(), 0); - let future_outp_1_package = PackageTemplate::build_package(fake_txid(1), 2, future_outp_1.clone(), 0); - let future_outp_2_package = PackageTemplate::build_package(fake_txid(1), 3, future_outp_2.clone(), 0); + let old_outp_1_package = + PackageTemplate::build_package(fake_txid(1), 0, old_outp_1.clone(), 0); + let old_outp_2_package = + PackageTemplate::build_package(fake_txid(1), 1, old_outp_2.clone(), 0); + let future_outp_1_package = + PackageTemplate::build_package(fake_txid(1), 2, future_outp_1.clone(), 0); + let future_outp_2_package = + PackageTemplate::build_package(fake_txid(1), 3, future_outp_2.clone(), 0); assert!(old_outp_1_package.can_merge_with(&old_outp_2_package, 1000)); assert!(old_outp_2_package.can_merge_with(&old_outp_1_package, 1000)); @@ -1849,25 +2187,48 @@ mod tests { assert!(!future_outp_1_package.can_merge_with(&future_outp_2_package, 1000)); assert!(!future_outp_2_package.can_merge_with(&future_outp_1_package, 1000)); - assert!(future_outp_1_package.clone().merge_package(future_outp_2_package.clone(), 1000).is_err()); - assert!(future_outp_2_package.clone().merge_package(future_outp_1_package.clone(), 1000).is_err()); + assert!(future_outp_1_package + .clone() + .merge_package(future_outp_2_package.clone(), 1000) + .is_err()); + assert!(future_outp_2_package + .clone() + .merge_package(future_outp_1_package.clone(), 1000) + .is_err()); } #[test] fn test_merge_package_holder_htlc_output_clusters() { // Signed locktimes of 0. - let unpinnable_1 = dumb_accepted_htlc_output!(ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); - let unpinnable_2 = dumb_accepted_htlc_output!(ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); - let considered_pinnable = dumb_accepted_htlc_output!(ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); + let unpinnable_1 = dumb_accepted_htlc_output!( + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); + let unpinnable_2 = dumb_accepted_htlc_output!( + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); + let considered_pinnable = dumb_accepted_htlc_output!( + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); // Signed locktimes of 1000. - let pinnable_1 = dumb_offered_htlc_output!(1000, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); - let pinnable_2 = dumb_offered_htlc_output!(1000, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); + let pinnable_1 = dumb_offered_htlc_output!( + 1000, + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); + let pinnable_2 = dumb_offered_htlc_output!( + 1000, + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); - let mut unpinnable_1_package = PackageTemplate::build_package(fake_txid(1), 0, unpinnable_1.clone(), 1100); - let mut unpinnable_2_package = PackageTemplate::build_package(fake_txid(1), 1, unpinnable_2.clone(), 1100); - let mut considered_pinnable_package = PackageTemplate::build_package(fake_txid(1), 2, considered_pinnable.clone(), 1001); - let mut pinnable_1_package = PackageTemplate::build_package(fake_txid(1), 3, pinnable_1.clone(), 0); - let mut pinnable_2_package = PackageTemplate::build_package(fake_txid(1), 4, pinnable_2.clone(), 0); + let mut unpinnable_1_package = + PackageTemplate::build_package(fake_txid(1), 0, unpinnable_1.clone(), 1100); + let mut unpinnable_2_package = + PackageTemplate::build_package(fake_txid(1), 1, unpinnable_2.clone(), 1100); + let mut considered_pinnable_package = + PackageTemplate::build_package(fake_txid(1), 2, considered_pinnable.clone(), 1001); + let mut pinnable_1_package = + PackageTemplate::build_package(fake_txid(1), 3, pinnable_1.clone(), 0); + let mut pinnable_2_package = + PackageTemplate::build_package(fake_txid(1), 4, pinnable_2.clone(), 0); // Unpinnable with signed locktimes of 0. let unpinnable_cluster = [&mut unpinnable_1_package, &mut unpinnable_2_package]; @@ -1878,7 +2239,11 @@ mod tests { // Pinnable and unpinnable malleable packages are kept separate. A package is considered // unpinnable if it can only be claimed by the counterparty a given amount of time in the // future. - let clusters = [unpinnable_cluster.as_slice(), pinnable_cluster.as_slice(), considered_pinnable_cluster.as_slice()]; + let clusters = [ + unpinnable_cluster.as_slice(), + pinnable_cluster.as_slice(), + considered_pinnable_cluster.as_slice(), + ]; for a in 0..clusters.len() { for b in 0..clusters.len() { @@ -1897,8 +2262,11 @@ mod tests { } let mut packages = vec![ - unpinnable_1_package, unpinnable_2_package, considered_pinnable_package, - pinnable_1_package, pinnable_2_package, + unpinnable_1_package, + unpinnable_2_package, + considered_pinnable_package, + pinnable_1_package, + pinnable_2_package, ]; for i in (1..packages.len()).rev() { for j in 0..i { @@ -1914,13 +2282,24 @@ mod tests { #[test] #[should_panic] fn test_merge_package_different_tx_trees() { - let offered_htlc = dumb_offered_htlc_output!(900, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); - let mut offered_htlc_package = PackageTemplate::build_package(fake_txid(1), 0, offered_htlc.clone(), 0); - let counterparty_received_htlc = dumb_counterparty_received_output!(1_000_000, 900, ChannelTypeFeatures::only_static_remote_key()); - let counterparty_received_htlc_package = PackageTemplate::build_package(fake_txid(2), 0, counterparty_received_htlc.clone(), 0); + let offered_htlc = dumb_offered_htlc_output!( + 900, + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); + let mut offered_htlc_package = + PackageTemplate::build_package(fake_txid(1), 0, offered_htlc.clone(), 0); + let counterparty_received_htlc = dumb_counterparty_received_output!( + 1_000_000, + 900, + ChannelTypeFeatures::only_static_remote_key() + ); + let counterparty_received_htlc_package = + PackageTemplate::build_package(fake_txid(2), 0, counterparty_received_htlc.clone(), 0); assert!(!offered_htlc_package.can_merge_with(&counterparty_received_htlc_package, 1000)); - assert!(offered_htlc_package.merge_package(counterparty_received_htlc_package.clone(), 1000).is_err()); + assert!(offered_htlc_package + .merge_package(counterparty_received_htlc_package.clone(), 1000) + .is_err()); } #[test] @@ -1937,19 +2316,27 @@ mod tests { assert!(package_one.merge_package(package_three, 1000).is_ok()); assert_eq!(package_one.outpoints().len(), 3); - if let Some(split_package) = package_one.split_package(&BitcoinOutPoint { txid: fake_txid(1), vout: 1 }) { + if let Some(split_package) = + package_one.split_package(&BitcoinOutPoint { txid: fake_txid(1), vout: 1 }) + { // Packages attributes should be identical assert!(split_package.is_malleable()); - assert_eq!(split_package.counterparty_spendable_height, package_one.counterparty_spendable_height); + assert_eq!( + split_package.counterparty_spendable_height, + package_one.counterparty_spendable_height + ); assert_eq!(split_package.feerate_previous, package_one.feerate_previous); assert_eq!(split_package.height_timer, package_one.height_timer); - } else { panic!(); } + } else { + panic!(); + } assert_eq!(package_one.outpoints().len(), 2); } #[test] fn test_package_split_untractable() { - let htlc_outp_one = dumb_accepted_htlc_output!(ChannelTypeFeatures::only_static_remote_key()); + let htlc_outp_one = + dumb_accepted_htlc_output!(ChannelTypeFeatures::only_static_remote_key()); let mut package_one = PackageTemplate::build_package(fake_txid(1), 0, htlc_outp_one, 1000); let ret_split = package_one.split_package(&BitcoinOutPoint { txid: fake_txid(1), vout: 0 }); @@ -1968,7 +2355,11 @@ mod tests { #[test] fn test_package_amounts() { - let counterparty_outp = dumb_counterparty_received_output!(1_000_000, 1000, ChannelTypeFeatures::only_static_remote_key()); + let counterparty_outp = dumb_counterparty_received_output!( + 1_000_000, + 1000, + ChannelTypeFeatures::only_static_remote_key() + ); let package = PackageTemplate::build_package(fake_txid(1), 0, counterparty_outp, 1000); assert_eq!(package.package_amount(), 1000); @@ -1977,27 +2368,54 @@ mod tests { #[test] fn test_package_weight() { // (nVersion (4) + nLocktime (4) + count_tx_in (1) + prevout (36) + sequence (4) + script_length (1) + count_tx_out (1) + value (8) + var_int (1)) * WITNESS_SCALE_FACTOR + witness marker (2) - let weight_sans_output = (4 + 4 + 1 + 36 + 4 + 1 + 1 + 8 + 1) * WITNESS_SCALE_FACTOR as u64 + 2; + let weight_sans_output = + (4 + 4 + 1 + 36 + 4 + 1 + 1 + 8 + 1) * WITNESS_SCALE_FACTOR as u64 + 2; { let revk_outp = dumb_revk_output!(false); let package = PackageTemplate::build_package(fake_txid(1), 0, revk_outp, 0); - assert_eq!(package.package_weight(&ScriptBuf::new()), weight_sans_output + WEIGHT_REVOKED_OUTPUT); + assert_eq!( + package.package_weight(&ScriptBuf::new()), + weight_sans_output + WEIGHT_REVOKED_OUTPUT + ); } { - for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() { - let counterparty_outp = dumb_counterparty_received_output!(1_000_000, 1000, channel_type_features.clone()); - let package = PackageTemplate::build_package(fake_txid(1), 0, counterparty_outp, 1000); - assert_eq!(package.package_weight(&ScriptBuf::new()), weight_sans_output + weight_received_htlc(channel_type_features)); + for channel_type_features in [ + ChannelTypeFeatures::only_static_remote_key(), + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + ] + .iter() + { + let counterparty_outp = dumb_counterparty_received_output!( + 1_000_000, + 1000, + channel_type_features.clone() + ); + let package = + PackageTemplate::build_package(fake_txid(1), 0, counterparty_outp, 1000); + assert_eq!( + package.package_weight(&ScriptBuf::new()), + weight_sans_output + weight_received_htlc(channel_type_features) + ); } } { - for channel_type_features in [ChannelTypeFeatures::only_static_remote_key(), ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()].iter() { - let counterparty_outp = dumb_counterparty_offered_output!(1_000_000, channel_type_features.clone()); - let package = PackageTemplate::build_package(fake_txid(1), 0, counterparty_outp, 1000); - assert_eq!(package.package_weight(&ScriptBuf::new()), weight_sans_output + weight_offered_htlc(channel_type_features)); + for channel_type_features in [ + ChannelTypeFeatures::only_static_remote_key(), + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + ] + .iter() + { + let counterparty_outp = + dumb_counterparty_offered_output!(1_000_000, channel_type_features.clone()); + let package = + PackageTemplate::build_package(fake_txid(1), 0, counterparty_outp, 1000); + assert_eq!( + package.package_weight(&ScriptBuf::new()), + weight_sans_output + weight_offered_htlc(channel_type_features) + ); } } } @@ -2026,9 +2444,23 @@ mod tests { let input_satoshis = 505; let logger = TestLogger::new(); - let bumped_fee_rate = feerate_bump(predicted_weight_units, input_satoshis, 546, 253, &fee_rate_strategy, confirmation_target, &fee_estimator, &logger); + let bumped_fee_rate = feerate_bump( + predicted_weight_units, + input_satoshis, + 546, + 253, + &fee_rate_strategy, + confirmation_target, + &fee_estimator, + &logger, + ); assert!(bumped_fee_rate.is_none()); - logger.assert_log_regex("lightning::chain::package", regex::Regex::new(r"Can't bump new claiming tx, input amount 505 is too small").unwrap(), 1); + logger.assert_log_regex( + "lightning::chain::package", + regex::Regex::new(r"Can't bump new claiming tx, input amount 505 is too small") + .unwrap(), + 1, + ); } { @@ -2044,9 +2476,25 @@ mod tests { let input_satoshis = 2734; let logger = TestLogger::new(); - let bumped_fee_rate = feerate_bump(predicted_weight_units, input_satoshis, 546, 2188, &fee_rate_strategy, confirmation_target, &fee_estimator, &logger); + let bumped_fee_rate = feerate_bump( + predicted_weight_units, + input_satoshis, + 546, + 2188, + &fee_rate_strategy, + confirmation_target, + &fee_estimator, + &logger, + ); assert!(bumped_fee_rate.is_none()); - logger.assert_log_regex("lightning::chain::package", regex::Regex::new(r"Can't bump new claiming tx, output amount 0 would end up below dust threshold 546").unwrap(), 1); + logger.assert_log_regex( + "lightning::chain::package", + regex::Regex::new( + r"Can't bump new claiming tx, output amount 0 would end up below dust threshold 546", + ) + .unwrap(), + 1, + ); } { @@ -2055,9 +2503,25 @@ mod tests { let input_satoshis = 506; let logger = TestLogger::new(); - let bumped_fee_rate = feerate_bump(predicted_weight_units, input_satoshis, 546, 253, &fee_rate_strategy, confirmation_target, &fee_estimator, &logger); + let bumped_fee_rate = feerate_bump( + predicted_weight_units, + input_satoshis, + 546, + 253, + &fee_rate_strategy, + confirmation_target, + &fee_estimator, + &logger, + ); assert!(bumped_fee_rate.is_none()); - logger.assert_log_regex("lightning::chain::package", regex::Regex::new(r"Can't bump new claiming tx, output amount 0 would end up below dust threshold 546").unwrap(), 1); + logger.assert_log_regex( + "lightning::chain::package", + regex::Regex::new( + r"Can't bump new claiming tx, output amount 0 would end up below dust threshold 546", + ) + .unwrap(), + 1, + ); } { @@ -2066,9 +2530,25 @@ mod tests { let input_satoshis = 1051; let logger = TestLogger::new(); - let bumped_fee_rate = feerate_bump(predicted_weight_units, input_satoshis, 546, 253, &fee_rate_strategy, confirmation_target, &fee_estimator, &logger); + let bumped_fee_rate = feerate_bump( + predicted_weight_units, + input_satoshis, + 546, + 253, + &fee_rate_strategy, + confirmation_target, + &fee_estimator, + &logger, + ); assert!(bumped_fee_rate.is_none()); - logger.assert_log_regex("lightning::chain::package", regex::Regex::new(r"Can't bump new claiming tx, output amount 545 would end up below dust threshold 546").unwrap(), 1); + logger.assert_log_regex( + "lightning::chain::package", + regex::Regex::new( + r"Can't bump new claiming tx, output amount 545 would end up below dust threshold 546", + ) + .unwrap(), + 1, + ); } { @@ -2076,9 +2556,26 @@ mod tests { let input_satoshis = 1052; let logger = TestLogger::new(); - let bumped_fee_rate = feerate_bump(predicted_weight_units, input_satoshis, 546, 253, &fee_rate_strategy, confirmation_target, &fee_estimator, &logger).unwrap(); + let bumped_fee_rate = feerate_bump( + predicted_weight_units, + input_satoshis, + 546, + 253, + &fee_rate_strategy, + confirmation_target, + &fee_estimator, + &logger, + ) + .unwrap(); assert_eq!(bumped_fee_rate, (506, 506)); - logger.assert_log_regex("lightning::chain::package", regex::Regex::new(r"Naive fee bump of 63s does not meet min relay fee requirements of 253s").unwrap(), 1); + logger.assert_log_regex( + "lightning::chain::package", + regex::Regex::new( + r"Naive fee bump of 63s does not meet min relay fee requirements of 253s", + ) + .unwrap(), + 1, + ); } } } diff --git a/lightning/src/chain/transaction.rs b/lightning/src/chain/transaction.rs index 60c1e4475a5..533beaf5545 100644 --- a/lightning/src/chain/transaction.rs +++ b/lightning/src/chain/transaction.rs @@ -61,10 +61,7 @@ impl OutPoint { /// This is not exported to bindings users as the same type is used universally in the C bindings /// for all outpoints pub fn into_bitcoin_outpoint(self) -> BitcoinOutPoint { - BitcoinOutPoint { - txid: self.txid, - vout: self.index as u32, - } + BitcoinOutPoint { txid: self.txid, vout: self.index as u32 } } } @@ -90,20 +87,28 @@ mod tests { use crate::chain::transaction::OutPoint; use crate::ln::types::ChannelId; - use bitcoin::transaction::Transaction; use bitcoin::consensus::encode; use bitcoin::hex::FromHex; + use bitcoin::transaction::Transaction; #[test] fn test_channel_id_calculation() { let tx: Transaction = encode::deserialize(&>::from_hex("020000000001010e0adef48412e4361325ac1c6e36411299ab09d4f083b9d8ddb55fbc06e1b0c00000000000feffffff0220a1070000000000220020f81d95e040bd0a493e38bae27bff52fe2bb58b93b293eb579c01c31b05c5af1dc072cfee54a3000016001434b1d6211af5551905dc2642d05f5b04d25a8fe80247304402207f570e3f0de50546aad25a872e3df059d277e776dda4269fa0d2cc8c2ee6ec9a022054e7fae5ca94d47534c86705857c24ceea3ad51c69dd6051c5850304880fc43a012103cb11a1bacc223d98d91f1946c6752e358a5eb1a1c983b3e6fb15378f453b76bd00000000").unwrap()[..]).unwrap(); - assert_eq!(&ChannelId::v1_from_funding_outpoint(OutPoint { - txid: tx.compute_txid(), - index: 0 - }).0[..], &>::from_hex("3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25e").unwrap()[..]); - assert_eq!(&ChannelId::v1_from_funding_outpoint(OutPoint { - txid: tx.compute_txid(), - index: 1 - }).0[..], &>::from_hex("3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25f").unwrap()[..]); + assert_eq!( + &ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 0 }).0 + [..], + &>::from_hex( + "3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25e" + ) + .unwrap()[..] + ); + assert_eq!( + &ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 1 }).0 + [..], + &>::from_hex( + "3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25f" + ) + .unwrap()[..] + ); } } diff --git a/lightning/src/events/bump_transaction.rs b/lightning/src/events/bump_transaction.rs index a9550a67236..e5c428348c2 100644 --- a/lightning/src/events/bump_transaction.rs +++ b/lightning/src/events/bump_transaction.rs @@ -14,35 +14,38 @@ use alloc::collections::BTreeMap; use core::ops::Deref; -use crate::chain::chaininterface::{BroadcasterInterface, fee_for_weight}; +use crate::chain::chaininterface::{fee_for_weight, BroadcasterInterface}; use crate::chain::ClaimId; use crate::io_extras::sink; -use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; -use crate::ln::types::ChannelId; use crate::ln::chan_utils; use crate::ln::chan_utils::{ - ANCHOR_INPUT_WITNESS_WEIGHT, HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT, - HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT, HTLCOutputInCommitment, shared_anchor_script_pubkey, + shared_anchor_script_pubkey, HTLCOutputInCommitment, ANCHOR_INPUT_WITNESS_WEIGHT, + HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT, HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT, }; +use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; +use crate::ln::types::ChannelId; use crate::prelude::*; +use crate::sign::ecdsa::EcdsaChannelSigner; use crate::sign::{ - ChannelDerivationParameters, HTLCDescriptor, SignerProvider, P2WPKH_WITNESS_WEIGHT + ChannelDerivationParameters, HTLCDescriptor, SignerProvider, P2WPKH_WITNESS_WEIGHT, }; -use crate::sign::ecdsa::EcdsaChannelSigner; use crate::sync::Mutex; use crate::util::logger::Logger; -use bitcoin::{OutPoint, Psbt, PubkeyHash, Sequence, ScriptBuf, Transaction, TxIn, TxOut, Witness, WPubkeyHash}; use bitcoin::amount::Amount; +use bitcoin::consensus::Encodable; use bitcoin::constants::WITNESS_SCALE_FACTOR; use bitcoin::locktime::absolute::LockTime; -use bitcoin::consensus::Encodable; use bitcoin::secp256k1; -use bitcoin::secp256k1::{PublicKey, Secp256k1}; use bitcoin::secp256k1::ecdsa::Signature; +use bitcoin::secp256k1::{PublicKey, Secp256k1}; use bitcoin::transaction::Version; +use bitcoin::{ + OutPoint, Psbt, PubkeyHash, ScriptBuf, Sequence, Transaction, TxIn, TxOut, WPubkeyHash, Witness, +}; -pub(crate) const EMPTY_SCRIPT_SIG_WEIGHT: u64 = 1 /* empty script_sig */ * WITNESS_SCALE_FACTOR as u64; +pub(crate) const EMPTY_SCRIPT_SIG_WEIGHT: u64 = + 1 /* empty script_sig */ * WITNESS_SCALE_FACTOR as u64; const BASE_INPUT_SIZE: u64 = 32 /* txid */ + 4 /* vout */ + 4 /* sequence */; @@ -63,18 +66,16 @@ impl AnchorDescriptor { /// [`Self::unsigned_tx_input`]. pub fn previous_utxo(&self) -> TxOut { let tx_params = &self.channel_derivation_parameters.transaction_parameters; - let script_pubkey = - if tx_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() { - let channel_params = tx_params.as_holder_broadcastable(); - chan_utils::get_keyed_anchor_redeemscript(&channel_params.broadcaster_pubkeys().funding_pubkey) - } else { - assert!(tx_params.channel_type_features.supports_anchor_zero_fee_commitments()); - shared_anchor_script_pubkey() - }; - TxOut { - script_pubkey, - value: Amount::from_sat(ANCHOR_OUTPUT_VALUE_SATOSHI), - } + let script_pubkey = if tx_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() { + let channel_params = tx_params.as_holder_broadcastable(); + chan_utils::get_keyed_anchor_redeemscript( + &channel_params.broadcaster_pubkeys().funding_pubkey, + ) + } else { + assert!(tx_params.channel_type_features.supports_anchor_zero_fee_commitments()); + shared_anchor_script_pubkey() + }; + TxOut { script_pubkey, value: Amount::from_sat(ANCHOR_OUTPUT_VALUE_SATOSHI) } } /// Returns the unsigned transaction input spending the anchor output in the commitment @@ -93,8 +94,12 @@ impl AnchorDescriptor { pub fn tx_input_witness(&self, signature: &Signature) -> Witness { let tx_params = &self.channel_derivation_parameters.transaction_parameters; if tx_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() { - let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); - chan_utils::build_keyed_anchor_input_witness(&channel_params.broadcaster_pubkeys().funding_pubkey, signature) + let channel_params = + self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); + chan_utils::build_keyed_anchor_input_witness( + &channel_params.broadcaster_pubkeys().funding_pubkey, + signature, + ) } else { debug_assert!(tx_params.channel_type_features.supports_anchor_zero_fee_commitments()); Witness::from_slice(&[&[]]) @@ -262,11 +267,8 @@ impl Utxo { 33 /* pubkey */; Self { outpoint, - output: TxOut { - value, - script_pubkey: ScriptBuf::new_p2pkh(pubkey_hash), - }, - satisfaction_weight: script_sig_size * WITNESS_SCALE_FACTOR as u64 + 1 /* empty witness */, + output: TxOut { value, script_pubkey: ScriptBuf::new_p2pkh(pubkey_hash) }, + satisfaction_weight: script_sig_size * WITNESS_SCALE_FACTOR as u64 + 1, /* empty witness */ } } @@ -280,9 +282,12 @@ impl Utxo { outpoint, output: TxOut { value, - script_pubkey: ScriptBuf::new_p2sh(&ScriptBuf::new_p2wpkh(pubkey_hash).script_hash()), + script_pubkey: ScriptBuf::new_p2sh( + &ScriptBuf::new_p2wpkh(pubkey_hash).script_hash(), + ), }, - satisfaction_weight: script_sig_size * WITNESS_SCALE_FACTOR as u64 + P2WPKH_WITNESS_WEIGHT, + satisfaction_weight: script_sig_size * WITNESS_SCALE_FACTOR as u64 + + P2WPKH_WITNESS_WEIGHT, } } @@ -290,10 +295,7 @@ impl Utxo { pub fn new_v0_p2wpkh(outpoint: OutPoint, value: Amount, pubkey_hash: &WPubkeyHash) -> Self { Self { outpoint, - output: TxOut { - value, - script_pubkey: ScriptBuf::new_p2wpkh(pubkey_hash), - }, + output: TxOut { value, script_pubkey: ScriptBuf::new_p2wpkh(pubkey_hash) }, satisfaction_weight: EMPTY_SCRIPT_SIG_WEIGHT + P2WPKH_WITNESS_WEIGHT, } } @@ -379,7 +381,7 @@ pub trait WalletSource { pub struct Wallet where W::Target: WalletSource, - L::Target: Logger + L::Target: Logger, { source: W, logger: L, @@ -392,7 +394,7 @@ where impl Wallet where W::Target: WalletSource, - L::Target: Logger + L::Target: Logger, { /// Returns a new instance backed by the given [`WalletSource`] that serves as an implementation /// of [`CoinSelectionSource`]. @@ -414,32 +416,47 @@ where preexisting_tx_weight: u64, input_amount_sat: Amount, target_amount_sat: Amount, ) -> Result { let mut locked_utxos = self.locked_utxos.lock().unwrap(); - let mut eligible_utxos = utxos.iter().filter_map(|utxo| { - if let Some(utxo_claim_id) = locked_utxos.get(&utxo.outpoint) { - if *utxo_claim_id != claim_id && !force_conflicting_utxo_spend { - log_trace!(self.logger, "Skipping UTXO {} to prevent conflicting spend", utxo.outpoint); - return None; + let mut eligible_utxos = utxos + .iter() + .filter_map(|utxo| { + if let Some(utxo_claim_id) = locked_utxos.get(&utxo.outpoint) { + if *utxo_claim_id != claim_id && !force_conflicting_utxo_spend { + log_trace!( + self.logger, + "Skipping UTXO {} to prevent conflicting spend", + utxo.outpoint + ); + return None; + } } - } - let fee_to_spend_utxo = Amount::from_sat(fee_for_weight( - target_feerate_sat_per_1000_weight, BASE_INPUT_WEIGHT + utxo.satisfaction_weight, - )); - let should_spend = if tolerate_high_network_feerates { - utxo.output.value > fee_to_spend_utxo - } else { - utxo.output.value >= fee_to_spend_utxo * 2 - }; - if should_spend { - Some((utxo, fee_to_spend_utxo)) - } else { - log_trace!(self.logger, "Skipping UTXO {} due to dust proximity after spend", utxo.outpoint); - None - } - }).collect::>(); + let fee_to_spend_utxo = Amount::from_sat(fee_for_weight( + target_feerate_sat_per_1000_weight, + BASE_INPUT_WEIGHT + utxo.satisfaction_weight, + )); + let should_spend = if tolerate_high_network_feerates { + utxo.output.value > fee_to_spend_utxo + } else { + utxo.output.value >= fee_to_spend_utxo * 2 + }; + if should_spend { + Some((utxo, fee_to_spend_utxo)) + } else { + log_trace!( + self.logger, + "Skipping UTXO {} due to dust proximity after spend", + utxo.outpoint + ); + None + } + }) + .collect::>(); eligible_utxos.sort_unstable_by_key(|(utxo, _)| utxo.output.value); let mut selected_amount = input_amount_sat; - let mut total_fees = Amount::from_sat(fee_for_weight(target_feerate_sat_per_1000_weight, preexisting_tx_weight)); + let mut total_fees = Amount::from_sat(fee_for_weight( + target_feerate_sat_per_1000_weight, + preexisting_tx_weight, + )); let mut selected_utxos = Vec::new(); for (utxo, fee_to_spend_utxo) in eligible_utxos { if selected_amount >= target_amount_sat + total_fees { @@ -450,8 +467,11 @@ where selected_utxos.push(utxo.clone()); } if selected_amount < target_amount_sat + total_fees { - log_debug!(self.logger, "Insufficient funds to meet target feerate {} sat/kW", - target_feerate_sat_per_1000_weight); + log_debug!( + self.logger, + "Insufficient funds to meet target feerate {} sat/kW", + target_feerate_sat_per_1000_weight + ); return Err(()); } for utxo in &selected_utxos { @@ -463,10 +483,11 @@ where let change_script = self.source.get_change_script()?; let change_output_fee = fee_for_weight( target_feerate_sat_per_1000_weight, - (8 /* value */ + change_script.consensus_encode(&mut sink()).unwrap() as u64) * - WITNESS_SCALE_FACTOR as u64, + (8 /* value */ + change_script.consensus_encode(&mut sink()).unwrap() as u64) + * WITNESS_SCALE_FACTOR as u64, ); - let change_output_amount = Amount::from_sat(remaining_amount.to_sat().saturating_sub(change_output_fee)); + let change_output_amount = + Amount::from_sat(remaining_amount.to_sat().saturating_sub(change_output_fee)); let change_output = if change_output_amount < change_script.minimal_non_dust() { log_debug!(self.logger, "Coin selection attempt did not yield change output"); None @@ -474,17 +495,14 @@ where Some(TxOut { script_pubkey: change_script, value: change_output_amount }) }; - Ok(CoinSelection { - confirmed_utxos: selected_utxos, - change_output, - }) + Ok(CoinSelection { confirmed_utxos: selected_utxos, change_output }) } } impl CoinSelectionSource for Wallet where W::Target: WalletSource, - L::Target: Logger + L::Target: Logger, { fn select_confirmed_utxos( &self, claim_id: ClaimId, must_spend: Vec, must_pay_to: &[TxOut], @@ -493,22 +511,32 @@ where let utxos = self.source.list_confirmed_utxos()?; // TODO: Use fee estimation utils when we upgrade to bitcoin v0.30.0. const BASE_TX_SIZE: u64 = 4 /* version */ + 1 /* input count */ + 1 /* output count */ + 4 /* locktime */; - let total_output_size: u64 = must_pay_to.iter().map(|output| - 8 /* value */ + 1 /* script len */ + output.script_pubkey.len() as u64 - ).sum(); - let total_satisfaction_weight: u64 = must_spend.iter().map(|input| input.satisfaction_weight).sum(); - let total_input_weight = (BASE_INPUT_WEIGHT * must_spend.len() as u64) + total_satisfaction_weight; + let total_output_size: u64 = must_pay_to + .iter() + .map(|output| 8 /* value */ + 1 /* script len */ + output.script_pubkey.len() as u64) + .sum(); + let total_satisfaction_weight: u64 = + must_spend.iter().map(|input| input.satisfaction_weight).sum(); + let total_input_weight = + (BASE_INPUT_WEIGHT * must_spend.len() as u64) + total_satisfaction_weight; let preexisting_tx_weight = 2 /* segwit marker & flag */ + total_input_weight + ((BASE_TX_SIZE + total_output_size) * WITNESS_SCALE_FACTOR as u64); let input_amount_sat = must_spend.iter().map(|input| input.previous_utxo.value).sum(); let target_amount_sat = must_pay_to.iter().map(|output| output.value).sum(); - let do_coin_selection = |force_conflicting_utxo_spend: bool, tolerate_high_network_feerates: bool| { + let do_coin_selection = |force_conflicting_utxo_spend: bool, + tolerate_high_network_feerates: bool| { log_debug!(self.logger, "Attempting coin selection targeting {} sat/kW (force_conflicting_utxo_spend = {}, tolerate_high_network_feerates = {})", target_feerate_sat_per_1000_weight, force_conflicting_utxo_spend, tolerate_high_network_feerates); self.select_confirmed_utxos_internal( - &utxos, claim_id, force_conflicting_utxo_spend, tolerate_high_network_feerates, - target_feerate_sat_per_1000_weight, preexisting_tx_weight, input_amount_sat, target_amount_sat, + &utxos, + claim_id, + force_conflicting_utxo_spend, + tolerate_high_network_feerates, + target_feerate_sat_per_1000_weight, + preexisting_tx_weight, + input_amount_sat, + target_amount_sat, ) }; do_coin_selection(false, false) @@ -552,13 +580,7 @@ where /// /// [`Event::BumpTransaction`]: crate::events::Event::BumpTransaction pub fn new(broadcaster: B, utxo_source: C, signer_provider: SP, logger: L) -> Self { - Self { - broadcaster, - utxo_source, - signer_provider, - logger, - secp: Secp256k1::new(), - } + Self { broadcaster, utxo_source, signer_provider, logger, secp: Secp256k1::new() } } /// Updates a transaction with the result of a successful coin selection attempt. @@ -605,7 +627,8 @@ where /// broadcasts them to the network as a package. fn handle_channel_close( &self, claim_id: ClaimId, package_target_feerate_sat_per_1000_weight: u32, - commitment_tx: &Transaction, commitment_tx_fee_sat: u64, anchor_descriptor: &AnchorDescriptor, + commitment_tx: &Transaction, commitment_tx_fee_sat: u64, + anchor_descriptor: &AnchorDescriptor, ) -> Result<(), ()> { // Our commitment transaction already has fees allocated to it, so we should take them into // account. We do so by pretending the commitment transaction's fee and weight are part of @@ -624,12 +647,16 @@ where previous_utxo: anchor_utxo.clone(), satisfaction_weight: package_and_fixed_input_satisfaction_weight, }]; - let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::(); + let must_spend_amount = + must_spend.iter().map(|input| input.previous_utxo.value).sum::(); log_debug!(self.logger, "Performing coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW", package_target_feerate_sat_per_1000_weight); let coin_selection: CoinSelection = self.utxo_source.select_confirmed_utxos( - claim_id, must_spend, &[], package_target_feerate_sat_per_1000_weight, + claim_id, + must_spend, + &[], + package_target_feerate_sat_per_1000_weight, )?; let mut anchor_tx = Transaction { @@ -639,10 +666,15 @@ where output: vec![], }; - let total_satisfaction_weight = ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT + - coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::(); - let total_input_amount = must_spend_amount + - coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum(); + let total_satisfaction_weight = ANCHOR_INPUT_WITNESS_WEIGHT + + EMPTY_SCRIPT_SIG_WEIGHT + + coin_selection + .confirmed_utxos + .iter() + .map(|utxo| utxo.satisfaction_weight) + .sum::(); + let total_input_amount = must_spend_amount + + coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum(); self.process_coin_selection(&mut anchor_tx, &coin_selection); let anchor_txid = anchor_tx.compute_txid(); @@ -655,27 +687,38 @@ where for (idx, utxo) in coin_selection.confirmed_utxos.into_iter().enumerate() { // add 1 to skip the anchor input let index = idx + 1; - debug_assert_eq!(anchor_psbt.unsigned_tx.input[index].previous_output, utxo.outpoint); + debug_assert_eq!( + anchor_psbt.unsigned_tx.input[index].previous_output, + utxo.outpoint + ); if utxo.output.script_pubkey.is_witness_program() { anchor_psbt.inputs[index].witness_utxo = Some(utxo.output); } } debug_assert_eq!(anchor_psbt.unsigned_tx.output.len(), 1); - let unsigned_tx_weight = anchor_psbt.unsigned_tx.weight().to_wu() - (anchor_psbt.unsigned_tx.input.len() as u64 * EMPTY_SCRIPT_SIG_WEIGHT); + let unsigned_tx_weight = anchor_psbt.unsigned_tx.weight().to_wu() + - (anchor_psbt.unsigned_tx.input.len() as u64 * EMPTY_SCRIPT_SIG_WEIGHT); - let package_fee = total_input_amount - - anchor_psbt.unsigned_tx.output.iter().map(|output| output.value).sum(); + let package_fee = total_input_amount + - anchor_psbt.unsigned_tx.output.iter().map(|output| output.value).sum(); let package_weight = unsigned_tx_weight + 2 /* wit marker */ + total_satisfaction_weight + commitment_tx.weight().to_wu(); - if package_fee.to_sat() * 1000 / package_weight < package_target_feerate_sat_per_1000_weight.into() { + if package_fee.to_sat() * 1000 / package_weight + < package_target_feerate_sat_per_1000_weight.into() + { // On the first iteration of the loop, we may undershoot the target feerate because // we had to add an OP_RETURN output in `process_coin_selection` which we didn't // select sufficient coins for. Here we detect that case and go around again // seeking additional weight. - if package_and_fixed_input_satisfaction_weight == starting_package_and_fixed_input_satisfaction_weight { - debug_assert!(anchor_psbt.unsigned_tx.output[0].script_pubkey.is_op_return(), - "Coin selection failed to select sufficient coins for its change output"); - package_and_fixed_input_satisfaction_weight += anchor_psbt.unsigned_tx.output[0].weight().to_wu(); + if package_and_fixed_input_satisfaction_weight + == starting_package_and_fixed_input_satisfaction_weight + { + debug_assert!( + anchor_psbt.unsigned_tx.output[0].script_pubkey.is_op_return(), + "Coin selection failed to select sufficient coins for its change output" + ); + package_and_fixed_input_satisfaction_weight += + anchor_psbt.unsigned_tx.output[0].weight().to_wu(); continue; } else { debug_assert!(false, "Coin selection failed to select sufficient coins"); @@ -685,28 +728,47 @@ where log_debug!(self.logger, "Signing anchor transaction {}", anchor_txid); anchor_tx = self.utxo_source.sign_psbt(anchor_psbt)?; - let signer = self.signer_provider.derive_channel_signer(anchor_descriptor.channel_derivation_parameters.keys_id); - let channel_parameters = &anchor_descriptor.channel_derivation_parameters.transaction_parameters; - let anchor_sig = signer.sign_holder_keyed_anchor_input(channel_parameters, &anchor_tx, 0, &self.secp)?; + let signer = self + .signer_provider + .derive_channel_signer(anchor_descriptor.channel_derivation_parameters.keys_id); + let channel_parameters = + &anchor_descriptor.channel_derivation_parameters.transaction_parameters; + let anchor_sig = signer.sign_holder_keyed_anchor_input( + channel_parameters, + &anchor_tx, + 0, + &self.secp, + )?; anchor_tx.input[0].witness = anchor_descriptor.tx_input_witness(&anchor_sig); - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let signed_tx_weight = anchor_tx.weight().to_wu(); - let expected_signed_tx_weight = unsigned_tx_weight + 2 /* wit marker */ + total_satisfaction_weight; + let expected_signed_tx_weight = + unsigned_tx_weight + 2 /* wit marker */ + total_satisfaction_weight; // Our estimate should be within a 1% error margin of the actual weight and we should // never underestimate. - assert!(expected_signed_tx_weight >= signed_tx_weight && - expected_signed_tx_weight - (expected_signed_tx_weight / 100) <= signed_tx_weight); - - let expected_package_fee = Amount::from_sat(fee_for_weight(package_target_feerate_sat_per_1000_weight, - signed_tx_weight + commitment_tx.weight().to_wu())); + assert!( + expected_signed_tx_weight >= signed_tx_weight + && expected_signed_tx_weight - (expected_signed_tx_weight / 100) + <= signed_tx_weight + ); + + let expected_package_fee = Amount::from_sat(fee_for_weight( + package_target_feerate_sat_per_1000_weight, + signed_tx_weight + commitment_tx.weight().to_wu(), + )); // Our feerate should always be at least what we were seeking. It may overshoot if // the coin selector burned funds to an OP_RETURN without a change output. assert!(package_fee >= expected_package_fee); } - log_info!(self.logger, "Broadcasting anchor transaction {} to bump channel close with txid {}", - anchor_txid, commitment_tx.compute_txid()); + log_info!( + self.logger, + "Broadcasting anchor transaction {} to bump channel close with txid {}", + anchor_txid, + commitment_tx.compute_txid() + ); self.broadcaster.broadcast_transactions(&[&commitment_tx, &anchor_tx]); return Ok(()); } @@ -730,36 +792,52 @@ where must_spend.push(Input { outpoint: htlc_input.previous_output.clone(), previous_utxo: htlc_descriptor.previous_utxo(&self.secp), - satisfaction_weight: EMPTY_SCRIPT_SIG_WEIGHT + if htlc_descriptor.preimage.is_some() { - HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT - } else { - HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT - }, + satisfaction_weight: EMPTY_SCRIPT_SIG_WEIGHT + + if htlc_descriptor.preimage.is_some() { + HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT + } else { + HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT + }, }); htlc_tx.input.push(htlc_input); let htlc_output = htlc_descriptor.tx_output(&self.secp); htlc_tx.output.push(htlc_output); } - log_debug!(self.logger, "Performing coin selection for HTLC transaction targeting {} sat/kW", - target_feerate_sat_per_1000_weight); + log_debug!( + self.logger, + "Performing coin selection for HTLC transaction targeting {} sat/kW", + target_feerate_sat_per_1000_weight + ); #[cfg(debug_assertions)] let must_spend_satisfaction_weight = must_spend.iter().map(|input| input.satisfaction_weight).sum::(); #[cfg(debug_assertions)] - let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value.to_sat()).sum::(); + let must_spend_amount = + must_spend.iter().map(|input| input.previous_utxo.value.to_sat()).sum::(); let coin_selection: CoinSelection = self.utxo_source.select_confirmed_utxos( - claim_id, must_spend, &htlc_tx.output, target_feerate_sat_per_1000_weight, + claim_id, + must_spend, + &htlc_tx.output, + target_feerate_sat_per_1000_weight, )?; #[cfg(debug_assertions)] - let total_satisfaction_weight = must_spend_satisfaction_weight + - coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::(); + let total_satisfaction_weight = must_spend_satisfaction_weight + + coin_selection + .confirmed_utxos + .iter() + .map(|utxo| utxo.satisfaction_weight) + .sum::(); #[cfg(debug_assertions)] - let total_input_amount = must_spend_amount + - coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value.to_sat()).sum::(); + let total_input_amount = must_spend_amount + + coin_selection + .confirmed_utxos + .iter() + .map(|utxo| utxo.output.value.to_sat()) + .sum::(); self.process_coin_selection(&mut htlc_tx, &coin_selection); @@ -767,7 +845,10 @@ where let mut htlc_psbt = Psbt::from_unsigned_tx(htlc_tx).unwrap(); // add witness_utxo to htlc inputs for (i, htlc_descriptor) in htlc_descriptors.iter().enumerate() { - debug_assert_eq!(htlc_psbt.unsigned_tx.input[i].previous_output, htlc_descriptor.outpoint()); + debug_assert_eq!( + htlc_psbt.unsigned_tx.input[i].previous_output, + htlc_descriptor.outpoint() + ); htlc_psbt.inputs[i].witness_utxo = Some(htlc_descriptor.previous_utxo(&self.secp)); } // add witness_utxo to remaining inputs @@ -781,32 +862,45 @@ where } #[cfg(debug_assertions)] - let unsigned_tx_weight = htlc_psbt.unsigned_tx.weight().to_wu() - (htlc_psbt.unsigned_tx.input.len() as u64 * EMPTY_SCRIPT_SIG_WEIGHT); + let unsigned_tx_weight = htlc_psbt.unsigned_tx.weight().to_wu() + - (htlc_psbt.unsigned_tx.input.len() as u64 * EMPTY_SCRIPT_SIG_WEIGHT); - log_debug!(self.logger, "Signing HTLC transaction {}", htlc_psbt.unsigned_tx.compute_txid()); + log_debug!( + self.logger, + "Signing HTLC transaction {}", + htlc_psbt.unsigned_tx.compute_txid() + ); htlc_tx = self.utxo_source.sign_psbt(htlc_psbt)?; let mut signers = BTreeMap::new(); for (idx, htlc_descriptor) in htlc_descriptors.iter().enumerate() { let keys_id = htlc_descriptor.channel_derivation_parameters.keys_id; - let signer = signers.entry(keys_id) + let signer = signers + .entry(keys_id) .or_insert_with(|| self.signer_provider.derive_channel_signer(keys_id)); - let htlc_sig = signer.sign_holder_htlc_transaction(&htlc_tx, idx, htlc_descriptor, &self.secp)?; + let htlc_sig = + signer.sign_holder_htlc_transaction(&htlc_tx, idx, htlc_descriptor, &self.secp)?; let witness_script = htlc_descriptor.witness_script(&self.secp); - htlc_tx.input[idx].witness = htlc_descriptor.tx_input_witness(&htlc_sig, &witness_script); + htlc_tx.input[idx].witness = + htlc_descriptor.tx_input_witness(&htlc_sig, &witness_script); } - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let signed_tx_weight = htlc_tx.weight().to_wu(); let expected_signed_tx_weight = unsigned_tx_weight + total_satisfaction_weight; // Our estimate should be within a 1% error margin of the actual weight and we should // never underestimate. - assert!(expected_signed_tx_weight >= signed_tx_weight && - expected_signed_tx_weight - (expected_signed_tx_weight / 100) <= signed_tx_weight); - - let expected_signed_tx_fee = fee_for_weight(target_feerate_sat_per_1000_weight, signed_tx_weight); - let signed_tx_fee = total_input_amount - - htlc_tx.output.iter().map(|output| output.value.to_sat()).sum::(); + assert!( + expected_signed_tx_weight >= signed_tx_weight + && expected_signed_tx_weight - (expected_signed_tx_weight / 100) + <= signed_tx_weight + ); + + let expected_signed_tx_fee = + fee_for_weight(target_feerate_sat_per_1000_weight, signed_tx_weight); + let signed_tx_fee = total_input_amount + - htlc_tx.output.iter().map(|output| output.value.to_sat()).sum::(); // Our feerate should always be at least what we were seeking. It may overshoot if // the coin selector burned funds to an OP_RETURN without a change output. assert!(signed_tx_fee >= expected_signed_tx_fee); @@ -821,31 +915,59 @@ where pub fn handle_event(&self, event: &BumpTransactionEvent) { match event { BumpTransactionEvent::ChannelClose { - claim_id, package_target_feerate_sat_per_1000_weight, commitment_tx, - commitment_tx_fee_satoshis, anchor_descriptor, .. + claim_id, + package_target_feerate_sat_per_1000_weight, + commitment_tx, + commitment_tx_fee_satoshis, + anchor_descriptor, + .. } => { - log_info!(self.logger, "Handling channel close bump (claim_id = {}, commitment_txid = {})", - log_bytes!(claim_id.0), commitment_tx.compute_txid()); + log_info!( + self.logger, + "Handling channel close bump (claim_id = {}, commitment_txid = {})", + log_bytes!(claim_id.0), + commitment_tx.compute_txid() + ); if let Err(_) = self.handle_channel_close( - *claim_id, *package_target_feerate_sat_per_1000_weight, commitment_tx, - *commitment_tx_fee_satoshis, anchor_descriptor, + *claim_id, + *package_target_feerate_sat_per_1000_weight, + commitment_tx, + *commitment_tx_fee_satoshis, + anchor_descriptor, ) { - log_error!(self.logger, "Failed bumping commitment transaction fee for {}", - commitment_tx.compute_txid()); + log_error!( + self.logger, + "Failed bumping commitment transaction fee for {}", + commitment_tx.compute_txid() + ); } - } + }, BumpTransactionEvent::HTLCResolution { - claim_id, target_feerate_sat_per_1000_weight, htlc_descriptors, tx_lock_time, .. + claim_id, + target_feerate_sat_per_1000_weight, + htlc_descriptors, + tx_lock_time, + .. } => { - log_info!(self.logger, "Handling HTLC bump (claim_id = {}, htlcs_to_claim = {})", - log_bytes!(claim_id.0), log_iter!(htlc_descriptors.iter().map(|d| d.outpoint()))); + log_info!( + self.logger, + "Handling HTLC bump (claim_id = {}, htlcs_to_claim = {})", + log_bytes!(claim_id.0), + log_iter!(htlc_descriptors.iter().map(|d| d.outpoint())) + ); if let Err(_) = self.handle_htlc_resolution( - *claim_id, *target_feerate_sat_per_1000_weight, htlc_descriptors, *tx_lock_time, + *claim_id, + *target_feerate_sat_per_1000_weight, + htlc_descriptors, + *tx_lock_time, ) { - log_error!(self.logger, "Failed bumping HTLC transaction fee for commitment {}", - htlc_descriptors[0].commitment_txid); + log_error!( + self.logger, + "Failed bumping HTLC transaction fee for commitment {}", + htlc_descriptors[0].commitment_txid + ); } - } + }, } } } @@ -856,10 +978,10 @@ mod tests { use crate::io::Cursor; use crate::ln::chan_utils::ChannelTransactionParameters; - use crate::util::ser::Readable; - use crate::util::test_utils::{TestBroadcaster, TestLogger}; use crate::sign::KeysManager; use crate::types::features::ChannelTypeFeatures; + use crate::util::ser::Readable; + use crate::util::test_utils::{TestBroadcaster, TestLogger}; use bitcoin::hashes::Hash; use bitcoin::hex::FromHex; @@ -871,11 +993,8 @@ mod tests { } impl CoinSelectionSource for TestCoinSelectionSource { fn select_confirmed_utxos( - &self, - _claim_id: ClaimId, - must_spend: Vec, - _must_pay_to: &[TxOut], - target_feerate_sat_per_1000_weight: u32 + &self, _claim_id: ClaimId, must_spend: Vec, _must_pay_to: &[TxOut], + target_feerate_sat_per_1000_weight: u32, ) -> Result { let mut expected_selects = self.expected_selects.lock().unwrap(); let (weight, value, feerate, res) = expected_selects.remove(0); @@ -918,26 +1037,41 @@ mod tests { // Tx 18032ad172a5f28fa6e16392d6cc57ea47895781434ce15d03766cc47a955fb9 let commitment_tx_bytes = Vec::::from_hex("02000000000101cc6b0a9dd84b52c07340fff6fab002fc37b4bdccfdce9f39c5ec8391a56b652907000000009b948b80044a01000000000000220020b4182433fdfdfbf894897c98f84d92cec815cee222755ffd000ae091c9dadc2d4a01000000000000220020f83f7dbf90e2de325b5bb6bab0ae370151278c6964739242b2e7ce0cb68a5d81cb4a02000000000022002024add256b3dccee772610caef82a601045ab6f98fd6d5df608cc756b891ccfe63ffa490000000000220020894bf32b37906a643625e87131897c3714c71b3ac9b161862c9aa6c8d468b4c70400473044022060abd347bff2cca0212b660e6addff792b3356bd4a1b5b26672dc2e694c3c5f002202b40b7e346b494a7b1d048b4ec33ba99c90a09ab48eb1df64ccdc768066c865c014730440220554d8361e04dc0ee178dcb23d2d23f53ec7a1ae4312a5be76bd9e83ab8981f3d0220501f23ffb18cb81ccea72d30252f88d5e69fd28ba4992803d03c00d06fa8899e0147522102817f6ce189ab7114f89e8d5df58cdbbaf272dc8e71b92982d47456a0b6a0ceee2102c9b4d2f24aca54f65e13f4c83e2a8d8e877e12d3c71a76e81f28a5cabc652aa352ae626c7620").unwrap(); - let commitment_tx: Transaction = Readable::read(&mut Cursor::new(&commitment_tx_bytes)).unwrap(); - let total_commitment_weight = commitment_tx.weight().to_wu() + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT; + let commitment_tx: Transaction = + Readable::read(&mut Cursor::new(&commitment_tx_bytes)).unwrap(); + let total_commitment_weight = + commitment_tx.weight().to_wu() + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT; let commitment_and_anchor_fee = 930 + 330; - let op_return_weight = TxOut { - value: Amount::ZERO, - script_pubkey: ScriptBuf::new_op_return(&[0; 3]), - }.weight().to_wu(); + let op_return_weight = + TxOut { value: Amount::ZERO, script_pubkey: ScriptBuf::new_op_return(&[0; 3]) } + .weight() + .to_wu(); let broadcaster = TestBroadcaster::new(Network::Testnet); let source = TestCoinSelectionSource { expected_selects: Mutex::new(vec![ - (total_commitment_weight, commitment_and_anchor_fee, 868, CoinSelection { confirmed_utxos: Vec::new(), change_output: None }), - (total_commitment_weight + op_return_weight, commitment_and_anchor_fee, 868, CoinSelection { - confirmed_utxos: vec![Utxo { - outpoint: OutPoint { txid: Txid::from_byte_array([44; 32]), vout: 0 }, - output: TxOut { value: Amount::from_sat(200), script_pubkey: ScriptBuf::new() }, - satisfaction_weight: 5, // Just the script_sig and witness lengths - }], - change_output: None, - }) + ( + total_commitment_weight, + commitment_and_anchor_fee, + 868, + CoinSelection { confirmed_utxos: Vec::new(), change_output: None }, + ), + ( + total_commitment_weight + op_return_weight, + commitment_and_anchor_fee, + 868, + CoinSelection { + confirmed_utxos: vec![Utxo { + outpoint: OutPoint { txid: Txid::from_byte_array([44; 32]), vout: 0 }, + output: TxOut { + value: Amount::from_sat(200), + script_pubkey: ScriptBuf::new(), + }, + satisfaction_weight: 5, // Just the script_sig and witness lengths + }], + change_output: None, + }, + ), ]), }; let signer = KeysManager::new(&[42; 32], 42, 42); diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index 8d28c9b4191..2c0ef60446b 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -19,33 +19,38 @@ pub mod bump_transaction; pub use bump_transaction::BumpTransactionEvent; use crate::blinded_path::message::OffersContext; -use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext, PaymentContextRef}; +use crate::blinded_path::payment::{ + Bolt12OfferContext, Bolt12RefundContext, PaymentContext, PaymentContextRef, +}; use crate::chain::transaction; -use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; -use crate::offers::invoice::Bolt12Invoice; -use crate::offers::static_invoice::StaticInvoice; -use crate::types::features::ChannelTypeFeatures; +use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; use crate::ln::msgs; use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret}; +use crate::offers::invoice::Bolt12Invoice; +use crate::offers::static_invoice::StaticInvoice; use crate::onion_message::messenger::Responder; use crate::routing::gossip::NetworkUpdate; use crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters}; use crate::sign::SpendableOutputDescriptor; +use crate::types::features::ChannelTypeFeatures; +use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::errors::APIError; -use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired, WithoutLength}; +use crate::util::ser::{ + BigSize, FixedLengthReader, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired, + WithoutLength, Writeable, Writer, +}; use crate::util::string::UntrustedString; -use bitcoin::{Transaction, OutPoint}; -use bitcoin::script::ScriptBuf; -use bitcoin::hashes::Hash; +use crate::io; +use crate::sync::Arc; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; +use bitcoin::script::ScriptBuf; use bitcoin::secp256k1::PublicKey; -use crate::io; -use core::time::Duration; +use bitcoin::{OutPoint, Transaction}; use core::ops::Deref; -use crate::sync::Arc; +use core::time::Duration; #[allow(unused_imports)] use crate::prelude::*; @@ -63,12 +68,12 @@ pub enum FundingInfo { /// The full funding `Transaction`. Tx { /// The funding transaction - transaction: Transaction + transaction: Transaction, }, /// The `OutPoint` of the funding. OutPoint { /// The outpoint of the funding - outpoint: transaction::OutPoint + outpoint: transaction::OutPoint, }, } @@ -81,7 +86,6 @@ impl_writeable_tlv_based_enum!(FundingInfo, } ); - /// Some information provided on receipt of payment depends on whether the payment received is a /// spontaneous payment or a "conventional" lightning payment that's paying an invoice. #[derive(Clone, Debug, PartialEq, Eq)] @@ -182,22 +186,15 @@ impl PaymentPurpose { /// Errors when provided an `AsyncBolt12OfferContext`, see below. pub(crate) fn from_parts( payment_preimage: Option, payment_secret: PaymentSecret, - payment_context: Option + payment_context: Option, ) -> Result { match payment_context { - None => { - Ok(PaymentPurpose::Bolt11InvoicePayment { - payment_preimage, - payment_secret, - }) - }, - Some(PaymentContext::Bolt12Offer(context)) => { - Ok(PaymentPurpose::Bolt12OfferPayment { - payment_preimage, - payment_secret, - payment_context: context, - }) - }, + None => Ok(PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret }), + Some(PaymentContext::Bolt12Offer(context)) => Ok(PaymentPurpose::Bolt12OfferPayment { + payment_preimage, + payment_secret, + payment_context: context, + }), Some(PaymentContext::Bolt12Refund(context)) => { Ok(PaymentPurpose::Bolt12RefundPayment { payment_preimage, @@ -210,7 +207,7 @@ impl PaymentPurpose { // using the invoice request provided in the payment onion prior to calling this method. debug_assert!(false); Err(()) - } + }, } } } @@ -337,7 +334,7 @@ pub enum ClosureReason { /// /// [`ChannelManager::force_close_broadcasting_latest_txn`]: crate::ln::channelmanager::ChannelManager::force_close_broadcasting_latest_txn. /// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn. - broadcasted_latest_txn: Option + broadcasted_latest_txn: Option, }, /// The channel was closed after negotiating a cooperative close and we've now broadcasted /// the cooperative close transaction. Note the shutdown may have been initiated by us. @@ -418,30 +415,56 @@ impl core::fmt::Display for ClosureReason { ClosureReason::HolderForceClosed { broadcasted_latest_txn } => { f.write_str("user force-closed the channel")?; if let Some(brodcasted) = broadcasted_latest_txn { - write!(f, " and {} the latest transaction", if *brodcasted { "broadcasted" } else { "elected not to broadcast" }) + write!( + f, + " and {} the latest transaction", + if *brodcasted { "broadcasted" } else { "elected not to broadcast" } + ) } else { Ok(()) } }, - ClosureReason::LegacyCooperativeClosure => f.write_str("the channel was cooperatively closed"), - ClosureReason::CounterpartyInitiatedCooperativeClosure => f.write_str("the channel was cooperatively closed by our peer"), - ClosureReason::LocallyInitiatedCooperativeClosure => f.write_str("the channel was cooperatively closed by us"), - ClosureReason::CommitmentTxConfirmed => f.write_str("commitment or closing transaction was confirmed on chain."), - ClosureReason::FundingTimedOut => write!(f, "funding transaction failed to confirm within {} blocks", FUNDING_CONF_DEADLINE_BLOCKS), + ClosureReason::LegacyCooperativeClosure => { + f.write_str("the channel was cooperatively closed") + }, + ClosureReason::CounterpartyInitiatedCooperativeClosure => { + f.write_str("the channel was cooperatively closed by our peer") + }, + ClosureReason::LocallyInitiatedCooperativeClosure => { + f.write_str("the channel was cooperatively closed by us") + }, + ClosureReason::CommitmentTxConfirmed => { + f.write_str("commitment or closing transaction was confirmed on chain.") + }, + ClosureReason::FundingTimedOut => write!( + f, + "funding transaction failed to confirm within {} blocks", + FUNDING_CONF_DEADLINE_BLOCKS + ), ClosureReason::ProcessingError { err } => { f.write_str("of an exception: ")?; f.write_str(&err) }, - ClosureReason::DisconnectedPeer => f.write_str("the peer disconnected prior to the channel being funded"), - ClosureReason::OutdatedChannelManager => f.write_str("the ChannelManager read from disk was stale compared to ChannelMonitor(s)"), - ClosureReason::CounterpartyCoopClosedUnfundedChannel => f.write_str("the peer requested the unfunded channel be closed"), - ClosureReason::FundingBatchClosure => f.write_str("another channel in the same funding batch closed"), + ClosureReason::DisconnectedPeer => { + f.write_str("the peer disconnected prior to the channel being funded") + }, + ClosureReason::OutdatedChannelManager => f.write_str( + "the ChannelManager read from disk was stale compared to ChannelMonitor(s)", + ), + ClosureReason::CounterpartyCoopClosedUnfundedChannel => { + f.write_str("the peer requested the unfunded channel be closed") + }, + ClosureReason::FundingBatchClosure => { + f.write_str("another channel in the same funding batch closed") + }, ClosureReason::HTLCsTimedOut => f.write_str("htlcs on the channel timed out"), - ClosureReason::PeerFeerateTooLow { peer_feerate_sat_per_kw, required_feerate_sat_per_kw } => - f.write_fmt(format_args!( - "peer provided a feerate ({} sat/kw) which was below our lower bound ({} sat/kw)", - peer_feerate_sat_per_kw, required_feerate_sat_per_kw, - )), + ClosureReason::PeerFeerateTooLow { + peer_feerate_sat_per_kw, + required_feerate_sat_per_kw, + } => f.write_fmt(format_args!( + "peer provided a feerate ({} sat/kw) which was below our lower bound ({} sat/kw)", + peer_feerate_sat_per_kw, required_feerate_sat_per_kw, + )), } } } @@ -488,7 +511,7 @@ pub enum HTLCDestination { /// intercept HTLC. InvalidForward { /// Short channel id we are requesting to forward an HTLC to. - requested_forward_scid: u64 + requested_forward_scid: u64, }, /// We couldn't decode the incoming onion to obtain the forwarding details. InvalidOnion, @@ -504,7 +527,7 @@ pub enum HTLCDestination { /// recipient for a payment. FailedPayment { /// The payment hash of the payment we attempted to process. - payment_hash: PaymentHash + payment_hash: PaymentHash, }, } @@ -530,9 +553,7 @@ impl_writeable_tlv_based_enum_upgradable!(HTLCDestination, /// will be added for general-purpose HTLC forward intercepts as well as trampoline forward /// intercepts in upcoming work. enum InterceptNextHop { - FakeScid { - requested_next_hop_scid: u64, - }, + FakeScid { requested_next_hop_scid: u64 }, } impl_writeable_tlv_based_enum!(InterceptNextHop, @@ -556,13 +577,22 @@ pub enum PaymentFailureReason { /// /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment UserAbandoned, - #[cfg_attr(feature = "std", doc = "We exhausted all of our retry attempts while trying to send the payment, or we")] + #[cfg_attr( + feature = "std", + doc = "We exhausted all of our retry attempts while trying to send the payment, or we" + )] #[cfg_attr(feature = "std", doc = "exhausted the [`Retry::Timeout`] if the user set one.")] - #[cfg_attr(not(feature = "std"), doc = "We exhausted all of our retry attempts while trying to send the payment.")] + #[cfg_attr( + not(feature = "std"), + doc = "We exhausted all of our retry attempts while trying to send the payment." + )] /// If at any point a retry attempt failed while being forwarded along the path, an [`Event::PaymentPathFailed`] will /// have come before this. #[cfg_attr(feature = "std", doc = "")] - #[cfg_attr(feature = "std", doc = "[`Retry::Timeout`]: crate::ln::channelmanager::Retry::Timeout")] + #[cfg_attr( + feature = "std", + doc = "[`Retry::Timeout`]: crate::ln::channelmanager::Retry::Timeout" + )] RetriesExhausted, /// Either the BOLT 12 invoice was expired by the time we received it or the payment expired while /// retrying based on the provided [`PaymentParameters::expiry_time`]. @@ -1507,7 +1537,7 @@ pub enum Event { /// The node id of the peer we just connected to, who advertises support for /// onion messages. peer_node_id: PublicKey, - } + }, } impl Writeable for Event { @@ -1518,9 +1548,17 @@ impl Writeable for Event { // We never write out FundingGenerationReady events as, upon disconnection, peers // drop any channels which have not yet exchanged funding_signed. }, - &Event::PaymentClaimable { ref payment_hash, ref amount_msat, counterparty_skimmed_fee_msat, - ref purpose, ref receiver_node_id, ref via_channel_id, ref via_user_channel_id, - ref claim_deadline, ref onion_fields, ref payment_id, + &Event::PaymentClaimable { + ref payment_hash, + ref amount_msat, + counterparty_skimmed_fee_msat, + ref purpose, + ref receiver_node_id, + ref via_channel_id, + ref via_user_channel_id, + ref claim_deadline, + ref onion_fields, + ref payment_id, } => { 1u8.write(writer)?; let mut payment_secret = None; @@ -1528,20 +1566,25 @@ impl Writeable for Event { let mut payment_context = None; match &purpose { PaymentPurpose::Bolt11InvoicePayment { - payment_preimage: preimage, payment_secret: secret + payment_preimage: preimage, + payment_secret: secret, } => { payment_secret = Some(secret); payment_preimage = *preimage; }, PaymentPurpose::Bolt12OfferPayment { - payment_preimage: preimage, payment_secret: secret, payment_context: context + payment_preimage: preimage, + payment_secret: secret, + payment_context: context, } => { payment_secret = Some(secret); payment_preimage = *preimage; payment_context = Some(PaymentContextRef::Bolt12Offer(context)); }, PaymentPurpose::Bolt12RefundPayment { - payment_preimage: preimage, payment_secret: secret, payment_context: context + payment_preimage: preimage, + payment_secret: secret, + payment_context: context, } => { payment_secret = Some(secret); payment_preimage = *preimage; @@ -1549,10 +1592,13 @@ impl Writeable for Event { }, PaymentPurpose::SpontaneousPayment(preimage) => { payment_preimage = Some(*preimage); - } + }, } - let skimmed_fee_opt = if counterparty_skimmed_fee_msat == 0 { None } - else { Some(counterparty_skimmed_fee_msat) }; + let skimmed_fee_opt = if counterparty_skimmed_fee_msat == 0 { + None + } else { + Some(counterparty_skimmed_fee_msat) + }; write_tlv_fields!(writer, { (0, payment_hash, required), (1, receiver_node_id, option), @@ -1569,7 +1615,14 @@ impl Writeable for Event { (13, payment_id, option), }); }, - &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat, ref bolt12_invoice } => { + &Event::PaymentSent { + ref payment_id, + ref payment_preimage, + ref payment_hash, + ref amount_msat, + ref fee_paid_msat, + ref bolt12_invoice, + } => { 2u8.write(writer)?; write_tlv_fields!(writer, { (0, payment_preimage, required), @@ -1581,8 +1634,12 @@ impl Writeable for Event { }); }, &Event::PaymentPathFailed { - ref payment_id, ref payment_hash, ref payment_failed_permanently, ref failure, - ref path, ref short_channel_id, + ref payment_id, + ref payment_hash, + ref payment_failed_permanently, + ref failure, + ref path, + ref short_channel_id, #[cfg(any(test, feature = "_test_utils"))] ref error_code, #[cfg(any(test, feature = "_test_utils"))] @@ -1618,7 +1675,13 @@ impl Writeable for Event { (1, channel_id, option), }); }, - &Event::HTLCIntercepted { requested_next_hop_scid, payment_hash, inbound_amount_msat, expected_outbound_amount_msat, intercept_id } => { + &Event::HTLCIntercepted { + requested_next_hop_scid, + payment_hash, + inbound_amount_msat, + expected_outbound_amount_msat, + intercept_id, + } => { 6u8.write(writer)?; let intercept_scid = InterceptNextHop::FakeScid { requested_next_hop_scid }; write_tlv_fields!(writer, { @@ -1628,11 +1691,18 @@ impl Writeable for Event { (6, inbound_amount_msat, required), (8, expected_outbound_amount_msat, required), }); - } + }, &Event::PaymentForwarded { - prev_channel_id, next_channel_id, prev_user_channel_id, next_user_channel_id, - prev_node_id, next_node_id, total_fee_earned_msat, skimmed_fee_msat, - claim_from_onchain_tx, outbound_amount_forwarded_msat, + prev_channel_id, + next_channel_id, + prev_user_channel_id, + next_user_channel_id, + prev_node_id, + next_node_id, + total_fee_earned_msat, + skimmed_fee_msat, + claim_from_onchain_tx, + outbound_amount_forwarded_msat, } => { 7u8.write(writer)?; write_tlv_fields!(writer, { @@ -1648,8 +1718,13 @@ impl Writeable for Event { (15, next_node_id, option), }); }, - &Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason, - ref counterparty_node_id, ref channel_capacity_sats, ref channel_funding_txo, + &Event::ChannelClosed { + ref channel_id, + ref user_channel_id, + ref reason, + ref counterparty_node_id, + ref channel_capacity_sats, + ref channel_funding_txo, ref last_local_balance_msat, } => { 9u8.write(writer)?; @@ -1702,21 +1777,25 @@ impl Writeable for Event { None => &None, // Variants available prior to version 0.0.124. Some(PaymentFailureReason::RecipientRejected) - | Some(PaymentFailureReason::UserAbandoned) - | Some(PaymentFailureReason::RetriesExhausted) - | Some(PaymentFailureReason::PaymentExpired) - | Some(PaymentFailureReason::RouteNotFound) - | Some(PaymentFailureReason::UnexpectedError) => reason, + | Some(PaymentFailureReason::UserAbandoned) + | Some(PaymentFailureReason::RetriesExhausted) + | Some(PaymentFailureReason::PaymentExpired) + | Some(PaymentFailureReason::RouteNotFound) + | Some(PaymentFailureReason::UnexpectedError) => reason, // Variants introduced at version 0.0.124 or later. Prior versions fail to parse // unknown variants, while versions 0.0.124 or later will use None. - Some(PaymentFailureReason::UnknownRequiredFeatures) => - &Some(PaymentFailureReason::RecipientRejected), - Some(PaymentFailureReason::InvoiceRequestExpired) => - &Some(PaymentFailureReason::RetriesExhausted), - Some(PaymentFailureReason::InvoiceRequestRejected) => - &Some(PaymentFailureReason::RecipientRejected), - Some(PaymentFailureReason::BlindedPathCreationFailed) => + Some(PaymentFailureReason::UnknownRequiredFeatures) => { + &Some(PaymentFailureReason::RecipientRejected) + }, + Some(PaymentFailureReason::InvoiceRequestExpired) => { + &Some(PaymentFailureReason::RetriesExhausted) + }, + Some(PaymentFailureReason::InvoiceRequestRejected) => { + &Some(PaymentFailureReason::RecipientRejected) + }, + Some(PaymentFailureReason::BlindedPathCreationFailed) => { &Some(PaymentFailureReason::RouteNotFound) + }, }; write_tlv_fields!(writer, { (0, payment_id, required), @@ -1731,8 +1810,14 @@ impl Writeable for Event { // We never write the OpenChannelRequest events as, upon disconnection, peers // drop any channels which have not yet exchanged funding_signed. }, - &Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose, - ref receiver_node_id, ref htlcs, ref sender_intended_total_msat, ref onion_fields, + &Event::PaymentClaimed { + ref payment_hash, + ref amount_msat, + ref purpose, + ref receiver_node_id, + ref htlcs, + ref sender_intended_total_msat, + ref onion_fields, ref payment_id, } => { 19u8.write(writer)?; @@ -1756,7 +1841,12 @@ impl Writeable for Event { (6, path.blinded_tail, option), }) }, - &Event::ProbeFailed { ref payment_id, ref payment_hash, ref path, ref short_channel_id } => { + &Event::ProbeFailed { + ref payment_id, + ref payment_hash, + ref path, + ref short_channel_id, + } => { 23u8.write(writer)?; write_tlv_fields!(writer, { (0, payment_id, required), @@ -1773,17 +1863,22 @@ impl Writeable for Event { (2, failed_next_destination, required), }) }, - &Event::BumpTransaction(ref event)=> { + &Event::BumpTransaction(ref event) => { 27u8.write(writer)?; match event { // We never write the ChannelClose|HTLCResolution events as they'll be replayed // upon restarting anyway if they remain unresolved. - BumpTransactionEvent::ChannelClose { .. } => {} - BumpTransactionEvent::HTLCResolution { .. } => {} + BumpTransactionEvent::ChannelClose { .. } => {}, + BumpTransactionEvent::HTLCResolution { .. } => {}, } write_tlv_fields!(writer, {}); // Write a length field for forwards compat - } - &Event::ChannelReady { ref channel_id, ref user_channel_id, ref counterparty_node_id, ref channel_type } => { + }, + &Event::ChannelReady { + ref channel_id, + ref user_channel_id, + ref counterparty_node_id, + ref channel_type, + } => { 29u8.write(writer)?; write_tlv_fields!(writer, { (0, channel_id, required), @@ -1792,9 +1887,13 @@ impl Writeable for Event { (6, channel_type, required), }); }, - &Event::ChannelPending { ref channel_id, ref user_channel_id, - ref former_temporary_channel_id, ref counterparty_node_id, ref funding_txo, - ref channel_type + &Event::ChannelPending { + ref channel_id, + ref user_channel_id, + ref former_temporary_channel_id, + ref counterparty_node_id, + ref funding_txo, + ref channel_type, } => { 31u8.write(writer)?; write_tlv_fields!(writer, { @@ -1832,7 +1931,13 @@ impl Writeable for Event { (6, responder, option), }); }, - &Event::FundingTxBroadcastSafe { ref channel_id, ref user_channel_id, ref funding_txo, ref counterparty_node_id, ref former_temporary_channel_id} => { + &Event::FundingTxBroadcastSafe { + ref channel_id, + ref user_channel_id, + ref funding_txo, + ref counterparty_node_id, + ref former_temporary_channel_id, + } => { 43u8.write(writer)?; write_tlv_fields!(writer, { (0, channel_id, required), @@ -1885,16 +1990,21 @@ impl MaybeReadable for Event { (13, payment_id, option), }); let purpose = match payment_secret { - Some(secret) => PaymentPurpose::from_parts(payment_preimage, secret, payment_context) - .map_err(|()| msgs::DecodeError::InvalidValue)?, - None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()), + Some(secret) => { + PaymentPurpose::from_parts(payment_preimage, secret, payment_context) + .map_err(|()| msgs::DecodeError::InvalidValue)? + }, + None if payment_preimage.is_some() => { + PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()) + }, None => return Err(msgs::DecodeError::InvalidValue), }; Ok(Some(Event::PaymentClaimable { receiver_node_id, payment_hash, amount_msat, - counterparty_skimmed_fee_msat: counterparty_skimmed_fee_msat_opt.unwrap_or(0), + counterparty_skimmed_fee_msat: counterparty_skimmed_fee_msat_opt + .unwrap_or(0), purpose, via_channel_id, via_user_channel_id, @@ -1922,7 +2032,9 @@ impl MaybeReadable for Event { (9, bolt12_invoice, option), }); if payment_hash.is_none() { - payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array())); + payment_hash = Some(PaymentHash( + Sha256::hash(&payment_preimage.0[..]).to_byte_array(), + )); } Ok(Some(Event::PaymentSent { payment_id, @@ -1961,7 +2073,8 @@ impl MaybeReadable for Event { (11, payment_id, option), (13, failure_opt, upgradable_option), }); - let failure = failure_opt.unwrap_or_else(|| PathFailure::OnPath { network_update }); + let failure = + failure_opt.unwrap_or_else(|| PathFailure::OnPath { network_update }); Ok(Some(Event::PaymentPathFailed { payment_id, payment_hash, @@ -1993,7 +2106,8 @@ impl MaybeReadable for Event { 6u8 => { let mut payment_hash = PaymentHash([0; 32]); let mut intercept_id = InterceptId([0; 32]); - let mut requested_next_hop_scid = InterceptNextHop::FakeScid { requested_next_hop_scid: 0 }; + let mut requested_next_hop_scid = + InterceptNextHop::FakeScid { requested_next_hop_scid: 0 }; let mut inbound_amount_msat = 0; let mut expected_outbound_amount_msat = 0; read_tlv_fields!(reader, { @@ -2004,7 +2118,7 @@ impl MaybeReadable for Event { (8, expected_outbound_amount_msat, required), }); let next_scid = match requested_next_hop_scid { - InterceptNextHop::FakeScid { requested_next_hop_scid: scid } => scid + InterceptNextHop::FakeScid { requested_next_hop_scid: scid } => scid, }; Ok(Some(Event::HTLCIntercepted { payment_hash, @@ -2039,9 +2153,15 @@ impl MaybeReadable for Event { (15, next_node_id, option), }); Ok(Some(Event::PaymentForwarded { - prev_channel_id, next_channel_id, prev_user_channel_id, - next_user_channel_id, prev_node_id, next_node_id, - total_fee_earned_msat, skimmed_fee_msat, claim_from_onchain_tx, + prev_channel_id, + next_channel_id, + prev_user_channel_id, + next_user_channel_id, + prev_node_id, + next_node_id, + total_fee_earned_msat, + skimmed_fee_msat, + claim_from_onchain_tx, outbound_amount_forwarded_msat, })) }; @@ -2071,12 +2191,17 @@ impl MaybeReadable for Event { // `user_channel_id` used to be a single u64 value. In order to remain // backwards compatible with versions prior to 0.0.113, the u128 is serialized // as two separate u64 values. - let user_channel_id = (user_channel_id_low_opt.unwrap_or(0) as u128) + - ((user_channel_id_high_opt.unwrap_or(0) as u128) << 64); + let user_channel_id = (user_channel_id_low_opt.unwrap_or(0) as u128) + + ((user_channel_id_high_opt.unwrap_or(0) as u128) << 64); Ok(Some(Event::ChannelClosed { - channel_id, user_channel_id, reason: _init_tlv_based_struct_field!(reason, upgradable_required), - counterparty_node_id, channel_capacity_sats, channel_funding_txo, last_local_balance_msat, + channel_id, + user_channel_id, + reason: _init_tlv_based_struct_field!(reason, upgradable_required), + counterparty_node_id, + channel_capacity_sats, + channel_funding_txo, + last_local_balance_msat, })) }; f() @@ -2097,7 +2222,7 @@ impl MaybeReadable for Event { } else { funding_info.ok_or(msgs::DecodeError::InvalidValue)? }; - Ok(Some(Event::DiscardFunding { channel_id, funding_info } )) + Ok(Some(Event::DiscardFunding { channel_id, funding_info })) }; f() }, @@ -2225,7 +2350,10 @@ impl MaybeReadable for Event { }); Ok(Some(Event::HTLCHandlingFailed { prev_channel_id, - failed_next_destination: _init_tlv_based_struct_field!(failed_next_destination_opt, upgradable_required), + failed_next_destination: _init_tlv_based_struct_field!( + failed_next_destination_opt, + upgradable_required + ), })) }; f() @@ -2248,7 +2376,7 @@ impl MaybeReadable for Event { channel_id, user_channel_id, counterparty_node_id: counterparty_node_id.0.unwrap(), - channel_type: channel_type.0.unwrap() + channel_type: channel_type.0.unwrap(), })) }; f() @@ -2304,7 +2432,8 @@ impl MaybeReadable for Event { (2, message, required), }); Ok(Some(Event::OnionMessageIntercepted { - peer_node_id: peer_node_id.0.unwrap(), message: message.0.unwrap() + peer_node_id: peer_node_id.0.unwrap(), + message: message.0.unwrap(), })) }; f() @@ -2315,7 +2444,7 @@ impl MaybeReadable for Event { (0, peer_node_id, required), }); Ok(Some(Event::OnionMessagePeerConnected { - peer_node_id: peer_node_id.0.unwrap() + peer_node_id: peer_node_id.0.unwrap(), })) }; f() @@ -2369,10 +2498,11 @@ impl MaybeReadable for Event { // exactly the number of bytes specified, ignoring them entirely. let tlv_len: BigSize = Readable::read(reader)?; FixedLengthReader::new(reader, tlv_len.0) - .eat_remaining().map_err(|_| msgs::DecodeError::ShortRead)?; + .eat_remaining() + .map_err(|_| msgs::DecodeError::ShortRead)?; Ok(None) }, - _ => Err(msgs::DecodeError::InvalidValue) + _ => Err(msgs::DecodeError::InvalidValue), } } } @@ -2421,7 +2551,9 @@ pub trait EventsProvider { /// Processes any events generated since the last call using the given event handler. /// /// See the trait-level documentation for requirements. - fn process_pending_events(&self, handler: H) where H::Target: EventHandler; + fn process_pending_events(&self, handler: H) + where + H::Target: EventHandler; } /// An error type that may be returned to LDK in order to safely abort event handling if it can't @@ -2444,7 +2576,10 @@ pub trait EventHandler { fn handle_event(&self, event: Event) -> Result<(), ReplayEvent>; } -impl EventHandler for F where F: Fn(Event) -> Result<(), ReplayEvent> { +impl EventHandler for F +where + F: Fn(Event) -> Result<(), ReplayEvent>, +{ fn handle_event(&self, event: Event) -> Result<(), ReplayEvent> { self(event) } @@ -2465,7 +2600,7 @@ pub enum PaidBolt12Invoice { /// The Static invoice, used in the async payment specification update proposal, /// where the user cannot perform proof of payment. StaticInvoice(StaticInvoice), - } +} impl_writeable_tlv_based_enum!(PaidBolt12Invoice, {0, Bolt12Invoice} => (), diff --git a/lightning/src/lib.rs b/lightning/src/lib.rs index 5c608d9607a..ec2c5995706 100644 --- a/lightning/src/lib.rs +++ b/lightning/src/lib.rs @@ -31,18 +31,14 @@ #![cfg_attr(not(any(test, fuzzing, feature = "_test_utils")), deny(missing_docs))] #![cfg_attr(not(any(test, feature = "_test_utils")), forbid(unsafe_code))] - #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - // In general, rust is absolutely horrid at supporting users doing things like, // for example, compiling Rust code for real environments. Disable useless lints // that don't do anything but annoy us and cant actually ever be resolved. #![allow(bare_trait_objects)] #![allow(ellipsis_inclusive_range_patterns)] - #![cfg_attr(docsrs, feature(doc_auto_cfg))] - #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] #[cfg(all(fuzzing, test))] @@ -60,24 +56,28 @@ pub extern crate lightning_invoice as bolt11_invoice; #[cfg(any(test, feature = "std"))] extern crate core; -#[cfg(any(test, feature = "_test_utils"))] extern crate regex; +#[cfg(any(test, feature = "_test_utils"))] +extern crate regex; -#[cfg(not(feature = "std"))] extern crate libm; +#[cfg(not(feature = "std"))] +extern crate libm; -#[cfg(ldk_bench)] extern crate criterion; +#[cfg(ldk_bench)] +extern crate criterion; -#[cfg(all(feature = "std", test))] extern crate parking_lot; +#[cfg(all(feature = "std", test))] +extern crate parking_lot; #[macro_use] pub mod util; +pub mod blinded_path; pub mod chain; +pub mod events; pub mod ln; pub mod offers; +pub mod onion_message; pub mod routing; pub mod sign; -pub mod onion_message; -pub mod blinded_path; -pub mod events; pub(crate) mod crypto; @@ -95,7 +95,7 @@ pub mod io_extras { pub use bitcoin::io::sink; pub fn copy(reader: &mut R, writer: &mut W) -> Result - where + where R: Read, W: Write, { @@ -105,7 +105,10 @@ pub mod io_extras { loop { match reader.read(&mut buf) { Ok(0) => break, - Ok(n) => { writer.write_all(&buf[0..n])?; count += n as u64; }, + Ok(n) => { + writer.write_all(&buf[0..n])?; + count += n as u64; + }, Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}, Err(e) => return Err(e.into()), }; @@ -131,7 +134,7 @@ pub mod io_extras { mod prelude { #![allow(unused_imports)] - pub use alloc::{vec, vec::Vec, string::String, collections::VecDeque, boxed::Box}; + pub use alloc::{boxed::Box, collections::VecDeque, string::String, vec, vec::Vec}; pub use alloc::borrow::ToOwned; pub use alloc::string::ToString; diff --git a/lightning/src/ln/async_signer_tests.rs b/lightning/src/ln/async_signer_tests.rs index 1f6f508d837..855054fae06 100644 --- a/lightning/src/ln/async_signer_tests.rs +++ b/lightning/src/ln/async_signer_tests.rs @@ -11,10 +11,10 @@ //! properly with a signer implementation that asynchronously derives signatures. use crate::prelude::*; -use bitcoin::secp256k1::Secp256k1; -use bitcoin::{Transaction, TxOut, TxIn, Amount}; use bitcoin::locktime::absolute::LockTime; +use bitcoin::secp256k1::Secp256k1; use bitcoin::transaction::Version; +use bitcoin::{Amount, Transaction, TxIn, TxOut}; use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS; use crate::chain::ChannelMonitorUpdateStatus; @@ -28,8 +28,8 @@ use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEven use crate::ln::{functional_test_utils::*, msgs}; use crate::sign::ecdsa::EcdsaChannelSigner; use crate::sign::SignerProvider; -use crate::util::test_channel_signer::SignerOp; use crate::util::logger::Logger; +use crate::util::test_channel_signer::SignerOp; #[test] fn test_open_channel() { @@ -51,18 +51,36 @@ fn do_test_open_channel(zero_conf: bool) { let channel_value_satoshis = 100000; let user_channel_id = 42; nodes[0].disable_next_channel_signer_op(SignerOp::GetPerCommitmentPoint); - let channel_id_0 = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, 10001, user_channel_id, None, None).unwrap(); + let channel_id_0 = nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_satoshis, + 10001, + user_channel_id, + None, + None, + ) + .unwrap(); { let msgs = nodes[0].node.get_and_clear_pending_msg_events(); assert!(msgs.is_empty(), "Expected no message events; got {:?}", msgs); } - nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &channel_id_0, SignerOp::GetPerCommitmentPoint); + nodes[0].enable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &channel_id_0, + SignerOp::GetPerCommitmentPoint, + ); nodes[0].node.signer_unblocked(None); // nodes[0] --- open_channel --> nodes[1] - let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let mut open_chan_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); // Handle an inbound channel simulating an async signer. nodes[1].disable_next_channel_signer_op(SignerOp::GetPerCommitmentPoint); @@ -73,11 +91,17 @@ fn do_test_open_channel(zero_conf: bool) { assert_eq!(events.len(), 1, "Expected one event, got {}", events.len()); match &events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf( - temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None) + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) .expect("Unable to accept inbound zero-conf channel"); }, - ev => panic!("Expected OpenChannelRequest, not {:?}", ev) + ev => panic!("Expected OpenChannelRequest, not {:?}", ev), } } else { let msgs = nodes[1].node.get_and_clear_pending_msg_events(); @@ -90,7 +114,11 @@ fn do_test_open_channel(zero_conf: bool) { channels[0].channel_id }; - nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &channel_id_1, SignerOp::GetPerCommitmentPoint); + nodes[1].enable_channel_signer_op( + &nodes[0].node.get_our_node_id(), + &channel_id_1, + SignerOp::GetPerCommitmentPoint, + ); nodes[1].node.signer_unblocked(None); // nodes[0] <-- accept_channel --- nodes[1] @@ -99,8 +127,14 @@ fn do_test_open_channel(zero_conf: bool) { #[test] fn test_funding_created() { - do_test_funding_created(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]); - do_test_funding_created(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]); + do_test_funding_created(vec![ + SignerOp::SignCounterpartyCommitment, + SignerOp::GetPerCommitmentPoint, + ]); + do_test_funding_created(vec![ + SignerOp::GetPerCommitmentPoint, + SignerOp::SignCounterpartyCommitment, + ]); } fn do_test_funding_created(signer_ops: Vec) { @@ -110,24 +144,50 @@ fn do_test_funding_created(signer_ops: Vec) { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); // nodes[0] --- open_channel --> nodes[1] - let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let mut open_chan_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_chan_msg); // nodes[0] <-- accept_channel --- nodes[1] - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); // nodes[0] --- funding_created --> nodes[1] // // But! Let's make node[0]'s signer be unavailable: we should *not* broadcast a funding_created // message... - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); for op in signer_ops.iter() { - nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &temporary_channel_id, *op); + nodes[0].disable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &temporary_channel_id, + *op, + ); } - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors(&nodes[0], 0); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -145,13 +205,21 @@ fn do_test_funding_created(signer_ops: Vec) { nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id))); } - let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let mut funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors(&nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); // nodes[0] <-- funding_signed --- nodes[1] - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); @@ -159,8 +227,14 @@ fn do_test_funding_created(signer_ops: Vec) { #[test] fn test_funding_signed() { - do_test_funding_signed(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]); - do_test_funding_signed(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]); + do_test_funding_signed(vec![ + SignerOp::SignCounterpartyCommitment, + SignerOp::GetPerCommitmentPoint, + ]); + do_test_funding_signed(vec![ + SignerOp::GetPerCommitmentPoint, + SignerOp::SignCounterpartyCommitment, + ]); } fn do_test_funding_signed(signer_ops: Vec) { @@ -170,26 +244,56 @@ fn do_test_funding_signed(signer_ops: Vec) { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); // nodes[0] --- open_channel --> nodes[1] - let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let mut open_chan_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_chan_msg); // nodes[0] <-- accept_channel --- nodes[1] - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); // nodes[0] --- funding_created --> nodes[1] - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors(&nodes[0], 0); - let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let mut funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); // Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should // *not* broadcast a `funding_signed`... for op in signer_ops.iter() { - nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op); + nodes[1].disable_channel_signer_op( + &nodes[0].node.get_our_node_id(), + &temporary_channel_id, + *op, + ); } nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors(&nodes[1], 1); @@ -210,8 +314,14 @@ fn do_test_funding_signed(signer_ops: Vec) { expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); // nodes[0] <-- funding_signed --- nodes[1] - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); + nodes[0] + .node + .handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); } else { @@ -227,12 +337,19 @@ fn test_async_commitment_signature_for_commitment_signed() { SignerOp::GetPerCommitmentPoint, SignerOp::ReleaseCommitmentSecret, SignerOp::SignCounterpartyCommitment, - ].into_iter().filter(|&op| i & (1 << op as u8) != 0).collect(); - do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enable_signer_op_order); + ] + .into_iter() + .filter(|&op| i & (1 << op as u8) != 0) + .collect(); + do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack( + enable_signer_op_order, + ); } } -fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enable_signer_op_order: Vec) { +fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack( + enable_signer_op_order: Vec, +) { let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); @@ -242,9 +359,16 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl // Send a payment. let src = &nodes[0]; let dst = &nodes[1]; - let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(src, dst, 8000000); - src.node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(src, dst, 8000000); + src.node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(src, 1); // Pass the payment along the route. @@ -260,10 +384,25 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl // Mark dst's signer as unavailable and handle src's commitment_signed: while dst won't yet have a // `commitment_signed` of its own to offer, it should publish a `revoke_and_ack`. - dst.disable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, SignerOp::GetPerCommitmentPoint); - dst.disable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, SignerOp::ReleaseCommitmentSecret); - dst.disable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment); - dst.node.handle_commitment_signed_batch_test(src.node.get_our_node_id(), &payment_event.commitment_msg); + dst.disable_channel_signer_op( + &src.node.get_our_node_id(), + &chan_id, + SignerOp::GetPerCommitmentPoint, + ); + dst.disable_channel_signer_op( + &src.node.get_our_node_id(), + &chan_id, + SignerOp::ReleaseCommitmentSecret, + ); + dst.disable_channel_signer_op( + &src.node.get_our_node_id(), + &chan_id, + SignerOp::SignCounterpartyCommitment, + ); + dst.node.handle_commitment_signed_batch_test( + src.node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors(dst, 1); let mut enabled_signer_ops = new_hash_set(); @@ -273,7 +412,9 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl dst.enable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, op); dst.node.signer_unblocked(Some((src.node.get_our_node_id(), chan_id))); - if enabled_signer_ops.contains(&SignerOp::GetPerCommitmentPoint) && enabled_signer_ops.contains(&SignerOp::ReleaseCommitmentSecret) { + if enabled_signer_ops.contains(&SignerOp::GetPerCommitmentPoint) + && enabled_signer_ops.contains(&SignerOp::ReleaseCommitmentSecret) + { // We are just able to send revoke_and_ack if op == SignerOp::GetPerCommitmentPoint || op == SignerOp::ReleaseCommitmentSecret { get_event_msg!(dst, MessageSendEvent::SendRevokeAndACK, src.node.get_our_node_id()); @@ -293,8 +434,14 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(enabl #[test] fn test_funding_signed_0conf() { - do_test_funding_signed_0conf(vec![SignerOp::GetPerCommitmentPoint, SignerOp::SignCounterpartyCommitment]); - do_test_funding_signed_0conf(vec![SignerOp::SignCounterpartyCommitment, SignerOp::GetPerCommitmentPoint]); + do_test_funding_signed_0conf(vec![ + SignerOp::GetPerCommitmentPoint, + SignerOp::SignCounterpartyCommitment, + ]); + do_test_funding_signed_0conf(vec![ + SignerOp::SignCounterpartyCommitment, + SignerOp::GetPerCommitmentPoint, + ]); } fn do_test_funding_signed_0conf(signer_ops: Vec) { @@ -308,8 +455,15 @@ fn do_test_funding_signed_0conf(signer_ops: Vec) { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // nodes[0] --- open_channel --> nodes[1] - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); @@ -318,30 +472,56 @@ fn do_test_funding_signed_0conf(signer_ops: Vec) { assert_eq!(events.len(), 1, "Expected one event, got {}", events.len()); match &events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf( - temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None) + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) .expect("Unable to accept inbound zero-conf channel"); }, - ev => panic!("Expected OpenChannelRequest, not {:?}", ev) + ev => panic!("Expected OpenChannelRequest, not {:?}", ev), } } // nodes[0] <-- accept_channel --- nodes[1] - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); assert_eq!(accept_channel.common_fields.minimum_depth, 0, "Expected minimum depth of 0"); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); // nodes[0] --- funding_created --> nodes[1] - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors(&nodes[0], 0); - let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let mut funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); // Now let's make node[1]'s signer be unavailable while handling the `funding_created`. It should // *not* broadcast a `funding_signed`... for op in signer_ops.iter() { - nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &temporary_channel_id, *op); + nodes[1].disable_channel_signer_op( + &nodes[0].node.get_our_node_id(), + &temporary_channel_id, + *op, + ); } nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors(&nodes[1], 1); @@ -367,11 +547,11 @@ fn do_test_funding_signed_0conf(signer_ops: Vec) { assert_eq!(events.len(), 2); let funding_signed = match &events[0] { MessageSendEvent::SendFundingSigned { msg, .. } => msg.clone(), - ev => panic!("Expected SendFundingSigned, not {:?}", ev) + ev => panic!("Expected SendFundingSigned, not {:?}", ev), }; let channel_ready = match &events[1] { MessageSendEvent::SendChannelReady { msg, .. } => msg.clone(), - ev => panic!("Expected SendChannelReady, not {:?}", ev) + ev => panic!("Expected SendChannelReady, not {:?}", ev), }; (funding_signed, channel_ready) }; @@ -381,7 +561,11 @@ fn do_test_funding_signed_0conf(signer_ops: Vec) { expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); check_added_monitors(&nodes[0], 1); - let channel_ready_0 = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let channel_ready_0 = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ); nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &channel_ready_1); expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id()); @@ -389,8 +573,16 @@ fn do_test_funding_signed_0conf(signer_ops: Vec) { nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &channel_ready_0); expect_channel_ready_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let channel_update_0 = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); - let channel_update_1 = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); + let channel_update_0 = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ); + let channel_update_1 = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_channel_update(nodes[1].node.get_our_node_id(), &channel_update_1); nodes[1].node.handle_channel_update(nodes[0].node.get_our_node_id(), &channel_update_0); @@ -410,13 +602,21 @@ enum UnblockSignerAcrossDisconnectCase { fn test_async_raa_peer_disconnect() { do_test_async_raa_peer_disconnect(UnblockSignerAcrossDisconnectCase::AtEnd, true); do_test_async_raa_peer_disconnect(UnblockSignerAcrossDisconnectCase::AtEnd, false); - do_test_async_raa_peer_disconnect(UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored, true); - do_test_async_raa_peer_disconnect(UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored, false); + do_test_async_raa_peer_disconnect( + UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored, + true, + ); + do_test_async_raa_peer_disconnect( + UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored, + false, + ); do_test_async_raa_peer_disconnect(UnblockSignerAcrossDisconnectCase::BeforeReestablish, true); do_test_async_raa_peer_disconnect(UnblockSignerAcrossDisconnectCase::BeforeReestablish, false); } -fn do_test_async_raa_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCase, raa_blocked_by_commit_point: bool) { +fn do_test_async_raa_peer_disconnect( + test_case: UnblockSignerAcrossDisconnectCase, raa_blocked_by_commit_point: bool, +) { // `raa_blocked_by_commit_point` determines whether we block the RAA by blocking the // signer on `GetPerCommitmentPoint` or `ReleaseCommitmentSecret`. let block_raa_signer_op = if raa_blocked_by_commit_point { @@ -433,9 +633,16 @@ fn do_test_async_raa_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCas // Send a payment. let src = &nodes[0]; let dst = &nodes[1]; - let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(src, dst, 8000000); - src.node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(src, dst, 8000000); + src.node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(src, 1); // Pass the payment along the route. @@ -457,7 +664,10 @@ fn do_test_async_raa_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCas // Mark dst's signer as unavailable and handle src's commitment_signed: while dst won't yet have a // `commitment_signed` of its own to offer, it should publish a `revoke_and_ack`. dst.disable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, block_raa_signer_op); - dst.node.handle_commitment_signed_batch_test(src.node.get_our_node_id(), &payment_event.commitment_msg); + dst.node.handle_commitment_signed_batch_test( + src.node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors(dst, 1); let events = dst.node.get_and_clear_pending_msg_events(); @@ -468,14 +678,30 @@ fn do_test_async_raa_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCas dst.node.peer_disconnected(src.node.get_our_node_id()); // do reestablish stuff - src.node.peer_connected(dst.node.get_our_node_id(), &msgs::Init { - features: dst.node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + src.node + .peer_connected( + dst.node.get_our_node_id(), + &msgs::Init { + features: dst.node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(src, dst); assert_eq!(reestablish_1.len(), 1); - dst.node.peer_connected(src.node.get_our_node_id(), &msgs::Init { - features: src.node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + dst.node + .peer_connected( + src.node.get_our_node_id(), + &msgs::Init { + features: src.node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(dst, src); assert_eq!(reestablish_2.len(), 1); @@ -489,13 +715,21 @@ fn do_test_async_raa_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCas if test_case == UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored { dst.enable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, block_raa_signer_op); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = dst.chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone(); + let (latest_update, _) = dst + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id) + .unwrap() + .clone(); dst.chain_monitor.chain_monitor.force_channel_monitor_updated(chan_id, latest_update); check_added_monitors!(dst, 0); } // Expect the RAA - let (_, revoke_and_ack, commitment_signed, resend_order) = handle_chan_reestablish_msgs!(dst, src); + let (_, revoke_and_ack, commitment_signed, resend_order) = + handle_chan_reestablish_msgs!(dst, src); if test_case == UnblockSignerAcrossDisconnectCase::AtEnd { assert!(revoke_and_ack.is_none()); assert!(commitment_signed.is_none()); @@ -510,7 +744,8 @@ fn do_test_async_raa_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCas dst.node.signer_unblocked(Some((src.node.get_our_node_id(), chan_id))); if test_case == UnblockSignerAcrossDisconnectCase::AtEnd { - let (_, revoke_and_ack, commitment_signed, resend_order) = handle_chan_reestablish_msgs!(dst, src); + let (_, revoke_and_ack, commitment_signed, resend_order) = + handle_chan_reestablish_msgs!(dst, src); assert!(revoke_and_ack.is_some()); assert!(commitment_signed.is_some()); assert!(resend_order == RAACommitmentOrder::RevokeAndACKFirst); @@ -522,7 +757,6 @@ fn do_test_async_raa_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCas } } - #[test] fn test_async_commitment_signature_peer_disconnect() { // This tests that if our signer is blocked and gets unblocked @@ -536,7 +770,9 @@ fn test_async_commitment_signature_peer_disconnect_signer_restored_before_monito // and needed to send a CS, that if our signer becomes available before the monitor // update completes, then we don't send duplicate messages upon calling `signer_unblocked` // after the monitor update completes. - do_test_async_commitment_signature_peer_disconnect(UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored); + do_test_async_commitment_signature_peer_disconnect( + UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored, + ); } #[test] @@ -544,10 +780,14 @@ fn test_async_commitment_signature_peer_disconnect_signer_restored_before_reesta // This tests that if we tried to send a commitment_signed, but our signer was blocked, // if we disconnect, reconnect, the signer becomes available, then handle channel_reestablish, // that we don't send duplicate messages upon calling `signer_unblocked`. - do_test_async_commitment_signature_peer_disconnect(UnblockSignerAcrossDisconnectCase::BeforeReestablish); + do_test_async_commitment_signature_peer_disconnect( + UnblockSignerAcrossDisconnectCase::BeforeReestablish, + ); } -fn do_test_async_commitment_signature_peer_disconnect(test_case: UnblockSignerAcrossDisconnectCase) { +fn do_test_async_commitment_signature_peer_disconnect( + test_case: UnblockSignerAcrossDisconnectCase, +) { let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); @@ -557,9 +797,16 @@ fn do_test_async_commitment_signature_peer_disconnect(test_case: UnblockSignerAc // Send a payment. let src = &nodes[0]; let dst = &nodes[1]; - let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(src, dst, 8000000); - src.node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(src, dst, 8000000); + src.node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(src, 1); // Pass the payment along the route. @@ -580,8 +827,15 @@ fn do_test_async_commitment_signature_peer_disconnect(test_case: UnblockSignerAc // Mark dst's signer as unavailable and handle src's commitment_signed: while dst won't yet have a // `commitment_signed` of its own to offer, it should publish a `revoke_and_ack`. - dst.disable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment); - dst.node.handle_commitment_signed_batch_test(src.node.get_our_node_id(), &payment_event.commitment_msg); + dst.disable_channel_signer_op( + &src.node.get_our_node_id(), + &chan_id, + SignerOp::SignCounterpartyCommitment, + ); + dst.node.handle_commitment_signed_batch_test( + src.node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors(dst, 1); if test_case != UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored { @@ -593,28 +847,59 @@ fn do_test_async_commitment_signature_peer_disconnect(test_case: UnblockSignerAc dst.node.peer_disconnected(src.node.get_our_node_id()); // do reestablish stuff - src.node.peer_connected(dst.node.get_our_node_id(), &msgs::Init { - features: dst.node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + src.node + .peer_connected( + dst.node.get_our_node_id(), + &msgs::Init { + features: dst.node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(src, dst); assert_eq!(reestablish_1.len(), 1); - dst.node.peer_connected(src.node.get_our_node_id(), &msgs::Init { - features: src.node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + dst.node + .peer_connected( + src.node.get_our_node_id(), + &msgs::Init { + features: src.node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(dst, src); assert_eq!(reestablish_2.len(), 1); if test_case == UnblockSignerAcrossDisconnectCase::BeforeReestablish { // Reenable the signer before the reestablish. - dst.enable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment); + dst.enable_channel_signer_op( + &src.node.get_our_node_id(), + &chan_id, + SignerOp::SignCounterpartyCommitment, + ); } dst.node.handle_channel_reestablish(src.node.get_our_node_id(), &reestablish_1[0]); if test_case == UnblockSignerAcrossDisconnectCase::BeforeMonitorRestored { - dst.enable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment); + dst.enable_channel_signer_op( + &src.node.get_our_node_id(), + &chan_id, + SignerOp::SignCounterpartyCommitment, + ); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = dst.chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone(); + let (latest_update, _) = dst + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id) + .unwrap() + .clone(); dst.chain_monitor.chain_monitor.force_channel_monitor_updated(chan_id, latest_update); check_added_monitors!(dst, 0); } @@ -629,7 +914,11 @@ fn do_test_async_commitment_signature_peer_disconnect(test_case: UnblockSignerAc } // Mark dst's signer as available and retry: we now expect to see dst's `commitment_signed`. - dst.enable_channel_signer_op(&src.node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment); + dst.enable_channel_signer_op( + &src.node.get_our_node_id(), + &chan_id, + SignerOp::SignCounterpartyCommitment, + ); dst.node.signer_unblocked(Some((src.node.get_our_node_id(), chan_id))); if test_case == UnblockSignerAcrossDisconnectCase::AtEnd { @@ -670,13 +959,22 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1); - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); // Start to send the second update_add_htlc + commitment_signed, but don't actually make it // to the peer. - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id()); @@ -691,17 +989,31 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events_2.len(), 1); match events_2[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_fulfill_htlcs, ref commitment_signed, .. } } => { - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_fulfill_htlcs[0]); + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: msgs::CommitmentUpdate { ref update_fulfill_htlcs, ref commitment_signed, .. }, + } => { + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage_1, None, false, false); if monitor_update_failure { chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); } - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + commitment_signed, + ); if monitor_update_failure { assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } else { - let _ = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let _ = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); } // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); @@ -714,21 +1026,43 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); assert_eq!(reestablish_1.len(), 1); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); assert_eq!(reestablish_2.len(), 1); // With a fully working signer, here we would send a commitment_signed, // and then revoke_and_ack. With commitment_signed disabled, since // our ordering is CS then RAA, we should make sure we don't send the RAA. - nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment); + nodes[0].disable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignCounterpartyCommitment, + ); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); let as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]); assert!(as_resp.0.is_none()); @@ -737,7 +1071,14 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { if monitor_update_failure { chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_id, latest_update); check_added_monitors!(nodes[0], 0); } @@ -750,7 +1091,11 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { assert!(as_resp.1.is_none()); assert!(as_resp.2.is_none()); - nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignCounterpartyCommitment); + nodes[0].enable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignCounterpartyCommitment, + ); nodes[0].node.signer_unblocked(Some((nodes[1].node.get_our_node_id(), chan_id))); let as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]); @@ -766,10 +1111,19 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { assert!(as_resp.3 == RAACommitmentOrder::CommitmentFirst); // Now that everything is restored, get the CS + RAA and handle them. - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_resp.2.as_ref().unwrap().update_add_htlcs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_resp.2.as_ref().unwrap().commitment_signed); - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), as_resp.1.as_ref().unwrap()); - let (bs_revoke_and_ack, bs_second_commitment_signed) = get_revoke_commit_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); + nodes[1].node.handle_update_add_htlc( + nodes[0].node.get_our_node_id(), + &as_resp.2.as_ref().unwrap().update_add_htlcs[0], + ); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_resp.2.as_ref().unwrap().commitment_signed, + ); + nodes[1] + .node + .handle_revoke_and_ack(nodes[0].node.get_our_node_id(), as_resp.1.as_ref().unwrap()); + let (bs_revoke_and_ack, bs_second_commitment_signed) = + get_revoke_commit_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 2); // The rest of this is boilerplate for resolving the previous state. @@ -778,13 +1132,27 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { let as_commitment_signed = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_commitment_signed); - let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_second_commitment_signed, + ); + let as_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_commitment_signed.commitment_signed); - let bs_second_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_commitment_signed.commitment_signed, + ); + let bs_second_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[1], 1); @@ -799,7 +1167,14 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) { expect_pending_htlcs_forwardable!(nodes[1]); let events_5 = nodes[1].node.get_and_clear_pending_events(); - check_payment_claimable(&events_5[0], payment_hash_2, payment_secret_2, 1_000_000, None, nodes[1].node.get_our_node_id()); + check_payment_claimable( + &events_5[0], + payment_hash_2, + payment_secret_2, + 1_000_000, + None, + nodes[1].node.get_our_node_id(), + ); expect_payment_path_successful!(nodes[0]); claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2); @@ -825,17 +1200,18 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) { version: Version::TWO, lock_time: LockTime::ZERO, input: vec![TxIn { ..Default::default() }], - output: vec![ - TxOut { - value: Amount::ONE_BTC, - script_pubkey: closing_node.wallet_source.get_change_script().unwrap(), - }, - ], + output: vec![TxOut { + value: Amount::ONE_BTC, + script_pubkey: closing_node.wallet_source.get_change_script().unwrap(), + }], }; if anchors { *nodes[0].fee_estimator.sat_per_kw.lock().unwrap() *= 2; *nodes[1].fee_estimator.sat_per_kw.lock().unwrap() *= 2; - closing_node.wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); + closing_node.wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); } // Route an HTLC and set the signer as unavailable. @@ -843,16 +1219,37 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) { route_payment(&nodes[0], &[&nodes[1]], 1_000_000); let error_message = "Channel force-closed"; - if remote_commitment { // Make the counterparty broadcast its latest commitment. - nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors(&nodes[1], 1); check_closed_broadcast(&nodes[1], 1, true); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[0].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[0].node.get_our_node_id()], + 100_000, + ); } else { - nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderCommitment); - nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderHtlcTransaction); + nodes[0].disable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignHolderCommitment, + ); + nodes[0].disable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignHolderHtlcTransaction, + ); // We'll connect blocks until the sender has to go onchain to time out the HTLC. connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); @@ -861,9 +1258,21 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) { assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); // Mark it as available now, we should see the signed commitment transaction. - nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderCommitment); - nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderHtlcTransaction); - get_monitor!(nodes[0], chan_id).signer_unblocked(nodes[0].tx_broadcaster, nodes[0].fee_estimator, &nodes[0].logger); + nodes[0].enable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignHolderCommitment, + ); + nodes[0].enable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignHolderHtlcTransaction, + ); + get_monitor!(nodes[0], chan_id).signer_unblocked( + nodes[0].tx_broadcaster, + nodes[0].fee_estimator, + &nodes[0].logger, + ); } let commitment_tx = { @@ -893,13 +1302,24 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) { } else { SignerOp::SignHolderHtlcTransaction }; - nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderCommitment); + nodes[0].disable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignHolderCommitment, + ); nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, sign_htlc_op); mine_transaction(&nodes[0], &commitment_tx); check_added_monitors(&nodes[0], 1); check_closed_broadcast(&nodes[0], 1, true); - check_closed_event(&nodes[0], 1, ClosureReason::CommitmentTxConfirmed, false, &[nodes[1].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + &[nodes[1].node.get_our_node_id()], + 100_000, + ); // If the counterparty broadcast its latest commitment, we need to mine enough blocks for the // HTLC timeout. @@ -915,9 +1335,17 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) { assert!(txn.is_empty(), "expected no transaction to be broadcast, got {:?}", txn); // Mark it as available now, we should see the signed HTLC transaction. - nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderCommitment); + nodes[0].enable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignHolderCommitment, + ); nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, sign_htlc_op); - get_monitor!(nodes[0], chan_id).signer_unblocked(nodes[0].tx_broadcaster, nodes[0].fee_estimator, &nodes[0].logger); + get_monitor!(nodes[0], chan_id).signer_unblocked( + nodes[0].tx_broadcaster, + nodes[0].fee_estimator, + &nodes[0].logger, + ); if anchors && !remote_commitment { handle_bump_htlc_event(&nodes[0], 1); @@ -976,14 +1404,20 @@ fn do_test_closing_signed(extra_closing_signed: bool, reconnect: bool) { expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::ShutdownInitiated); expect_channel_shutdown_state!(nodes[1], chan_id, ChannelShutdownState::NotShuttingDown); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::ShutdownInitiated); expect_channel_shutdown_state!(nodes[1], chan_id, ChannelShutdownState::NegotiatingClosingFee); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); - nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + nodes[0].disable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignClosingTransaction, + ); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::NegotiatingClosingFee); @@ -991,25 +1425,53 @@ fn do_test_closing_signed(extra_closing_signed: bool, reconnect: bool) { let events = nodes[0].node.get_and_clear_pending_msg_events(); assert!(events.is_empty(), "Expected no events, got {:?}", events); - nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction); + nodes[0].enable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignClosingTransaction, + ); nodes[0].node.signer_unblocked(None); - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); - nodes[1].disable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); + nodes[1].disable_channel_signer_op( + &nodes[0].node.get_our_node_id(), + &chan_id, + SignerOp::SignClosingTransaction, + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert!(events.is_empty(), "Expected no events, got {:?}", events); - nodes[1].enable_channel_signer_op(&nodes[0].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction); + nodes[1].enable_channel_signer_op( + &nodes[0].node.get_our_node_id(), + &chan_id, + SignerOp::SignClosingTransaction, + ); nodes[1].node.signer_unblocked(None); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); - - nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); + + nodes[0].disable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignClosingTransaction, + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert!(events.is_empty(), "Expected no events, got {:?}", events); - nodes[0].enable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignClosingTransaction); + nodes[0].enable_channel_signer_op( + &nodes[1].node.get_our_node_id(), + &chan_id, + SignerOp::SignClosingTransaction, + ); if extra_closing_signed { let node_1_closing_signed_2_bad = { @@ -1017,26 +1479,41 @@ fn do_test_closing_signed(extra_closing_signed: bool, reconnect: bool) { let holder_script = nodes[0].keys_manager.get_shutdown_scriptpubkey().unwrap(); let counterparty_script = nodes[1].keys_manager.get_shutdown_scriptpubkey().unwrap(); let funding_outpoint = bitcoin::OutPoint { txid: funding_tx.compute_txid(), vout: 0 }; - let closing_tx_2 = ClosingTransaction::new(50000, 0, holder_script.into(), - counterparty_script.into(), funding_outpoint); + let closing_tx_2 = ClosingTransaction::new( + 50000, + 0, + holder_script.into(), + counterparty_script.into(), + funding_outpoint, + ); let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); - let mut chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); + let mut chan_lock = + per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); let channel = chan_lock.channel_by_id.get_mut(&chan_id).unwrap(); let (funding, context) = channel.funding_and_context_mut(); let signer = context.get_mut_signer().as_mut_ecdsa().unwrap(); - let signature = signer.sign_closing_transaction(&funding.channel_transaction_parameters, &closing_tx_2, &Secp256k1::new()).unwrap(); + let signature = signer + .sign_closing_transaction( + &funding.channel_transaction_parameters, + &closing_tx_2, + &Secp256k1::new(), + ) + .unwrap(); node_1_closing_signed_2.signature = signature; node_1_closing_signed_2 }; - nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed_2_bad); + nodes[0] + .node + .handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed_2_bad); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { MessageSendEvent::HandleError { - action: msgs::ErrorAction::SendWarningMessage { .. }, ref node_id + action: msgs::ErrorAction::SendWarningMessage { .. }, + ref node_id, } => { assert_eq!(node_id, &nodes[1].node.get_our_node_id()); }, @@ -1054,43 +1531,72 @@ fn do_test_closing_signed(extra_closing_signed: bool, reconnect: bool) { connect_nodes(&nodes[0], &nodes[1]); let node_0_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); let node_1_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); - nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &node_0_reestablish); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &node_1_reestablish); + nodes[1] + .node + .handle_channel_reestablish(nodes[0].node.get_our_node_id(), &node_0_reestablish); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &node_1_reestablish); let node_0_msgs = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(node_0_msgs.len(), 2); let node_0_2nd_shutdown = match node_0_msgs[0] { - MessageSendEvent::SendShutdown { ref msg, .. } => { - msg.clone() - }, + MessageSendEvent::SendShutdown { ref msg, .. } => msg.clone(), _ => panic!(), }; let node_0_2nd_closing_signed = match node_0_msgs[1] { - MessageSendEvent::SendClosingSigned { ref msg, .. } => { - msg.clone() - }, + MessageSendEvent::SendClosingSigned { ref msg, .. } => msg.clone(), _ => panic!(), }; - let node_1_2nd_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_2nd_shutdown = get_event_msg!( + nodes[1], + MessageSendEvent::SendShutdown, + nodes[0].node.get_our_node_id() + ); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_2nd_shutdown); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_2nd_shutdown); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); + nodes[1] + .node + .handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); + nodes[0] + .node + .handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); } nodes[0].node.signer_unblocked(None); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_closing_signed) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_closing_signed) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_closing_signed.is_none()); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[1].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index 368b9cd199a..5f4aef9d1fa 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -7,44 +7,51 @@ // You may not use this file except in accordance with one or both of these // licenses. -use bitcoin::hashes::hex::FromHex; -use bitcoin::hex::DisplayHex; -use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, schnorr}; -use bitcoin::secp256k1::ecdh::SharedSecret; -use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use crate::blinded_path; -use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12RefundContext, ForwardTlvs, PaymentConstraints, PaymentContext, PaymentForwardNode, PaymentRelay, UnauthenticatedReceiveTlvs, PAYMENT_PADDING_ROUND_OFF}; +use crate::blinded_path::payment::{ + BlindedPaymentPath, Bolt12RefundContext, ForwardTlvs, PaymentConstraints, PaymentContext, + PaymentForwardNode, PaymentRelay, UnauthenticatedReceiveTlvs, PAYMENT_PADDING_ROUND_OFF, +}; use crate::blinded_path::utils::is_padded; +use crate::blinded_path::BlindedHop; use crate::events::{Event, HTLCDestination, PaymentFailureReason}; -use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::ln::channelmanager; use crate::ln::channelmanager::{HTLCFailureMsg, PaymentId, RecipientOnionFields}; -use crate::types::features::{BlindedHopFeatures, ChannelFeatures, NodeFeatures}; use crate::ln::functional_test_utils::*; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, UnsignedGossipMessage, MessageSendEvent}; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, MessageSendEvent, UnsignedGossipMessage, +}; use crate::ln::onion_payment; use crate::ln::onion_utils::{self, LocalHTLCFailureReason}; use crate::ln::outbound_payment::{Retry, IDEMPOTENCY_TIMEOUT_TICKS}; +use crate::ln::types::ChannelId; use crate::offers::invoice::UnsignedBolt12Invoice; use crate::offers::nonce::Nonce; use crate::prelude::*; -use crate::routing::router::{BlindedTail, Path, Payee, PaymentParameters, RouteHop, RouteParameters, TrampolineHop}; +use crate::routing::router::Route; +use crate::routing::router::{ + BlindedTail, Path, Payee, PaymentParameters, RouteHop, RouteParameters, TrampolineHop, +}; use crate::sign::{NodeSigner, Recipient}; +use crate::types::features::{BlindedHopFeatures, ChannelFeatures, NodeFeatures}; +use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::util::config::UserConfig; use crate::util::ser::{WithoutLength, Writeable}; use crate::util::test_utils; +use bitcoin::hashes::hex::FromHex; +use bitcoin::hex::DisplayHex; +use bitcoin::secp256k1::ecdh::SharedSecret; +use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; +use bitcoin::secp256k1::{schnorr, PublicKey, Scalar, Secp256k1, SecretKey}; use lightning_invoice::RawBolt11Invoice; use types::features::Features; -use crate::blinded_path::BlindedHop; -use crate::routing::router::Route; pub fn blinded_payment_path( payment_secret: PaymentSecret, intro_node_min_htlc: u64, intro_node_max_htlc: u64, node_ids: Vec, channel_upds: &[&msgs::UnsignedChannelUpdate], - keys_manager: &test_utils::TestKeysInterface + keys_manager: &test_utils::TestKeysInterface, ) -> BlindedPaymentPath { let mut intermediate_nodes = Vec::new(); let mut intro_node_min_htlc_opt = Some(intro_node_min_htlc); @@ -61,13 +68,15 @@ pub fn blinded_payment_path( }, payment_constraints: PaymentConstraints { max_cltv_expiry: u32::max_value(), - htlc_minimum_msat: intro_node_min_htlc_opt.take() + htlc_minimum_msat: intro_node_min_htlc_opt + .take() .unwrap_or_else(|| channel_upds[idx - 1].htlc_minimum_msat), }, next_blinding_override: None, features: BlindedHopFeatures::empty(), }, - htlc_maximum_msat: intro_node_max_htlc_opt.take() + htlc_maximum_msat: intro_node_max_htlc_opt + .take() .unwrap_or_else(|| channel_upds[idx - 1].htlc_maximum_msat), }); } @@ -76,8 +85,8 @@ pub fn blinded_payment_path( payment_secret, payment_constraints: PaymentConstraints { max_cltv_expiry: u32::max_value(), - htlc_minimum_msat: - intro_node_min_htlc_opt.unwrap_or_else(|| channel_upds.last().unwrap().htlc_minimum_msat), + htlc_minimum_msat: intro_node_min_htlc_opt + .unwrap_or_else(|| channel_upds.last().unwrap().htlc_minimum_msat), }, payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}), }; @@ -88,58 +97,94 @@ pub fn blinded_payment_path( let mut secp_ctx = Secp256k1::new(); BlindedPaymentPath::new( - &intermediate_nodes[..], *node_ids.last().unwrap(), payee_tlvs, + &intermediate_nodes[..], + *node_ids.last().unwrap(), + payee_tlvs, intro_node_max_htlc_opt.unwrap_or_else(|| channel_upds.last().unwrap().htlc_maximum_msat), - TEST_FINAL_CLTV as u16, keys_manager, &secp_ctx - ).unwrap() + TEST_FINAL_CLTV as u16, + keys_manager, + &secp_ctx, + ) + .unwrap() } pub fn get_blinded_route_parameters( - amt_msat: u64, payment_secret: PaymentSecret, intro_node_min_htlc: u64, intro_node_max_htlc: u64, - node_ids: Vec, channel_upds: &[&msgs::UnsignedChannelUpdate], - keys_manager: &test_utils::TestKeysInterface + amt_msat: u64, payment_secret: PaymentSecret, intro_node_min_htlc: u64, + intro_node_max_htlc: u64, node_ids: Vec, + channel_upds: &[&msgs::UnsignedChannelUpdate], keys_manager: &test_utils::TestKeysInterface, ) -> RouteParameters { RouteParameters::from_payment_params_and_value( - PaymentParameters::blinded(vec![ - blinded_payment_path( - payment_secret, intro_node_min_htlc, intro_node_max_htlc, node_ids, channel_upds, - keys_manager - ) - ]), amt_msat + PaymentParameters::blinded(vec![blinded_payment_path( + payment_secret, + intro_node_min_htlc, + intro_node_max_htlc, + node_ids, + channel_upds, + keys_manager, + )]), + amt_msat, ) } pub fn fail_blinded_htlc_backwards( - payment_hash: PaymentHash, intro_node_idx: usize, nodes: &[&Node], - retry_expected: bool + payment_hash: PaymentHash, intro_node_idx: usize, nodes: &[&Node], retry_expected: bool, ) { for i in (0..nodes.len()).rev() { match i { 0 => { let mut payment_failed_conditions = PaymentFailedConditions::new() - .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]); + .expected_htlc_error_data( + LocalHTLCFailureReason::InvalidOnionBlinding, + &[0; 32], + ); if retry_expected { payment_failed_conditions = payment_failed_conditions.retry_expected(); } - expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + payment_failed_conditions, + ); }, i if i <= intro_node_idx => { - let unblinded_node_updates = get_htlc_update_msgs!(nodes[i], nodes[i-1].node.get_our_node_id()); + let unblinded_node_updates = + get_htlc_update_msgs!(nodes[i], nodes[i - 1].node.get_our_node_id()); assert_eq!(unblinded_node_updates.update_fail_htlcs.len(), 1); - nodes[i-1].node.handle_update_fail_htlc( - nodes[i].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[i-1] + nodes[i - 1].node.handle_update_fail_htlc( + nodes[i].node.get_our_node_id(), + &unblinded_node_updates.update_fail_htlcs[i - 1], + ); + do_commitment_signed_dance( + &nodes[i - 1], + &nodes[i], + &unblinded_node_updates.commitment_signed, + false, + false, ); - do_commitment_signed_dance(&nodes[i-1], &nodes[i], &unblinded_node_updates.commitment_signed, false, false); }, _ => { - let blinded_node_updates = get_htlc_update_msgs!(nodes[i], nodes[i-1].node.get_our_node_id()); + let blinded_node_updates = + get_htlc_update_msgs!(nodes[i], nodes[i - 1].node.get_our_node_id()); assert_eq!(blinded_node_updates.update_fail_malformed_htlcs.len(), 1); let update_malformed = &blinded_node_updates.update_fail_malformed_htlcs[0]; assert_eq!(update_malformed.sha256_of_onion, [0; 32]); - assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()); - nodes[i-1].node.handle_update_fail_malformed_htlc(nodes[i].node.get_our_node_id(), update_malformed); - do_commitment_signed_dance(&nodes[i-1], &nodes[i], &blinded_node_updates.commitment_signed, true, false); - } + assert_eq!( + update_malformed.failure_code, + LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() + ); + nodes[i - 1].node.handle_update_fail_malformed_htlc( + nodes[i].node.get_our_node_id(), + update_malformed, + ); + do_commitment_signed_dance( + &nodes[i - 1], + &nodes[i], + &blinded_node_updates.commitment_signed, + true, + false, + ); + }, } } } @@ -155,10 +200,12 @@ fn do_one_hop_blinded_path(success: bool) { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; + let chan_upd = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; let amt_msat = 5000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -173,16 +220,30 @@ fn do_one_hop_blinded_path(success: bool) { let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, - &chanmon_cfgs[1].keys_manager, &secp_ctx - ).unwrap(); + &[], + nodes[1].node.get_our_node_id(), + payee_tlvs, + u64::MAX, + TEST_FINAL_CLTV as u16, + &chanmon_cfgs[1].keys_manager, + &secp_ctx, + ) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), amt_msat, ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), - PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); pass_along_route(&nodes[0], &[&[&nodes[1]]], amt_msat, payment_hash, payment_secret); if success { @@ -206,13 +267,14 @@ fn mpp_to_one_hop_blinded_path() { create_announced_chan_between_nodes(&nodes, 2, 3).0.contents; // Ensure all nodes start at the same height. - connect_blocks(&nodes[0], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); - connect_blocks(&nodes[3], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); + connect_blocks(&nodes[0], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[3], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); let amt_msat = 15_000_000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -225,17 +287,33 @@ fn mpp_to_one_hop_blinded_path() { let expanded_key = chanmon_cfgs[3].keys_manager.get_inbound_payment_key(); let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key); let blinded_path = BlindedPaymentPath::new( - &[], nodes[3].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, - &chanmon_cfgs[3].keys_manager, &secp_ctx - ).unwrap(); + &[], + nodes[3].node.get_our_node_id(), + payee_tlvs, + u64::MAX, + TEST_FINAL_CLTV as u16, + &chanmon_cfgs[3].keys_manager, + &secp_ctx, + ) + .unwrap(); - let bolt12_features = - channelmanager::provided_bolt12_invoice_features(&UserConfig::default()); + let bolt12_features = channelmanager::provided_bolt12_invoice_features(&UserConfig::default()); let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::blinded(vec![blinded_path]).with_bolt12_features(bolt12_features).unwrap(), + PaymentParameters::blinded(vec![blinded_path]) + .with_bolt12_features(bolt12_features) + .unwrap(), amt_msat, ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 2); let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]]; @@ -243,15 +321,33 @@ fn mpp_to_one_hop_blinded_path() { assert_eq!(events.len(), 2); let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], expected_route[0], amt_msat, payment_hash.clone(), - Some(payment_secret), ev.clone(), false, None); + pass_along_path( + &nodes[0], + expected_route[0], + amt_msat, + payment_hash.clone(), + Some(payment_secret), + ev.clone(), + false, + None, + ); let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], expected_route[1], amt_msat, payment_hash.clone(), - Some(payment_secret), ev.clone(), true, None); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage) + pass_along_path( + &nodes[0], + expected_route[1], + amt_msat, + payment_hash.clone(), + Some(payment_secret), + ev.clone(), + true, + None, ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + expected_route, + payment_preimage, + )); } #[test] @@ -275,57 +371,99 @@ fn mpp_to_three_hop_blinded_paths() { let chan_upd_4_5 = create_announced_chan_between_nodes(&nodes, 4, 5).0.contents; // Start every node on the same block height to make reasoning about timeouts easier - connect_blocks(&nodes[0], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); - connect_blocks(&nodes[3], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); - connect_blocks(&nodes[4], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[4].best_block_info().1); - connect_blocks(&nodes[5], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[5].best_block_info().1); + connect_blocks(&nodes[0], 6 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 6 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 6 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[3], 6 * CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); + connect_blocks(&nodes[4], 6 * CHAN_CONFIRM_DEPTH + 1 - nodes[4].best_block_info().1); + connect_blocks(&nodes[5], 6 * CHAN_CONFIRM_DEPTH + 1 - nodes[5].best_block_info().1); let amt_msat = 15_000_000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[5], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[5], Some(amt_msat), None); let route_params = { let path_1_params = get_blinded_route_parameters( - amt_msat, payment_secret, 1, 1_0000_0000, vec![ - nodes[1].node.get_our_node_id(), nodes[3].node.get_our_node_id(), - nodes[5].node.get_our_node_id() - ], &[&chan_upd_1_3, &chan_upd_3_5], &chanmon_cfgs[5].keys_manager + amt_msat, + payment_secret, + 1, + 1_0000_0000, + vec![ + nodes[1].node.get_our_node_id(), + nodes[3].node.get_our_node_id(), + nodes[5].node.get_our_node_id(), + ], + &[&chan_upd_1_3, &chan_upd_3_5], + &chanmon_cfgs[5].keys_manager, ); let path_2_params = get_blinded_route_parameters( - amt_msat, payment_secret, 1, 1_0000_0000, vec![ - nodes[2].node.get_our_node_id(), nodes[4].node.get_our_node_id(), - nodes[5].node.get_our_node_id() - ], &[&chan_upd_2_4, &chan_upd_4_5], &chanmon_cfgs[5].keys_manager - ); - let pay_params = PaymentParameters::blinded( + amt_msat, + payment_secret, + 1, + 1_0000_0000, vec![ - path_1_params.payment_params.payee.blinded_route_hints()[0].clone(), - path_2_params.payment_params.payee.blinded_route_hints()[0].clone() - ] - ) - .with_bolt12_features(channelmanager::provided_bolt12_invoice_features(&UserConfig::default())) - .unwrap(); + nodes[2].node.get_our_node_id(), + nodes[4].node.get_our_node_id(), + nodes[5].node.get_our_node_id(), + ], + &[&chan_upd_2_4, &chan_upd_4_5], + &chanmon_cfgs[5].keys_manager, + ); + let pay_params = PaymentParameters::blinded(vec![ + path_1_params.payment_params.payee.blinded_route_hints()[0].clone(), + path_2_params.payment_params.payee.blinded_route_hints()[0].clone(), + ]) + .with_bolt12_features(channelmanager::provided_bolt12_invoice_features( + &UserConfig::default(), + )) + .unwrap(); RouteParameters::from_payment_params_and_value(pay_params, amt_msat) }; - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), - PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 2); - let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3], &nodes[5]], &[&nodes[2], &nodes[4], &nodes[5]]]; + let expected_route: &[&[&Node]] = + &[&[&nodes[1], &nodes[3], &nodes[5]], &[&nodes[2], &nodes[4], &nodes[5]]]; let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], expected_route[0], amt_msat, payment_hash.clone(), - Some(payment_secret), ev.clone(), false, None); + pass_along_path( + &nodes[0], + expected_route[0], + amt_msat, + payment_hash.clone(), + Some(payment_secret), + ev.clone(), + false, + None, + ); let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], expected_route[1], amt_msat, payment_hash.clone(), - Some(payment_secret), ev.clone(), true, None); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage) + pass_along_path( + &nodes[0], + expected_route[1], + amt_msat, + payment_hash.clone(), + Some(payment_secret), + ev.clone(), + true, + None, ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + expected_route, + payment_preimage, + )); } enum ForwardCheckFail { @@ -364,15 +502,31 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) { let chan_upd_2_3 = chan_2_3.0.contents; let amt_msat = 5000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); - let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); + let mut route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), - &[&chan_upd_1_2, &chan_upd_2_3], &chanmon_cfgs[3].keys_manager); + &[&chan_upd_1_2, &chan_upd_2_3], + &chanmon_cfgs[3].keys_manager, + ); route_params.payment_params.max_path_length = 16; let route = get_route(&nodes[0], &route_params).unwrap(); node_cfgs[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); macro_rules! cause_error { @@ -422,28 +576,48 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) { if intro_fails { let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false); let failed_destination = match check { ForwardCheckFail::InboundOnionCheck => HTLCDestination::InvalidOnion, ForwardCheckFail::ForwardPayloadEncodedAsReceive => HTLCDestination::InvalidOnion, - ForwardCheckFail::OutboundChannelCheck => - HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_1_2.2 }, + ForwardCheckFail::OutboundChannelCheck => HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_1_2.2, + }, }; expect_htlc_handling_failed_destinations!( - nodes[1].node.get_and_clear_pending_events(), &[failed_destination.clone()] + nodes[1].node.get_and_clear_pending_events(), + &[failed_destination.clone()] ); match check { ForwardCheckFail::ForwardPayloadEncodedAsReceive => { - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[0; 0])); - } + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().expected_htlc_error_data( + LocalHTLCFailureReason::InvalidOnionPayload, + &[0; 0], + ), + ); + }, _ => { - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32])); - } + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().expected_htlc_error_data( + LocalHTLCFailureReason::InvalidOnionBlinding, + &[0; 32], + ), + ); + }, }; - return + return; } let mut updates_1_2 = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id()); @@ -457,31 +631,48 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) { expect_pending_htlcs_forwardable!(nodes[2]); let failed_destination = match check { - ForwardCheckFail::InboundOnionCheck|ForwardCheckFail::ForwardPayloadEncodedAsReceive => HTLCDestination::InvalidOnion, - ForwardCheckFail::OutboundChannelCheck => - HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 }, + ForwardCheckFail::InboundOnionCheck | ForwardCheckFail::ForwardPayloadEncodedAsReceive => { + HTLCDestination::InvalidOnion + }, + ForwardCheckFail::OutboundChannelCheck => HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_2_3.2, + }, }; expect_htlc_handling_failed_destinations!( - nodes[2].node.get_and_clear_pending_events(), &[failed_destination.clone()] + nodes[2].node.get_and_clear_pending_events(), + &[failed_destination.clone()] ); check_added_monitors!(nodes[2], 1); let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); let update_malformed = &mut updates.update_fail_malformed_htlcs[0]; - assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()); + assert_eq!( + update_malformed.failure_code, + LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() + ); assert_eq!(update_malformed.sha256_of_onion, [0; 32]); // Ensure the intro node will properly blind the error if its downstream node failed to do so. update_malformed.sha256_of_onion = [1; 32]; update_malformed.failure_code = LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() ^ 1; - nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); + nodes[1] + .node + .handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, true, false); let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]), + ); } #[test] @@ -493,15 +684,32 @@ fn failed_backwards_to_intro_node() { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); - let chan_upd_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; + let chan_upd_1_2 = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; let amt_msat = 5000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); - let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, - nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2], - &chanmon_cfgs[2].keys_manager); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_1_2], + &chanmon_cfgs[2].keys_manager, + ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -527,26 +735,41 @@ fn failed_backwards_to_intro_node() { do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event.commitment_msg, true, true); expect_pending_htlcs_forwardable!(nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::InvalidOnion]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::InvalidOnion] + ); check_added_monitors(&nodes[2], 1); let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); let mut update_malformed = &mut updates.update_fail_malformed_htlcs[0]; // Check that the final node encodes its failure correctly. - assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()); + assert_eq!( + update_malformed.failure_code, + LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() + ); assert_eq!(update_malformed.sha256_of_onion, [0; 32]); // Modify such the final hop does not correctly blind their error so we can ensure the intro node // converts it to the correct error. update_malformed.sha256_of_onion = [1; 32]; - nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); + nodes[1] + .node + .handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, true, false); let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]), + ); } enum ProcessPendingHTLCsCheck { @@ -556,12 +779,20 @@ enum ProcessPendingHTLCsCheck { #[test] fn forward_fail_in_process_pending_htlc_fwds() { - do_forward_fail_in_process_pending_htlc_fwds(ProcessPendingHTLCsCheck::FwdPeerDisconnected, true); - do_forward_fail_in_process_pending_htlc_fwds(ProcessPendingHTLCsCheck::FwdPeerDisconnected, false); + do_forward_fail_in_process_pending_htlc_fwds( + ProcessPendingHTLCsCheck::FwdPeerDisconnected, + true, + ); + do_forward_fail_in_process_pending_htlc_fwds( + ProcessPendingHTLCsCheck::FwdPeerDisconnected, + false, + ); do_forward_fail_in_process_pending_htlc_fwds(ProcessPendingHTLCsCheck::FwdChannelClosed, true); do_forward_fail_in_process_pending_htlc_fwds(ProcessPendingHTLCsCheck::FwdChannelClosed, false); } -fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck, intro_fails: bool) { +fn do_forward_fail_in_process_pending_htlc_fwds( + check: ProcessPendingHTLCsCheck, intro_fails: bool, +) { // Ensure the intro node will error backwards properly if the HTLC fails in // process_pending_htlc_forwards. let chanmon_cfgs = create_chanmon_cfgs(4); @@ -580,12 +811,28 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck, let error_message = "Channel force-closed"; let amt_msat = 5000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); - let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, - nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2, &chan_upd_2_3], - &chanmon_cfgs[2].keys_manager); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_1_2, &chan_upd_2_3], + &chanmon_cfgs[2].keys_manager, + ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -637,7 +884,7 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck, cause_error!(nodes[0], nodes[1], nodes[2], chan_id_1_2, chan_upd_1_2.short_channel_id); check_added_monitors!(nodes[1], 1); fail_blinded_htlc_backwards(payment_hash, 1, &[&nodes[0], &nodes[1]], false); - return + return; } expect_pending_htlcs_forwardable!(nodes[1]); @@ -654,20 +901,32 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck, let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); let update_malformed = &mut updates.update_fail_malformed_htlcs[0]; - assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()); + assert_eq!( + update_malformed.failure_code, + LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() + ); assert_eq!(update_malformed.sha256_of_onion, [0; 32]); // Ensure the intro node will properly blind the error if its downstream node failed to do so. update_malformed.sha256_of_onion = [1; 32]; update_malformed.failure_code = LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() ^ 1; - nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); + nodes[1] + .node + .handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, true, false); let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]), + ); } #[test] @@ -680,7 +939,8 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let mut intercept_forwards_config = test_default_channel_config(); intercept_forwards_config.accept_intercept_htlcs = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), None]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); let (channel_id, chan_upd) = { @@ -689,16 +949,31 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) { }; let amt_msat = 5000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); let intercept_scid = nodes[1].node.get_intercept_scid(); let mut intercept_chan_upd = chan_upd; intercept_chan_upd.short_channel_id = intercept_scid; - let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, - nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&intercept_chan_upd], - &chanmon_cfgs[2].keys_manager); + let route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&intercept_chan_upd], + &chanmon_cfgs[2].keys_manager, + ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), - PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let payment_event = { let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -713,26 +988,40 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) { assert_eq!(events.len(), 1); let (intercept_id, expected_outbound_amount_msat) = match events[0] { crate::events::Event::HTLCIntercepted { - intercept_id, payment_hash: pmt_hash, - requested_next_hop_scid: short_channel_id, expected_outbound_amount_msat, .. + intercept_id, + payment_hash: pmt_hash, + requested_next_hop_scid: short_channel_id, + expected_outbound_amount_msat, + .. } => { assert_eq!(pmt_hash, payment_hash); assert_eq!(short_channel_id, intercept_scid); (intercept_id, expected_outbound_amount_msat) }, - _ => panic!() + _ => panic!(), }; if intercept_node_fails { nodes[1].node.fail_intercepted_htlc(intercept_id).unwrap(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::UnknownNextHop { requested_forward_scid: intercept_scid }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::UnknownNextHop { requested_forward_scid: intercept_scid }] + ); nodes[1].node.process_pending_htlc_forwards(); check_added_monitors!(&nodes[1], 1); fail_blinded_htlc_backwards(payment_hash, 1, &[&nodes[0], &nodes[1]], false); - return + return; } - nodes[1].node.forward_intercepted_htlc(intercept_id, &channel_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap(); + nodes[1] + .node + .forward_intercepted_htlc( + intercept_id, + &channel_id, + nodes[2].node.get_our_node_id(), + expected_outbound_amount_msat, + ) + .unwrap(); expect_pending_htlcs_forwardable!(nodes[1]); let payment_event = { @@ -749,10 +1038,19 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) { commitment_signed_dance!(nodes[2], nodes[1], &payment_event.commitment_msg, false, true); expect_pending_htlcs_forwardable!(nodes[2]); - expect_payment_claimable!(&nodes[2], payment_hash, payment_secret, amt_msat, None, nodes[2].node.get_our_node_id()); - do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + expect_payment_claimable!( + &nodes[2], + payment_hash, + payment_secret, + amt_msat, + None, + nodes[2].node.get_our_node_id() ); + do_claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + payment_preimage, + )); expect_payment_sent(&nodes[0], payment_preimage, Some(Some(1000)), true, true); } @@ -763,15 +1061,32 @@ fn two_hop_blinded_path_success() { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); - let chan_upd_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; + let chan_upd_1_2 = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; let amt_msat = 5000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); - let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, - nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2], - &chanmon_cfgs[2].keys_manager); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_1_2], + &chanmon_cfgs[2].keys_manager, + ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); @@ -785,8 +1100,10 @@ fn three_hop_blinded_path_success() { let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); - let chan_upd_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; - let chan_upd_3_4 = create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0).0.contents; + let chan_upd_2_3 = + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; + let chan_upd_3_4 = + create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0).0.contents; // Get all our nodes onto the same height so payments don't fail for CLTV violations. connect_blocks(&nodes[0], nodes[4].best_block_info().1 - nodes[0].best_block_info().1); @@ -795,14 +1112,36 @@ fn three_hop_blinded_path_success() { assert_eq!(nodes[4].best_block_info().1, nodes[3].best_block_info().1); let amt_msat = 5000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); - let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); + let route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(), - &[&chan_upd_2_3, &chan_upd_3_4], &chanmon_cfgs[4].keys_manager); + &[&chan_upd_2_3, &chan_upd_3_4], + &chanmon_cfgs[4].keys_manager, + ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], + amt_msat, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]], payment_preimage); } @@ -815,26 +1154,56 @@ fn three_hop_blinded_path_fail() { let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); - let chan_upd_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; - let chan_upd_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; + let chan_upd_1_2 = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; + let chan_upd_2_3 = + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; let amt_msat = 5000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); - let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); + let route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), - &[&chan_upd_1_2, &chan_upd_2_3], &chanmon_cfgs[3].keys_manager); + &[&chan_upd_1_2, &chan_upd_2_3], + &chanmon_cfgs[3].keys_manager, + ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], amt_msat, payment_hash, payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2], &nodes[3]]], + amt_msat, + payment_hash, + payment_secret, + ); nodes[3].node.fail_htlc_backwards(&payment_hash); expect_pending_htlcs_forwardable_conditions( - nodes[3].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }] + nodes[3].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }], ); nodes[3].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[3], 1); - fail_blinded_htlc_backwards(payment_hash, 1, &[&nodes[0], &nodes[1], &nodes[2], &nodes[3]], false); + fail_blinded_htlc_backwards( + payment_hash, + 1, + &[&nodes[0], &nodes[1], &nodes[2], &nodes[3]], + false, + ); } #[derive(PartialEq)] @@ -877,9 +1246,8 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { *nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some(session_priv); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); let (chan_upd_1_2, chan_id_1_2) = { - let (chan_upd, _, channel_id, ..) = create_announced_chan_between_nodes_with_value( - &nodes, 1, 2, 1_000_000, 0 - ); + let (chan_upd, _, channel_id, ..) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); (chan_upd.contents, channel_id) }; @@ -887,19 +1255,33 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { let excess_final_cltv_delta_opt = if check == ReceiveCheckFail::ProcessPendingHTLCsCheck { // Set the final CLTV expiry too low to trigger the failure in process_pending_htlc_forwards. Some(TEST_FINAL_CLTV as u16 - 2) - } else { None }; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), excess_final_cltv_delta_opt); - let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, - nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2], - &chanmon_cfgs[2].keys_manager); + } else { + None + }; + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), excess_final_cltv_delta_opt); + let mut route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_1_2], + &chanmon_cfgs[2].keys_manager, + ); route_params.payment_params.max_path_length = 17; let route = if check == ReceiveCheckFail::ProcessPendingHTLCsCheck { let mut route = get_route(&nodes[0], &route_params).unwrap(); // Set the final CLTV expiry too low to trigger the failure in process_pending_htlc_forwards. - route.paths[0].hops.last_mut().map(|h| h.cltv_expiry_delta += excess_final_cltv_delta_opt.unwrap() as u32); - route.paths[0].blinded_tail.as_mut().map(|bt| bt.excess_final_cltv_expiry_delta = excess_final_cltv_delta_opt.unwrap() as u32); + route.paths[0] + .hops + .last_mut() + .map(|h| h.cltv_expiry_delta += excess_final_cltv_delta_opt.unwrap() as u32); + route.paths[0].blinded_tail.as_mut().map(|bt| { + bt.excess_final_cltv_expiry_delta = excess_final_cltv_delta_opt.unwrap() as u32 + }); route } else if check == ReceiveCheckFail::PaymentConstraints { // Create a blinded path where the receiver's encrypted payload has an htlc_minimum_msat that is @@ -908,23 +1290,42 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { let high_htlc_min_bp = { let mut high_htlc_minimum_upd = chan_upd_1_2.clone(); high_htlc_minimum_upd.htlc_minimum_msat = amt_msat + 1000; - let high_htlc_min_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, - nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&high_htlc_minimum_upd], - &chanmon_cfgs[2].keys_manager); + let high_htlc_min_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&high_htlc_minimum_upd], + &chanmon_cfgs[2].keys_manager, + ); if let Payee::Blinded { route_hints, .. } = high_htlc_min_params.payment_params.payee { route_hints[0].clone() - } else { panic!() } + } else { + panic!() + } }; if let Payee::Blinded { ref mut route_hints, .. } = route_params.payment_params.payee { route_hints[0] = high_htlc_min_bp; route_hints[0].payinfo.htlc_minimum_msat = amt_msat; - } else { panic!() } + } else { + panic!() + } find_route(&nodes[0], &route_params).unwrap() } else { find_route(&nodes[0], &route_params).unwrap() }; node_cfgs[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut payment_event_0_1 = { @@ -933,9 +1334,17 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); SendEvent::from_event(ev) }; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event_0_1.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event_0_1.msgs[0]); check_added_monitors!(nodes[1], 0); - do_commitment_signed_dance(&nodes[1], &nodes[0], &payment_event_0_1.commitment_msg, false, false); + do_commitment_signed_dance( + &nodes[1], + &nodes[0], + &payment_event_0_1.commitment_msg, + false, + false, + ); expect_pending_htlcs_forwardable!(nodes[1]); check_added_monitors!(&nodes[1], 1); @@ -948,47 +1357,93 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { match check { ReceiveCheckFail::RecipientFail => { - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event_1_2.msgs[0]); + nodes[2].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &payment_event_1_2.msgs[0], + ); check_added_monitors!(nodes[2], 0); - do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true); + do_commitment_signed_dance( + &nodes[2], + &nodes[1], + &payment_event_1_2.commitment_msg, + true, + true, + ); expect_pending_htlcs_forwardable!(nodes[2]); check_payment_claimable( - &nodes[2].node.get_and_clear_pending_events()[0], payment_hash, payment_secret, amt_msat, - None, nodes[2].node.get_our_node_id() + &nodes[2].node.get_and_clear_pending_events()[0], + payment_hash, + payment_secret, + amt_msat, + None, + nodes[2].node.get_our_node_id(), ); nodes[2].node.fail_htlc_backwards(&payment_hash); expect_pending_htlcs_forwardable_conditions( - nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }] + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }], ); nodes[2].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[2], 1); }, ReceiveCheckFail::OnionDecodeFail => { let session_priv = SecretKey::from_slice(&session_priv).unwrap(); - let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); + let mut onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); let cur_height = nodes[0].best_block_info().1; let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (mut onion_payloads, ..) = onion_utils::build_onion_payloads( - &route.paths[0], amt_msat, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); + &route.paths[0], + amt_msat, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); let update_add = &mut payment_event_1_2.msgs[0]; onion_payloads.last_mut().map(|p| { - if let msgs::OutboundOnionPayload::BlindedReceive { ref mut intro_node_blinding_point, .. } = p { + if let msgs::OutboundOnionPayload::BlindedReceive { + ref mut intro_node_blinding_point, + .. + } = p + { // The receiver should error if both the update_add blinding_point and the // intro_node_blinding_point are set. - assert!(intro_node_blinding_point.is_none() && update_add.blinding_point.is_some()); + assert!( + intro_node_blinding_point.is_none() && update_add.blinding_point.is_some() + ); *intro_node_blinding_point = Some(PublicKey::from_slice(&[2; 33]).unwrap()); - } else { panic!() } + } else { + panic!() + } }); update_add.onion_routing_packet = onion_utils::construct_onion_packet( - vec![onion_payloads.pop().unwrap()], vec![onion_keys.pop().unwrap()], [0; 32], - &payment_hash - ).unwrap(); + vec![onion_payloads.pop().unwrap()], + vec![onion_keys.pop().unwrap()], + [0; 32], + &payment_hash, + ) + .unwrap(); nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), update_add); check_added_monitors!(nodes[2], 0); - do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true); + do_commitment_signed_dance( + &nodes[2], + &nodes[1], + &payment_event_1_2.commitment_msg, + true, + true, + ); expect_pending_htlcs_forwardable!(nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::InvalidOnion]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::InvalidOnion] + ); check_added_monitors(&nodes[2], 1); }, ReceiveCheckFail::ReceiveRequirements => { @@ -996,74 +1451,144 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { update_add.amount_msat -= 1; nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), update_add); check_added_monitors!(nodes[2], 0); - do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true); + do_commitment_signed_dance( + &nodes[2], + &nodes[1], + &payment_event_1_2.commitment_msg, + true, + true, + ); expect_pending_htlcs_forwardable!(nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors(&nodes[2], 1); }, ReceiveCheckFail::ChannelCheck => { nodes[2].node.close_channel(&chan_id_1_2, &nodes[1].node.get_our_node_id()).unwrap(); - let node_2_shutdown = get_event_msg!(nodes[2], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_2_shutdown = get_event_msg!( + nodes[2], + MessageSendEvent::SendShutdown, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_shutdown(nodes[2].node.get_our_node_id(), &node_2_shutdown); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id()); + let node_1_shutdown = get_event_msg!( + nodes[1], + MessageSendEvent::SendShutdown, + nodes[2].node.get_our_node_id() + ); - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event_1_2.msgs[0]); - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &payment_event_1_2.commitment_msg); + nodes[2].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &payment_event_1_2.msgs[0], + ); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &payment_event_1_2.commitment_msg, + ); check_added_monitors!(nodes[2], 1); nodes[2].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); commitment_signed_dance!(nodes[2], nodes[1], (), false, true, false, false); expect_pending_htlcs_forwardable!(nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors(&nodes[2], 1); }, ReceiveCheckFail::ProcessPendingHTLCsCheck => { - assert_eq!(payment_event_1_2.msgs[0].cltv_expiry, nodes[0].best_block_info().1 + 1 + excess_final_cltv_delta_opt.unwrap() as u32 + TEST_FINAL_CLTV); - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event_1_2.msgs[0]); + assert_eq!( + payment_event_1_2.msgs[0].cltv_expiry, + nodes[0].best_block_info().1 + + 1 + excess_final_cltv_delta_opt.unwrap() as u32 + + TEST_FINAL_CLTV + ); + nodes[2].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &payment_event_1_2.msgs[0], + ); check_added_monitors!(nodes[2], 0); - do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true); + do_commitment_signed_dance( + &nodes[2], + &nodes[1], + &payment_event_1_2.commitment_msg, + true, + true, + ); expect_pending_htlcs_forwardable!(nodes[2]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[2], - vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[2], 1); }, ReceiveCheckFail::PaymentConstraints => { - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event_1_2.msgs[0]); + nodes[2].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &payment_event_1_2.msgs[0], + ); check_added_monitors!(nodes[2], 0); - do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true); + do_commitment_signed_dance( + &nodes[2], + &nodes[1], + &payment_event_1_2.commitment_msg, + true, + true, + ); expect_pending_htlcs_forwardable!(nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors(&nodes[2], 1); - } + }, } let updates_2_1 = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); assert_eq!(updates_2_1.update_fail_malformed_htlcs.len(), 1); let update_malformed = &updates_2_1.update_fail_malformed_htlcs[0]; assert_eq!(update_malformed.sha256_of_onion, [0; 32]); - assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()); - nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); + assert_eq!( + update_malformed.failure_code, + LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() + ); + nodes[1] + .node + .handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed); do_commitment_signed_dance(&nodes[1], &nodes[2], &updates_2_1.commitment_signed, true, false); let updates_1_0 = if check == ReceiveCheckFail::ChannelCheck { let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); - events.into_iter().find_map(|ev| { - match ev { + events + .into_iter() + .find_map(|ev| match ev { MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, updates } => { assert_eq!(node_id, nodes[0].node.get_our_node_id()); - return Some(updates) + return Some(updates); }, MessageSendEvent::SendClosingSigned { .. } => None, - _ => panic!() - } - }).unwrap() - } else { get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()) }; + _ => panic!(), + }) + .unwrap() + } else { + get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()) + }; assert_eq!(updates_1_0.update_fail_htlcs.len(), 1); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates_1_0.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates_1_0.update_fail_htlcs[0], + ); do_commitment_signed_dance(&nodes[0], &nodes[1], &updates_1_0.commitment_signed, false, false); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]), + ); } #[test] @@ -1073,7 +1598,8 @@ fn blinded_path_retries() { let mut higher_fee_chan_cfg = test_default_channel_config(); higher_fee_chan_cfg.channel_config.forwarding_fee_base_msat += 1; let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, Some(higher_fee_chan_cfg), None]); + let node_chanmgrs = + create_node_chanmgrs(4, &node_cfgs, &[None, None, Some(higher_fee_chan_cfg), None]); let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs); // Create this network topology so nodes[0] has a blinded route hint to retry over. @@ -1088,32 +1614,50 @@ fn blinded_path_retries() { let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0); // Ensure all nodes start at the same height. - connect_blocks(&nodes[0], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); - connect_blocks(&nodes[3], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); + connect_blocks(&nodes[0], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[3], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); let amt_msat = 5000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); let route_params = { - let pay_params = PaymentParameters::blinded( - vec![ - blinded_payment_path(payment_secret, 1, 1_0000_0000, - vec![nodes[1].node.get_our_node_id(), nodes[3].node.get_our_node_id()], &[&chan_1_3.0.contents], - &chanmon_cfgs[3].keys_manager - ), - blinded_payment_path(payment_secret, 1, 1_0000_0000, - vec![nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()], &[&chan_2_3.0.contents], - &chanmon_cfgs[3].keys_manager - ), - ] - ) - .with_bolt12_features(channelmanager::provided_bolt12_invoice_features(&UserConfig::default())) - .unwrap(); + let pay_params = PaymentParameters::blinded(vec![ + blinded_payment_path( + payment_secret, + 1, + 1_0000_0000, + vec![nodes[1].node.get_our_node_id(), nodes[3].node.get_our_node_id()], + &[&chan_1_3.0.contents], + &chanmon_cfgs[3].keys_manager, + ), + blinded_payment_path( + payment_secret, + 1, + 1_0000_0000, + vec![nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()], + &[&chan_2_3.0.contents], + &chanmon_cfgs[3].keys_manager, + ), + ]) + .with_bolt12_features(channelmanager::provided_bolt12_invoice_features( + &UserConfig::default(), + )) + .unwrap(); RouteParameters::from_payment_params_and_value(pay_params, amt_msat) }; - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(2)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(2), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]]], amt_msat, payment_hash, payment_secret); @@ -1121,7 +1665,8 @@ fn blinded_path_retries() { ($intro_node: expr) => { nodes[3].node.fail_htlc_backwards(&payment_hash); expect_pending_htlcs_forwardable_conditions( - nodes[3].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }] + nodes[3].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }], ); nodes[3].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[3], 1); @@ -1130,19 +1675,44 @@ fn blinded_path_retries() { assert_eq!(updates.update_fail_malformed_htlcs.len(), 1); let update_malformed = &updates.update_fail_malformed_htlcs[0]; assert_eq!(update_malformed.sha256_of_onion, [0; 32]); - assert_eq!(update_malformed.failure_code, LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()); - $intro_node.node.handle_update_fail_malformed_htlc(nodes[3].node.get_our_node_id(), update_malformed); - do_commitment_signed_dance(&$intro_node, &nodes[3], &updates.commitment_signed, true, false); + assert_eq!( + update_malformed.failure_code, + LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() + ); + $intro_node.node.handle_update_fail_malformed_htlc( + nodes[3].node.get_our_node_id(), + update_malformed, + ); + do_commitment_signed_dance( + &$intro_node, + &nodes[3], + &updates.commitment_signed, + true, + false, + ); - let updates = get_htlc_update_msgs!($intro_node, nodes[0].node.get_our_node_id()); + let updates = get_htlc_update_msgs!($intro_node, nodes[0].node.get_our_node_id()); assert_eq!(updates.update_fail_htlcs.len(), 1); - nodes[0].node.handle_update_fail_htlc($intro_node.node.get_our_node_id(), &updates.update_fail_htlcs[0]); - do_commitment_signed_dance(&nodes[0], &$intro_node, &updates.commitment_signed, false, false); + nodes[0].node.handle_update_fail_htlc( + $intro_node.node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); + do_commitment_signed_dance( + &nodes[0], + &$intro_node, + &updates.commitment_signed, + false, + false, + ); let mut events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, .. } => { + Event::PaymentPathFailed { + payment_hash: ev_payment_hash, + payment_failed_permanently, + .. + } => { assert_eq!(payment_hash, ev_payment_hash); assert_eq!(payment_failed_permanently, false); }, @@ -1153,7 +1723,7 @@ fn blinded_path_retries() { _ => panic!("Unexpected event"), } nodes[0].node.process_pending_htlc_forwards(); - } + }; } fail_payment_back!(nodes[1]); @@ -1162,7 +1732,16 @@ fn blinded_path_retries() { check_added_monitors!(nodes[0], 1); let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], amt_msat, payment_hash, Some(payment_secret), msg_events.pop().unwrap(), true, None); + pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + amt_msat, + payment_hash, + Some(payment_secret), + msg_events.pop().unwrap(), + true, + None, + ); fail_payment_back!(nodes[2]); let evs = nodes[0].node.get_and_clear_pending_events(); @@ -1173,7 +1752,7 @@ fn blinded_path_retries() { // We have 1 retry attempt remaining, but we're out of blinded paths to try. assert_eq!(reason, Some(PaymentFailureReason::RouteNotFound)); }, - _ => panic!() + _ => panic!(), } } @@ -1193,7 +1772,11 @@ fn min_htlc() { node_2_cfg.channel_config.forwarding_fee_proportional_millionths = 150_000; let mut node_3_cfg = test_default_channel_config(); node_3_cfg.channel_handshake_config.our_htlc_minimum_msat = 2000; - let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg)]); + let node_chanmgrs = create_node_chanmgrs( + 4, + &node_cfgs, + &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg)], + ); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); @@ -1202,22 +1785,49 @@ fn min_htlc() { let min_htlc_msat = { // The min htlc for this setup is nodes[2]'s htlc_minimum_msat minus the // following fees. - let post_base_fee = chan_2_3.1.contents.htlc_minimum_msat - chan_2_3.0.contents.fee_base_msat as u64; + let post_base_fee = + chan_2_3.1.contents.htlc_minimum_msat - chan_2_3.0.contents.fee_base_msat as u64; let prop_fee = chan_2_3.0.contents.fee_proportional_millionths as u64; (post_base_fee * 1_000_000 + 1_000_000 + prop_fee - 1) / (prop_fee + 1_000_000) }; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(min_htlc_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[3], Some(min_htlc_msat), None); let mut route_params = get_blinded_route_parameters( - min_htlc_msat, payment_secret, chan_1_2.1.contents.htlc_minimum_msat, - chan_1_2.1.contents.htlc_maximum_msat, vec![nodes[1].node.get_our_node_id(), - nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()], - &[&chan_1_2.0.contents, &chan_2_3.0.contents], &chanmon_cfgs[3].keys_manager); - assert_eq!(min_htlc_msat, - route_params.payment_params.payee.blinded_route_hints()[0].payinfo.htlc_minimum_msat); - - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap(); + min_htlc_msat, + payment_secret, + chan_1_2.1.contents.htlc_minimum_msat, + chan_1_2.1.contents.htlc_maximum_msat, + vec![ + nodes[1].node.get_our_node_id(), + nodes[2].node.get_our_node_id(), + nodes[3].node.get_our_node_id(), + ], + &[&chan_1_2.0.contents, &chan_2_3.0.contents], + &chanmon_cfgs[3].keys_manager, + ); + assert_eq!( + min_htlc_msat, + route_params.payment_params.payee.blinded_route_hints()[0].payinfo.htlc_minimum_msat + ); + + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], min_htlc_msat, payment_hash, payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2], &nodes[3]]], + min_htlc_msat, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], payment_preimage); // Paying 1 less than the min fails. @@ -1226,9 +1836,20 @@ fn min_htlc() { } if let Payee::Blinded { ref mut route_hints, .. } = route_params.payment_params.payee { route_hints[0].payinfo.htlc_minimum_msat -= 1; - } else { panic!() } + } else { + panic!() + } route_params.final_value_msat -= 1; - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut payment_event_0_1 = { @@ -1237,20 +1858,32 @@ fn min_htlc() { let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); SendEvent::from_event(ev) }; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event_0_1.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event_0_1.msgs[0]); check_added_monitors!(nodes[1], 0); do_commitment_signed_dance(&nodes[1], &nodes[0], &payment_event_0_1.commitment_msg, true, true); expect_pending_htlcs_forwardable!(nodes[1]); expect_htlc_handling_failed_destinations!( nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_1_2.2 }] + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_1_2.2 + }] ); check_added_monitors(&nodes[1], 1); let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]), + ); } #[test] @@ -1275,7 +1908,11 @@ fn conditionally_round_fwd_amt() { node_3_cfg.channel_config.forwarding_fee_base_msat = 132845; node_3_cfg.channel_config.forwarding_fee_proportional_millionths = 552561; - let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg), None]); + let node_chanmgrs = create_node_chanmgrs( + 5, + &node_cfgs, + &[None, Some(node_1_cfg), Some(node_2_cfg), Some(node_3_cfg), None], + ); let nodes = create_network(5, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); @@ -1283,18 +1920,42 @@ fn conditionally_round_fwd_amt() { let chan_3_4 = create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0); let amt_msat = 100_000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); - let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret, - chan_1_2.1.contents.htlc_minimum_msat, chan_1_2.1.contents.htlc_maximum_msat, - vec![nodes[1].node.get_our_node_id(), nodes[2].node.get_our_node_id(), - nodes[3].node.get_our_node_id(), nodes[4].node.get_our_node_id()], + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); + let mut route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + chan_1_2.1.contents.htlc_minimum_msat, + chan_1_2.1.contents.htlc_maximum_msat, + vec![ + nodes[1].node.get_our_node_id(), + nodes[2].node.get_our_node_id(), + nodes[3].node.get_our_node_id(), + nodes[4].node.get_our_node_id(), + ], &[&chan_1_2.0.contents, &chan_2_3.0.contents, &chan_3_4.0.contents], - &chanmon_cfgs[4].keys_manager); + &chanmon_cfgs[4].keys_manager, + ); route_params.max_total_routing_fee_msat = None; - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], + amt_msat, + payment_hash, + payment_secret, + ); nodes[4].node.claim_funds(payment_preimage); let expected_path = &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]; let expected_route = &[&expected_path[..]]; @@ -1304,17 +1965,18 @@ fn conditionally_round_fwd_amt() { expect_payment_sent(&nodes[0], payment_preimage, Some(Some(expected_fee)), true, true); } - #[test] fn custom_tlvs_to_blinded_path() { let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; + let chan_upd = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; let amt_msat = 5000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -1328,9 +1990,15 @@ fn custom_tlvs_to_blinded_path() { let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key); let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, - &chanmon_cfgs[1].keys_manager, &secp_ctx - ).unwrap(); + &[], + nodes[1].node.get_our_node_id(), + payee_tlvs, + u64::MAX, + TEST_FINAL_CLTV as u16, + &chanmon_cfgs[1].keys_manager, + &secp_ctx, + ) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), @@ -1340,8 +2008,16 @@ fn custom_tlvs_to_blinded_path() { let recipient_onion_fields = RecipientOnionFields::spontaneous_empty() .with_custom_tlvs(vec![((1 << 16) + 1, vec![42, 42])]) .unwrap(); - nodes[0].node.send_payment(payment_hash, recipient_onion_fields.clone(), - PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + recipient_onion_fields.clone(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1355,7 +2031,7 @@ fn custom_tlvs_to_blinded_path() { do_pass_along_path(args); claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage) - .with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone()) + .with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone()), ); } @@ -1365,10 +2041,12 @@ fn fails_receive_tlvs_authentication() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; + let chan_upd = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents; let amt_msat = 5000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -1383,9 +2061,15 @@ fn fails_receive_tlvs_authentication() { let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, - &chanmon_cfgs[1].keys_manager, &secp_ctx - ).unwrap(); + &[], + nodes[1].node.get_our_node_id(), + payee_tlvs, + u64::MAX, + TEST_FINAL_CLTV as u16, + &chanmon_cfgs[1].keys_manager, + &secp_ctx, + ) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), @@ -1393,13 +2077,23 @@ fn fails_receive_tlvs_authentication() { ); // Test authentication works normally. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); pass_along_route(&nodes[0], &[&[&nodes[1]]], amt_msat, payment_hash, payment_secret); claim_payment(&nodes[0], &[&nodes[1]], payment_preimage); // Swap in a different nonce to force authentication to fail. - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -1414,16 +2108,31 @@ fn fails_receive_tlvs_authentication() { let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, - &chanmon_cfgs[1].keys_manager, &secp_ctx - ).unwrap(); + &[], + nodes[1].node.get_our_node_id(), + payee_tlvs, + u64::MAX, + TEST_FINAL_CLTV as u16, + &chanmon_cfgs[1].keys_manager, + &secp_ctx, + ) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path]), amt_msat, ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1436,7 +2145,10 @@ fn fails_receive_tlvs_authentication() { expect_pending_htlcs_forwardable!(nodes[1]); nodes[1].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[1], 1); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::InvalidOnion]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::InvalidOnion] + ); let mut update_fail = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(update_fail.update_fail_htlcs.len() == 1); @@ -1444,8 +2156,11 @@ fn fails_receive_tlvs_authentication() { nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), fail_msg); commitment_signed_dance!(nodes[0], nodes[1], update_fail.commitment_signed, false); expect_payment_failed_conditions( - &nodes[0], payment_hash, true, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[]), + &nodes[0], + payment_hash, + true, + PaymentFailedConditions::new() + .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[]), ); } @@ -1458,8 +2173,10 @@ fn blinded_payment_path_padding() { let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); - let chan_upd_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; - let chan_upd_3_4 = create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0).0.contents; + let chan_upd_2_3 = + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; + let chan_upd_3_4 = + create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0).0.contents; // Get all our nodes onto the same height so payments don't fail for CLTV violations. connect_blocks(&nodes[0], nodes[4].best_block_info().1 - nodes[0].best_block_info().1); @@ -1468,20 +2185,43 @@ fn blinded_payment_path_padding() { assert_eq!(nodes[4].best_block_info().1, nodes[3].best_block_info().1); let amt_msat = 5000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[4], Some(amt_msat), None); - let blinded_path = blinded_payment_path(payment_secret, 1, 1_0000_0000, - nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_2_3, &chan_upd_3_4], - &chanmon_cfgs[4].keys_manager + let blinded_path = blinded_payment_path( + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_2_3, &chan_upd_3_4], + &chanmon_cfgs[4].keys_manager, ); assert!(is_padded(&blinded_path.blinded_hops(), PAYMENT_PADDING_ROUND_OFF)); - let route_params = RouteParameters::from_payment_params_and_value(PaymentParameters::blinded(vec![blinded_path]), amt_msat); + let route_params = RouteParameters::from_payment_params_and_value( + PaymentParameters::blinded(vec![blinded_path]), + amt_msat, + ); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], + amt_msat, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]], payment_preimage); } @@ -1499,7 +2239,7 @@ fn pubkey_from_hex(hex: &str) -> PublicKey { fn update_add_msg( amount_msat: u64, cltv_expiry: u32, blinding_point: Option, - onion_routing_packet: msgs::OnionPacket + onion_routing_packet: msgs::OnionPacket, ) -> msgs::UpdateAddHTLC { msgs::UpdateAddHTLC { channel_id: ChannelId::from_bytes([0; 32]), @@ -1516,36 +2256,57 @@ fn update_add_msg( #[test] fn route_blinding_spec_test_vector() { let mut secp_ctx = Secp256k1::new(); - let bob_secret = secret_from_hex("4242424242424242424242424242424242424242424242424242424242424242"); + let bob_secret = + secret_from_hex("4242424242424242424242424242424242424242424242424242424242424242"); let bob_node_id = PublicKey::from_secret_key(&secp_ctx, &bob_secret); let bob_unblinded_tlvs = bytes_from_hex("011a0000000000000000000000000000000000000000000000000000020800000000000006c10a0800240000009627100c06000b69e505dc0e00fd023103123456"); - let carol_secret = secret_from_hex("4343434343434343434343434343434343434343434343434343434343434343"); + let carol_secret = + secret_from_hex("4343434343434343434343434343434343434343434343434343434343434343"); let carol_node_id = PublicKey::from_secret_key(&secp_ctx, &carol_secret); let carol_unblinded_tlvs = bytes_from_hex("020800000000000004510821031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f0a0800300000006401f40c06000b69c105dc0e00"); - let dave_secret = secret_from_hex("4444444444444444444444444444444444444444444444444444444444444444"); + let dave_secret = + secret_from_hex("4444444444444444444444444444444444444444444444444444444444444444"); let dave_node_id = PublicKey::from_secret_key(&secp_ctx, &dave_secret); let dave_unblinded_tlvs = bytes_from_hex("01230000000000000000000000000000000000000000000000000000000000000000000000020800000000000002310a060090000000fa0c06000b699105dc0e00"); - let eve_secret = secret_from_hex("4545454545454545454545454545454545454545454545454545454545454545"); + let eve_secret = + secret_from_hex("4545454545454545454545454545454545454545454545454545454545454545"); let eve_node_id = PublicKey::from_secret_key(&secp_ctx, &eve_secret); let eve_unblinded_tlvs = bytes_from_hex("011a00000000000000000000000000000000000000000000000000000604deadbeef0c06000b690105dc0e0f020000000000000000000000000000fdffff0206c1"); // Eve creates a blinded path to herself through Dave: - let dave_eve_session_priv = secret_from_hex("0101010101010101010101010101010101010101010101010101010101010101"); + let dave_eve_session_priv = + secret_from_hex("0101010101010101010101010101010101010101010101010101010101010101"); let blinding_override = PublicKey::from_secret_key(&secp_ctx, &dave_eve_session_priv); - assert_eq!(blinding_override, pubkey_from_hex("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f")); + assert_eq!( + blinding_override, + pubkey_from_hex("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f") + ); // Can't use the public API here as the encrypted payloads contain unknown TLVs. - let path = [(dave_node_id, WithoutLength(&dave_unblinded_tlvs)), (eve_node_id, WithoutLength(&eve_unblinded_tlvs))]; + let path = [ + (dave_node_id, WithoutLength(&dave_unblinded_tlvs)), + (eve_node_id, WithoutLength(&eve_unblinded_tlvs)), + ]; let mut dave_eve_blinded_hops = blinded_path::utils::construct_blinded_hops( - &secp_ctx, path.into_iter(), &dave_eve_session_priv - ).unwrap(); + &secp_ctx, + path.into_iter(), + &dave_eve_session_priv, + ) + .unwrap(); // Concatenate an additional Bob -> Carol blinded path to the Eve -> Dave blinded path. - let bob_carol_session_priv = secret_from_hex("0202020202020202020202020202020202020202020202020202020202020202"); + let bob_carol_session_priv = + secret_from_hex("0202020202020202020202020202020202020202020202020202020202020202"); let bob_blinding_point = PublicKey::from_secret_key(&secp_ctx, &bob_carol_session_priv); - let path = [(bob_node_id, WithoutLength(&bob_unblinded_tlvs)), (carol_node_id, WithoutLength(&carol_unblinded_tlvs))]; + let path = [ + (bob_node_id, WithoutLength(&bob_unblinded_tlvs)), + (carol_node_id, WithoutLength(&carol_unblinded_tlvs)), + ]; let bob_carol_blinded_hops = blinded_path::utils::construct_blinded_hops( - &secp_ctx, path.into_iter(), &bob_carol_session_priv - ).unwrap(); + &secp_ctx, + path.into_iter(), + &bob_carol_session_priv, + ) + .unwrap(); let mut blinded_hops = bob_carol_blinded_hops; blinded_hops.append(&mut dave_eve_blinded_hops); @@ -1569,7 +2330,8 @@ fn route_blinding_spec_test_vector() { ); let mut amt_msat = 100_000; - let session_priv = secret_from_hex("0303030303030303030303030303030303030303030303030303030303030303"); + let session_priv = + secret_from_hex("0303030303030303030303030303030303030303030303030303030303030303"); let path = Path { hops: vec![RouteHop { pubkey: bob_node_id, @@ -1585,11 +2347,23 @@ fn route_blinding_spec_test_vector() { hops: blinded_hops, blinding_point: bob_blinding_point, excess_final_cltv_expiry_delta: 0, - final_value_msat: amt_msat + final_value_msat: amt_msat, }), }; let cur_height = 747_000; - let (bob_onion, _, _) = onion_utils::create_payment_onion(&secp_ctx, &path, &session_priv, amt_msat, &RecipientOnionFields::spontaneous_empty(), cur_height, &PaymentHash([0; 32]), &None, None, [0; 32]).unwrap(); + let (bob_onion, _, _) = onion_utils::create_payment_onion( + &secp_ctx, + &path, + &session_priv, + amt_msat, + &RecipientOnionFields::spontaneous_empty(), + cur_height, + &PaymentHash([0; 32]), + &None, + None, + [0; 32], + ) + .unwrap(); struct TestEcdhSigner { node_secret: SecretKey, @@ -1604,15 +2378,25 @@ fn route_blinding_spec_test_vector() { } Ok(SharedSecret::new(other_key, &node_secret)) } - fn get_inbound_payment_key(&self) -> ExpandedKey { unreachable!() } - fn get_node_id(&self, _recipient: Recipient) -> Result { unreachable!() } + fn get_inbound_payment_key(&self) -> ExpandedKey { + unreachable!() + } + fn get_node_id(&self, _recipient: Recipient) -> Result { + unreachable!() + } fn sign_invoice( &self, _invoice: &RawBolt11Invoice, _recipient: Recipient, - ) -> Result { unreachable!() } + ) -> Result { + unreachable!() + } fn sign_bolt12_invoice( &self, _invoice: &UnsignedBolt12Invoice, - ) -> Result { unreachable!() } - fn sign_gossip_message(&self, _msg: UnsignedGossipMessage) -> Result { unreachable!() } + ) -> Result { + unreachable!() + } + fn sign_gossip_message(&self, _msg: UnsignedGossipMessage) -> Result { + unreachable!() + } } let logger = test_utils::TestLogger::with_id("".to_owned()); @@ -1622,24 +2406,49 @@ fn route_blinding_spec_test_vector() { // < MIN_CLTV_EXPIRY_DELTA). let (bob_peeled_onion, next_packet_details_opt) = match onion_payment::decode_incoming_update_add_htlc_onion( - &bob_update_add, &bob_node_signer, &logger, &secp_ctx + &bob_update_add, + &bob_node_signer, + &logger, + &secp_ctx, ) { Ok(res) => res, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), }; let (carol_packet_bytes, carol_hmac) = if let onion_utils::Hop::BlindedForward { - next_hop_data: msgs::InboundOnionBlindedForwardPayload { - short_channel_id, payment_relay, payment_constraints, features, intro_node_blinding_point, next_blinding_override - }, next_hop_hmac, new_packet_bytes, .. - } = bob_peeled_onion { + next_hop_data: + msgs::InboundOnionBlindedForwardPayload { + short_channel_id, + payment_relay, + payment_constraints, + features, + intro_node_blinding_point, + next_blinding_override, + }, + next_hop_hmac, + new_packet_bytes, + .. + } = bob_peeled_onion + { assert_eq!(short_channel_id, 1729); assert!(next_blinding_override.is_none()); assert_eq!(intro_node_blinding_point, Some(bob_blinding_point)); - assert_eq!(payment_relay, PaymentRelay { cltv_expiry_delta: 36, fee_proportional_millionths: 150, fee_base_msat: 10_000 }); + assert_eq!( + payment_relay, + PaymentRelay { + cltv_expiry_delta: 36, + fee_proportional_millionths: 150, + fee_base_msat: 10_000 + } + ); assert_eq!(features, BlindedHopFeatures::empty()); - assert_eq!(payment_constraints, PaymentConstraints { max_cltv_expiry: 748_005, htlc_minimum_msat: 1500 }); + assert_eq!( + payment_constraints, + PaymentConstraints { max_cltv_expiry: 748_005, htlc_minimum_msat: 1500 } + ); (new_packet_bytes, next_hop_hmac) - } else { panic!() }; + } else { + panic!() + }; let carol_packet_details = next_packet_details_opt.unwrap(); let carol_onion = msgs::OnionPacket { @@ -1649,31 +2458,62 @@ fn route_blinding_spec_test_vector() { hmac: carol_hmac, }; let carol_update_add = update_add_msg( - carol_packet_details.outgoing_amt_msat, carol_packet_details.outgoing_cltv_value, + carol_packet_details.outgoing_amt_msat, + carol_packet_details.outgoing_cltv_value, Some(pubkey_from_hex("034e09f450a80c3d252b258aba0a61215bf60dda3b0dc78ffb0736ea1259dfd8a0")), - carol_onion + carol_onion, ); let carol_node_signer = TestEcdhSigner { node_secret: carol_secret }; let (carol_peeled_onion, next_packet_details_opt) = match onion_payment::decode_incoming_update_add_htlc_onion( - &carol_update_add, &carol_node_signer, &logger, &secp_ctx + &carol_update_add, + &carol_node_signer, + &logger, + &secp_ctx, ) { Ok(res) => res, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), }; let (dave_packet_bytes, dave_hmac) = if let onion_utils::Hop::BlindedForward { - next_hop_data: msgs::InboundOnionBlindedForwardPayload { - short_channel_id, payment_relay, payment_constraints, features, intro_node_blinding_point, next_blinding_override - }, next_hop_hmac, new_packet_bytes, .. - } = carol_peeled_onion { + next_hop_data: + msgs::InboundOnionBlindedForwardPayload { + short_channel_id, + payment_relay, + payment_constraints, + features, + intro_node_blinding_point, + next_blinding_override, + }, + next_hop_hmac, + new_packet_bytes, + .. + } = carol_peeled_onion + { assert_eq!(short_channel_id, 1105); - assert_eq!(next_blinding_override, Some(pubkey_from_hex("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f"))); + assert_eq!( + next_blinding_override, + Some(pubkey_from_hex( + "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f" + )) + ); assert!(intro_node_blinding_point.is_none()); - assert_eq!(payment_relay, PaymentRelay { cltv_expiry_delta: 48, fee_proportional_millionths: 100, fee_base_msat: 500 }); + assert_eq!( + payment_relay, + PaymentRelay { + cltv_expiry_delta: 48, + fee_proportional_millionths: 100, + fee_base_msat: 500 + } + ); assert_eq!(features, BlindedHopFeatures::empty()); - assert_eq!(payment_constraints, PaymentConstraints { max_cltv_expiry: 747_969, htlc_minimum_msat: 1500 }); + assert_eq!( + payment_constraints, + PaymentConstraints { max_cltv_expiry: 747_969, htlc_minimum_msat: 1500 } + ); (new_packet_bytes, next_hop_hmac) - } else { panic!() }; + } else { + panic!() + }; let dave_packet_details = next_packet_details_opt.unwrap(); let dave_onion = msgs::OnionPacket { @@ -1683,31 +2523,57 @@ fn route_blinding_spec_test_vector() { hmac: dave_hmac, }; let dave_update_add = update_add_msg( - dave_packet_details.outgoing_amt_msat, dave_packet_details.outgoing_cltv_value, + dave_packet_details.outgoing_amt_msat, + dave_packet_details.outgoing_cltv_value, Some(pubkey_from_hex("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f")), - dave_onion + dave_onion, ); let dave_node_signer = TestEcdhSigner { node_secret: dave_secret }; let (dave_peeled_onion, next_packet_details_opt) = match onion_payment::decode_incoming_update_add_htlc_onion( - &dave_update_add, &dave_node_signer, &logger, &secp_ctx + &dave_update_add, + &dave_node_signer, + &logger, + &secp_ctx, ) { Ok(res) => res, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), }; let (eve_packet_bytes, eve_hmac) = if let onion_utils::Hop::BlindedForward { - next_hop_data: msgs::InboundOnionBlindedForwardPayload { - short_channel_id, payment_relay, payment_constraints, features, intro_node_blinding_point, next_blinding_override - }, next_hop_hmac, new_packet_bytes, .. - } = dave_peeled_onion { + next_hop_data: + msgs::InboundOnionBlindedForwardPayload { + short_channel_id, + payment_relay, + payment_constraints, + features, + intro_node_blinding_point, + next_blinding_override, + }, + next_hop_hmac, + new_packet_bytes, + .. + } = dave_peeled_onion + { assert_eq!(short_channel_id, 561); assert!(next_blinding_override.is_none()); assert!(intro_node_blinding_point.is_none()); - assert_eq!(payment_relay, PaymentRelay { cltv_expiry_delta: 144, fee_proportional_millionths: 250, fee_base_msat: 0 }); + assert_eq!( + payment_relay, + PaymentRelay { + cltv_expiry_delta: 144, + fee_proportional_millionths: 250, + fee_base_msat: 0 + } + ); assert_eq!(features, BlindedHopFeatures::empty()); - assert_eq!(payment_constraints, PaymentConstraints { max_cltv_expiry: 747_921, htlc_minimum_msat: 1500 }); + assert_eq!( + payment_constraints, + PaymentConstraints { max_cltv_expiry: 747_921, htlc_minimum_msat: 1500 } + ); (new_packet_bytes, next_hop_hmac) - } else { panic!() }; + } else { + panic!() + }; let eve_packet_details = next_packet_details_opt.unwrap(); let eve_onion = msgs::OnionPacket { @@ -1717,19 +2583,25 @@ fn route_blinding_spec_test_vector() { hmac: eve_hmac, }; let eve_update_add = update_add_msg( - eve_packet_details.outgoing_amt_msat, eve_packet_details.outgoing_cltv_value, + eve_packet_details.outgoing_amt_msat, + eve_packet_details.outgoing_cltv_value, Some(pubkey_from_hex("03e09038ee76e50f444b19abf0a555e8697e035f62937168b80adf0931b31ce52a")), - eve_onion + eve_onion, ); let eve_node_signer = TestEcdhSigner { node_secret: eve_secret }; // We can't decode the final payload because it contains a path_id and is missing some LDK // specific fields. match onion_payment::decode_incoming_update_add_htlc_onion( - &eve_update_add, &eve_node_signer, &logger, &secp_ctx + &eve_update_add, + &eve_node_signer, + &logger, + &secp_ctx, ) { - Err((HTLCFailureMsg::Malformed(msg), _)) => assert_eq!(msg.failure_code, - LocalHTLCFailureReason::InvalidOnionBlinding.failure_code()), - _ => panic!("Unexpected error") + Err((HTLCFailureMsg::Malformed(msg), _)) => assert_eq!( + msg.failure_code, + LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() + ), + _ => panic!("Unexpected error"), } } @@ -1738,7 +2610,8 @@ fn test_combined_trampoline_onion_creation_vectors() { // As per https://github.com/lightning/bolts/blob/fa0594ac2af3531d734f1d707a146d6e13679451/bolt04/trampoline-to-blinded-path-payment-onion-test.json#L251 let mut secp_ctx = Secp256k1::new(); - let session_priv = secret_from_hex("a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99"); + let session_priv = + secret_from_hex("a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99"); let path = Path { hops: vec![ @@ -1799,16 +2672,36 @@ fn test_combined_trampoline_onion_creation_vectors() { }), }; - let associated_data_slice = secret_from_hex("e89bc505e84aaca09613833fc58c9069078fb43bfbea0488f34eec9db99b5f82"); + let associated_data_slice = + secret_from_hex("e89bc505e84aaca09613833fc58c9069078fb43bfbea0488f34eec9db99b5f82"); let associated_data = PaymentHash(associated_data_slice.secret_bytes()); - let payment_secret = PaymentSecret(secret_from_hex("7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da").secret_bytes()); - let outer_session_key = secret_from_hex("4f777e8dac16e6dfe333066d9efb014f7a51d11762ff76eca4d3a95ada99ba3e"); - let outer_onion_prng_seed = onion_utils::gen_pad_from_shared_secret(&outer_session_key.secret_bytes()); + let payment_secret = PaymentSecret( + secret_from_hex("7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da") + .secret_bytes(), + ); + let outer_session_key = + secret_from_hex("4f777e8dac16e6dfe333066d9efb014f7a51d11762ff76eca4d3a95ada99ba3e"); + let outer_onion_prng_seed = + onion_utils::gen_pad_from_shared_secret(&outer_session_key.secret_bytes()); let amt_msat = 150_000_000; let cur_height = 800_000; let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); - let (bob_onion, htlc_msat, htlc_cltv) = onion_utils::create_payment_onion_internal(&secp_ctx, &path, &session_priv, amt_msat, &recipient_onion_fields, cur_height, &associated_data, &None, None, [0; 32], Some(outer_session_key), Some(outer_onion_prng_seed)).unwrap(); + let (bob_onion, htlc_msat, htlc_cltv) = onion_utils::create_payment_onion_internal( + &secp_ctx, + &path, + &session_priv, + amt_msat, + &recipient_onion_fields, + cur_height, + &associated_data, + &None, + None, + [0; 32], + Some(outer_session_key), + Some(outer_onion_prng_seed), + ) + .unwrap(); let outer_onion_packet_hex = bob_onion.encode().to_lower_hex_string(); assert_eq!(outer_onion_packet_hex, "00025fd60556c134ae97e4baedba220a644037754ee67c54fd05e93bf40c17cbb73362fb9dee96001ff229945595b6edb59437a6bc143406d3f90f749892a84d8d430c6890437d26d5bfc599d565316ef51347521075bbab87c59c57bcf20af7e63d7192b46cf171e4f73cb11f9f603915389105d91ad630224bea95d735e3988add1e24b5bf28f1d7128db64284d90a839ba340d088c74b1fb1bd21136b1809428ec5399c8649e9bdf92d2dcfc694deae5046fa5b2bdf646847aaad73f5e95275763091c90e71031cae1f9a770fdea559642c9c02f424a2a28163dd0957e3874bd28a97bec67d18c0321b0e68bc804aa8345b17cb626e2348ca06c8312a167c989521056b0f25c55559d446507d6c491d50605cb79fa87929ce64b0a9860926eeaec2c431d926a1cadb9a1186e4061cb01671a122fc1f57602cbef06d6c194ec4b715c2e3dd4120baca3172cd81900b49fef857fb6d6afd24c983b608108b0a5ac0c1c6c52011f23b8778059ffadd1bb7cd06e2525417365f485a7fd1d4a9ba3818ede7cdc9e71afee8532252d08e2531ca52538655b7e8d912f7ec6d37bbcce8d7ec690709dbf9321e92c565b78e7fe2c22edf23e0902153d1ca15a112ad32fb19695ec65ce11ddf670da7915f05ad4b86c154fb908cb567315d1124f303f75fa075ebde8ef7bb12e27737ad9e4924439097338ea6d7a6fc3721b88c9b830a34e8d55f4c582b74a3895cc848fe57f4fe29f115dabeb6b3175be15d94408ed6771109cfaf57067ae658201082eae7605d26b1449af4425ae8e8f58cdda5c6265f1fd7a386fc6cea3074e4f25b909b96175883676f7610a00fdf34df9eb6c7b9a4ae89b839c69fd1f285e38cdceb634d782cc6d81179759bc9fd47d7fd060470d0b048287764c6837963274e708314f017ac7dc26d0554d59bfcfd3136225798f65f0b0fea337c6b256ebbb63a90b994c0ab93fd8b1d6bd4c74aebe535d6110014cd3d525394027dfe8faa98b4e9b2bee7949eb1961f1b026791092f84deea63afab66603dbe9b6365a102a1fef2f6b9744bc1bb091a8da9130d34d4d39f25dbad191649cfb67e10246364b7ce0c6ec072f9690cabb459d9fda0c849e17535de4357e9907270c75953fca3c845bb613926ecf73205219c7057a4b6bb244c184362bb4e2f24279dc4e60b94a5b1ec11c34081a628428ba5646c995b9558821053ba9c84a05afbf00dabd60223723096516d2f5668f3ec7e11612b01eb7a3a0506189a2272b88e89807943adb34291a17f6cb5516ffd6f945a1c42a524b21f096d66f350b1dad4db455741ae3d0e023309fbda5ef55fb0dc74f3297041448b2be76c525141963934c6afc53d263fb7836626df502d7c2ee9e79cbbd87afd84bbb8dfbf45248af3cd61ad5fac827e7683ca4f91dfad507a8eb9c17b2c9ac5ec051fe645a4a6cb37136f6f19b611e0ea8da7960af2d779507e55f57305bc74b7568928c5dd5132990fe54c22117df91c257d8c7b61935a018a28c1c3b17bab8e4294fa699161ec21123c9fc4e71079df31f300c2822e1246561e04765d3aab333eafd026c7431ac7616debb0e022746f4538e1c6348b600c988eeb2d051fc60c468dca260a84c79ab3ab8342dc345a764672848ea234e17332bc124799daf7c5fcb2e2358514a7461357e1c19c802c5ee32deccf1776885dd825bedd5f781d459984370a6b7ae885d4483a76ddb19b30f47ed47cd56aa5a079a89793dbcad461c59f2e002067ac98dd5a534e525c9c46c2af730741bf1f8629357ec0bfc0bc9ecb31af96777e507648ff4260dc3673716e098d9111dfd245f1d7c55a6de340deb8bd7a053e5d62d760f184dc70ca8fa255b9023b9b9aedfb6e419a5b5951ba0f83b603793830ee68d442d7b88ee1bbf6bbd1bcd6f68cc1af"); @@ -1819,18 +2712,23 @@ fn test_combined_trampoline_onion_creation_vectors() { #[test] fn test_trampoline_inbound_payment_decoding() { let secp_ctx = Secp256k1::new(); - let session_priv = secret_from_hex("0303030303030303030303030303030303030303030303030303030303030303"); + let session_priv = + secret_from_hex("0303030303030303030303030303030303030303030303030303030303030303"); - let bob_secret = secret_from_hex("4242424242424242424242424242424242424242424242424242424242424242"); + let bob_secret = + secret_from_hex("4242424242424242424242424242424242424242424242424242424242424242"); let bob_node_id = PublicKey::from_secret_key(&secp_ctx, &bob_secret); let _bob_unblinded_tlvs = bytes_from_hex("011a0000000000000000000000000000000000000000000000000000020800000000000006c10a0800240000009627100c06000b69e505dc0e00fd023103123456"); - let carol_secret = secret_from_hex("4343434343434343434343434343434343434343434343434343434343434343"); + let carol_secret = + secret_from_hex("4343434343434343434343434343434343434343434343434343434343434343"); let carol_node_id = PublicKey::from_secret_key(&secp_ctx, &carol_secret); let _carol_unblinded_tlvs = bytes_from_hex("020800000000000004510821031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f0a0800300000006401f40c06000b69c105dc0e00"); - let dave_secret = secret_from_hex("4444444444444444444444444444444444444444444444444444444444444444"); + let dave_secret = + secret_from_hex("4444444444444444444444444444444444444444444444444444444444444444"); let dave_node_id = PublicKey::from_secret_key(&secp_ctx, &dave_secret); let _dave_unblinded_tlvs = bytes_from_hex("01230000000000000000000000000000000000000000000000000000000000000000000000020800000000000002310a060090000000fa0c06000b699105dc0e00"); - let eve_secret = secret_from_hex("4545454545454545454545454545454545454545454545454545454545454545"); + let eve_secret = + secret_from_hex("4545454545454545454545454545454545454545454545454545454545454545"); let _eve_node_id = PublicKey::from_secret_key(&secp_ctx, &eve_secret); let _eve_unblinded_tlvs = bytes_from_hex("011a00000000000000000000000000000000000000000000000000000604deadbeef0c06000b690105dc0e0f020000000000000000000000000000fdffff0206c1"); @@ -1893,12 +2791,27 @@ fn test_trampoline_inbound_payment_decoding() { }) }; - let payment_secret = PaymentSecret(secret_from_hex("7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da").secret_bytes()); + let payment_secret = PaymentSecret( + secret_from_hex("7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da") + .secret_bytes(), + ); let amt_msat = 150_000_001; let cur_height = 800_001; let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); - let (bob_onion, _, _) = onion_utils::create_payment_onion(&secp_ctx, &path, &session_priv, amt_msat, &recipient_onion_fields, cur_height, &PaymentHash([0; 32]), &None, None, [0; 32]).unwrap(); + let (bob_onion, _, _) = onion_utils::create_payment_onion( + &secp_ctx, + &path, + &session_priv, + amt_msat, + &recipient_onion_fields, + cur_height, + &PaymentHash([0; 32]), + &None, + None, + [0; 32], + ) + .unwrap(); struct TestEcdhSigner { node_secret: SecretKey, @@ -1913,30 +2826,51 @@ fn test_trampoline_inbound_payment_decoding() { } Ok(SharedSecret::new(other_key, &node_secret)) } - fn get_inbound_payment_key(&self) -> ExpandedKey { unreachable!() } - fn get_node_id(&self, _recipient: Recipient) -> Result { unreachable!() } + fn get_inbound_payment_key(&self) -> ExpandedKey { + unreachable!() + } + fn get_node_id(&self, _recipient: Recipient) -> Result { + unreachable!() + } fn sign_invoice( &self, _invoice: &RawBolt11Invoice, _recipient: Recipient, - ) -> Result { unreachable!() } + ) -> Result { + unreachable!() + } fn sign_bolt12_invoice( &self, _invoice: &UnsignedBolt12Invoice, - ) -> Result { unreachable!() } - fn sign_gossip_message(&self, _msg: UnsignedGossipMessage) -> Result { unreachable!() } + ) -> Result { + unreachable!() + } + fn sign_gossip_message(&self, _msg: UnsignedGossipMessage) -> Result { + unreachable!() + } } let logger = test_utils::TestLogger::with_id("".to_owned()); let bob_update_add = update_add_msg(111_000, 747_501, None, bob_onion); let bob_node_signer = TestEcdhSigner { node_secret: bob_secret }; - let (bob_peeled_onion, next_packet_details_opt) = onion_payment::decode_incoming_update_add_htlc_onion( - &bob_update_add, &bob_node_signer, &logger, &secp_ctx - ).unwrap_or_else(|_| panic!()); + let (bob_peeled_onion, next_packet_details_opt) = + onion_payment::decode_incoming_update_add_htlc_onion( + &bob_update_add, + &bob_node_signer, + &logger, + &secp_ctx, + ) + .unwrap_or_else(|_| panic!()); let (carol_packet_bytes, carol_hmac) = if let onion_utils::Hop::Forward { - next_hop_data: msgs::InboundOnionForwardPayload {..}, next_hop_hmac, new_packet_bytes, .. - } = bob_peeled_onion { + next_hop_data: msgs::InboundOnionForwardPayload { .. }, + next_hop_hmac, + new_packet_bytes, + .. + } = bob_peeled_onion + { (new_packet_bytes, next_hop_hmac) - } else { panic!() }; + } else { + panic!() + }; let carol_packet_details = next_packet_details_opt.unwrap(); let carol_onion = msgs::OnionPacket { @@ -1945,18 +2879,30 @@ fn test_trampoline_inbound_payment_decoding() { hop_data: carol_packet_bytes, hmac: carol_hmac, }; - let carol_update_add = update_add_msg(carol_packet_details.outgoing_amt_msat, carol_packet_details.outgoing_cltv_value, None, carol_onion); + let carol_update_add = update_add_msg( + carol_packet_details.outgoing_amt_msat, + carol_packet_details.outgoing_cltv_value, + None, + carol_onion, + ); let carol_node_signer = TestEcdhSigner { node_secret: carol_secret }; let (carol_peeled_onion, _) = onion_payment::decode_incoming_update_add_htlc_onion( - &carol_update_add, &carol_node_signer, &logger, &secp_ctx - ).unwrap_or_else(|_| panic!()); + &carol_update_add, + &carol_node_signer, + &logger, + &secp_ctx, + ) + .unwrap_or_else(|_| panic!()); - let _carol_trampoline_update_add = if let onion_utils::Hop::TrampolineForward { next_trampoline_hop_data, .. } = carol_peeled_onion { - assert_eq!(next_trampoline_hop_data.next_trampoline, dave_node_id); - } else { - panic!(); - }; + let _carol_trampoline_update_add = + if let onion_utils::Hop::TrampolineForward { next_trampoline_hop_data, .. } = + carol_peeled_onion + { + assert_eq!(next_trampoline_hop_data.next_trampoline, dave_node_id); + } else { + panic!(); + }; } fn do_test_trampoline_single_hop_receive(success: bool) { @@ -1965,28 +2911,52 @@ fn do_test_trampoline_single_hop_receive(success: bool) { let chanmon_cfgs = create_chanmon_cfgs(TOTAL_NODE_COUNT); let node_cfgs = create_node_cfgs(TOTAL_NODE_COUNT, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]); + let node_chanmgrs = + create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]); let mut nodes = create_network(TOTAL_NODE_COUNT, &node_cfgs, &node_chanmgrs); - let (_, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); - let (_, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); + let (_, _, chan_id_alice_bob, _) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + let (_, _, chan_id_bob_carol, _) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); - for i in 0..TOTAL_NODE_COUNT { // connect all nodes' blocks - connect_blocks(&nodes[i], (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1); + for i in 0..TOTAL_NODE_COUNT { + // connect all nodes' blocks + connect_blocks( + &nodes[i], + (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1, + ); } let alice_node_id = nodes[0].node().get_our_node_id(); let bob_node_id = nodes[1].node().get_our_node_id(); let carol_node_id = nodes[2].node().get_our_node_id(); - let alice_bob_scid = nodes[0].node().list_channels().iter().find(|c| c.channel_id == chan_id_alice_bob).unwrap().short_channel_id.unwrap(); - let bob_carol_scid = nodes[1].node().list_channels().iter().find(|c| c.channel_id == chan_id_bob_carol).unwrap().short_channel_id.unwrap(); + let alice_bob_scid = nodes[0] + .node() + .list_channels() + .iter() + .find(|c| c.channel_id == chan_id_alice_bob) + .unwrap() + .short_channel_id + .unwrap(); + let bob_carol_scid = nodes[1] + .node() + .list_channels() + .iter() + .find(|c| c.channel_id == chan_id_bob_carol) + .unwrap() + .short_channel_id + .unwrap(); let amt_msat = 1000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); - let carol_alice_trampoline_session_priv = secret_from_hex("a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03"); - let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv); + let carol_alice_trampoline_session_priv = + secret_from_hex("a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03"); + let carol_blinding_point = + PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv); let carol_blinded_hops = if success { let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, @@ -2004,8 +2974,11 @@ fn do_test_trampoline_single_hop_receive(success: bool) { let path = [(carol_node_id, WithoutLength(&carol_unblinded_tlvs))]; blinded_path::utils::construct_blinded_hops( - &secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv - ).unwrap() + &secp_ctx, + path.into_iter(), + &carol_alice_trampoline_session_priv, + ) + .unwrap() } else { let payee_tlvs = blinded_path::payment::TrampolineForwardTlvs { next_trampoline: alice_node_id, @@ -2025,8 +2998,11 @@ fn do_test_trampoline_single_hop_receive(success: bool) { let carol_unblinded_tlvs = payee_tlvs.encode(); let path = [(carol_node_id, WithoutLength(&carol_unblinded_tlvs))]; blinded_path::utils::construct_blinded_hops( - &secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv - ).unwrap() + &secp_ctx, + path.into_iter(), + &carol_alice_trampoline_session_priv, + ) + .unwrap() }; let route = Route { @@ -2042,7 +3018,6 @@ fn do_test_trampoline_single_hop_receive(success: bool) { cltv_expiry_delta: 48, maybe_announced_channel: false, }, - // Carol RouteHop { pubkey: carol_node_id, @@ -2052,7 +3027,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) { fee_msat: 0, cltv_expiry_delta: 48, maybe_announced_channel: false, - } + }, ], blinded_tail: Some(BlindedTail { trampoline_hops: vec![ @@ -2068,100 +3043,166 @@ fn do_test_trampoline_single_hop_receive(success: bool) { blinding_point: carol_blinding_point, excess_final_cltv_expiry_delta: 39, final_value_msat: amt_msat, - }) + }), }], route_params: None, }; - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(&nodes[0], 1); if success { - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + amt_msat, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); } else { let replacement_onion = { // create a substitute onion where the last Trampoline hop is a forward - let trampoline_secret_key = secret_from_hex("0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799"); - let prng_seed = secret_from_hex("fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9"); + let trampoline_secret_key = + secret_from_hex("0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799"); + let prng_seed = + secret_from_hex("fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9"); let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let mut blinded_tail = route.paths[0].blinded_tail.clone().unwrap(); // append some dummy blinded hop so the intro hop looks like a forward - blinded_tail.hops.push(BlindedHop { - blinded_node_id: alice_node_id, - encrypted_payload: vec![], - }); - - let (mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils::build_trampoline_onion_payloads(&blinded_tail, amt_msat, &recipient_onion_fields, 32, &None).unwrap(); + blinded_tail + .hops + .push(BlindedHop { blinded_node_id: alice_node_id, encrypted_payload: vec![] }); + + let (mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = + onion_utils::build_trampoline_onion_payloads( + &blinded_tail, + amt_msat, + &recipient_onion_fields, + 32, + &None, + ) + .unwrap(); // pop the last dummy hop trampoline_payloads.pop(); - let trampoline_onion_keys = onion_utils::construct_trampoline_onion_keys(&secp_ctx, &route.paths[0].blinded_tail.as_ref().unwrap(), &trampoline_secret_key); + let trampoline_onion_keys = onion_utils::construct_trampoline_onion_keys( + &secp_ctx, + &route.paths[0].blinded_tail.as_ref().unwrap(), + &trampoline_secret_key, + ); let trampoline_packet = onion_utils::construct_trampoline_onion_packet( trampoline_payloads, trampoline_onion_keys, prng_seed.secret_bytes(), &payment_hash, None, - ).unwrap(); + ) + .unwrap(); - let outer_session_priv = secret_from_hex("e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677"); + let outer_session_priv = + secret_from_hex("e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677"); - let (outer_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], outer_total_msat, &recipient_onion_fields, outer_starting_htlc_offset, &None, None, Some(trampoline_packet)).unwrap(); - let outer_onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.clone().paths[0], &outer_session_priv); + let (outer_payloads, _, _) = onion_utils::build_onion_payloads( + &route.paths[0], + outer_total_msat, + &recipient_onion_fields, + outer_starting_htlc_offset, + &None, + None, + Some(trampoline_packet), + ) + .unwrap(); + let outer_onion_keys = onion_utils::construct_onion_keys( + &secp_ctx, + &route.clone().paths[0], + &outer_session_priv, + ); let outer_packet = onion_utils::construct_onion_packet( outer_payloads, outer_onion_keys, prng_seed.secret_bytes(), &payment_hash, - ).unwrap(); + ) + .unwrap(); outer_packet }; let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - let mut first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + let mut first_message_event = + remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); let mut update_message = match first_message_event { MessageSendEvent::UpdateHTLCs { ref mut updates, .. } => { assert_eq!(updates.update_add_htlcs.len(), 1); updates.update_add_htlcs.get_mut(0) }, - _ => panic!() + _ => panic!(), }; update_message.map(|msg| { msg.onion_routing_packet = replacement_onion.clone(); }); let route: &[&Node] = &[&nodes[1], &nodes[2]]; - let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event) - .with_payment_preimage(payment_preimage) - .without_claimable_event() - .expect_failure(HTLCDestination::InvalidOnion); + let args = + PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event) + .with_payment_preimage(payment_preimage) + .without_claimable_event() + .expect_failure(HTLCDestination::InvalidOnion); do_pass_along_path(args); { - let unblinded_node_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); + let unblinded_node_updates = + get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); nodes[1].node.handle_update_fail_htlc( - nodes[2].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0] + nodes[2].node.get_our_node_id(), + &unblinded_node_updates.update_fail_htlcs[0], + ); + do_commitment_signed_dance( + &nodes[1], + &nodes[2], + &unblinded_node_updates.commitment_signed, + true, + false, ); - do_commitment_signed_dance(&nodes[1], &nodes[2], &unblinded_node_updates.commitment_signed, true, false); } { - let unblinded_node_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let unblinded_node_updates = + get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_update_fail_htlc( - nodes[1].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0] + nodes[1].node.get_our_node_id(), + &unblinded_node_updates.update_fail_htlcs[0], + ); + do_commitment_signed_dance( + &nodes[0], + &nodes[1], + &unblinded_node_updates.commitment_signed, + false, + false, ); - do_commitment_signed_dance(&nodes[0], &nodes[1], &unblinded_node_updates.commitment_signed, false, false); } { let payment_failed_conditions = PaymentFailedConditions::new() .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionPayload, &[0; 0]); - expect_payment_failed_conditions(&nodes[0], payment_hash, true, payment_failed_conditions); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + true, + payment_failed_conditions, + ); } } } @@ -2184,25 +3225,47 @@ fn test_trampoline_unblinded_receive() { let chanmon_cfgs = create_chanmon_cfgs(TOTAL_NODE_COUNT); let node_cfgs = create_node_cfgs(TOTAL_NODE_COUNT, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]); + let node_chanmgrs = + create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]); let mut nodes = create_network(TOTAL_NODE_COUNT, &node_cfgs, &node_chanmgrs); - let (_, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); - let (_, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); + let (_, _, chan_id_alice_bob, _) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + let (_, _, chan_id_bob_carol, _) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); - for i in 0..TOTAL_NODE_COUNT { // connect all nodes' blocks - connect_blocks(&nodes[i], (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1); + for i in 0..TOTAL_NODE_COUNT { + // connect all nodes' blocks + connect_blocks( + &nodes[i], + (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1, + ); } let alice_node_id = nodes[0].node().get_our_node_id(); let bob_node_id = nodes[1].node().get_our_node_id(); let carol_node_id = nodes[2].node().get_our_node_id(); - let alice_bob_scid = nodes[0].node().list_channels().iter().find(|c| c.channel_id == chan_id_alice_bob).unwrap().short_channel_id.unwrap(); - let bob_carol_scid = nodes[1].node().list_channels().iter().find(|c| c.channel_id == chan_id_bob_carol).unwrap().short_channel_id.unwrap(); + let alice_bob_scid = nodes[0] + .node() + .list_channels() + .iter() + .find(|c| c.channel_id == chan_id_alice_bob) + .unwrap() + .short_channel_id + .unwrap(); + let bob_carol_scid = nodes[1] + .node() + .list_channels() + .iter() + .find(|c| c.channel_id == chan_id_bob_carol) + .unwrap() + .short_channel_id + .unwrap(); let amt_msat = 1000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); let payee_tlvs = blinded_path::payment::TrampolineForwardTlvs { next_trampoline: alice_node_id, payment_constraints: PaymentConstraints { @@ -2220,11 +3283,16 @@ fn test_trampoline_unblinded_receive() { let carol_unblinded_tlvs = payee_tlvs.encode(); let path = [(carol_node_id, WithoutLength(&carol_unblinded_tlvs))]; - let carol_alice_trampoline_session_priv = secret_from_hex("a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03"); - let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv); + let carol_alice_trampoline_session_priv = + secret_from_hex("a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03"); + let carol_blinding_point = + PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv); let carol_blinded_hops = blinded_path::utils::construct_blinded_hops( - &secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv - ).unwrap(); + &secp_ctx, + path.into_iter(), + &carol_alice_trampoline_session_priv, + ) + .unwrap(); let route = Route { paths: vec![Path { @@ -2239,7 +3307,6 @@ fn test_trampoline_unblinded_receive() { cltv_expiry_delta: 48, maybe_announced_channel: false, }, - // Carol RouteHop { pubkey: carol_node_id, @@ -2249,7 +3316,7 @@ fn test_trampoline_unblinded_receive() { fee_msat: 0, cltv_expiry_delta: 48, maybe_announced_channel: false, - } + }, ], blinded_tail: Some(BlindedTail { trampoline_hops: vec![ @@ -2265,54 +3332,89 @@ fn test_trampoline_unblinded_receive() { blinding_point: carol_blinding_point, excess_final_cltv_expiry_delta: 39, final_value_msat: amt_msat, - }) + }), }], route_params: None, }; - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + ) + .unwrap(); let replacement_onion = { // create a substitute onion where the last Trampoline hop is an unblinded receive, which we // (deliberately) do not support out of the box, therefore necessitating this workaround - let trampoline_secret_key = secret_from_hex("0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799"); - let prng_seed = secret_from_hex("fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9"); + let trampoline_secret_key = + secret_from_hex("0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799"); + let prng_seed = + secret_from_hex("fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9"); let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let blinded_tail = route.paths[0].blinded_tail.clone().unwrap(); - let (mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils::build_trampoline_onion_payloads(&blinded_tail, amt_msat, &recipient_onion_fields, 32, &None).unwrap(); + let (mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = + onion_utils::build_trampoline_onion_payloads( + &blinded_tail, + amt_msat, + &recipient_onion_fields, + 32, + &None, + ) + .unwrap(); // pop the last dummy hop trampoline_payloads.pop(); trampoline_payloads.push(msgs::OutboundTrampolinePayload::Receive { - payment_data: Some(msgs::FinalOnionHopData { - payment_secret, - total_msat: amt_msat, - }), + payment_data: Some(msgs::FinalOnionHopData { payment_secret, total_msat: amt_msat }), sender_intended_htlc_amt_msat: amt_msat, cltv_expiry_height: 104, }); - let trampoline_onion_keys = onion_utils::construct_trampoline_onion_keys(&secp_ctx, &route.paths[0].blinded_tail.as_ref().unwrap(), &trampoline_secret_key); + let trampoline_onion_keys = onion_utils::construct_trampoline_onion_keys( + &secp_ctx, + &route.paths[0].blinded_tail.as_ref().unwrap(), + &trampoline_secret_key, + ); let trampoline_packet = onion_utils::construct_trampoline_onion_packet( trampoline_payloads, trampoline_onion_keys, prng_seed.secret_bytes(), &payment_hash, None, - ).unwrap(); + ) + .unwrap(); - let outer_session_priv = secret_from_hex("e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677"); + let outer_session_priv = + secret_from_hex("e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677"); - let (outer_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], outer_total_msat, &recipient_onion_fields, outer_starting_htlc_offset, &None, None, Some(trampoline_packet)).unwrap(); - let outer_onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.clone().paths[0], &outer_session_priv); + let (outer_payloads, _, _) = onion_utils::build_onion_payloads( + &route.paths[0], + outer_total_msat, + &recipient_onion_fields, + outer_starting_htlc_offset, + &None, + None, + Some(trampoline_packet), + ) + .unwrap(); + let outer_onion_keys = onion_utils::construct_onion_keys( + &secp_ctx, + &route.clone().paths[0], + &outer_session_priv, + ); let outer_packet = onion_utils::construct_onion_packet( outer_payloads, outer_onion_keys, prng_seed.secret_bytes(), &payment_hash, - ).unwrap(); + ) + .unwrap(); outer_packet }; @@ -2321,21 +3423,23 @@ fn test_trampoline_unblinded_receive() { let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - let mut first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + let mut first_message_event = + remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); let mut update_message = match first_message_event { MessageSendEvent::UpdateHTLCs { ref mut updates, .. } => { assert_eq!(updates.update_add_htlcs.len(), 1); updates.update_add_htlcs.get_mut(0) }, - _ => panic!() + _ => panic!(), }; update_message.map(|msg| { msg.onion_routing_packet = replacement_onion.clone(); }); let route: &[&Node] = &[&nodes[1], &nodes[2]]; - let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event) - .with_payment_secret(payment_secret); + let args = + PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event) + .with_payment_secret(payment_secret); do_pass_along_path(args); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); @@ -2347,25 +3451,47 @@ fn test_trampoline_forward_rejection() { let chanmon_cfgs = create_chanmon_cfgs(TOTAL_NODE_COUNT); let node_cfgs = create_node_cfgs(TOTAL_NODE_COUNT, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]); + let node_chanmgrs = + create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]); let mut nodes = create_network(TOTAL_NODE_COUNT, &node_cfgs, &node_chanmgrs); - let (_, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); - let (_, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); + let (_, _, chan_id_alice_bob, _) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + let (_, _, chan_id_bob_carol, _) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); - for i in 0..TOTAL_NODE_COUNT { // connect all nodes' blocks - connect_blocks(&nodes[i], (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1); + for i in 0..TOTAL_NODE_COUNT { + // connect all nodes' blocks + connect_blocks( + &nodes[i], + (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1, + ); } let alice_node_id = nodes[0].node().get_our_node_id(); let bob_node_id = nodes[1].node().get_our_node_id(); let carol_node_id = nodes[2].node().get_our_node_id(); - let alice_bob_scid = nodes[0].node().list_channels().iter().find(|c| c.channel_id == chan_id_alice_bob).unwrap().short_channel_id.unwrap(); - let bob_carol_scid = nodes[1].node().list_channels().iter().find(|c| c.channel_id == chan_id_bob_carol).unwrap().short_channel_id.unwrap(); + let alice_bob_scid = nodes[0] + .node() + .list_channels() + .iter() + .find(|c| c.channel_id == chan_id_alice_bob) + .unwrap() + .short_channel_id + .unwrap(); + let bob_carol_scid = nodes[1] + .node() + .list_channels() + .iter() + .find(|c| c.channel_id == chan_id_bob_carol) + .unwrap() + .short_channel_id + .unwrap(); let amt_msat = 1000; - let (payment_preimage, payment_hash, _) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let (payment_preimage, payment_hash, _) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); let route = Route { paths: vec![Path { @@ -2380,7 +3506,6 @@ fn test_trampoline_forward_rejection() { cltv_expiry_delta: 48, maybe_announced_channel: false, }, - // Carol RouteHop { pubkey: carol_node_id, @@ -2390,7 +3515,7 @@ fn test_trampoline_forward_rejection() { fee_msat: 0, cltv_expiry_delta: 48, maybe_announced_channel: false, - } + }, ], blinded_tail: Some(BlindedTail { trampoline_hops: vec![ @@ -2401,7 +3526,6 @@ fn test_trampoline_forward_rejection() { fee_msat: amt_msat, cltv_expiry_delta: 24, }, - // Alice (unreachable) TrampolineHop { pubkey: alice_node_id, @@ -2410,7 +3534,7 @@ fn test_trampoline_forward_rejection() { cltv_expiry_delta: 24, }, ], - hops: vec![BlindedHop{ + hops: vec![BlindedHop { // Fake public key blinded_node_id: alice_node_id, encrypted_payload: vec![], @@ -2418,39 +3542,65 @@ fn test_trampoline_forward_rejection() { blinding_point: alice_node_id, excess_final_cltv_expiry_delta: 39, final_value_msat: amt_msat, - }) + }), }], route_params: None, }; - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.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); - let first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + let first_message_event = + remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); let route: &[&Node] = &[&nodes[1], &nodes[2]]; - let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event) - .with_payment_preimage(payment_preimage) - .without_claimable_event() - .expect_failure(HTLCDestination::FailedPayment { payment_hash }); + let args = + PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event) + .with_payment_preimage(payment_preimage) + .without_claimable_event() + .expect_failure(HTLCDestination::FailedPayment { payment_hash }); do_pass_along_path(args); { - let unblinded_node_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); + let unblinded_node_updates = + get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); nodes[1].node.handle_update_fail_htlc( - nodes[2].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0] + nodes[2].node.get_our_node_id(), + &unblinded_node_updates.update_fail_htlcs[0], + ); + do_commitment_signed_dance( + &nodes[1], + &nodes[2], + &unblinded_node_updates.commitment_signed, + true, + false, ); - do_commitment_signed_dance(&nodes[1], &nodes[2], &unblinded_node_updates.commitment_signed, true, false); } { - let unblinded_node_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let unblinded_node_updates = + get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_update_fail_htlc( - nodes[1].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0] + nodes[1].node.get_our_node_id(), + &unblinded_node_updates.update_fail_htlcs[0], + ); + do_commitment_signed_dance( + &nodes[0], + &nodes[1], + &unblinded_node_updates.commitment_signed, + false, + false, ); - do_commitment_signed_dance(&nodes[0], &nodes[1], &unblinded_node_updates.commitment_signed, false, false); } { // Expect UnknownNextPeer error while we are unable to route forwarding Trampoline payments. diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 621bae134cf..12407a488bb 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -10,43 +10,46 @@ //! Various utilities for building scripts related to channels. These are //! largely of interest for those implementing the traits on [`crate::sign`] by hand. -use bitcoin::{PubkeyHash, WPubkeyHash}; use bitcoin::amount::Amount; -use bitcoin::script::{Script, ScriptBuf, Builder}; use bitcoin::opcodes; -use bitcoin::transaction::{TxIn,TxOut,OutPoint,Transaction}; +use bitcoin::script::{Builder, Script, ScriptBuf}; use bitcoin::sighash; use bitcoin::sighash::EcdsaSighashType; use bitcoin::transaction::Version; +use bitcoin::transaction::{OutPoint, Transaction, TxIn, TxOut}; +use bitcoin::{PubkeyHash, WPubkeyHash}; -use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::hash_types::Txid; use bitcoin::hashes::hash160::Hash as Hash160; -use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::ripemd160::Hash as Ripemd160; -use bitcoin::hash_types::Txid; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::{Hash, HashEngine}; use crate::chain::chaininterface::fee_for_weight; use crate::chain::package::WEIGHT_REVOKED_OUTPUT; +use crate::ln::msgs::DecodeError; use crate::sign::EntropySource; use crate::types::payment::{PaymentHash, PaymentPreimage}; -use crate::ln::msgs::DecodeError; use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, Writeable, Writer}; use crate::util::transaction_utils; -use bitcoin::locktime::absolute::LockTime; use bitcoin::ecdsa::Signature as BitcoinSignature; -use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar}; -use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message}; +use bitcoin::locktime::absolute::LockTime; +use bitcoin::secp256k1::{ecdsa::Signature, Message, Secp256k1}; +use bitcoin::secp256k1::{PublicKey, Scalar, SecretKey}; use bitcoin::{secp256k1, Sequence, Witness}; +use super::channel_keys::{ + DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, HtlcKey, RevocationBasepoint, + RevocationKey, +}; +use crate::chain; +use crate::crypto::utils::{sign, sign_with_aux_rand}; use crate::io; +use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, INITIAL_COMMITMENT_NUMBER}; +use crate::types::features::ChannelTypeFeatures; use core::cmp; -use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI}; use core::ops::Deref; -use crate::chain; -use crate::types::features::ChannelTypeFeatures; -use crate::crypto::utils::{sign, sign_with_aux_rand}; -use super::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint}; #[allow(unused_imports)] use crate::prelude::*; @@ -87,18 +90,16 @@ pub const HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT: u64 = 288; pub const HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT: u64 = 327; /// The size of the 2-of-2 multisig script -const MULTISIG_SCRIPT_SIZE: u64 = - 1 + // OP_2 +const MULTISIG_SCRIPT_SIZE: u64 = 1 + // OP_2 1 + // data len 33 + // pubkey1 1 + // data len 33 + // pubkey2 1 + // OP_2 - 1; // OP_CHECKMULTISIG + 1; // OP_CHECKMULTISIG /// The weight of a funding transaction input (2-of-2 P2WSH) /// See https://github.com/lightning/bolts/blob/master/03-transactions.md#expected-weight-of-the-commitment-transaction -pub const FUNDING_TRANSACTION_WITNESS_WEIGHT: u64 = - 1 + // number_of_witness_elements +pub const FUNDING_TRANSACTION_WITNESS_WEIGHT: u64 = 1 + // number_of_witness_elements 1 + // nil_len 1 + // sig len 73 + // sig1 @@ -112,7 +113,11 @@ pub const FUNDING_TRANSACTION_WITNESS_WEIGHT: u64 = pub fn htlc_success_tx_weight(channel_type_features: &ChannelTypeFeatures) -> u64 { const HTLC_SUCCESS_TX_WEIGHT: u64 = 703; const HTLC_SUCCESS_ANCHOR_TX_WEIGHT: u64 = 706; - if channel_type_features.supports_anchors_zero_fee_htlc_tx() { HTLC_SUCCESS_ANCHOR_TX_WEIGHT } else { HTLC_SUCCESS_TX_WEIGHT } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + HTLC_SUCCESS_ANCHOR_TX_WEIGHT + } else { + HTLC_SUCCESS_TX_WEIGHT + } } /// Gets the weight for an HTLC-Timeout transaction. @@ -120,7 +125,11 @@ pub fn htlc_success_tx_weight(channel_type_features: &ChannelTypeFeatures) -> u6 pub fn htlc_timeout_tx_weight(channel_type_features: &ChannelTypeFeatures) -> u64 { const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663; const HTLC_TIMEOUT_ANCHOR_TX_WEIGHT: u64 = 666; - if channel_type_features.supports_anchors_zero_fee_htlc_tx() { HTLC_TIMEOUT_ANCHOR_TX_WEIGHT } else { HTLC_TIMEOUT_TX_WEIGHT } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + HTLC_TIMEOUT_ANCHOR_TX_WEIGHT + } else { + HTLC_TIMEOUT_TX_WEIGHT + } } /// Describes the type of HTLC claim as determined by analyzing the witness. @@ -181,8 +190,9 @@ impl HTLCClaim { } else { None } - } else if witness_script.len() > MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT && - witness_script.len() <= MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT { + } else if witness_script.len() > MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT + && witness_script.len() <= MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT + { // Handle remaining range of ACCEPTED_HTLC_SCRIPT_WEIGHT. if witness.len() == 3 && second_to_last.len() == 33 { // @@ -210,24 +220,38 @@ pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; pub(crate) fn commitment_tx_base_weight(channel_type_features: &ChannelTypeFeatures) -> u64 { const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; const COMMITMENT_TX_BASE_ANCHOR_WEIGHT: u64 = 1124; - if channel_type_features.supports_anchors_zero_fee_htlc_tx() { COMMITMENT_TX_BASE_ANCHOR_WEIGHT } else { COMMITMENT_TX_BASE_WEIGHT } + if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + COMMITMENT_TX_BASE_ANCHOR_WEIGHT + } else { + COMMITMENT_TX_BASE_WEIGHT + } } /// Get the fee cost of a commitment tx with a given number of HTLC outputs. /// Note that num_htlcs should not include dust HTLCs. -pub(crate) fn commit_tx_fee_sat(feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 { - feerate_per_kw as u64 * - (commitment_tx_base_weight(channel_type_features) + - num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) +pub(crate) fn commit_tx_fee_sat( + feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures, +) -> u64 { + feerate_per_kw as u64 + * (commitment_tx_base_weight(channel_type_features) + + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 } -pub(crate) fn commit_and_htlc_tx_fees_sat(feerate_per_kw: u32, num_accepted_htlcs: usize, num_offered_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 { +pub(crate) fn commit_and_htlc_tx_fees_sat( + feerate_per_kw: u32, num_accepted_htlcs: usize, num_offered_htlcs: usize, + channel_type_features: &ChannelTypeFeatures, +) -> u64 { let num_htlcs = num_accepted_htlcs + num_offered_htlcs; let commit_tx_fees_sat = commit_tx_fee_sat(feerate_per_kw, num_htlcs, channel_type_features); let htlc_tx_fees_sat = if !channel_type_features.supports_anchors_zero_fee_htlc_tx() { - num_accepted_htlcs as u64 * htlc_success_tx_weight(channel_type_features) * feerate_per_kw as u64 / 1000 - + num_offered_htlcs as u64 * htlc_timeout_tx_weight(channel_type_features) * feerate_per_kw as u64 / 1000 + num_accepted_htlcs as u64 + * htlc_success_tx_weight(channel_type_features) + * feerate_per_kw as u64 + / 1000 + num_offered_htlcs as u64 + * htlc_timeout_tx_weight(channel_type_features) + * feerate_per_kw as u64 + / 1000 } else { 0 }; @@ -251,7 +275,10 @@ pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] } /// Build a closing transaction -pub fn build_closing_transaction(to_holder_value_sat: Amount, to_counterparty_value_sat: Amount, to_holder_script: ScriptBuf, to_counterparty_script: ScriptBuf, funding_outpoint: OutPoint) -> Transaction { +pub fn build_closing_transaction( + to_holder_value_sat: Amount, to_counterparty_value_sat: Amount, to_holder_script: ScriptBuf, + to_counterparty_script: ScriptBuf, funding_outpoint: OutPoint, +) -> Transaction { let txins = { let ins: Vec = vec![TxIn { previous_output: funding_outpoint, @@ -265,32 +292,24 @@ pub fn build_closing_transaction(to_holder_value_sat: Amount, to_counterparty_va let mut txouts: Vec<(TxOut, ())> = Vec::new(); if to_counterparty_value_sat > Amount::ZERO { - txouts.push((TxOut { - script_pubkey: to_counterparty_script, - value: to_counterparty_value_sat - }, ())); + txouts.push(( + TxOut { script_pubkey: to_counterparty_script, value: to_counterparty_value_sat }, + (), + )); } if to_holder_value_sat > Amount::ZERO { - txouts.push((TxOut { - script_pubkey: to_holder_script, - value: to_holder_value_sat - }, ())); + txouts.push((TxOut { script_pubkey: to_holder_script, value: to_holder_value_sat }, ())); } - transaction_utils::sort_outputs(&mut txouts, |_, _| { cmp::Ordering::Equal }); // Ordering doesnt matter if they used our pubkey... + transaction_utils::sort_outputs(&mut txouts, |_, _| cmp::Ordering::Equal); // Ordering doesnt matter if they used our pubkey... let mut outputs: Vec = Vec::new(); for out in txouts.drain(..) { outputs.push(out.0); } - Transaction { - version: Version::TWO, - lock_time: LockTime::ZERO, - input: txins, - output: outputs, - } + Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: txins, output: outputs } } /// Implements the per-commitment secret storage scheme from @@ -306,9 +325,11 @@ pub struct CounterpartyCommitmentSecrets { impl Eq for CounterpartyCommitmentSecrets {} impl PartialEq for CounterpartyCommitmentSecrets { fn eq(&self, other: &Self) -> bool { - for (&(ref secret, ref idx), &(ref o_secret, ref o_idx)) in self.old_secrets.iter().zip(other.old_secrets.iter()) { + for (&(ref secret, ref idx), &(ref o_secret, ref o_idx)) in + self.old_secrets.iter().zip(other.old_secrets.iter()) + { if secret != o_secret || idx != o_idx { - return false + return false; } } true @@ -318,14 +339,14 @@ impl PartialEq for CounterpartyCommitmentSecrets { impl CounterpartyCommitmentSecrets { /// Creates a new empty `CounterpartyCommitmentSecrets` structure. pub fn new() -> Self { - Self { old_secrets: [([0; 32], 1 << 48); 49], } + Self { old_secrets: [([0; 32], 1 << 48); 49] } } #[inline] fn place_secret(idx: u64) -> u8 { for i in 0..48 { if idx & (1 << i) == (1 << i) { - return i + return i; } } 48 @@ -379,7 +400,7 @@ impl CounterpartyCommitmentSecrets { pub fn get_secret(&self, idx: u64) -> Option<[u8; 32]> { for i in 0..self.old_secrets.len() { if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 { - return Some(Self::derive_secret(self.old_secrets[i].0, i as u8, idx)) + return Some(Self::derive_secret(self.old_secrets[i].0, i as u8, idx)); } } assert!(idx < self.get_min_seen_secret()); @@ -411,7 +432,9 @@ impl Readable for CounterpartyCommitmentSecrets { /// Derives a per-commitment-transaction private key (eg an htlc key or delayed_payment key) /// from the base secret and the per_commitment_point. -pub fn derive_private_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> SecretKey { +pub fn derive_private_key( + secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_secret: &SecretKey, +) -> SecretKey { let mut sha = Sha256::engine(); sha.input(&per_commitment_point.serialize()); sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).serialize()); @@ -427,10 +450,12 @@ pub fn derive_private_key(secp_ctx: &Secp256k1, per_co /// commitment transaction, thus per_commitment_secret always come from cheater /// and revocation_base_secret always come from punisher, which is the broadcaster /// of the transaction spending with this key knowledge. -pub fn derive_private_revocation_key(secp_ctx: &Secp256k1, - per_commitment_secret: &SecretKey, countersignatory_revocation_base_secret: &SecretKey) --> SecretKey { - let countersignatory_revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &countersignatory_revocation_base_secret); +pub fn derive_private_revocation_key( + secp_ctx: &Secp256k1, per_commitment_secret: &SecretKey, + countersignatory_revocation_base_secret: &SecretKey, +) -> SecretKey { + let countersignatory_revocation_base_point = + PublicKey::from_secret_key(&secp_ctx, &countersignatory_revocation_base_secret); let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); let rev_append_commit_hash_key = { @@ -448,9 +473,13 @@ pub fn derive_private_revocation_key(secp_ctx: &Secp256k1 Sha256::from_engine(sha).to_byte_array() }; - let countersignatory_contrib = countersignatory_revocation_base_secret.clone().mul_tweak(&Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap()) + let countersignatory_contrib = countersignatory_revocation_base_secret + .clone() + .mul_tweak(&Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap()) .expect("Multiplying a secret key by a hash is expected to never fail per secp256k1 docs"); - let broadcaster_contrib = per_commitment_secret.clone().mul_tweak(&Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap()) + let broadcaster_contrib = per_commitment_secret + .clone() + .mul_tweak(&Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap()) .expect("Multiplying a secret key by a hash is expected to never fail per secp256k1 docs"); countersignatory_contrib.add_tweak(&Scalar::from_be_bytes(broadcaster_contrib.secret_bytes()).unwrap()) .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.") @@ -526,19 +555,44 @@ impl_writeable_tlv_based!(ChannelPublicKeys, { impl TxCreationKeys { /// Create per-state keys from channel base points and the per-commitment point. /// Key set is asymmetric and can't be used as part of counter-signatory set of transactions. - pub fn derive_new(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &DelayedPaymentBasepoint, broadcaster_htlc_base: &HtlcBasepoint, countersignatory_revocation_base: &RevocationBasepoint, countersignatory_htlc_base: &HtlcBasepoint) -> TxCreationKeys { + pub fn derive_new( + secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, + broadcaster_delayed_payment_base: &DelayedPaymentBasepoint, + broadcaster_htlc_base: &HtlcBasepoint, + countersignatory_revocation_base: &RevocationBasepoint, + countersignatory_htlc_base: &HtlcBasepoint, + ) -> TxCreationKeys { TxCreationKeys { per_commitment_point: per_commitment_point.clone(), - revocation_key: RevocationKey::from_basepoint(&secp_ctx, &countersignatory_revocation_base, &per_commitment_point), - broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &broadcaster_htlc_base, &per_commitment_point), - countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &countersignatory_htlc_base, &per_commitment_point), - broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &broadcaster_delayed_payment_base, &per_commitment_point), + revocation_key: RevocationKey::from_basepoint( + &secp_ctx, + &countersignatory_revocation_base, + &per_commitment_point, + ), + broadcaster_htlc_key: HtlcKey::from_basepoint( + &secp_ctx, + &broadcaster_htlc_base, + &per_commitment_point, + ), + countersignatory_htlc_key: HtlcKey::from_basepoint( + &secp_ctx, + &countersignatory_htlc_base, + &per_commitment_point, + ), + broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint( + &secp_ctx, + &broadcaster_delayed_payment_base, + &per_commitment_point, + ), } } /// Generate per-state keys from channel static keys. /// Key set is asymmetric and can't be used as part of counter-signatory set of transactions. - pub fn from_channel_static_keys(per_commitment_point: &PublicKey, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1) -> TxCreationKeys { + pub fn from_channel_static_keys( + per_commitment_point: &PublicKey, broadcaster_keys: &ChannelPublicKeys, + countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1, + ) -> TxCreationKeys { TxCreationKeys::derive_new( &secp_ctx, &per_commitment_point, @@ -555,29 +609,35 @@ impl TxCreationKeys { // keys of 33 bytes (+ 1 push). Generally, pushes are only 2 bytes (for values below 0x7fff, i.e. // around 7 months), however, a 7 month contest delay shouldn't result in being unable to reclaim // on-chain funds. -pub const REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH: usize = 6 + 4 + 34*2; +pub const REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH: usize = 6 + 4 + 34 * 2; /// A script either spendable by the revocation /// key or the broadcaster_delayed_payment_key and satisfying the relative-locktime OP_CSV constrain. /// Encumbering a `to_holder` output on a commitment transaction or 2nd-stage HTLC transactions. -pub fn get_revokeable_redeemscript(revocation_key: &RevocationKey, contest_delay: u16, broadcaster_delayed_payment_key: &DelayedPaymentKey) -> ScriptBuf { - let res = Builder::new().push_opcode(opcodes::all::OP_IF) - .push_slice(&revocation_key.to_public_key().serialize()) - .push_opcode(opcodes::all::OP_ELSE) - .push_int(contest_delay as i64) - .push_opcode(opcodes::all::OP_CSV) - .push_opcode(opcodes::all::OP_DROP) - .push_slice(&broadcaster_delayed_payment_key.to_public_key().serialize()) - .push_opcode(opcodes::all::OP_ENDIF) - .push_opcode(opcodes::all::OP_CHECKSIG) - .into_script(); +pub fn get_revokeable_redeemscript( + revocation_key: &RevocationKey, contest_delay: u16, + broadcaster_delayed_payment_key: &DelayedPaymentKey, +) -> ScriptBuf { + let res = Builder::new() + .push_opcode(opcodes::all::OP_IF) + .push_slice(&revocation_key.to_public_key().serialize()) + .push_opcode(opcodes::all::OP_ELSE) + .push_int(contest_delay as i64) + .push_opcode(opcodes::all::OP_CSV) + .push_opcode(opcodes::all::OP_DROP) + .push_slice(&broadcaster_delayed_payment_key.to_public_key().serialize()) + .push_opcode(opcodes::all::OP_ENDIF) + .push_opcode(opcodes::all::OP_CHECKSIG) + .into_script(); debug_assert!(res.len() <= REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH); res } /// Returns the script for the counterparty's output on a holder's commitment transaction based on /// the channel type. -pub fn get_counterparty_payment_script(channel_type_features: &ChannelTypeFeatures, payment_key: &PublicKey) -> ScriptBuf { +pub fn get_counterparty_payment_script( + channel_type_features: &ChannelTypeFeatures, payment_key: &PublicKey, +) -> ScriptBuf { if channel_type_features.supports_anchors_zero_fee_htlc_tx() { get_to_countersigner_keyed_anchor_redeemscript(payment_key).to_p2wsh() } else { @@ -633,105 +693,125 @@ impl_writeable_tlv_based!(HTLCOutputInCommitment, { }); #[inline] -pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_htlc_key: &HtlcKey, countersignatory_htlc_key: &HtlcKey, revocation_key: &RevocationKey) -> ScriptBuf { +pub(crate) fn get_htlc_redeemscript_with_explicit_keys( + htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, + broadcaster_htlc_key: &HtlcKey, countersignatory_htlc_key: &HtlcKey, + revocation_key: &RevocationKey, +) -> ScriptBuf { let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).to_byte_array(); if htlc.offered { - let mut bldr = Builder::new().push_opcode(opcodes::all::OP_DUP) - .push_opcode(opcodes::all::OP_HASH160) - .push_slice(PubkeyHash::hash(&revocation_key.to_public_key().serialize())) - .push_opcode(opcodes::all::OP_EQUAL) - .push_opcode(opcodes::all::OP_IF) - .push_opcode(opcodes::all::OP_CHECKSIG) - .push_opcode(opcodes::all::OP_ELSE) - .push_slice(&countersignatory_htlc_key.to_public_key().serialize()) - .push_opcode(opcodes::all::OP_SWAP) - .push_opcode(opcodes::all::OP_SIZE) - .push_int(32) - .push_opcode(opcodes::all::OP_EQUAL) - .push_opcode(opcodes::all::OP_NOTIF) - .push_opcode(opcodes::all::OP_DROP) - .push_int(2) - .push_opcode(opcodes::all::OP_SWAP) - .push_slice(&broadcaster_htlc_key.to_public_key().serialize()) - .push_int(2) - .push_opcode(opcodes::all::OP_CHECKMULTISIG) - .push_opcode(opcodes::all::OP_ELSE) - .push_opcode(opcodes::all::OP_HASH160) - .push_slice(&payment_hash160) - .push_opcode(opcodes::all::OP_EQUALVERIFY) - .push_opcode(opcodes::all::OP_CHECKSIG) - .push_opcode(opcodes::all::OP_ENDIF); + let mut bldr = Builder::new() + .push_opcode(opcodes::all::OP_DUP) + .push_opcode(opcodes::all::OP_HASH160) + .push_slice(PubkeyHash::hash(&revocation_key.to_public_key().serialize())) + .push_opcode(opcodes::all::OP_EQUAL) + .push_opcode(opcodes::all::OP_IF) + .push_opcode(opcodes::all::OP_CHECKSIG) + .push_opcode(opcodes::all::OP_ELSE) + .push_slice(&countersignatory_htlc_key.to_public_key().serialize()) + .push_opcode(opcodes::all::OP_SWAP) + .push_opcode(opcodes::all::OP_SIZE) + .push_int(32) + .push_opcode(opcodes::all::OP_EQUAL) + .push_opcode(opcodes::all::OP_NOTIF) + .push_opcode(opcodes::all::OP_DROP) + .push_int(2) + .push_opcode(opcodes::all::OP_SWAP) + .push_slice(&broadcaster_htlc_key.to_public_key().serialize()) + .push_int(2) + .push_opcode(opcodes::all::OP_CHECKMULTISIG) + .push_opcode(opcodes::all::OP_ELSE) + .push_opcode(opcodes::all::OP_HASH160) + .push_slice(&payment_hash160) + .push_opcode(opcodes::all::OP_EQUALVERIFY) + .push_opcode(opcodes::all::OP_CHECKSIG) + .push_opcode(opcodes::all::OP_ENDIF); if channel_type_features.supports_anchors_zero_fee_htlc_tx() { - bldr = bldr.push_opcode(opcodes::all::OP_PUSHNUM_1) + bldr = bldr + .push_opcode(opcodes::all::OP_PUSHNUM_1) .push_opcode(opcodes::all::OP_CSV) .push_opcode(opcodes::all::OP_DROP); } - bldr.push_opcode(opcodes::all::OP_ENDIF) - .into_script() + bldr.push_opcode(opcodes::all::OP_ENDIF).into_script() } else { - let mut bldr = Builder::new().push_opcode(opcodes::all::OP_DUP) - .push_opcode(opcodes::all::OP_HASH160) - .push_slice(&PubkeyHash::hash(&revocation_key.to_public_key().serialize())) - .push_opcode(opcodes::all::OP_EQUAL) - .push_opcode(opcodes::all::OP_IF) - .push_opcode(opcodes::all::OP_CHECKSIG) - .push_opcode(opcodes::all::OP_ELSE) - .push_slice(&countersignatory_htlc_key.to_public_key().serialize()) - .push_opcode(opcodes::all::OP_SWAP) - .push_opcode(opcodes::all::OP_SIZE) - .push_int(32) - .push_opcode(opcodes::all::OP_EQUAL) - .push_opcode(opcodes::all::OP_IF) - .push_opcode(opcodes::all::OP_HASH160) - .push_slice(&payment_hash160) - .push_opcode(opcodes::all::OP_EQUALVERIFY) - .push_int(2) - .push_opcode(opcodes::all::OP_SWAP) - .push_slice(&broadcaster_htlc_key.to_public_key().serialize()) - .push_int(2) - .push_opcode(opcodes::all::OP_CHECKMULTISIG) - .push_opcode(opcodes::all::OP_ELSE) - .push_opcode(opcodes::all::OP_DROP) - .push_int(htlc.cltv_expiry as i64) - .push_opcode(opcodes::all::OP_CLTV) - .push_opcode(opcodes::all::OP_DROP) - .push_opcode(opcodes::all::OP_CHECKSIG) - .push_opcode(opcodes::all::OP_ENDIF); + let mut bldr = Builder::new() + .push_opcode(opcodes::all::OP_DUP) + .push_opcode(opcodes::all::OP_HASH160) + .push_slice(&PubkeyHash::hash(&revocation_key.to_public_key().serialize())) + .push_opcode(opcodes::all::OP_EQUAL) + .push_opcode(opcodes::all::OP_IF) + .push_opcode(opcodes::all::OP_CHECKSIG) + .push_opcode(opcodes::all::OP_ELSE) + .push_slice(&countersignatory_htlc_key.to_public_key().serialize()) + .push_opcode(opcodes::all::OP_SWAP) + .push_opcode(opcodes::all::OP_SIZE) + .push_int(32) + .push_opcode(opcodes::all::OP_EQUAL) + .push_opcode(opcodes::all::OP_IF) + .push_opcode(opcodes::all::OP_HASH160) + .push_slice(&payment_hash160) + .push_opcode(opcodes::all::OP_EQUALVERIFY) + .push_int(2) + .push_opcode(opcodes::all::OP_SWAP) + .push_slice(&broadcaster_htlc_key.to_public_key().serialize()) + .push_int(2) + .push_opcode(opcodes::all::OP_CHECKMULTISIG) + .push_opcode(opcodes::all::OP_ELSE) + .push_opcode(opcodes::all::OP_DROP) + .push_int(htlc.cltv_expiry as i64) + .push_opcode(opcodes::all::OP_CLTV) + .push_opcode(opcodes::all::OP_DROP) + .push_opcode(opcodes::all::OP_CHECKSIG) + .push_opcode(opcodes::all::OP_ENDIF); if channel_type_features.supports_anchors_zero_fee_htlc_tx() { - bldr = bldr.push_opcode(opcodes::all::OP_PUSHNUM_1) + bldr = bldr + .push_opcode(opcodes::all::OP_PUSHNUM_1) .push_opcode(opcodes::all::OP_CSV) .push_opcode(opcodes::all::OP_DROP); } - bldr.push_opcode(opcodes::all::OP_ENDIF) - .into_script() + bldr.push_opcode(opcodes::all::OP_ENDIF).into_script() } } /// Gets the witness redeemscript for an HTLC output in a commitment transaction. Note that htlc /// does not need to have its previous_output_index filled. #[inline] -pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, keys: &TxCreationKeys) -> ScriptBuf { - get_htlc_redeemscript_with_explicit_keys(htlc, channel_type_features, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key) +pub fn get_htlc_redeemscript( + htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, + keys: &TxCreationKeys, +) -> ScriptBuf { + get_htlc_redeemscript_with_explicit_keys( + htlc, + channel_type_features, + &keys.broadcaster_htlc_key, + &keys.countersignatory_htlc_key, + &keys.revocation_key, + ) } /// Gets the redeemscript for a funding output from the two funding public keys. /// Note that the order of funding public keys does not matter. -pub fn make_funding_redeemscript(broadcaster: &PublicKey, countersignatory: &PublicKey) -> ScriptBuf { +pub fn make_funding_redeemscript( + broadcaster: &PublicKey, countersignatory: &PublicKey, +) -> ScriptBuf { let broadcaster_funding_key = broadcaster.serialize(); let countersignatory_funding_key = countersignatory.serialize(); make_funding_redeemscript_from_slices(&broadcaster_funding_key, &countersignatory_funding_key) } -pub(crate) fn make_funding_redeemscript_from_slices(broadcaster_funding_key: &[u8; 33], countersignatory_funding_key: &[u8; 33]) -> ScriptBuf { +pub(crate) fn make_funding_redeemscript_from_slices( + broadcaster_funding_key: &[u8; 33], countersignatory_funding_key: &[u8; 33], +) -> ScriptBuf { let builder = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2); if broadcaster_funding_key[..] < countersignatory_funding_key[..] { - builder.push_slice(broadcaster_funding_key) - .push_slice(countersignatory_funding_key) + builder.push_slice(broadcaster_funding_key).push_slice(countersignatory_funding_key) } else { - builder.push_slice(countersignatory_funding_key) - .push_slice(broadcaster_funding_key) - }.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script() + builder.push_slice(countersignatory_funding_key).push_slice(broadcaster_funding_key) + } + .push_opcode(opcodes::all::OP_PUSHNUM_2) + .push_opcode(opcodes::all::OP_CHECKMULTISIG) + .into_script() } /// Builds an unsigned HTLC-Success or HTLC-Timeout transaction from the given channel and HTLC @@ -741,13 +821,21 @@ pub(crate) fn make_funding_redeemscript_from_slices(broadcaster_funding_key: &[u /// /// Panics if htlc.transaction_output_index.is_none() (as such HTLCs do not appear in the /// commitment transaction). -pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_delayed_payment_key: &DelayedPaymentKey, revocation_key: &RevocationKey) -> Transaction { - let txins= vec![build_htlc_input(commitment_txid, htlc, channel_type_features)]; +pub fn build_htlc_transaction( + commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, + channel_type_features: &ChannelTypeFeatures, + broadcaster_delayed_payment_key: &DelayedPaymentKey, revocation_key: &RevocationKey, +) -> Transaction { + let txins = vec![build_htlc_input(commitment_txid, htlc, channel_type_features)]; let mut txouts: Vec = Vec::new(); txouts.push(build_htlc_output( - feerate_per_kw, contest_delay, htlc, channel_type_features, - broadcaster_delayed_payment_key, revocation_key + feerate_per_kw, + contest_delay, + htlc, + channel_type_features, + broadcaster_delayed_payment_key, + revocation_key, )); Transaction { @@ -758,27 +846,40 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte } } -pub(crate) fn build_htlc_input(commitment_txid: &Txid, htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures) -> TxIn { +pub(crate) fn build_htlc_input( + commitment_txid: &Txid, htlc: &HTLCOutputInCommitment, + channel_type_features: &ChannelTypeFeatures, +) -> TxIn { TxIn { previous_output: OutPoint { txid: commitment_txid.clone(), - vout: htlc.transaction_output_index.expect("Can't build an HTLC transaction for a dust output"), + vout: htlc + .transaction_output_index + .expect("Can't build an HTLC transaction for a dust output"), }, script_sig: ScriptBuf::new(), - sequence: Sequence(if channel_type_features.supports_anchors_zero_fee_htlc_tx() { 1 } else { 0 }), + sequence: Sequence(if channel_type_features.supports_anchors_zero_fee_htlc_tx() { + 1 + } else { + 0 + }), witness: Witness::new(), } } pub(crate) fn build_htlc_output( - feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, broadcaster_delayed_payment_key: &DelayedPaymentKey, revocation_key: &RevocationKey + feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, + channel_type_features: &ChannelTypeFeatures, + broadcaster_delayed_payment_key: &DelayedPaymentKey, revocation_key: &RevocationKey, ) -> TxOut { let weight = if htlc.offered { htlc_timeout_tx_weight(channel_type_features) } else { htlc_success_tx_weight(channel_type_features) }; - let output_value = if channel_type_features.supports_anchors_zero_fee_htlc_tx() && !channel_type_features.supports_anchors_nonzero_fee_htlc_tx() { + let output_value = if channel_type_features.supports_anchors_zero_fee_htlc_tx() + && !channel_type_features.supports_anchors_nonzero_fee_htlc_tx() + { htlc.to_bitcoin_amount() } else { let total_fee = Amount::from_sat(feerate_per_kw as u64 * weight / 1000); @@ -786,7 +887,12 @@ pub(crate) fn build_htlc_output( }; TxOut { - script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_p2wsh(), + script_pubkey: get_revokeable_redeemscript( + revocation_key, + contest_delay, + broadcaster_delayed_payment_key, + ) + .to_p2wsh(), value: output_value, } } @@ -805,7 +911,10 @@ pub fn build_htlc_input_witness( let mut witness = Witness::new(); // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element. witness.push(vec![]); - witness.push_ecdsa_signature(&BitcoinSignature { signature: *remote_sig, sighash_type: remote_sighash_type }); + witness.push_ecdsa_signature(&BitcoinSignature { + signature: *remote_sig, + sighash_type: remote_sighash_type, + }); witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(*local_sig)); if let Some(preimage) = preimage { witness.push(preimage.0.to_vec()); @@ -836,7 +945,9 @@ pub fn build_htlc_input_witness( /// [`CounterpartyReceivedHTLCOutput`]: crate::chain::package::CounterpartyReceivedHTLCOutput /// [`HolderHTLCOutput`]: crate::chain::package::HolderHTLCOutput /// [`HolderFundingOutput`]: crate::chain::package::HolderFundingOutput -pub(crate) fn legacy_deserialization_prevention_marker_for_channel_type_features(features: &ChannelTypeFeatures) -> Option<()> { +pub(crate) fn legacy_deserialization_prevention_marker_for_channel_type_features( + features: &ChannelTypeFeatures, +) -> Option<()> { let mut legacy_version_bit_set = ChannelTypeFeatures::only_static_remote_key(); legacy_version_bit_set.set_scid_privacy_required(); legacy_version_bit_set.set_zero_conf_required(); @@ -875,7 +986,8 @@ pub fn shared_anchor_script_pubkey() -> ScriptBuf { /// <> /// (empty vector required to satisfy compliance with MINIMALIF-standard rule) pub fn get_keyed_anchor_redeemscript(funding_pubkey: &PublicKey) -> ScriptBuf { - Builder::new().push_slice(funding_pubkey.serialize()) + Builder::new() + .push_slice(funding_pubkey.serialize()) .push_opcode(opcodes::all::OP_CHECKSIG) .push_opcode(opcodes::all::OP_IFDUP) .push_opcode(opcodes::all::OP_NOTIF) @@ -887,16 +999,23 @@ pub fn get_keyed_anchor_redeemscript(funding_pubkey: &PublicKey) -> ScriptBuf { /// Locates the output with a keyed anchor (non-zero-fee-commitments) script paying to /// `funding_pubkey` within `commitment_tx`. -pub(crate) fn get_keyed_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> { +pub(crate) fn get_keyed_anchor_output<'a>( + commitment_tx: &'a Transaction, funding_pubkey: &PublicKey, +) -> Option<(u32, &'a TxOut)> { let anchor_script = get_keyed_anchor_redeemscript(funding_pubkey).to_p2wsh(); - commitment_tx.output.iter().enumerate() + commitment_tx + .output + .iter() + .enumerate() .find(|(_, txout)| txout.script_pubkey == anchor_script) .map(|(idx, txout)| (idx as u32, txout)) } /// Returns the witness required to satisfy and spend a keyed anchor (non-zero-fee-commitments) /// input. -pub fn build_keyed_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness { +pub fn build_keyed_anchor_input_witness( + funding_key: &PublicKey, funding_sig: &Signature, +) -> Witness { let anchor_redeem_script = get_keyed_anchor_redeemscript(funding_key); let mut ret = Witness::new(); ret.push_ecdsa_signature(&BitcoinSignature::sighash_all(*funding_sig)); @@ -961,11 +1080,11 @@ impl ChannelTransactionParameters { /// /// self.is_populated() must be true before calling this function. pub fn as_holder_broadcastable(&self) -> DirectedChannelTransactionParameters { - assert!(self.is_populated(), "self.late_parameters must be set before using as_holder_broadcastable"); - DirectedChannelTransactionParameters { - inner: self, - holder_is_broadcaster: true - } + assert!( + self.is_populated(), + "self.late_parameters must be set before using as_holder_broadcastable" + ); + DirectedChannelTransactionParameters { inner: self, holder_is_broadcaster: true } } /// Convert the holder/counterparty parameters to broadcaster/countersignatory-organized parameters, @@ -973,17 +1092,17 @@ impl ChannelTransactionParameters { /// /// self.is_populated() must be true before calling this function. pub fn as_counterparty_broadcastable(&self) -> DirectedChannelTransactionParameters { - assert!(self.is_populated(), "self.late_parameters must be set before using as_counterparty_broadcastable"); - DirectedChannelTransactionParameters { - inner: self, - holder_is_broadcaster: false - } + assert!( + self.is_populated(), + "self.late_parameters must be set before using as_counterparty_broadcastable" + ); + DirectedChannelTransactionParameters { inner: self, holder_is_broadcaster: false } } pub(crate) fn make_funding_redeemscript(&self) -> ScriptBuf { make_funding_redeemscript( &self.holder_pubkeys.funding_pubkey, - &self.counterparty_parameters.as_ref().unwrap().pubkeys.funding_pubkey + &self.counterparty_parameters.as_ref().unwrap().pubkeys.funding_pubkey, ) } @@ -1010,7 +1129,8 @@ impl ChannelTransactionParameters { selected_contest_delay: 42, }), funding_outpoint: Some(chain::transaction::OutPoint { - txid: Txid::from_byte_array([42; 32]), index: 0 + txid: Txid::from_byte_array([42; 32]), + index: 0, }), splice_parent_funding_txid: None, channel_type_features: ChannelTypeFeatures::empty(), @@ -1026,7 +1146,10 @@ impl_writeable_tlv_based!(CounterpartyChannelTransactionParameters, { impl Writeable for ChannelTransactionParameters { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let legacy_deserialization_prevention_marker = legacy_deserialization_prevention_marker_for_channel_type_features(&self.channel_type_features); + let legacy_deserialization_prevention_marker = + legacy_deserialization_prevention_marker_for_channel_type_features( + &self.channel_type_features, + ); write_tlv_fields!(writer, { (0, self.holder_pubkeys, required), (2, self.holder_selected_contest_delay, required), @@ -1080,7 +1203,10 @@ impl ReadableArgs> for ChannelTransactionParameters { let mut additional_features = ChannelTypeFeatures::empty(); additional_features.set_anchors_nonzero_fee_htlc_tx_required(); - chain::package::verify_channel_type_features(&channel_type_features, Some(&additional_features))?; + chain::package::verify_channel_type_features( + &channel_type_features, + Some(&additional_features), + )?; Ok(Self { holder_pubkeys: holder_pubkeys.0.unwrap(), @@ -1089,7 +1215,8 @@ impl ReadableArgs> for ChannelTransactionParameters { counterparty_parameters, funding_outpoint, splice_parent_funding_txid, - channel_type_features: channel_type_features.unwrap_or(ChannelTypeFeatures::only_static_remote_key()), + channel_type_features: channel_type_features + .unwrap_or(ChannelTypeFeatures::only_static_remote_key()), channel_value_satoshis, }) } @@ -1130,7 +1257,11 @@ impl<'a> DirectedChannelTransactionParameters<'a> { /// Note that the contest delay was selected by the countersignatory. pub fn contest_delay(&self) -> u16 { let counterparty_parameters = self.inner.counterparty_parameters.as_ref().unwrap(); - if self.holder_is_broadcaster { counterparty_parameters.selected_contest_delay } else { self.inner.holder_selected_contest_delay } + if self.holder_is_broadcaster { + counterparty_parameters.selected_contest_delay + } else { + self.inner.holder_selected_contest_delay + } } /// Whether the channel is outbound from the broadcaster. @@ -1138,7 +1269,11 @@ impl<'a> DirectedChannelTransactionParameters<'a> { /// The boolean representing the side that initiated the channel is /// an input to the commitment number obscure factor computation. pub fn is_outbound(&self) -> bool { - if self.holder_is_broadcaster { self.inner.is_outbound_from_holder } else { !self.inner.is_outbound_from_holder } + if self.holder_is_broadcaster { + self.inner.is_outbound_from_holder + } else { + !self.inner.is_outbound_from_holder + } } /// The funding outpoint @@ -1170,7 +1305,9 @@ pub struct HolderCommitmentTransaction { impl Deref for HolderCommitmentTransaction { type Target = CommitmentTransaction; - fn deref(&self) -> &Self::Target { &self.inner } + fn deref(&self) -> &Self::Target { + &self.inner + } } impl Eq for HolderCommitmentTransaction {} @@ -1192,22 +1329,33 @@ impl HolderCommitmentTransaction { #[cfg(test)] pub fn dummy(channel_value_satoshis: u64, nondust_htlcs: Vec) -> Self { let secp_ctx = Secp256k1::new(); - let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_digest([42; 32]), &SecretKey::from_slice(&[42; 32]).unwrap()); + let dummy_key = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let dummy_sig = sign( + &secp_ctx, + &secp256k1::Message::from_digest([42; 32]), + &SecretKey::from_slice(&[42; 32]).unwrap(), + ); let channel_pubkeys = ChannelPublicKeys { funding_pubkey: dummy_key.clone(), revocation_basepoint: RevocationBasepoint::from(dummy_key), payment_point: dummy_key.clone(), delayed_payment_basepoint: DelayedPaymentBasepoint::from(dummy_key.clone()), - htlc_basepoint: HtlcBasepoint::from(dummy_key.clone()) + htlc_basepoint: HtlcBasepoint::from(dummy_key.clone()), }; let channel_parameters = ChannelTransactionParameters { holder_pubkeys: channel_pubkeys.clone(), holder_selected_contest_delay: 0, is_outbound_from_holder: false, - counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: channel_pubkeys.clone(), selected_contest_delay: 0 }), - funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }), + counterparty_parameters: Some(CounterpartyChannelTransactionParameters { + pubkeys: channel_pubkeys.clone(), + selected_contest_delay: 0, + }), + funding_outpoint: Some(chain::transaction::OutPoint { + txid: Txid::all_zeros(), + index: 0, + }), splice_parent_funding_txid: None, channel_type_features: ChannelTypeFeatures::only_static_remote_key(), channel_value_satoshis, @@ -1216,36 +1364,56 @@ impl HolderCommitmentTransaction { for _ in 0..nondust_htlcs.len() { counterparty_htlc_sigs.push(dummy_sig); } - let inner = CommitmentTransaction::new(0, &dummy_key, 0, 0, 0, nondust_htlcs, &channel_parameters.as_counterparty_broadcastable(), &secp_ctx); + let inner = CommitmentTransaction::new( + 0, + &dummy_key, + 0, + 0, + 0, + nondust_htlcs, + &channel_parameters.as_counterparty_broadcastable(), + &secp_ctx, + ); HolderCommitmentTransaction { inner, counterparty_sig: dummy_sig, counterparty_htlc_sigs, - holder_sig_first: false + holder_sig_first: false, } } /// Create a new holder transaction with the given counterparty signatures. /// The funding keys are used to figure out which signature should go first when building the transaction for broadcast. - pub fn new(commitment_tx: CommitmentTransaction, counterparty_sig: Signature, counterparty_htlc_sigs: Vec, holder_funding_key: &PublicKey, counterparty_funding_key: &PublicKey) -> Self { + pub fn new( + commitment_tx: CommitmentTransaction, counterparty_sig: Signature, + counterparty_htlc_sigs: Vec, holder_funding_key: &PublicKey, + counterparty_funding_key: &PublicKey, + ) -> Self { Self { inner: commitment_tx, counterparty_sig, counterparty_htlc_sigs, - holder_sig_first: holder_funding_key.serialize()[..] < counterparty_funding_key.serialize()[..], + holder_sig_first: holder_funding_key.serialize()[..] + < counterparty_funding_key.serialize()[..], } } - pub(crate) fn add_holder_sig(&self, funding_redeemscript: &Script, holder_sig: Signature) -> Transaction { + pub(crate) fn add_holder_sig( + &self, funding_redeemscript: &Script, holder_sig: Signature, + ) -> Transaction { // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element. let mut tx = self.inner.built.transaction.clone(); tx.input[0].witness.push(Vec::new()); if self.holder_sig_first { tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(holder_sig)); - tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(self.counterparty_sig)); + tx.input[0] + .witness + .push_ecdsa_signature(&BitcoinSignature::sighash_all(self.counterparty_sig)); } else { - tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(self.counterparty_sig)); + tx.input[0] + .witness + .push_ecdsa_signature(&BitcoinSignature::sighash_all(self.counterparty_sig)); tx.input[0].witness.push_ecdsa_signature(&BitcoinSignature::sighash_all(holder_sig)); } @@ -1275,13 +1443,25 @@ impl BuiltCommitmentTransaction { /// Get the SIGHASH_ALL sighash value of the transaction. /// /// This can be used to verify a signature. - pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message { - let sighash = &sighash::SighashCache::new(&self.transaction).p2wsh_signature_hash(0, funding_redeemscript, Amount::from_sat(channel_value_satoshis), EcdsaSighashType::All).unwrap()[..]; + pub fn get_sighash_all( + &self, funding_redeemscript: &Script, channel_value_satoshis: u64, + ) -> Message { + let sighash = &sighash::SighashCache::new(&self.transaction) + .p2wsh_signature_hash( + 0, + funding_redeemscript, + Amount::from_sat(channel_value_satoshis), + EcdsaSighashType::All, + ) + .unwrap()[..]; hash_to_message!(sighash) } /// Signs the counterparty's commitment transaction. - pub fn sign_counterparty_commitment(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1) -> Signature { + pub fn sign_counterparty_commitment( + &self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, + secp_ctx: &Secp256k1, + ) -> Signature { let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis); sign(secp_ctx, &sighash, funding_key) } @@ -1289,8 +1469,11 @@ impl BuiltCommitmentTransaction { /// Signs the holder commitment transaction because we are about to broadcast it. pub fn sign_holder_commitment( &self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, - entropy_source: &ES, secp_ctx: &Secp256k1 - ) -> Signature where ES::Target: EntropySource { + entropy_source: &ES, secp_ctx: &Secp256k1, + ) -> Signature + where + ES::Target: EntropySource, + { let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis); sign_with_aux_rand(secp_ctx, &sighash, funding_key, entropy_source) } @@ -1313,25 +1496,24 @@ pub struct ClosingTransaction { impl ClosingTransaction { /// Construct an object of the class pub fn new( - to_holder_value_sat: u64, - to_counterparty_value_sat: u64, - to_holder_script: ScriptBuf, - to_counterparty_script: ScriptBuf, - funding_outpoint: OutPoint, + to_holder_value_sat: u64, to_counterparty_value_sat: u64, to_holder_script: ScriptBuf, + to_counterparty_script: ScriptBuf, funding_outpoint: OutPoint, ) -> Self { let to_holder_value_sat = Amount::from_sat(to_holder_value_sat); let to_counterparty_value_sat = Amount::from_sat(to_counterparty_value_sat); let built = build_closing_transaction( - to_holder_value_sat, to_counterparty_value_sat, - to_holder_script.clone(), to_counterparty_script.clone(), - funding_outpoint + to_holder_value_sat, + to_counterparty_value_sat, + to_holder_script.clone(), + to_counterparty_script.clone(), + funding_outpoint, ); ClosingTransaction { to_holder_value_sat, to_counterparty_value_sat, to_holder_script, to_counterparty_script, - built + built, } } @@ -1353,12 +1535,14 @@ impl ClosingTransaction { /// or using the built transaction. pub fn verify(&self, funding_outpoint: OutPoint) -> Result { let built = build_closing_transaction( - self.to_holder_value_sat, self.to_counterparty_value_sat, - self.to_holder_script.clone(), self.to_counterparty_script.clone(), - funding_outpoint + self.to_holder_value_sat, + self.to_counterparty_value_sat, + self.to_holder_script.clone(), + self.to_counterparty_script.clone(), + funding_outpoint, ); if self.built != built { - return Err(()) + return Err(()); } Ok(TrustedClosingTransaction { inner: self }) } @@ -1397,7 +1581,9 @@ pub struct TrustedClosingTransaction<'a> { impl<'a> Deref for TrustedClosingTransaction<'a> { type Target = ClosingTransaction; - fn deref(&self) -> &Self::Target { self.inner } + fn deref(&self) -> &Self::Target { + self.inner + } } impl<'a> TrustedClosingTransaction<'a> { @@ -1409,14 +1595,26 @@ impl<'a> TrustedClosingTransaction<'a> { /// Get the SIGHASH_ALL sighash value of the transaction. /// /// This can be used to verify a signature. - pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message { - let sighash = &sighash::SighashCache::new(&self.inner.built).p2wsh_signature_hash(0, funding_redeemscript, Amount::from_sat(channel_value_satoshis), EcdsaSighashType::All).unwrap()[..]; + pub fn get_sighash_all( + &self, funding_redeemscript: &Script, channel_value_satoshis: u64, + ) -> Message { + let sighash = &sighash::SighashCache::new(&self.inner.built) + .p2wsh_signature_hash( + 0, + funding_redeemscript, + Amount::from_sat(channel_value_satoshis), + EcdsaSighashType::All, + ) + .unwrap()[..]; hash_to_message!(sighash) } /// Sign a transaction, either because we are counter-signing the counterparty's transaction or /// because we are about to broadcast a holder transaction. - pub fn sign(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1) -> Signature { + pub fn sign( + &self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, + secp_ctx: &Secp256k1, + ) -> Signature { let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis); sign(secp_ctx, &sighash, funding_key) } @@ -1449,13 +1647,13 @@ pub struct CommitmentTransaction { impl Eq for CommitmentTransaction {} impl PartialEq for CommitmentTransaction { fn eq(&self, o: &Self) -> bool { - let eq = self.commitment_number == o.commitment_number && - self.to_broadcaster_value_sat == o.to_broadcaster_value_sat && - self.to_countersignatory_value_sat == o.to_countersignatory_value_sat && - self.feerate_per_kw == o.feerate_per_kw && - self.nondust_htlcs == o.nondust_htlcs && - self.channel_type_features == o.channel_type_features && - self.keys == o.keys; + let eq = self.commitment_number == o.commitment_number + && self.to_broadcaster_value_sat == o.to_broadcaster_value_sat + && self.to_countersignatory_value_sat == o.to_countersignatory_value_sat + && self.feerate_per_kw == o.feerate_per_kw + && self.nondust_htlcs == o.nondust_htlcs + && self.channel_type_features == o.channel_type_features + && self.keys == o.keys; if eq { debug_assert_eq!(self.built.transaction, o.built.transaction); debug_assert_eq!(self.built.txid, o.built.txid); @@ -1466,7 +1664,10 @@ impl PartialEq for CommitmentTransaction { impl Writeable for CommitmentTransaction { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let legacy_deserialization_prevention_marker = legacy_deserialization_prevention_marker_for_channel_type_features(&self.channel_type_features); + let legacy_deserialization_prevention_marker = + legacy_deserialization_prevention_marker_for_channel_type_features( + &self.channel_type_features, + ); write_tlv_fields!(writer, { (0, self.commitment_number, required), (1, self.to_broadcaster_delay, option), @@ -1500,7 +1701,10 @@ impl Readable for CommitmentTransaction { let mut additional_features = ChannelTypeFeatures::empty(); additional_features.set_anchors_nonzero_fee_htlc_tx_required(); - chain::package::verify_channel_type_features(&channel_type_features, Some(&additional_features))?; + chain::package::verify_channel_type_features( + &channel_type_features, + Some(&additional_features), + )?; Ok(Self { commitment_number: commitment_number.0.unwrap(), @@ -1511,7 +1715,8 @@ impl Readable for CommitmentTransaction { keys: keys.0.unwrap(), built: built.0.unwrap(), nondust_htlcs, - channel_type_features: channel_type_features.unwrap_or(ChannelTypeFeatures::only_static_remote_key()) + channel_type_features: channel_type_features + .unwrap_or(ChannelTypeFeatures::only_static_remote_key()), }) } } @@ -1522,18 +1727,37 @@ impl CommitmentTransaction { /// All HTLCs MUST be above the dust limit for the channel. /// The broadcaster and countersignatory amounts MUST be either 0 or above dust. If the amount /// is 0, the corresponding output will be omitted from the transaction. - pub fn new(commitment_number: u64, per_commitment_point: &PublicKey, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, feerate_per_kw: u32, mut nondust_htlcs: Vec, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1) -> CommitmentTransaction { + pub fn new( + commitment_number: u64, per_commitment_point: &PublicKey, to_broadcaster_value_sat: u64, + to_countersignatory_value_sat: u64, feerate_per_kw: u32, + mut nondust_htlcs: Vec, + channel_parameters: &DirectedChannelTransactionParameters, + secp_ctx: &Secp256k1, + ) -> CommitmentTransaction { let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat); let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat); - let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx); + let keys = TxCreationKeys::from_channel_static_keys( + per_commitment_point, + channel_parameters.broadcaster_pubkeys(), + channel_parameters.countersignatory_pubkeys(), + secp_ctx, + ); // Build and sort the outputs of the transaction. // Also sort the HTLC output data in `nondust_htlcs` in the same order, and populate the // transaction output indices therein. - let outputs = Self::build_outputs_and_htlcs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, &mut nondust_htlcs, channel_parameters); + let outputs = Self::build_outputs_and_htlcs( + &keys, + to_broadcaster_value_sat, + to_countersignatory_value_sat, + &mut nondust_htlcs, + channel_parameters, + ); - let (obscured_commitment_transaction_number, txins) = Self::build_inputs(commitment_number, channel_parameters); - let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); + let (obscured_commitment_transaction_number, txins) = + Self::build_inputs(commitment_number, channel_parameters); + let transaction = + Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); let txid = transaction.compute_txid(); CommitmentTransaction { commitment_number, @@ -1544,10 +1768,7 @@ impl CommitmentTransaction { nondust_htlcs, channel_type_features: channel_parameters.channel_type_features().clone(), keys, - built: BuiltCommitmentTransaction { - transaction, - txid - }, + built: BuiltCommitmentTransaction { transaction, txid }, } } @@ -1568,8 +1789,12 @@ impl CommitmentTransaction { // // `txouts` and `nondust_htlcs` MUST be of equal length, and of length >= 2. // For all `i < len`, the `TxOut` at `txouts[i]` MUST correspond to the HTLC at `nondust_htlcs[i]`. - fn is_left_greater(i: usize, txouts: &Vec, nondust_htlcs: &Vec) -> bool { - txouts[i - 1].value.cmp(&txouts[i].value) + fn is_left_greater( + i: usize, txouts: &Vec, nondust_htlcs: &Vec, + ) -> bool { + txouts[i - 1] + .value + .cmp(&txouts[i].value) .then(txouts[i - 1].script_pubkey.cmp(&txouts[i].script_pubkey)) .then(nondust_htlcs[i - 1].cltv_expiry.cmp(&nondust_htlcs[i].cltv_expiry)) // Note that due to hash collisions, we have to have a fallback comparison @@ -1579,21 +1804,36 @@ impl CommitmentTransaction { .is_gt() } - fn rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters) -> Result { - let (obscured_commitment_transaction_number, txins) = Self::build_inputs(self.commitment_number, channel_parameters); + fn rebuild_transaction( + &self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters, + ) -> Result { + let (obscured_commitment_transaction_number, txins) = + Self::build_inputs(self.commitment_number, channel_parameters); // First rebuild the htlc outputs, note that `outputs` is now the same length as `self.nondust_htlcs` - let mut outputs = Self::build_htlc_outputs(keys, &self.nondust_htlcs, channel_parameters.channel_type_features()); + let mut outputs = Self::build_htlc_outputs( + keys, + &self.nondust_htlcs, + channel_parameters.channel_type_features(), + ); // Check that the HTLC outputs are sorted by value, script pubkey, and cltv expiry. // Note that this only iterates if the length of `outputs` and `self.nondust_htlcs` is >= 2. - if (1..outputs.len()).into_iter().any(|i| Self::is_left_greater(i, &outputs, &self.nondust_htlcs)) { - return Err(()) + if (1..outputs.len()) + .into_iter() + .any(|i| Self::is_left_greater(i, &outputs, &self.nondust_htlcs)) + { + return Err(()); } // Then insert the max-4 non-htlc outputs, ordered by value, then by script pubkey let insert_non_htlc_output = |non_htlc_output: TxOut| { - let idx = match outputs.binary_search_by(|output| output.value.cmp(&non_htlc_output.value).then(output.script_pubkey.cmp(&non_htlc_output.script_pubkey))) { + let idx = match outputs.binary_search_by(|output| { + output + .value + .cmp(&non_htlc_output.value) + .then(output.script_pubkey.cmp(&non_htlc_output.script_pubkey)) + }) { // For non-HTLC outputs, if they're copying our SPK we don't really care if we // close the channel due to mismatches - they're doing something dumb Ok(i) => i, @@ -1608,37 +1848,42 @@ impl CommitmentTransaction { self.to_countersignatory_value_sat, channel_parameters, !self.nondust_htlcs.is_empty(), - insert_non_htlc_output + insert_non_htlc_output, ); - let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); + let transaction = + Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); let txid = transaction.compute_txid(); - let built_transaction = BuiltCommitmentTransaction { - transaction, - txid - }; + let built_transaction = BuiltCommitmentTransaction { transaction, txid }; Ok(built_transaction) } - fn make_transaction(obscured_commitment_transaction_number: u64, txins: Vec, outputs: Vec) -> Transaction { + fn make_transaction( + obscured_commitment_transaction_number: u64, txins: Vec, outputs: Vec, + ) -> Transaction { Transaction { version: Version::TWO, - lock_time: LockTime::from_consensus(((0x20 as u32) << 8 * 3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32)), + lock_time: LockTime::from_consensus( + ((0x20 as u32) << 8 * 3) + | ((obscured_commitment_transaction_number & 0xffffffu64) as u32), + ), input: txins, output: outputs, } } fn build_outputs_and_htlcs( - keys: &TxCreationKeys, - to_broadcaster_value_sat: Amount, - to_countersignatory_value_sat: Amount, - nondust_htlcs: &mut Vec, - channel_parameters: &DirectedChannelTransactionParameters + keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, + to_countersignatory_value_sat: Amount, nondust_htlcs: &mut Vec, + channel_parameters: &DirectedChannelTransactionParameters, ) -> Vec { // First build and sort the HTLC outputs. // Also sort the HTLC output data in `nondust_htlcs` in the same order. - let mut outputs = Self::build_sorted_htlc_outputs(keys, nondust_htlcs, channel_parameters.channel_type_features()); + let mut outputs = Self::build_sorted_htlc_outputs( + keys, + nondust_htlcs, + channel_parameters.channel_type_features(), + ); let tx_has_htlc_outputs = !outputs.is_empty(); // Initialize the transaction output indices; we will update them below when we @@ -1650,7 +1895,12 @@ impl CommitmentTransaction { // Then insert the max-4 non-htlc outputs, ordered by value, then by script pubkey let insert_non_htlc_output = |non_htlc_output: TxOut| { - let idx = match outputs.binary_search_by(|output| output.value.cmp(&non_htlc_output.value).then(output.script_pubkey.cmp(&non_htlc_output.script_pubkey))) { + let idx = match outputs.binary_search_by(|output| { + output + .value + .cmp(&non_htlc_output.value) + .then(output.script_pubkey.cmp(&non_htlc_output.script_pubkey)) + }) { // For non-HTLC outputs, if they're copying our SPK we don't really care if we // close the channel due to mismatches - they're doing something dumb Ok(i) => i, @@ -1677,33 +1927,36 @@ impl CommitmentTransaction { to_countersignatory_value_sat, channel_parameters, tx_has_htlc_outputs, - insert_non_htlc_output + insert_non_htlc_output, ); outputs } fn insert_non_htlc_outputs( - keys: &TxCreationKeys, - to_broadcaster_value_sat: Amount, + keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, - channel_parameters: &DirectedChannelTransactionParameters, - tx_has_htlc_outputs: bool, + channel_parameters: &DirectedChannelTransactionParameters, tx_has_htlc_outputs: bool, mut insert_non_htlc_output: F, ) where F: FnMut(TxOut), { - let countersignatory_payment_point = &channel_parameters.countersignatory_pubkeys().payment_point; - let countersignatory_funding_key = &channel_parameters.countersignatory_pubkeys().funding_pubkey; + let countersignatory_payment_point = + &channel_parameters.countersignatory_pubkeys().payment_point; + let countersignatory_funding_key = + &channel_parameters.countersignatory_pubkeys().funding_pubkey; let broadcaster_funding_key = &channel_parameters.broadcaster_pubkeys().funding_pubkey; let channel_type = channel_parameters.channel_type_features(); let contest_delay = channel_parameters.contest_delay(); if to_countersignatory_value_sat > Amount::ZERO { let script = if channel_type.supports_anchors_zero_fee_htlc_tx() { - get_to_countersigner_keyed_anchor_redeemscript(countersignatory_payment_point).to_p2wsh() + get_to_countersigner_keyed_anchor_redeemscript(countersignatory_payment_point) + .to_p2wsh() } else { - ScriptBuf::new_p2wpkh(&Hash160::hash(&countersignatory_payment_point.serialize()).into()) + ScriptBuf::new_p2wpkh( + &Hash160::hash(&countersignatory_payment_point.serialize()).into(), + ) }; insert_non_htlc_output(TxOut { script_pubkey: script, @@ -1742,16 +1995,16 @@ impl CommitmentTransaction { } } - fn build_htlc_outputs(keys: &TxCreationKeys, nondust_htlcs: &Vec, channel_type: &ChannelTypeFeatures) -> Vec { + fn build_htlc_outputs( + keys: &TxCreationKeys, nondust_htlcs: &Vec, + channel_type: &ChannelTypeFeatures, + ) -> Vec { // Allocate memory for the 4 possible non-htlc outputs let mut txouts = Vec::with_capacity(nondust_htlcs.len() + 4); for htlc in nondust_htlcs { let script = get_htlc_redeemscript(htlc, channel_type, keys); - let txout = TxOut { - script_pubkey: script.to_p2wsh(), - value: htlc.to_bitcoin_amount(), - }; + let txout = TxOut { script_pubkey: script.to_p2wsh(), value: htlc.to_bitcoin_amount() }; txouts.push(txout); } @@ -1759,9 +2012,8 @@ impl CommitmentTransaction { } fn build_sorted_htlc_outputs( - keys: &TxCreationKeys, - nondust_htlcs: &mut Vec, - channel_type: &ChannelTypeFeatures + keys: &TxCreationKeys, nondust_htlcs: &mut Vec, + channel_type: &ChannelTypeFeatures, ) -> Vec { // Note that `txouts` has the same length as `nondust_htlcs` here let mut txouts = Self::build_htlc_outputs(keys, nondust_htlcs, channel_type); @@ -1771,9 +2023,9 @@ impl CommitmentTransaction { // Also sort the HTLC output data in `nondust_htlcs` in the same order. // // This is insertion sort. In the worst case this is O(n^2) over 2 * 483 HTLCs in the - // channel. We expect people to transition soon to zero-fee-commitment channels, + // channel. We expect people to transition soon to zero-fee-commitment channels, // where n will be 2 * 114. - // + // // These are small numbers, and channels today rarely reach this protocol-max, if ever, // so we accept the performance tradeoff. @@ -1793,24 +2045,29 @@ impl CommitmentTransaction { txouts } - fn build_inputs(commitment_number: u64, channel_parameters: &DirectedChannelTransactionParameters) -> (u64, Vec) { + fn build_inputs( + commitment_number: u64, channel_parameters: &DirectedChannelTransactionParameters, + ) -> (u64, Vec) { let broadcaster_pubkeys = channel_parameters.broadcaster_pubkeys(); let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys(); - let commitment_transaction_number_obscure_factor = get_commitment_transaction_number_obscure_factor( - &broadcaster_pubkeys.payment_point, - &countersignatory_pubkeys.payment_point, - channel_parameters.is_outbound(), - ); + let commitment_transaction_number_obscure_factor = + get_commitment_transaction_number_obscure_factor( + &broadcaster_pubkeys.payment_point, + &countersignatory_pubkeys.payment_point, + channel_parameters.is_outbound(), + ); - let obscured_commitment_transaction_number = - commitment_transaction_number_obscure_factor ^ (INITIAL_COMMITMENT_NUMBER - commitment_number); + let obscured_commitment_transaction_number = commitment_transaction_number_obscure_factor + ^ (INITIAL_COMMITMENT_NUMBER - commitment_number); let txins = { let ins: Vec = vec![TxIn { previous_output: channel_parameters.funding_outpoint(), script_sig: ScriptBuf::new(), - sequence: Sequence(((0x80 as u32) << 8 * 3) - | ((obscured_commitment_transaction_number >> 3 * 8) as u32)), + sequence: Sequence( + ((0x80 as u32) << 8 * 3) + | ((obscured_commitment_transaction_number >> 3 * 8) as u32), + ), witness: Witness::new(), }]; ins @@ -1869,10 +2126,17 @@ impl CommitmentTransaction { /// /// An external validating signer must call this method before signing /// or using the built transaction. - pub fn verify(&self, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1) -> Result { + pub fn verify( + &self, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1, + ) -> Result { // This is the only field of the key cache that we trust let per_commitment_point = &self.keys.per_commitment_point; - let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx); + let keys = TxCreationKeys::from_channel_static_keys( + per_commitment_point, + channel_parameters.broadcaster_pubkeys(), + channel_parameters.countersignatory_pubkeys(), + secp_ctx, + ); if keys != self.keys { return Err(()); } @@ -1897,7 +2161,9 @@ pub struct TrustedCommitmentTransaction<'a> { impl<'a> Deref for TrustedCommitmentTransaction<'a> { type Target = CommitmentTransaction; - fn deref(&self) -> &Self::Target { self.inner } + fn deref(&self) -> &Self::Target { + self.inner + } } impl<'a> TrustedCommitmentTransaction<'a> { @@ -1928,22 +2194,50 @@ impl<'a> TrustedCommitmentTransaction<'a> { /// /// This function is only valid in the holder commitment context, it always uses EcdsaSighashType::All. pub fn get_htlc_sigs( - &self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters, - entropy_source: &ES, secp_ctx: &Secp256k1, - ) -> Result, ()> where ES::Target: EntropySource { + &self, htlc_base_key: &SecretKey, + channel_parameters: &DirectedChannelTransactionParameters, entropy_source: &ES, + secp_ctx: &Secp256k1, + ) -> Result, ()> + where + ES::Target: EntropySource, + { let inner = self.inner; let keys = &inner.keys; let txid = inner.built.txid; let mut ret = Vec::with_capacity(inner.nondust_htlcs.len()); - let holder_htlc_key = derive_private_key(secp_ctx, &inner.keys.per_commitment_point, htlc_base_key); + let holder_htlc_key = + derive_private_key(secp_ctx, &inner.keys.per_commitment_point, htlc_base_key); for this_htlc in inner.nondust_htlcs.iter() { assert!(this_htlc.transaction_output_index.is_some()); - let htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, &self.channel_type_features, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + let htlc_tx = build_htlc_transaction( + &txid, + inner.feerate_per_kw, + channel_parameters.contest_delay(), + &this_htlc, + &self.channel_type_features, + &keys.broadcaster_delayed_payment_key, + &keys.revocation_key, + ); - let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, &self.channel_type_features, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key); + let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys( + &this_htlc, + &self.channel_type_features, + &keys.broadcaster_htlc_key, + &keys.countersignatory_htlc_key, + &keys.revocation_key, + ); - let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, this_htlc.to_bitcoin_amount(), EcdsaSighashType::All).unwrap()[..]); + let sighash = hash_to_message!( + &sighash::SighashCache::new(&htlc_tx) + .p2wsh_signature_hash( + 0, + &htlc_redeemscript, + this_htlc.to_bitcoin_amount(), + EcdsaSighashType::All + ) + .unwrap()[..] + ); ret.push(sign_with_aux_rand(secp_ctx, &sighash, &holder_htlc_key, entropy_source)); } Ok(ret) @@ -1966,7 +2260,9 @@ impl<'a> TrustedCommitmentTransaction<'a> { ); let revokeable_p2wsh = revokeable_redeemscript.to_p2wsh(); let outputs = &self.inner.built.transaction.output; - outputs.iter().enumerate() + outputs + .iter() + .enumerate() .find(|(_, out)| out.script_pubkey == revokeable_p2wsh) .map(|(idx, _)| idx) } @@ -1982,35 +2278,25 @@ impl<'a> TrustedCommitmentTransaction<'a> { /// The built transaction will allow fee bumping with RBF, and this method takes /// `feerate_per_kw` as an input such that multiple copies of a justice transaction at different /// fee rates may be built. - pub fn build_to_local_justice_tx(&self, feerate_per_kw: u64, destination_script: ScriptBuf) - -> Result { + pub fn build_to_local_justice_tx( + &self, feerate_per_kw: u64, destination_script: ScriptBuf, + ) -> Result { let output_idx = self.revokeable_output_index().ok_or(())?; let input = vec![TxIn { - previous_output: OutPoint { - txid: self.trust().txid(), - vout: output_idx as u32, - }, + previous_output: OutPoint { txid: self.trust().txid(), vout: output_idx as u32 }, script_sig: ScriptBuf::new(), sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, witness: Witness::new(), }]; let value = self.inner.built.transaction.output[output_idx].value; - let output = vec![TxOut { - script_pubkey: destination_script, - value, - }]; - let mut justice_tx = Transaction { - version: Version::TWO, - lock_time: LockTime::ZERO, - input, - output, - }; + let output = vec![TxOut { script_pubkey: destination_script, value }]; + let mut justice_tx = + Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input, output }; let weight = justice_tx.weight().to_wu() + WEIGHT_REVOKED_OUTPUT; let fee = Amount::from_sat(fee_for_weight(feerate_per_kw as u32, weight)); justice_tx.output[0].value = value.checked_sub(fee).ok_or(())?; Ok(justice_tx) } - } /// Commitment transaction numbers which appear in the transactions themselves are XOR'd with a @@ -2020,8 +2306,7 @@ impl<'a> TrustedCommitmentTransaction<'a> { /// This function gets the shared secret from relevant channel public keys and can be used to /// "decrypt" the commitment transaction number given a commitment transaction on-chain. pub fn get_commitment_transaction_number_obscure_factor( - broadcaster_payment_basepoint: &PublicKey, - countersignatory_payment_basepoint: &PublicKey, + broadcaster_payment_basepoint: &PublicKey, countersignatory_payment_basepoint: &PublicKey, outbound_from_broadcaster: bool, ) -> u64 { let mut sha = Sha256::engine(); @@ -2045,18 +2330,23 @@ pub fn get_commitment_transaction_number_obscure_factor( #[cfg(test)] mod tests { - use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys}; + use super::{ChannelPublicKeys, CounterpartyCommitmentSecrets}; use crate::chain; - use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersigner_keyed_anchor_redeemscript, CommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment, TrustedCommitmentTransaction, BuiltCommitmentTransaction}; - use bitcoin::secp256k1::{self, PublicKey, SecretKey, Secp256k1}; - use crate::util::test_utils; + use crate::ln::chan_utils::{ + get_htlc_redeemscript, get_to_countersigner_keyed_anchor_redeemscript, + BuiltCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, + CounterpartyChannelTransactionParameters, HTLCOutputInCommitment, + TrustedCommitmentTransaction, + }; use crate::sign::{ChannelSigner, SignerProvider}; - use bitcoin::{Network, Txid, ScriptBuf, CompressedPublicKey}; + use crate::types::features::ChannelTypeFeatures; + use crate::types::payment::PaymentHash; + use crate::util::test_utils; use bitcoin::hashes::Hash; use bitcoin::hex::FromHex; - use crate::types::payment::PaymentHash; + use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; use bitcoin::PublicKey as BitcoinPublicKey; - use crate::types::features::ChannelTypeFeatures; + use bitcoin::{CompressedPublicKey, Network, ScriptBuf, Txid}; #[allow(unused_imports)] use crate::prelude::*; @@ -2067,7 +2357,7 @@ mod tests { feerate_per_kw: u32, channel_parameters: ChannelTransactionParameters, counterparty_pubkeys: ChannelPublicKeys, - secp_ctx: Secp256k1::, + secp_ctx: Secp256k1, } impl TestCommitmentTxBuilder { @@ -2076,18 +2366,33 @@ mod tests { let seed = [42; 32]; let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); - let signer = keys_provider.derive_channel_signer(keys_provider.generate_channel_keys_id(false, 0)); - let counterparty_signer = keys_provider.derive_channel_signer(keys_provider.generate_channel_keys_id(true, 1)); - let per_commitment_secret = SecretKey::from_slice(&>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); - let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); + let signer = keys_provider + .derive_channel_signer(keys_provider.generate_channel_keys_id(false, 0)); + let counterparty_signer = keys_provider + .derive_channel_signer(keys_provider.generate_channel_keys_id(true, 1)); + let per_commitment_secret = SecretKey::from_slice( + &>::from_hex( + "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", + ) + .unwrap()[..], + ) + .unwrap(); + let per_commitment_point = + PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); let holder_pubkeys = signer.pubkeys(None, &secp_ctx); let counterparty_pubkeys = counterparty_signer.pubkeys(None, &secp_ctx).clone(); let channel_parameters = ChannelTransactionParameters { holder_pubkeys: holder_pubkeys.clone(), holder_selected_contest_delay: 0, is_outbound_from_holder: false, - counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: counterparty_pubkeys.clone(), selected_contest_delay: 0 }), - funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }), + counterparty_parameters: Some(CounterpartyChannelTransactionParameters { + pubkeys: counterparty_pubkeys.clone(), + selected_contest_delay: 0, + }), + funding_outpoint: Some(chain::transaction::OutPoint { + txid: Txid::all_zeros(), + index: 0, + }), splice_parent_funding_txid: None, channel_type_features: ChannelTypeFeatures::only_static_remote_key(), channel_value_satoshis: 3000, @@ -2103,14 +2408,25 @@ mod tests { } } - fn build(&self, to_broadcaster_sats: u64, to_countersignatory_sats: u64, nondust_htlcs: Vec) -> CommitmentTransaction { + fn build( + &self, to_broadcaster_sats: u64, to_countersignatory_sats: u64, + nondust_htlcs: Vec, + ) -> CommitmentTransaction { CommitmentTransaction::new( - self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw, - nondust_htlcs, &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx + self.commitment_number, + &self.per_commitment_point, + to_broadcaster_sats, + to_countersignatory_sats, + self.feerate_per_kw, + nondust_htlcs, + &self.channel_parameters.as_holder_broadcastable(), + &self.secp_ctx, ) } - fn verify<'a>(&self, tx: &'a CommitmentTransaction) -> Result, ()> { + fn verify<'a>( + &self, tx: &'a CommitmentTransaction, + ) -> Result, ()> { tx.verify(&self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx) } } @@ -2122,13 +2438,27 @@ mod tests { // Generate broadcaster and counterparty outputs let tx = builder.build(1000, 2000, Vec::new()); assert_eq!(tx.built.transaction.output.len(), 2); - assert_eq!(tx.built.transaction.output[1].script_pubkey, bitcoin::address::Address::p2wpkh(&CompressedPublicKey(builder.counterparty_pubkeys.payment_point), Network::Testnet).script_pubkey()); + assert_eq!( + tx.built.transaction.output[1].script_pubkey, + bitcoin::address::Address::p2wpkh( + &CompressedPublicKey(builder.counterparty_pubkeys.payment_point), + Network::Testnet + ) + .script_pubkey() + ); // Generate broadcaster and counterparty outputs as well as two anchors - builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + builder.channel_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); let tx = builder.build(1000, 2000, Vec::new()); assert_eq!(tx.built.transaction.output.len(), 4); - assert_eq!(tx.built.transaction.output[3].script_pubkey, get_to_countersigner_keyed_anchor_redeemscript(&builder.counterparty_pubkeys.payment_point).to_p2wsh()); + assert_eq!( + tx.built.transaction.output[3].script_pubkey, + get_to_countersigner_keyed_anchor_redeemscript( + &builder.counterparty_pubkeys.payment_point + ) + .to_p2wsh() + ); // Generate broadcaster output and anchor let tx = builder.build(3000, 0, Vec::new()); @@ -2155,27 +2485,93 @@ mod tests { }; // Generate broadcaster output and received and offered HTLC outputs, w/o anchors - builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key(); + builder.channel_parameters.channel_type_features = + ChannelTypeFeatures::only_static_remote_key(); let tx = builder.build(3000, 0, vec![received_htlc.clone(), offered_htlc.clone()]); let keys = tx.trust().keys(); assert_eq!(tx.built.transaction.output.len(), 3); - assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh()); - assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh()); - assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh().to_hex_string(), - "0020e43a7c068553003fe68fcae424fb7b28ec5ce48cd8b6744b3945631389bad2fb"); - assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh().to_hex_string(), - "0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d"); + assert_eq!( + tx.built.transaction.output[0].script_pubkey, + get_htlc_redeemscript( + &received_htlc, + &ChannelTypeFeatures::only_static_remote_key(), + &keys + ) + .to_p2wsh() + ); + assert_eq!( + tx.built.transaction.output[1].script_pubkey, + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::only_static_remote_key(), + &keys + ) + .to_p2wsh() + ); + assert_eq!( + get_htlc_redeemscript( + &received_htlc, + &ChannelTypeFeatures::only_static_remote_key(), + &keys + ) + .to_p2wsh() + .to_hex_string(), + "0020e43a7c068553003fe68fcae424fb7b28ec5ce48cd8b6744b3945631389bad2fb" + ); + assert_eq!( + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::only_static_remote_key(), + &keys + ) + .to_p2wsh() + .to_hex_string(), + "0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d" + ); // Generate broadcaster output and received and offered HTLC outputs, with anchors - builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + builder.channel_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); let tx = builder.build(3000, 0, vec![received_htlc.clone(), offered_htlc.clone()]); assert_eq!(tx.built.transaction.output.len(), 5); - assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh()); - assert_eq!(tx.built.transaction.output[3].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh()); - assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh().to_hex_string(), - "0020b70d0649c72b38756885c7a30908d912a7898dd5d79457a7280b8e9a20f3f2bc"); - assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh().to_hex_string(), - "002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7"); + assert_eq!( + tx.built.transaction.output[2].script_pubkey, + get_htlc_redeemscript( + &received_htlc, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + &keys + ) + .to_p2wsh() + ); + assert_eq!( + tx.built.transaction.output[3].script_pubkey, + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + &keys + ) + .to_p2wsh() + ); + assert_eq!( + get_htlc_redeemscript( + &received_htlc, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + &keys + ) + .to_p2wsh() + .to_hex_string(), + "0020b70d0649c72b38756885c7a30908d912a7898dd5d79457a7280b8e9a20f3f2bc" + ); + assert_eq!( + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + &keys + ) + .to_p2wsh() + .to_hex_string(), + "002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7" + ); } #[test] @@ -2216,16 +2612,26 @@ mod tests { // Generate a random public key for destination script let secret_key = SecretKey::from_slice( - &>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100") - .unwrap()[..]).unwrap(); - let pubkey_hash = BitcoinPublicKey::new( - PublicKey::from_secret_key(&Secp256k1::new(), &secret_key)).wpubkey_hash().unwrap(); + &>::from_hex( + "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", + ) + .unwrap()[..], + ) + .unwrap(); + let pubkey_hash = + BitcoinPublicKey::new(PublicKey::from_secret_key(&Secp256k1::new(), &secret_key)) + .wpubkey_hash() + .unwrap(); let destination_script = ScriptBuf::new_p2wpkh(&pubkey_hash); - let justice_tx = tx.trust().build_to_local_justice_tx(253, destination_script.clone()).unwrap(); + let justice_tx = + tx.trust().build_to_local_justice_tx(253, destination_script.clone()).unwrap(); assert_eq!(justice_tx.input.len(), 1); assert_eq!(justice_tx.input[0].previous_output.txid, tx.built.transaction.compute_txid()); - assert_eq!(justice_tx.input[0].previous_output.vout, tx.trust().revokeable_output_index().unwrap() as u32); + assert_eq!( + justice_tx.input[0].previous_output.vout, + tx.trust().revokeable_output_index().unwrap() as u32 + ); assert!(justice_tx.input[0].sequence.is_rbf()); assert_eq!(justice_tx.output.len(), 1); @@ -2257,42 +2663,82 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd", + ) + .unwrap(), + ); monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2", + ) + .unwrap(), + ); monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32", + ) + .unwrap(), + ); monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17", + ) + .unwrap(), + ); monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); } @@ -2303,13 +2749,25 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); - assert!(monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710654, secrets.last().unwrap().clone()) + .is_err()); } { @@ -2318,23 +2776,45 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); - assert!(monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710652, secrets.last().unwrap().clone()) + .is_err()); } { @@ -2343,23 +2823,45 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); - assert!(monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710652, secrets.last().unwrap().clone()) + .is_err()); } { @@ -2368,43 +2870,85 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4", + ) + .unwrap(), + ); monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd", + ) + .unwrap(), + ); monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2", + ) + .unwrap(), + ); monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32", + ) + .unwrap(), + ); monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); - assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710648, secrets.last().unwrap().clone()) + .is_err()); } { @@ -2413,33 +2957,65 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6", + ) + .unwrap(), + ); monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); - assert!(monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710650, secrets.last().unwrap().clone()) + .is_err()); } { @@ -2448,43 +3024,85 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6", + ) + .unwrap(), + ); monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("b7e76a83668bde38b373970155c868a653304308f9896692f904a23731224bb1").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "b7e76a83668bde38b373970155c868a653304308f9896692f904a23731224bb1", + ) + .unwrap(), + ); monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32", + ) + .unwrap(), + ); monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); - assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710648, secrets.last().unwrap().clone()) + .is_err()); } { @@ -2493,43 +3111,85 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd", + ) + .unwrap(), + ); monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2", + ) + .unwrap(), + ); monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("e7971de736e01da8ed58b94c2fc216cb1dca9e326f3a96e7194fe8ea8af6c0a3").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "e7971de736e01da8ed58b94c2fc216cb1dca9e326f3a96e7194fe8ea8af6c0a3", + ) + .unwrap(), + ); monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); - assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710648, secrets.last().unwrap().clone()) + .is_err()); } { @@ -2538,43 +3198,85 @@ mod tests { secrets.clear(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc", + ) + .unwrap(), + ); monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964", + ) + .unwrap(), + ); monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8", + ) + .unwrap(), + ); monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116", + ) + .unwrap(), + ); monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd", + ) + .unwrap(), + ); monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2", + ) + .unwrap(), + ); monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32", + ) + .unwrap(), + ); monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); test_secrets!(); secrets.push([0; 32]); - secrets.last_mut().unwrap()[0..32].clone_from_slice(&>::from_hex("a7efbc61aac46d34f77778bac22c8a20c6a46ca460addc49009bda875ec88fa4").unwrap()); - assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + secrets.last_mut().unwrap()[0..32].clone_from_slice( + &>::from_hex( + "a7efbc61aac46d34f77778bac22c8a20c6a46ca460addc49009bda875ec88fa4", + ) + .unwrap(), + ); + assert!(monitor + .provide_secret(281474976710648, secrets.last().unwrap().clone()) + .is_err()); } } @@ -2602,16 +3304,13 @@ mod tests { assert_eq!(transaction.output.len(), 2); transaction.output.swap(0, 1); let txid = transaction.compute_txid(); - let built = BuiltCommitmentTransaction { - transaction, - txid, - }; + let built = BuiltCommitmentTransaction { transaction, txid }; commit_tx.built = built; // Yes the HTLCs in `nondust_htlcs` are in the same order as in the cached transaction, // but they are not sorted! assert!(builder.verify(&commit_tx).is_err()); - } + }; } // script_pubkey: Script(OP_0 OP_PUSHBYTES_32 1b202f6bdf42cd8ba08e263868b5bd0cf5a7f95c227c27e1935984a8f6130fa3) diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs index 1192a14e2b9..d0d03bcbcbd 100644 --- a/lightning/src/ln/chanmon_update_fail_tests.rs +++ b/lightning/src/ln/chanmon_update_fail_tests.rs @@ -12,29 +12,31 @@ //! There are a bunch of these as their handling is relatively error-prone so they are split out //! here. See also the chanmon_fail_consistency fuzz test. -use bitcoin::constants::genesis_block; -use bitcoin::hash_types::BlockHash; -use bitcoin::network::Network; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor}; +use crate::chain::channelmonitor::{ChannelMonitor, ANTI_REORG_DELAY}; use crate::chain::{ChannelMonitorUpdateStatus, Listen, Watch}; -use crate::events::{Event, PaymentPurpose, ClosureReason, HTLCDestination}; -use crate::ln::channelmanager::{PaymentId, RAACommitmentOrder, RecipientOnionFields}; +use crate::events::{ClosureReason, Event, HTLCDestination, PaymentPurpose}; use crate::ln::channel::AnnouncementSigsState; +use crate::ln::channelmanager::{PaymentId, RAACommitmentOrder, RecipientOnionFields}; use crate::ln::msgs; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, MessageSendEvent, RoutingMessageHandler, +}; use crate::ln::types::ChannelId; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, RoutingMessageHandler, MessageSendEvent}; -use crate::util::test_channel_signer::TestChannelSigner; use crate::util::ser::{ReadableArgs, Writeable}; +use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_utils::TestBroadcaster; +use bitcoin::constants::genesis_block; +use bitcoin::hash_types::BlockHash; +use bitcoin::network::Network; use crate::ln::functional_test_utils::*; use crate::util::test_utils; use crate::io; -use bitcoin::hashes::Hash; use crate::prelude::*; use crate::sync::{Arc, Mutex}; +use bitcoin::hashes::Hash; #[test] fn test_monitor_and_persister_update_fail() { @@ -50,7 +52,7 @@ fn test_monitor_and_persister_update_fail() { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); // Rebalance the network to generate htlc in the two directions - send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 10_000_000); // Route an HTLC from node 0 to node 1 (but don't settle) let (preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 9_000_000); @@ -73,15 +75,31 @@ fn test_monitor_and_persister_update_fail() { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(chan.2).unwrap(); let new_monitor = <(BlockHash, ChannelMonitor)>::read( - &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; + &mut io::Cursor::new(&monitor.encode()), + (nodes[0].keys_manager, nodes[0].keys_manager), + ) + .unwrap() + .1; assert!(new_monitor == *monitor); new_monitor }; - let chain_mon = test_utils::TestChainMonitor::new(Some(&chain_source), &tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister, &node_cfgs[0].keys_manager); - assert_eq!(chain_mon.watch_channel(chan.2, new_monitor), Ok(ChannelMonitorUpdateStatus::Completed)); + let chain_mon = test_utils::TestChainMonitor::new( + Some(&chain_source), + &tx_broadcaster, + &logger, + &chanmon_cfgs[0].fee_estimator, + &persister, + &node_cfgs[0].keys_manager, + ); + assert_eq!( + chain_mon.watch_channel(chan.2, new_monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); chain_mon }; - chain_mon.chain_monitor.block_connected(&create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()), 200); + chain_mon + .chain_monitor + .block_connected(&create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()), 200); // Try to update ChannelMonitor nodes[1].node.claim_funds(preimage); @@ -90,24 +108,51 @@ fn test_monitor_and_persister_update_fail() { let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - if let Some(channel) = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2).as_funded_mut() { + if let Some(channel) = get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan.2 + ) + .as_funded_mut() + { assert_eq!(updates.commitment_signed.len(), 1); - if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed[0], &node_cfgs[0].logger) { + if let Ok(Some(update)) = + channel.commitment_signed(&updates.commitment_signed[0], &node_cfgs[0].logger) + { // Check that the persister returns InProgress (and will never actually complete) // as the monitor update errors. - if let ChannelMonitorUpdateStatus::InProgress = chain_mon.chain_monitor.update_channel(chan.2, &update) {} else { panic!("Expected monitor paused"); } - logger.assert_log_regex("lightning::chain::chainmonitor", regex::Regex::new("Failed to update ChannelMonitor for channel [0-9a-f]*.").unwrap(), 1); + if let ChannelMonitorUpdateStatus::InProgress = + chain_mon.chain_monitor.update_channel(chan.2, &update) + { + } else { + panic!("Expected monitor paused"); + } + logger.assert_log_regex( + "lightning::chain::chainmonitor", + regex::Regex::new("Failed to update ChannelMonitor for channel [0-9a-f]*.") + .unwrap(), + 1, + ); // Apply the monitor update to the original ChainMonitor, ensuring the // ChannelManager and ChannelMonitor aren't out of sync. - assert_eq!(nodes[0].chain_monitor.update_channel(chan.2, &update), - ChannelMonitorUpdateStatus::Completed); - } else { assert!(false); } + assert_eq!( + nodes[0].chain_monitor.update_channel(chan.2, &update), + ChannelMonitorUpdateStatus::Completed + ); + } else { + assert!(false); + } } else { assert!(false); } @@ -126,14 +171,21 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(&nodes[0], nodes[1], 1000000); + let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(&nodes[0], nodes[1], 1000000); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); { - nodes[0].node.send_payment_with_route(route, payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0) - ).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -150,7 +202,14 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { } chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[0], 0); @@ -166,17 +225,26 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { let events_3 = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events_3.len(), 1); match events_3[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + .. + } => { assert_eq!(payment_hash_1, *payment_hash); assert_eq!(amount_msat, 1_000_000); assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id()); assert_eq!(via_channel_id, Some(channel_id)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_1, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -185,12 +253,19 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1); // Now set it to failed again... - let (route, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(&nodes[0], nodes[1], 1000000); + let (route, payment_hash_2, _, payment_secret_2) = + get_route_and_payment_hash!(&nodes[0], nodes[1], 1000000); { chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0) - ).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -206,7 +281,14 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { // ...and make sure we can force-close a frozen channel let error_message = "Channel force-closed"; - nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &channel_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); @@ -214,7 +296,13 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { // PaymentPathFailed event assert_eq!(nodes[0].node.list_channels().len(), 0); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -249,15 +337,23 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); // Now try to send a second payment which will fail to send - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0) - ).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -274,7 +370,19 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events_2.len(), 1); let (bs_initial_fulfill, bs_initial_commitment_signed) = match events_2[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); assert!(update_add_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); @@ -283,7 +391,10 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { assert!(update_fee.is_none()); if (disconnect_count & 16) == 0 { - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &update_fulfill_htlcs[0], + ); let events_3 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_3.len(), 1); match events_3[0] { @@ -294,7 +405,10 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { _ => panic!("Unexpected event"), } - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + commitment_signed, + ); check_added_monitors!(nodes[0], 1); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -311,55 +425,108 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { // Now fix monitor updating... chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[0], 0); - macro_rules! disconnect_reconnect_peers { () => { { - nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); - nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); - assert_eq!(reestablish_1.len(), 1); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); - let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); - assert_eq!(reestablish_2.len(), 1); - - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); - let as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]); - nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); - let bs_resp = handle_chan_reestablish_msgs!(nodes[1], nodes[0]); - - assert!(as_resp.0.is_none()); - assert!(bs_resp.0.is_none()); - - (reestablish_1, reestablish_2, as_resp, bs_resp) - } } } + macro_rules! disconnect_reconnect_peers { + () => {{ + nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); + nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); + + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); + assert_eq!(reestablish_1.len(), 1); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); + let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); + assert_eq!(reestablish_2.len(), 1); + + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); + let as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]); + nodes[1] + .node + .handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); + let bs_resp = handle_chan_reestablish_msgs!(nodes[1], nodes[0]); + + assert!(as_resp.0.is_none()); + assert!(bs_resp.0.is_none()); + + (reestablish_1, reestablish_2, as_resp, bs_resp) + }}; + } let (payment_event, initial_revoke_and_ack) = if disconnect_count & !disconnect_flags > 0 { assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); assert_eq!(reestablish_1.len(), 1); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); assert_eq!(reestablish_2.len(), 1); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); check_added_monitors!(nodes[0], 0); let mut as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]); - nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); + nodes[1] + .node + .handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); check_added_monitors!(nodes[1], 0); let mut bs_resp = handle_chan_reestablish_msgs!(nodes[1], nodes[0]); @@ -383,7 +550,10 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { assert!(as_resp.1.is_none()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_resp.2.as_ref().unwrap().update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_resp.2.as_ref().unwrap().update_fulfill_htlcs[0], + ); let events_3 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_3.len(), 1); match events_3[0] { @@ -394,8 +564,15 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { _ => panic!("Unexpected event"), } - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_resp.2.as_ref().unwrap().commitment_signed); - let as_resp_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_resp.2.as_ref().unwrap().commitment_signed, + ); + let as_resp_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); @@ -404,7 +581,8 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { } if disconnect_count & !disconnect_flags > 1 { - let (second_reestablish_1, second_reestablish_2, second_as_resp, second_bs_resp) = disconnect_reconnect_peers!(); + let (second_reestablish_1, second_reestablish_2, second_as_resp, second_bs_resp) = + disconnect_reconnect_peers!(); if (disconnect_count & 16) == 0 { assert!(reestablish_1 == second_reestablish_1); @@ -414,24 +592,41 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { assert!(bs_resp == second_bs_resp); } - (SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), channel_id, as_resp.2.unwrap()), as_resp.1.unwrap()) + ( + SendEvent::from_commitment_update( + nodes[1].node.get_our_node_id(), + channel_id, + as_resp.2.unwrap(), + ), + as_resp.1.unwrap(), + ) } else { let mut events_4 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_4.len(), 2); - (SendEvent::from_event(events_4.remove(0)), match events_4[0] { - MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - assert_eq!(*node_id, nodes[1].node.get_our_node_id()); - msg.clone() + ( + SendEvent::from_event(events_4.remove(0)), + match events_4[0] { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, nodes[1].node.get_our_node_id()); + msg.clone() + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }) + ) }; assert_eq!(payment_event.node_id, nodes[1].node.get_our_node_id()); 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); - let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); + let bs_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // nodes[1] is awaiting an RAA from nodes[0] still so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[1], 1); @@ -448,27 +643,36 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let as_commitment_update; let bs_second_commitment_update; - macro_rules! handle_bs_raa { () => { - nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_revoke_and_ack); - as_commitment_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - assert!(as_commitment_update.update_add_htlcs.is_empty()); - assert!(as_commitment_update.update_fulfill_htlcs.is_empty()); - assert!(as_commitment_update.update_fail_htlcs.is_empty()); - assert!(as_commitment_update.update_fail_malformed_htlcs.is_empty()); - assert!(as_commitment_update.update_fee.is_none()); - check_added_monitors!(nodes[0], 1); - } } - - macro_rules! handle_initial_raa { () => { - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &initial_revoke_and_ack); - bs_second_commitment_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - assert!(bs_second_commitment_update.update_add_htlcs.is_empty()); - assert!(bs_second_commitment_update.update_fulfill_htlcs.is_empty()); - assert!(bs_second_commitment_update.update_fail_htlcs.is_empty()); - assert!(bs_second_commitment_update.update_fail_malformed_htlcs.is_empty()); - assert!(bs_second_commitment_update.update_fee.is_none()); - check_added_monitors!(nodes[1], 1); - } } + macro_rules! handle_bs_raa { + () => { + nodes[0] + .node + .handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_revoke_and_ack); + as_commitment_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + assert!(as_commitment_update.update_add_htlcs.is_empty()); + assert!(as_commitment_update.update_fulfill_htlcs.is_empty()); + assert!(as_commitment_update.update_fail_htlcs.is_empty()); + assert!(as_commitment_update.update_fail_malformed_htlcs.is_empty()); + assert!(as_commitment_update.update_fee.is_none()); + check_added_monitors!(nodes[0], 1); + }; + } + + macro_rules! handle_initial_raa { + () => { + nodes[1] + .node + .handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &initial_revoke_and_ack); + bs_second_commitment_update = + get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + assert!(bs_second_commitment_update.update_add_htlcs.is_empty()); + assert!(bs_second_commitment_update.update_fulfill_htlcs.is_empty()); + assert!(bs_second_commitment_update.update_fail_htlcs.is_empty()); + assert!(bs_second_commitment_update.update_fail_malformed_htlcs.is_empty()); + assert!(bs_second_commitment_update.update_fee.is_none()); + check_added_monitors!(nodes[1], 1); + }; + } if (disconnect_count & 8) == 0 { handle_bs_raa!(); @@ -524,13 +728,27 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { } } - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_commitment_update.commitment_signed); - let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_second_commitment_update.commitment_signed, + ); + let as_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_commitment_update.commitment_signed); - let bs_second_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_commitment_update.commitment_signed, + ); + let bs_second_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[1], 1); @@ -548,17 +766,26 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let events_5 = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events_5.len(), 1); match events_5[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + .. + } => { assert_eq!(payment_hash_2, *payment_hash); assert_eq!(amount_msat, 1_000_000); assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id()); assert_eq!(via_channel_id, Some(channel_id)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_2, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -603,24 +830,43 @@ fn test_monitor_update_fail_cs() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (route, our_payment_hash, payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, our_payment_hash, payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } - let send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); + let send_event = + SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event.msgs[0]); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &send_event.commitment_msg); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &send_event.commitment_msg, + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[1], 0); let responses = nodes[1].node.get_and_clear_pending_msg_events(); @@ -644,7 +890,10 @@ fn test_monitor_update_fail_cs() { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &updates.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &updates.commitment_signed, + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -653,11 +902,22 @@ fn test_monitor_update_fail_cs() { } chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[0], 0); - let final_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let final_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &final_raa); check_added_monitors!(nodes[1], 1); @@ -666,17 +926,26 @@ fn test_monitor_update_fail_cs() { let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentClaimable { payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { + Event::PaymentClaimable { + payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + .. + } => { assert_eq!(payment_hash, our_payment_hash); assert_eq!(amount_msat, 1_000_000); assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id()); assert_eq!(via_channel_id, Some(channel_id)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(our_payment_secret, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -696,16 +965,33 @@ fn test_monitor_update_fail_no_rebroadcast() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (route, our_payment_hash, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, our_payment_hash, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } - let send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); + let send_event = + SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event.msgs[0]); - let bs_raa = commitment_signed_dance!(nodes[1], nodes[0], send_event.commitment_msg, false, true, false, true); + let bs_raa = commitment_signed_dance!( + nodes[1], + nodes[0], + send_event.commitment_msg, + false, + true, + false, + true + ); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &bs_raa); @@ -715,7 +1001,14 @@ fn test_monitor_update_fail_no_rebroadcast() { check_added_monitors!(nodes[1], 1); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 0); @@ -744,31 +1037,59 @@ fn test_monitor_update_raa_while_paused() { let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; send_payment(&nodes[0], &[&nodes[1]], 5000000); - let (route, our_payment_hash_1, payment_preimage_1, our_payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, our_payment_hash_1, payment_preimage_1, our_payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, our_payment_hash_1, - RecipientOnionFields::secret_only(our_payment_secret_1), PaymentId(our_payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash_1, + RecipientOnionFields::secret_only(our_payment_secret_1), + PaymentId(our_payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } - let send_event_1 = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); + let send_event_1 = + SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); - let (route, our_payment_hash_2, payment_preimage_2, our_payment_secret_2) = get_route_and_payment_hash!(nodes[1], nodes[0], 1000000); + let (route, our_payment_hash_2, payment_preimage_2, our_payment_secret_2) = + get_route_and_payment_hash!(nodes[1], nodes[0], 1000000); { - nodes[1].node.send_payment_with_route(route, our_payment_hash_2, - RecipientOnionFields::secret_only(our_payment_secret_2), PaymentId(our_payment_hash_2.0)).unwrap(); + nodes[1] + .node + .send_payment_with_route( + route, + our_payment_hash_2, + RecipientOnionFields::secret_only(our_payment_secret_2), + PaymentId(our_payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); } - let send_event_2 = SendEvent::from_event(nodes[1].node.get_and_clear_pending_msg_events().remove(0)); + let send_event_2 = + SendEvent::from_event(nodes[1].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event_1.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &send_event_1.commitment_msg); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &send_event_1.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &send_event_2.msgs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &send_event_2.commitment_msg); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &send_event_2.commitment_msg, + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -777,7 +1098,14 @@ fn test_monitor_update_raa_while_paused() { assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[0], 0); @@ -786,13 +1114,26 @@ fn test_monitor_update_raa_while_paused() { check_added_monitors!(nodes[1], 1); let bs_cs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_update_raa.1); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_update_raa.1); check_added_monitors!(nodes[1], 1); - let bs_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_second_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_cs.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_cs.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_second_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_second_raa); check_added_monitors!(nodes[0], 1); @@ -825,7 +1166,10 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { // Fail the payment backwards, failing the monitor update on nodes[1]'s receipt of the RAA nodes[2].node.fail_htlc_backwards(&payment_hash_1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_1 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_1 }] + ); check_added_monitors!(nodes[2], 1); let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); @@ -834,21 +1178,40 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); - - let bs_revoke_and_ack = commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true, false, true); + nodes[1] + .node + .handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + + let bs_revoke_and_ack = commitment_signed_dance!( + nodes[1], + nodes[2], + updates.commitment_signed, + false, + true, + false, + true + ); check_added_monitors!(nodes[0], 0); // While the second channel is AwaitingRAA, forward a second payment to get it into the // holding cell. - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], 1000000); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[2], 1000000); { - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } - let mut send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); + let mut send_event = + SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], send_event.commitment_msg, false); @@ -866,10 +1229,18 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { // Forward a third payment which will also be added to the holding cell, despite the channel // being paused waiting a monitor update. - let (route, payment_hash_3, _, payment_secret_3) = get_route_and_payment_hash!(nodes[0], nodes[2], 1000000); + let (route, payment_hash_3, _, payment_secret_3) = + get_route_and_payment_hash!(nodes[0], nodes[2], 1000000); { - nodes[0].node.send_payment_with_route(route, payment_hash_3, - RecipientOnionFields::secret_only(payment_secret_3), PaymentId(payment_hash_3.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_3, + RecipientOnionFields::secret_only(payment_secret_3), + PaymentId(payment_hash_3.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -887,26 +1258,53 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { let (payment_preimage_4, payment_hash_4) = if test_ignore_second_cs { // Try to route another payment backwards from 2 to make sure 1 holds off on responding - let (route, payment_hash_4, payment_preimage_4, payment_secret_4) = get_route_and_payment_hash!(nodes[2], nodes[0], 1000000); - nodes[2].node.send_payment_with_route(route, payment_hash_4, - RecipientOnionFields::secret_only(payment_secret_4), PaymentId(payment_hash_4.0)).unwrap(); + let (route, payment_hash_4, payment_preimage_4, payment_secret_4) = + get_route_and_payment_hash!(nodes[2], nodes[0], 1000000); + nodes[2] + .node + .send_payment_with_route( + route, + payment_hash_4, + RecipientOnionFields::secret_only(payment_secret_4), + PaymentId(payment_hash_4.0), + ) + .unwrap(); check_added_monitors!(nodes[2], 1); - send_event = SendEvent::from_event(nodes[2].node.get_and_clear_pending_msg_events().remove(0)); + send_event = + SendEvent::from_event(nodes[2].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(nodes[2].node.get_our_node_id(), &send_event.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &send_event.commitment_msg); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &send_event.commitment_msg, + ); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); (Some(payment_preimage_4), Some(payment_hash_4)) - } else { (None, None) }; + } else { + (None, None) + }; // Restore monitor updating, ensuring we immediately get a fail-back update and a // update_add update. chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2.2).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_2.2) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_2.2, latest_update); check_added_monitors!(nodes[1], 0); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); check_added_monitors!(nodes[1], 1); let mut events_3 = nodes[1].node.get_and_clear_pending_msg_events(); @@ -918,7 +1316,8 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { // Note that the ordering of the events for different nodes is non-prescriptive, though the // ordering of the two events that both go to nodes[2] have to stay in the same order. - let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events_3); + let nodes_0_event = + remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events_3); let messages_a = match nodes_0_event { MessageSendEvent::UpdateHTLCs { node_id, mut updates, channel_id: _ } => { assert_eq!(node_id, nodes[0].node.get_our_node_id()); @@ -932,12 +1331,14 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { _ => panic!("Unexpected event type!"), }; - let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events_3); + let nodes_2_event = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events_3); let send_event_b = SendEvent::from_event(nodes_2_event); assert_eq!(send_event_b.node_id, nodes[2].node.get_our_node_id()); let raa = if test_ignore_second_cs { - let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events_3); + let nodes_2_event = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events_3); match nodes_2_event { MessageSendEvent::SendRevokeAndACK { node_id, msg } => { assert_eq!(node_id, nodes[2].node.get_our_node_id()); @@ -945,7 +1346,9 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { }, _ => panic!("Unexpected event"), } - } else { None }; + } else { + None + }; // Now deliver the new messages... @@ -956,9 +1359,16 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &send_event_b.msgs[0]); let as_cs; if test_ignore_second_cs { - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &send_event_b.commitment_msg); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &send_event_b.commitment_msg, + ); check_added_monitors!(nodes[2], 1); - let bs_revoke_and_ack = get_event_msg!(nodes[2], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let bs_revoke_and_ack = get_event_msg!( + nodes[2], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &raa.unwrap()); check_added_monitors!(nodes[2], 1); let bs_cs = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); @@ -972,10 +1382,16 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { check_added_monitors!(nodes[1], 1); as_cs = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &bs_cs.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &bs_cs.commitment_signed, + ); check_added_monitors!(nodes[1], 1); } else { - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &send_event_b.commitment_msg); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &send_event_b.commitment_msg, + ); check_added_monitors!(nodes[2], 1); let bs_revoke_and_commit = nodes[2].node.get_and_clear_pending_msg_events(); @@ -1000,7 +1416,10 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fulfill_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); }, _ => panic!("Unexpected event"), @@ -1012,13 +1431,25 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { assert!(as_cs.update_fail_malformed_htlcs.is_empty()); assert!(as_cs.update_fulfill_htlcs.is_empty()); assert!(as_cs.update_fee.is_none()); - let as_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id()); - + let as_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[2].node.get_our_node_id() + ); - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &as_cs.update_add_htlcs[0]); - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &as_cs.commitment_signed); + nodes[2] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &as_cs.update_add_htlcs[0]); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &as_cs.commitment_signed, + ); check_added_monitors!(nodes[2], 1); - let bs_second_raa = get_event_msg!(nodes[2], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let bs_second_raa = get_event_msg!( + nodes[2], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[2], 1); @@ -1028,9 +1459,16 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &bs_second_cs.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &bs_second_cs.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let as_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id()); + let as_second_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[2].node.get_our_node_id() + ); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &as_second_raa); check_added_monitors!(nodes[2], 1); @@ -1041,11 +1479,15 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { let events_6 = nodes[2].node.get_and_clear_pending_events(); assert_eq!(events_6.len(), 2); match events_6[0] { - Event::PaymentClaimable { payment_hash, .. } => { assert_eq!(payment_hash, payment_hash_2); }, + Event::PaymentClaimable { payment_hash, .. } => { + assert_eq!(payment_hash, payment_hash_2); + }, _ => panic!("Unexpected event"), }; match events_6[1] { - Event::PaymentClaimable { payment_hash, .. } => { assert_eq!(payment_hash, payment_hash_3); }, + Event::PaymentClaimable { payment_hash, .. } => { + assert_eq!(payment_hash, payment_hash_3); + }, _ => panic!("Unexpected event"), }; @@ -1064,7 +1506,9 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { let events_9 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_9.len(), 1); match events_9[0] { - Event::PaymentClaimable { payment_hash, .. } => assert_eq!(payment_hash, payment_hash_4.unwrap()), + Event::PaymentClaimable { payment_hash, .. } => { + assert_eq!(payment_hash, payment_hash_4.unwrap()) + }, _ => panic!("Unexpected event"), }; claim_payment(&nodes[2], &[&nodes[1], &nodes[0]], payment_preimage_4.unwrap()); @@ -1091,7 +1535,8 @@ fn test_monitor_update_fail_reestablish() { let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); create_announced_chan_between_nodes(&nodes, 1, 2); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); @@ -1106,19 +1551,40 @@ fn test_monitor_update_fail_reestablish() { assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); @@ -1127,8 +1593,16 @@ fn test_monitor_update_fail_reestablish() { nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &as_reestablish); assert_eq!( - get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()) - .contents.channel_flags & 2, 0); // The "disabled" bit should be unset as we just reconnected + get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ) + .contents + .channel_flags + & 2, + 0 + ); // The "disabled" bit should be unset as we just reconnected nodes[1].node.get_and_clear_pending_msg_events(); // Free the holding cell check_added_monitors!(nodes[1], 1); @@ -1136,29 +1610,70 @@ fn test_monitor_update_fail_reestablish() { nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); assert_eq!(get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(), as_reestablish); assert_eq!(get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(), bs_reestablish); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_reestablish); assert_eq!( - get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()) - .contents.channel_flags & 2, 0); // The "disabled" bit should be unset as we just reconnected + get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ) + .contents + .channel_flags + & 2, + 0 + ); // The "disabled" bit should be unset as we just reconnected nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &as_reestablish); check_added_monitors!(nodes[1], 0); assert_eq!( - get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()) - .contents.channel_flags & 2, 0); // The "disabled" bit should be unset as we just reconnected + get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[0].node.get_our_node_id() + ) + .contents + .channel_flags + & 2, + 0 + ); // The "disabled" bit should be unset as we just reconnected chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_1.2) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_1.2, latest_update); check_added_monitors!(nodes[1], 0); @@ -1168,7 +1683,10 @@ fn test_monitor_update_fail_reestablish() { assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false); expect_payment_sent!(nodes[0], payment_preimage); } @@ -1185,9 +1703,12 @@ fn raa_no_response_awaiting_raa_state() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]); - let (payment_preimage_3, payment_hash_3, payment_secret_3) = get_payment_preimage_hash!(nodes[1]); + let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (payment_preimage_2, payment_hash_2, payment_secret_2) = + get_payment_preimage_hash!(nodes[1]); + let (payment_preimage_3, payment_hash_3, payment_secret_3) = + get_payment_preimage_hash!(nodes[1]); // Queue up two payments - one will be delivered right away, one immediately goes into the // holding cell as nodes[0] is AwaitingRAA. Ultimately this allows us to deliver an RAA @@ -1195,11 +1716,25 @@ fn raa_no_response_awaiting_raa_state() { // requires only an RAA response due to AwaitingRAA) we can deliver the RAA and require the CS // generation during RAA while in monitor-update-failed state. { - nodes[0].node.send_payment_with_route(route.clone(), payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); } @@ -1207,7 +1742,10 @@ fn raa_no_response_awaiting_raa_state() { assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); 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_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors!(nodes[1], 1); let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -1217,9 +1755,15 @@ fn raa_no_response_awaiting_raa_state() { assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // Now we have a CS queued up which adds a new HTLC (which will need a RAA/CS response from // nodes[1]) followed by an RAA. Fail the monitor updating prior to the CS, deliver the RAA, @@ -1227,7 +1771,10 @@ fn raa_no_response_awaiting_raa_state() { chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); 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_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); @@ -1236,7 +1783,14 @@ fn raa_no_response_awaiting_raa_state() { assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); // nodes[1] should be AwaitingRAA here! check_added_monitors!(nodes[1], 0); @@ -1248,8 +1802,15 @@ fn raa_no_response_awaiting_raa_state() { // chanmon_fail_consistency test required it to actually find the bug (by seeing out-of-sync // commitment transaction states) whereas here we can explicitly check for it. { - nodes[0].node.send_payment_with_route(route, payment_hash_3, - RecipientOnionFields::secret_only(payment_secret_3), PaymentId(payment_hash_3.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_3, + RecipientOnionFields::secret_only(payment_secret_3), + PaymentId(payment_hash_3.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -1259,14 +1820,27 @@ fn raa_no_response_awaiting_raa_state() { assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); 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_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // Finally deliver the RAA to nodes[1] which results in a CS response to the last update nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); @@ -1278,9 +1852,16 @@ fn raa_no_response_awaiting_raa_state() { nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_raa); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_update.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_update.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[1], 1); @@ -1307,7 +1888,8 @@ fn claim_while_disconnected_monitor_update_fail() { let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; // Forward a payment for B to claim - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); @@ -1316,40 +1898,79 @@ fn claim_while_disconnected_monitor_update_fail() { check_added_monitors!(nodes[1], 1); expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let as_reconnect = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); let bs_reconnect = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_reconnect); - let _as_channel_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); + let _as_channel_update = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ); // Now deliver a's reestablish, freeing the claim from the holding cell, but fail the monitor // update. chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &as_reconnect); - let _bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); + let _bs_channel_update = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[0].node.get_our_node_id() + ); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); // Send a second payment from A to B, resulting in a commitment update that gets swallowed with // the monitor still failed - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } let as_updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_updates.update_add_htlcs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_updates.commitment_signed); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_updates.update_add_htlcs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); // Note that nodes[1] not updating monitor here is OK - it wont take action on the new HTLC @@ -1358,7 +1979,14 @@ fn claim_while_disconnected_monitor_update_fail() { // Now un-fail the monitor, which will result in B sending its original commitment update, // receiving the commitment update from A, and the resulting commitment dances. chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[1], 0); @@ -1368,12 +1996,22 @@ fn claim_while_disconnected_monitor_update_fail() { match bs_msgs[0] { MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, ref updates } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage_1, None, false, false); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &updates.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[1], 1); }, @@ -1392,13 +2030,27 @@ fn claim_while_disconnected_monitor_update_fail() { let as_commitment = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let bs_commitment = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_commitment.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_commitment.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_commitment.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_commitment.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[1], 1); @@ -1426,20 +2078,44 @@ fn monitor_failed_no_reestablish_response() { { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, channel_id).context_mut().announcement_sigs_state = AnnouncementSigsState::PeerReceived; + get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + channel_id + ) + .context_mut() + .announcement_sigs_state = AnnouncementSigsState::PeerReceived; } { let mut node_1_per_peer_lock; let mut node_1_peer_state_lock; - get_channel_ref!(nodes[1], nodes[0], node_1_per_peer_lock, node_1_peer_state_lock, channel_id).context_mut().announcement_sigs_state = AnnouncementSigsState::PeerReceived; + get_channel_ref!( + nodes[1], + nodes[0], + node_1_per_peer_lock, + node_1_peer_state_lock, + channel_id + ) + .context_mut() + .announcement_sigs_state = AnnouncementSigsState::PeerReceived; } // Route the payment and deliver the initial commitment_signed (with a monitor update failure // on receipt). - let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -1448,7 +2124,10 @@ fn monitor_failed_no_reestablish_response() { assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); 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_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); @@ -1457,33 +2136,72 @@ fn monitor_failed_no_reestablish_response() { nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let as_reconnect = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); let bs_reconnect = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &as_reconnect); - let _bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); + let _bs_channel_update = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_reconnect); - let _as_channel_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); + let _as_channel_update = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[1], 0); let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_responses.0); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[1], 1); @@ -1513,10 +2231,18 @@ fn first_message_on_recv_ordering() { // Route the first payment outbound, holding the last RAA for B until we are set up so that we // can deliver it and fail the monitor update. - let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -1525,22 +2251,39 @@ fn first_message_on_recv_ordering() { let payment_event = SendEvent::from_event(events.pop().unwrap()); assert_eq!(payment_event.node_id, nodes[1].node.get_our_node_id()); 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_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors!(nodes[1], 1); let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_responses.0); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // Route the second payment, generating an update_add_htlc/commitment_signed - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1561,12 +2304,22 @@ fn first_message_on_recv_ordering() { // RAA/CS response, which should be generated when we call channel_monitor_update (with the // appropriate HTLC acceptance). 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_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[1], 0); @@ -1576,10 +2329,16 @@ fn first_message_on_recv_ordering() { let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_responses.0); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_responses.1); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[1], 1); @@ -1607,7 +2366,8 @@ fn test_monitor_update_fail_claim() { // Rebalance a bit so that we can send backwards from 3 to 2. send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000); - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); // As long as the preimage isn't on-chain, we shouldn't expose the `PaymentClaimed` event to @@ -1622,10 +2382,18 @@ fn test_monitor_update_fail_claim() { // already-signed commitment transaction and will instead wait for it to resolve before // forwarding the payment onwards. - let (route, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[2], nodes[0], 1_000_000); + let (route, payment_hash_2, _, payment_secret_2) = + get_route_and_payment_hash!(nodes[2], nodes[0], 1_000_000); { - nodes[2].node.send_payment_with_route(route.clone(), payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[2] + .node + .send_payment_with_route( + route.clone(), + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[2], 1); } @@ -1643,8 +2411,15 @@ fn test_monitor_update_fail_claim() { expect_pending_htlcs_forwardable_ignore!(nodes[1]); let (_, payment_hash_3, payment_secret_3) = get_payment_preimage_hash!(nodes[0]); - nodes[2].node.send_payment_with_route(route, payment_hash_3, - RecipientOnionFields::secret_only(payment_secret_3), PaymentId(payment_hash_3.0)).unwrap(); + nodes[2] + .node + .send_payment_with_route( + route, + payment_hash_3, + RecipientOnionFields::secret_only(payment_secret_3), + PaymentId(payment_hash_3.0), + ) + .unwrap(); check_added_monitors!(nodes[2], 1); let mut events = nodes[2].node.get_and_clear_pending_msg_events(); @@ -1657,13 +2432,23 @@ fn test_monitor_update_fail_claim() { // Now restore monitor updating on the 0<->1 channel and claim the funds on B. let channel_id = chan_1.2; - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000); check_added_monitors!(nodes[1], 0); let bs_fulfill_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_fulfill_update.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_fulfill_update.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], bs_fulfill_update.commitment_signed, false); expect_payment_sent!(nodes[0], payment_preimage_1); @@ -1671,42 +2456,67 @@ fn test_monitor_update_fail_claim() { nodes[1].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[1], 1); let bs_forward_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &bs_forward_update.update_add_htlcs[0]); - nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &bs_forward_update.update_add_htlcs[1]); + nodes[0].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &bs_forward_update.update_add_htlcs[0], + ); + nodes[0].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &bs_forward_update.update_add_htlcs[1], + ); commitment_signed_dance!(nodes[0], nodes[1], bs_forward_update.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[0]); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + via_user_channel_id, + .. + } => { assert_eq!(payment_hash_2, *payment_hash); assert_eq!(1_000_000, amount_msat); assert_eq!(receiver_node_id.unwrap(), nodes[0].node.get_our_node_id()); assert_eq!(via_channel_id, Some(channel_id)); assert_eq!(via_user_channel_id, Some(42)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_2, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), } match events[1] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + .. + } => { assert_eq!(payment_hash_3, *payment_hash); assert_eq!(1_000_000, amount_msat); assert_eq!(receiver_node_id.unwrap(), nodes[0].node.get_our_node_id()); assert_eq!(via_channel_id, Some(channel_id)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_3, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -1731,18 +2541,32 @@ fn test_monitor_update_on_pending_forwards() { let (_, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000); nodes[2].node.fail_htlc_backwards(&payment_hash_1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_1 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_1 }] + ); check_added_monitors!(nodes[2], 1); let cs_fail_update = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &cs_fail_update.update_fail_htlcs[0]); + nodes[1].node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &cs_fail_update.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[1], nodes[2], cs_fail_update.commitment_signed, true, true); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[2], nodes[0], 1000000); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[2], nodes[0], 1000000); { - nodes[2].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[2] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[2], 1); } @@ -1753,17 +2577,34 @@ fn test_monitor_update_on_pending_forwards() { commitment_signed_dance!(nodes[1], nodes[2], payment_event.commitment_msg, false); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); check_added_monitors!(nodes[1], 1); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_1.2) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_1.2, latest_update); check_added_monitors!(nodes[1], 0); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); - nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_add_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, false, true); let events = nodes[0].node.get_and_clear_pending_events(); @@ -1771,7 +2612,9 @@ fn test_monitor_update_on_pending_forwards() { if let Event::PaymentPathFailed { payment_hash, payment_failed_permanently, .. } = events[1] { assert_eq!(payment_hash, payment_hash_1); assert!(payment_failed_permanently); - } else { panic!("Unexpected event!"); } + } else { + panic!("Unexpected event!"); + } match events[2] { Event::PaymentFailed { payment_hash, .. } => { assert_eq!(payment_hash, Some(payment_hash_1)); @@ -1779,7 +2622,7 @@ fn test_monitor_update_on_pending_forwards() { _ => panic!("Unexpected event"), } match events[0] { - Event::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event"), }; nodes[0].node.process_pending_htlc_forwards(); @@ -1801,13 +2644,22 @@ fn monitor_update_claim_fail_no_response() { let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; // Forward a payment for B to claim - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); // Now start forwarding a second payment, skipping the last RAA so B is in AwaitingRAA - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); { - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -1815,7 +2667,15 @@ fn monitor_update_claim_fail_no_response() { assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); - let as_raa = commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false, true, false, true); + let as_raa = commitment_signed_dance!( + nodes[1], + nodes[0], + payment_event.commitment_msg, + false, + true, + false, + true + ); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[1].node.claim_funds(payment_preimage_1); @@ -1824,7 +2684,14 @@ fn monitor_update_claim_fail_no_response() { assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000); check_added_monitors!(nodes[1], 0); @@ -1836,7 +2703,10 @@ fn monitor_update_claim_fail_no_response() { expect_payment_claimable!(nodes[1], payment_hash_2, payment_secret_2, 1000000); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, false); expect_payment_sent!(nodes[0], payment_preimage_1); @@ -1845,7 +2715,9 @@ fn monitor_update_claim_fail_no_response() { // restore_b_before_conf has no meaning if !confirm_a_first // restore_b_before_lock has no meaning if confirm_a_first -fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: bool, restore_b_before_lock: bool) { +fn do_during_funding_monitor_fail( + confirm_a_first: bool, restore_b_before_conf: bool, restore_b_before_lock: bool, +) { // Test that if the monitor update generated by funding_transaction_generated fails we continue // the channel setup happily after the update is restored. let chanmon_cfgs = create_chanmon_cfgs(2); @@ -1853,28 +2725,74 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 43, None, None).unwrap(); - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id())); - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); - - let (temporary_channel_id, funding_tx, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 43); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 43, None, None) + .unwrap(); + nodes[1].node.handle_open_channel( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ), + ); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), funding_tx.clone()).unwrap(); + let (temporary_channel_id, funding_tx, funding_output) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 43); + + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + funding_tx.clone(), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); - let channel_id = ChannelId::v1_from_funding_txid(funding_created_msg.funding_txid.as_byte_array(), funding_created_msg.funding_output_index); + let funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); + let channel_id = ChannelId::v1_from_funding_txid( + funding_created_msg.funding_txid.as_byte_array(), + funding_created_msg.funding_output_index, + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors!(nodes[1], 1); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_funding_signed( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[0], 1); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[0], 0); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); @@ -1882,11 +2800,21 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 0); assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); - assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0].compute_txid(), funding_output.txid); + assert_eq!( + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0].compute_txid(), + funding_output.txid + ); if confirm_a_first { confirm_transaction(&nodes[0], &funding_tx); - nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &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(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ), + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); } else { @@ -1914,25 +2842,54 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: } if !confirm_a_first && !restore_b_before_lock { confirm_transaction(&nodes[0], &funding_tx); - nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &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(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ), + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); } chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); check_added_monitors!(nodes[1], 0); let (channel_id, (announcement, as_update, bs_update)) = if !confirm_a_first { if !restore_b_before_lock { - let (channel_ready, channel_id) = create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]); - (channel_id, create_chan_between_nodes_with_value_b(&nodes[1], &nodes[0], &channel_ready)) + let (channel_ready, channel_id) = + create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]); + ( + channel_id, + create_chan_between_nodes_with_value_b(&nodes[1], &nodes[0], &channel_ready), + ) } else { - nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_channel_ready( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelReady, + nodes[0].node.get_our_node_id() + ), + ); confirm_transaction(&nodes[0], &funding_tx); - let (channel_ready, channel_id) = create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]); - (channel_id, create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready)) + let (channel_ready, channel_id) = + create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]); + ( + channel_id, + create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready), + ) } } else { if restore_b_before_conf { @@ -1940,12 +2897,16 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); confirm_transaction(&nodes[1], &funding_tx); } - let (channel_ready, channel_id) = create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]); + let (channel_ready, channel_id) = + create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]); (channel_id, create_chan_between_nodes_with_value_b(&nodes[1], &nodes[0], &channel_ready)) }; for (i, node) in nodes.iter().enumerate() { let counterparty_node_id = nodes[(i + 1) % 2].node.get_our_node_id(); - assert!(node.gossip_sync.handle_channel_announcement(Some(counterparty_node_id), &announcement).unwrap()); + assert!(node + .gossip_sync + .handle_channel_announcement(Some(counterparty_node_id), &announcement) + .unwrap()); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &as_update).unwrap(); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &bs_update).unwrap(); } @@ -1956,11 +2917,22 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id()); } - send_payment(&nodes[0], &[&nodes[1]], 8000000); close_channel(&nodes[0], &nodes[1], &channel_id, funding_tx, true); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1985,7 +2957,8 @@ fn test_path_paused_mpp() { let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3).0.contents.short_channel_id; let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3).0.contents.short_channel_id; - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); // Set us up to take multiple routes, one 0 -> 1 -> 3 and one 0 -> 2 -> 3: let path = route.paths[0].clone(); @@ -2003,28 +2976,61 @@ fn test_path_paused_mpp() { chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); // The first path should have succeeded with the second getting a MonitorUpdateInProgress err. - nodes[0].node.send_payment_with_route( - route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); // Pass the first HTLC of the payment along to nodes[3]. let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 0, payment_hash.clone(), Some(payment_secret), events.pop().unwrap(), false, None); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + 0, + payment_hash.clone(), + Some(payment_secret), + events.pop().unwrap(), + false, + None, + ); // And check that, after we successfully update the monitor for chan_2 we can pass the second // HTLC along to nodes[3] and claim the whole payment back to nodes[0]. - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_2_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_2_id, latest_update); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash.clone(), Some(payment_secret), events.pop().unwrap(), true, None); - - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + 200_000, + payment_hash.clone(), + Some(payment_secret), + events.pop().unwrap(), + true, + None, ); + + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + payment_preimage, + )); } #[test] @@ -2047,9 +3053,17 @@ fn test_pending_update_fee_ack_on_reconnect() { create_announced_chan_between_nodes(&nodes, 0, 1); send_payment(&nodes[0], &[&nodes[1]], 100_000_00); - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[1], nodes[0], 1_000_000); - nodes[1].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[1], nodes[0], 1_000_000); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); let bs_initial_send_msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); // bs_initial_send_msgs are not delivered until they are re-generated after reconnect @@ -2063,22 +3077,50 @@ fn test_pending_update_fee_ack_on_reconnect() { let as_update_fee_msgs = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); assert!(as_update_fee_msgs.update_fee.is_some()); - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), as_update_fee_msgs.update_fee.as_ref().unwrap()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_update_fee_msgs.commitment_signed); + nodes[1].node.handle_update_fee( + nodes[0].node.get_our_node_id(), + as_update_fee_msgs.update_fee.as_ref().unwrap(), + ); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_update_fee_msgs.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_first_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_first_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // bs_first_raa is not delivered until it is re-generated after reconnect nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let as_connect_msg = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let bs_connect_msg = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &as_connect_msg); @@ -2086,34 +3128,71 @@ fn test_pending_update_fee_ack_on_reconnect() { assert_eq!(bs_resend_msgs.len(), 3); if let MessageSendEvent::UpdateHTLCs { ref updates, .. } = bs_resend_msgs[0] { assert_eq!(*updates, bs_initial_send_msgs); - } else { panic!(); } + } else { + panic!(); + } if let MessageSendEvent::SendRevokeAndACK { ref msg, .. } = bs_resend_msgs[1] { assert_eq!(*msg, bs_first_raa); - } else { panic!(); } - if let MessageSendEvent::SendChannelUpdate { .. } = bs_resend_msgs[2] { } else { panic!(); } + } else { + panic!(); + } + if let MessageSendEvent::SendChannelUpdate { .. } = bs_resend_msgs[2] { + } else { + panic!(); + } nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_connect_msg); get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); - nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &bs_initial_send_msgs.update_add_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_initial_send_msgs.commitment_signed); + nodes[0].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &bs_initial_send_msgs.update_add_htlcs[0], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_initial_send_msgs.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id())); + nodes[1].node.handle_revoke_and_ack( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[1], 1); - let bs_second_cs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()).commitment_signed; + let bs_second_cs = + get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()).commitment_signed; nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_first_raa); check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()).commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()).commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_third_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_cs); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_cs); check_added_monitors!(nodes[0], 1); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_third_raa); check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id())); + nodes[1].node.handle_revoke_and_ack( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[1], 1); expect_pending_htlcs_forwardable!(nodes[0]); @@ -2140,7 +3219,8 @@ fn test_fail_htlc_on_broadcast_after_claim() { create_announced_chan_between_nodes(&nodes, 0, 1); let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2).2; - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 2000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 2000); let bs_txn = get_local_commitment_txn!(nodes[2], chan_id_2); assert_eq!(bs_txn.len(), 1); @@ -2150,19 +3230,37 @@ fn test_fail_htlc_on_broadcast_after_claim() { expect_payment_claimed!(nodes[2], payment_hash, 2000); let cs_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &cs_updates.update_fulfill_htlcs[0], + ); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false); mine_transaction(&nodes[1], &bs_txn[0]); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[2].node.get_our_node_id()], + 100000 + ); check_closed_broadcast!(nodes[1], true); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); check_added_monitors!(nodes[1], 1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] + ); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, true, true); expect_payment_path_successful!(nodes[0]); @@ -2189,7 +3287,10 @@ fn do_update_fee_resend_test(deliver_update: bool, parallel_updates: bool) { let update_msgs = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); assert!(update_msgs.update_fee.is_some()); if deliver_update { - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msgs.update_fee.as_ref().unwrap()); + nodes[1].node.handle_update_fee( + nodes[0].node.get_our_node_id(), + update_msgs.update_fee.as_ref().unwrap(), + ); } if parallel_updates { @@ -2204,13 +3305,31 @@ fn do_update_fee_resend_test(deliver_update: bool, parallel_updates: bool) { nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let as_connect_msg = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let bs_connect_msg = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &as_connect_msg); @@ -2220,27 +3339,57 @@ fn do_update_fee_resend_test(deliver_update: bool, parallel_updates: bool) { nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_connect_msg); let mut as_reconnect_msgs = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(as_reconnect_msgs.len(), 2); - if let MessageSendEvent::SendChannelUpdate { .. } = as_reconnect_msgs.pop().unwrap() {} else { panic!(); } - let update_msgs = if let MessageSendEvent::UpdateHTLCs { updates, .. } = as_reconnect_msgs.pop().unwrap() - { updates } else { panic!(); }; + if let MessageSendEvent::SendChannelUpdate { .. } = as_reconnect_msgs.pop().unwrap() { + } else { + panic!(); + } + let update_msgs = + if let MessageSendEvent::UpdateHTLCs { updates, .. } = as_reconnect_msgs.pop().unwrap() { + updates + } else { + panic!(); + }; assert!(update_msgs.update_fee.is_some()); - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msgs.update_fee.as_ref().unwrap()); + nodes[1].node.handle_update_fee( + nodes[0].node.get_our_node_id(), + update_msgs.update_fee.as_ref().unwrap(), + ); if parallel_updates { - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &update_msgs.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &update_msgs.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_first_raa, bs_first_cs) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_first_raa); check_added_monitors!(nodes[0], 1); let as_second_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); check_added_monitors!(nodes[0], 1); - let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); - - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), as_second_update.update_fee.as_ref().unwrap()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_second_update.commitment_signed); + let as_first_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); + + nodes[1].node.handle_update_fee( + nodes[0].node.get_our_node_id(), + as_second_update.update_fee.as_ref().unwrap(), + ); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_second_update.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_second_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_first_raa); let bs_second_cs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -2249,9 +3398,16 @@ fn do_update_fee_resend_test(deliver_update: bool, parallel_updates: bool) { nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_second_raa); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_cs.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_second_cs.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_second_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_second_raa); check_added_monitors!(nodes[1], 1); @@ -2282,9 +3438,12 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { let nodes_0_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 15_000_000, 7_000_000_000).2; - let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100000); - let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(&nodes[1]); + let chan_id = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 15_000_000, 7_000_000_000).2; + let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(&nodes[0], nodes[1], 100000); + let (payment_preimage_2, payment_hash_2, payment_secret_2) = + get_payment_preimage_hash!(&nodes[1]); // Do a really complicated dance to get an HTLC into the holding cell, with // MonitorUpdateInProgress set but AwaitingRemoteRevoke unset. When this test was written, any @@ -2308,14 +3467,28 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { // (c) will not be freed from the holding cell. let (payment_preimage_0, payment_hash_0, ..) = route_payment(&nodes[1], &[&nodes[0]], 100_000); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let send = SendEvent::from_node(&nodes[0]); assert_eq!(send.msgs.len(), 1); - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); @@ -2325,7 +3498,9 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { check_added_monitors!(nodes[0], 1); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &send.commitment_msg); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &send.commitment_msg); check_added_monitors!(nodes[1], 1); let (raa, cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -2338,7 +3513,14 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { // disconnect the peers. Note that the fuzzer originally found this issue because // deserializing a ChannelManager in this state causes an assertion failure. if reload_a { - reload_node!(nodes[0], &nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + &nodes[0].node.encode(), + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); } else { @@ -2347,22 +3529,44 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); // Now reconnect the two - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); assert_eq!(reestablish_1.len(), 1); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); assert_eq!(reestablish_2.len(), 1); - nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); + nodes[1] + .node + .handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); let resp_1 = handle_chan_reestablish_msgs!(nodes[1], nodes[0]); check_added_monitors!(nodes[1], 0); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); let resp_0 = handle_chan_reestablish_msgs!(nodes[0], nodes[1]); assert!(resp_0.0.is_none()); @@ -2378,7 +3582,9 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { assert!(pending_cs.update_fail_htlcs.is_empty()); assert!(pending_cs.update_fulfill_htlcs.is_empty()); assert_eq!(pending_cs.commitment_signed, cs); - } else { panic!(); } + } else { + panic!(); + } if reload_a { // The two pending monitor updates were replayed (but are still pending). @@ -2393,7 +3599,14 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { // If we finish updating the monitor, we should free the holding cell right away (this did // not occur prior to #756). chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (mon_id, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone(); + let (mon_id, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_id, mon_id); expect_payment_claimed!(nodes[0], payment_hash_0, 100_000); @@ -2415,19 +3628,31 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[1].node.handle_update_fulfill_htlc(nodes[0].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[0].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[1], payment_preimage_0, None, false, false); assert_eq!(updates.update_add_htlcs.len(), 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1].node.handle_update_add_htlc( + nodes[0].node.get_our_node_id(), + &updates.update_add_htlcs[0], + ); updates.commitment_signed }, _ => panic!("Unexpected event type!"), }; - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commitment_msg); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commitment_msg); check_added_monitors!(nodes[1], 1); - let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_revoke_and_ack); expect_pending_htlcs_forwardable!(nodes[1]); expect_payment_claimable!(nodes[1], payment_hash_1, payment_secret_1, 100000); @@ -2438,11 +3663,11 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event"), }; match events[1] { - Event::PaymentPathSuccessful { .. } => { }, + Event::PaymentPathSuccessful { .. } => {}, _ => panic!("Unexpected event"), }; @@ -2480,20 +3705,33 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f create_announced_chan_between_nodes(&nodes, 0, 1); let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2).2; - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); let mut as_raa = None; if htlc_status == HTLCStatusAtDupClaim::HoldingCell { // In order to get the HTLC claim into the holding cell at nodes[1], we need nodes[1] to be // awaiting a remote revoke_and_ack from nodes[0]. - let (route, second_payment_hash, _, second_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); - nodes[0].node.send_payment_with_route(route, second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), PaymentId(second_payment_hash.0)).unwrap(); + let (route, second_payment_hash, _, second_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); + nodes[0] + .node + .send_payment_with_route( + route, + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + PaymentId(second_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - let send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); + let send_event = + SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &send_event.commitment_msg); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &send_event.commitment_msg, + ); check_added_monitors!(nodes[1], 1); let (bs_raa, bs_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -2502,17 +3740,21 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_cs); check_added_monitors!(nodes[0], 1); - as_raa = Some(get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id())); + as_raa = Some(get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + )); } - let fulfill_msg = msgs::UpdateFulfillHTLC { - channel_id: chan_id_2, - htlc_id: 0, - payment_preimage, - }; + let fulfill_msg = + msgs::UpdateFulfillHTLC { channel_id: chan_id_2, htlc_id: 0, payment_preimage }; if second_fails { nodes[2].node.fail_htlc_backwards(&payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[2], 1); get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); } else { @@ -2533,10 +3775,18 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f if htlc_status != HTLCStatusAtDupClaim::HoldingCell { bs_updates = Some(get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id())); assert_eq!(bs_updates.as_ref().unwrap().update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.as_ref().unwrap().update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.as_ref().unwrap().update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); if htlc_status == HTLCStatusAtDupClaim::Cleared { - commitment_signed_dance!(nodes[0], nodes[1], &bs_updates.as_ref().unwrap().commitment_signed, false); + commitment_signed_dance!( + nodes[0], + nodes[1], + &bs_updates.as_ref().unwrap().commitment_signed, + false + ); expect_payment_path_successful!(nodes[0]); } } else { @@ -2550,7 +3800,13 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f let mut reconnect_args = ReconnectArgs::new(&nodes[1], &nodes[2]); reconnect_args.pending_htlc_fails.0 = 1; reconnect_nodes(reconnect_args); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] + ); } else { let mut reconnect_args = ReconnectArgs::new(&nodes[1], &nodes[2]); reconnect_args.pending_htlc_claims.0 = 1; @@ -2564,11 +3820,19 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f bs_updates = Some(get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id())); assert_eq!(bs_updates.as_ref().unwrap().update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.as_ref().unwrap().update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.as_ref().unwrap().update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); } if htlc_status != HTLCStatusAtDupClaim::Cleared { - commitment_signed_dance!(nodes[0], nodes[1], &bs_updates.as_ref().unwrap().commitment_signed, false); + commitment_signed_dance!( + nodes[0], + nodes[1], + &bs_updates.as_ref().unwrap().commitment_signed, + false + ); expect_payment_path_successful!(nodes[0]); } } @@ -2601,10 +3865,16 @@ fn test_temporary_error_during_shutdown() { chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[0].node.close_channel(&channel_id, &nodes[1].node.get_our_node_id()).unwrap(); - nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id())); + nodes[1].node.handle_shutdown( + nodes[0].node.get_our_node_id(), + &get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()), + ); check_added_monitors!(nodes[1], 1); - nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_shutdown( + nodes[1].node.get_our_node_id(), + &get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()), + ); check_added_monitors!(nodes[0], 1); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -2612,21 +3882,52 @@ fn test_temporary_error_during_shutdown() { chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id())); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ), + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update); - nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id())); - let (_, closing_signed_a) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_closing_signed( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ), + ); + let (_, closing_signed_a) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); let txn_a = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &closing_signed_a.unwrap()); + nodes[1] + .node + .handle_closing_signed(nodes[0].node.get_our_node_id(), &closing_signed_a.unwrap()); let (_, none_b) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(none_b.is_none()); let txn_b = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); @@ -2634,8 +3935,20 @@ fn test_temporary_error_during_shutdown() { assert_eq!(txn_a, txn_b); assert_eq!(txn_a.len(), 1); check_spends!(txn_a[0], funding_tx); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -2648,14 +3961,23 @@ fn double_temp_error() { let (_, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1); - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); - let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); // `claim_funds` results in a ChannelMonitorUpdate. nodes[1].node.claim_funds(payment_preimage_1); check_added_monitors!(nodes[1], 1); - let (latest_update_1, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update_1, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); // Previously, this would've panicked due to a double-call to `Channel::monitor_update_failed`, @@ -2664,7 +3986,14 @@ fn double_temp_error() { check_added_monitors!(nodes[1], 1); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (latest_update_2, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (latest_update_2, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&channel_id) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(channel_id, latest_update_1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 0); @@ -2677,18 +4006,34 @@ fn double_temp_error() { let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentClaimed { amount_msat: 1_000_000, payment_hash, .. } => assert_eq!(payment_hash, payment_hash_1), + Event::PaymentClaimed { amount_msat: 1_000_000, payment_hash, .. } => { + assert_eq!(payment_hash, payment_hash_1) + }, _ => panic!("Unexpected Event: {:?}", events[0]), } match events[1] { - Event::PaymentClaimed { amount_msat: 1_000_000, payment_hash, .. } => assert_eq!(payment_hash, payment_hash_2), + Event::PaymentClaimed { amount_msat: 1_000_000, payment_hash, .. } => { + assert_eq!(payment_hash, payment_hash_2) + }, _ => panic!("Unexpected Event: {:?}", events[1]), } assert_eq!(msg_events.len(), 1); let (update_fulfill_1, commitment_signed_b1, node_id) = { match &msg_events[0] { - &MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + &MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert!(update_add_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); assert!(update_fail_htlcs.is_empty()); @@ -2703,40 +4048,49 @@ fn double_temp_error() { nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_fulfill_1); check_added_monitors!(nodes[0], 0); expect_payment_sent(&nodes[0], payment_preimage_1, None, false, false); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed_b1); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &commitment_signed_b1, + ); check_added_monitors!(nodes[0], 1); nodes[0].node.process_pending_htlc_forwards(); - let (raa_a1, commitment_signed_a1) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (raa_a1, commitment_signed_a1) = + get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); check_added_monitors!(nodes[1], 0); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &raa_a1); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commitment_signed_a1); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &commitment_signed_a1, + ); check_added_monitors!(nodes[1], 1); // Complete the second HTLC. let ((update_fulfill_2, commitment_signed_b2), raa_b2) = { let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); - (match &events[0] { - MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, updates } => { - assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - assert!(updates.update_add_htlcs.is_empty()); - assert!(updates.update_fail_htlcs.is_empty()); - assert!(updates.update_fail_malformed_htlcs.is_empty()); - assert!(updates.update_fee.is_none()); - assert_eq!(updates.update_fulfill_htlcs.len(), 1); - (updates.update_fulfill_htlcs[0].clone(), updates.commitment_signed.clone()) + ( + match &events[0] { + MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, updates } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + assert!(updates.update_add_htlcs.is_empty()); + assert!(updates.update_fail_htlcs.is_empty()); + assert!(updates.update_fail_malformed_htlcs.is_empty()); + assert!(updates.update_fee.is_none()); + assert_eq!(updates.update_fulfill_htlcs.len(), 1); + (updates.update_fulfill_htlcs[0].clone(), updates.commitment_signed.clone()) + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }, - match events[1] { - MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - (*msg).clone() - }, - _ => panic!("Unexpected event"), - }) + match events[1] { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + (*msg).clone() + }, + _ => panic!("Unexpected event"), + }, + ) }; nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &raa_b2); check_added_monitors!(nodes[0], 1); @@ -2763,35 +4117,81 @@ fn do_test_outbound_reload_without_init_mon(use_0conf: bool) { chan_config.manually_accept_inbound_channels = true; chan_config.channel_handshake_limits.trust_own_funding_0conf = true; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(chan_config.clone()), Some(chan_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(chan_config.clone()), Some(chan_config)]); let nodes_0_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 43, None, None).unwrap(); - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id())); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 43, None, None) + .unwrap(); + nodes[1].node.handle_open_channel( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ), + ); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { if use_0conf { - nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) + .unwrap(); } else { - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).unwrap(); + nodes[1] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) + .unwrap(); } }, _ => panic!("Unexpected event"), }; - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); - - let (temporary_channel_id, funding_tx, ..) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 43); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), funding_tx.clone()).unwrap(); + let (temporary_channel_id, funding_tx, ..) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 43); + + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + funding_tx.clone(), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); @@ -2804,14 +4204,14 @@ fn do_test_outbound_reload_without_init_mon(use_0conf: bool) { nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &msg); check_added_monitors!(nodes[0], 1); - } + }, _ => panic!("Unexpected event"), } if use_0conf { match &bs_signed_locked[1] { MessageSendEvent::SendChannelReady { msg, .. } => { nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &msg); - } + }, _ => panic!("Unexpected event"), } } @@ -2829,8 +4229,21 @@ fn do_test_outbound_reload_without_init_mon(use_0conf: bool) { nodes[0].chain_source.watched_txn.lock().unwrap().clear(); nodes[0].chain_source.watched_outputs.lock().unwrap().clear(); - reload_node!(nodes[0], &nodes[0].node.encode(), &[], persister, new_chain_monitor, nodes_0_deserialized); - check_closed_event!(nodes[0], 1, ClosureReason::DisconnectedPeer, [nodes[1].node.get_our_node_id()], 100000); + reload_node!( + nodes[0], + &nodes[0].node.encode(), + &[], + persister, + new_chain_monitor, + nodes_0_deserialized + ); + check_closed_event!( + nodes[0], + 1, + ClosureReason::DisconnectedPeer, + [nodes[1].node.get_our_node_id()], + 100000 + ); assert!(nodes[0].node.list_channels().is_empty()); } @@ -2854,35 +4267,81 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo chan_config.manually_accept_inbound_channels = true; chan_config.channel_handshake_limits.trust_own_funding_0conf = true; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(chan_config.clone()), Some(chan_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(chan_config.clone()), Some(chan_config)]); let nodes_1_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 43, None, None).unwrap(); - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id())); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 43, None, None) + .unwrap(); + nodes[1].node.handle_open_channel( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ), + ); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { if use_0conf { - nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) + .unwrap(); } else { - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).unwrap(); + nodes[1] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) + .unwrap(); } }, _ => panic!("Unexpected event"), }; - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); - - let (temporary_channel_id, funding_tx, ..) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 43); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), funding_tx.clone()).unwrap(); + let (temporary_channel_id, funding_tx, ..) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 43); + + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + funding_tx.clone(), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors!(nodes[1], 1); @@ -2890,7 +4349,11 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo // nodes[1] happily sends its funding_signed even though its awaiting the persistence of the // initial ChannelMonitor, but it will decline to send its channel_ready even if the funding // transaction is confirmed. - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); check_added_monitors!(nodes[0], 1); @@ -2902,7 +4365,11 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo confirm_transaction(&nodes[1], &as_funding_tx[0]); } if use_0conf || lock_commitment { - let as_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let as_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(), &as_ready); } assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); @@ -2916,9 +4383,22 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo nodes[1].chain_source.watched_txn.lock().unwrap().clear(); nodes[1].chain_source.watched_outputs.lock().unwrap().clear(); - reload_node!(nodes[1], &nodes[1].node.encode(), &[], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + &nodes[1].node.encode(), + &[], + persister, + new_chain_monitor, + nodes_1_deserialized + ); - check_closed_event!(nodes[1], 1, ClosureReason::DisconnectedPeer, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::DisconnectedPeer, + [nodes[0].node.get_our_node_id()], + 100000 + ); assert!(nodes[1].node.list_channels().is_empty()); } @@ -2946,8 +4426,10 @@ fn test_blocked_chan_preimage_release() { // Tee up two payments in opposite directions across nodes[1], one it sent to generate a // PaymentSent event and one it forwards. - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[1], &[&nodes[2]], 1_000_000); - let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[2], &[&nodes[1], &nodes[0]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[1], &[&nodes[2]], 1_000_000); + let (payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[2], &[&nodes[1], &nodes[0]], 1_000_000); // Claim the first payment to get a `PaymentSent` event (but don't handle it yet). nodes[2].node.claim_funds(payment_preimage_1); @@ -2955,8 +4437,17 @@ fn test_blocked_chan_preimage_release() { expect_payment_claimed!(nodes[2], payment_hash_1, 1_000_000); let cs_htlc_fulfill_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &cs_htlc_fulfill_updates.update_fulfill_htlcs[0]); - do_commitment_signed_dance(&nodes[1], &nodes[2], &cs_htlc_fulfill_updates.commitment_signed, false, false); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &cs_htlc_fulfill_updates.update_fulfill_htlcs[0], + ); + do_commitment_signed_dance( + &nodes[1], + &nodes[2], + &cs_htlc_fulfill_updates.commitment_signed, + false, + false, + ); check_added_monitors(&nodes[1], 0); // Now claim the second payment on nodes[0], which will ultimately result in nodes[1] trying to @@ -2967,7 +4458,10 @@ fn test_blocked_chan_preimage_release() { expect_payment_claimed!(nodes[0], payment_hash_2, 1_000_000); let as_htlc_fulfill_updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[0].node.get_our_node_id(), &as_htlc_fulfill_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[0].node.get_our_node_id(), + &as_htlc_fulfill_updates.update_fulfill_htlcs[0], + ); check_added_monitors(&nodes[1], 1); // We generate only a preimage monitor update assert!(get_monitor!(nodes[1], chan_id_2).get_stored_preimages().contains_key(&payment_hash_2)); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); @@ -2975,7 +4469,10 @@ fn test_blocked_chan_preimage_release() { // Finish the CS dance between nodes[0] and nodes[1]. Note that until the event handling, the // update_fulfill_htlc + CS is held, even though the preimage is already on disk for the // channel. - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_htlc_fulfill_updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_htlc_fulfill_updates.commitment_signed, + ); check_added_monitors(&nodes[1], 1); let (a, raa) = do_main_commitment_signed_dance(&nodes[1], &nodes[0], false); assert!(a.is_none()); @@ -2986,9 +4483,18 @@ fn test_blocked_chan_preimage_release() { let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 3); - if let Event::PaymentSent { .. } = events[0] {} else { panic!(); } - if let Event::PaymentPathSuccessful { .. } = events[2] {} else { panic!(); } - if let Event::PaymentForwarded { .. } = events[1] {} else { panic!(); } + if let Event::PaymentSent { .. } = events[0] { + } else { + panic!(); + } + if let Event::PaymentPathSuccessful { .. } = events[2] { + } else { + panic!(); + } + if let Event::PaymentForwarded { .. } = events[1] { + } else { + panic!(); + } // The event processing should release the last RAA updates on both channels. check_added_monitors(&nodes[1], 2); @@ -2998,12 +4504,23 @@ fn test_blocked_chan_preimage_release() { let bs_htlc_fulfill_updates = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id()); check_added_monitors(&nodes[1], 1); - nodes[2].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_htlc_fulfill_updates.update_fulfill_htlcs[0]); - do_commitment_signed_dance(&nodes[2], &nodes[1], &bs_htlc_fulfill_updates.commitment_signed, false, false); + nodes[2].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_htlc_fulfill_updates.update_fulfill_htlcs[0], + ); + do_commitment_signed_dance( + &nodes[2], + &nodes[1], + &bs_htlc_fulfill_updates.commitment_signed, + false, + false, + ); expect_payment_sent(&nodes[2], payment_preimage_2, None, true, true); } -fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_commitment_dance: bool) { +fn do_test_inverted_mon_completion_order( + with_latest_manager: bool, complete_bc_commitment_dance: bool, +) { // When we forward a payment and receive `update_fulfill_htlc`+`commitment_signed` messages // from the downstream channel, we immediately claim the HTLC on the upstream channel, before // even doing a `commitment_signed` dance on the downstream channel. This implies that our @@ -3028,7 +4545,8 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ // Route a payment from A, through B, to C, then claim it on C. Once we pass B the // `update_fulfill_htlc` we have a monitor update for both of B's channels. We complete the one // on the B<->C channel but leave the A<->B monitor update pending, then reload B. - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); let mon_ab = get_monitor!(nodes[1], chan_id_ab).encode(); let mut manager_b = Vec::new(); @@ -3042,7 +4560,10 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); let cs_updates = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &cs_updates.update_fulfill_htlcs[0], + ); // B generates a new monitor update for the A <-> B channel, but doesn't send the new messages // for it since the monitor update is marked in-progress. @@ -3052,15 +4573,26 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ // Now step the Commitment Signed Dance between B and C forward a bit (or fully), ensuring we // won't get the preimage when the nodes reconnect and we have to get it from the // ChannelMonitor. - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &cs_updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &cs_updates.commitment_signed, + ); check_added_monitors(&nodes[1], 1); if complete_bc_commitment_dance { - let (bs_revoke_and_ack, bs_commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[2].node.get_our_node_id()); + let (bs_revoke_and_ack, bs_commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[2].node.get_our_node_id()); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_revoke_and_ack); check_added_monitors(&nodes[2], 1); - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_commitment_signed); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_commitment_signed, + ); check_added_monitors(&nodes[2], 1); - let cs_raa = get_event_msg!(nodes[2], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let cs_raa = get_event_msg!( + nodes[2], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // At this point node B still hasn't persisted the `ChannelMonitorUpdate` with the // preimage in the A <-> B channel, which will prevent it from persisting the @@ -3076,7 +4608,14 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ } let mon_bc = get_monitor!(nodes[1], chan_id_bc).encode(); - reload_node!(nodes[1], &manager_b, &[&mon_ab, &mon_bc], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + &manager_b, + &[&mon_ab, &mon_bc], + persister, + new_chain_monitor, + nodes_1_deserialized + ); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[2].node.peer_disconnected(nodes[1].node.get_our_node_id()); @@ -3111,12 +4650,23 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ // (Finally) complete the A <-> B ChannelMonitorUpdate, ensuring the preimage is durably on // disk in the proper ChannelMonitor, unblocking the B <-> C ChannelMonitor updating // process. - let (_, ab_update_id) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_ab).unwrap().clone(); - nodes[1].chain_monitor.chain_monitor.channel_monitor_updated(chan_id_ab, ab_update_id).unwrap(); - - // When we fetch B's HTLC update messages next (now that the ChannelMonitorUpdate has - // completed), it will also release the final RAA ChannelMonitorUpdate on the B <-> C - // channel. + let (_, ab_update_id) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id_ab) + .unwrap() + .clone(); + nodes[1] + .chain_monitor + .chain_monitor + .channel_monitor_updated(chan_id_ab, ab_update_id) + .unwrap(); + + // When we fetch B's HTLC update messages next (now that the ChannelMonitorUpdate has + // completed), it will also release the final RAA ChannelMonitorUpdate on the B <-> C + // channel. } else { // If the ChannelManager used in the reload was stale, check that the B <-> C channel was // closed. @@ -3128,7 +4678,14 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ check_added_monitors(&nodes[1], 0); persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - check_closed_event(&nodes[1], 1, ClosureReason::OutdatedChannelManager, false, &[nodes[2].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::OutdatedChannelManager, + false, + &[nodes[2].node.get_our_node_id()], + 100_000, + ); check_added_monitors(&nodes[1], 2); nodes[1].node.timer_tick_occurred(); @@ -3139,8 +4696,19 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ // ChannelMonitorUpdate hasn't yet completed. reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); - let (_, ab_update_id) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_ab).unwrap().clone(); - nodes[1].chain_monitor.chain_monitor.channel_monitor_updated(chan_id_ab, ab_update_id).unwrap(); + let (_, ab_update_id) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id_ab) + .unwrap() + .clone(); + nodes[1] + .chain_monitor + .chain_monitor + .channel_monitor_updated(chan_id_ab, ab_update_id) + .unwrap(); // The ChannelMonitorUpdate which was completed prior to the reconnect only contained the // preimage (as it was a replay of the original ChannelMonitorUpdate from before we @@ -3153,10 +4721,20 @@ fn do_test_inverted_mon_completion_order(with_latest_manager: bool, complete_bc_ let bs_updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); check_added_monitors(&nodes[1], 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.update_fulfill_htlcs[0], + ); do_commitment_signed_dance(&nodes[0], &nodes[1], &bs_updates.commitment_signed, false, false); - expect_payment_forwarded!(nodes[1], &nodes[0], &nodes[2], Some(1_000), false, !with_latest_manager); + expect_payment_forwarded!( + nodes[1], + &nodes[0], + &nodes[2], + Some(1_000), + false, + !with_latest_manager + ); // Finally, check that the payment was, ultimately, seen as sent by node A. expect_payment_sent(&nodes[0], payment_preimage, None, true, true); @@ -3170,7 +4748,9 @@ fn test_inverted_mon_completion_order() { do_test_inverted_mon_completion_order(false, false); } -fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, close_only_a: bool, hold_post_reload_mon_update: bool) { +fn do_test_durable_preimages_on_closed_channel( + close_chans_before_reload: bool, close_only_a: bool, hold_post_reload_mon_update: bool, +) { // Test that we can apply a `ChannelMonitorUpdate` with a payment preimage even if the channel // is force-closed between when we generate the update on reload and when we go to handle the // update or prior to generating the update at all. @@ -3196,7 +4776,8 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, // Route a payment from A, through B, to C, then claim it on C. Once we pass B the // `update_fulfill_htlc` we have a monitor update for both of B's channels. We complete the one // on the B<->C channel but leave the A<->B monitor update pending, then reload B. - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); let mon_ab = get_monitor!(nodes[1], chan_id_ab).encode(); @@ -3206,7 +4787,10 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); let cs_updates = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &cs_updates.update_fulfill_htlcs[0], + ); // B generates a new monitor update for the A <-> B channel, but doesn't send the new messages // for it since the monitor update is marked in-progress. @@ -3216,7 +4800,10 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, // Now step the Commitment Signed Dance between B and C forward a bit, ensuring we won't get // the preimage when the nodes reconnect, at which point we have to ensure we get it from the // ChannelMonitor. - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &cs_updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &cs_updates.commitment_signed, + ); check_added_monitors(&nodes[1], 1); let _ = get_revoke_commit_msgs!(nodes[1], nodes[2].node.get_our_node_id()); @@ -3226,20 +4813,55 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, if close_chans_before_reload { if !close_only_a { chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[1].node.force_close_broadcasting_latest_txn(&chan_id_bc, &nodes[2].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_id_bc, + &nodes[2].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[2].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[2].node.get_our_node_id()], + 100000, + ); } chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[1].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_id_ab, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); } // Now reload node B let manager_b = nodes[1].node.encode(); - reload_node!(nodes[1], &manager_b, &[&mon_ab, &mon_bc], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + &manager_b, + &[&mon_ab, &mon_bc], + persister, + new_chain_monitor, + nodes_1_deserialized + ); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[2].node.peer_disconnected(nodes[1].node.get_our_node_id()); @@ -3255,8 +4877,22 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, } let error_message = "Channel force-closed"; - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[1].node.get_our_node_id()], 100000); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id_ab, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); let as_closing_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(as_closing_tx.len(), 1); @@ -3268,7 +4904,15 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, // After a timer tick a payment preimage ChannelMonitorUpdate is applied to the A<->B // ChannelMonitor (possible twice), even though the channel has since been closed. check_added_monitors(&nodes[1], 0); - let mons_added = if close_chans_before_reload { if !close_only_a { 4 } else { 3 } } else { 2 }; + let mons_added = if close_chans_before_reload { + if !close_only_a { + 4 + } else { + 3 + } + } else { + 2 + }; if hold_post_reload_mon_update { for _ in 0..mons_added { persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); @@ -3280,12 +4924,22 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, // Finally, check that B created a payment preimage transaction and close out the payment. let bs_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(bs_txn.len(), if close_chans_before_reload && !close_only_a { 2 } else { 1 }); - let bs_preimage_tx = bs_txn.iter().find(|tx| tx.input[0].previous_output.txid == as_closing_tx[0].compute_txid()).unwrap(); + let bs_preimage_tx = bs_txn + .iter() + .find(|tx| tx.input[0].previous_output.txid == as_closing_tx[0].compute_txid()) + .unwrap(); check_spends!(bs_preimage_tx, as_closing_tx[0]); if !close_chans_before_reload { check_closed_broadcast(&nodes[1], 1, true); - check_closed_event(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); } mine_transactions(&nodes[0], &[&as_closing_tx[0], bs_preimage_tx]); @@ -3303,12 +4957,18 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, reconnect_args.pending_raa.1 = true; reconnect_nodes(reconnect_args); - } // Once the blocked `ChannelMonitorUpdate` *finally* completes, the pending // `PaymentForwarded` event will finally be released. - let (ab_update_id, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_ab).unwrap().clone(); + let (ab_update_id, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id_ab) + .unwrap() + .clone(); nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_id_ab, ab_update_id); // If the A<->B channel was closed before we reload, we'll replay the claim against it on @@ -3316,8 +4976,8 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, let evs = nodes[1].node.get_and_clear_pending_events(); assert_eq!(evs.len(), if close_chans_before_reload { 2 } else { 1 }); for ev in evs { - if let Event::PaymentForwarded { .. } = ev { } - else { + if let Event::PaymentForwarded { .. } = ev { + } else { panic!(); } } @@ -3359,17 +5019,25 @@ fn test_sync_async_persist_doesnt_hang() { // Send two payments from A to B, then claim the first, marking the very last // ChannelMonitorUpdate as InProgress... - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); - let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); nodes[1].node.claim_funds(payment_preimage_1); check_added_monitors(&nodes[1], 1); expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000); let bs_updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage_1, None, false, false); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_updates.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_updates.commitment_signed, + ); check_added_monitors(&nodes[0], 1); let (as_raa, as_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -3378,7 +5046,11 @@ fn test_sync_async_persist_doesnt_hang() { nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_cs); check_added_monitors(&nodes[1], 1); - let bs_final_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_final_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_final_raa); check_added_monitors(&nodes[0], 1); @@ -3386,7 +5058,14 @@ fn test_sync_async_persist_doesnt_hang() { // Immediately complete the monitor update, but before the ChannelManager has a chance to see // the MonitorEvent::Completed, create a channel update by receiving a claim on the second // payment. - let (_, ab_update_id) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_ab).unwrap().clone(); + let (_, ab_update_id) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id_ab) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.channel_monitor_updated(chan_id_ab, ab_update_id).unwrap(); nodes[1].node.claim_funds(payment_preimage_2); @@ -3394,8 +5073,14 @@ fn test_sync_async_persist_doesnt_hang() { expect_payment_claimed!(nodes[1], payment_hash_2, 1_000_000); let bs_updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_updates.commitment_signed); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.update_fulfill_htlcs[0], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_updates.commitment_signed, + ); check_added_monitors(&nodes[0], 1); // At this point, we have completed an extra `ChannelMonitorUpdate` but the `ChannelManager` @@ -3409,12 +5094,16 @@ fn test_sync_async_persist_doesnt_hang() { // pending `MonitorEvent`s). let pending_events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(pending_events.len(), 2); - if let Event::PaymentPathSuccessful { ref payment_hash, ..} = pending_events[1] { + if let Event::PaymentPathSuccessful { ref payment_hash, .. } = pending_events[1] { assert_eq!(payment_hash.unwrap(), payment_hash_1); - } else { panic!(); } - if let Event::PaymentSent { ref payment_hash, ..} = pending_events[0] { + } else { + panic!(); + } + if let Event::PaymentSent { ref payment_hash, .. } = pending_events[0] { assert_eq!(*payment_hash, payment_hash_2); - } else { panic!(); } + } else { + panic!(); + } // Finally, complete the claiming of the second payment nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); @@ -3422,7 +5111,11 @@ fn test_sync_async_persist_doesnt_hang() { nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_cs); check_added_monitors(&nodes[1], 1); - let bs_final_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_final_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_final_raa); check_added_monitors(&nodes[0], 1); expect_payment_path_successful!(nodes[0]); @@ -3449,7 +5142,8 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) { // We complete the commitment signed dance on the B<->C channel but leave the A<->B monitor // update pending, then reload B. At that point, the final monitor update on the B<->C channel // is still pending because it can't fly until the preimage is persisted on the A<->B monitor. - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); nodes[2].node.claim_funds(payment_preimage); check_added_monitors(&nodes[2], 1); @@ -3457,7 +5151,10 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) { chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); let cs_updates = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &cs_updates.update_fulfill_htlcs[0], + ); // B generates a new monitor update for the A <-> B channel, but doesn't send the new messages // for it since the monitor update is marked in-progress. @@ -3466,7 +5163,10 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) { // Now step the Commitment Signed Dance between B and C and check that after the final RAA B // doesn't let the preimage-removing monitor update fly. - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &cs_updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &cs_updates.commitment_signed, + ); check_added_monitors(&nodes[1], 1); let (bs_raa, bs_cs) = get_revoke_commit_msgs!(nodes[1], nodes[2].node.get_our_node_id()); @@ -3475,7 +5175,11 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) { nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_cs); check_added_monitors(&nodes[2], 1); - let cs_final_raa = get_event_msg!(nodes[2], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let cs_final_raa = get_event_msg!( + nodes[2], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[2].node.get_our_node_id(), &cs_final_raa); check_added_monitors(&nodes[1], 0); @@ -3485,25 +5189,56 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) { let mon_ab = get_monitor!(nodes[1], chan_id_ab).encode(); let mon_bc = get_monitor!(nodes[1], chan_id_bc).encode(); let manager_b = nodes[1].node.encode(); - reload_node!(nodes[1], &manager_b, &[&mon_ab, &mon_bc], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + &manager_b, + &[&mon_ab, &mon_bc], + persister, + new_chain_monitor, + nodes_1_deserialized + ); let error_message = "Channel force-closed"; if close_during_reload { // Test that we still free the B<->C channel if the A<->B channel closed while we reloaded // (as learned about during the on-reload block connection). - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id_ab, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[1].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[1].node.get_our_node_id()], + 100_000, + ); let as_closing_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); mine_transaction_without_consistency_checks(&nodes[1], &as_closing_tx[0]); } - let bc_update_id = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_bc).unwrap().1; + let bc_update_id = + nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_bc).unwrap().1; let mut events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), if close_during_reload { 2 } else { 1 }); - expect_payment_forwarded(events.pop().unwrap(), &nodes[1], &nodes[0], &nodes[2], Some(1000), - None, close_during_reload, false, false); + expect_payment_forwarded( + events.pop().unwrap(), + &nodes[1], + &nodes[0], + &nodes[2], + Some(1000), + None, + close_during_reload, + false, + false, + ); if close_during_reload { match events[0] { Event::ChannelClosed { .. } => {}, @@ -3515,7 +5250,8 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) { // Once we run event processing the monitor should free, check that it was indeed the B<->C // channel which was updated. check_added_monitors(&nodes[1], if close_during_reload { 2 } else { 1 }); - let post_ev_bc_update_id = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_bc).unwrap().1; + let post_ev_bc_update_id = + nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_bc).unwrap().1; assert!(bc_update_id != post_ev_bc_update_id); // Finally, check that there's nothing left to do on B<->C reconnect and the channel operates @@ -3551,7 +5287,8 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) { // Route a payment from A, through B, to C, then claim it on C. Replay the // `update_fulfill_htlc` twice on B to check that B doesn't hang. - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); nodes[2].node.claim_funds(payment_preimage); check_added_monitors(&nodes[2], 1); @@ -3562,12 +5299,18 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) { // The first update will be on the A <-> B channel, which we optionally allow to complete. chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); } - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &cs_updates.update_fulfill_htlcs[0], + ); check_added_monitors(&nodes[1], 1); if !hold_chan_a { let bs_updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, false); expect_payment_sent!(&nodes[0], payment_preimage); } @@ -3591,8 +5334,15 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) { // With the A<->B preimage persistence not yet complete, the B<->C channel is stuck // waiting. - nodes[1].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors(&nodes[1], 0); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); @@ -3600,36 +5350,65 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) { // ...but once we complete the A<->B channel preimage persistence, the B<->C channel // unlocks and we send both peers commitment updates. - let (ab_update_id, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_ab).unwrap().clone(); - assert!(nodes[1].chain_monitor.chain_monitor.channel_monitor_updated(chan_id_ab, ab_update_id).is_ok()); + let (ab_update_id, _) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id_ab) + .unwrap() + .clone(); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .channel_monitor_updated(chan_id_ab, ab_update_id) + .is_ok()); let mut msg_events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 2); check_added_monitors(&nodes[1], 2); - let mut c_update = msg_events.iter() - .filter(|ev| matches!(ev, MessageSendEvent::UpdateHTLCs { node_id, .. } if *node_id == node_c_id)) - .cloned().collect::>(); - let a_filtermap = |ev| if let MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, updates } = ev { - if node_id == node_a_id { - Some(updates) + let mut c_update = msg_events + .iter() + .filter( + |ev| matches!(ev, MessageSendEvent::UpdateHTLCs { node_id, .. } if *node_id == node_c_id), + ) + .cloned() + .collect::>(); + let a_filtermap = |ev| { + if let MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, updates } = ev { + if node_id == node_a_id { + Some(updates) + } else { + None + } } else { None } - } else { - None }; let a_update = msg_events.drain(..).filter_map(|ev| a_filtermap(ev)).collect::>(); assert_eq!(a_update.len(), 1); assert_eq!(c_update.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &a_update[0].update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &a_update[0].update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], a_update[0].commitment_signed, false); expect_payment_sent(&nodes[0], payment_preimage, None, true, true); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false); - pass_along_path(&nodes[1], &[&nodes[2]], 1_000_000, payment_hash_2, Some(payment_secret_2), c_update.pop().unwrap(), true, None); + pass_along_path( + &nodes[1], + &[&nodes[2]], + 1_000_000, + payment_hash_2, + Some(payment_secret_2), + c_update.pop().unwrap(), + true, + None, + ); claim_payment(&nodes[1], &[&nodes[2]], payment_preimage_2); } } @@ -3657,7 +5436,8 @@ fn test_partial_claim_mon_update_compl_actions() { let (chan_4_update, _, chan_4_id, ..) = create_announced_chan_between_nodes(&nodes, 2, 3); let chan_4_scid = chan_4_update.contents.short_channel_id; - let (mut route, payment_hash, preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); + let (mut route, payment_hash, preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); let path = route.paths[0].clone(); route.paths.push(path); route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -3666,7 +5446,14 @@ fn test_partial_claim_mon_update_compl_actions() { route.paths[1].hops[0].pubkey = nodes[2].node.get_our_node_id(); route.paths[1].hops[0].short_channel_id = chan_2_scid; route.paths[1].hops[1].short_channel_id = chan_4_scid; - send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, payment_secret); + send_along_route_with_secret( + &nodes[0], + route, + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + 200_000, + payment_hash, + payment_secret, + ); // Claim along both paths, but only complete one of the two monitor updates. chanmon_cfgs[3].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); @@ -3682,12 +5469,18 @@ fn test_partial_claim_mon_update_compl_actions() { expect_payment_claimed!(&nodes[3], payment_hash, 200_000); let updates = get_htlc_update_msgs(&nodes[3], &nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[3].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[3].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); check_added_monitors(&nodes[1], 1); expect_payment_forwarded!(nodes[1], nodes[0], nodes[3], Some(1000), false, false); let _bs_updates_for_a = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[3].node.get_our_node_id(), &updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[3].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors(&nodes[1], 1); let (bs_raa, bs_cs) = get_revoke_commit_msgs(&nodes[1], &nodes[3].node.get_our_node_id()); @@ -3713,18 +5506,25 @@ fn test_partial_claim_mon_update_compl_actions() { MessageSendEvent::SendRevokeAndACK { msg, .. } => { nodes[1].node.handle_revoke_and_ack(nodes[3].node.get_our_node_id(), &msg); check_added_monitors(&nodes[1], 1); - } + }, _ => panic!(), } match remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut ds_msgs) { MessageSendEvent::UpdateHTLCs { updates, .. } => { - nodes[2].node.handle_update_fulfill_htlc(nodes[3].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[2].node.handle_update_fulfill_htlc( + nodes[3].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); check_added_monitors(&nodes[2], 1); expect_payment_forwarded!(nodes[2], nodes[0], nodes[3], Some(1000), false, false); - let _cs_updates_for_a = get_htlc_update_msgs(&nodes[2], &nodes[0].node.get_our_node_id()); + let _cs_updates_for_a = + get_htlc_update_msgs(&nodes[2], &nodes[0].node.get_our_node_id()); - nodes[2].node.handle_commitment_signed_batch_test(nodes[3].node.get_our_node_id(), &updates.commitment_signed); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[3].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors(&nodes[2], 1); }, _ => panic!(), @@ -3738,7 +5538,11 @@ fn test_partial_claim_mon_update_compl_actions() { nodes[3].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &cs_cs); check_added_monitors(&nodes[3], 1); - let ds_raa = get_event_msg!(nodes[3], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id()); + let ds_raa = get_event_msg!( + nodes[3], + MessageSendEvent::SendRevokeAndACK, + nodes[2].node.get_our_node_id() + ); nodes[2].node.handle_revoke_and_ack(nodes[3].node.get_our_node_id(), &ds_raa); check_added_monitors(&nodes[2], 1); @@ -3754,7 +5558,6 @@ fn test_partial_claim_mon_update_compl_actions() { assert!(!get_monitor!(nodes[3], chan_4_id).get_stored_preimages().contains_key(&payment_hash)); } - #[test] fn test_claim_to_closed_channel_blocks_forwarded_preimage_removal() { // One of the last features for async persistence we implemented was the correct blocking of @@ -3767,12 +5570,22 @@ fn test_claim_to_closed_channel_blocks_forwarded_preimage_removal() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // First open channels, route a payment, and force-close the first hop. - let chan_a = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000); - let chan_b = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000); - - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); - - nodes[0].node.force_close_broadcasting_latest_txn(&chan_a.2, &nodes[1].node.get_our_node_id(), String::new()).unwrap(); + let chan_a = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000); + let chan_b = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000); + + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); + + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_a.2, + &nodes[1].node.get_our_node_id(), + String::new(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let a_reason = ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }; check_closed_event!(nodes[0], 1, a_reason, [nodes[1].node.get_our_node_id()], 1000000); @@ -3783,7 +5596,13 @@ fn test_claim_to_closed_channel_blocks_forwarded_preimage_removal() { mine_transaction(&nodes[1], &as_commit_tx[0]); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); check_closed_broadcast!(nodes[1], true); // Now that B has a pending forwarded payment across it with the inbound edge on-chain, claim @@ -3794,14 +5613,20 @@ fn test_claim_to_closed_channel_blocks_forwarded_preimage_removal() { let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); check_added_monitors!(nodes[1], 1); commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false); // At this point nodes[1] has the preimage and is waiting for the `ChannelMonitorUpdate` for // channel A to hit disk. Until it does so, it shouldn't ever let the preimage dissapear from // channel B's `ChannelMonitor` - assert!(get_monitor!(nodes[1], chan_b.2).get_all_current_outbound_htlcs().iter().any(|(_, (_, preimage))| *preimage == Some(payment_preimage))); + assert!(get_monitor!(nodes[1], chan_b.2) + .get_all_current_outbound_htlcs() + .iter() + .any(|(_, (_, preimage))| *preimage == Some(payment_preimage))); // Once we complete the `ChannelMonitorUpdate` on channel A, and the `ChannelManager` processes // background events (via `get_and_clear_pending_msg_events`), the final `ChannelMonitorUpdate` @@ -3814,7 +5639,10 @@ fn test_claim_to_closed_channel_blocks_forwarded_preimage_removal() { nodes[1].chain_monitor.complete_sole_pending_chan_update(&chan_a.2); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); - assert!(!get_monitor!(nodes[1], chan_b.2).get_all_current_outbound_htlcs().iter().any(|(_, (_, preimage))| *preimage == Some(payment_preimage))); + assert!(!get_monitor!(nodes[1], chan_b.2) + .get_all_current_outbound_htlcs() + .iter() + .any(|(_, (_, preimage))| *preimage == Some(payment_preimage))); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], None, true, false); } @@ -3830,11 +5658,19 @@ fn test_claim_to_closed_channel_blocks_claimed_event() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // First open channels, route a payment, and force-close the first hop. - let chan_a = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000); + let chan_a = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000); let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); - nodes[0].node.force_close_broadcasting_latest_txn(&chan_a.2, &nodes[1].node.get_our_node_id(), String::new()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_a.2, + &nodes[1].node.get_our_node_id(), + String::new(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let a_reason = ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }; check_closed_event!(nodes[0], 1, a_reason, [nodes[1].node.get_our_node_id()], 1000000); @@ -3845,7 +5681,13 @@ fn test_claim_to_closed_channel_blocks_claimed_event() { mine_transaction(&nodes[1], &as_commit_tx[0]); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); check_closed_broadcast!(nodes[1], true); // Now that B has a pending payment with the inbound HTLC on a closed channel, claim the @@ -3926,9 +5768,24 @@ fn test_single_channel_multiple_mpp() { create_announced_chan_between_nodes_with_value(&nodes, 6, 7, 100_000, 0); create_announced_chan_between_nodes_with_value(&nodes, 7, 8, 1_000_000, 0); - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[8], 50_000_000); - - send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[7], &nodes[8]], &[&nodes[2], &nodes[7], &nodes[8]], &[&nodes[3], &nodes[7], &nodes[8]], &[&nodes[4], &nodes[7], &nodes[8]], &[&nodes[5], &nodes[7], &nodes[8]], &[&nodes[6], &nodes[7], &nodes[8]]], 50_000_000, payment_hash, payment_secret); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[8], 50_000_000); + + send_along_route_with_secret( + &nodes[0], + route, + &[ + &[&nodes[1], &nodes[7], &nodes[8]], + &[&nodes[2], &nodes[7], &nodes[8]], + &[&nodes[3], &nodes[7], &nodes[8]], + &[&nodes[4], &nodes[7], &nodes[8]], + &[&nodes[5], &nodes[7], &nodes[8]], + &[&nodes[6], &nodes[7], &nodes[8]], + ], + 50_000_000, + payment_hash, + payment_secret, + ); let (do_a_write, blocker) = std::sync::mpsc::sync_channel(0); *nodes[8].chain_monitor.write_blocker.lock().unwrap() = Some(blocker); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index d4d613967c7..828bd6fd324 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -7,75 +7,90 @@ // You may not use this file except in accordance with one or both of these // licenses. +use bitcoin::absolute::LockTime; use bitcoin::amount::Amount; +use bitcoin::consensus::encode; use bitcoin::constants::ChainHash; -use bitcoin::script::{Script, ScriptBuf, Builder, WScriptHash}; -use bitcoin::transaction::{Transaction, TxIn, TxOut}; +use bitcoin::script::{Builder, Script, ScriptBuf, WScriptHash}; use bitcoin::sighash::EcdsaSighashType; -use bitcoin::consensus::encode; -use bitcoin::absolute::LockTime; +use bitcoin::transaction::{Transaction, TxIn, TxOut}; use bitcoin::Weight; -use bitcoin::hashes::Hash; +use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256d::Hash as Sha256d; -use bitcoin::hash_types::{Txid, BlockHash}; +use bitcoin::hashes::Hash; use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE; -use bitcoin::secp256k1::{PublicKey,SecretKey}; -use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature}; +use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::{secp256k1, sighash}; -use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentPreimage, PaymentHash}; -use crate::types::features::{ChannelTypeFeatures, InitFeatures}; +use crate::chain::chaininterface::{ + fee_for_weight, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator, +}; +use crate::chain::channelmonitor::{ + ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS, +}; +use crate::chain::transaction::{OutPoint, TransactionData}; +use crate::chain::BestBlock; +use crate::events::bump_transaction::BASE_INPUT_WEIGHT; +use crate::events::{ClosureReason, Event}; +use crate::ln::chan_utils; +#[cfg(splicing)] +use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT; +use crate::ln::chan_utils::{ + commit_tx_fee_sat, get_commitment_transaction_number_obscure_factor, htlc_success_tx_weight, + htlc_timeout_tx_weight, max_htlcs, ChannelPublicKeys, ChannelTransactionParameters, + ClosingTransaction, CommitmentTransaction, CounterpartyChannelTransactionParameters, + CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HolderCommitmentTransaction, +}; +use crate::ln::channel_state::{ + ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails, + OutboundHTLCDetails, OutboundHTLCStateDetails, +}; +use crate::ln::channelmanager::{ + self, HTLCFailureMsg, HTLCSource, OpenChannelMessage, PaymentClaimDetails, PendingHTLCInfo, + PendingHTLCStatus, RAACommitmentOrder, SentHTLCId, BREAKDOWN_TIMEOUT, + MAX_LOCAL_BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::interactivetxs::{ - calculate_change_output_value, get_output_weight, AbortReason, HandleTxCompleteValue, HandleTxCompleteResult, InteractiveTxConstructor, - InteractiveTxConstructorArgs, InteractiveTxMessageSend, InteractiveTxSigningSession, InteractiveTxMessageSendResult, + calculate_change_output_value, get_output_weight, AbortReason, HandleTxCompleteResult, + HandleTxCompleteValue, InteractiveTxConstructor, InteractiveTxConstructorArgs, + InteractiveTxMessageSend, InteractiveTxMessageSendResult, InteractiveTxSigningSession, OutputOwned, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT, }; use crate::ln::msgs; use crate::ln::msgs::{ClosingSigned, ClosingSignedFeeRange, DecodeError, OnionErrorPacket}; +use crate::ln::onion_utils::{AttributionData, HTLCFailReason, LocalHTLCFailureReason}; use crate::ln::script::{self, ShutdownScript}; -use crate::ln::channel_state::{ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails}; -use crate::ln::channelmanager::{self, OpenChannelMessage, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentClaimDetails, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT}; -use crate::ln::chan_utils::{ - CounterpartyCommitmentSecrets, HTLCOutputInCommitment, htlc_success_tx_weight, - htlc_timeout_tx_weight, ChannelPublicKeys, CommitmentTransaction, - HolderCommitmentTransaction, ChannelTransactionParameters, - CounterpartyChannelTransactionParameters, max_htlcs, - get_commitment_transaction_number_obscure_factor, - ClosingTransaction, commit_tx_fee_sat, -}; -#[cfg(splicing)] -use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT; -use crate::ln::chan_utils; -use crate::ln::onion_utils::{HTLCFailReason, LocalHTLCFailureReason, AttributionData}; -use crate::chain::BestBlock; -use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator, fee_for_weight}; -use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS}; -use crate::chain::transaction::{OutPoint, TransactionData}; -use crate::sign::ecdsa::EcdsaChannelSigner; -use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient}; -use crate::events::{ClosureReason, Event}; -use crate::events::bump_transaction::BASE_INPUT_WEIGHT; +use crate::ln::types::ChannelId; use crate::routing::gossip::NodeId; -use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, TransactionU16LenLimited, Writeable, Writer}; -use crate::util::logger::{Logger, Record, WithContext}; +use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::{ChannelSigner, EntropySource, NodeSigner, Recipient, SignerProvider}; +use crate::types::features::{ChannelTypeFeatures, InitFeatures}; +use crate::types::payment::{PaymentHash, PaymentPreimage}; +use crate::util::config::{ + ChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits, LegacyChannelConfig, + MaxDustHTLCExposure, UserConfig, +}; use crate::util::errors::APIError; -use crate::util::config::{UserConfig, ChannelConfig, LegacyChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits, MaxDustHTLCExposure}; +use crate::util::logger::{Logger, Record, WithContext}; use crate::util::scid_utils::scid_from_parts; +use crate::util::ser::{ + Readable, ReadableArgs, RequiredWrapper, TransactionU16LenLimited, Writeable, Writer, +}; use alloc::collections::BTreeMap; use crate::io; use crate::prelude::*; -use core::time::Duration; -use core::{cmp,mem,fmt}; -use core::ops::Deref; +use crate::sign::type_resolver::ChannelSignerType; #[cfg(any(test, fuzzing, debug_assertions))] use crate::sync::Mutex; -use crate::sign::type_resolver::ChannelSignerType; +use core::ops::Deref; +use core::time::Duration; +use core::{cmp, fmt, mem}; use super::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint}; @@ -132,15 +147,11 @@ enum InboundHTLCResolution { // // TODO: Once this variant is removed, we should also clean up // [`MonitorRestoreUpdates::accepted_htlcs`] as the path will be unreachable. - Resolved { - pending_htlc_status: PendingHTLCStatus, - }, + Resolved { pending_htlc_status: PendingHTLCStatus }, /// Pending implies we will attempt to resolve the inbound HTLC once it has been fully committed /// to by both sides of the channel, i.e., once a `revoke_and_ack` has been processed by both /// nodes for the state update in which it was proposed. - Pending { - update_add_htlc: msgs::UpdateAddHTLC, - }, + Pending { update_add_htlc: msgs::UpdateAddHTLC }, } impl_writeable_tlv_based_enum!(InboundHTLCResolution, @@ -210,18 +221,22 @@ impl From<&InboundHTLCState> for Option { fn from(state: &InboundHTLCState) -> Option { match state { InboundHTLCState::RemoteAnnounced(_) => None, - InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => - Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToAdd), - InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => - Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToAdd), - InboundHTLCState::Committed => - Some(InboundHTLCStateDetails::Committed), - InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(_)) => - Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail), - InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed(_)) => - Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail), - InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_)) => - Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFulfill), + InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => { + Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToAdd) + }, + InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => { + Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToAdd) + }, + InboundHTLCState::Committed => Some(InboundHTLCStateDetails::Committed), + InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(_)) => { + Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail) + }, + InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed(_)) => { + Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail) + }, + InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_)) => { + Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFulfill) + }, } } } @@ -230,8 +245,12 @@ impl fmt::Display for InboundHTLCState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { InboundHTLCState::RemoteAnnounced(_) => write!(f, "RemoteAnnounced"), - InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => write!(f, "AwaitingRemoteRevokeToAnnounce"), - InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => write!(f, "AwaitingAnnouncedRemoteRevoke"), + InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => { + write!(f, "AwaitingRemoteRevokeToAnnounce") + }, + InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => { + write!(f, "AwaitingAnnouncedRemoteRevoke") + }, InboundHTLCState::Committed => write!(f, "Committed"), InboundHTLCState::LocalRemoved(_) => write!(f, "LocalRemoved"), } @@ -251,7 +270,9 @@ impl InboundHTLCState { fn preimage(&self) -> Option { match self { - InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(preimage)) => Some(*preimage), + InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(preimage)) => { + Some(*preimage) + }, _ => None, } } @@ -266,7 +287,10 @@ struct InboundHTLCOutput { } impl InboundHTLCOutput { - fn is_dust(&self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64, features: &ChannelTypeFeatures) -> bool { + fn is_dust( + &self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64, + features: &ChannelTypeFeatures, + ) -> bool { let htlc_tx_fee_sat = if features.supports_anchors_zero_fee_htlc_tx() { 0 } else { @@ -319,22 +343,25 @@ enum OutboundHTLCState { impl From<&OutboundHTLCState> for OutboundHTLCStateDetails { fn from(state: &OutboundHTLCState) -> OutboundHTLCStateDetails { match state { - OutboundHTLCState::LocalAnnounced(_) => - OutboundHTLCStateDetails::AwaitingRemoteRevokeToAdd, - OutboundHTLCState::Committed => - OutboundHTLCStateDetails::Committed, + OutboundHTLCState::LocalAnnounced(_) => { + OutboundHTLCStateDetails::AwaitingRemoteRevokeToAdd + }, + OutboundHTLCState::Committed => OutboundHTLCStateDetails::Committed, // RemoteRemoved states are ignored as the state is transient and the remote has not committed to // the state yet. - OutboundHTLCState::RemoteRemoved(_) => - OutboundHTLCStateDetails::Committed, - OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) => - OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveSuccess, - OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Failure(_)) => - OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFailure, - OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) => - OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveSuccess, - OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Failure(_)) => - OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFailure, + OutboundHTLCState::RemoteRemoved(_) => OutboundHTLCStateDetails::Committed, + OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) => { + OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveSuccess + }, + OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Failure(_)) => { + OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFailure + }, + OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) => { + OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveSuccess + }, + OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Failure(_)) => { + OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFailure + }, } } } @@ -345,8 +372,12 @@ impl fmt::Display for OutboundHTLCState { OutboundHTLCState::LocalAnnounced(_) => write!(f, "LocalAnnounced"), OutboundHTLCState::Committed => write!(f, "Committed"), OutboundHTLCState::RemoteRemoved(_) => write!(f, "RemoteRemoved"), - OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) => write!(f, "AwaitingRemoteRevokeToRemove"), - OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => write!(f, "AwaitingRemovedRemoteRevoke"), + OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) => { + write!(f, "AwaitingRemoteRevokeToRemove") + }, + OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => { + write!(f, "AwaitingRemovedRemoteRevoke") + }, } } } @@ -365,10 +396,12 @@ impl OutboundHTLCState { fn preimage(&self) -> Option { match self { OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(preimage)) - | OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(preimage)) - | OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(preimage)) => { - Some(*preimage) - }, + | OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success( + preimage, + )) + | OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success( + preimage, + )) => Some(*preimage), _ => None, } } @@ -387,7 +420,7 @@ impl<'a> Into> for &'a OutboundHTLCOutcome { fn into(self) -> Option<&'a HTLCFailReason> { match self { OutboundHTLCOutcome::Success(_) => None, - OutboundHTLCOutcome::Failure(ref r) => Some(r) + OutboundHTLCOutcome::Failure(ref r) => Some(r), } } } @@ -406,7 +439,10 @@ struct OutboundHTLCOutput { } impl OutboundHTLCOutput { - fn is_dust(&self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64, features: &ChannelTypeFeatures) -> bool { + fn is_dust( + &self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64, + features: &ChannelTypeFeatures, + ) -> bool { let htlc_tx_fee_sat = if features.supports_anchors_zero_fee_htlc_tx() { 0 } else { @@ -426,7 +462,8 @@ impl OutboundHTLCOutput { /// See AwaitingRemoteRevoke ChannelState for more info #[cfg_attr(test, derive(Clone, Debug, PartialEq))] enum HTLCUpdateAwaitingACK { - AddHTLC { // TODO: Time out if we're getting close to cltv_expiry + AddHTLC { + // TODO: Time out if we're getting close to cltv_expiry // always outbound amount_msat: u64, cltv_expiry: u32, @@ -724,7 +761,8 @@ impl ChannelState { state_flags::FUNDING_NEGOTIATED => Ok(ChannelState::FundingNegotiated), state_flags::SHUTDOWN_COMPLETE => Ok(ChannelState::ShutdownComplete), val => { - if val & state_flags::AWAITING_CHANNEL_READY == state_flags::AWAITING_CHANNEL_READY { + if val & state_flags::AWAITING_CHANNEL_READY == state_flags::AWAITING_CHANNEL_READY + { AwaitingChannelReadyFlags::from_u32(val & !state_flags::AWAITING_CHANNEL_READY) .map(|flags| ChannelState::AwaitingChannelReady(flags)) } else if val & state_flags::CHANNEL_READY == state_flags::CHANNEL_READY { @@ -743,14 +781,16 @@ impl ChannelState { match self { ChannelState::NegotiatingFunding(flags) => flags.0, ChannelState::FundingNegotiated => state_flags::FUNDING_NEGOTIATED, - ChannelState::AwaitingChannelReady(flags) => state_flags::AWAITING_CHANNEL_READY | flags.0, + ChannelState::AwaitingChannelReady(flags) => { + state_flags::AWAITING_CHANNEL_READY | flags.0 + }, ChannelState::ChannelReady(flags) => state_flags::CHANNEL_READY | flags.0, ChannelState::ShutdownComplete => state_flags::SHUTDOWN_COMPLETE, } } fn is_pre_funded_state(&self) -> bool { - matches!(self, ChannelState::NegotiatingFunding(_)|ChannelState::FundingNegotiated) + matches!(self, ChannelState::NegotiatingFunding(_) | ChannelState::FundingNegotiated) } fn is_both_sides_shutdown(&self) -> bool { @@ -759,20 +799,25 @@ impl ChannelState { fn with_funded_state_flags_mask(&self) -> FundedStateFlags { match self { - ChannelState::AwaitingChannelReady(flags) => FundedStateFlags((*flags & FundedStateFlags::ALL).0), - ChannelState::ChannelReady(flags) => FundedStateFlags((*flags & FundedStateFlags::ALL).0), + ChannelState::AwaitingChannelReady(flags) => { + FundedStateFlags((*flags & FundedStateFlags::ALL).0) + }, + ChannelState::ChannelReady(flags) => { + FundedStateFlags((*flags & FundedStateFlags::ALL).0) + }, _ => FundedStateFlags::new(), } } fn can_generate_new_commitment(&self) -> bool { match self { - ChannelState::ChannelReady(flags) => - !flags.is_set(ChannelReadyFlags::AWAITING_REMOTE_REVOKE) && - !flags.is_set(ChannelReadyFlags::LOCAL_STFU_SENT) && - !flags.is_set(ChannelReadyFlags::QUIESCENT) && - !flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) && - !flags.is_set(FundedStateFlags::PEER_DISCONNECTED.into()), + ChannelState::ChannelReady(flags) => { + !flags.is_set(ChannelReadyFlags::AWAITING_REMOTE_REVOKE) + && !flags.is_set(ChannelReadyFlags::LOCAL_STFU_SENT) + && !flags.is_set(ChannelReadyFlags::QUIESCENT) + && !flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) + && !flags.is_set(FundedStateFlags::PEER_DISCONNECTED.into()) + }, _ => { debug_assert!(false, "Can only generate new commitment within ChannelReady"); false @@ -780,17 +825,67 @@ impl ChannelState { } } - impl_state_flag!(is_peer_disconnected, set_peer_disconnected, clear_peer_disconnected, FUNDED_STATES); - impl_state_flag!(is_monitor_update_in_progress, set_monitor_update_in_progress, clear_monitor_update_in_progress, FUNDED_STATES); - impl_state_flag!(is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent, FUNDED_STATES); - impl_state_flag!(is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent, FUNDED_STATES); - impl_state_flag!(is_our_channel_ready, set_our_channel_ready, clear_our_channel_ready, AwaitingChannelReady); - impl_state_flag!(is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready, AwaitingChannelReady); - impl_state_flag!(is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch, AwaitingChannelReady); - impl_state_flag!(is_awaiting_remote_revoke, set_awaiting_remote_revoke, clear_awaiting_remote_revoke, ChannelReady); - impl_state_flag!(is_awaiting_quiescence, set_awaiting_quiescence, clear_awaiting_quiescence, ChannelReady); + impl_state_flag!( + is_peer_disconnected, + set_peer_disconnected, + clear_peer_disconnected, + FUNDED_STATES + ); + impl_state_flag!( + is_monitor_update_in_progress, + set_monitor_update_in_progress, + clear_monitor_update_in_progress, + FUNDED_STATES + ); + impl_state_flag!( + is_local_shutdown_sent, + set_local_shutdown_sent, + clear_local_shutdown_sent, + FUNDED_STATES + ); + impl_state_flag!( + is_remote_shutdown_sent, + set_remote_shutdown_sent, + clear_remote_shutdown_sent, + FUNDED_STATES + ); + impl_state_flag!( + is_our_channel_ready, + set_our_channel_ready, + clear_our_channel_ready, + AwaitingChannelReady + ); + impl_state_flag!( + is_their_channel_ready, + set_their_channel_ready, + clear_their_channel_ready, + AwaitingChannelReady + ); + impl_state_flag!( + is_waiting_for_batch, + set_waiting_for_batch, + clear_waiting_for_batch, + AwaitingChannelReady + ); + impl_state_flag!( + is_awaiting_remote_revoke, + set_awaiting_remote_revoke, + clear_awaiting_remote_revoke, + ChannelReady + ); + impl_state_flag!( + is_awaiting_quiescence, + set_awaiting_quiescence, + clear_awaiting_quiescence, + ChannelReady + ); impl_state_flag!(is_local_stfu_sent, set_local_stfu_sent, clear_local_stfu_sent, ChannelReady); - impl_state_flag!(is_remote_stfu_sent, set_remote_stfu_sent, clear_remote_stfu_sent, ChannelReady); + impl_state_flag!( + is_remote_stfu_sent, + set_remote_stfu_sent, + clear_remote_stfu_sent, + ChannelReady + ); impl_state_flag!(is_quiescent, set_quiescent, clear_quiescent, ChannelReady); } @@ -852,7 +947,9 @@ impl fmt::Debug for ChannelError { match self { &ChannelError::Ignore(ref e) => write!(f, "Ignore: {}", e), &ChannelError::Warn(ref e) => write!(f, "Warn: {}", e), - &ChannelError::WarnAndDisconnect(ref e) => write!(f, "Disconnecting with warning: {}", e), + &ChannelError::WarnAndDisconnect(ref e) => { + write!(f, "Disconnecting with warning: {}", e) + }, &ChannelError::Close((ref e, _)) => write!(f, "Close: {}", e), &ChannelError::SendError(ref e) => write!(f, "Not Found: {}", e), } @@ -877,14 +974,20 @@ impl ChannelError { } } -pub(super) struct WithChannelContext<'a, L: Deref> where L::Target: Logger { +pub(super) struct WithChannelContext<'a, L: Deref> +where + L::Target: Logger, +{ pub logger: &'a L, pub peer_id: Option, pub channel_id: Option, pub payment_hash: Option, } -impl<'a, L: Deref> Logger for WithChannelContext<'a, L> where L::Target: Logger { +impl<'a, L: Deref> Logger for WithChannelContext<'a, L> +where + L::Target: Logger, +{ fn log(&self, mut record: Record) { record.peer_id = self.peer_id; record.channel_id = self.channel_id; @@ -894,15 +997,20 @@ impl<'a, L: Deref> Logger for WithChannelContext<'a, L> where L::Target: Logger } impl<'a, 'b, L: Deref> WithChannelContext<'a, L> -where L::Target: Logger { - pub(super) fn from(logger: &'a L, context: &'b ChannelContext, payment_hash: Option) -> Self - where S::Target: SignerProvider +where + L::Target: Logger, +{ + pub(super) fn from( + logger: &'a L, context: &'b ChannelContext, payment_hash: Option, + ) -> Self + where + S::Target: SignerProvider, { WithChannelContext { logger, peer_id: Some(context.counterparty_node_id), channel_id: Some(context.channel_id), - payment_hash + payment_hash, } } } @@ -986,9 +1094,9 @@ struct CommitmentData<'a> { /// A struct gathering stats on a commitment transaction, either local or remote. struct CommitmentStats { - feerate_per_kw: u32, // the feerate of the commitment transaction - total_fee_sat: u64, // the total fee included in the transaction - total_anchors_sat: u64, // the sum of the anchors' amounts + feerate_per_kw: u32, // the feerate of the commitment transaction + total_fee_sat: u64, // the total fee included in the transaction + total_anchors_sat: u64, // the sum of the anchors' amounts broadcaster_dust_limit_sat: u64, // the broadcaster's dust limit local_balance_before_fee_anchors_msat: u64, // local balance before fees and anchors *not* considering dust limits remote_balance_before_fee_anchors_msat: u64, // remote balance before fees and anchors *not* considering dust limits @@ -1002,10 +1110,7 @@ struct HTLCCandidate { impl HTLCCandidate { fn new(amount_msat: u64, origin: HTLCInitiator) -> Self { - Self { - amount_msat, - origin, - } + Self { amount_msat, origin } } } @@ -1119,21 +1224,37 @@ enum HolderCommitmentPoint { } impl HolderCommitmentPoint { - pub fn new(signer: &ChannelSignerType, secp_ctx: &Secp256k1) -> Option - where SP::Target: SignerProvider + pub fn new( + signer: &ChannelSignerType, secp_ctx: &Secp256k1, + ) -> Option + where + SP::Target: SignerProvider, { - let current = signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER, secp_ctx).ok()?; - let next = signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, secp_ctx).ok(); + let current = + signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER, secp_ctx).ok()?; + let next = + signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, secp_ctx).ok(); let point = if let Some(next) = next { - HolderCommitmentPoint::Available { transaction_number: INITIAL_COMMITMENT_NUMBER, current, next } + HolderCommitmentPoint::Available { + transaction_number: INITIAL_COMMITMENT_NUMBER, + current, + next, + } } else { - HolderCommitmentPoint::PendingNext { transaction_number: INITIAL_COMMITMENT_NUMBER, current } + HolderCommitmentPoint::PendingNext { + transaction_number: INITIAL_COMMITMENT_NUMBER, + current, + } }; Some(point) } pub fn is_available(&self) -> bool { - if let HolderCommitmentPoint::Available { .. } = self { true } else { false } + if let HolderCommitmentPoint::Available { .. } = self { + true + } else { + false + } } pub fn transaction_number(&self) -> u64 { @@ -1162,13 +1283,26 @@ impl HolderCommitmentPoint { /// /// This method is used for the following transitions: /// - `PendingNext` -> `Available` - pub fn try_resolve_pending(&mut self, signer: &ChannelSignerType, secp_ctx: &Secp256k1, logger: &L) - where SP::Target: SignerProvider, L::Target: Logger + pub fn try_resolve_pending( + &mut self, signer: &ChannelSignerType, secp_ctx: &Secp256k1, logger: &L, + ) where + SP::Target: SignerProvider, + L::Target: Logger, { if let HolderCommitmentPoint::PendingNext { transaction_number, current } = self { - if let Ok(next) = signer.as_ref().get_per_commitment_point(*transaction_number - 1, secp_ctx) { - log_trace!(logger, "Retrieved next per-commitment point {}", *transaction_number - 1); - *self = HolderCommitmentPoint::Available { transaction_number: *transaction_number, current: *current, next }; + if let Ok(next) = + signer.as_ref().get_per_commitment_point(*transaction_number - 1, secp_ctx) + { + log_trace!( + logger, + "Retrieved next per-commitment point {}", + *transaction_number - 1 + ); + *self = HolderCommitmentPoint::Available { + transaction_number: *transaction_number, + current: *current, + next, + }; } else { log_trace!(logger, "Next per-commitment point {} is pending", transaction_number); } @@ -1191,9 +1325,11 @@ impl HolderCommitmentPoint { /// - `Available` -> `PendingNext` /// - `Available` -> `PendingNext` -> `Available` (in one fell swoop) pub fn advance( - &mut self, signer: &ChannelSignerType, secp_ctx: &Secp256k1, logger: &L + &mut self, signer: &ChannelSignerType, secp_ctx: &Secp256k1, logger: &L, ) -> Result<(), ()> - where SP::Target: SignerProvider, L::Target: Logger + where + SP::Target: SignerProvider, + L::Target: Logger, { if let HolderCommitmentPoint::Available { transaction_number, next, .. } = self { *self = HolderCommitmentPoint::PendingNext { @@ -1278,13 +1414,19 @@ impl_writeable_tlv_based!(PendingChannelMonitorUpdate, { /// A payment channel with a counterparty throughout its life-cycle, encapsulating negotiation and /// funding phases. -pub(super) struct Channel where SP::Target: SignerProvider { +pub(super) struct Channel +where + SP::Target: SignerProvider, +{ phase: ChannelPhase, } /// The `ChannelPhase` enum describes the current phase in life of a lightning channel with each of /// its variants containing an appropriate channel struct. -enum ChannelPhase where SP::Target: SignerProvider { +enum ChannelPhase +where + SP::Target: SignerProvider, +{ Undefined, UnfundedOutboundV1(OutboundV1Channel), UnfundedInboundV1(InboundV1Channel), @@ -1292,7 +1434,8 @@ enum ChannelPhase where SP::Target: SignerProvider { Funded(FundedChannel), } -impl Channel where +impl Channel +where SP::Target: SignerProvider, ::EcdsaSigner: ChannelSigner, { @@ -1350,7 +1493,10 @@ impl Channel where pub fn unfunded_context_mut(&mut self) -> Option<&mut UnfundedChannelContext> { match &mut self.phase { ChannelPhase::Undefined => unreachable!(), - ChannelPhase::Funded(_) => { debug_assert!(false); None }, + ChannelPhase::Funded(_) => { + debug_assert!(false); + None + }, ChannelPhase::UnfundedOutboundV1(chan) => Some(&mut chan.unfunded_context), ChannelPhase::UnfundedInboundV1(chan) => Some(&mut chan.unfunded_context), ChannelPhase::UnfundedV2(chan) => Some(&mut chan.unfunded_context), @@ -1387,7 +1533,10 @@ impl Channel where #[cfg(any(test, feature = "_externalize_tests"))] pub fn is_unfunded_v1(&self) -> bool { - matches!(self.phase, ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_)) + matches!( + self.phase, + ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) + ) } pub fn into_unfunded_outbound_v1(self) -> Result, Self> { @@ -1424,12 +1573,16 @@ impl Channel where pub fn signer_maybe_unblocked( &mut self, chain_hash: ChainHash, logger: &L, - ) -> Option where L::Target: Logger { + ) -> Option + where + L::Target: Logger, + { match &mut self.phase { ChannelPhase::Undefined => unreachable!(), ChannelPhase::Funded(chan) => Some(chan.signer_maybe_unblocked(logger)), ChannelPhase::UnfundedOutboundV1(chan) => { - let (open_channel, funding_created) = chan.signer_maybe_unblocked(chain_hash, logger); + let (open_channel, funding_created) = + chan.signer_maybe_unblocked(chain_hash, logger); Some(SignerResumeUpdates { commitment_update: None, revoke_and_ack: None, @@ -1467,10 +1620,15 @@ impl Channel where /// Should be called when the peer is disconnected. Returns true if the channel can be resumed /// when the peer reconnects (via [`Self::peer_connected_get_handshake`]). If not, the channel /// must be immediately closed. - pub fn peer_disconnected_is_resumable(&mut self, logger: &L) -> bool where L::Target: Logger { + pub fn peer_disconnected_is_resumable(&mut self, logger: &L) -> bool + where + L::Target: Logger, + { match &mut self.phase { ChannelPhase::Undefined => unreachable!(), - ChannelPhase::Funded(chan) => chan.remove_uncommitted_htlcs_and_mark_paused(logger).is_ok(), + ChannelPhase::Funded(chan) => { + chan.remove_uncommitted_htlcs_and_mark_paused(logger).is_ok() + }, // If we get disconnected and haven't yet committed to a funding // transaction, we can replay the `open_channel` on reconnection, so don't // bother dropping the channel here. However, if we already committed to @@ -1487,16 +1645,19 @@ impl Channel where /// send our peer to begin the channel reconnection process. pub fn peer_connected_get_handshake( &mut self, chain_hash: ChainHash, logger: &L, - ) -> ReconnectionMsg where L::Target: Logger { + ) -> ReconnectionMsg + where + L::Target: Logger, + { match &mut self.phase { ChannelPhase::Undefined => unreachable!(), - ChannelPhase::Funded(chan) => - ReconnectionMsg::Reestablish(chan.get_channel_reestablish(logger)), - ChannelPhase::UnfundedOutboundV1(chan) => { - chan.get_open_channel(chain_hash, logger) - .map(|msg| ReconnectionMsg::Open(OpenChannelMessage::V1(msg))) - .unwrap_or(ReconnectionMsg::None) + ChannelPhase::Funded(chan) => { + ReconnectionMsg::Reestablish(chan.get_channel_reestablish(logger)) }, + ChannelPhase::UnfundedOutboundV1(chan) => chan + .get_open_channel(chain_hash, logger) + .map(|msg| ReconnectionMsg::Open(OpenChannelMessage::V1(msg))) + .unwrap_or(ReconnectionMsg::None), ChannelPhase::UnfundedInboundV1(_) => { // Since unfunded inbound channel maps are cleared upon disconnecting a peer, // they are not persisted and won't be recovered after a crash. @@ -1507,7 +1668,7 @@ impl Channel where ChannelPhase::UnfundedV2(chan) => { if chan.funding.is_outbound() { ReconnectionMsg::Open(OpenChannelMessage::V2( - chan.get_open_channel_v2(chain_hash) + chan.get_open_channel_v2(chain_hash), )) } else { // Since unfunded inbound channel maps are cleared upon disconnecting a peer, @@ -1548,10 +1709,14 @@ impl Channel where } pub fn funding_signed( - &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result<(&mut FundedChannel, ChannelMonitor<::EcdsaSigner>), ChannelError> + &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, + logger: &L, + ) -> Result< + (&mut FundedChannel, ChannelMonitor<::EcdsaSigner>), + ChannelError, + > where - L::Target: Logger + L::Target: Logger, { let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined); let result = if let ChannelPhase::UnfundedOutboundV1(chan) = phase { @@ -1559,7 +1724,10 @@ impl Channel where let logger = WithChannelContext::from(logger, &chan.context, None); match chan.funding_signed(msg, best_block, signer_provider, &&logger) { Ok((chan, monitor)) => { - debug_assert!(matches!(chan.context.channel_state, ChannelState::AwaitingChannelReady(_))); + debug_assert!(matches!( + chan.context.channel_state, + ChannelState::AwaitingChannelReady(_) + )); self.phase = ChannelPhase::Funded(chan); Ok(monitor) }, @@ -1571,7 +1739,9 @@ impl Channel where } } else { self.phase = phase; - Err(ChannelError::SendError("Failed to find corresponding UnfundedOutboundV1 channel".to_owned())) + Err(ChannelError::SendError( + "Failed to find corresponding UnfundedOutboundV1 channel".to_owned(), + )) }; debug_assert!(!matches!(self.phase, ChannelPhase::Undefined)); @@ -1579,10 +1749,10 @@ impl Channel where } pub fn funding_tx_constructed( - &mut self, signing_session: InteractiveTxSigningSession, logger: &L + &mut self, signing_session: InteractiveTxSigningSession, logger: &L, ) -> Result<(msgs::CommitmentSigned, Option), ChannelError> where - L::Target: Logger + L::Target: Logger, { if let ChannelPhase::UnfundedV2(chan) = &mut self.phase { let logger = WithChannelContext::from(logger, &chan.context, None); @@ -1592,16 +1762,25 @@ impl Channel where } } - pub fn force_shutdown(&mut self, should_broadcast: bool, closure_reason: ClosureReason) -> ShutdownResult { + pub fn force_shutdown( + &mut self, should_broadcast: bool, closure_reason: ClosureReason, + ) -> ShutdownResult { let (funding, context) = self.funding_and_context_mut(); context.force_shutdown(funding, should_broadcast, closure_reason) } pub fn commitment_signed( - &mut self, msg: &msgs::CommitmentSigned, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result<(Option::EcdsaSigner>>, Option), ChannelError> + &mut self, msg: &msgs::CommitmentSigned, best_block: BestBlock, signer_provider: &SP, + logger: &L, + ) -> Result< + ( + Option::EcdsaSigner>>, + Option, + ), + ChannelError, + > where - L::Target: Logger + L::Target: Logger, { let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined); match phase { @@ -1614,7 +1793,7 @@ impl Channel where return Err( ChannelError::close( format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}", channel_id))); - } + }, }; let mut funded_channel = FundedChannel { funding: chan.funding, @@ -1626,7 +1805,8 @@ impl Channel where #[cfg(splicing)] pending_splice: None, }; - let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger) + let res = funded_channel + .commitment_signed_initial_v2(msg, best_block, signer_provider, logger) .map(|monitor| (Some(monitor), None)) // TODO: Change to `inspect_err` when MSRV is high enough. .map_err(|err| { @@ -1638,15 +1818,19 @@ impl Channel where res }, ChannelPhase::Funded(mut funded_channel) => { - let res = funded_channel.commitment_signed(msg, logger).map(|monitor_update_opt| (None, monitor_update_opt)); + let res = funded_channel + .commitment_signed(msg, logger) + .map(|monitor_update_opt| (None, monitor_update_opt)); self.phase = ChannelPhase::Funded(funded_channel); res }, _ => { self.phase = phase; debug_assert!(!matches!(self.phase, ChannelPhase::Undefined)); - Err(ChannelError::close("Got a commitment_signed message for an unfunded V1 channel!".into())) - } + Err(ChannelError::close( + "Got a commitment_signed message for an unfunded V1 channel!".into(), + )) + }, } } @@ -1663,9 +1847,15 @@ impl Channel where match &self.phase { ChannelPhase::Undefined => unreachable!(), ChannelPhase::Funded(chan) => chan.get_available_balances(fee_estimator), - ChannelPhase::UnfundedOutboundV1(chan) => chan.context.get_available_balances_for_scope(&chan.funding, fee_estimator), - ChannelPhase::UnfundedInboundV1(chan) => chan.context.get_available_balances_for_scope(&chan.funding, fee_estimator), - ChannelPhase::UnfundedV2(chan) => chan.context.get_available_balances_for_scope(&chan.funding, fee_estimator), + ChannelPhase::UnfundedOutboundV1(chan) => { + chan.context.get_available_balances_for_scope(&chan.funding, fee_estimator) + }, + ChannelPhase::UnfundedInboundV1(chan) => { + chan.context.get_available_balances_for_scope(&chan.funding, fee_estimator) + }, + ChannelPhase::UnfundedV2(chan) => { + chan.context.get_available_balances_for_scope(&chan.funding, fee_estimator) + }, } } } @@ -1676,9 +1866,7 @@ where ::EcdsaSigner: ChannelSigner, { fn from(channel: OutboundV1Channel) -> Self { - Channel { - phase: ChannelPhase::UnfundedOutboundV1(channel), - } + Channel { phase: ChannelPhase::UnfundedOutboundV1(channel) } } } @@ -1688,9 +1876,7 @@ where ::EcdsaSigner: ChannelSigner, { fn from(channel: InboundV1Channel) -> Self { - Channel { - phase: ChannelPhase::UnfundedInboundV1(channel), - } + Channel { phase: ChannelPhase::UnfundedInboundV1(channel) } } } @@ -1700,9 +1886,7 @@ where ::EcdsaSigner: ChannelSigner, { fn from(channel: PendingV2Channel) -> Self { - Channel { - phase: ChannelPhase::UnfundedV2(channel), - } + Channel { phase: ChannelPhase::UnfundedV2(channel) } } } @@ -1712,9 +1896,7 @@ where ::EcdsaSigner: ChannelSigner, { fn from(channel: FundedChannel) -> Self { - Channel { - phase: ChannelPhase::Funded(channel), - } + Channel { phase: ChannelPhase::Funded(channel) } } } @@ -1742,7 +1924,9 @@ impl UnfundedChannelContext { } fn transaction_number(&self) -> u64 { - self.holder_commitment_point.as_ref().map(|point| point.transaction_number()) + self.holder_commitment_point + .as_ref() + .map(|point| point.transaction_number()) .unwrap_or(INITIAL_COMMITMENT_NUMBER) } } @@ -1816,7 +2000,9 @@ impl Readable for FundingScope { Ok(Self { value_to_self_msat: value_to_self_msat.0.unwrap(), counterparty_selected_channel_reserve_satoshis, - holder_selected_channel_reserve_satoshis: holder_selected_channel_reserve_satoshis.0.unwrap(), + holder_selected_channel_reserve_satoshis: holder_selected_channel_reserve_satoshis + .0 + .unwrap(), #[cfg(debug_assertions)] holder_max_commitment_tx_output: Mutex::new((0, 0)), #[cfg(debug_assertions)] @@ -1841,7 +2027,10 @@ impl FundingScope { } pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option) { - (self.holder_selected_channel_reserve_satoshis, self.counterparty_selected_channel_reserve_satoshis) + ( + self.holder_selected_channel_reserve_satoshis, + self.counterparty_selected_channel_reserve_satoshis, + ) } fn get_htlc_maximum_msat(&self, party_max_htlc_value_in_flight_msat: u64) -> Option { @@ -1849,7 +2038,7 @@ impl FundingScope { let holder_reserve = self.holder_selected_channel_reserve_satoshis; cmp::min( (self.get_value_satoshis() - counterparty_reserve - holder_reserve) * 1000, - party_max_htlc_value_in_flight_msat + party_max_htlc_value_in_flight_msat, ) }) } @@ -1873,8 +2062,10 @@ impl FundingScope { } pub fn get_counterparty_selected_contest_delay(&self) -> Option { - self.channel_transaction_parameters.counterparty_parameters - .as_ref().map(|params| params.selected_contest_delay) + self.channel_transaction_parameters + .counterparty_parameters + .as_ref() + .map(|params| params.selected_contest_delay) } fn get_counterparty_pubkeys(&self) -> &ChannelPublicKeys { @@ -1905,7 +2096,10 @@ struct PendingSplice { } /// Contains everything about the channel including state, and various flags. -pub(super) struct ChannelContext where SP::Target: SignerProvider { +pub(super) struct ChannelContext +where + SP::Target: SignerProvider, +{ config: LegacyChannelConfig, // Track the previous `ChannelConfig` so that we can continue forwarding HTLCs that were @@ -1947,7 +2141,6 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction // generation start at 0 and count up...this simplifies some parts of implementation at the // cost of others, but should really just be changed. - cur_counterparty_commitment_transaction_number: u64, pending_inbound_htlcs: Vec, pending_outbound_htlcs: Vec, @@ -2083,9 +2276,9 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { counterparty_htlc_minimum_msat: u64, holder_htlc_minimum_msat: u64, - #[cfg(any(test, feature="_test_utils"))] + #[cfg(any(test, feature = "_test_utils"))] pub counterparty_max_accepted_htlcs: u16, - #[cfg(not(any(test, feature="_test_utils")))] + #[cfg(not(any(test, feature = "_test_utils")))] counterparty_max_accepted_htlcs: u16, holder_max_accepted_htlcs: u16, minimum_depth: Option, @@ -2202,7 +2395,10 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { /// A channel struct implementing this trait can receive an initial counterparty commitment /// transaction signature. -trait InitialRemoteCommitmentReceiver where SP::Target: SignerProvider { +trait InitialRemoteCommitmentReceiver +where + SP::Target: SignerProvider, +{ fn context(&self) -> &ChannelContext; fn context_mut(&mut self) -> &mut ChannelContext; @@ -2214,35 +2410,59 @@ trait InitialRemoteCommitmentReceiver where SP::Target: SignerProvide fn received_msg(&self) -> &'static str; fn check_counterparty_commitment_signature( - &self, sig: &Signature, holder_commitment_point: &HolderCommitmentPoint, logger: &L - ) -> Result where L::Target: Logger { + &self, sig: &Signature, holder_commitment_point: &HolderCommitmentPoint, logger: &L, + ) -> Result + where + L::Target: Logger, + { let funding_script = self.funding().get_funding_redeemscript(); - let commitment_data = self.context().build_commitment_transaction(self.funding(), - holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), - true, false, logger); + let commitment_data = self.context().build_commitment_transaction( + self.funding(), + holder_commitment_point.transaction_number(), + &holder_commitment_point.current_point(), + true, + false, + logger, + ); let initial_commitment_tx = commitment_data.tx; let trusted_tx = initial_commitment_tx.trust(); let initial_commitment_bitcoin_tx = trusted_tx.built_transaction(); - let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.funding().get_value_satoshis()); + let sighash = initial_commitment_bitcoin_tx + .get_sighash_all(&funding_script, self.funding().get_value_satoshis()); // They sign the holder commitment transaction... log_trace!(logger, "Checking {} tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.", self.received_msg(), log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.funding().counterparty_funding_pubkey().serialize()), encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), &self.context().channel_id()); - secp_check!(self.context().secp_ctx.verify_ecdsa(&sighash, sig, self.funding().counterparty_funding_pubkey()), format!("Invalid {} signature from peer", self.received_msg())); + secp_check!( + self.context().secp_ctx.verify_ecdsa( + &sighash, + sig, + self.funding().counterparty_funding_pubkey() + ), + format!("Invalid {} signature from peer", self.received_msg()) + ); Ok(initial_commitment_tx) } fn initial_commitment_signed( - &mut self, channel_id: ChannelId, counterparty_signature: Signature, holder_commitment_point: &mut HolderCommitmentPoint, - best_block: BestBlock, signer_provider: &SP, logger: &L, - ) -> Result<(ChannelMonitor<::EcdsaSigner>, CommitmentTransaction), ChannelError> + &mut self, channel_id: ChannelId, counterparty_signature: Signature, + holder_commitment_point: &mut HolderCommitmentPoint, best_block: BestBlock, + signer_provider: &SP, logger: &L, + ) -> Result< + (ChannelMonitor<::EcdsaSigner>, CommitmentTransaction), + ChannelError, + > where - L::Target: Logger + L::Target: Logger, { - let initial_commitment_tx = match self.check_counterparty_commitment_signature(&counterparty_signature, holder_commitment_point, logger) { + let initial_commitment_tx = match self.check_counterparty_commitment_signature( + &counterparty_signature, + holder_commitment_point, + logger, + ) { Ok(res) => res, Err(ChannelError::Close(e)) => { // TODO(dual_funding): Update for V2 established channels. @@ -2254,29 +2474,47 @@ trait InitialRemoteCommitmentReceiver where SP::Target: SignerProvide Err(e) => { // The only error we know how to handle is ChannelError::Close, so we fall over here // to make sure we don't continue with an inconsistent state. - panic!("unexpected error type from check_counterparty_commitment_signature {:?}", e); - } + panic!( + "unexpected error type from check_counterparty_commitment_signature {:?}", + e + ); + }, }; let context = self.context(); - let commitment_data = context.build_commitment_transaction(self.funding(), + let commitment_data = context.build_commitment_transaction( + self.funding(), context.cur_counterparty_commitment_transaction_number, - &context.counterparty_cur_commitment_point.unwrap(), false, false, logger); + &context.counterparty_cur_commitment_point.unwrap(), + false, + false, + logger, + ); let counterparty_initial_commitment_tx = commitment_data.tx; let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust(); let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction(); - log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}", - &context.channel_id(), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); + log_trace!( + logger, + "Initial counterparty tx for channel {} is: txid {} tx {}", + &context.channel_id(), + counterparty_initial_bitcoin_tx.txid, + encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction) + ); let holder_commitment_tx = HolderCommitmentTransaction::new( initial_commitment_tx, counterparty_signature, Vec::new(), &self.funding().get_holder_pubkeys().funding_pubkey, - &self.funding().counterparty_funding_pubkey() + &self.funding().counterparty_funding_pubkey(), ); - if context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()).is_err() { + if context + .holder_signer + .as_ref() + .validate_holder_commitment(&holder_commitment_tx, Vec::new()) + .is_err() + { return Err(ChannelError::close("Failed to validate our commitment".to_owned())); } @@ -2287,34 +2525,59 @@ trait InitialRemoteCommitmentReceiver where SP::Target: SignerProvide assert!(!context.channel_state.is_monitor_update_in_progress()); // We have not had any monitor(s) yet to fail update! if context.is_batch_funding() { - context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH); + context.channel_state = + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH); } else { - context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); + context.channel_state = + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); } - if holder_commitment_point.advance(&context.holder_signer, &context.secp_ctx, logger).is_err() { + if holder_commitment_point + .advance(&context.holder_signer, &context.secp_ctx, logger) + .is_err() + { // We only fail to advance our commitment point/number if we're currently // waiting for our signer to unblock and provide a commitment point. // We cannot send accept_channel/open_channel before this has occurred, so if we // err here by the time we receive funding_created/funding_signed, something has gone wrong. - debug_assert!(false, "We should be ready to advance our commitment point by the time we receive {}", self.received_msg()); - return Err(ChannelError::close("Failed to advance holder commitment point".to_owned())); + debug_assert!( + false, + "We should be ready to advance our commitment point by the time we receive {}", + self.received_msg() + ); + return Err(ChannelError::close( + "Failed to advance holder commitment point".to_owned(), + )); } let context = self.context(); let funding = self.funding(); - let obscure_factor = get_commitment_transaction_number_obscure_factor(&funding.get_holder_pubkeys().payment_point, &funding.get_counterparty_pubkeys().payment_point, funding.is_outbound()); - let shutdown_script = context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); + let obscure_factor = get_commitment_transaction_number_obscure_factor( + &funding.get_holder_pubkeys().payment_point, + &funding.get_counterparty_pubkeys().payment_point, + funding.is_outbound(), + ); + let shutdown_script = + context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); let monitor_signer = signer_provider.derive_channel_signer(context.channel_keys_id); // TODO(RBF): When implementing RBF, the funding_txo passed here must only update // ChannelMonitorImp::first_confirmed_funding_txo during channel establishment, not splicing let channel_monitor = ChannelMonitor::new( - context.secp_ctx.clone(), monitor_signer, shutdown_script, - funding.get_holder_selected_contest_delay(), &context.destination_script, - &funding.channel_transaction_parameters, funding.is_outbound(), obscure_factor, - holder_commitment_tx, best_block, context.counterparty_node_id, context.channel_id(), + context.secp_ctx.clone(), + monitor_signer, + shutdown_script, + funding.get_holder_selected_contest_delay(), + &context.destination_script, + &funding.channel_transaction_parameters, + funding.is_outbound(), + obscure_factor, + holder_commitment_tx, + best_block, + context.counterparty_node_id, + context.channel_id(), ); channel_monitor.provide_initial_counterparty_commitment_tx( - counterparty_initial_commitment_tx.clone(), logger, + counterparty_initial_commitment_tx.clone(), + logger, ); self.context_mut().cur_counterparty_commitment_transaction_number -= 1; @@ -2323,7 +2586,10 @@ trait InitialRemoteCommitmentReceiver where SP::Target: SignerProvide } } -impl InitialRemoteCommitmentReceiver for OutboundV1Channel where SP::Target: SignerProvider { +impl InitialRemoteCommitmentReceiver for OutboundV1Channel +where + SP::Target: SignerProvider, +{ fn context(&self) -> &ChannelContext { &self.context } @@ -2345,7 +2611,10 @@ impl InitialRemoteCommitmentReceiver for OutboundV1Channel wh } } -impl InitialRemoteCommitmentReceiver for InboundV1Channel where SP::Target: SignerProvider { +impl InitialRemoteCommitmentReceiver for InboundV1Channel +where + SP::Target: SignerProvider, +{ fn context(&self) -> &ChannelContext { &self.context } @@ -2367,7 +2636,10 @@ impl InitialRemoteCommitmentReceiver for InboundV1Channel whe } } -impl InitialRemoteCommitmentReceiver for FundedChannel where SP::Target: SignerProvider { +impl InitialRemoteCommitmentReceiver for FundedChannel +where + SP::Target: SignerProvider, +{ fn context(&self) -> &ChannelContext { &self.context } @@ -2389,7 +2661,10 @@ impl InitialRemoteCommitmentReceiver for FundedChannel where } } -impl PendingV2Channel where SP::Target: SignerProvider { +impl PendingV2Channel +where + SP::Target: SignerProvider, +{ /// Prepare and start interactive transaction negotiation. /// `change_destination_opt` - Optional destination for optional change; if None, /// default destination address is used. @@ -2399,7 +2674,8 @@ impl PendingV2Channel where SP::Target: SignerProvider { &mut self, signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey, change_destination_opt: Option, ) -> Result, AbortReason> - where ES::Target: EntropySource + where + ES::Target: EntropySource, { debug_assert!(matches!(self.context.channel_state, ChannelState::NegotiatingFunding(_))); debug_assert!(self.interactive_tx_constructor.is_none()); @@ -2421,11 +2697,10 @@ impl PendingV2Channel where SP::Target: SignerProvider { }; if self.funding.is_outbound() { - funding_outputs.push( - OutputOwned::Shared(SharedOwnedOutput::new( - shared_funding_output, self.dual_funding_context.our_funding_satoshis, - )) - ); + funding_outputs.push(OutputOwned::Shared(SharedOwnedOutput::new( + shared_funding_output, + self.dual_funding_context.our_funding_satoshis, + ))); } else { let TxOut { value, script_pubkey } = shared_funding_output; expected_remote_shared_funding_output = Some((script_pubkey, value.to_sat())); @@ -2435,22 +2710,26 @@ impl PendingV2Channel where SP::Target: SignerProvider { let change_script = if let Some(script) = change_destination_opt { script } else { - signer_provider.get_destination_script(self.context.channel_keys_id) + signer_provider + .get_destination_script(self.context.channel_keys_id) .map_err(|_err| AbortReason::InternalError("Error getting destination script"))? }; let change_value_opt = calculate_change_output_value( - self.funding.is_outbound(), self.dual_funding_context.our_funding_satoshis, - &funding_inputs, &funding_outputs, + self.funding.is_outbound(), + self.dual_funding_context.our_funding_satoshis, + &funding_inputs, + &funding_outputs, self.dual_funding_context.funding_feerate_sat_per_1000_weight, change_script.minimal_non_dust().to_sat(), )?; if let Some(change_value) = change_value_opt { - let mut change_output = TxOut { - value: Amount::from_sat(change_value), - script_pubkey: change_script, - }; + let mut change_output = + TxOut { value: Amount::from_sat(change_value), script_pubkey: change_script }; let change_output_weight = get_output_weight(&change_output.script_pubkey).to_wu(); - let change_output_fee = fee_for_weight(self.dual_funding_context.funding_feerate_sat_per_1000_weight, change_output_weight); + let change_output_fee = fee_for_weight( + self.dual_funding_context.funding_feerate_sat_per_1000_weight, + change_output_weight, + ); let change_value_decreased_with_fee = change_value.saturating_sub(change_output_fee); // Check dust limit again if change_value_decreased_with_fee > self.context.holder_dust_limit_satoshis { @@ -2481,44 +2760,50 @@ impl PendingV2Channel where SP::Target: SignerProvider { pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult { InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor { - Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_input(msg).map_err( - |reason| reason.into_tx_abort_msg(self.context.channel_id())), + Some(ref mut tx_constructor) => tx_constructor + .handle_tx_add_input(msg) + .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())), None => Err(msgs::TxAbort { channel_id: self.context.channel_id(), - data: b"No interactive transaction negotiation in progress".to_vec() + data: b"No interactive transaction negotiation in progress".to_vec(), }), }) } - pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult { + pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput) -> InteractiveTxMessageSendResult { InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor { - Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_output(msg).map_err( - |reason| reason.into_tx_abort_msg(self.context.channel_id())), + Some(ref mut tx_constructor) => tx_constructor + .handle_tx_add_output(msg) + .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())), None => Err(msgs::TxAbort { channel_id: self.context.channel_id(), - data: b"No interactive transaction negotiation in progress".to_vec() + data: b"No interactive transaction negotiation in progress".to_vec(), }), }) } - pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput)-> InteractiveTxMessageSendResult { + pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput) -> InteractiveTxMessageSendResult { InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor { - Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_input(msg).map_err( - |reason| reason.into_tx_abort_msg(self.context.channel_id())), + Some(ref mut tx_constructor) => tx_constructor + .handle_tx_remove_input(msg) + .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())), None => Err(msgs::TxAbort { channel_id: self.context.channel_id(), - data: b"No interactive transaction negotiation in progress".to_vec() + data: b"No interactive transaction negotiation in progress".to_vec(), }), }) } - pub fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput)-> InteractiveTxMessageSendResult { + pub fn tx_remove_output( + &mut self, msg: &msgs::TxRemoveOutput, + ) -> InteractiveTxMessageSendResult { InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor { - Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_output(msg).map_err( - |reason| reason.into_tx_abort_msg(self.context.channel_id())), + Some(ref mut tx_constructor) => tx_constructor + .handle_tx_remove_output(msg) + .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())), None => Err(msgs::TxAbort { channel_id: self.context.channel_id(), - data: b"No interactive transaction negotiation in progress".to_vec() + data: b"No interactive transaction negotiation in progress".to_vec(), }), }) } @@ -2539,7 +2824,7 @@ impl PendingV2Channel where SP::Target: SignerProvider { Ok(tx_complete) => tx_complete, Err(reason) => { return HandleTxCompleteResult(Err(reason.into_tx_abort_msg(msg.channel_id))) - } + }, }; if let HandleTxCompleteValue::SendTxComplete(_, ref signing_session) = tx_complete { @@ -2550,10 +2835,10 @@ impl PendingV2Channel where SP::Target: SignerProvider { } pub fn funding_tx_constructed( - &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L + &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L, ) -> Result<(msgs::CommitmentSigned, Option), ChannelError> where - L::Target: Logger + L::Target: Logger, { let our_funding_satoshis = self.dual_funding_context.our_funding_satoshis; let transaction_number = self.unfunded_context.transaction_number(); @@ -2561,13 +2846,14 @@ impl PendingV2Channel where SP::Target: SignerProvider { let mut output_index = None; let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh(); for (idx, outp) in signing_session.unsigned_tx.outputs().enumerate() { - if outp.script_pubkey() == &expected_spk && outp.value() == self.funding.get_value_satoshis() { + if outp.script_pubkey() == &expected_spk + && outp.value() == self.funding.get_value_satoshis() + { if output_index.is_some() { - return Err(ChannelError::Close( - ( - "Multiple outputs matched the expected script and value".to_owned(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, - ))); + return Err(ChannelError::Close(( + "Multiple outputs matched the expected script and value".to_owned(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + ))); } output_index = Some(idx as u16); } @@ -2575,37 +2861,44 @@ impl PendingV2Channel where SP::Target: SignerProvider { let outpoint = if let Some(output_index) = output_index { OutPoint { txid: signing_session.unsigned_tx.compute_txid(), index: output_index } } else { - return Err(ChannelError::Close( - ( - "No output matched the funding script_pubkey".to_owned(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, - ))); + return Err(ChannelError::Close(( + "No output matched the funding script_pubkey".to_owned(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + ))); }; self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint); - self.context.assert_no_commitment_advancement(transaction_number, "initial commitment_signed"); + self.context + .assert_no_commitment_advancement(transaction_number, "initial commitment_signed"); let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger); let commitment_signed = match commitment_signed { Ok(commitment_signed) => { - self.funding.funding_transaction = Some(signing_session.unsigned_tx.build_unsigned_tx()); + self.funding.funding_transaction = + Some(signing_session.unsigned_tx.build_unsigned_tx()); commitment_signed }, Err(err) => { self.funding.channel_transaction_parameters.funding_outpoint = None; - return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }))); + return Err(ChannelError::Close(( + err.to_string(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + ))); }, }; let funding_ready_for_sig_event = if signing_session.local_inputs_count() == 0 { debug_assert_eq!(our_funding_satoshis, 0); - if signing_session.provide_holder_witnesses(self.context.channel_id, Vec::new()).is_err() { + if signing_session + .provide_holder_witnesses(self.context.channel_id, Vec::new()) + .is_err() + { debug_assert!( false, "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found", ); return Err(ChannelError::Close(( "V2 channel rejected due to sender error".into(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) } + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, ))); } None @@ -2630,7 +2923,7 @@ impl PendingV2Channel where SP::Target: SignerProvider { ); return Err(ChannelError::Close(( "V2 channel rejected due to sender error".into(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) } + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, ))); }; @@ -2644,36 +2937,36 @@ impl PendingV2Channel where SP::Target: SignerProvider { } } -impl ChannelContext where SP::Target: SignerProvider { +impl ChannelContext +where + SP::Target: SignerProvider, +{ fn new_for_inbound_channel<'a, ES: Deref, F: Deref, L: Deref>( - fee_estimator: &'a LowerBoundedFeeEstimator, - entropy_source: &'a ES, - signer_provider: &'a SP, - counterparty_node_id: PublicKey, - their_features: &'a InitFeatures, - user_id: u128, - config: &'a UserConfig, - current_chain_height: u32, - logger: &'a L, - is_0conf: bool, - our_funding_satoshis: u64, - counterparty_pubkeys: ChannelPublicKeys, - channel_type: ChannelTypeFeatures, - holder_selected_channel_reserve_satoshis: u64, - msg_channel_reserve_satoshis: u64, - msg_push_msat: u64, + fee_estimator: &'a LowerBoundedFeeEstimator, entropy_source: &'a ES, + signer_provider: &'a SP, counterparty_node_id: PublicKey, their_features: &'a InitFeatures, + user_id: u128, config: &'a UserConfig, current_chain_height: u32, logger: &'a L, + is_0conf: bool, our_funding_satoshis: u64, counterparty_pubkeys: ChannelPublicKeys, + channel_type: ChannelTypeFeatures, holder_selected_channel_reserve_satoshis: u64, + msg_channel_reserve_satoshis: u64, msg_push_msat: u64, open_channel_fields: msgs::CommonOpenChannelFields, ) -> Result<(FundingScope, ChannelContext), ChannelError> - where - ES::Target: EntropySource, - F::Target: FeeEstimator, - L::Target: Logger, - SP::Target: SignerProvider, + where + ES::Target: EntropySource, + F::Target: FeeEstimator, + L::Target: Logger, + SP::Target: SignerProvider, { - let logger = WithContext::from(logger, Some(counterparty_node_id), Some(open_channel_fields.temporary_channel_id), None); - let announce_for_forwarding = if (open_channel_fields.channel_flags & 1) == 1 { true } else { false }; + let logger = WithContext::from( + logger, + Some(counterparty_node_id), + Some(open_channel_fields.temporary_channel_id), + None, + ); + let announce_for_forwarding = + if (open_channel_fields.channel_flags & 1) == 1 { true } else { false }; - let channel_value_satoshis = our_funding_satoshis.saturating_add(open_channel_fields.funding_satoshis); + let channel_value_satoshis = + our_funding_satoshis.saturating_add(open_channel_fields.funding_satoshis); let channel_keys_id = signer_provider.generate_channel_keys_id(true, user_id); let holder_signer = signer_provider.derive_channel_signer(channel_keys_id); @@ -2690,55 +2983,113 @@ impl ChannelContext where SP::Target: SignerProvider { open_channel_fields.funding_satoshis, our_funding_satoshis))); } if channel_value_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS { - return Err(ChannelError::close(format!("Funding must be smaller than the total bitcoin supply. It was {}", channel_value_satoshis))); + return Err(ChannelError::close(format!( + "Funding must be smaller than the total bitcoin supply. It was {}", + channel_value_satoshis + ))); } if msg_channel_reserve_satoshis > channel_value_satoshis { return Err(ChannelError::close(format!("Bogus channel_reserve_satoshis ({}). Must be no greater than channel_value_satoshis: {}", msg_channel_reserve_satoshis, channel_value_satoshis))); } - let full_channel_value_msat = (channel_value_satoshis - msg_channel_reserve_satoshis) * 1000; + let full_channel_value_msat = + (channel_value_satoshis - msg_channel_reserve_satoshis) * 1000; if msg_push_msat > full_channel_value_msat { - return Err(ChannelError::close(format!("push_msat {} was larger than channel amount minus reserve ({})", msg_push_msat, full_channel_value_msat))); + return Err(ChannelError::close(format!( + "push_msat {} was larger than channel amount minus reserve ({})", + msg_push_msat, full_channel_value_msat + ))); } if open_channel_fields.dust_limit_satoshis > channel_value_satoshis { return Err(ChannelError::close(format!("dust_limit_satoshis {} was larger than channel_value_satoshis {}. Peer never wants payout outputs?", open_channel_fields.dust_limit_satoshis, channel_value_satoshis))); } if open_channel_fields.htlc_minimum_msat >= full_channel_value_msat { - return Err(ChannelError::close(format!("Minimum htlc value ({}) was larger than full channel value ({})", open_channel_fields.htlc_minimum_msat, full_channel_value_msat))); + return Err(ChannelError::close(format!( + "Minimum htlc value ({}) was larger than full channel value ({})", + open_channel_fields.htlc_minimum_msat, full_channel_value_msat + ))); } - FundedChannel::::check_remote_fee(&channel_type, fee_estimator, open_channel_fields.commitment_feerate_sat_per_1000_weight, None, &&logger)?; + FundedChannel::::check_remote_fee( + &channel_type, + fee_estimator, + open_channel_fields.commitment_feerate_sat_per_1000_weight, + None, + &&logger, + )?; - let max_counterparty_selected_contest_delay = u16::min(config.channel_handshake_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); + let max_counterparty_selected_contest_delay = u16::min( + config.channel_handshake_limits.their_to_self_delay, + MAX_LOCAL_BREAKDOWN_TIMEOUT, + ); if open_channel_fields.to_self_delay > max_counterparty_selected_contest_delay { return Err(ChannelError::close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_counterparty_selected_contest_delay, open_channel_fields.to_self_delay))); } if open_channel_fields.max_accepted_htlcs < 1 { - return Err(ChannelError::close("0 max_accepted_htlcs makes for a useless channel".to_owned())); + return Err(ChannelError::close( + "0 max_accepted_htlcs makes for a useless channel".to_owned(), + )); } if open_channel_fields.max_accepted_htlcs > max_htlcs(&channel_type) { - return Err(ChannelError::close(format!("max_accepted_htlcs was {}. It must not be larger than {}", open_channel_fields.max_accepted_htlcs, max_htlcs(&channel_type)))); + return Err(ChannelError::close(format!( + "max_accepted_htlcs was {}. It must not be larger than {}", + open_channel_fields.max_accepted_htlcs, + max_htlcs(&channel_type) + ))); } // Now check against optional parameters as set by config... if channel_value_satoshis < config.channel_handshake_limits.min_funding_satoshis { - return Err(ChannelError::close(format!("Funding satoshis ({}) is less than the user specified limit ({})", channel_value_satoshis, config.channel_handshake_limits.min_funding_satoshis))); + return Err(ChannelError::close(format!( + "Funding satoshis ({}) is less than the user specified limit ({})", + channel_value_satoshis, config.channel_handshake_limits.min_funding_satoshis + ))); } - if open_channel_fields.htlc_minimum_msat > config.channel_handshake_limits.max_htlc_minimum_msat { - return Err(ChannelError::close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", open_channel_fields.htlc_minimum_msat, config.channel_handshake_limits.max_htlc_minimum_msat))); + if open_channel_fields.htlc_minimum_msat + > config.channel_handshake_limits.max_htlc_minimum_msat + { + return Err(ChannelError::close(format!( + "htlc_minimum_msat ({}) is higher than the user specified limit ({})", + open_channel_fields.htlc_minimum_msat, + config.channel_handshake_limits.max_htlc_minimum_msat + ))); } - if open_channel_fields.max_htlc_value_in_flight_msat < config.channel_handshake_limits.min_max_htlc_value_in_flight_msat { - return Err(ChannelError::close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", open_channel_fields.max_htlc_value_in_flight_msat, config.channel_handshake_limits.min_max_htlc_value_in_flight_msat))); + if open_channel_fields.max_htlc_value_in_flight_msat + < config.channel_handshake_limits.min_max_htlc_value_in_flight_msat + { + return Err(ChannelError::close(format!( + "max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", + open_channel_fields.max_htlc_value_in_flight_msat, + config.channel_handshake_limits.min_max_htlc_value_in_flight_msat + ))); } - if msg_channel_reserve_satoshis > config.channel_handshake_limits.max_channel_reserve_satoshis { - return Err(ChannelError::close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg_channel_reserve_satoshis, config.channel_handshake_limits.max_channel_reserve_satoshis))); + if msg_channel_reserve_satoshis + > config.channel_handshake_limits.max_channel_reserve_satoshis + { + return Err(ChannelError::close(format!( + "channel_reserve_satoshis ({}) is higher than the user specified limit ({})", + msg_channel_reserve_satoshis, + config.channel_handshake_limits.max_channel_reserve_satoshis + ))); } - if open_channel_fields.max_accepted_htlcs < config.channel_handshake_limits.min_max_accepted_htlcs { - return Err(ChannelError::close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", open_channel_fields.max_accepted_htlcs, config.channel_handshake_limits.min_max_accepted_htlcs))); + if open_channel_fields.max_accepted_htlcs + < config.channel_handshake_limits.min_max_accepted_htlcs + { + return Err(ChannelError::close(format!( + "max_accepted_htlcs ({}) is less than the user specified limit ({})", + open_channel_fields.max_accepted_htlcs, + config.channel_handshake_limits.min_max_accepted_htlcs + ))); } if open_channel_fields.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", open_channel_fields.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS))); + return Err(ChannelError::close(format!( + "dust_limit_satoshis ({}) is less than the implementation limit ({})", + open_channel_fields.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS + ))); } - if open_channel_fields.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", open_channel_fields.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS))); + if open_channel_fields.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::close(format!( + "dust_limit_satoshis ({}) is greater than the implementation limit ({})", + open_channel_fields.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS + ))); } // Convert things into internal flags and prep our state: @@ -2773,19 +3124,28 @@ impl ChannelContext where SP::Target: SignerProvider { 0 }; let funders_amount_msat = open_channel_fields.funding_satoshis * 1000 - msg_push_msat; - let commitment_tx_fee = commit_tx_fee_sat(open_channel_fields.commitment_feerate_sat_per_1000_weight, MIN_AFFORDABLE_HTLC_COUNT, &channel_type); + let commitment_tx_fee = commit_tx_fee_sat( + open_channel_fields.commitment_feerate_sat_per_1000_weight, + MIN_AFFORDABLE_HTLC_COUNT, + &channel_type, + ); if (funders_amount_msat / 1000).saturating_sub(anchor_outputs_value) < commitment_tx_fee { return Err(ChannelError::close(format!("Funding amount ({} sats) can't even pay fee for initial commitment transaction fee of {} sats.", (funders_amount_msat / 1000).saturating_sub(anchor_outputs_value), commitment_tx_fee))); } - let to_remote_satoshis = funders_amount_msat / 1000 - commitment_tx_fee - anchor_outputs_value; + let to_remote_satoshis = + funders_amount_msat / 1000 - commitment_tx_fee - anchor_outputs_value; // While it's reasonable for us to not meet the channel reserve initially (if they don't // want to push much to us), our counterparty should always have more than our reserve. if to_remote_satoshis < holder_selected_channel_reserve_satoshis { - return Err(ChannelError::close("Insufficient funding amount for initial reserve".to_owned())); + return Err(ChannelError::close( + "Insufficient funding amount for initial reserve".to_owned(), + )); } - let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { + let counterparty_shutdown_scriptpubkey = if their_features + .supports_upfront_shutdown_script() + { match &open_channel_fields.shutdown_scriptpubkey { &Some(ref script) => { // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything @@ -2793,7 +3153,7 @@ impl ChannelContext where SP::Target: SignerProvider { None } else { if !script::is_bolt2_compliant(&script, their_features) { - return Err(ChannelError::close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script))) + return Err(ChannelError::close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script))); } Some(script.clone()) } @@ -2801,26 +3161,40 @@ impl ChannelContext where SP::Target: SignerProvider { // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel &None => { return Err(ChannelError::close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out".to_owned())); - } + }, } - } else { None }; + } else { + None + }; - let shutdown_scriptpubkey = if config.channel_handshake_config.commit_upfront_shutdown_pubkey { - match signer_provider.get_shutdown_scriptpubkey() { - Ok(scriptpubkey) => Some(scriptpubkey), - Err(_) => return Err(ChannelError::close("Failed to get upfront shutdown scriptpubkey".to_owned())), - } - } else { None }; + let shutdown_scriptpubkey = + if config.channel_handshake_config.commit_upfront_shutdown_pubkey { + match signer_provider.get_shutdown_scriptpubkey() { + Ok(scriptpubkey) => Some(scriptpubkey), + Err(_) => { + return Err(ChannelError::close( + "Failed to get upfront shutdown scriptpubkey".to_owned(), + )) + }, + } + } else { + None + }; if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey { if !shutdown_scriptpubkey.is_compatible(&their_features) { - return Err(ChannelError::close(format!("Provided a scriptpubkey format not accepted by peer: {}", shutdown_scriptpubkey))); + return Err(ChannelError::close(format!( + "Provided a scriptpubkey format not accepted by peer: {}", + shutdown_scriptpubkey + ))); } } let destination_script = match signer_provider.get_destination_script(channel_keys_id) { Ok(script) => script, - Err(_) => return Err(ChannelError::close("Failed to get destination script".to_owned())), + Err(_) => { + return Err(ChannelError::close("Failed to get destination script".to_owned())) + }, }; let mut secp_ctx = Secp256k1::new(); @@ -2844,9 +3218,15 @@ impl ChannelContext where SP::Target: SignerProvider { holder_selected_channel_reserve_satoshis, #[cfg(debug_assertions)] - holder_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))), + holder_max_commitment_tx_output: Mutex::new(( + value_to_self_msat, + (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat), + )), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))), + counterparty_max_commitment_tx_output: Mutex::new(( + value_to_self_msat, + (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat), + )), #[cfg(any(test, fuzzing))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), @@ -2874,7 +3254,9 @@ impl ChannelContext where SP::Target: SignerProvider { config: LegacyChannelConfig { options: config.channel_config.clone(), announce_for_forwarding, - commit_upfront_shutdown_pubkey: config.channel_handshake_config.commit_upfront_shutdown_pubkey, + commit_upfront_shutdown_pubkey: config + .channel_handshake_config + .commit_upfront_shutdown_pubkey, }, prev_config: None, @@ -2884,7 +3266,7 @@ impl ChannelContext where SP::Target: SignerProvider { temporary_channel_id: Some(open_channel_fields.temporary_channel_id), channel_id: open_channel_fields.temporary_channel_id, channel_state: ChannelState::NegotiatingFunding( - NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT + NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT, ), announcement_sigs_state: AnnouncementSigsState::NotSent, secp_ctx, @@ -2938,12 +3320,26 @@ impl ChannelContext where SP::Target: SignerProvider { feerate_per_kw: open_channel_fields.commitment_feerate_sat_per_1000_weight, counterparty_dust_limit_satoshis: open_channel_fields.dust_limit_satoshis, holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS, - counterparty_max_htlc_value_in_flight_msat: cmp::min(open_channel_fields.max_htlc_value_in_flight_msat, channel_value_satoshis * 1000), - holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &config.channel_handshake_config), + counterparty_max_htlc_value_in_flight_msat: cmp::min( + open_channel_fields.max_htlc_value_in_flight_msat, + channel_value_satoshis * 1000, + ), + holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat( + channel_value_satoshis, + &config.channel_handshake_config, + ), counterparty_htlc_minimum_msat: open_channel_fields.htlc_minimum_msat, - holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 { 1 } else { config.channel_handshake_config.our_htlc_minimum_msat }, + holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 + { + 1 + } else { + config.channel_handshake_config.our_htlc_minimum_msat + }, counterparty_max_accepted_htlcs: open_channel_fields.max_accepted_htlcs, - holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, max_htlcs(&channel_type)), + holder_max_accepted_htlcs: cmp::min( + config.channel_handshake_config.our_max_accepted_htlcs, + max_htlcs(&channel_type), + ), minimum_depth, counterparty_forwarding_info: None, @@ -2990,43 +3386,51 @@ impl ChannelContext where SP::Target: SignerProvider { } fn new_for_outbound_channel<'a, ES: Deref, F: Deref, L: Deref>( - fee_estimator: &'a LowerBoundedFeeEstimator, - entropy_source: &'a ES, - signer_provider: &'a SP, - counterparty_node_id: PublicKey, - their_features: &'a InitFeatures, - funding_satoshis: u64, - push_msat: u64, - user_id: u128, - config: &'a UserConfig, - current_chain_height: u32, - outbound_scid_alias: u64, + fee_estimator: &'a LowerBoundedFeeEstimator, entropy_source: &'a ES, + signer_provider: &'a SP, counterparty_node_id: PublicKey, their_features: &'a InitFeatures, + funding_satoshis: u64, push_msat: u64, user_id: u128, config: &'a UserConfig, + current_chain_height: u32, outbound_scid_alias: u64, temporary_channel_id_fn: Option ChannelId>, - holder_selected_channel_reserve_satoshis: u64, - channel_keys_id: [u8; 32], - holder_signer: ::EcdsaSigner, - _logger: L, + holder_selected_channel_reserve_satoshis: u64, channel_keys_id: [u8; 32], + holder_signer: ::EcdsaSigner, _logger: L, ) -> Result<(FundingScope, ChannelContext), APIError> - where - ES::Target: EntropySource, - F::Target: FeeEstimator, - SP::Target: SignerProvider, - L::Target: Logger, + where + ES::Target: EntropySource, + F::Target: FeeEstimator, + SP::Target: SignerProvider, + L::Target: Logger, { // This will be updated with the counterparty contribution if this is a dual-funded channel let channel_value_satoshis = funding_satoshis; let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay; - if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO { - return Err(APIError::APIMisuseError{err: format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis)}); + if !their_features.supports_wumbo() + && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO + { + return Err(APIError::APIMisuseError { + err: format!( + "funding_value must not exceed {}, it was {}", + MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis + ), + }); } if channel_value_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS { - return Err(APIError::APIMisuseError{err: format!("funding_value must be smaller than the total bitcoin supply, it was {}", channel_value_satoshis)}); + return Err(APIError::APIMisuseError { + err: format!( + "funding_value must be smaller than the total bitcoin supply, it was {}", + channel_value_satoshis + ), + }); } let channel_value_msat = channel_value_satoshis * 1000; if push_msat > channel_value_msat { - return Err(APIError::APIMisuseError { err: format!("Push value ({}) was larger than channel_value ({})", push_msat, channel_value_msat) }); + return Err(APIError::APIMisuseError { + err: format!( + "Push value ({}) was larger than channel_value ({})", + push_msat, channel_value_msat + ), + }); } if holder_selected_contest_delay < BREAKDOWN_TIMEOUT { return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)}); @@ -3034,17 +3438,20 @@ impl ChannelContext where SP::Target: SignerProvider { let channel_type = get_initial_channel_type(&config, their_features); debug_assert!(!channel_type.supports_any_optional_bits()); - debug_assert!(!channel_type.requires_unknown_bits_from(&channelmanager::provided_channel_type_features(&config))); + debug_assert!(!channel_type + .requires_unknown_bits_from(&channelmanager::provided_channel_type_features(&config))); - let (commitment_conf_target, anchor_outputs_value_msat) = if channel_type.supports_anchors_zero_fee_htlc_tx() { - (ConfirmationTarget::AnchorChannelFee, ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000) - } else { - (ConfirmationTarget::NonAnchorChannelFee, 0) - }; + let (commitment_conf_target, anchor_outputs_value_msat) = + if channel_type.supports_anchors_zero_fee_htlc_tx() { + (ConfirmationTarget::AnchorChannelFee, ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000) + } else { + (ConfirmationTarget::NonAnchorChannelFee, 0) + }; let commitment_feerate = fee_estimator.bounded_sat_per_1000_weight(commitment_conf_target); let value_to_self_msat = channel_value_satoshis * 1000 - push_msat; - let commitment_tx_fee = commit_tx_fee_sat(commitment_feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) * 1000; + let commitment_tx_fee = + commit_tx_fee_sat(commitment_feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) * 1000; if value_to_self_msat.saturating_sub(anchor_outputs_value_msat) < commitment_tx_fee { return Err(APIError::APIMisuseError{ err: format!("Funding amount ({}) can't even pay fee for initial commitment transaction fee of {}.", value_to_self_msat / 1000, commitment_tx_fee / 1000) }); } @@ -3052,26 +3459,40 @@ impl ChannelContext where SP::Target: SignerProvider { let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes()); - let shutdown_scriptpubkey = if config.channel_handshake_config.commit_upfront_shutdown_pubkey { - match signer_provider.get_shutdown_scriptpubkey() { - Ok(scriptpubkey) => Some(scriptpubkey), - Err(_) => return Err(APIError::ChannelUnavailable { err: "Failed to get shutdown scriptpubkey".to_owned()}), - } - } else { None }; + let shutdown_scriptpubkey = + if config.channel_handshake_config.commit_upfront_shutdown_pubkey { + match signer_provider.get_shutdown_scriptpubkey() { + Ok(scriptpubkey) => Some(scriptpubkey), + Err(_) => { + return Err(APIError::ChannelUnavailable { + err: "Failed to get shutdown scriptpubkey".to_owned(), + }) + }, + } + } else { + None + }; if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey { if !shutdown_scriptpubkey.is_compatible(&their_features) { - return Err(APIError::IncompatibleShutdownScript { script: shutdown_scriptpubkey.clone() }); + return Err(APIError::IncompatibleShutdownScript { + script: shutdown_scriptpubkey.clone(), + }); } } let destination_script = match signer_provider.get_destination_script(channel_keys_id) { Ok(script) => script, - Err(_) => return Err(APIError::ChannelUnavailable { err: "Failed to get destination script".to_owned()}), + Err(_) => { + return Err(APIError::ChannelUnavailable { + err: "Failed to get destination script".to_owned(), + }) + }, }; let pubkeys = holder_signer.pubkeys(None, &secp_ctx); - let temporary_channel_id = temporary_channel_id_fn.map(|f| f(&pubkeys)) + let temporary_channel_id = temporary_channel_id_fn + .map(|f| f(&pubkeys)) .unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source)); let funding = FundingScope { @@ -3082,9 +3503,15 @@ impl ChannelContext where SP::Target: SignerProvider { // We'll add our counterparty's `funding_satoshis` to these max commitment output assertions // when we receive `accept_channel2`. #[cfg(debug_assertions)] - holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + holder_max_commitment_tx_output: Mutex::new(( + channel_value_satoshis * 1000 - push_msat, + push_msat, + )), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), + counterparty_max_commitment_tx_output: Mutex::new(( + channel_value_satoshis * 1000 - push_msat, + push_msat, + )), #[cfg(any(test, fuzzing))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), @@ -3110,7 +3537,9 @@ impl ChannelContext where SP::Target: SignerProvider { config: LegacyChannelConfig { options: config.channel_config.clone(), announce_for_forwarding: config.channel_handshake_config.announce_for_forwarding, - commit_upfront_shutdown_pubkey: config.channel_handshake_config.commit_upfront_shutdown_pubkey, + commit_upfront_shutdown_pubkey: config + .channel_handshake_config + .commit_upfront_shutdown_pubkey, }, prev_config: None, @@ -3175,11 +3604,22 @@ impl ChannelContext where SP::Target: SignerProvider { counterparty_max_htlc_value_in_flight_msat: 0, // We'll adjust this to include our counterparty's `funding_satoshis` when we // receive `accept_channel2`. - holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &config.channel_handshake_config), + holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat( + channel_value_satoshis, + &config.channel_handshake_config, + ), counterparty_htlc_minimum_msat: 0, - holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 { 1 } else { config.channel_handshake_config.our_htlc_minimum_msat }, + holder_htlc_minimum_msat: if config.channel_handshake_config.our_htlc_minimum_msat == 0 + { + 1 + } else { + config.channel_handshake_config.our_htlc_minimum_msat + }, counterparty_max_accepted_htlcs: 0, - holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, max_htlcs(&channel_type)), + holder_max_accepted_htlcs: cmp::min( + config.channel_handshake_config.our_max_accepted_htlcs, + max_htlcs(&channel_type), + ), minimum_depth: None, // Filled in in accept_channel counterparty_forwarding_info: None, @@ -3243,31 +3683,41 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns true if we've ever received a message from the remote end for this Channel pub fn have_received_message(&self) -> bool { - self.channel_state > ChannelState::NegotiatingFunding(NegotiatingFundingFlags::OUR_INIT_SENT) + self.channel_state + > ChannelState::NegotiatingFunding(NegotiatingFundingFlags::OUR_INIT_SENT) } /// Returns true if this channel is fully established and not known to be closing. /// Allowed in any state (including after shutdown) pub fn is_usable(&self) -> bool { - matches!(self.channel_state, ChannelState::ChannelReady(_)) && - !self.channel_state.is_local_shutdown_sent() && - !self.channel_state.is_remote_shutdown_sent() && - !self.monitor_pending_channel_ready + matches!(self.channel_state, ChannelState::ChannelReady(_)) + && !self.channel_state.is_local_shutdown_sent() + && !self.channel_state.is_remote_shutdown_sent() + && !self.monitor_pending_channel_ready } /// shutdown state returns the state of the channel in its various stages of shutdown pub fn shutdown_state(&self) -> ChannelShutdownState { match self.channel_state { - ChannelState::AwaitingChannelReady(_)|ChannelState::ChannelReady(_) => - if self.channel_state.is_local_shutdown_sent() && !self.channel_state.is_remote_shutdown_sent() { + ChannelState::AwaitingChannelReady(_) | ChannelState::ChannelReady(_) => { + if self.channel_state.is_local_shutdown_sent() + && !self.channel_state.is_remote_shutdown_sent() + { ChannelShutdownState::ShutdownInitiated - } else if (self.channel_state.is_local_shutdown_sent() || self.channel_state.is_remote_shutdown_sent()) && !self.closing_negotiation_ready() { + } else if (self.channel_state.is_local_shutdown_sent() + || self.channel_state.is_remote_shutdown_sent()) + && !self.closing_negotiation_ready() + { ChannelShutdownState::ResolvingHTLCs - } else if (self.channel_state.is_local_shutdown_sent() || self.channel_state.is_remote_shutdown_sent()) && self.closing_negotiation_ready() { + } else if (self.channel_state.is_local_shutdown_sent() + || self.channel_state.is_remote_shutdown_sent()) + && self.closing_negotiation_ready() + { ChannelShutdownState::NegotiatingClosingFee } else { ChannelShutdownState::NotShuttingDown - }, + } + }, ChannelState::ShutdownComplete => ChannelShutdownState::ShutdownComplete, _ => ChannelShutdownState::NotShuttingDown, } @@ -3275,16 +3725,22 @@ impl ChannelContext where SP::Target: SignerProvider { fn closing_negotiation_ready(&self) -> bool { let is_ready_to_close = match self.channel_state { - ChannelState::AwaitingChannelReady(flags) => - flags & FundedStateFlags::ALL == FundedStateFlags::LOCAL_SHUTDOWN_SENT | FundedStateFlags::REMOTE_SHUTDOWN_SENT, - ChannelState::ChannelReady(flags) => - flags == FundedStateFlags::LOCAL_SHUTDOWN_SENT | FundedStateFlags::REMOTE_SHUTDOWN_SENT, + ChannelState::AwaitingChannelReady(flags) => { + flags & FundedStateFlags::ALL + == FundedStateFlags::LOCAL_SHUTDOWN_SENT + | FundedStateFlags::REMOTE_SHUTDOWN_SENT + }, + ChannelState::ChannelReady(flags) => { + flags + == FundedStateFlags::LOCAL_SHUTDOWN_SENT + | FundedStateFlags::REMOTE_SHUTDOWN_SENT + }, _ => false, }; - self.pending_inbound_htlcs.is_empty() && - self.pending_outbound_htlcs.is_empty() && - self.pending_update_fee.is_none() && - is_ready_to_close + self.pending_inbound_htlcs.is_empty() + && self.pending_outbound_htlcs.is_empty() + && self.pending_update_fee.is_none() + && is_ready_to_close } /// Returns true if this channel is currently available for use. This is a superset of @@ -3296,10 +3752,11 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns false if our last broadcasted channel_update message has the "channel disabled" bit set pub fn is_enabled(&self) -> bool { - self.is_usable() && match self.channel_update_status { - ChannelUpdateStatus::Enabled | ChannelUpdateStatus::DisabledStaged(_) => true, - ChannelUpdateStatus::Disabled | ChannelUpdateStatus::EnabledStaged(_) => false, - } + self.is_usable() + && match self.channel_update_status { + ChannelUpdateStatus::Enabled | ChannelUpdateStatus::DisabledStaged(_) => true, + ChannelUpdateStatus::Disabled | ChannelUpdateStatus::EnabledStaged(_) => false, + } } /// Checks whether the channel has any HTLC additions, HTLC removals, or fee updates that have @@ -3337,30 +3794,27 @@ impl ChannelContext where SP::Target: SignerProvider { return true; } - if self.pending_inbound_htlcs.iter() - .any(|htlc| match htlc.state { - InboundHTLCState::Committed => false, - // An HTLC removal from the local node is pending on the remote commitment. - InboundHTLCState::LocalRemoved(_) => true, - // An HTLC add from the remote node is pending on the local commitment. - InboundHTLCState::RemoteAnnounced(_) - | InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) - | InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => true, - }) - { + if self.pending_inbound_htlcs.iter().any(|htlc| match htlc.state { + InboundHTLCState::Committed => false, + // An HTLC removal from the local node is pending on the remote commitment. + InboundHTLCState::LocalRemoved(_) => true, + // An HTLC add from the remote node is pending on the local commitment. + InboundHTLCState::RemoteAnnounced(_) + | InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) + | InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => true, + }) { return true; } - self.pending_outbound_htlcs.iter() - .any(|htlc| match htlc.state { - OutboundHTLCState::Committed => false, - // An HTLC add from the local node is pending on the remote commitment. - OutboundHTLCState::LocalAnnounced(_) => true, - // An HTLC removal from the remote node is pending on the local commitment. - OutboundHTLCState::RemoteRemoved(_) - | OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) - | OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => true, - }) + self.pending_outbound_htlcs.iter().any(|htlc| match htlc.state { + OutboundHTLCState::Committed => false, + // An HTLC add from the local node is pending on the remote commitment. + OutboundHTLCState::LocalAnnounced(_) => true, + // An HTLC removal from the remote node is pending on the local commitment. + OutboundHTLCState::RemoteRemoved(_) + | OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) + | OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => true, + }) } // Public utilities: @@ -3406,7 +3860,7 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns the holder signer for this channel. #[cfg(any(test, feature = "_test_utils"))] pub fn get_mut_signer(&mut self) -> &mut ChannelSignerType { - return &mut self.holder_signer + return &mut self.holder_signer; } /// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0, @@ -3434,84 +3888,145 @@ impl ChannelContext where SP::Target: SignerProvider { their_features: &InitFeatures, common_fields: &msgs::CommonAcceptChannelFields, channel_reserve_satoshis: u64, ) -> Result<(), ChannelError> { - let peer_limits = if let Some(ref limits) = self.inbound_handshake_limits_override { limits } else { default_limits }; + let peer_limits = if let Some(ref limits) = self.inbound_handshake_limits_override { + limits + } else { + default_limits + }; // Check sanity of message fields: if !funding.is_outbound() { - return Err(ChannelError::close("Got an accept_channel message from an inbound peer".to_owned())); + return Err(ChannelError::close( + "Got an accept_channel message from an inbound peer".to_owned(), + )); } - if !matches!(self.channel_state, ChannelState::NegotiatingFunding(flags) if flags == NegotiatingFundingFlags::OUR_INIT_SENT) { - return Err(ChannelError::close("Got an accept_channel message at a strange time".to_owned())); + if !matches!(self.channel_state, ChannelState::NegotiatingFunding(flags) if flags == NegotiatingFundingFlags::OUR_INIT_SENT) + { + return Err(ChannelError::close( + "Got an accept_channel message at a strange time".to_owned(), + )); } if let Some(ty) = &common_fields.channel_type { if ty != funding.get_channel_type() { - return Err(ChannelError::close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned())); + return Err(ChannelError::close( + "Channel Type in accept_channel didn't match the one sent in open_channel." + .to_owned(), + )); } } else if their_features.supports_channel_type() { // Assume they've accepted the channel type as they said they understand it. } else { let channel_type = ChannelTypeFeatures::from_init(&their_features); if channel_type != ChannelTypeFeatures::only_static_remote_key() { - return Err(ChannelError::close("Only static_remote_key is supported for non-negotiated channel types".to_owned())); + return Err(ChannelError::close( + "Only static_remote_key is supported for non-negotiated channel types" + .to_owned(), + )); } funding.channel_transaction_parameters.channel_type_features = channel_type; } if common_fields.dust_limit_satoshis > 21000000 * 100000000 { - return Err(ChannelError::close(format!("Peer never wants payout outputs? dust_limit_satoshis was {}", common_fields.dust_limit_satoshis))); + return Err(ChannelError::close(format!( + "Peer never wants payout outputs? dust_limit_satoshis was {}", + common_fields.dust_limit_satoshis + ))); } if channel_reserve_satoshis > funding.get_value_satoshis() { - return Err(ChannelError::close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", channel_reserve_satoshis, funding.get_value_satoshis()))); + return Err(ChannelError::close(format!( + "Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", + channel_reserve_satoshis, + funding.get_value_satoshis() + ))); } if common_fields.dust_limit_satoshis > funding.holder_selected_channel_reserve_satoshis { - return Err(ChannelError::close(format!("Dust limit ({}) is bigger than our channel reserve ({})", common_fields.dust_limit_satoshis, funding.holder_selected_channel_reserve_satoshis))); + return Err(ChannelError::close(format!( + "Dust limit ({}) is bigger than our channel reserve ({})", + common_fields.dust_limit_satoshis, funding.holder_selected_channel_reserve_satoshis + ))); } - if channel_reserve_satoshis > funding.get_value_satoshis() - funding.holder_selected_channel_reserve_satoshis { + if channel_reserve_satoshis + > funding.get_value_satoshis() - funding.holder_selected_channel_reserve_satoshis + { return Err(ChannelError::close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than channel value minus our reserve ({})", channel_reserve_satoshis, funding.get_value_satoshis() - funding.holder_selected_channel_reserve_satoshis))); } - let full_channel_value_msat = (funding.get_value_satoshis() - channel_reserve_satoshis) * 1000; + let full_channel_value_msat = + (funding.get_value_satoshis() - channel_reserve_satoshis) * 1000; if common_fields.htlc_minimum_msat >= full_channel_value_msat { - return Err(ChannelError::close(format!("Minimum htlc value ({}) is full channel value ({})", common_fields.htlc_minimum_msat, full_channel_value_msat))); + return Err(ChannelError::close(format!( + "Minimum htlc value ({}) is full channel value ({})", + common_fields.htlc_minimum_msat, full_channel_value_msat + ))); } - let max_delay_acceptable = u16::min(peer_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); + let max_delay_acceptable = + u16::min(peer_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); if common_fields.to_self_delay > max_delay_acceptable { return Err(ChannelError::close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_delay_acceptable, common_fields.to_self_delay))); } if common_fields.max_accepted_htlcs < 1 { - return Err(ChannelError::close("0 max_accepted_htlcs makes for a useless channel".to_owned())); + return Err(ChannelError::close( + "0 max_accepted_htlcs makes for a useless channel".to_owned(), + )); } let channel_type = funding.get_channel_type(); if common_fields.max_accepted_htlcs > max_htlcs(channel_type) { - return Err(ChannelError::close(format!("max_accepted_htlcs was {}. It must not be larger than {}", common_fields.max_accepted_htlcs, max_htlcs(channel_type)))); + return Err(ChannelError::close(format!( + "max_accepted_htlcs was {}. It must not be larger than {}", + common_fields.max_accepted_htlcs, + max_htlcs(channel_type) + ))); } // Now check against optional parameters as set by config... if common_fields.htlc_minimum_msat > peer_limits.max_htlc_minimum_msat { - return Err(ChannelError::close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", common_fields.htlc_minimum_msat, peer_limits.max_htlc_minimum_msat))); + return Err(ChannelError::close(format!( + "htlc_minimum_msat ({}) is higher than the user specified limit ({})", + common_fields.htlc_minimum_msat, peer_limits.max_htlc_minimum_msat + ))); } - if common_fields.max_htlc_value_in_flight_msat < peer_limits.min_max_htlc_value_in_flight_msat { - return Err(ChannelError::close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", common_fields.max_htlc_value_in_flight_msat, peer_limits.min_max_htlc_value_in_flight_msat))); + if common_fields.max_htlc_value_in_flight_msat + < peer_limits.min_max_htlc_value_in_flight_msat + { + return Err(ChannelError::close(format!( + "max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", + common_fields.max_htlc_value_in_flight_msat, + peer_limits.min_max_htlc_value_in_flight_msat + ))); } if channel_reserve_satoshis > peer_limits.max_channel_reserve_satoshis { - return Err(ChannelError::close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", channel_reserve_satoshis, peer_limits.max_channel_reserve_satoshis))); + return Err(ChannelError::close(format!( + "channel_reserve_satoshis ({}) is higher than the user specified limit ({})", + channel_reserve_satoshis, peer_limits.max_channel_reserve_satoshis + ))); } if common_fields.max_accepted_htlcs < peer_limits.min_max_accepted_htlcs { - return Err(ChannelError::close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", common_fields.max_accepted_htlcs, peer_limits.min_max_accepted_htlcs))); + return Err(ChannelError::close(format!( + "max_accepted_htlcs ({}) is less than the user specified limit ({})", + common_fields.max_accepted_htlcs, peer_limits.min_max_accepted_htlcs + ))); } if common_fields.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", common_fields.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS))); + return Err(ChannelError::close(format!( + "dust_limit_satoshis ({}) is less than the implementation limit ({})", + common_fields.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS + ))); } if common_fields.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", common_fields.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS))); + return Err(ChannelError::close(format!( + "dust_limit_satoshis ({}) is greater than the implementation limit ({})", + common_fields.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS + ))); } if common_fields.minimum_depth > peer_limits.max_minimum_depth { return Err(ChannelError::close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, common_fields.minimum_depth))); } - let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { + let counterparty_shutdown_scriptpubkey = if their_features + .supports_upfront_shutdown_script() + { match &common_fields.shutdown_scriptpubkey { &Some(ref script) => { // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything @@ -3527,12 +4042,17 @@ impl ChannelContext where SP::Target: SignerProvider { // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel &None => { return Err(ChannelError::close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out".to_owned())); - } + }, } - } else { None }; + } else { + None + }; self.counterparty_dust_limit_satoshis = common_fields.dust_limit_satoshis; - self.counterparty_max_htlc_value_in_flight_msat = cmp::min(common_fields.max_htlc_value_in_flight_msat, funding.get_value_satoshis() * 1000); + self.counterparty_max_htlc_value_in_flight_msat = cmp::min( + common_fields.max_htlc_value_in_flight_msat, + funding.get_value_satoshis() * 1000, + ); funding.counterparty_selected_channel_reserve_satoshis = Some(channel_reserve_satoshis); self.counterparty_htlc_minimum_msat = common_fields.htlc_minimum_msat; self.counterparty_max_accepted_htlcs = common_fields.max_accepted_htlcs; @@ -3547,20 +4067,23 @@ impl ChannelContext where SP::Target: SignerProvider { funding_pubkey: common_fields.funding_pubkey, revocation_basepoint: RevocationBasepoint::from(common_fields.revocation_basepoint), payment_point: common_fields.payment_basepoint, - delayed_payment_basepoint: DelayedPaymentBasepoint::from(common_fields.delayed_payment_basepoint), - htlc_basepoint: HtlcBasepoint::from(common_fields.htlc_basepoint) + delayed_payment_basepoint: DelayedPaymentBasepoint::from( + common_fields.delayed_payment_basepoint, + ), + htlc_basepoint: HtlcBasepoint::from(common_fields.htlc_basepoint), }; - funding.channel_transaction_parameters.counterparty_parameters = Some(CounterpartyChannelTransactionParameters { - selected_contest_delay: common_fields.to_self_delay, - pubkeys: counterparty_pubkeys, - }); + funding.channel_transaction_parameters.counterparty_parameters = + Some(CounterpartyChannelTransactionParameters { + selected_contest_delay: common_fields.to_self_delay, + pubkeys: counterparty_pubkeys, + }); self.counterparty_cur_commitment_point = Some(common_fields.first_per_commitment_point); self.counterparty_shutdown_scriptpubkey = counterparty_shutdown_scriptpubkey; self.channel_state = ChannelState::NegotiatingFunding( - NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT + NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT, ); self.inbound_handshake_limits_override = None; // We're done enforcing limits on our peer's handshake now. @@ -3619,9 +4142,12 @@ impl ChannelContext where SP::Target: SignerProvider { cmp::max(self.config.options.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA) } - fn get_dust_exposure_limiting_feerate(&self, - fee_estimator: &LowerBoundedFeeEstimator, - ) -> u32 where F::Target: FeeEstimator { + fn get_dust_exposure_limiting_feerate( + &self, fee_estimator: &LowerBoundedFeeEstimator, + ) -> u32 + where + F::Target: FeeEstimator, + { fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::MaximumFeeEstimate) } @@ -3696,10 +4222,10 @@ impl ChannelContext where SP::Target: SignerProvider { /// Updates the channel's config. A bool is returned indicating whether the config update /// applied resulted in a new ChannelUpdate message. pub fn update_config(&mut self, config: &ChannelConfig) -> bool { - let did_channel_update = - self.config.options.forwarding_fee_proportional_millionths != config.forwarding_fee_proportional_millionths || - self.config.options.forwarding_fee_base_msat != config.forwarding_fee_base_msat || - self.config.options.cltv_expiry_delta != config.cltv_expiry_delta; + let did_channel_update = self.config.options.forwarding_fee_proportional_millionths + != config.forwarding_fee_proportional_millionths + || self.config.options.forwarding_fee_base_msat != config.forwarding_fee_base_msat + || self.config.options.cltv_expiry_delta != config.cltv_expiry_delta; if did_channel_update { self.prev_config = Some((self.config.options, 0)); // Update the counter, which backs the ChannelUpdate timestamp, to allow the relay @@ -3724,8 +4250,8 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns true if funding_signed was sent/received and the /// funding transaction has been broadcast if necessary. pub fn is_funding_broadcast(&self) -> bool { - !self.channel_state.is_pre_funded_state() && - !matches!(self.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) + !self.channel_state.is_pre_funded_state() + && !matches!(self.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) } fn unset_funding_info(&mut self, funding: &mut FundingScope) { @@ -3736,7 +4262,7 @@ impl ChannelContext where SP::Target: SignerProvider { funding.channel_transaction_parameters.funding_outpoint = None; self.channel_id = self.temporary_channel_id.expect( "temporary_channel_id should be set since unset_funding_info is only called on funded \ - channels that were unfunded immediately beforehand" + channels that were unfunded immediately beforehand", ); } @@ -3749,9 +4275,14 @@ impl ChannelContext where SP::Target: SignerProvider { { let funding_script = funding.get_funding_redeemscript(); - let commitment_data = self.build_commitment_transaction(funding, - holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), - true, false, logger); + let commitment_data = self.build_commitment_transaction( + funding, + holder_commitment_point.transaction_number(), + &holder_commitment_point.current_point(), + true, + false, + logger, + ); let commitment_txid = { let trusted_tx = commitment_data.tx.trust(); let bitcoin_tx = trusted_tx.built_transaction(); @@ -3761,8 +4292,14 @@ impl ChannelContext where SP::Target: SignerProvider { log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(funding.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction), log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), &self.channel_id()); - if let Err(_) = self.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &funding.counterparty_funding_pubkey()) { - return Err(ChannelError::close("Invalid commitment tx signature from peer".to_owned())); + if let Err(_) = self.secp_ctx.verify_ecdsa( + &sighash, + &msg.signature, + &funding.counterparty_funding_pubkey(), + ) { + return Err(ChannelError::close( + "Invalid commitment tx signature from peer".to_owned(), + )); } bitcoin_tx.txid }; @@ -3771,53 +4308,100 @@ impl ChannelContext where SP::Target: SignerProvider { // they can actually afford the new fee now. let update_fee = if let Some((_, update_state)) = self.pending_update_fee { update_state == FeeUpdateState::RemoteAnnounced - } else { false }; + } else { + false + }; if update_fee { debug_assert!(!funding.is_outbound()); - let counterparty_reserve_we_require_msat = funding.holder_selected_channel_reserve_satoshis * 1000; - if commitment_data.stats.remote_balance_before_fee_anchors_msat < commitment_data.stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat { - return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned())); + let counterparty_reserve_we_require_msat = + funding.holder_selected_channel_reserve_satoshis * 1000; + if commitment_data.stats.remote_balance_before_fee_anchors_msat + < commitment_data.stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat + { + return Err(ChannelError::close( + "Funding remote cannot afford proposed new fee".to_owned(), + )); } } #[cfg(any(test, fuzzing))] { if funding.is_outbound() { - let projected_commit_tx_info = funding.next_local_commitment_tx_fee_info_cached.lock().unwrap().take(); + let projected_commit_tx_info = + funding.next_local_commitment_tx_fee_info_cached.lock().unwrap().take(); *funding.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None; if let Some(info) = projected_commit_tx_info { - let total_pending_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + let total_pending_htlcs = self.pending_inbound_htlcs.len() + + self.pending_outbound_htlcs.len() + self.holding_cell_htlc_updates.len(); if info.total_pending_htlcs == total_pending_htlcs && info.next_holder_htlc_id == self.next_holder_htlc_id && info.next_counterparty_htlc_id == self.next_counterparty_htlc_id - && info.feerate == self.feerate_per_kw { - assert_eq!(commitment_data.stats.total_fee_sat, info.fee / 1000); - } + && info.feerate == self.feerate_per_kw + { + assert_eq!(commitment_data.stats.total_fee_sat, info.fee / 1000); + } } } } if msg.htlc_signatures.len() != commitment_data.tx.nondust_htlcs().len() { - return Err(ChannelError::close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_data.tx.nondust_htlcs().len()))); + return Err(ChannelError::close(format!( + "Got wrong number of HTLC signatures ({}) from remote. It must be {}", + msg.htlc_signatures.len(), + commitment_data.tx.nondust_htlcs().len() + ))); } let holder_keys = commitment_data.tx.trust().keys(); let mut nondust_htlc_sources = Vec::with_capacity(commitment_data.tx.nondust_htlcs().len()); - let mut dust_htlcs = Vec::with_capacity(commitment_data.htlcs_included.len() - commitment_data.tx.nondust_htlcs().len()); - for (idx, (htlc, mut source_opt)) in commitment_data.htlcs_included.into_iter().enumerate() { + let mut dust_htlcs = Vec::with_capacity( + commitment_data.htlcs_included.len() - commitment_data.tx.nondust_htlcs().len(), + ); + for (idx, (htlc, mut source_opt)) in commitment_data.htlcs_included.into_iter().enumerate() + { if let Some(_) = htlc.transaction_output_index { - let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_data.tx.feerate_per_kw(), - funding.get_counterparty_selected_contest_delay().unwrap(), &htlc, funding.get_channel_type(), - &holder_keys.broadcaster_delayed_payment_key, &holder_keys.revocation_key); + let htlc_tx = chan_utils::build_htlc_transaction( + &commitment_txid, + commitment_data.tx.feerate_per_kw(), + funding.get_counterparty_selected_contest_delay().unwrap(), + &htlc, + funding.get_channel_type(), + &holder_keys.broadcaster_delayed_payment_key, + &holder_keys.revocation_key, + ); - let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, funding.get_channel_type(), &holder_keys); - let htlc_sighashtype = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; - let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]); + let htlc_redeemscript = chan_utils::get_htlc_redeemscript( + &htlc, + funding.get_channel_type(), + &holder_keys, + ); + let htlc_sighashtype = + if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + EcdsaSighashType::SinglePlusAnyoneCanPay + } else { + EcdsaSighashType::All + }; + let htlc_sighash = hash_to_message!( + &sighash::SighashCache::new(&htlc_tx) + .p2wsh_signature_hash( + 0, + &htlc_redeemscript, + htlc.to_bitcoin_amount(), + htlc_sighashtype + ) + .unwrap()[..] + ); log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(holder_keys.countersignatory_htlc_key.to_public_key().serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.channel_id()); - if let Err(_) = self.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &holder_keys.countersignatory_htlc_key.to_public_key()) { - return Err(ChannelError::close("Invalid HTLC tx signature from peer".to_owned())); + if let Err(_) = self.secp_ctx.verify_ecdsa( + &htlc_sighash, + &msg.htlc_signatures[idx], + &holder_keys.countersignatory_htlc_key.to_public_key(), + ) { + return Err(ChannelError::close( + "Invalid HTLC tx signature from peer".to_owned(), + )); } if htlc.offered { if let Some(source) = source_opt.take() { @@ -3837,10 +4421,15 @@ impl ChannelContext where SP::Target: SignerProvider { msg.signature, msg.htlc_signatures.clone(), &funding.get_holder_pubkeys().funding_pubkey, - funding.counterparty_funding_pubkey() + funding.counterparty_funding_pubkey(), ); - self.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_data.outbound_htlc_preimages) + self.holder_signer + .as_ref() + .validate_holder_commitment( + &holder_commitment_tx, + commitment_data.outbound_htlc_preimages, + ) .map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?; Ok(LatestHolderCommitmentTXInfo { @@ -3853,8 +4442,14 @@ impl ChannelContext where SP::Target: SignerProvider { /// Builds stats on a potential commitment transaction build, without actually building the /// commitment transaction. See `build_commitment_transaction` for further docs. #[inline] - fn build_commitment_stats(&self, funding: &FundingScope, local: bool, generated_by_local: bool) -> CommitmentStats { - let broadcaster_dust_limit_sat = if local { self.holder_dust_limit_satoshis } else { self.counterparty_dust_limit_satoshis }; + fn build_commitment_stats( + &self, funding: &FundingScope, local: bool, generated_by_local: bool, + ) -> CommitmentStats { + let broadcaster_dust_limit_sat = if local { + self.holder_dust_limit_satoshis + } else { + self.counterparty_dust_limit_satoshis + }; let mut non_dust_htlc_count = 0; let mut remote_htlc_total_msat = 0; let mut local_htlc_total_msat = 0; @@ -3865,9 +4460,18 @@ impl ChannelContext where SP::Target: SignerProvider { if match update_state { // Note that these match the inclusion criteria when scanning // pending_inbound_htlcs below. - FeeUpdateState::RemoteAnnounced => { debug_assert!(!funding.is_outbound()); !generated_by_local }, - FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { debug_assert!(!funding.is_outbound()); !generated_by_local }, - FeeUpdateState::Outbound => { assert!(funding.is_outbound()); generated_by_local }, + FeeUpdateState::RemoteAnnounced => { + debug_assert!(!funding.is_outbound()); + !generated_by_local + }, + FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { + debug_assert!(!funding.is_outbound()); + !generated_by_local + }, + FeeUpdateState::Outbound => { + assert!(funding.is_outbound()); + generated_by_local + }, } { feerate_per_kw = feerate; } @@ -3875,7 +4479,12 @@ impl ChannelContext where SP::Target: SignerProvider { for htlc in self.pending_inbound_htlcs.iter() { if htlc.state.included_in_commitment(generated_by_local) { - if !htlc.is_dust(local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type()) { + if !htlc.is_dust( + local, + feerate_per_kw, + broadcaster_dust_limit_sat, + funding.get_channel_type(), + ) { non_dust_htlc_count += 1; } remote_htlc_total_msat += htlc.amount_msat; @@ -3884,11 +4493,16 @@ impl ChannelContext where SP::Target: SignerProvider { value_to_self_msat_offset += htlc.amount_msat as i64; } } - }; + } for htlc in self.pending_outbound_htlcs.iter() { if htlc.state.included_in_commitment(generated_by_local) { - if !htlc.is_dust(local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type()) { + if !htlc.is_dust( + local, + feerate_per_kw, + broadcaster_dust_limit_sat, + funding.get_channel_type(), + ) { non_dust_htlc_count += 1; } local_htlc_total_msat += htlc.amount_msat; @@ -3897,7 +4511,7 @@ impl ChannelContext where SP::Target: SignerProvider { value_to_self_msat_offset -= htlc.amount_msat as i64; } } - }; + } // # Panics // @@ -3906,8 +4520,10 @@ impl ChannelContext where SP::Target: SignerProvider { // failure. // TODO: When MSRV >= 1.66.0, use u64::checked_add_signed - let mut value_to_self_msat = (funding.value_to_self_msat as i64 + value_to_self_msat_offset).try_into().unwrap(); - let mut value_to_remote_msat = (funding.get_value_satoshis() * 1000).checked_sub(value_to_self_msat).unwrap(); + let mut value_to_self_msat = + (funding.value_to_self_msat as i64 + value_to_self_msat_offset).try_into().unwrap(); + let mut value_to_remote_msat = + (funding.get_value_satoshis() * 1000).checked_sub(value_to_self_msat).unwrap(); value_to_self_msat = value_to_self_msat.checked_sub(local_htlc_total_msat).unwrap(); value_to_remote_msat = value_to_remote_msat.checked_sub(remote_htlc_total_msat).unwrap(); @@ -3920,14 +4536,36 @@ impl ChannelContext where SP::Target: SignerProvider { } else { funding.counterparty_max_commitment_tx_output.lock().unwrap() }; - debug_assert!(broadcaster_max_commitment_tx_output.0 <= value_to_self_msat || value_to_self_msat / 1000 >= funding.counterparty_selected_channel_reserve_satoshis.unwrap()); - broadcaster_max_commitment_tx_output.0 = cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat); - debug_assert!(broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat || value_to_remote_msat / 1000 >= funding.holder_selected_channel_reserve_satoshis); - broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat); + debug_assert!( + broadcaster_max_commitment_tx_output.0 <= value_to_self_msat + || value_to_self_msat / 1000 + >= funding.counterparty_selected_channel_reserve_satoshis.unwrap() + ); + broadcaster_max_commitment_tx_output.0 = + cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat); + debug_assert!( + broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat + || value_to_remote_msat / 1000 + >= funding.holder_selected_channel_reserve_satoshis + ); + broadcaster_max_commitment_tx_output.1 = + cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat); } - let total_fee_sat = commit_tx_fee_sat(feerate_per_kw, non_dust_htlc_count, &funding.channel_transaction_parameters.channel_type_features); - let total_anchors_sat = if funding.channel_transaction_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx() { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 }; + let total_fee_sat = commit_tx_fee_sat( + feerate_per_kw, + non_dust_htlc_count, + &funding.channel_transaction_parameters.channel_type_features, + ); + let total_anchors_sat = if funding + .channel_transaction_parameters + .channel_type_features + .supports_anchors_zero_fee_htlc_tx() + { + ANCHOR_OUTPUT_VALUE_SATOSHI * 2 + } else { + 0 + }; CommitmentStats { feerate_per_kw, @@ -3953,8 +4591,12 @@ impl ChannelContext where SP::Target: SignerProvider { /// generated by the peer which proposed adding the HTLCs, and thus we need to understand both /// which peer generated this transaction and "to whom" this transaction flows. #[inline] - fn build_commitment_transaction(&self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, local: bool, generated_by_local: bool, logger: &L) -> CommitmentData - where L::Target: Logger + fn build_commitment_transaction( + &self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, + local: bool, generated_by_local: bool, logger: &L, + ) -> CommitmentData + where + L::Target: Logger, { let stats = self.build_commitment_stats(funding, local, generated_by_local); let CommitmentStats { @@ -3963,11 +4605,12 @@ impl ChannelContext where SP::Target: SignerProvider { total_anchors_sat, broadcaster_dust_limit_sat, local_balance_before_fee_anchors_msat, - remote_balance_before_fee_anchors_msat + remote_balance_before_fee_anchors_msat, } = stats; let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len(); - let mut htlcs_included: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs); + let mut htlcs_included: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = + Vec::with_capacity(num_htlcs); let mut nondust_htlcs: Vec = Vec::with_capacity(num_htlcs); log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for channel {} for {}, generated by {} with fee {}...", @@ -3983,9 +4626,9 @@ impl ChannelContext where SP::Target: SignerProvider { amount_msat: $htlc.amount_msat, cltv_expiry: $htlc.cltv_expiry, payment_hash: $htlc.payment_hash, - transaction_output_index: None + transaction_output_index: None, } - } + }; } macro_rules! add_htlc_output { @@ -4008,12 +4651,19 @@ impl ChannelContext where SP::Target: SignerProvider { if htlc.state.included_in_commitment(generated_by_local) { add_htlc_output!(htlc, false, None); } else { - log_trace!(logger, " ...not including inbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, htlc.payment_hash, htlc.amount_msat, htlc.state); + log_trace!( + logger, + " ...not including inbound HTLC {} (hash {}) with value {} due to state ({})", + htlc.htlc_id, + htlc.payment_hash, + htlc.amount_msat, + htlc.state + ); if let Some(preimage) = htlc.state.preimage() { inbound_htlc_preimages.push(preimage); } } - }; + } for htlc in self.pending_outbound_htlcs.iter() { if let Some(preimage) = htlc.state.preimage() { @@ -4024,7 +4674,7 @@ impl ChannelContext where SP::Target: SignerProvider { } else { log_trace!(logger, " ...not including outbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, htlc.payment_hash, htlc.amount_msat, htlc.state); } - }; + } // We MUST use saturating subs here, as the funder's balance is not guaranteed to be greater // than or equal to the sum of `total_fee_sat` and `total_anchors_sat`. @@ -4034,29 +4684,51 @@ impl ChannelContext where SP::Target: SignerProvider { // cover the total fee and the anchors. let (value_to_self, value_to_remote) = if funding.is_outbound() { - ((local_balance_before_fee_anchors_msat / 1000).saturating_sub(total_anchors_sat).saturating_sub(total_fee_sat), remote_balance_before_fee_anchors_msat / 1000) + ( + (local_balance_before_fee_anchors_msat / 1000) + .saturating_sub(total_anchors_sat) + .saturating_sub(total_fee_sat), + remote_balance_before_fee_anchors_msat / 1000, + ) } else { - (local_balance_before_fee_anchors_msat / 1000, (remote_balance_before_fee_anchors_msat / 1000).saturating_sub(total_anchors_sat).saturating_sub(total_fee_sat)) + ( + local_balance_before_fee_anchors_msat / 1000, + (remote_balance_before_fee_anchors_msat / 1000) + .saturating_sub(total_anchors_sat) + .saturating_sub(total_fee_sat), + ) }; let mut to_broadcaster_value_sat = if local { value_to_self } else { value_to_remote }; let mut to_countersignatory_value_sat = if local { value_to_remote } else { value_to_self }; if to_broadcaster_value_sat >= broadcaster_dust_limit_sat { - log_trace!(logger, " ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, to_broadcaster_value_sat); + log_trace!( + logger, + " ...including {} output with value {}", + if local { "to_local" } else { "to_remote" }, + to_broadcaster_value_sat + ); } else { to_broadcaster_value_sat = 0; } if to_countersignatory_value_sat >= broadcaster_dust_limit_sat { - log_trace!(logger, " ...including {} output with value {}", if local { "to_remote" } else { "to_local" }, to_countersignatory_value_sat); + log_trace!( + logger, + " ...including {} output with value {}", + if local { "to_remote" } else { "to_local" }, + to_countersignatory_value_sat + ); } else { to_countersignatory_value_sat = 0; } - let channel_parameters = - if local { funding.channel_transaction_parameters.as_holder_broadcastable() } - else { funding.channel_transaction_parameters.as_counterparty_broadcastable() }; + let channel_parameters = if local { + funding.channel_transaction_parameters.as_holder_broadcastable() + } else { + funding.channel_transaction_parameters.as_counterparty_broadcastable() + }; let tx = CommitmentTransaction::new( commitment_number, per_commitment_point, @@ -4077,13 +4749,15 @@ impl ChannelContext where SP::Target: SignerProvider { let htlc = htlcs_included .iter_mut() .filter(|(htlc, _source)| htlc.transaction_output_index.is_none()) - .find_map(|(htlc, _source)| { - if htlc.is_data_equal(nondust_htlc) { - Some(htlc) - } else { - None - } - }) + .find_map( + |(htlc, _source)| { + if htlc.is_data_equal(nondust_htlc) { + Some(htlc) + } else { + None + } + }, + ) .unwrap(); htlc.transaction_output_index = Some(nondust_htlc.transaction_output_index.unwrap()); } @@ -4142,14 +4816,19 @@ impl ChannelContext where SP::Target: SignerProvider { dust_exposure_limiting_feerate: u32, ) -> HTLCStats { let context = self; - let uses_0_htlc_fee_anchors = funding.get_channel_type().supports_anchors_zero_fee_htlc_tx(); + let uses_0_htlc_fee_anchors = + funding.get_channel_type().supports_anchors_zero_fee_htlc_tx(); let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update); let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if uses_0_htlc_fee_anchors { (0, 0) } else { - (dust_buffer_feerate as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000, - dust_buffer_feerate as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000) + ( + dust_buffer_feerate as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) + / 1000, + dust_buffer_feerate as u64 * htlc_success_tx_weight(funding.get_channel_type()) + / 1000, + ) }; let mut on_holder_tx_dust_exposure_msat = 0; @@ -4161,8 +4840,10 @@ impl ChannelContext where SP::Target: SignerProvider { let mut pending_inbound_htlcs_value_msat = 0; { - let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis; - let holder_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis; + let counterparty_dust_limit_timeout_sat = + htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis; + let holder_dust_limit_success_sat = + htlc_success_dust_limit + context.holder_dust_limit_satoshis; for ref htlc in context.pending_inbound_htlcs.iter() { pending_inbound_htlcs_value_msat += htlc.amount_msat; if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat { @@ -4181,8 +4862,10 @@ impl ChannelContext where SP::Target: SignerProvider { let mut on_holder_tx_outbound_holding_cell_htlcs_count = 0; let mut pending_outbound_htlcs = self.pending_outbound_htlcs.len(); { - let counterparty_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis; - let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis; + let counterparty_dust_limit_success_sat = + htlc_success_dust_limit + context.counterparty_dust_limit_satoshis; + let holder_dust_limit_timeout_sat = + htlc_timeout_dust_limit + context.holder_dust_limit_satoshis; for ref htlc in context.pending_outbound_htlcs.iter() { pending_outbound_htlcs_value_msat += htlc.amount_msat; if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat { @@ -4219,13 +4902,23 @@ impl ChannelContext where SP::Target: SignerProvider { .or(self.pending_update_fee.map(|(fee, _)| fee)) .unwrap_or(self.feerate_per_kw) .checked_sub(dust_exposure_limiting_feerate); - let extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat = excess_feerate_opt.map(|excess_feerate| { - let extra_htlc_dust_exposure = on_counterparty_tx_dust_exposure_msat - + chan_utils::commit_and_htlc_tx_fees_sat(excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + 1, on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type()) * 1000; - on_counterparty_tx_dust_exposure_msat - += chan_utils::commit_and_htlc_tx_fees_sat(excess_feerate, on_counterparty_tx_accepted_nondust_htlcs, on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type()) * 1000; - extra_htlc_dust_exposure - }); + let extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat = + excess_feerate_opt.map(|excess_feerate| { + let extra_htlc_dust_exposure = on_counterparty_tx_dust_exposure_msat + + chan_utils::commit_and_htlc_tx_fees_sat( + excess_feerate, + on_counterparty_tx_accepted_nondust_htlcs + 1, + on_counterparty_tx_offered_nondust_htlcs, + funding.get_channel_type(), + ) * 1000; + on_counterparty_tx_dust_exposure_msat += chan_utils::commit_and_htlc_tx_fees_sat( + excess_feerate, + on_counterparty_tx_accepted_nondust_htlcs, + on_counterparty_tx_offered_nondust_htlcs, + funding.get_channel_type(), + ) * 1000; + extra_htlc_dust_exposure + }); HTLCStats { pending_inbound_htlcs: self.pending_inbound_htlcs.len(), @@ -4241,7 +4934,9 @@ impl ChannelContext where SP::Target: SignerProvider { } /// Returns information on all pending inbound HTLCs. - pub fn get_pending_inbound_htlc_details(&self, funding: &FundingScope) -> Vec { + pub fn get_pending_inbound_htlc_details( + &self, funding: &FundingScope, + ) -> Vec { let mut holding_cell_states = new_hash_map(); for holding_cell_update in self.holding_cell_htlc_updates.iter() { match holding_cell_update { @@ -4252,32 +4947,30 @@ impl ChannelContext where SP::Target: SignerProvider { ); }, HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { - holding_cell_states.insert( - htlc_id, - InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail, - ); + holding_cell_states + .insert(htlc_id, InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail); }, HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => { - holding_cell_states.insert( - htlc_id, - InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail, - ); + holding_cell_states + .insert(htlc_id, InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail); }, // Outbound HTLC. HTLCUpdateAwaitingACK::AddHTLC { .. } => {}, } } let mut inbound_details = Vec::new(); - let htlc_success_dust_limit = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - 0 - } else { - let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64; - dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000 - }; - let holder_dust_limit_success_sat = htlc_success_dust_limit + self.holder_dust_limit_satoshis; + let htlc_success_dust_limit = + if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + 0 + } else { + let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64; + dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000 + }; + let holder_dust_limit_success_sat = + htlc_success_dust_limit + self.holder_dust_limit_satoshis; for htlc in self.pending_inbound_htlcs.iter() { if let Some(state_details) = (&htlc.state).into() { - inbound_details.push(InboundHTLCDetails{ + inbound_details.push(InboundHTLCDetails { htlc_id: htlc.htlc_id, amount_msat: htlc.amount_msat, cltv_expiry: htlc.cltv_expiry, @@ -4291,17 +4984,21 @@ impl ChannelContext where SP::Target: SignerProvider { } /// Returns information on all pending outbound HTLCs. - pub fn get_pending_outbound_htlc_details(&self, funding: &FundingScope) -> Vec { + pub fn get_pending_outbound_htlc_details( + &self, funding: &FundingScope, + ) -> Vec { let mut outbound_details = Vec::new(); - let htlc_timeout_dust_limit = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - 0 - } else { - let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64; - dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000 - }; - let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis; + let htlc_timeout_dust_limit = + if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + 0 + } else { + let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64; + dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000 + }; + let holder_dust_limit_timeout_sat = + htlc_timeout_dust_limit + self.holder_dust_limit_satoshis; for htlc in self.pending_outbound_htlcs.iter() { - outbound_details.push(OutboundHTLCDetails{ + outbound_details.push(OutboundHTLCDetails { htlc_id: Some(htlc.htlc_id), amount_msat: htlc.amount_msat, cltv_expiry: htlc.cltv_expiry, @@ -4318,13 +5015,14 @@ impl ChannelContext where SP::Target: SignerProvider { payment_hash, skimmed_fee_msat, .. - } = *holding_cell_update { - outbound_details.push(OutboundHTLCDetails{ + } = *holding_cell_update + { + outbound_details.push(OutboundHTLCDetails { htlc_id: None, - amount_msat: amount_msat, - cltv_expiry: cltv_expiry, - payment_hash: payment_hash, - skimmed_fee_msat: skimmed_fee_msat, + amount_msat, + cltv_expiry, + payment_hash, + skimmed_fee_msat, state: Some(OutboundHTLCStateDetails::AwaitingRemoteRevokeToAdd), is_dust: amount_msat / 1000 < holder_dust_limit_timeout_sat, }); @@ -4343,21 +5041,26 @@ impl ChannelContext where SP::Target: SignerProvider { // Note that we have to handle overflow due to the case mentioned in the docs in general // here. - let dust_exposure_limiting_feerate = self.get_dust_exposure_limiting_feerate(&fee_estimator); - let htlc_stats = context.get_pending_htlc_stats(funding, None, dust_exposure_limiting_feerate); + let dust_exposure_limiting_feerate = + self.get_dust_exposure_limiting_feerate(&fee_estimator); + let htlc_stats = + context.get_pending_htlc_stats(funding, None, dust_exposure_limiting_feerate); - let outbound_capacity_msat = funding.value_to_self_msat - .saturating_sub(htlc_stats.pending_outbound_htlcs_value_msat) - .saturating_sub( - funding.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) * 1000); + let outbound_capacity_msat = funding + .value_to_self_msat + .saturating_sub(htlc_stats.pending_outbound_htlcs_value_msat) + .saturating_sub( + funding.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) * 1000, + ); let mut available_capacity_msat = outbound_capacity_msat; - let anchor_outputs_value_msat = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 - } else { - 0 - }; + let anchor_outputs_value_msat = + if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 + } else { + 0 + }; if funding.is_outbound() { // We should mind channel commit tx fee when computing how much of the available capacity // can be used in the next htlc. Mirrors the logic in send_htlc. @@ -4368,13 +5071,21 @@ impl ChannelContext where SP::Target: SignerProvider { // This complicates the computation around dust-values, up to the one-htlc-value. let mut real_dust_limit_timeout_sat = context.holder_dust_limit_satoshis; if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - real_dust_limit_timeout_sat += context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000; + real_dust_limit_timeout_sat += context.feerate_per_kw as u64 + * htlc_timeout_tx_weight(funding.get_channel_type()) + / 1000; } - let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered); - let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(&funding, htlc_above_dust, Some(())); - let htlc_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000 - 1, HTLCInitiator::LocalOffered); - let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(&funding, htlc_dust, Some(())); + let htlc_above_dust = + HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered); + let mut max_reserved_commit_tx_fee_msat = + context.next_local_commit_tx_fee_msat(&funding, htlc_above_dust, Some(())); + let htlc_dust = HTLCCandidate::new( + real_dust_limit_timeout_sat * 1000 - 1, + HTLCInitiator::LocalOffered, + ); + let mut min_reserved_commit_tx_fee_msat = + context.next_local_commit_tx_fee_msat(&funding, htlc_dust, Some(())); if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { max_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE; min_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE; @@ -4383,14 +5094,22 @@ impl ChannelContext where SP::Target: SignerProvider { // We will first subtract the fee as if we were above-dust. Then, if the resulting // value ends up being below dust, we have this fee available again. In that case, // match the value to right-below-dust. - let mut capacity_minus_commitment_fee_msat: i64 = available_capacity_msat as i64 - - max_reserved_commit_tx_fee_msat as i64 - anchor_outputs_value_msat as i64; + let mut capacity_minus_commitment_fee_msat: i64 = available_capacity_msat as i64 + - max_reserved_commit_tx_fee_msat as i64 + - anchor_outputs_value_msat as i64; if capacity_minus_commitment_fee_msat < (real_dust_limit_timeout_sat as i64) * 1000 { - let one_htlc_difference_msat = max_reserved_commit_tx_fee_msat - min_reserved_commit_tx_fee_msat; + let one_htlc_difference_msat = + max_reserved_commit_tx_fee_msat - min_reserved_commit_tx_fee_msat; debug_assert!(one_htlc_difference_msat != 0); capacity_minus_commitment_fee_msat += one_htlc_difference_msat as i64; - capacity_minus_commitment_fee_msat = cmp::min(real_dust_limit_timeout_sat as i64 * 1000 - 1, capacity_minus_commitment_fee_msat); - available_capacity_msat = cmp::max(0, cmp::min(capacity_minus_commitment_fee_msat, available_capacity_msat as i64)) as u64; + capacity_minus_commitment_fee_msat = cmp::min( + real_dust_limit_timeout_sat as i64 * 1000 - 1, + capacity_minus_commitment_fee_msat, + ); + available_capacity_msat = cmp::max( + 0, + cmp::min(capacity_minus_commitment_fee_msat, available_capacity_msat as i64), + ) as u64; } else { available_capacity_msat = capacity_minus_commitment_fee_msat as u64; } @@ -4399,20 +5118,31 @@ impl ChannelContext where SP::Target: SignerProvider { // sending a new HTLC won't reduce their balance below our reserve threshold. let mut real_dust_limit_success_sat = context.counterparty_dust_limit_satoshis; if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - real_dust_limit_success_sat += context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000; + real_dust_limit_success_sat += context.feerate_per_kw as u64 + * htlc_success_tx_weight(funding.get_channel_type()) + / 1000; } - let htlc_above_dust = HTLCCandidate::new(real_dust_limit_success_sat * 1000, HTLCInitiator::LocalOffered); - let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(&funding, Some(htlc_above_dust), None); + let htlc_above_dust = + HTLCCandidate::new(real_dust_limit_success_sat * 1000, HTLCInitiator::LocalOffered); + let max_reserved_commit_tx_fee_msat = + context.next_remote_commit_tx_fee_msat(&funding, Some(htlc_above_dust), None); - let holder_selected_chan_reserve_msat = funding.holder_selected_channel_reserve_satoshis * 1000; - let remote_balance_msat = (funding.get_value_satoshis() * 1000 - funding.value_to_self_msat) + let holder_selected_chan_reserve_msat = + funding.holder_selected_channel_reserve_satoshis * 1000; + let remote_balance_msat = (funding.get_value_satoshis() * 1000 + - funding.value_to_self_msat) .saturating_sub(htlc_stats.pending_inbound_htlcs_value_msat); - if remote_balance_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat + anchor_outputs_value_msat { + if remote_balance_msat + < max_reserved_commit_tx_fee_msat + + holder_selected_chan_reserve_msat + + anchor_outputs_value_msat + { // If another HTLC's fee would reduce the remote's balance below the reserve limit // we've selected for them, we can only send dust HTLCs. - available_capacity_msat = cmp::min(available_capacity_msat, real_dust_limit_success_sat * 1000 - 1); + available_capacity_msat = + cmp::min(available_capacity_msat, real_dust_limit_success_sat * 1000 - 1); } } @@ -4424,61 +5154,91 @@ impl ChannelContext where SP::Target: SignerProvider { // send above the dust limit (as the router can always overpay to meet the dust limit). let mut remaining_msat_below_dust_exposure_limit = None; let mut dust_exposure_dust_limit_msat = 0; - let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + let max_dust_htlc_exposure_msat = + context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - (context.counterparty_dust_limit_satoshis, context.holder_dust_limit_satoshis) - } else { - let dust_buffer_feerate = context.get_dust_buffer_feerate(None) as u64; - (context.counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000, - context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000) - }; + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = + if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + (context.counterparty_dust_limit_satoshis, context.holder_dust_limit_satoshis) + } else { + let dust_buffer_feerate = context.get_dust_buffer_feerate(None) as u64; + ( + context.counterparty_dust_limit_satoshis + + dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) + / 1000, + context.holder_dust_limit_satoshis + + dust_buffer_feerate * htlc_timeout_tx_weight(funding.get_channel_type()) + / 1000, + ) + }; - if let Some(extra_htlc_dust_exposure) = htlc_stats.extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat { + if let Some(extra_htlc_dust_exposure) = + htlc_stats.extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat + { if extra_htlc_dust_exposure > max_dust_htlc_exposure_msat { // If adding an extra HTLC would put us over the dust limit in total fees, we cannot // send any non-dust HTLCs. - available_capacity_msat = cmp::min(available_capacity_msat, htlc_success_dust_limit * 1000); + available_capacity_msat = + cmp::min(available_capacity_msat, htlc_success_dust_limit * 1000); } } - if htlc_stats.on_counterparty_tx_dust_exposure_msat.saturating_add(htlc_success_dust_limit * 1000) > max_dust_htlc_exposure_msat.saturating_add(1) { + if htlc_stats + .on_counterparty_tx_dust_exposure_msat + .saturating_add(htlc_success_dust_limit * 1000) + > max_dust_htlc_exposure_msat.saturating_add(1) + { // Note that we don't use the `counterparty_tx_dust_exposure` (with // `htlc_dust_exposure_msat`) here as it only applies to non-dust HTLCs. - remaining_msat_below_dust_exposure_limit = - Some(max_dust_htlc_exposure_msat.saturating_sub(htlc_stats.on_counterparty_tx_dust_exposure_msat)); - dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000); + remaining_msat_below_dust_exposure_limit = Some( + max_dust_htlc_exposure_msat + .saturating_sub(htlc_stats.on_counterparty_tx_dust_exposure_msat), + ); + dust_exposure_dust_limit_msat = + cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000); } - if htlc_stats.on_holder_tx_dust_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) { + if htlc_stats.on_holder_tx_dust_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 + - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) + { remaining_msat_below_dust_exposure_limit = Some(cmp::min( remaining_msat_below_dust_exposure_limit.unwrap_or(u64::max_value()), - max_dust_htlc_exposure_msat.saturating_sub(htlc_stats.on_holder_tx_dust_exposure_msat))); - dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000); + max_dust_htlc_exposure_msat + .saturating_sub(htlc_stats.on_holder_tx_dust_exposure_msat), + )); + dust_exposure_dust_limit_msat = + cmp::max(dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000); } if let Some(remaining_limit_msat) = remaining_msat_below_dust_exposure_limit { if available_capacity_msat < dust_exposure_dust_limit_msat { available_capacity_msat = cmp::min(available_capacity_msat, remaining_limit_msat); } else { - next_outbound_htlc_minimum_msat = cmp::max(next_outbound_htlc_minimum_msat, dust_exposure_dust_limit_msat); + next_outbound_htlc_minimum_msat = + cmp::max(next_outbound_htlc_minimum_msat, dust_exposure_dust_limit_msat); } } - available_capacity_msat = cmp::min(available_capacity_msat, - context.counterparty_max_htlc_value_in_flight_msat - htlc_stats.pending_outbound_htlcs_value_msat); + available_capacity_msat = cmp::min( + available_capacity_msat, + context.counterparty_max_htlc_value_in_flight_msat + - htlc_stats.pending_outbound_htlcs_value_msat, + ); - if htlc_stats.pending_outbound_htlcs + 1 > context.counterparty_max_accepted_htlcs as usize { + if htlc_stats.pending_outbound_htlcs + 1 > context.counterparty_max_accepted_htlcs as usize + { available_capacity_msat = 0; } #[allow(deprecated)] // TODO: Remove once balance_msat is removed. AvailableBalances { - inbound_capacity_msat: cmp::max(funding.get_value_satoshis() as i64 * 1000 + inbound_capacity_msat: cmp::max( + funding.get_value_satoshis() as i64 * 1000 - funding.value_to_self_msat as i64 - htlc_stats.pending_inbound_htlcs_value_msat as i64 - funding.holder_selected_channel_reserve_satoshis as i64 * 1000, - 0) as u64, + 0, + ) as u64, outbound_capacity_msat, next_outbound_htlc_limit_msat: available_capacity_msat, next_outbound_htlc_minimum_msat, @@ -4501,17 +5261,28 @@ impl ChannelContext where SP::Target: SignerProvider { let context = &self; assert!(funding.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding + .get_channel_type() + .supports_anchors_zero_fee_htlc_tx() + { (0, 0) } else { - (context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000, - context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000) + ( + context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) + / 1000, + context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) + / 1000, + ) }; - let real_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis; - let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis; + let real_dust_limit_success_sat = + htlc_success_dust_limit + context.holder_dust_limit_satoshis; + let real_dust_limit_timeout_sat = + htlc_timeout_dust_limit + context.holder_dust_limit_satoshis; let mut addl_htlcs = 0; - if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; } + if fee_spike_buffer_htlc.is_some() { + addl_htlcs += 1; + } match htlc.origin { HTLCInitiator::LocalOffered => { if htlc.amount_msat / 1000 >= real_dust_limit_timeout_sat { @@ -4522,13 +5293,13 @@ impl ChannelContext where SP::Target: SignerProvider { if htlc.amount_msat / 1000 >= real_dust_limit_success_sat { addl_htlcs += 1; } - } + }, } let mut included_htlcs = 0; for ref htlc in context.pending_inbound_htlcs.iter() { if htlc.amount_msat / 1000 < real_dust_limit_success_sat { - continue + continue; } // We include LocalRemoved HTLCs here because we may still need to broadcast a commitment // transaction including this HTLC if it times out before they RAA. @@ -4537,12 +5308,12 @@ impl ChannelContext where SP::Target: SignerProvider { for ref htlc in context.pending_outbound_htlcs.iter() { if htlc.amount_msat / 1000 < real_dust_limit_timeout_sat { - continue + continue; } match htlc.state { - OutboundHTLCState::LocalAnnounced {..} => included_htlcs += 1, + OutboundHTLCState::LocalAnnounced { .. } => included_htlcs += 1, OutboundHTLCState::Committed => included_htlcs += 1, - OutboundHTLCState::RemoteRemoved {..} => included_htlcs += 1, + OutboundHTLCState::RemoteRemoved { .. } => included_htlcs += 1, // We don't include AwaitingRemoteRevokeToRemove HTLCs because our next commitment // transaction won't be generated until they send us their next RAA, which will mean // dropping any HTLCs in this state. @@ -4554,7 +5325,7 @@ impl ChannelContext where SP::Target: SignerProvider { match htlc { &HTLCUpdateAwaitingACK::AddHTLC { amount_msat, .. } => { if amount_msat / 1000 < real_dust_limit_timeout_sat { - continue + continue; } included_htlcs += 1 }, @@ -4564,14 +5335,20 @@ impl ChannelContext where SP::Target: SignerProvider { } let num_htlcs = included_htlcs + addl_htlcs; - let res = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, funding.get_channel_type()) * 1000; + let res = + commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, funding.get_channel_type()) * 1000; #[cfg(any(test, fuzzing))] { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs - 1, funding.get_channel_type()) * 1000; + fee = commit_tx_fee_sat( + context.feerate_per_kw, + num_htlcs - 1, + funding.get_channel_type(), + ) * 1000; } - let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len() + let total_pending_htlcs = context.pending_inbound_htlcs.len() + + context.pending_outbound_htlcs.len() + context.holding_cell_htlc_updates.len(); let commitment_tx_info = CommitmentTxInfoCached { fee, @@ -4586,7 +5363,8 @@ impl ChannelContext where SP::Target: SignerProvider { }, feerate: context.feerate_per_kw, }; - *funding.next_local_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info); + *funding.next_local_commitment_tx_fee_info_cached.lock().unwrap() = + Some(commitment_tx_info); } res } @@ -4602,24 +5380,39 @@ impl ChannelContext where SP::Target: SignerProvider { /// /// Dust HTLCs are excluded. fn next_remote_commit_tx_fee_msat( - &self, funding: &FundingScope, htlc: Option, fee_spike_buffer_htlc: Option<()>, + &self, funding: &FundingScope, htlc: Option, + fee_spike_buffer_htlc: Option<()>, ) -> u64 { - debug_assert!(htlc.is_some() || fee_spike_buffer_htlc.is_some(), "At least one of the options must be set"); + debug_assert!( + htlc.is_some() || fee_spike_buffer_htlc.is_some(), + "At least one of the options must be set" + ); let context = &self; assert!(!funding.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding + .get_channel_type() + .supports_anchors_zero_fee_htlc_tx() + { (0, 0) } else { - (context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000, - context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000) + ( + context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) + / 1000, + context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) + / 1000, + ) }; - let real_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis; - let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis; + let real_dust_limit_success_sat = + htlc_success_dust_limit + context.counterparty_dust_limit_satoshis; + let real_dust_limit_timeout_sat = + htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis; let mut addl_htlcs = 0; - if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; } + if fee_spike_buffer_htlc.is_some() { + addl_htlcs += 1; + } if let Some(htlc) = &htlc { match htlc.origin { HTLCInitiator::LocalOffered => { @@ -4631,7 +5424,7 @@ impl ChannelContext where SP::Target: SignerProvider { if htlc.amount_msat / 1000 >= real_dust_limit_timeout_sat { addl_htlcs += 1; } - } + }, } } @@ -4641,34 +5434,40 @@ impl ChannelContext where SP::Target: SignerProvider { let mut included_htlcs = 0; for ref htlc in context.pending_inbound_htlcs.iter() { if htlc.amount_msat / 1000 <= real_dust_limit_timeout_sat { - continue + continue; } included_htlcs += 1; } for ref htlc in context.pending_outbound_htlcs.iter() { if htlc.amount_msat / 1000 <= real_dust_limit_success_sat { - continue + continue; } // We only include outbound HTLCs if it will not be included in their next commitment_signed, // i.e. if they've responded to us with an RAA after announcement. match htlc.state { OutboundHTLCState::Committed => included_htlcs += 1, - OutboundHTLCState::RemoteRemoved {..} => included_htlcs += 1, + OutboundHTLCState::RemoteRemoved { .. } => included_htlcs += 1, OutboundHTLCState::LocalAnnounced { .. } => included_htlcs += 1, _ => {}, } } let num_htlcs = included_htlcs + addl_htlcs; - let res = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, funding.get_channel_type()) * 1000; + let res = + commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, funding.get_channel_type()) * 1000; #[cfg(any(test, fuzzing))] if let Some(htlc) = &htlc { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = commit_tx_fee_sat(context.feerate_per_kw, num_htlcs - 1, funding.get_channel_type()) * 1000; + fee = commit_tx_fee_sat( + context.feerate_per_kw, + num_htlcs - 1, + funding.get_channel_type(), + ) * 1000; } - let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len(); + let total_pending_htlcs = + context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len(); let commitment_tx_info = CommitmentTxInfoCached { fee, total_pending_htlcs, @@ -4682,22 +5481,27 @@ impl ChannelContext where SP::Target: SignerProvider { }, feerate: context.feerate_per_kw, }; - *funding.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info); + *funding.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = + Some(commitment_tx_info); } res } - fn if_unbroadcasted_funding(&self, f: F) -> Option where F: Fn() -> Option { + fn if_unbroadcasted_funding(&self, f: F) -> Option + where + F: Fn() -> Option, + { match self.channel_state { ChannelState::FundingNegotiated => f(), - ChannelState::AwaitingChannelReady(flags) => - if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) || - flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) + ChannelState::AwaitingChannelReady(flags) => { + if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) + || flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) { f() } else { None - }, + } + }, _ => None, } } @@ -4714,9 +5518,9 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns the transaction ID if there is a pending funding transaction that is yet to be /// broadcast. pub fn unbroadcasted_funding_txid(&self, funding: &FundingScope) -> Option { - self.if_unbroadcasted_funding(|| + self.if_unbroadcasted_funding(|| { funding.channel_transaction_parameters.funding_outpoint.map(|txo| txo.txid) - ) + }) } /// Returns whether the channel is funded in a batch. @@ -4735,7 +5539,9 @@ impl ChannelContext where SP::Target: SignerProvider { /// those explicitly stated to be allowed after shutdown completes, eg some simple getters). /// Also returns the list of payment_hashes for channels which we can safely fail backwards /// immediately (others we will have to allow to time out). - pub fn force_shutdown(&mut self, funding: &FundingScope, should_broadcast: bool, closure_reason: ClosureReason) -> ShutdownResult { + pub fn force_shutdown( + &mut self, funding: &FundingScope, should_broadcast: bool, closure_reason: ClosureReason, + ) -> ShutdownResult { // Note that we MUST only generate a monitor update that indicates force-closure - we're // called during initialization prior to the chain_monitor in the encompassing ChannelManager // being fully configured in some cases. Thus, its likely any monitor events we generate will @@ -4749,9 +5555,14 @@ impl ChannelContext where SP::Target: SignerProvider { for htlc_update in self.holding_cell_htlc_updates.drain(..) { match htlc_update { HTLCUpdateAwaitingACK::AddHTLC { source, payment_hash, .. } => { - dropped_outbound_htlcs.push((source, payment_hash, counterparty_node_id, self.channel_id)); + dropped_outbound_htlcs.push(( + source, + payment_hash, + counterparty_node_id, + self.channel_id, + )); }, - _ => {} + _ => {}, } } let monitor_update = if let Some(funding_txo) = funding.get_funding_txo() { @@ -4764,13 +5575,24 @@ impl ChannelContext where SP::Target: SignerProvider { // See test_duplicate_chan_id and test_pre_lockin_no_chan_closed_update for more. if !self.channel_state.is_pre_funded_state() { self.latest_monitor_update_id += 1; - Some((self.get_counterparty_node_id(), funding_txo, self.channel_id(), ChannelMonitorUpdate { - update_id: self.latest_monitor_update_id, - updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast }], - channel_id: Some(self.channel_id()), - })) - } else { None } - } else { None }; + Some(( + self.get_counterparty_node_id(), + funding_txo, + self.channel_id(), + ChannelMonitorUpdate { + update_id: self.latest_monitor_update_id, + updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { + should_broadcast, + }], + channel_id: Some(self.channel_id()), + }, + )) + } else { + None + } + } else { + None + }; let unbroadcasted_batch_funding_txid = self.unbroadcasted_batch_funding_txid(funding); let unbroadcasted_funding_tx = self.unbroadcasted_funding(funding); @@ -4796,21 +5618,35 @@ impl ChannelContext where SP::Target: SignerProvider { fn get_funding_signed_msg( &mut self, channel_parameters: &ChannelTransactionParameters, logger: &L, counterparty_initial_commitment_tx: CommitmentTransaction, - ) -> Option where L::Target: Logger { + ) -> Option + where + L::Target: Logger, + { let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust(); let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction(); - log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}", - &self.channel_id(), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); + log_trace!( + logger, + "Initial counterparty tx for channel {} is: txid {} tx {}", + &self.channel_id(), + counterparty_initial_bitcoin_tx.txid, + encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction) + ); // We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish. let signature = match &self.holder_signer { // TODO (arik): move match into calling method for Taproot - ChannelSignerType::Ecdsa(ecdsa) => ecdsa.sign_counterparty_commitment( - channel_parameters, &counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx - ).ok(), + ChannelSignerType::Ecdsa(ecdsa) => ecdsa + .sign_counterparty_commitment( + channel_parameters, + &counterparty_initial_commitment_tx, + Vec::new(), + Vec::new(), + &self.secp_ctx, + ) + .ok(), // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), }; if signature.is_some() && self.signer_pending_funding { @@ -4833,17 +5669,16 @@ impl ChannelContext where SP::Target: SignerProvider { /// of the channel type we tried, not of our ability to open any channel at all. We can see if a /// downgrade of channel features would be possible so that we can still open the channel. pub(crate) fn maybe_downgrade_channel_features( - &mut self, funding: &mut FundingScope, fee_estimator: &LowerBoundedFeeEstimator + &mut self, funding: &mut FundingScope, fee_estimator: &LowerBoundedFeeEstimator, ) -> Result<(), ()> where - F::Target: FeeEstimator + F::Target: FeeEstimator, { - if !funding.is_outbound() || - !matches!( + if !funding.is_outbound() + || !matches!( self.channel_state, ChannelState::NegotiatingFunding(flags) if flags == NegotiatingFundingFlags::OUR_INIT_SENT - ) - { + ) { return Err(()); } if funding.get_channel_type() == &ChannelTypeFeatures::only_static_remote_key() { @@ -4862,7 +5697,8 @@ impl ChannelContext where SP::Target: SignerProvider { let channel_type = &mut funding.channel_transaction_parameters.channel_type_features; if channel_type.supports_anchors_zero_fee_htlc_tx() { channel_type.clear_anchors_zero_fee_htlc_tx(); - self.feerate_per_kw = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); + self.feerate_per_kw = + fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); assert!(!channel_type.supports_anchors_nonzero_fee_htlc_tx()); } else if channel_type.supports_scid_privacy() { channel_type.clear_scid_privacy(); @@ -4873,37 +5709,58 @@ impl ChannelContext where SP::Target: SignerProvider { } /// Asserts that the commitment tx numbers have not advanced from their initial number. - fn assert_no_commitment_advancement(&self, holder_commitment_transaction_number: u64, msg_name: &str) { - if self.commitment_secrets.get_min_seen_secret() != (1 << 48) || - self.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || - holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { - debug_assert!(false, "Should not have advanced channel commitment tx numbers prior to {}", - msg_name); + fn assert_no_commitment_advancement( + &self, holder_commitment_transaction_number: u64, msg_name: &str, + ) { + if self.commitment_secrets.get_min_seen_secret() != (1 << 48) + || self.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER + || holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER + { + debug_assert!( + false, + "Should not have advanced channel commitment tx numbers prior to {}", + msg_name + ); } } fn get_initial_counterparty_commitment_signature( - &self, funding: &FundingScope, logger: &L + &self, funding: &FundingScope, logger: &L, ) -> Result where SP::Target: SignerProvider, - L::Target: Logger + L::Target: Logger, { - let commitment_data = self.build_commitment_transaction(funding, + let commitment_data = self.build_commitment_transaction( + funding, self.cur_counterparty_commitment_transaction_number, - &self.counterparty_cur_commitment_point.unwrap(), false, false, logger); + &self.counterparty_cur_commitment_point.unwrap(), + false, + false, + logger, + ); let counterparty_initial_commitment_tx = commitment_data.tx; match self.holder_signer { // TODO (taproot|arik): move match into calling method for Taproot ChannelSignerType::Ecdsa(ref ecdsa) => { let channel_parameters = &funding.channel_transaction_parameters; - ecdsa.sign_counterparty_commitment(channel_parameters, &counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx) + ecdsa + .sign_counterparty_commitment( + channel_parameters, + &counterparty_initial_commitment_tx, + Vec::new(), + Vec::new(), + &self.secp_ctx, + ) .map(|(signature, _)| signature) - .map_err(|_| ChannelError::Close( - ( + .map_err(|_| { + ChannelError::Close(( "Failed to get signatures for new commitment_signed".to_owned(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, - ))) + ClosureReason::HolderForceClosed { + broadcasted_latest_txn: Some(false), + }, + )) + }) }, // TODO (taproot|arik) #[cfg(taproot)] @@ -4912,20 +5769,22 @@ impl ChannelContext where SP::Target: SignerProvider { } fn get_initial_commitment_signed( - &mut self, funding: &FundingScope, logger: &L + &mut self, funding: &FundingScope, logger: &L, ) -> Result where SP::Target: SignerProvider, - L::Target: Logger + L::Target: Logger, { if !matches!( self.channel_state, ChannelState::NegotiatingFunding(flags) if flags == (NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT) ) { debug_assert!(false); - return Err(ChannelError::Close(("Tried to get an initial commitment_signed messsage at a time other than \ - immediately after initial handshake completion (or tried to get funding_created twice)".to_string(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) } + return Err(ChannelError::Close(( + "Tried to get an initial commitment_signed messsage at a time other than \ + immediately after initial handshake completion (or tried to get funding_created twice)" + .to_string(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, ))); } @@ -4934,10 +5793,14 @@ impl ChannelContext where SP::Target: SignerProvider { Err(e) => { log_error!(logger, "Got bad signatures: {:?}!", e); return Err(e); - } + }, }; - log_info!(logger, "Generated commitment_signed for peer for channel {}", &self.channel_id()); + log_info!( + logger, + "Generated commitment_signed for peer for channel {}", + &self.channel_id() + ); Ok(msgs::CommitmentSigned { channel_id: self.channel_id, @@ -4956,7 +5819,7 @@ impl ChannelContext where SP::Target: SignerProvider { ) -> Result where SP::Target: SignerProvider, - L::Target: Logger + L::Target: Logger, { self.counterparty_cur_commitment_point = Some(counterparty_cur_commitment_point_override); self.get_initial_counterparty_commitment_signature(funding, logger) @@ -4972,7 +5835,9 @@ impl ChannelContext where SP::Target: SignerProvider { /// The effective percentage is lower bounded by 1% and upper bounded by 100%. /// /// [`ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel`]: crate::util::config::ChannelHandshakeConfig::max_inbound_htlc_value_in_flight_percent_of_channel -fn get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis: u64, config: &ChannelHandshakeConfig) -> u64 { +fn get_holder_max_htlc_value_in_flight_msat( + channel_value_satoshis: u64, config: &ChannelHandshakeConfig, +) -> u64 { let configured_percent = if config.max_inbound_htlc_value_in_flight_percent_of_channel < 1 { 1 } else if config.max_inbound_htlc_value_in_flight_percent_of_channel > 100 { @@ -4991,8 +5856,12 @@ fn get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis: u64, config: /// /// This is used both for outbound and inbound channels and has lower bound /// of `MIN_THEIR_CHAN_RESERVE_SATOSHIS`. -pub(crate) fn get_holder_selected_channel_reserve_satoshis(channel_value_satoshis: u64, config: &UserConfig) -> u64 { - let calculated_reserve = channel_value_satoshis.saturating_mul(config.channel_handshake_config.their_channel_reserve_proportional_millionths as u64) / 1_000_000; +pub(crate) fn get_holder_selected_channel_reserve_satoshis( + channel_value_satoshis: u64, config: &UserConfig, +) -> u64 { + let calculated_reserve = channel_value_satoshis.saturating_mul( + config.channel_handshake_config.their_channel_reserve_proportional_millionths as u64, + ) / 1_000_000; cmp::min(channel_value_satoshis, cmp::max(calculated_reserve, MIN_THEIR_CHAN_RESERVE_SATOSHIS)) } @@ -5000,7 +5869,9 @@ pub(crate) fn get_holder_selected_channel_reserve_satoshis(channel_value_satoshi /// LDK versions older than 0.0.104 don't know how read/handle values other than default /// from storage. Hence, we use this function to not persist default values of /// `holder_selected_channel_reserve_satoshis` for channels into storage. -pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 { +pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis( + channel_value_satoshis: u64, +) -> u64 { let (q, _) = channel_value_satoshis.overflowing_div(100); cmp::min(channel_value_satoshis, cmp::max(q, 1000)) } @@ -5039,9 +5910,12 @@ fn estimate_v2_funding_transaction_fee( // The weight of the funding output, a P2WSH output // NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want // to calculate the contributed weight, so we use an all-zero hash. - .saturating_add(get_output_weight(&ScriptBuf::new_p2wsh( - &WScriptHash::from_raw_hash(Hash::all_zeros()) - )).to_wu()) + .saturating_add( + get_output_weight(&ScriptBuf::new_p2wsh(&WScriptHash::from_raw_hash( + Hash::all_zeros(), + ))) + .to_wu(), + ) } fee_for_weight(funding_feerate_sat_per_1000_weight, weight) @@ -5058,14 +5932,20 @@ fn check_v2_funding_inputs_sufficient( contribution_amount: i64, funding_inputs: &[(TxIn, Transaction, Weight)], is_initiator: bool, is_splice: bool, funding_feerate_sat_per_1000_weight: u32, ) -> Result { - let mut total_input_witness_weight = Weight::from_wu(funding_inputs.iter().map(|(_, _, w)| w.to_wu()).sum()); + let mut total_input_witness_weight = + Weight::from_wu(funding_inputs.iter().map(|(_, _, w)| w.to_wu()).sum()); let mut funding_inputs_len = funding_inputs.len(); if is_initiator && is_splice { // consider the weight of the input and witness needed for spending the old funding transaction funding_inputs_len += 1; total_input_witness_weight += Weight::from_wu(FUNDING_TRANSACTION_WITNESS_WEIGHT); } - let estimated_fee = estimate_v2_funding_transaction_fee(is_initiator, funding_inputs_len, total_input_witness_weight, funding_feerate_sat_per_1000_weight); + let estimated_fee = estimate_v2_funding_transaction_fee( + is_initiator, + funding_inputs_len, + total_input_witness_weight, + funding_feerate_sat_per_1000_weight, + ); let mut total_input_sats = 0u64; for (idx, input) in funding_inputs.iter().enumerate() { @@ -5127,7 +6007,10 @@ pub(super) struct DualFundingChannelContext { // Holder designates channel data owned for the benefit of the user client. // Counterparty designates channel data owned by the another channel participant entity. -pub(super) struct FundedChannel where SP::Target: SignerProvider { +pub(super) struct FundedChannel +where + SP::Target: SignerProvider, +{ pub funding: FundingScope, pending_funding: Vec, pub context: ChannelContext, @@ -5169,7 +6052,12 @@ trait FailHTLCContents { impl FailHTLCContents for msgs::OnionErrorPacket { type Message = msgs::UpdateFailHTLC; fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message { - msgs::UpdateFailHTLC { htlc_id, channel_id, reason: self.data, attribution_data: self.attribution_data } + msgs::UpdateFailHTLC { + htlc_id, + channel_id, + reason: self.data, + attribution_data: self.attribution_data, + } } fn to_inbound_htlc_state(self) -> InboundHTLCState { InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(self)) @@ -5185,7 +6073,7 @@ impl FailHTLCContents for ([u8; 32], u16) { htlc_id, channel_id, sha256_of_onion: self.0, - failure_code: self.1 + failure_code: self.1, } } fn to_inbound_htlc_state(self) -> InboundHTLCState { @@ -5195,7 +6083,7 @@ impl FailHTLCContents for ([u8; 32], u16) { HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, sha256_of_onion: self.0, - failure_code: self.1 + failure_code: self.1, } } } @@ -5214,14 +6102,18 @@ impl FailHTLCMessageName for msgs::UpdateFailMalformedHTLC { } } -impl FundedChannel where +impl FundedChannel +where SP::Target: SignerProvider, - ::EcdsaSigner: EcdsaChannelSigner + ::EcdsaSigner: EcdsaChannelSigner, { fn check_remote_fee( channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator, - feerate_per_kw: u32, cur_feerate_per_kw: Option, logger: &L - ) -> Result<(), ChannelError> where F::Target: FeeEstimator, L::Target: Logger, + feerate_per_kw: u32, cur_feerate_per_kw: Option, logger: &L, + ) -> Result<(), ChannelError> + where + F::Target: FeeEstimator, + L::Target: Logger, { let lower_limit_conf_target = if channel_type.supports_anchors_zero_fee_htlc_tx() { ConfirmationTarget::MinAllowedAnchorChannelRemoteFee @@ -5238,12 +6130,16 @@ impl FundedChannel where return Ok(()); } } - return Err(ChannelError::Close((format!( - "Peer's feerate much too low. Actual: {}. Our expected lower limit: {}", feerate_per_kw, lower_limit - ), ClosureReason::PeerFeerateTooLow { - peer_feerate_sat_per_kw: feerate_per_kw, - required_feerate_sat_per_kw: lower_limit, - }))); + return Err(ChannelError::Close(( + format!( + "Peer's feerate much too low. Actual: {}. Our expected lower limit: {}", + feerate_per_kw, lower_limit + ), + ClosureReason::PeerFeerateTooLow { + peer_feerate_sat_per_kw: feerate_per_kw, + required_feerate_sat_per_kw: lower_limit, + }, + ))); } Ok(()) } @@ -5257,9 +6153,10 @@ impl FundedChannel where } #[inline] - fn get_closing_transaction_weight(&self, a_scriptpubkey: Option<&Script>, b_scriptpubkey: Option<&Script>) -> u64 { - let mut ret = - (4 + // version + fn get_closing_transaction_weight( + &self, a_scriptpubkey: Option<&Script>, b_scriptpubkey: Option<&Script>, + ) -> u64 { + let mut ret = (4 + // version 1 + // input count 36 + // prevout 1 + // script length (0) @@ -5271,27 +6168,34 @@ impl FundedChannel where 1 + // witness element count 4 + // 4 element lengths (2 sigs, multisig dummy, and witness script) self.funding.get_funding_redeemscript().len() as u64 + // funding witness script - 2*(1 + 71); // two signatures + sighash type flags + 2*(1 + 71); // two signatures + sighash type flags if let Some(spk) = a_scriptpubkey { ret += ((8+1) + // output values and script length - spk.len() as u64) * 4; // scriptpubkey and witness multiplier + spk.len() as u64) + * 4; // scriptpubkey and witness multiplier } if let Some(spk) = b_scriptpubkey { ret += ((8+1) + // output values and script length - spk.len() as u64) * 4; // scriptpubkey and witness multiplier + spk.len() as u64) + * 4; // scriptpubkey and witness multiplier } ret } #[inline] - fn build_closing_transaction(&self, proposed_total_fee_satoshis: u64, skip_remote_output: bool) -> Result<(ClosingTransaction, u64), ChannelError> { + fn build_closing_transaction( + &self, proposed_total_fee_satoshis: u64, skip_remote_output: bool, + ) -> Result<(ClosingTransaction, u64), ChannelError> { assert!(self.context.pending_inbound_htlcs.is_empty()); assert!(self.context.pending_outbound_htlcs.is_empty()); assert!(self.context.pending_update_fee.is_none()); let mut total_fee_satoshis = proposed_total_fee_satoshis; - let mut value_to_holder: i64 = (self.funding.value_to_self_msat as i64) / 1000 - if self.funding.is_outbound() { total_fee_satoshis as i64 } else { 0 }; - let mut value_to_counterparty: i64 = ((self.funding.get_value_satoshis() * 1000 - self.funding.value_to_self_msat) as i64 / 1000) - if self.funding.is_outbound() { 0 } else { total_fee_satoshis as i64 }; + let mut value_to_holder: i64 = (self.funding.value_to_self_msat as i64) / 1000 + - if self.funding.is_outbound() { total_fee_satoshis as i64 } else { 0 }; + let mut value_to_counterparty: i64 = + ((self.funding.get_value_satoshis() * 1000 - self.funding.value_to_self_msat) as i64 + / 1000) - if self.funding.is_outbound() { 0 } else { total_fee_satoshis as i64 }; if value_to_holder < 0 { assert!(self.funding.is_outbound()); @@ -5303,15 +6207,23 @@ impl FundedChannel where debug_assert!(value_to_counterparty >= 0); if value_to_counterparty < 0 { - return Err(ChannelError::close(format!("Value to counterparty below 0: {}", value_to_counterparty))) + return Err(ChannelError::close(format!( + "Value to counterparty below 0: {}", + value_to_counterparty + ))); } - if skip_remote_output || value_to_counterparty as u64 <= self.context.holder_dust_limit_satoshis { + if skip_remote_output + || value_to_counterparty as u64 <= self.context.holder_dust_limit_satoshis + { value_to_counterparty = 0; } debug_assert!(value_to_holder >= 0); if value_to_holder < 0 { - return Err(ChannelError::close(format!("Value to holder below 0: {}", value_to_holder))) + return Err(ChannelError::close(format!( + "Value to holder below 0: {}", + value_to_holder + ))); } if value_to_holder as u64 <= self.context.holder_dust_limit_satoshis { value_to_holder = 0; @@ -5319,10 +6231,17 @@ impl FundedChannel where assert!(self.context.shutdown_scriptpubkey.is_some()); let holder_shutdown_script = self.get_closing_scriptpubkey(); - let counterparty_shutdown_script = self.context.counterparty_shutdown_scriptpubkey.clone().unwrap(); + let counterparty_shutdown_script = + self.context.counterparty_shutdown_scriptpubkey.clone().unwrap(); let funding_outpoint = self.funding_outpoint().into_bitcoin_outpoint(); - let closing_transaction = ClosingTransaction::new(value_to_holder as u64, value_to_counterparty as u64, holder_shutdown_script, counterparty_shutdown_script, funding_outpoint); + let closing_transaction = ClosingTransaction::new( + value_to_holder as u64, + value_to_counterparty as u64, + holder_shutdown_script, + counterparty_shutdown_script, + funding_outpoint, + ); Ok((closing_transaction, total_fee_satoshis)) } @@ -5340,14 +6259,17 @@ impl FundedChannel where /// /// The HTLC claim will end up in the holding cell (because the caller must ensure the peer is /// disconnected). - pub fn claim_htlc_while_disconnected_dropping_mon_update_legacy - (&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) - where L::Target: Logger { + pub fn claim_htlc_while_disconnected_dropping_mon_update_legacy( + &mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L, + ) where + L::Target: Logger, + { // Assert that we'll add the HTLC claim to the holding cell in `get_update_fulfill_htlc` // (see equivalent if condition there). assert!(!self.context.channel_state.can_generate_new_commitment()); let mon_update_id = self.context.latest_monitor_update_id; // Forget the ChannelMonitor update - let fulfill_resp = self.get_update_fulfill_htlc(htlc_id_arg, payment_preimage_arg, None, logger); + let fulfill_resp = + self.get_update_fulfill_htlc(htlc_id_arg, payment_preimage_arg, None, logger); self.context.latest_monitor_update_id = mon_update_id; if let UpdateFulfillFetch::NewClaim { msg, .. } = fulfill_resp { assert!(msg.is_none()); // The HTLC must have ended up in the holding cell. @@ -5357,7 +6279,10 @@ impl FundedChannel where fn get_update_fulfill_htlc( &mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, payment_info: Option, logger: &L, - ) -> UpdateFulfillFetch where L::Target: Logger { + ) -> UpdateFulfillFetch + where + L::Target: Logger, + { // Either ChannelReady got set (which means it won't be unset) or there is no way any // caller thought we could have something claimed (cause we wouldn't have accepted in an // incoming HTLC anyway). If we got to ShutdownComplete, callers aren't allowed to call us, @@ -5374,23 +6299,34 @@ impl FundedChannel where let mut htlc_value_msat = 0; for (idx, htlc) in self.context.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { - debug_assert_eq!(htlc.payment_hash, PaymentHash(Sha256::hash(&payment_preimage_arg.0[..]).to_byte_array())); - log_debug!(logger, "Claiming inbound HTLC id {} with payment hash {} with preimage {}", - htlc.htlc_id, htlc.payment_hash, payment_preimage_arg); + debug_assert_eq!( + htlc.payment_hash, + PaymentHash(Sha256::hash(&payment_preimage_arg.0[..]).to_byte_array()) + ); + log_debug!( + logger, + "Claiming inbound HTLC id {} with payment hash {} with preimage {}", + htlc.htlc_id, + htlc.payment_hash, + payment_preimage_arg + ); match htlc.state { InboundHTLCState::Committed => {}, InboundHTLCState::LocalRemoved(ref reason) => { if let &InboundHTLCRemovalReason::Fulfill(_) = reason { } else { log_warn!(logger, "Have preimage and want to fulfill HTLC with payment hash {} we already failed against channel {}", &htlc.payment_hash, &self.context.channel_id()); - debug_assert!(false, "Tried to fulfill an HTLC that was already failed"); + debug_assert!( + false, + "Tried to fulfill an HTLC that was already failed" + ); } return UpdateFulfillFetch::DuplicateClaim {}; }, _ => { debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); // Don't return in release mode here so that we can update channel_monitor - } + }, } pending_idx = idx; htlc_value_msat = htlc.amount_msat; @@ -5429,23 +6365,35 @@ impl FundedChannel where return UpdateFulfillFetch::DuplicateClaim {}; } }, - &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } | - &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => - { + &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } + | &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { log_warn!(logger, "Have preimage and want to fulfill HTLC with pending failure against channel {}", &self.context.channel_id()); // TODO: We may actually be able to switch to a fulfill here, though its // rare enough it may not be worth the complexity burden. - debug_assert!(false, "Tried to fulfill an HTLC that was already failed"); - return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None }; + debug_assert!( + false, + "Tried to fulfill an HTLC that was already failed" + ); + return UpdateFulfillFetch::NewClaim { + monitor_update, + htlc_value_msat, + msg: None, + }; } }, - _ => {} + _ => {}, } } - log_trace!(logger, "Adding HTLC claim to holding_cell in channel {}! Current state: {}", &self.context.channel_id(), self.context.channel_state.to_u32()); + log_trace!( + logger, + "Adding HTLC claim to holding_cell in channel {}! Current state: {}", + &self.context.channel_id(), + self.context.channel_state.to_u32() + ); self.context.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::ClaimHTLC { - payment_preimage: payment_preimage_arg, htlc_id: htlc_id_arg, + payment_preimage: payment_preimage_arg, + htlc_id: htlc_id_arg, }); return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None }; } @@ -5454,11 +6402,21 @@ impl FundedChannel where let htlc = &mut self.context.pending_inbound_htlcs[pending_idx]; if let InboundHTLCState::Committed = htlc.state { } else { - debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); + debug_assert!( + false, + "Have an inbound HTLC we tried to claim before it was fully committed to" + ); return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None }; } - log_trace!(logger, "Upgrading HTLC {} to LocalRemoved with a Fulfill in channel {}!", &htlc.payment_hash, &self.context.channel_id); - htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(payment_preimage_arg.clone())); + log_trace!( + logger, + "Upgrading HTLC {} to LocalRemoved with a Fulfill in channel {}!", + &htlc.payment_hash, + &self.context.channel_id + ); + htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill( + payment_preimage_arg.clone(), + )); } UpdateFulfillFetch::NewClaim { @@ -5475,7 +6433,10 @@ impl FundedChannel where pub fn get_update_fulfill_htlc_and_commit( &mut self, htlc_id: u64, payment_preimage: PaymentPreimage, payment_info: Option, logger: &L, - ) -> UpdateFulfillCommitFetch where L::Target: Logger { + ) -> UpdateFulfillCommitFetch + where + L::Target: Logger, + { let release_cs_monitor = self.context.blocked_monitor_updates.is_empty(); match self.get_update_fulfill_htlc(htlc_id, payment_preimage, payment_info, logger) { UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => { @@ -5491,8 +6452,12 @@ impl FundedChannel where self.context.latest_monitor_update_id = monitor_update.update_id; monitor_update.updates.append(&mut additional_update.updates); } else { - let new_mon_id = self.context.blocked_monitor_updates.get(0) - .map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id); + let new_mon_id = self + .context + .blocked_monitor_updates + .get(0) + .map(|upd| upd.update.update_id) + .unwrap_or(monitor_update.update_id); monitor_update.update_id = new_mon_id; for held_update in self.context.blocked_monitor_updates.iter_mut() { held_update.update.update_id += 1; @@ -5500,14 +6465,21 @@ impl FundedChannel where if msg.is_some() { debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set"); let update = self.build_commitment_no_status_check(logger); - self.context.blocked_monitor_updates.push(PendingChannelMonitorUpdate { - update, - }); + self.context + .blocked_monitor_updates + .push(PendingChannelMonitorUpdate { update }); } } - self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new()); - UpdateFulfillCommitFetch::NewClaim { monitor_update, htlc_value_msat, } + self.monitor_updating_paused( + false, + msg.is_some(), + false, + Vec::new(), + Vec::new(), + Vec::new(), + ); + UpdateFulfillCommitFetch::NewClaim { monitor_update, htlc_value_msat } }, UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {}, } @@ -5515,8 +6487,12 @@ impl FundedChannel where /// Returns `Err` (always with [`ChannelError::Ignore`]) if the HTLC could not be failed (e.g. /// if it was already resolved). Otherwise returns `Ok`. - pub fn queue_fail_htlc(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, logger: &L) - -> Result<(), ChannelError> where L::Target: Logger { + pub fn queue_fail_htlc( + &mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, logger: &L, + ) -> Result<(), ChannelError> + where + L::Target: Logger, + { self.fail_htlc(htlc_id_arg, err_packet, true, logger) .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?")) } @@ -5526,8 +6502,11 @@ impl FundedChannel where /// /// See [`Self::queue_fail_htlc`] for more info. pub fn queue_fail_malformed_htlc( - &mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32], logger: &L - ) -> Result<(), ChannelError> where L::Target: Logger { + &mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32], logger: &L, + ) -> Result<(), ChannelError> + where + L::Target: Logger, + { self.fail_htlc(htlc_id_arg, (sha256_of_onion, failure_code), true, logger) .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?")) } @@ -5535,9 +6514,11 @@ impl FundedChannel where /// Returns `Err` (always with [`ChannelError::Ignore`]) if the HTLC could not be failed (e.g. /// if it was already resolved). Otherwise returns `Ok`. fn fail_htlc( - &mut self, htlc_id_arg: u64, err_contents: E, mut force_holding_cell: bool, - logger: &L - ) -> Result, ChannelError> where L::Target: Logger { + &mut self, htlc_id_arg: u64, err_contents: E, mut force_holding_cell: bool, logger: &L, + ) -> Result, ChannelError> + where + L::Target: Logger, + { if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { panic!("Was asked to fail an HTLC when channel was not in an operational state"); } @@ -5552,18 +6533,27 @@ impl FundedChannel where match htlc.state { InboundHTLCState::Committed => {}, InboundHTLCState::LocalRemoved(_) => { - return Err(ChannelError::Ignore(format!("HTLC {} was already resolved", htlc.htlc_id))); + return Err(ChannelError::Ignore(format!( + "HTLC {} was already resolved", + htlc.htlc_id + ))); }, _ => { debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); - return Err(ChannelError::Ignore(format!("Unable to find a pending HTLC which matched the given HTLC ID ({})", htlc.htlc_id))); - } + return Err(ChannelError::Ignore(format!( + "Unable to find a pending HTLC which matched the given HTLC ID ({})", + htlc.htlc_id + ))); + }, } pending_idx = idx; } } if pending_idx == core::usize::MAX { - return Err(ChannelError::Ignore(format!("Unable to find a pending HTLC which matched the given HTLC ID ({})", htlc_id_arg))); + return Err(ChannelError::Ignore(format!( + "Unable to find a pending HTLC which matched the given HTLC ID ({})", + htlc_id_arg + ))); } if !self.context.channel_state.can_generate_new_commitment() { @@ -5577,26 +6567,43 @@ impl FundedChannel where match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - return Err(ChannelError::Ignore(format!("HTLC {} was already claimed!", htlc_id))); + return Err(ChannelError::Ignore(format!( + "HTLC {} was already claimed!", + htlc_id + ))); } }, - &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } | - &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => - { + &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } + | &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - return Err(ChannelError::Ignore(format!("HTLC {} was already pending failure", htlc_id))); + return Err(ChannelError::Ignore(format!( + "HTLC {} was already pending failure", + htlc_id + ))); } }, - _ => {} + _ => {}, } } - log_trace!(logger, "Placing failure for HTLC ID {} in holding cell in channel {}.", htlc_id_arg, &self.context.channel_id()); - self.context.holding_cell_htlc_updates.push(err_contents.to_htlc_update_awaiting_ack(htlc_id_arg)); + log_trace!( + logger, + "Placing failure for HTLC ID {} in holding cell in channel {}.", + htlc_id_arg, + &self.context.channel_id() + ); + self.context + .holding_cell_htlc_updates + .push(err_contents.to_htlc_update_awaiting_ack(htlc_id_arg)); return Ok(None); } - log_trace!(logger, "Failing HTLC ID {} back with {} message in channel {}.", htlc_id_arg, - E::Message::name(), &self.context.channel_id()); + log_trace!( + logger, + "Failing HTLC ID {} back with {} message in channel {}.", + htlc_id_arg, + E::Message::name(), + &self.context.channel_id() + ); { let htlc = &mut self.context.pending_inbound_htlcs[pending_idx]; htlc.state = err_contents.clone().to_inbound_htlc_state(); @@ -5630,11 +6637,11 @@ impl FundedChannel where /// reply with. pub fn channel_ready( &mut self, msg: &msgs::ChannelReady, node_signer: &NS, chain_hash: ChainHash, - user_config: &UserConfig, best_block: &BestBlock, logger: &L + user_config: &UserConfig, best_block: &BestBlock, logger: &L, ) -> Result, ChannelError> where NS::Target: NodeSigner, - L::Target: Logger + L::Target: Logger, { if self.context.channel_state.is_peer_disconnected() { self.context.workaround_lnd_bug_4006 = Some(msg.clone()); @@ -5656,76 +6663,122 @@ impl FundedChannel where match &self.context.channel_state { ChannelState::AwaitingChannelReady(flags) => { let flags = flags.clone().clear(FundedStateFlags::ALL.into()); - debug_assert!(!flags.is_set(AwaitingChannelReadyFlags::OUR_CHANNEL_READY) || !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)); - if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY { + debug_assert!( + !flags.is_set(AwaitingChannelReadyFlags::OUR_CHANNEL_READY) + || !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) + ); + if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) + == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY + { // If we reconnected before sending our `channel_ready` they may still resend theirs. check_reconnection = true; - } else if flags.clone().clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() { + } else if flags + .clone() + .clear(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) + .is_empty() + { self.context.channel_state.set_their_channel_ready(); } else if flags == AwaitingChannelReadyFlags::OUR_CHANNEL_READY { - self.context.channel_state = ChannelState::ChannelReady(self.context.channel_state.with_funded_state_flags_mask().into()); + self.context.channel_state = ChannelState::ChannelReady( + self.context.channel_state.with_funded_state_flags_mask().into(), + ); self.context.update_time_counter += 1; } else { // We're in `WAITING_FOR_BATCH`, so we should wait until we're ready. debug_assert!(flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)); } - } + }, // If we reconnected before sending our `channel_ready` they may still resend theirs. ChannelState::ChannelReady(_) => check_reconnection = true, - _ => return Err(ChannelError::close("Peer sent a channel_ready at a strange time".to_owned())), + _ => { + return Err(ChannelError::close( + "Peer sent a channel_ready at a strange time".to_owned(), + )) + }, } if check_reconnection { // They probably disconnected/reconnected and re-sent the channel_ready, which is // required, or they're sending a fresh SCID alias. - let expected_point = - if self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 { - // If they haven't ever sent an updated point, the point they send should match - // the current one. - self.context.counterparty_cur_commitment_point - } else if self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 2 { - // If we've advanced the commitment number once, the second commitment point is - // at `counterparty_prev_commitment_point`, which is not yet revoked. - debug_assert!(self.context.counterparty_prev_commitment_point.is_some()); - self.context.counterparty_prev_commitment_point - } else { - // If they have sent updated points, channel_ready is always supposed to match - // their "first" point, which we re-derive here. - Some(PublicKey::from_secret_key(&self.context.secp_ctx, &SecretKey::from_slice( + let expected_point = if self.context.cur_counterparty_commitment_transaction_number + == INITIAL_COMMITMENT_NUMBER - 1 + { + // If they haven't ever sent an updated point, the point they send should match + // the current one. + self.context.counterparty_cur_commitment_point + } else if self.context.cur_counterparty_commitment_transaction_number + == INITIAL_COMMITMENT_NUMBER - 2 + { + // If we've advanced the commitment number once, the second commitment point is + // at `counterparty_prev_commitment_point`, which is not yet revoked. + debug_assert!(self.context.counterparty_prev_commitment_point.is_some()); + self.context.counterparty_prev_commitment_point + } else { + // If they have sent updated points, channel_ready is always supposed to match + // their "first" point, which we re-derive here. + Some(PublicKey::from_secret_key(&self.context.secp_ctx, &SecretKey::from_slice( &self.context.commitment_secrets.get_secret(INITIAL_COMMITMENT_NUMBER - 1).expect("We should have all prev secrets available") ).expect("We already advanced, so previous secret keys should have been validated already"))) - }; + }; if expected_point != Some(msg.next_per_commitment_point) { - return Err(ChannelError::close("Peer sent a reconnect channel_ready with a different point".to_owned())); + return Err(ChannelError::close( + "Peer sent a reconnect channel_ready with a different point".to_owned(), + )); } return Ok(None); } - self.context.counterparty_prev_commitment_point = self.context.counterparty_cur_commitment_point; + self.context.counterparty_prev_commitment_point = + self.context.counterparty_cur_commitment_point; self.context.counterparty_cur_commitment_point = Some(msg.next_per_commitment_point); - log_info!(logger, "Received channel_ready from peer for channel {}", &self.context.channel_id()); + log_info!( + logger, + "Received channel_ready from peer for channel {}", + &self.context.channel_id() + ); - Ok(self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block.height, logger)) + Ok(self.get_announcement_sigs( + node_signer, + chain_hash, + user_config, + best_block.height, + logger, + )) } pub fn update_add_htlc( &mut self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator, - ) -> Result<(), ChannelError> where F::Target: FeeEstimator { - if self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got add HTLC message while quiescent".to_owned())); + ) -> Result<(), ChannelError> + where + F::Target: FeeEstimator, + { + if self.context.channel_state.is_remote_stfu_sent() + || self.context.channel_state.is_quiescent() + { + return Err(ChannelError::WarnAndDisconnect( + "Got add HTLC message while quiescent".to_owned(), + )); } if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { - return Err(ChannelError::close("Got add HTLC message when channel was not in an operational state".to_owned())); + return Err(ChannelError::close( + "Got add HTLC message when channel was not in an operational state".to_owned(), + )); } // If the remote has sent a shutdown prior to adding this HTLC, then they are in violation of the spec. if self.context.channel_state.is_remote_shutdown_sent() { - return Err(ChannelError::close("Got add HTLC message when channel was not in an operational state".to_owned())); + return Err(ChannelError::close( + "Got add HTLC message when channel was not in an operational state".to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent update_add_htlc when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent update_add_htlc when we needed a channel_reestablish".to_owned(), + )); } if msg.amount_msat > self.funding.get_value_satoshis() * 1000 { - return Err(ChannelError::close("Remote side tried to send more than the total value of the channel".to_owned())); + return Err(ChannelError::close( + "Remote side tried to send more than the total value of the channel".to_owned(), + )); } if msg.amount_msat == 0 { return Err(ChannelError::close("Remote side tried to send a 0-msat HTLC".to_owned())); @@ -5734,13 +6787,26 @@ impl FundedChannel where return Err(ChannelError::close(format!("Remote side tried to send less than our minimum HTLC value. Lower limit: ({}). Actual: ({})", self.context.holder_htlc_minimum_msat, msg.amount_msat))); } - let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator); - let htlc_stats = self.context.get_pending_htlc_stats(&self.funding, None, dust_exposure_limiting_feerate); + let dust_exposure_limiting_feerate = + self.context.get_dust_exposure_limiting_feerate(&fee_estimator); + let htlc_stats = self.context.get_pending_htlc_stats( + &self.funding, + None, + dust_exposure_limiting_feerate, + ); if htlc_stats.pending_inbound_htlcs + 1 > self.context.holder_max_accepted_htlcs as usize { - return Err(ChannelError::close(format!("Remote tried to push more than our max accepted HTLCs ({})", self.context.holder_max_accepted_htlcs))); + return Err(ChannelError::close(format!( + "Remote tried to push more than our max accepted HTLCs ({})", + self.context.holder_max_accepted_htlcs + ))); } - if htlc_stats.pending_inbound_htlcs_value_msat + msg.amount_msat > self.context.holder_max_htlc_value_in_flight_msat { - return Err(ChannelError::close(format!("Remote HTLC add would put them over our max HTLC value ({})", self.context.holder_max_htlc_value_in_flight_msat))); + if htlc_stats.pending_inbound_htlcs_value_msat + msg.amount_msat + > self.context.holder_max_htlc_value_in_flight_msat + { + return Err(ChannelError::close(format!( + "Remote HTLC add would put them over our max HTLC value ({})", + self.context.holder_max_htlc_value_in_flight_msat + ))); } // Check holder_selected_channel_reserve_satoshis (we're getting paid, so they have to at least meet @@ -5757,59 +6823,101 @@ impl FundedChannel where // transaction). let mut removed_outbound_total_msat = 0; for ref htlc in self.context.pending_outbound_htlcs.iter() { - if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) = htlc.state { + if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success( + _, + )) = htlc.state + { removed_outbound_total_msat += htlc.amount_msat; - } else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) = htlc.state { + } else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke( + OutboundHTLCOutcome::Success(_), + ) = htlc.state + { removed_outbound_total_msat += htlc.amount_msat; } } - let pending_value_to_self_msat = - self.funding.value_to_self_msat + htlc_stats.pending_inbound_htlcs_value_msat - removed_outbound_total_msat; + let pending_value_to_self_msat = self.funding.value_to_self_msat + + htlc_stats.pending_inbound_htlcs_value_msat + - removed_outbound_total_msat; let pending_remote_value_msat = self.funding.get_value_satoshis() * 1000 - pending_value_to_self_msat; if pending_remote_value_msat < msg.amount_msat { - return Err(ChannelError::close("Remote HTLC add would overdraw remaining funds".to_owned())); + return Err(ChannelError::close( + "Remote HTLC add would overdraw remaining funds".to_owned(), + )); } // Check that the remote can afford to pay for this HTLC on-chain at the current // feerate_per_kw, while maintaining their channel reserve (as required by the spec). { - let remote_commit_tx_fee_msat = if self.funding.is_outbound() { 0 } else { - let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); - self.context.next_remote_commit_tx_fee_msat(&self.funding, Some(htlc_candidate), None) // Don't include the extra fee spike buffer HTLC in calculations + let remote_commit_tx_fee_msat = if self.funding.is_outbound() { + 0 + } else { + let htlc_candidate = + HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); + self.context.next_remote_commit_tx_fee_msat( + &self.funding, + Some(htlc_candidate), + None, + ) // Don't include the extra fee spike buffer HTLC in calculations }; - let anchor_outputs_value_msat = if !self.funding.is_outbound() && self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + let anchor_outputs_value_msat = if !self.funding.is_outbound() + && self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() + { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 } else { 0 }; - if pending_remote_value_msat.saturating_sub(msg.amount_msat).saturating_sub(anchor_outputs_value_msat) < remote_commit_tx_fee_msat { - return Err(ChannelError::close("Remote HTLC add would not leave enough to pay for fees".to_owned())); + if pending_remote_value_msat + .saturating_sub(msg.amount_msat) + .saturating_sub(anchor_outputs_value_msat) + < remote_commit_tx_fee_msat + { + return Err(ChannelError::close( + "Remote HTLC add would not leave enough to pay for fees".to_owned(), + )); }; - if pending_remote_value_msat.saturating_sub(msg.amount_msat).saturating_sub(remote_commit_tx_fee_msat).saturating_sub(anchor_outputs_value_msat) < self.funding.holder_selected_channel_reserve_satoshis * 1000 { - return Err(ChannelError::close("Remote HTLC add would put them under remote reserve value".to_owned())); + if pending_remote_value_msat + .saturating_sub(msg.amount_msat) + .saturating_sub(remote_commit_tx_fee_msat) + .saturating_sub(anchor_outputs_value_msat) + < self.funding.holder_selected_channel_reserve_satoshis * 1000 + { + return Err(ChannelError::close( + "Remote HTLC add would put them under remote reserve value".to_owned(), + )); } } - let anchor_outputs_value_msat = if self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 - } else { - 0 - }; + let anchor_outputs_value_msat = + if self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 + } else { + 0 + }; if self.funding.is_outbound() { // Check that they won't violate our local required channel reserve by adding this HTLC. let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); - let local_commit_tx_fee_msat = self.context.next_local_commit_tx_fee_msat(&self.funding, htlc_candidate, None); - if self.funding.value_to_self_msat < self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 + local_commit_tx_fee_msat + anchor_outputs_value_msat { + let local_commit_tx_fee_msat = + self.context.next_local_commit_tx_fee_msat(&self.funding, htlc_candidate, None); + if self.funding.value_to_self_msat + < self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 + + local_commit_tx_fee_msat + + anchor_outputs_value_msat + { return Err(ChannelError::close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned())); } } if self.context.next_counterparty_htlc_id != msg.htlc_id { - return Err(ChannelError::close(format!("Remote skipped HTLC ID (skipped ID: {})", self.context.next_counterparty_htlc_id))); + return Err(ChannelError::close(format!( + "Remote skipped HTLC ID (skipped ID: {})", + self.context.next_counterparty_htlc_id + ))); } if msg.cltv_expiry >= 500000000 { - return Err(ChannelError::close("Remote provided CLTV expiry in seconds instead of block height".to_owned())); + return Err(ChannelError::close( + "Remote provided CLTV expiry in seconds instead of block height".to_owned(), + )); } // Now update local state: @@ -5828,13 +6936,19 @@ impl FundedChannel where /// Marks an outbound HTLC which we have received update_fail/fulfill/malformed #[inline] - fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, outcome: OutboundHTLCOutcome) -> Result<&OutboundHTLCOutput, ChannelError> { + fn mark_outbound_htlc_removed( + &mut self, htlc_id: u64, outcome: OutboundHTLCOutcome, + ) -> Result<&OutboundHTLCOutput, ChannelError> { for htlc in self.context.pending_outbound_htlcs.iter_mut() { if htlc.htlc_id == htlc_id { if let OutboundHTLCOutcome::Success(ref payment_preimage) = outcome { - let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()); + let payment_hash = + PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()); if payment_hash != htlc.payment_hash { - return Err(ChannelError::close(format!("Remote tried to fulfill HTLC ({}) with an incorrect preimage", htlc_id))); + return Err(ChannelError::close(format!( + "Remote tried to fulfill HTLC ({}) with an incorrect preimage", + htlc_id + ))); } } match htlc.state { @@ -5852,44 +6966,80 @@ impl FundedChannel where Err(ChannelError::close("Remote tried to fulfill/fail an HTLC we couldn't find".to_owned())) } - pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<(HTLCSource, u64, Option), ChannelError> { - if self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got fulfill HTLC message while quiescent".to_owned())); + pub fn update_fulfill_htlc( + &mut self, msg: &msgs::UpdateFulfillHTLC, + ) -> Result<(HTLCSource, u64, Option), ChannelError> { + if self.context.channel_state.is_remote_stfu_sent() + || self.context.channel_state.is_quiescent() + { + return Err(ChannelError::WarnAndDisconnect( + "Got fulfill HTLC message while quiescent".to_owned(), + )); } if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { - return Err(ChannelError::close("Got fulfill HTLC message when channel was not in an operational state".to_owned())); + return Err(ChannelError::close( + "Got fulfill HTLC message when channel was not in an operational state".to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent update_fulfill_htlc when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent update_fulfill_htlc when we needed a channel_reestablish".to_owned(), + )); } - self.mark_outbound_htlc_removed(msg.htlc_id, OutboundHTLCOutcome::Success(msg.payment_preimage)).map(|htlc| (htlc.source.clone(), htlc.amount_msat, htlc.skimmed_fee_msat)) + self.mark_outbound_htlc_removed( + msg.htlc_id, + OutboundHTLCOutcome::Success(msg.payment_preimage), + ) + .map(|htlc| (htlc.source.clone(), htlc.amount_msat, htlc.skimmed_fee_msat)) } - pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> { - if self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got fail HTLC message while quiescent".to_owned())); + pub fn update_fail_htlc( + &mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason, + ) -> Result<(), ChannelError> { + if self.context.channel_state.is_remote_stfu_sent() + || self.context.channel_state.is_quiescent() + { + return Err(ChannelError::WarnAndDisconnect( + "Got fail HTLC message while quiescent".to_owned(), + )); } if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { - return Err(ChannelError::close("Got fail HTLC message when channel was not in an operational state".to_owned())); + return Err(ChannelError::close( + "Got fail HTLC message when channel was not in an operational state".to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent update_fail_htlc when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent update_fail_htlc when we needed a channel_reestablish".to_owned(), + )); } self.mark_outbound_htlc_removed(msg.htlc_id, OutboundHTLCOutcome::Failure(fail_reason))?; Ok(()) } - pub fn update_fail_malformed_htlc(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> { - if self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got fail malformed HTLC message while quiescent".to_owned())); + pub fn update_fail_malformed_htlc( + &mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason, + ) -> Result<(), ChannelError> { + if self.context.channel_state.is_remote_stfu_sent() + || self.context.channel_state.is_quiescent() + { + return Err(ChannelError::WarnAndDisconnect( + "Got fail malformed HTLC message while quiescent".to_owned(), + )); } if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { - return Err(ChannelError::close("Got fail malformed HTLC message when channel was not in an operational state".to_owned())); + return Err(ChannelError::close( + "Got fail malformed HTLC message when channel was not in an operational state" + .to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent update_fail_malformed_htlc when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent update_fail_malformed_htlc when we needed a channel_reestablish" + .to_owned(), + )); } self.mark_outbound_htlc_removed(msg.htlc_id, OutboundHTLCOutcome::Failure(fail_reason))?; @@ -5897,38 +7047,65 @@ impl FundedChannel where } pub fn commitment_signed_initial_v2( - &mut self, msg: &msgs::CommitmentSigned, best_block: BestBlock, signer_provider: &SP, logger: &L + &mut self, msg: &msgs::CommitmentSigned, best_block: BestBlock, signer_provider: &SP, + logger: &L, ) -> Result::EcdsaSigner>, ChannelError> - where L::Target: Logger + where + L::Target: Logger, { if !matches!(self.context.channel_state, ChannelState::FundingNegotiated) { - return Err(ChannelError::Close( - ( - "Received initial commitment_signed before funding transaction constructed!".to_owned(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, - ))); + return Err(ChannelError::Close(( + "Received initial commitment_signed before funding transaction constructed!" + .to_owned(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + ))); } if msg.batch.is_some() { - return Err(ChannelError::close("Peer sent initial commitment_signed with a batch".to_owned())); + return Err(ChannelError::close( + "Peer sent initial commitment_signed with a batch".to_owned(), + )); } let holder_commitment_point = &mut self.holder_commitment_point.clone(); - self.context.assert_no_commitment_advancement(holder_commitment_point.transaction_number(), "initial commitment_signed"); + self.context.assert_no_commitment_advancement( + holder_commitment_point.transaction_number(), + "initial commitment_signed", + ); let (channel_monitor, _) = self.initial_commitment_signed( - self.context.channel_id(), msg.signature, holder_commitment_point, best_block, signer_provider, logger)?; + self.context.channel_id(), + msg.signature, + holder_commitment_point, + best_block, + signer_provider, + logger, + )?; self.holder_commitment_point = *holder_commitment_point; - log_info!(logger, "Received initial commitment_signed from peer for channel {}", &self.context.channel_id()); + log_info!( + logger, + "Received initial commitment_signed from peer for channel {}", + &self.context.channel_id() + ); let need_channel_ready = self.check_get_channel_ready(0, logger).is_some(); - self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); - self.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new()); + self.context.channel_state = + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); + self.monitor_updating_paused( + false, + false, + need_channel_ready, + Vec::new(), + Vec::new(), + Vec::new(), + ); - if let Some(tx_signatures) = self.interactive_tx_signing_session.as_mut().and_then( - |session| session.received_commitment_signed() - ) { + if let Some(tx_signatures) = self + .interactive_tx_signing_session + .as_mut() + .and_then(|session| session.received_commitment_signed()) + { // We're up first for submitting our tx_signatures, but our monitor has not persisted yet // so they'll be sent as soon as that's done. self.context.monitor_pending_tx_signatures = Some(tx_signatures); @@ -5937,25 +7114,40 @@ impl FundedChannel where Ok(channel_monitor) } - pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result, ChannelError> - where L::Target: Logger + pub fn commitment_signed( + &mut self, msg: &msgs::CommitmentSigned, logger: &L, + ) -> Result, ChannelError> + where + L::Target: Logger, { self.commitment_signed_check_state()?; let updates = self .context .validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger) - .map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }| - vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { - commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources, - }] + .map( + |LatestHolderCommitmentTXInfo { + commitment_tx, + htlc_outputs, + nondust_htlc_sources, + }| { + vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { + commitment_tx, + htlc_outputs, + claimed_htlcs: vec![], + nondust_htlc_sources, + }] + }, )?; self.commitment_signed_update_monitor(updates, logger) } - pub fn commitment_signed_batch(&mut self, batch: &BTreeMap, logger: &L) -> Result, ChannelError> - where L::Target: Logger + pub fn commitment_signed_batch( + &mut self, batch: &BTreeMap, logger: &L, + ) -> Result, ChannelError> + where + L::Target: Logger, { self.commitment_signed_check_state()?; @@ -5965,18 +7157,27 @@ impl FundedChannel where .chain(self.pending_funding.iter()) .map(|funding| { let funding_txid = funding.get_funding_txo().unwrap().txid; - let msg = batch - .get(&funding_txid) - .ok_or_else(|| ChannelError::close(format!("Peer did not send a commitment_signed for pending splice transaction: {}", funding_txid)))?; + let msg = batch.get(&funding_txid).ok_or_else(|| { + ChannelError::close(format!( + "Peer did not send a commitment_signed for pending splice transaction: {}", + funding_txid + )) + })?; self.context .validate_commitment_signed(funding, &self.holder_commitment_point, msg, logger) - .map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }| - ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { - commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources, - } + .map( + |LatestHolderCommitmentTXInfo { + commitment_tx, + htlc_outputs, + nondust_htlc_sources, + }| ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { + commitment_tx, + htlc_outputs, + claimed_htlcs: vec![], + nondust_htlc_sources, + }, ) - } - ) + }) .collect::, ChannelError>>()?; self.commitment_signed_update_monitor(updates, logger) @@ -5984,25 +7185,44 @@ impl FundedChannel where fn commitment_signed_check_state(&self) -> Result<(), ChannelError> { if self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got commitment_signed message while quiescent".to_owned())); + return Err(ChannelError::WarnAndDisconnect( + "Got commitment_signed message while quiescent".to_owned(), + )); } if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { - return Err(ChannelError::close("Got commitment signed message when channel was not in an operational state".to_owned())); + return Err(ChannelError::close( + "Got commitment signed message when channel was not in an operational state" + .to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent commitment_signed when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent commitment_signed when we needed a channel_reestablish".to_owned(), + )); } - if self.context.channel_state.is_both_sides_shutdown() && self.context.last_sent_closing_fee.is_some() { - return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned())); + if self.context.channel_state.is_both_sides_shutdown() + && self.context.last_sent_closing_fee.is_some() + { + return Err(ChannelError::close( + "Peer sent commitment_signed after we'd started exchanging closing_signeds" + .to_owned(), + )); } Ok(()) } - fn commitment_signed_update_monitor(&mut self, mut updates: Vec, logger: &L) -> Result, ChannelError> - where L::Target: Logger + fn commitment_signed_update_monitor( + &mut self, mut updates: Vec, logger: &L, + ) -> Result, ChannelError> + where + L::Target: Logger, { - if self.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger).is_err() { + if self + .holder_commitment_point + .advance(&self.context.holder_signer, &self.context.secp_ctx, logger) + .is_err() + { // We only fail to advance our commitment point/number if we're currently // waiting for our signer to unblock and provide a commitment point. // During post-funding channel operation, we only advance our point upon @@ -6029,7 +7249,8 @@ impl FundedChannel where if let &InboundHTLCState::RemoteAnnounced(ref htlc_resolution) = &htlc.state { log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToAnnounce due to commitment_signed in channel {}.", &htlc.payment_hash, &self.context.channel_id); - htlc.state = InboundHTLCState::AwaitingRemoteRevokeToAnnounce(htlc_resolution.clone()); + htlc.state = + InboundHTLCState::AwaitingRemoteRevokeToAnnounce(htlc_resolution.clone()); need_commitment = true; } } @@ -6057,8 +7278,10 @@ impl FundedChannel where for mut update in updates.iter_mut() { if let ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { - claimed_htlcs: ref mut update_claimed_htlcs, .. - } = &mut update { + claimed_htlcs: ref mut update_claimed_htlcs, + .. + } = &mut update + { debug_assert!(update_claimed_htlcs.is_empty()); *update_claimed_htlcs = claimed_htlcs.clone(); } else { @@ -6098,21 +7321,31 @@ impl FundedChannel where return Ok(self.push_ret_blockable_mon_update(monitor_update)); } - let need_commitment_signed = if need_commitment && !self.context.channel_state.is_awaiting_remote_revoke() { - // If we're AwaitingRemoteRevoke we can't send a new commitment here, but that's ok - - // we'll send one right away when we get the revoke_and_ack when we - // free_holding_cell_htlcs(). - let mut additional_update = self.build_commitment_no_status_check(logger); - // build_commitment_no_status_check may bump latest_monitor_id but we want them to be - // strictly increasing by one, so decrement it here. - self.context.latest_monitor_update_id = monitor_update.update_id; - monitor_update.updates.append(&mut additional_update.updates); - true - } else { false }; - - log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.", - &self.context.channel_id(), if need_commitment_signed { " our own commitment_signed and" } else { "" }); - self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new()); + let need_commitment_signed = + if need_commitment && !self.context.channel_state.is_awaiting_remote_revoke() { + // If we're AwaitingRemoteRevoke we can't send a new commitment here, but that's ok - + // we'll send one right away when we get the revoke_and_ack when we + // free_holding_cell_htlcs(). + let mut additional_update = self.build_commitment_no_status_check(logger); + // build_commitment_no_status_check may bump latest_monitor_id but we want them to be + // strictly increasing by one, so decrement it here. + self.context.latest_monitor_update_id = monitor_update.update_id; + monitor_update.updates.append(&mut additional_update.updates); + true + } else { + false + }; + + log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.", + &self.context.channel_id(), if need_commitment_signed { " our own commitment_signed and" } else { "" }); + self.monitor_updating_paused( + true, + need_commitment_signed, + false, + Vec::new(), + Vec::new(), + Vec::new(), + ); return Ok(self.push_ret_blockable_mon_update(monitor_update)); } @@ -6120,28 +7353,47 @@ impl FundedChannel where /// If we're not in a state where freeing the holding cell makes sense, this is a no-op and /// returns `(None, Vec::new())`. pub fn maybe_free_holding_cell_htlcs( - &mut self, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + &mut self, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> (Option, Vec<(HTLCSource, PaymentHash)>) - where F::Target: FeeEstimator, L::Target: Logger + where + F::Target: FeeEstimator, + L::Target: Logger, { - if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) && self.context.channel_state.can_generate_new_commitment() { + if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) + && self.context.channel_state.can_generate_new_commitment() + { self.free_holding_cell_htlcs(fee_estimator, logger) - } else { (None, Vec::new()) } + } else { + (None, Vec::new()) + } } /// Frees any pending commitment updates in the holding cell, generating the relevant messages /// for our counterparty. fn free_holding_cell_htlcs( - &mut self, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + &mut self, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> (Option, Vec<(HTLCSource, PaymentHash)>) - where F::Target: FeeEstimator, L::Target: Logger + where + F::Target: FeeEstimator, + L::Target: Logger, { assert!(matches!(self.context.channel_state, ChannelState::ChannelReady(_))); assert!(!self.context.channel_state.is_monitor_update_in_progress()); assert!(!self.context.channel_state.is_quiescent()); - if self.context.holding_cell_htlc_updates.len() != 0 || self.context.holding_cell_update_fee.is_some() { - log_trace!(logger, "Freeing holding cell with {} HTLC updates{} in channel {}", self.context.holding_cell_htlc_updates.len(), - if self.context.holding_cell_update_fee.is_some() { " and a fee update" } else { "" }, &self.context.channel_id()); + if self.context.holding_cell_htlc_updates.len() != 0 + || self.context.holding_cell_update_fee.is_some() + { + log_trace!( + logger, + "Freeing holding cell with {} HTLC updates{} in channel {}", + self.context.holding_cell_htlc_updates.len(), + if self.context.holding_cell_update_fee.is_some() { + " and a fee update" + } else { + "" + }, + &self.context.channel_id() + ); let mut monitor_update = ChannelMonitorUpdate { update_id: self.context.latest_monitor_update_id + 1, // We don't increment this yet! @@ -6163,12 +7415,26 @@ impl FundedChannel where // to rebalance channels. let fail_htlc_res = match &htlc_update { &HTLCUpdateAwaitingACK::AddHTLC { - amount_msat, cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet, - skimmed_fee_msat, blinding_point, .. + amount_msat, + cltv_expiry, + ref payment_hash, + ref source, + ref onion_routing_packet, + skimmed_fee_msat, + blinding_point, + .. } => { match self.send_htlc( - amount_msat, *payment_hash, cltv_expiry, source.clone(), onion_routing_packet.clone(), - false, skimmed_fee_msat, blinding_point, fee_estimator, logger + amount_msat, + *payment_hash, + cltv_expiry, + source.clone(), + onion_routing_packet.clone(), + false, + skimmed_fee_msat, + blinding_point, + fee_estimator, + logger, ) { Ok(update_add_msg_opt) => { // `send_htlc` only returns `Ok(None)`, when an update goes into @@ -6188,7 +7454,7 @@ impl FundedChannel where // successfully forwarded/failed/fulfilled, causing our // counterparty to eventually close on us. htlcs_to_fail.push((source.clone(), *payment_hash)); - } + }, } None }, @@ -6204,21 +7470,29 @@ impl FundedChannel where // there's no harm in including the extra `ChannelMonitorUpdateStep` here. // We do not bother to track and include `payment_info` here, however. let mut additional_monitor_update = - if let UpdateFulfillFetch::NewClaim { monitor_update, .. } = - self.get_update_fulfill_htlc(htlc_id, *payment_preimage, None, logger) - { monitor_update } else { unreachable!() }; + if let UpdateFulfillFetch::NewClaim { monitor_update, .. } = self + .get_update_fulfill_htlc(htlc_id, *payment_preimage, None, logger) + { + monitor_update + } else { + unreachable!() + }; update_fulfill_count += 1; monitor_update.updates.append(&mut additional_monitor_update.updates); None }, - &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, ref err_packet } => { - Some(self.fail_htlc(htlc_id, err_packet.clone(), false, logger) - .map(|fail_msg_opt| fail_msg_opt.map(|_| ()))) - }, - &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => { - Some(self.fail_htlc(htlc_id, (sha256_of_onion, failure_code), false, logger) - .map(|fail_msg_opt| fail_msg_opt.map(|_| ()))) - } + &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, ref err_packet } => Some( + self.fail_htlc(htlc_id, err_packet.clone(), false, logger) + .map(|fail_msg_opt| fail_msg_opt.map(|_| ())), + ), + &HTLCUpdateAwaitingACK::FailMalformedHTLC { + htlc_id, + failure_code, + sha256_of_onion, + } => Some( + self.fail_htlc(htlc_id, (sha256_of_onion, failure_code), false, logger) + .map(|fail_msg_opt| fail_msg_opt.map(|_| ())), + ), }; if let Some(res) = fail_htlc_res { match res { @@ -6238,7 +7512,11 @@ impl FundedChannel where } } } - if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() { + if update_add_count == 0 + && update_fulfill_count == 0 + && update_fail_count == 0 + && self.context.holding_cell_update_fee.is_none() + { return (None, htlcs_to_fail); } let update_fee = if let Some(feerate) = self.context.holding_cell_update_fee.take() { @@ -6269,28 +7547,48 @@ impl FundedChannel where /// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail, /// generating an appropriate error *after* the channel state has been updated based on the /// revoke_and_ack message. - pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK, - fee_estimator: &LowerBoundedFeeEstimator, logger: &L, hold_mon_update: bool, + pub fn revoke_and_ack( + &mut self, msg: &msgs::RevokeAndACK, fee_estimator: &LowerBoundedFeeEstimator, + logger: &L, hold_mon_update: bool, ) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option), ChannelError> - where F::Target: FeeEstimator, L::Target: Logger, + where + F::Target: FeeEstimator, + L::Target: Logger, { if self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got revoke_and_ack message while quiescent".to_owned())); + return Err(ChannelError::WarnAndDisconnect( + "Got revoke_and_ack message while quiescent".to_owned(), + )); } if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) { - return Err(ChannelError::close("Got revoke/ACK message when channel was not in an operational state".to_owned())); + return Err(ChannelError::close( + "Got revoke/ACK message when channel was not in an operational state".to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent revoke_and_ack when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent revoke_and_ack when we needed a channel_reestablish".to_owned(), + )); } - if self.context.channel_state.is_both_sides_shutdown() && self.context.last_sent_closing_fee.is_some() { - return Err(ChannelError::close("Peer sent revoke_and_ack after we'd started exchanging closing_signeds".to_owned())); + if self.context.channel_state.is_both_sides_shutdown() + && self.context.last_sent_closing_fee.is_some() + { + return Err(ChannelError::close( + "Peer sent revoke_and_ack after we'd started exchanging closing_signeds".to_owned(), + )); } - let secret = secp_check!(SecretKey::from_slice(&msg.per_commitment_secret), "Peer provided an invalid per_commitment_secret".to_owned()); + let secret = secp_check!( + SecretKey::from_slice(&msg.per_commitment_secret), + "Peer provided an invalid per_commitment_secret".to_owned() + ); - if let Some(counterparty_prev_commitment_point) = self.context.counterparty_prev_commitment_point { - if PublicKey::from_secret_key(&self.context.secp_ctx, &secret) != counterparty_prev_commitment_point { + if let Some(counterparty_prev_commitment_point) = + self.context.counterparty_prev_commitment_point + { + if PublicKey::from_secret_key(&self.context.secp_ctx, &secret) + != counterparty_prev_commitment_point + { return Err(ChannelError::close("Got a revoke commitment secret which didn't correspond to their current pubkey".to_owned())); } } @@ -6314,18 +7612,29 @@ impl FundedChannel where match &self.context.holder_signer { ChannelSignerType::Ecdsa(ecdsa) => { - ecdsa.validate_counterparty_revocation( - self.context.cur_counterparty_commitment_transaction_number + 1, - &secret - ).map_err(|_| ChannelError::close("Failed to validate revocation from peer".to_owned()))?; + ecdsa + .validate_counterparty_revocation( + self.context.cur_counterparty_commitment_transaction_number + 1, + &secret, + ) + .map_err(|_| { + ChannelError::close("Failed to validate revocation from peer".to_owned()) + })?; }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), }; - self.context.commitment_secrets.provide_secret(self.context.cur_counterparty_commitment_transaction_number + 1, msg.per_commitment_secret) - .map_err(|_| ChannelError::close("Previous secrets did not match new one".to_owned()))?; + self.context + .commitment_secrets + .provide_secret( + self.context.cur_counterparty_commitment_transaction_number + 1, + msg.per_commitment_secret, + ) + .map_err(|_| { + ChannelError::close("Previous secrets did not match new one".to_owned()) + })?; self.context.latest_monitor_update_id += 1; let mut monitor_update = ChannelMonitorUpdate { update_id: self.context.latest_monitor_update_id, @@ -6342,7 +7651,8 @@ impl FundedChannel where // channel based on that, but stepping stuff here should be safe either way. self.context.channel_state.clear_awaiting_remote_revoke(); self.mark_response_received(); - self.context.counterparty_prev_commitment_point = self.context.counterparty_cur_commitment_point; + self.context.counterparty_prev_commitment_point = + self.context.counterparty_cur_commitment_point; self.context.counterparty_cur_commitment_point = Some(msg.next_per_commitment_point); self.context.cur_counterparty_commitment_transaction_number -= 1; @@ -6350,7 +7660,11 @@ impl FundedChannel where self.context.announcement_sigs_state = AnnouncementSigsState::PeerReceived; } - log_trace!(logger, "Updating HTLCs on receipt of RAA in channel {}...", &self.context.channel_id()); + log_trace!( + logger, + "Updating HTLCs on receipt of RAA in channel {}...", + &self.context.channel_id() + ); let mut to_forward_infos = Vec::new(); let mut pending_update_adds = Vec::new(); let mut revoked_htlcs = Vec::new(); @@ -6364,7 +7678,8 @@ impl FundedChannel where // Take references explicitly so that we can hold multiple references to self.context. let pending_inbound_htlcs: &mut Vec<_> = &mut self.context.pending_inbound_htlcs; let pending_outbound_htlcs: &mut Vec<_> = &mut self.context.pending_outbound_htlcs; - let expecting_peer_commitment_signed = &mut self.context.expecting_peer_commitment_signed; + let expecting_peer_commitment_signed = + &mut self.context.expecting_peer_commitment_signed; // We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug) pending_inbound_htlcs.retain(|htlc| { @@ -6375,15 +7690,24 @@ impl FundedChannel where } *expecting_peer_commitment_signed = true; false - } else { true } + } else { + true + } }); let now = duration_since_epoch(); pending_outbound_htlcs.retain(|htlc| { if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) = &htlc.state { - log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", &htlc.payment_hash); - if let OutboundHTLCOutcome::Failure(mut reason) = outcome.clone() { // We really want take() here, but, again, non-mut ref :( + log_trace!( + logger, + " ...removing outbound AwaitingRemovedRemoteRevoke {}", + &htlc.payment_hash + ); + if let OutboundHTLCOutcome::Failure(mut reason) = outcome.clone() { + // We really want take() here, but, again, non-mut ref :( if let (Some(timestamp), Some(now)) = (htlc.send_timestamp, now) { - let hold_time = u32::try_from(now.saturating_sub(timestamp).as_millis()).unwrap_or(u32::MAX); + let hold_time = + u32::try_from(now.saturating_sub(timestamp).as_millis()) + .unwrap_or(u32::MAX); reason.set_hold_time(hold_time); } @@ -6394,14 +7718,19 @@ impl FundedChannel where value_to_self_msat_diff -= htlc.amount_msat as i64; } false - } else { true } + } else { + true + } }); for htlc in pending_inbound_htlcs.iter_mut() { - let swap = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) = &htlc.state { + let swap = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) = &htlc.state + { true } else if let &InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) = &htlc.state { true - } else { false }; + } else { + false + }; if swap { let mut state = InboundHTLCState::Committed; mem::swap(&mut state, &mut htlc.state); @@ -6410,20 +7739,31 @@ impl FundedChannel where log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to AwaitingAnnouncedRemoteRevoke", &htlc.payment_hash); htlc.state = InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution); require_commitment = true; - } else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution) = state { + } else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution) = + state + { match resolution { - InboundHTLCResolution::Resolved { pending_htlc_status } => + InboundHTLCResolution::Resolved { pending_htlc_status } => { match pending_htlc_status { PendingHTLCStatus::Fail(fail_msg) => { log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to LocalRemoved due to PendingHTLCStatus indicating failure", &htlc.payment_hash); require_commitment = true; match fail_msg { HTLCFailureMsg::Relay(msg) => { - htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(msg.clone().into())); + htlc.state = InboundHTLCState::LocalRemoved( + InboundHTLCRemovalReason::FailRelay( + msg.clone().into(), + ), + ); update_fail_htlcs.push(msg) }, HTLCFailureMsg::Malformed(msg) => { - htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed((msg.sha256_of_onion, msg.failure_code))); + htlc.state = InboundHTLCState::LocalRemoved( + InboundHTLCRemovalReason::FailMalformed(( + msg.sha256_of_onion, + msg.failure_code, + )), + ); update_fail_malformed_htlcs.push(msg) }, } @@ -6432,24 +7772,31 @@ impl FundedChannel where log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed, attempting to forward", &htlc.payment_hash); to_forward_infos.push((forward_info, htlc.htlc_id)); htlc.state = InboundHTLCState::Committed; - } + }, } + }, InboundHTLCResolution::Pending { update_add_htlc } => { log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", &htlc.payment_hash); pending_update_adds.push(update_add_htlc); htlc.state = InboundHTLCState::Committed; - } + }, } } } } for htlc in pending_outbound_htlcs.iter_mut() { if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { - log_trace!(logger, " ...promoting outbound LocalAnnounced {} to Committed", &htlc.payment_hash); + log_trace!( + logger, + " ...promoting outbound LocalAnnounced {} to Committed", + &htlc.payment_hash + ); htlc.state = OutboundHTLCState::Committed; *expecting_peer_commitment_signed = true; } - if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state { + if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = + &mut htlc.state + { log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash); // Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)` let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])); @@ -6459,18 +7806,25 @@ impl FundedChannel where } } } - self.funding.value_to_self_msat = (self.funding.value_to_self_msat as i64 + value_to_self_msat_diff) as u64; + self.funding.value_to_self_msat = + (self.funding.value_to_self_msat as i64 + value_to_self_msat_diff) as u64; if let Some((feerate, update_state)) = self.context.pending_update_fee { match update_state { FeeUpdateState::Outbound => { debug_assert!(self.funding.is_outbound()); - log_trace!(logger, " ...promoting outbound fee update {} to Committed", feerate); + log_trace!( + logger, + " ...promoting outbound fee update {} to Committed", + feerate + ); self.context.feerate_per_kw = feerate; self.context.pending_update_fee = None; self.context.expecting_peer_commitment_signed = true; }, - FeeUpdateState::RemoteAnnounced => { debug_assert!(!self.funding.is_outbound()); }, + FeeUpdateState::RemoteAnnounced => { + debug_assert!(!self.funding.is_outbound()); + }, FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { debug_assert!(!self.funding.is_outbound()); log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce fee update {} to Committed", feerate); @@ -6482,19 +7836,24 @@ impl FundedChannel where } let release_monitor = self.context.blocked_monitor_updates.is_empty() && !hold_mon_update; - let release_state_str = - if hold_mon_update { "Holding" } else if release_monitor { "Releasing" } else { "Blocked" }; + let release_state_str = if hold_mon_update { + "Holding" + } else if release_monitor { + "Releasing" + } else { + "Blocked" + }; macro_rules! return_with_htlcs_to_fail { ($htlcs_to_fail: expr) => { if !release_monitor { - self.context.blocked_monitor_updates.push(PendingChannelMonitorUpdate { - update: monitor_update, - }); + self.context + .blocked_monitor_updates + .push(PendingChannelMonitorUpdate { update: monitor_update }); return Ok(($htlcs_to_fail, None)); } else { return Ok(($htlcs_to_fail, Some(monitor_update))); } - } + }; } self.context.monitor_pending_update_adds.append(&mut pending_update_adds); @@ -6509,7 +7868,14 @@ impl FundedChannel where log_debug!(logger, "Received a valid revoke_and_ack for channel {} with holding cell HTLCs freed. {} monitor update.", &self.context.channel_id(), release_state_str); - self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs); + self.monitor_updating_paused( + false, + true, + false, + to_forward_infos, + revoked_htlcs, + finalized_claimed_htlcs, + ); return_with_htlcs_to_fail!(htlcs_to_fail); }, (None, htlcs_to_fail) => { @@ -6526,8 +7892,12 @@ impl FundedChannel where self.context.latest_monitor_update_id = monitor_update.update_id; monitor_update.updates.append(&mut additional_update.updates); - log_debug!(logger, "Received a valid revoke_and_ack for channel {}. {} monitor update.", - &self.context.channel_id(), release_state_str); + log_debug!( + logger, + "Received a valid revoke_and_ack for channel {}. {} monitor update.", + &self.context.channel_id(), + release_state_str + ); if self.context.channel_state.can_generate_new_commitment() { log_debug!(logger, "Responding with a commitment update with {} HTLCs failed for channel {}", update_fail_htlcs.len() + update_fail_malformed_htlcs.len(), @@ -6541,25 +7911,46 @@ impl FundedChannel where } else { "can continue progress" }; - log_debug!(logger, "Holding back commitment update until channel {} {}", - &self.context.channel_id, reason); + log_debug!( + logger, + "Holding back commitment update until channel {} {}", + &self.context.channel_id, + reason + ); } - self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs); + self.monitor_updating_paused( + false, + true, + false, + to_forward_infos, + revoked_htlcs, + finalized_claimed_htlcs, + ); return_with_htlcs_to_fail!(htlcs_to_fail); } else { log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary. {} monitor update.", &self.context.channel_id(), release_state_str); - self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs); + self.monitor_updating_paused( + false, + false, + false, + to_forward_infos, + revoked_htlcs, + finalized_claimed_htlcs, + ); return_with_htlcs_to_fail!(htlcs_to_fail); } - } + }, } } - pub fn tx_signatures(&mut self, msg: &msgs::TxSignatures, logger: &L) -> Result, ChannelError> - where L::Target: Logger + pub fn tx_signatures( + &mut self, msg: &msgs::TxSignatures, logger: &L, + ) -> Result, ChannelError> + where + L::Target: Logger, { if !matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) { return Err(ChannelError::close("Received tx_signatures in strange state!".to_owned())); @@ -6567,26 +7958,24 @@ impl FundedChannel where if let Some(ref mut signing_session) = self.interactive_tx_signing_session { if msg.tx_hash != signing_session.unsigned_tx.compute_txid() { - return Err(ChannelError::Close( - ( - "The txid for the transaction does not match".to_string(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, - ))); + return Err(ChannelError::Close(( + "The txid for the transaction does not match".to_string(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + ))); } if msg.witnesses.len() != signing_session.remote_inputs_count() { return Err(ChannelError::Warn( - "Witness count did not match contributed input count".to_string() + "Witness count did not match contributed input count".to_string(), )); } for witness in &msg.witnesses { if witness.is_empty() { - return Err(ChannelError::Close( - ( - "Unexpected empty witness in tx_signatures received".to_string(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, - ))); + return Err(ChannelError::Close(( + "Unexpected empty witness in tx_signatures received".to_string(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + ))); } // TODO(dual_funding): Check all sigs are SIGHASH_ALL. @@ -6595,9 +7984,12 @@ impl FundedChannel where // for spending. Doesn't seem to be anything in rust-bitcoin. } - let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg.clone()) - .map_err(|_| ChannelError::Warn("Witness count did not match contributed input count".to_string()))?; - + let (holder_tx_signatures_opt, funding_tx_opt) = + signing_session.received_tx_signatures(msg.clone()).map_err(|_| { + ChannelError::Warn( + "Witness count did not match contributed input count".to_string(), + ) + })?; if funding_tx_opt.is_some() { // We have a finalized funding transaction, so we can set the funding transaction and reset the @@ -6625,9 +8017,11 @@ impl FundedChannel where /// Queues up an outbound update fee by placing it in the holding cell. You should call /// [`Self::maybe_free_holding_cell_htlcs`] in order to actually generate and send the /// commitment update. - pub fn queue_update_fee(&mut self, feerate_per_kw: u32, - fee_estimator: &LowerBoundedFeeEstimator, logger: &L) - where F::Target: FeeEstimator, L::Target: Logger + pub fn queue_update_fee( + &mut self, feerate_per_kw: u32, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, + ) where + F::Target: FeeEstimator, + L::Target: Logger, { let msg_opt = self.send_update_fee(feerate_per_kw, true, fee_estimator, logger); assert!(msg_opt.is_none(), "We forced holding cell?"); @@ -6642,9 +8036,11 @@ impl FundedChannel where /// [`FundedChannel`] if `force_holding_cell` is false. fn send_update_fee( &mut self, feerate_per_kw: u32, mut force_holding_cell: bool, - fee_estimator: &LowerBoundedFeeEstimator, logger: &L + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Option - where F::Target: FeeEstimator, L::Target: Logger + where + F::Target: FeeEstimator, + L::Target: Logger, { if !self.funding.is_outbound() { panic!("Cannot send fee from inbound channel"); @@ -6657,28 +8053,56 @@ impl FundedChannel where } // Before proposing a feerate update, check that we can actually afford the new fee. - let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator); - let htlc_stats = self.context.get_pending_htlc_stats(&self.funding, Some(feerate_per_kw), dust_exposure_limiting_feerate); + let dust_exposure_limiting_feerate = + self.context.get_dust_exposure_limiting_feerate(&fee_estimator); + let htlc_stats = self.context.get_pending_htlc_stats( + &self.funding, + Some(feerate_per_kw), + dust_exposure_limiting_feerate, + ); let commitment_data = self.context.build_commitment_transaction( - &self.funding, self.holder_commitment_point.transaction_number(), - &self.holder_commitment_point.current_point(), true, true, logger, + &self.funding, + self.holder_commitment_point.transaction_number(), + &self.holder_commitment_point.current_point(), + true, + true, + logger, ); - let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_data.tx.nondust_htlcs().len() + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.funding.get_channel_type()) * 1000; - let holder_balance_msat = commitment_data.stats.local_balance_before_fee_anchors_msat - htlc_stats.outbound_holding_cell_msat; - if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 { + let buffer_fee_msat = commit_tx_fee_sat( + feerate_per_kw, + commitment_data.tx.nondust_htlcs().len() + + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, + self.funding.get_channel_type(), + ) * 1000; + let holder_balance_msat = commitment_data.stats.local_balance_before_fee_anchors_msat + - htlc_stats.outbound_holding_cell_msat; + if holder_balance_msat + < buffer_fee_msat + + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 + { //TODO: auto-close after a number of failures? log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw); return None; } // Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`. - let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + let max_dust_htlc_exposure_msat = + self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat { - log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw); + log_debug!( + logger, + "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", + feerate_per_kw + ); return None; } if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat { - log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw); + log_debug!( + logger, + "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", + feerate_per_kw + ); return None; } @@ -6697,10 +8121,7 @@ impl FundedChannel where debug_assert!(self.context.pending_update_fee.is_none()); self.context.pending_update_fee = Some((feerate_per_kw, FeeUpdateState::Outbound)); - Some(msgs::UpdateFee { - channel_id: self.context.channel_id, - feerate_per_kw, - }) + Some(msgs::UpdateFee { channel_id: self.context.channel_id, feerate_per_kw }) } /// Removes any uncommitted inbound HTLCs and resets the state of uncommitted outbound HTLC @@ -6709,14 +8130,17 @@ impl FundedChannel where /// No further message handling calls may be made until a channel_reestablish dance has /// completed. /// May return `Err(())`, which implies [`ChannelContext::force_shutdown`] should be called immediately. - fn remove_uncommitted_htlcs_and_mark_paused(&mut self, logger: &L) -> Result<(), ()> where L::Target: Logger { + fn remove_uncommitted_htlcs_and_mark_paused(&mut self, logger: &L) -> Result<(), ()> + where + L::Target: Logger, + { assert!(!matches!(self.context.channel_state, ChannelState::ShutdownComplete)); if self.context.channel_state.is_pre_funded_state() { - return Err(()) + return Err(()); } // We only clear `peer_disconnected` if we were able to reestablish the channel. We always - // reset our awaiting response in case we failed reestablishment and are disconnecting. + // reset our awaiting response in case we failed reestablishment and are disconnecting. self.context.sent_message_awaiting_response = None; if self.context.channel_state.is_peer_disconnected() { @@ -6725,7 +8149,9 @@ impl FundedChannel where return Ok(()); } - if self.context.announcement_sigs_state == AnnouncementSigsState::MessageSent || self.context.announcement_sigs_state == AnnouncementSigsState::Committed { + if self.context.announcement_sigs_state == AnnouncementSigsState::MessageSent + || self.context.announcement_sigs_state == AnnouncementSigsState::Committed + { self.context.announcement_sigs_state = AnnouncementSigsState::NotSent; } @@ -6745,7 +8171,8 @@ impl FundedChannel where inbound_drop_count += 1; false }, - InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_)|InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => { + InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) + | InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => { // We received a commitment_signed updating this HTLC and (at least hopefully) // sent a revoke_and_ack (which we can re-transmit) and have heard nothing // in response to it yet, so don't touch it. @@ -6789,7 +8216,12 @@ impl FundedChannel where } self.context.channel_state.set_peer_disconnected(); - log_trace!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", inbound_drop_count, &self.context.channel_id()); + log_trace!( + logger, + "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", + inbound_drop_count, + &self.context.channel_id() + ); Ok(()) } @@ -6804,17 +8236,20 @@ impl FundedChannel where /// [`ChannelManager`]: super::channelmanager::ChannelManager /// [`chain::Watch`]: crate::chain::Watch /// [`ChannelMonitorUpdateStatus::InProgress`]: crate::chain::ChannelMonitorUpdateStatus::InProgress - fn monitor_updating_paused(&mut self, resend_raa: bool, resend_commitment: bool, - resend_channel_ready: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>, + fn monitor_updating_paused( + &mut self, resend_raa: bool, resend_commitment: bool, resend_channel_ready: bool, + mut pending_forwards: Vec<(PendingHTLCInfo, u64)>, mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, - mut pending_finalized_claimed_htlcs: Vec + mut pending_finalized_claimed_htlcs: Vec, ) { self.context.monitor_pending_revoke_and_ack |= resend_raa; self.context.monitor_pending_commitment_signed |= resend_commitment; self.context.monitor_pending_channel_ready |= resend_channel_ready; self.context.monitor_pending_forwards.append(&mut pending_forwards); self.context.monitor_pending_failures.append(&mut pending_fails); - self.context.monitor_pending_finalized_fulfills.append(&mut pending_finalized_claimed_htlcs); + self.context + .monitor_pending_finalized_fulfills + .append(&mut pending_finalized_claimed_htlcs); self.context.channel_state.set_monitor_update_in_progress(); } @@ -6822,12 +8257,12 @@ impl FundedChannel where /// successfully and we should restore normal operation. Returns messages which should be sent /// to the remote side. pub fn monitor_updating_restored( - &mut self, logger: &L, node_signer: &NS, chain_hash: ChainHash, - user_config: &UserConfig, best_block_height: u32 + &mut self, logger: &L, node_signer: &NS, chain_hash: ChainHash, user_config: &UserConfig, + best_block_height: u32, ) -> MonitorRestoreUpdates where L::Target: Logger, - NS::Target: NodeSigner + NS::Target: NodeSigner, { assert!(self.context.channel_state.is_monitor_update_in_progress()); self.context.channel_state.clear_monitor_update_in_progress(); @@ -6837,9 +8272,9 @@ impl FundedChannel where // first received the funding_signed. let mut funding_broadcastable = None; if let Some(funding_transaction) = &self.funding.funding_transaction { - if (self.funding.is_outbound() || self.is_v2_established()) && - (matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) || - matches!(self.context.channel_state, ChannelState::ChannelReady(_))) + if (self.funding.is_outbound() || self.is_v2_established()) + && (matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) + || matches!(self.context.channel_state, ChannelState::ChannelReady(_))) { // Broadcast only if not yet confirmed if self.context.get_funding_tx_confirmation_height().is_none() { @@ -6859,16 +8294,27 @@ impl FundedChannel where "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); self.context.monitor_pending_channel_ready = false; self.get_channel_ready(logger) - } else { None }; + } else { + None + }; - let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block_height, logger); + let announcement_sigs = self.get_announcement_sigs( + node_signer, + chain_hash, + user_config, + best_block_height, + logger, + ); let mut accepted_htlcs = Vec::new(); mem::swap(&mut accepted_htlcs, &mut self.context.monitor_pending_forwards); let mut failed_htlcs = Vec::new(); mem::swap(&mut failed_htlcs, &mut self.context.monitor_pending_failures); let mut finalized_claimed_htlcs = Vec::new(); - mem::swap(&mut finalized_claimed_htlcs, &mut self.context.monitor_pending_finalized_fulfills); + mem::swap( + &mut finalized_claimed_htlcs, + &mut self.context.monitor_pending_finalized_fulfills, + ); let mut pending_update_adds = Vec::new(); mem::swap(&mut pending_update_adds, &mut self.context.monitor_pending_update_adds); // For channels established with V2 establishment we won't send a `tx_signatures` when we're in @@ -6880,25 +8326,41 @@ impl FundedChannel where self.context.monitor_pending_revoke_and_ack = false; self.context.monitor_pending_commitment_signed = false; return MonitorRestoreUpdates { - raa: None, commitment_update: None, order: RAACommitmentOrder::RevokeAndACKFirst, - accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, pending_update_adds, - funding_broadcastable, channel_ready, announcement_sigs, tx_signatures + raa: None, + commitment_update: None, + order: RAACommitmentOrder::RevokeAndACKFirst, + accepted_htlcs, + failed_htlcs, + finalized_claimed_htlcs, + pending_update_adds, + funding_broadcastable, + channel_ready, + announcement_sigs, + tx_signatures, }; } let mut raa = if self.context.monitor_pending_revoke_and_ack { self.get_last_revoke_and_ack(logger) - } else { None }; + } else { + None + }; let mut commitment_update = if self.context.monitor_pending_commitment_signed { self.get_last_commitment_update_for_send(logger).ok() - } else { None }; + } else { + None + }; if self.context.resend_order == RAACommitmentOrder::CommitmentFirst - && self.context.signer_pending_commitment_update && raa.is_some() { + && self.context.signer_pending_commitment_update + && raa.is_some() + { self.context.signer_pending_revoke_and_ack = true; raa = None; } if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst - && self.context.signer_pending_revoke_and_ack && commitment_update.is_some() { + && self.context.signer_pending_revoke_and_ack + && commitment_update.is_some() + { self.context.signer_pending_commitment_update = true; commitment_update = None; } @@ -6911,12 +8373,23 @@ impl FundedChannel where if commitment_update.is_some() { "a" } else { "no" }, if raa.is_some() { "an" } else { "no" }, match order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"}); MonitorRestoreUpdates { - raa, commitment_update, order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, - pending_update_adds, funding_broadcastable, channel_ready, announcement_sigs, tx_signatures + raa, + commitment_update, + order, + accepted_htlcs, + failed_htlcs, + finalized_claimed_htlcs, + pending_update_adds, + funding_broadcastable, + channel_ready, + announcement_sigs, + tx_signatures, } } - pub fn check_for_stale_feerate(&mut self, logger: &L, min_feerate: u32) -> Result<(), ClosureReason> { + pub fn check_for_stale_feerate( + &mut self, logger: &L, min_feerate: u32, + ) -> Result<(), ClosureReason> { if self.funding.is_outbound() { // While its possible our fee is too low for an outbound channel because we've been // unable to increase the fee, we don't try to force-close directly here. @@ -6936,26 +8409,51 @@ impl FundedChannel where } } - pub fn update_fee(&mut self, fee_estimator: &LowerBoundedFeeEstimator, msg: &msgs::UpdateFee, logger: &L) -> Result<(), ChannelError> - where F::Target: FeeEstimator, L::Target: Logger + pub fn update_fee( + &mut self, fee_estimator: &LowerBoundedFeeEstimator, msg: &msgs::UpdateFee, logger: &L, + ) -> Result<(), ChannelError> + where + F::Target: FeeEstimator, + L::Target: Logger, { if self.funding.is_outbound() { - return Err(ChannelError::close("Non-funding remote tried to update channel fee".to_owned())); + return Err(ChannelError::close( + "Non-funding remote tried to update channel fee".to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent update_fee when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent update_fee when we needed a channel_reestablish".to_owned(), + )); } - if self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got fee update message while quiescent".to_owned())); + if self.context.channel_state.is_remote_stfu_sent() + || self.context.channel_state.is_quiescent() + { + return Err(ChannelError::WarnAndDisconnect( + "Got fee update message while quiescent".to_owned(), + )); } - FundedChannel::::check_remote_fee(self.funding.get_channel_type(), fee_estimator, msg.feerate_per_kw, Some(self.context.feerate_per_kw), logger)?; + FundedChannel::::check_remote_fee( + self.funding.get_channel_type(), + fee_estimator, + msg.feerate_per_kw, + Some(self.context.feerate_per_kw), + logger, + )?; - self.context.pending_update_fee = Some((msg.feerate_per_kw, FeeUpdateState::RemoteAnnounced)); + self.context.pending_update_fee = + Some((msg.feerate_per_kw, FeeUpdateState::RemoteAnnounced)); self.context.update_time_counter += 1; // Check that we won't be pushed over our dust exposure limit by the feerate increase. - let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator); - let htlc_stats = self.context.get_pending_htlc_stats(&self.funding, None, dust_exposure_limiting_feerate); - let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + let dust_exposure_limiting_feerate = + self.context.get_dust_exposure_limiting_feerate(&fee_estimator); + let htlc_stats = self.context.get_pending_htlc_stats( + &self.funding, + None, + dust_exposure_limiting_feerate, + ); + let max_dust_htlc_exposure_msat = + self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat { return Err(ChannelError::close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)", msg.feerate_per_kw, htlc_stats.on_holder_tx_dust_exposure_msat))); @@ -6969,75 +8467,143 @@ impl FundedChannel where /// Indicates that the signer may have some signatures for us, so we should retry if we're /// blocked. - pub fn signer_maybe_unblocked(&mut self, logger: &L) -> SignerResumeUpdates where L::Target: Logger { + pub fn signer_maybe_unblocked(&mut self, logger: &L) -> SignerResumeUpdates + where + L::Target: Logger, + { if !self.holder_commitment_point.is_available() { log_trace!(logger, "Attempting to update holder per-commitment point..."); - self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger); + self.holder_commitment_point.try_resolve_pending( + &self.context.holder_signer, + &self.context.secp_ctx, + logger, + ); } let funding_signed = if self.context.signer_pending_funding && !self.funding.is_outbound() { - let commitment_data = self.context.build_commitment_transaction(&self.funding, + let commitment_data = self.context.build_commitment_transaction( + &self.funding, self.context.cur_counterparty_commitment_transaction_number + 1, - &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger); + &self.context.counterparty_cur_commitment_point.unwrap(), + false, + false, + logger, + ); let counterparty_initial_commitment_tx = commitment_data.tx; - self.context.get_funding_signed_msg(&self.funding.channel_transaction_parameters, logger, counterparty_initial_commitment_tx) - } else { None }; + self.context.get_funding_signed_msg( + &self.funding.channel_transaction_parameters, + logger, + counterparty_initial_commitment_tx, + ) + } else { + None + }; // Provide a `channel_ready` message if we need to, but only if we're _not_ still pending // funding. - let channel_ready = if self.context.signer_pending_channel_ready && !self.context.signer_pending_funding { - log_trace!(logger, "Attempting to generate pending channel_ready..."); - self.get_channel_ready(logger) - } else { None }; + let channel_ready = + if self.context.signer_pending_channel_ready && !self.context.signer_pending_funding { + log_trace!(logger, "Attempting to generate pending channel_ready..."); + self.get_channel_ready(logger) + } else { + None + }; let mut commitment_update = if self.context.signer_pending_commitment_update { log_trace!(logger, "Attempting to generate pending commitment update..."); self.get_last_commitment_update_for_send(logger).ok() - } else { None }; + } else { + None + }; let mut revoke_and_ack = if self.context.signer_pending_revoke_and_ack { log_trace!(logger, "Attempting to generate pending revoke and ack..."); self.get_last_revoke_and_ack(logger) - } else { None }; + } else { + None + }; if self.context.resend_order == RAACommitmentOrder::CommitmentFirst - && self.context.signer_pending_commitment_update && revoke_and_ack.is_some() { + && self.context.signer_pending_commitment_update + && revoke_and_ack.is_some() + { log_trace!(logger, "Signer unblocked for revoke and ack, but unable to send due to resend order, waiting on signer for commitment update"); self.context.signer_pending_revoke_and_ack = true; revoke_and_ack = None; } if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst - && self.context.signer_pending_revoke_and_ack && commitment_update.is_some() { + && self.context.signer_pending_revoke_and_ack + && commitment_update.is_some() + { log_trace!(logger, "Signer unblocked for commitment update, but unable to send due to resend order, waiting on signer for revoke and ack"); self.context.signer_pending_commitment_update = true; commitment_update = None; } - let (closing_signed, signed_closing_tx, shutdown_result) = if self.context.signer_pending_closing { - debug_assert!(self.context.last_sent_closing_fee.is_some()); - if let Some((fee, skip_remote_output, fee_range, holder_sig)) = self.context.last_sent_closing_fee.clone() { - debug_assert!(holder_sig.is_none()); - log_trace!(logger, "Attempting to generate pending closing_signed..."); - let closing_transaction_result = self.build_closing_transaction(fee, skip_remote_output); - match closing_transaction_result { - Ok((closing_tx, fee)) => { - let closing_signed = self.get_closing_signed_msg(&closing_tx, skip_remote_output, - fee, fee_range.min_fee_satoshis, fee_range.max_fee_satoshis, logger); - let signed_tx = if let (Some(ClosingSigned { signature, .. }), Some(counterparty_sig)) = - (closing_signed.as_ref(), self.context.last_received_closing_sig) { - let funding_redeemscript = self.funding.get_funding_redeemscript(); - let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.funding.get_value_satoshis()); - debug_assert!(self.context.secp_ctx.verify_ecdsa(&sighash, &counterparty_sig, - &self.funding.get_counterparty_pubkeys().funding_pubkey).is_ok()); - Some(self.build_signed_closing_transaction(&closing_tx, &counterparty_sig, signature)) - } else { None }; - let shutdown_result = signed_tx.as_ref().map(|_| self.shutdown_result_coop_close()); - (closing_signed, signed_tx, shutdown_result) - } - Err(err) => { - let shutdown = self.context.force_shutdown(&self.funding, true, ClosureReason::ProcessingError {err: err.to_string()}); - (None, None, Some(shutdown)) + let (closing_signed, signed_closing_tx, shutdown_result) = + if self.context.signer_pending_closing { + debug_assert!(self.context.last_sent_closing_fee.is_some()); + if let Some((fee, skip_remote_output, fee_range, holder_sig)) = + self.context.last_sent_closing_fee.clone() + { + debug_assert!(holder_sig.is_none()); + log_trace!(logger, "Attempting to generate pending closing_signed..."); + let closing_transaction_result = + self.build_closing_transaction(fee, skip_remote_output); + match closing_transaction_result { + Ok((closing_tx, fee)) => { + let closing_signed = self.get_closing_signed_msg( + &closing_tx, + skip_remote_output, + fee, + fee_range.min_fee_satoshis, + fee_range.max_fee_satoshis, + logger, + ); + let signed_tx = if let ( + Some(ClosingSigned { signature, .. }), + Some(counterparty_sig), + ) = + (closing_signed.as_ref(), self.context.last_received_closing_sig) + { + let funding_redeemscript = self.funding.get_funding_redeemscript(); + let sighash = closing_tx.trust().get_sighash_all( + &funding_redeemscript, + self.funding.get_value_satoshis(), + ); + debug_assert!(self + .context + .secp_ctx + .verify_ecdsa( + &sighash, + &counterparty_sig, + &self.funding.get_counterparty_pubkeys().funding_pubkey + ) + .is_ok()); + Some(self.build_signed_closing_transaction( + &closing_tx, + &counterparty_sig, + signature, + )) + } else { + None + }; + let shutdown_result = + signed_tx.as_ref().map(|_| self.shutdown_result_coop_close()); + (closing_signed, signed_tx, shutdown_result) + }, + Err(err) => { + let shutdown = self.context.force_shutdown( + &self.funding, + true, + ClosureReason::ProcessingError { err: err.to_string() }, + ); + (None, None, Some(shutdown)) + }, } + } else { + (None, None, None) } - } else { (None, None, None) } - } else { (None, None, None) }; + } else { + (None, None, None) + }; log_trace!(logger, "Signer unblocked with {} commitment_update, {} revoke_and_ack, with resend order {:?}, {} funding_signed, {} channel_ready, {} closing_signed, {} signed_closing_tx, and {} shutdown result", @@ -7065,13 +8631,27 @@ impl FundedChannel where } } - fn get_last_revoke_and_ack(&mut self, logger: &L) -> Option where L::Target: Logger { - debug_assert!(self.holder_commitment_point.transaction_number() <= INITIAL_COMMITMENT_NUMBER - 2); - self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger); - let per_commitment_secret = self.context.holder_signer.as_ref() - .release_commitment_secret(self.holder_commitment_point.transaction_number() + 2).ok(); + fn get_last_revoke_and_ack(&mut self, logger: &L) -> Option + where + L::Target: Logger, + { + debug_assert!( + self.holder_commitment_point.transaction_number() <= INITIAL_COMMITMENT_NUMBER - 2 + ); + self.holder_commitment_point.try_resolve_pending( + &self.context.holder_signer, + &self.context.secp_ctx, + logger, + ); + let per_commitment_secret = self + .context + .holder_signer + .as_ref() + .release_commitment_secret(self.holder_commitment_point.transaction_number() + 2) + .ok(); if let (HolderCommitmentPoint::Available { current, .. }, Some(per_commitment_secret)) = - (self.holder_commitment_point, per_commitment_secret) { + (self.holder_commitment_point, per_commitment_secret) + { self.context.signer_pending_revoke_and_ack = false; return Some(msgs::RevokeAndACK { channel_id: self.context.channel_id, @@ -7079,7 +8659,7 @@ impl FundedChannel where next_per_commitment_point: current, #[cfg(taproot)] next_local_nonce: None, - }) + }); } if !self.holder_commitment_point.is_available() { log_trace!(logger, "Last revoke-and-ack pending in channel {} for sequence {} because the next per-commitment point is not available", @@ -7103,7 +8683,12 @@ impl FundedChannel where } /// Gets the last commitment update for immediate sending to our peer. - fn get_last_commitment_update_for_send(&mut self, logger: &L) -> Result where L::Target: Logger { + fn get_last_commitment_update_for_send( + &mut self, logger: &L, + ) -> Result + where + L::Target: Logger, + { let mut update_add_htlcs = Vec::new(); let mut update_fulfill_htlcs = Vec::new(); let mut update_fail_htlcs = Vec::new(); @@ -7135,7 +8720,10 @@ impl FundedChannel where attribution_data: err_packet.attribution_data.clone(), }); }, - &InboundHTLCRemovalReason::FailMalformed((ref sha256_of_onion, ref failure_code)) => { + &InboundHTLCRemovalReason::FailMalformed(( + ref sha256_of_onion, + ref failure_code, + )) => { update_fail_malformed_htlcs.push(msgs::UpdateFailMalformedHTLC { channel_id: self.context.channel_id(), htlc_id: htlc.htlc_id, @@ -7154,31 +8742,42 @@ impl FundedChannel where } } - let update_fee = if self.funding.is_outbound() && self.context.pending_update_fee.is_some() { + let update_fee = if self.funding.is_outbound() && self.context.pending_update_fee.is_some() + { Some(msgs::UpdateFee { channel_id: self.context.channel_id(), feerate_per_kw: self.context.pending_update_fee.unwrap().0, }) - } else { None }; + } else { + None + }; log_trace!(logger, "Regenerating latest commitment update in channel {} with{} {} update_adds, {} update_fulfills, {} update_fails, and {} update_fail_malformeds", &self.context.channel_id(), if update_fee.is_some() { " update_fee," } else { "" }, update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len(), update_fail_malformed_htlcs.len()); - let commitment_signed = if let Ok(update) = self.send_commitment_no_state_update(logger) { - if self.context.signer_pending_commitment_update { - log_trace!(logger, "Commitment update generated: clearing signer_pending_commitment_update"); - self.context.signer_pending_commitment_update = false; - } - update - } else { - if !self.context.signer_pending_commitment_update { - log_trace!(logger, "Commitment update awaiting signer: setting signer_pending_commitment_update"); - self.context.signer_pending_commitment_update = true; - } - return Err(()); - }; + let commitment_signed = + if let Ok(update) = self.send_commitment_no_state_update(logger) { + if self.context.signer_pending_commitment_update { + log_trace!( + logger, + "Commitment update generated: clearing signer_pending_commitment_update" + ); + self.context.signer_pending_commitment_update = false; + } + update + } else { + if !self.context.signer_pending_commitment_update { + log_trace!(logger, "Commitment update awaiting signer: setting signer_pending_commitment_update"); + self.context.signer_pending_commitment_update = true; + } + return Err(()); + }; Ok(msgs::CommitmentUpdate { - update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs, update_fee, + update_add_htlcs, + update_fulfill_htlcs, + update_fail_htlcs, + update_fail_malformed_htlcs, + update_fee, commitment_signed, }) } @@ -7191,7 +8790,9 @@ impl FundedChannel where channel_id: self.context.channel_id, scriptpubkey: self.get_closing_scriptpubkey(), }) - } else { None } + } else { + None + } } /// May panic if some calls other than message-handling calls (which will all Err immediately) @@ -7203,40 +8804,62 @@ impl FundedChannel where /// [`super::channelmanager::ChannelManager::force_close_all_channels_without_broadcasting_txn`]. pub fn channel_reestablish( &mut self, msg: &msgs::ChannelReestablish, logger: &L, node_signer: &NS, - chain_hash: ChainHash, user_config: &UserConfig, best_block: &BestBlock + chain_hash: ChainHash, user_config: &UserConfig, best_block: &BestBlock, ) -> Result where L::Target: Logger, - NS::Target: NodeSigner + NS::Target: NodeSigner, { if !self.context.channel_state.is_peer_disconnected() { // While BOLT 2 doesn't indicate explicitly we should error this channel here, it // almost certainly indicates we are going to end up out-of-sync in some way, so we // just close here instead of trying to recover. - return Err(ChannelError::close("Peer sent a loose channel_reestablish not after reconnect".to_owned())); + return Err(ChannelError::close( + "Peer sent a loose channel_reestablish not after reconnect".to_owned(), + )); } - if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER || - msg.next_local_commitment_number == 0 { - return Err(ChannelError::close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned())); + if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER + || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER + || msg.next_local_commitment_number == 0 + { + return Err(ChannelError::close( + "Peer sent an invalid channel_reestablish to force close in a non-standard way" + .to_owned(), + )); } - let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.holder_commitment_point.transaction_number() - 1; + let our_commitment_transaction = + INITIAL_COMMITMENT_NUMBER - self.holder_commitment_point.transaction_number() - 1; if msg.next_remote_commitment_number > 0 { let expected_point = self.context.holder_signer.as_ref() .get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.context.secp_ctx) .expect("TODO: async signing is not yet supported for per commitment points upon channel reestablishment"); let given_secret = SecretKey::from_slice(&msg.your_last_per_commitment_secret) - .map_err(|_| ChannelError::close("Peer sent a garbage channel_reestablish with unparseable secret key".to_owned()))?; + .map_err(|_| { + ChannelError::close( + "Peer sent a garbage channel_reestablish with unparseable secret key" + .to_owned(), + ) + })?; if expected_point != PublicKey::from_secret_key(&self.context.secp_ctx, &given_secret) { return Err(ChannelError::close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided".to_owned())); } if msg.next_remote_commitment_number > our_commitment_transaction { macro_rules! log_and_panic { ($err_msg: expr) => { - log_error!(logger, $err_msg, &self.context.channel_id, log_pubkey!(self.context.counterparty_node_id)); - panic!($err_msg, &self.context.channel_id, log_pubkey!(self.context.counterparty_node_id)); - } + log_error!( + logger, + $err_msg, + &self.context.channel_id, + log_pubkey!(self.context.counterparty_node_id) + ); + panic!( + $err_msg, + &self.context.channel_id, + log_pubkey!(self.context.counterparty_node_id) + ); + }; } log_and_panic!("We have fallen behind - we have received proof that if we broadcast our counterparty is going to claim all our funds.\n\ This implies you have restarted with lost ChannelMonitor and ChannelManager state, the first of which is a violation of the LDK chain::Watch requirements.\n\ @@ -7266,30 +8889,41 @@ impl FundedChannel where let shutdown_msg = self.get_outbound_shutdown(); - let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block.height, logger); + let announcement_sigs = self.get_announcement_sigs( + node_signer, + chain_hash, + user_config, + best_block.height, + logger, + ); if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) { // If we're waiting on a monitor update, we shouldn't re-send any channel_ready's. - if !self.context.channel_state.is_our_channel_ready() || - self.context.channel_state.is_monitor_update_in_progress() { + if !self.context.channel_state.is_our_channel_ready() + || self.context.channel_state.is_monitor_update_in_progress() + { if msg.next_remote_commitment_number != 0 { return Err(ChannelError::close("Peer claimed they saw a revoke_and_ack but we haven't sent channel_ready yet".to_owned())); } // Short circuit the whole handler as there is nothing we can resend them return Ok(ReestablishResponses { channel_ready: None, - raa: None, commitment_update: None, + raa: None, + commitment_update: None, order: RAACommitmentOrder::CommitmentFirst, - shutdown_msg, announcement_sigs, + shutdown_msg, + announcement_sigs, }); } // We have OurChannelReady set! return Ok(ReestablishResponses { channel_ready: self.get_channel_ready(logger), - raa: None, commitment_update: None, + raa: None, + commitment_update: None, order: RAACommitmentOrder::CommitmentFirst, - shutdown_msg, announcement_sigs, + shutdown_msg, + announcement_sigs, }); } @@ -7318,43 +8952,72 @@ impl FundedChannel where // AwaitingRemoteRevoke set, which indicates we sent a commitment_signed but haven't gotten // the corresponding revoke_and_ack back yet. let is_awaiting_remote_revoke = self.context.channel_state.is_awaiting_remote_revoke(); - let next_counterparty_commitment_number = INITIAL_COMMITMENT_NUMBER - self.context.cur_counterparty_commitment_transaction_number + if is_awaiting_remote_revoke { 1 } else { 0 }; + let next_counterparty_commitment_number = INITIAL_COMMITMENT_NUMBER + - self.context.cur_counterparty_commitment_transaction_number + + if is_awaiting_remote_revoke { 1 } else { 0 }; - let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.holder_commitment_point.transaction_number() == 1 { + let channel_ready = if msg.next_local_commitment_number == 1 + && INITIAL_COMMITMENT_NUMBER - self.holder_commitment_point.transaction_number() == 1 + { // We should never have to worry about MonitorUpdateInProgress resending ChannelReady self.get_channel_ready(logger) - } else { None }; + } else { + None + }; if msg.next_local_commitment_number == next_counterparty_commitment_number { if required_revoke.is_some() || self.context.signer_pending_revoke_and_ack { - log_debug!(logger, "Reconnected channel {} with only lost outbound RAA", &self.context.channel_id()); + log_debug!( + logger, + "Reconnected channel {} with only lost outbound RAA", + &self.context.channel_id() + ); } else { - log_debug!(logger, "Reconnected channel {} with no loss", &self.context.channel_id()); + log_debug!( + logger, + "Reconnected channel {} with no loss", + &self.context.channel_id() + ); } Ok(ReestablishResponses { - channel_ready, shutdown_msg, announcement_sigs, + channel_ready, + shutdown_msg, + announcement_sigs, raa: required_revoke, commitment_update: None, order: self.context.resend_order.clone(), }) } else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 { if required_revoke.is_some() || self.context.signer_pending_revoke_and_ack { - log_debug!(logger, "Reconnected channel {} with lost outbound RAA and lost remote commitment tx", &self.context.channel_id()); + log_debug!( + logger, + "Reconnected channel {} with lost outbound RAA and lost remote commitment tx", + &self.context.channel_id() + ); } else { - log_debug!(logger, "Reconnected channel {} with only lost remote commitment tx", &self.context.channel_id()); + log_debug!( + logger, + "Reconnected channel {} with only lost remote commitment tx", + &self.context.channel_id() + ); } if self.context.channel_state.is_monitor_update_in_progress() { self.context.monitor_pending_commitment_signed = true; Ok(ReestablishResponses { - channel_ready, shutdown_msg, announcement_sigs, - commitment_update: None, raa: None, + channel_ready, + shutdown_msg, + announcement_sigs, + commitment_update: None, + raa: None, order: self.context.resend_order.clone(), }) } else { - let commitment_update = if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst - && self.context.signer_pending_revoke_and_ack { + let commitment_update = if self.context.resend_order + == RAACommitmentOrder::RevokeAndACKFirst + && self.context.signer_pending_revoke_and_ack + { log_trace!(logger, "Reconnected channel {} with lost outbound RAA and lost remote commitment tx, but unable to send due to resend order, waiting on signer for revoke and ack", &self.context.channel_id()); self.context.signer_pending_commitment_update = true; None @@ -7362,7 +9025,9 @@ impl FundedChannel where self.get_last_commitment_update_for_send(logger).ok() }; let raa = if self.context.resend_order == RAACommitmentOrder::CommitmentFirst - && self.context.signer_pending_commitment_update && required_revoke.is_some() { + && self.context.signer_pending_commitment_update + && required_revoke.is_some() + { log_trace!(logger, "Reconnected channel {} with lost outbound RAA and lost remote commitment tx, but unable to send due to resend order, waiting on signer for commitment update", &self.context.channel_id()); self.context.signer_pending_revoke_and_ack = true; None @@ -7370,8 +9035,11 @@ impl FundedChannel where required_revoke }; Ok(ReestablishResponses { - channel_ready, shutdown_msg, announcement_sigs, - raa, commitment_update, + channel_ready, + shutdown_msg, + announcement_sigs, + raa, + commitment_update, order: self.context.resend_order.clone(), }) } @@ -7393,20 +9061,27 @@ impl FundedChannel where /// Calculates and returns our minimum and maximum closing transaction fee amounts, in whole /// satoshis. The amounts remain consistent unless a peer disconnects/reconnects or we restart, /// at which point they will be recalculated. - fn calculate_closing_fee_limits(&mut self, fee_estimator: &LowerBoundedFeeEstimator) - -> (u64, u64) - where F::Target: FeeEstimator + fn calculate_closing_fee_limits( + &mut self, fee_estimator: &LowerBoundedFeeEstimator, + ) -> (u64, u64) + where + F::Target: FeeEstimator, { - if let Some((min, max)) = self.context.closing_fee_limits { return (min, max); } + if let Some((min, max)) = self.context.closing_fee_limits { + return (min, max); + } // Propose a range from our current Background feerate to our Normal feerate plus our // force_close_avoidance_max_fee_satoshis. // If we fail to come to consensus, we'll have to force-close. - let mut proposed_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::ChannelCloseMinimum); + let mut proposed_feerate = + fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::ChannelCloseMinimum); // Use NonAnchorChannelFee because this should be an estimate for a channel close // that we don't expect to need fee bumping - let normal_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); - let mut proposed_max_feerate = if self.funding.is_outbound() { normal_feerate } else { u32::max_value() }; + let normal_feerate = + fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); + let mut proposed_max_feerate = + if self.funding.is_outbound() { normal_feerate } else { u32::max_value() }; // The spec requires that (when the channel does not have anchors) we only send absolute // channel fees no greater than the absolute channel fee on the current commitment @@ -7415,7 +9090,11 @@ impl FundedChannel where // some force-closure by old nodes, but we wanted to close the channel anyway. if let Some(target_feerate) = self.context.target_closing_feerate_sats_per_kw { - let min_feerate = if self.funding.is_outbound() { target_feerate } else { cmp::min(self.context.feerate_per_kw, target_feerate) }; + let min_feerate = if self.funding.is_outbound() { + target_feerate + } else { + cmp::min(self.context.feerate_per_kw, target_feerate) + }; proposed_feerate = cmp::max(proposed_feerate, min_feerate); proposed_max_feerate = cmp::max(proposed_max_feerate, min_feerate); } @@ -7427,19 +9106,26 @@ impl FundedChannel where // come to consensus with our counterparty on appropriate fees, however it should be a // relatively rare case. We can revisit this later, though note that in order to determine // if the funders' output is dust we have to know the absolute fee we're going to use. - let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.context.counterparty_shutdown_scriptpubkey.as_ref().unwrap())); + let tx_weight = self.get_closing_transaction_weight( + Some(&self.get_closing_scriptpubkey()), + Some(self.context.counterparty_shutdown_scriptpubkey.as_ref().unwrap()), + ); let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000; let proposed_max_total_fee_satoshis = if self.funding.is_outbound() { - // We always add force_close_avoidance_max_fee_satoshis to our normal - // feerate-calculated fee, but allow the max to be overridden if we're using a - // target feerate-calculated fee. - cmp::max(normal_feerate as u64 * tx_weight / 1000 + self.context.config.options.force_close_avoidance_max_fee_satoshis, - proposed_max_feerate as u64 * tx_weight / 1000) - } else { - self.funding.get_value_satoshis() - (self.funding.value_to_self_msat + 999) / 1000 - }; + // We always add force_close_avoidance_max_fee_satoshis to our normal + // feerate-calculated fee, but allow the max to be overridden if we're using a + // target feerate-calculated fee. + cmp::max( + normal_feerate as u64 * tx_weight / 1000 + + self.context.config.options.force_close_avoidance_max_fee_satoshis, + proposed_max_feerate as u64 * tx_weight / 1000, + ) + } else { + self.funding.get_value_satoshis() - (self.funding.value_to_self_msat + 999) / 1000 + }; - self.context.closing_fee_limits = Some((proposed_total_fee_satoshis, proposed_max_total_fee_satoshis)); + self.context.closing_fee_limits = + Some((proposed_total_fee_satoshis, proposed_max_total_fee_satoshis)); self.context.closing_fee_limits.clone().unwrap() } @@ -7457,7 +9143,9 @@ impl FundedChannel where pub fn timer_check_closing_negotiation_progress(&mut self) -> Result<(), ChannelError> { if self.closing_negotiation_ready() { if self.context.closing_signed_in_flight { - return Err(ChannelError::close("closing_signed negotiation failed to finish within two timer ticks".to_owned())); + return Err(ChannelError::close( + "closing_signed negotiation failed to finish within two timer ticks".to_owned(), + )); } else { self.context.closing_signed_in_flight = true; } @@ -7466,9 +9154,14 @@ impl FundedChannel where } pub fn maybe_propose_closing_signed( - &mut self, fee_estimator: &LowerBoundedFeeEstimator, logger: &L) - -> Result<(Option, Option, Option), ChannelError> - where F::Target: FeeEstimator, L::Target: Logger + &mut self, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, + ) -> Result< + (Option, Option, Option), + ChannelError, + > + where + F::Target: FeeEstimator, + L::Target: Logger, { // If we're waiting on a monitor persistence, that implies we're also waiting to send some // message to our counterparty (probably a `revoke_and_ack`). In such a case, we shouldn't @@ -7494,11 +9187,19 @@ impl FundedChannel where let (our_min_fee, our_max_fee) = self.calculate_closing_fee_limits(fee_estimator); assert!(self.context.shutdown_scriptpubkey.is_some()); - let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(our_min_fee, false)?; + let (closing_tx, total_fee_satoshis) = + self.build_closing_transaction(our_min_fee, false)?; log_trace!(logger, "Proposing initial closing_signed for our counterparty with a fee range of {}-{} sat (with initial proposal {} sats)", our_min_fee, our_max_fee, total_fee_satoshis); - let closing_signed = self.get_closing_signed_msg(&closing_tx, false, total_fee_satoshis, our_min_fee, our_max_fee, logger); + let closing_signed = self.get_closing_signed_msg( + &closing_tx, + false, + total_fee_satoshis, + our_min_fee, + our_max_fee, + logger, + ); Ok((closing_signed, None, None)) } @@ -7517,8 +9218,8 @@ impl FundedChannel where *ticks_elapsed += 1; *ticks_elapsed >= DISCONNECT_PEER_AWAITING_RESPONSE_TICKS } else if - // Cleared upon receiving `channel_reestablish`. - self.context.channel_state.is_peer_disconnected() + // Cleared upon receiving `channel_reestablish`. + self.context.channel_state.is_peer_disconnected() // Cleared upon receiving `stfu`. || self.context.channel_state.is_local_stfu_sent() // Cleared upon receiving a message that triggers the end of quiescence. @@ -7540,21 +9241,29 @@ impl FundedChannel where } pub fn shutdown( - &mut self, signer_provider: &SP, their_features: &InitFeatures, msg: &msgs::Shutdown - ) -> Result<(Option, Option, Vec<(HTLCSource, PaymentHash)>), ChannelError> - { + &mut self, signer_provider: &SP, their_features: &InitFeatures, msg: &msgs::Shutdown, + ) -> Result< + (Option, Option, Vec<(HTLCSource, PaymentHash)>), + ChannelError, + > { if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent shutdown when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent shutdown when we needed a channel_reestablish".to_owned(), + )); } if self.context.channel_state.is_pre_funded_state() { // Spec says we should fail the connection, not the channel, but that's nonsense, there // are plenty of reasons you may want to fail a channel pre-funding, and spec says you // can do that via error message without getting a connection fail anyway... - return Err(ChannelError::close("Peer sent shutdown pre-funding generation".to_owned())); + return Err(ChannelError::close( + "Peer sent shutdown pre-funding generation".to_owned(), + )); } for htlc in self.context.pending_inbound_htlcs.iter() { if let InboundHTLCState::RemoteAnnounced(_) = htlc.state { - return Err(ChannelError::close("Got shutdown with remote pending HTLCs".to_owned())); + return Err(ChannelError::close( + "Got shutdown with remote pending HTLCs".to_owned(), + )); } } assert!(!matches!(self.context.channel_state, ChannelState::ShutdownComplete)); @@ -7564,11 +9273,16 @@ impl FundedChannel where || self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() { - return Err(ChannelError::WarnAndDisconnect("Got shutdown request while quiescent".to_owned())); + return Err(ChannelError::WarnAndDisconnect( + "Got shutdown request while quiescent".to_owned(), + )); } if !script::is_bolt2_compliant(&msg.scriptpubkey, their_features) { - return Err(ChannelError::Warn(format!("Got a nonstandard scriptpubkey ({}) from remote peer", msg.scriptpubkey.to_hex_string()))); + return Err(ChannelError::Warn(format!( + "Got a nonstandard scriptpubkey ({}) from remote peer", + msg.scriptpubkey.to_hex_string() + ))); } if self.context.counterparty_shutdown_scriptpubkey.is_some() { @@ -7590,10 +9304,17 @@ impl FundedChannel where assert!(send_shutdown); let shutdown_scriptpubkey = match signer_provider.get_shutdown_scriptpubkey() { Ok(scriptpubkey) => scriptpubkey, - Err(_) => return Err(ChannelError::close("Failed to get shutdown scriptpubkey".to_owned())), + Err(_) => { + return Err(ChannelError::close( + "Failed to get shutdown scriptpubkey".to_owned(), + )) + }, }; if !shutdown_scriptpubkey.is_compatible(their_features) { - return Err(ChannelError::close(format!("Provided a scriptpubkey format not accepted by peer: {}", shutdown_scriptpubkey))); + return Err(ChannelError::close(format!( + "Provided a scriptpubkey format not accepted by peer: {}", + shutdown_scriptpubkey + ))); } self.context.shutdown_scriptpubkey = Some(shutdown_scriptpubkey); true @@ -7621,27 +9342,30 @@ impl FundedChannel where }; self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new()); self.push_ret_blockable_mon_update(monitor_update) - } else { None }; + } else { + None + }; let shutdown = if send_shutdown { Some(msgs::Shutdown { channel_id: self.context.channel_id, scriptpubkey: self.get_closing_scriptpubkey(), }) - } else { None }; + } else { + None + }; // We can't send our shutdown until we've committed all of our pending HTLCs, but the // remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding // cell HTLCs and return them to fail the payment. self.context.holding_cell_update_fee = None; - let mut dropped_outbound_htlcs = Vec::with_capacity(self.context.holding_cell_htlc_updates.len()); - self.context.holding_cell_htlc_updates.retain(|htlc_update| { - match htlc_update { - &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, .. } => { - dropped_outbound_htlcs.push((source.clone(), payment_hash.clone())); - false - }, - _ => true - } + let mut dropped_outbound_htlcs = + Vec::with_capacity(self.context.holding_cell_htlc_updates.len()); + self.context.holding_cell_htlc_updates.retain(|htlc_update| match htlc_update { + &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, .. } => { + dropped_outbound_htlcs.push((source.clone(), payment_hash.clone())); + false + }, + _ => true, }); self.context.channel_state.set_local_shutdown_sent(); @@ -7650,7 +9374,9 @@ impl FundedChannel where Ok((shutdown, monitor_update, dropped_outbound_htlcs)) } - fn build_signed_closing_transaction(&self, closing_tx: &ClosingTransaction, counterparty_sig: &Signature, sig: &Signature) -> Transaction { + fn build_signed_closing_transaction( + &self, closing_tx: &ClosingTransaction, counterparty_sig: &Signature, sig: &Signature, + ) -> Transaction { let mut tx = closing_tx.trust().built_transaction().clone(); tx.input[0].witness.push(Vec::new()); // First is the multisig dummy @@ -7674,16 +9400,23 @@ impl FundedChannel where } fn get_closing_signed_msg( - &mut self, closing_tx: &ClosingTransaction, skip_remote_output: bool, - fee_satoshis: u64, min_fee_satoshis: u64, max_fee_satoshis: u64, logger: &L + &mut self, closing_tx: &ClosingTransaction, skip_remote_output: bool, fee_satoshis: u64, + min_fee_satoshis: u64, max_fee_satoshis: u64, logger: &L, ) -> Option - where L::Target: Logger + where + L::Target: Logger, { let sig = match &self.context.holder_signer { - ChannelSignerType::Ecdsa(ecdsa) => ecdsa.sign_closing_transaction(&self.funding.channel_transaction_parameters, closing_tx, &self.context.secp_ctx).ok(), + ChannelSignerType::Ecdsa(ecdsa) => ecdsa + .sign_closing_transaction( + &self.funding.channel_transaction_parameters, + closing_tx, + &self.context.secp_ctx, + ) + .ok(), // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), }; if sig.is_none() { log_trace!(logger, "Closing transaction signature unavailable, waiting on signer"); @@ -7692,7 +9425,8 @@ impl FundedChannel where self.context.signer_pending_closing = false; } let fee_range = msgs::ClosingSignedFeeRange { min_fee_satoshis, max_fee_satoshis }; - self.context.last_sent_closing_fee = Some((fee_satoshis, skip_remote_output, fee_range.clone(), sig.clone())); + self.context.last_sent_closing_fee = + Some((fee_satoshis, skip_remote_output, fee_range.clone(), sig.clone())); sig.map(|signature| msgs::ClosingSigned { channel_id: self.context.channel_id, fee_satoshis, @@ -7711,7 +9445,9 @@ impl FundedChannel where closure_reason, monitor_update: None, dropped_outbound_htlcs: Vec::new(), - unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(&self.funding), + unbroadcasted_batch_funding_txid: self + .context + .unbroadcasted_batch_funding_txid(&self.funding), channel_id: self.context.channel_id, user_channel_id: self.context.user_id, channel_capacity_satoshis: self.funding.get_value_satoshis(), @@ -7724,24 +9460,43 @@ impl FundedChannel where } pub fn closing_signed( - &mut self, fee_estimator: &LowerBoundedFeeEstimator, msg: &msgs::ClosingSigned, logger: &L) - -> Result<(Option, Option, Option), ChannelError> - where F::Target: FeeEstimator, L::Target: Logger + &mut self, fee_estimator: &LowerBoundedFeeEstimator, msg: &msgs::ClosingSigned, + logger: &L, + ) -> Result< + (Option, Option, Option), + ChannelError, + > + where + F::Target: FeeEstimator, + L::Target: Logger, { if self.is_shutdown_pending_signature() { return Err(ChannelError::Warn(String::from("Remote end sent us a closing_signed while fully shutdown and just waiting on the final closing signature"))); } if !self.context.channel_state.is_both_sides_shutdown() { - return Err(ChannelError::close("Remote end sent us a closing_signed before both sides provided a shutdown".to_owned())); + return Err(ChannelError::close( + "Remote end sent us a closing_signed before both sides provided a shutdown" + .to_owned(), + )); } if self.context.channel_state.is_peer_disconnected() { - return Err(ChannelError::close("Peer sent closing_signed when we needed a channel_reestablish".to_owned())); + return Err(ChannelError::close( + "Peer sent closing_signed when we needed a channel_reestablish".to_owned(), + )); } - if !self.context.pending_inbound_htlcs.is_empty() || !self.context.pending_outbound_htlcs.is_empty() { - return Err(ChannelError::close("Remote end sent us a closing_signed while there were still pending HTLCs".to_owned())); + if !self.context.pending_inbound_htlcs.is_empty() + || !self.context.pending_outbound_htlcs.is_empty() + { + return Err(ChannelError::close( + "Remote end sent us a closing_signed while there were still pending HTLCs" + .to_owned(), + )); } - if msg.fee_satoshis > TOTAL_BITCOIN_SUPPLY_SATOSHIS { // this is required to stop potential overflow in build_closing_transaction - return Err(ChannelError::close("Remote tried to send us a closing tx with > 21 million BTC fee".to_owned())); + if msg.fee_satoshis > TOTAL_BITCOIN_SUPPLY_SATOSHIS { + // this is required to stop potential overflow in build_closing_transaction + return Err(ChannelError::close( + "Remote tried to send us a closing tx with > 21 million BTC fee".to_owned(), + )); } if self.funding.is_outbound() && self.context.last_sent_closing_fee.is_none() { @@ -7755,26 +9510,45 @@ impl FundedChannel where let funding_redeemscript = self.funding.get_funding_redeemscript(); let mut skip_remote_output = false; - let (mut closing_tx, used_total_fee) = self.build_closing_transaction(msg.fee_satoshis, skip_remote_output)?; + let (mut closing_tx, used_total_fee) = + self.build_closing_transaction(msg.fee_satoshis, skip_remote_output)?; if used_total_fee != msg.fee_satoshis { return Err(ChannelError::close(format!("Remote sent us a closing_signed with a fee other than the value they can claim. Fee in message: {}. Actual closing tx fee: {}", msg.fee_satoshis, used_total_fee))); } - let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.funding.get_value_satoshis()); + let sighash = closing_tx + .trust() + .get_sighash_all(&funding_redeemscript, self.funding.get_value_satoshis()); - match self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.funding.get_counterparty_pubkeys().funding_pubkey) { + match self.context.secp_ctx.verify_ecdsa( + &sighash, + &msg.signature, + &self.funding.get_counterparty_pubkeys().funding_pubkey, + ) { Ok(_) => {}, Err(_e) => { // The remote end may have decided to revoke their output due to inconsistent dust // limits, so check for that case by re-checking the signature here. skip_remote_output = true; - closing_tx = self.build_closing_transaction(msg.fee_satoshis, skip_remote_output)?.0; - let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.funding.get_value_satoshis()); - secp_check!(self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, self.funding.counterparty_funding_pubkey()), "Invalid closing tx signature from peer".to_owned()); + closing_tx = + self.build_closing_transaction(msg.fee_satoshis, skip_remote_output)?.0; + let sighash = closing_tx + .trust() + .get_sighash_all(&funding_redeemscript, self.funding.get_value_satoshis()); + secp_check!( + self.context.secp_ctx.verify_ecdsa( + &sighash, + &msg.signature, + self.funding.counterparty_funding_pubkey() + ), + "Invalid closing tx signature from peer".to_owned() + ); }, }; for outp in closing_tx.trust().built_transaction().output.iter() { - if !outp.script_pubkey.is_witness_program() && outp.value < Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS) { + if !outp.script_pubkey.is_witness_program() + && outp.value < Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS) + { return Err(ChannelError::close("Remote sent us a closing_signed with a dust output. Always use segwit closing scripts!".to_owned())); } } @@ -7783,7 +9557,8 @@ impl FundedChannel where if let Some((last_fee, _, _, Some(sig))) = self.context.last_sent_closing_fee { if last_fee == msg.fee_satoshis { let shutdown_result = self.shutdown_result_coop_close(); - let tx = self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig); + let tx = + self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig); self.context.channel_state = ChannelState::ShutdownComplete; self.context.update_time_counter += 1; return Ok((None, Some(tx), Some(shutdown_result))); @@ -7801,26 +9576,40 @@ impl FundedChannel where self.build_closing_transaction($new_fee, skip_remote_output)? }; - let closing_signed = self.get_closing_signed_msg(&closing_tx, skip_remote_output, used_fee, our_min_fee, our_max_fee, logger); + let closing_signed = self.get_closing_signed_msg( + &closing_tx, + skip_remote_output, + used_fee, + our_min_fee, + our_max_fee, + logger, + ); let (signed_tx, shutdown_result) = if $new_fee == msg.fee_satoshis { - let shutdown_result = closing_signed.as_ref() - .map(|_| self.shutdown_result_coop_close()); + let shutdown_result = + closing_signed.as_ref().map(|_| self.shutdown_result_coop_close()); if closing_signed.is_some() { self.context.channel_state = ChannelState::ShutdownComplete; } self.context.update_time_counter += 1; self.context.last_received_closing_sig = Some(msg.signature.clone()); - let tx = closing_signed.as_ref().map(|ClosingSigned { signature, .. }| - self.build_signed_closing_transaction(&closing_tx, &msg.signature, signature)); + let tx = closing_signed.as_ref().map(|ClosingSigned { signature, .. }| { + self.build_signed_closing_transaction( + &closing_tx, + &msg.signature, + signature, + ) + }); (tx, shutdown_result) } else { (None, None) }; return Ok((closing_signed, signed_tx, shutdown_result)) - } + }; } - if let Some(msgs::ClosingSignedFeeRange { min_fee_satoshis, max_fee_satoshis }) = msg.fee_range { + if let Some(msgs::ClosingSignedFeeRange { min_fee_satoshis, max_fee_satoshis }) = + msg.fee_range + { if msg.fee_satoshis < min_fee_satoshis || msg.fee_satoshis > max_fee_satoshis { return Err(ChannelError::close(format!("Peer sent a bogus closing_signed - suggested fee of {} sat was not in their desired range of {} sat - {} sat", msg.fee_satoshis, min_fee_satoshis, max_fee_satoshis))); } @@ -7834,7 +9623,11 @@ impl FundedChannel where if !self.funding.is_outbound() { // They have to pay, so pick the highest fee in the overlapping range. // We should never set an upper bound aside from their full balance - debug_assert_eq!(our_max_fee, self.funding.get_value_satoshis() - (self.funding.value_to_self_msat + 999) / 1000); + debug_assert_eq!( + our_max_fee, + self.funding.get_value_satoshis() + - (self.funding.value_to_self_msat + 999) / 1000 + ); propose_fee!(cmp::min(max_fee_satoshis, our_max_fee)); } else { if msg.fee_satoshis < our_min_fee || msg.fee_satoshis > our_max_fee { @@ -7878,16 +9671,23 @@ impl FundedChannel where } fn internal_htlc_satisfies_config( - &self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, config: &ChannelConfig, + &self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, + config: &ChannelConfig, ) -> Result<(), (&'static str, LocalHTLCFailureReason)> { - let fee = amt_to_forward.checked_mul(config.forwarding_fee_proportional_millionths as u64) - .and_then(|prop_fee| (prop_fee / 1000000).checked_add(config.forwarding_fee_base_msat as u64)); - if fee.is_none() || htlc.amount_msat < fee.unwrap() || - (htlc.amount_msat - fee.unwrap()) < amt_to_forward { + let fee = amt_to_forward + .checked_mul(config.forwarding_fee_proportional_millionths as u64) + .and_then(|prop_fee| { + (prop_fee / 1000000).checked_add(config.forwarding_fee_base_msat as u64) + }); + if fee.is_none() + || htlc.amount_msat < fee.unwrap() + || (htlc.amount_msat - fee.unwrap()) < amt_to_forward + { return Err(("Prior hop has deviated from specified fees parameters or origin node has obsolete ones", LocalHTLCFailureReason::FeeInsufficient)); } - if (htlc.cltv_expiry as u64) < outgoing_cltv_value as u64 + config.cltv_expiry_delta as u64 { + if (htlc.cltv_expiry as u64) < outgoing_cltv_value as u64 + config.cltv_expiry_delta as u64 + { return Err(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", LocalHTLCFailureReason::IncorrectCLTVExpiry)); } @@ -7900,74 +9700,105 @@ impl FundedChannel where pub fn htlc_satisfies_config( &self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, ) -> Result<(), (&'static str, LocalHTLCFailureReason)> { - self.internal_htlc_satisfies_config(&htlc, amt_to_forward, outgoing_cltv_value, &self.context.config()) - .or_else(|err| { - if let Some(prev_config) = self.context.prev_config() { - self.internal_htlc_satisfies_config(htlc, amt_to_forward, outgoing_cltv_value, &prev_config) - } else { - Err(err) - } - }) + self.internal_htlc_satisfies_config( + &htlc, + amt_to_forward, + outgoing_cltv_value, + &self.context.config(), + ) + .or_else(|err| { + if let Some(prev_config) = self.context.prev_config() { + self.internal_htlc_satisfies_config( + htlc, + amt_to_forward, + outgoing_cltv_value, + &prev_config, + ) + } else { + Err(err) + } + }) } /// When this function is called, the HTLC is already irrevocably committed to the channel; /// this function determines whether to fail the HTLC, or forward / claim it. pub fn can_accept_incoming_htlc( - &self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator, logger: L + &self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator, logger: L, ) -> Result<(), (&'static str, LocalHTLCFailureReason)> where F::Target: FeeEstimator, - L::Target: Logger + L::Target: Logger, { if self.context.channel_state.is_local_shutdown_sent() { - return Err(("Shutdown was already sent", LocalHTLCFailureReason::ChannelClosed)) + return Err(("Shutdown was already sent", LocalHTLCFailureReason::ChannelClosed)); } - let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator); - let htlc_stats = self.context.get_pending_htlc_stats(&self.funding, None, dust_exposure_limiting_feerate); - let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); - let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat; + let dust_exposure_limiting_feerate = + self.context.get_dust_exposure_limiting_feerate(&fee_estimator); + let htlc_stats = self.context.get_pending_htlc_stats( + &self.funding, + None, + dust_exposure_limiting_feerate, + ); + let max_dust_htlc_exposure_msat = + self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate); + let on_counterparty_tx_dust_htlc_exposure_msat = + htlc_stats.on_counterparty_tx_dust_exposure_msat; if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat { // Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction log_info!(logger, "Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx", on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat); - return Err(("Exceeded our total dust exposure limit on counterparty commitment tx", - LocalHTLCFailureReason::DustLimitCounterparty)) + return Err(( + "Exceeded our total dust exposure limit on counterparty commitment tx", + LocalHTLCFailureReason::DustLimitCounterparty, + )); } - let htlc_success_dust_limit = if self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - 0 - } else { - let dust_buffer_feerate = self.context.get_dust_buffer_feerate(None) as u64; - dust_buffer_feerate * htlc_success_tx_weight(self.funding.get_channel_type()) / 1000 - }; - let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis; + let htlc_success_dust_limit = + if self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + 0 + } else { + let dust_buffer_feerate = self.context.get_dust_buffer_feerate(None) as u64; + dust_buffer_feerate * htlc_success_tx_weight(self.funding.get_channel_type()) / 1000 + }; + let exposure_dust_limit_success_sats = + htlc_success_dust_limit + self.context.holder_dust_limit_satoshis; if msg.amount_msat / 1000 < exposure_dust_limit_success_sats { let on_holder_tx_dust_htlc_exposure_msat = htlc_stats.on_holder_tx_dust_exposure_msat; if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat { log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat); - return Err(("Exceeded our dust exposure limit on holder commitment tx", - LocalHTLCFailureReason::DustLimitHolder)) + return Err(( + "Exceeded our dust exposure limit on holder commitment tx", + LocalHTLCFailureReason::DustLimitHolder, + )); } } - let anchor_outputs_value_msat = if self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 - } else { - 0 - }; + let anchor_outputs_value_msat = + if self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 + } else { + 0 + }; let mut removed_outbound_total_msat = 0; for ref htlc in self.context.pending_outbound_htlcs.iter() { - if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) = htlc.state { + if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success( + _, + )) = htlc.state + { removed_outbound_total_msat += htlc.amount_msat; - } else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) = htlc.state { + } else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke( + OutboundHTLCOutcome::Success(_), + ) = htlc.state + { removed_outbound_total_msat += htlc.amount_msat; } } - let pending_value_to_self_msat = - self.funding.value_to_self_msat + htlc_stats.pending_inbound_htlcs_value_msat - removed_outbound_total_msat; + let pending_value_to_self_msat = self.funding.value_to_self_msat + + htlc_stats.pending_inbound_htlcs_value_msat + - removed_outbound_total_msat; let pending_remote_value_msat = self.funding.get_value_satoshis() * 1000 - pending_value_to_self_msat; @@ -7979,11 +9810,16 @@ impl FundedChannel where // // A `None` `HTLCCandidate` is used as in this case because we're already accounting for // the incoming HTLC as it has been fully committed by both sides. - let mut remote_fee_cost_incl_stuck_buffer_msat = self.context.next_remote_commit_tx_fee_msat(&self.funding, None, Some(())); + let mut remote_fee_cost_incl_stuck_buffer_msat = + self.context.next_remote_commit_tx_fee_msat(&self.funding, None, Some(())); if !self.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE; } - if pending_remote_value_msat.saturating_sub(self.funding.holder_selected_channel_reserve_satoshis * 1000).saturating_sub(anchor_outputs_value_msat) < remote_fee_cost_incl_stuck_buffer_msat { + if pending_remote_value_msat + .saturating_sub(self.funding.holder_selected_channel_reserve_satoshis * 1000) + .saturating_sub(anchor_outputs_value_msat) + < remote_fee_cost_incl_stuck_buffer_msat + { log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", &self.context.channel_id()); return Err(("Fee spike buffer violation", LocalHTLCFailureReason::FeeSpikeBuffer)); } @@ -7997,7 +9833,8 @@ impl FundedChannel where } pub fn get_cur_counterparty_commitment_transaction_number(&self) -> u64 { - self.context.cur_counterparty_commitment_transaction_number + 1 - if self.context.channel_state.is_awaiting_remote_revoke() { 1 } else { 0 } + self.context.cur_counterparty_commitment_transaction_number + 1 + - if self.context.channel_state.is_awaiting_remote_revoke() { 1 } else { 0 } } pub fn get_revoked_counterparty_commitment_transaction_number(&self) -> u64 { @@ -8014,22 +9851,37 @@ impl FundedChannel where ChannelValueStat { value_to_self_msat: self.funding.value_to_self_msat, channel_value_msat: self.funding.get_value_satoshis() * 1000, - channel_reserve_msat: self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000, - pending_outbound_htlcs_amount_msat: self.context.pending_outbound_htlcs.iter().map(|ref h| h.amount_msat).sum::(), - pending_inbound_htlcs_amount_msat: self.context.pending_inbound_htlcs.iter().map(|ref h| h.amount_msat).sum::(), + channel_reserve_msat: self + .funding + .counterparty_selected_channel_reserve_satoshis + .unwrap() * 1000, + pending_outbound_htlcs_amount_msat: self + .context + .pending_outbound_htlcs + .iter() + .map(|ref h| h.amount_msat) + .sum::(), + pending_inbound_htlcs_amount_msat: self + .context + .pending_inbound_htlcs + .iter() + .map(|ref h| h.amount_msat) + .sum::(), holding_cell_outbound_amount_msat: { let mut res = 0; for h in self.context.holding_cell_htlc_updates.iter() { match h { - &HTLCUpdateAwaitingACK::AddHTLC{amount_msat, .. } => { + &HTLCUpdateAwaitingACK::AddHTLC { amount_msat, .. } => { res += amount_msat; - } - _ => {} + }, + _ => {}, } } res }, - counterparty_max_htlc_value_in_flight_msat: self.context.counterparty_max_htlc_value_in_flight_msat, + counterparty_max_htlc_value_in_flight_msat: self + .context + .counterparty_max_htlc_value_in_flight_msat, counterparty_dust_limit_msat: self.context.counterparty_dust_limit_satoshis * 1000, } } @@ -8042,27 +9894,32 @@ impl FundedChannel where /// Gets the latest [`ChannelMonitorUpdate`] ID which has been released and is in-flight. pub fn get_latest_unblocked_monitor_update_id(&self) -> u64 { - if self.context.blocked_monitor_updates.is_empty() { return self.context.get_latest_monitor_update_id(); } + if self.context.blocked_monitor_updates.is_empty() { + return self.context.get_latest_monitor_update_id(); + } self.context.blocked_monitor_updates[0].update.update_id - 1 } /// Returns the next blocked monitor update, if one exists, and a bool which indicates a /// further blocked monitor update exists after the next. pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(ChannelMonitorUpdate, bool)> { - if self.context.blocked_monitor_updates.is_empty() { return None; } - Some((self.context.blocked_monitor_updates.remove(0).update, - !self.context.blocked_monitor_updates.is_empty())) + if self.context.blocked_monitor_updates.is_empty() { + return None; + } + Some(( + self.context.blocked_monitor_updates.remove(0).update, + !self.context.blocked_monitor_updates.is_empty(), + )) } /// Pushes a new monitor update into our monitor update queue, returning it if it should be /// immediately given to the user for persisting or `None` if it should be held as blocked. - fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) - -> Option { + fn push_ret_blockable_mon_update( + &mut self, update: ChannelMonitorUpdate, + ) -> Option { let release_monitor = self.context.blocked_monitor_updates.is_empty(); if !release_monitor { - self.context.blocked_monitor_updates.push(PendingChannelMonitorUpdate { - update, - }); + self.context.blocked_monitor_updates.push(PendingChannelMonitorUpdate { update }); None } else { Some(update) @@ -8072,7 +9929,9 @@ impl FundedChannel where /// On startup, its possible we detect some monitor updates have actually completed (and the /// ChannelManager was simply stale). In that case, we should simply drop them, which we do /// here after logging them. - pub fn on_startup_drop_completed_blocked_mon_updates_through(&mut self, logger: &L, loaded_mon_update_id: u64) { + pub fn on_startup_drop_completed_blocked_mon_updates_through( + &mut self, logger: &L, loaded_mon_update_id: u64, + ) { let channel_id = self.context.channel_id(); self.context.blocked_monitor_updates.retain(|update| { if update.update.update_id <= loaded_mon_update_id { @@ -8098,7 +9957,9 @@ impl FundedChannel where /// transaction. If the channel is inbound, this implies simply that the channel has not /// advanced state. pub fn is_awaiting_initial_mon_persist(&self) -> bool { - if !self.is_awaiting_monitor_update() { return false; } + if !self.is_awaiting_monitor_update() { + return false; + } if matches!( self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.clone().clear(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY | FundedStateFlags::PEER_DISCONNECTED | FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS | AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty() @@ -8108,8 +9969,10 @@ impl FundedChannel where debug_assert!(self.context.minimum_depth.unwrap_or(1) > 0); return true; } - if self.holder_commitment_point.transaction_number() == INITIAL_COMMITMENT_NUMBER - 1 && - self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 { + if self.holder_commitment_point.transaction_number() == INITIAL_COMMITMENT_NUMBER - 1 + && self.context.cur_counterparty_commitment_transaction_number + == INITIAL_COMMITMENT_NUMBER - 1 + { // If we're a 0-conf channel, we'll move beyond AwaitingChannelReady immediately even while // waiting for the initial monitor persistence. Thus, we check if our commitment // transaction numbers have both been iterated only exactly once (for the @@ -8122,7 +9985,9 @@ impl FundedChannel where // Because deciding we're awaiting initial broadcast spuriously could result in // funds-loss (as we don't have a monitor, but have the funding transaction confirmed), // we hard-assert here, even in production builds. - if self.funding.is_outbound() { assert!(self.funding.funding_transaction.is_some()); } + if self.funding.is_outbound() { + assert!(self.funding.funding_transaction.is_some()); + } assert!(self.context.monitor_pending_channel_ready); assert_eq!(self.context.latest_monitor_update_id, 0); return true; @@ -8132,8 +9997,8 @@ impl FundedChannel where /// Returns true if our channel_ready has been sent pub fn is_our_channel_ready(&self) -> bool { - matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::OUR_CHANNEL_READY)) || - matches!(self.context.channel_state, ChannelState::ChannelReady(_)) + matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::OUR_CHANNEL_READY)) + || matches!(self.context.channel_state, ChannelState::ChannelReady(_)) } /// Returns true if our peer has either initiated or agreed to shut down the channel. @@ -8173,17 +10038,22 @@ impl FundedChannel where self.context.channel_update_status = status; } - fn check_get_channel_ready(&mut self, height: u32, logger: &L) -> Option - where L::Target: Logger + fn check_get_channel_ready( + &mut self, height: u32, logger: &L, + ) -> Option + where + L::Target: Logger, { // Called: // * always when a new block/transactions are confirmed with the new height // * when funding is signed with a height of 0 - if self.context.funding_tx_confirmation_height == 0 && self.context.minimum_depth != Some(0) { + if self.context.funding_tx_confirmation_height == 0 && self.context.minimum_depth != Some(0) + { return None; } - let funding_tx_confirmations = height as i64 - self.context.funding_tx_confirmation_height as i64 + 1; + let funding_tx_confirmations = + height as i64 - self.context.funding_tx_confirmation_height as i64 + 1; if funding_tx_confirmations <= 0 { self.context.funding_tx_confirmation_height = 0; } @@ -8194,28 +10064,35 @@ impl FundedChannel where // Note that we don't include ChannelState::WaitingForBatch as we don't want to send // channel_ready until the entire batch is ready. - let need_commitment_update = if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()).is_empty()) { + let need_commitment_update = if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()).is_empty()) + { self.context.channel_state.set_our_channel_ready(); true - } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()) == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY) { - self.context.channel_state = ChannelState::ChannelReady(self.context.channel_state.with_funded_state_flags_mask().into()); + } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()) == AwaitingChannelReadyFlags::THEIR_CHANNEL_READY) + { + self.context.channel_state = ChannelState::ChannelReady( + self.context.channel_state.with_funded_state_flags_mask().into(), + ); self.context.update_time_counter += 1; true - } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()) == AwaitingChannelReadyFlags::OUR_CHANNEL_READY) { + } else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(f) if f.clone().clear(FundedStateFlags::ALL.into()) == AwaitingChannelReadyFlags::OUR_CHANNEL_READY) + { // We got a reorg but not enough to trigger a force close, just ignore. false } else { - if self.context.funding_tx_confirmation_height != 0 && - self.context.channel_state < ChannelState::ChannelReady(ChannelReadyFlags::new()) + if self.context.funding_tx_confirmation_height != 0 + && self.context.channel_state < ChannelState::ChannelReady(ChannelReadyFlags::new()) { // We should never see a funding transaction on-chain until we've received // funding_signed (if we're an outbound channel), or seen funding_generated (if we're // an inbound channel - before that we have no known funding TXID). The fuzzer, // however, may do this and we shouldn't treat it as a bug. #[cfg(not(fuzzing))] - panic!("Started confirming a channel in a state pre-AwaitingChannelReady: {}.\n\ + panic!( + "Started confirming a channel in a state pre-AwaitingChannelReady: {}.\n\ Do NOT broadcast a funding transaction manually - let LDK do it for you!", - self.context.channel_state.to_u32()); + self.context.channel_state.to_u32() + ); } // We got a reorg but not enough to trigger a force close, just ignore. false @@ -8240,9 +10117,10 @@ impl FundedChannel where self.get_channel_ready(logger) } - fn get_channel_ready( - &mut self, logger: &L - ) -> Option where L::Target: Logger { + fn get_channel_ready(&mut self, logger: &L) -> Option + where + L::Target: Logger, + { if let HolderCommitmentPoint::Available { current, .. } = self.holder_commitment_point { self.context.signer_pending_channel_ready = false; Some(msgs::ChannelReady { @@ -8251,7 +10129,10 @@ impl FundedChannel where short_channel_id_alias: Some(self.context.outbound_scid_alias), }) } else { - log_debug!(logger, "Not producing channel_ready: the holder commitment point is not available."); + log_debug!( + logger, + "Not producing channel_ready: the holder commitment point is not available." + ); self.context.signer_pending_channel_ready = true; None } @@ -8262,11 +10143,11 @@ impl FundedChannel where /// In the second, we simply return an Err indicating we need to be force-closed now. pub fn transactions_confirmed( &mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData, - chain_hash: ChainHash, node_signer: &NS, user_config: &UserConfig, logger: &L + chain_hash: ChainHash, node_signer: &NS, user_config: &UserConfig, logger: &L, ) -> Result<(Option, Option), ClosureReason> where NS::Target: NodeSigner, - L::Target: Logger + L::Target: Logger, { let mut msgs = (None, None); if let Some(funding_txo) = self.funding.get_funding_txo() { @@ -8276,8 +10157,12 @@ impl FundedChannel where if self.context.funding_tx_confirmation_height == 0 { if tx.compute_txid() == funding_txo.txid { let txo_idx = funding_txo.index as usize; - if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.funding.get_funding_redeemscript().to_p2wsh() || - tx.output[txo_idx].value.to_sat() != self.funding.get_value_satoshis() { + if txo_idx >= tx.output.len() + || tx.output[txo_idx].script_pubkey + != self.funding.get_funding_redeemscript().to_p2wsh() + || tx.output[txo_idx].value.to_sat() + != self.funding.get_value_satoshis() + { if self.funding.is_outbound() { // If we generated the funding transaction and it doesn't match what it // should, the client is really broken and we should just panic and @@ -8289,7 +10174,9 @@ impl FundedChannel where } self.context.update_time_counter += 1; let err_reason = "funding tx had wrong script/value or output index"; - return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() }); + return Err(ClosureReason::ProcessingError { + err: err_reason.to_owned(), + }); } else { if self.funding.is_outbound() { if !tx.is_coinbase() { @@ -8312,9 +10199,10 @@ impl FundedChannel where } // If this is a coinbase transaction and not a 0-conf channel // we should update our min_depth to 100 to handle coinbase maturity - if tx.is_coinbase() && - self.context.minimum_depth.unwrap_or(0) > 0 && - self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY { + if tx.is_coinbase() + && self.context.minimum_depth.unwrap_or(0) > 0 + && self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY + { self.context.minimum_depth = Some(COINBASE_MATURITY); } } @@ -8322,14 +10210,31 @@ impl FundedChannel where // send it immediately instead of waiting for a best_block_updated call (which // may have already happened for this block). if let Some(channel_ready) = self.check_get_channel_ready(height, logger) { - log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id); - let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger); + log_info!( + logger, + "Sending a channel_ready to our peer for channel {}", + &self.context.channel_id + ); + let announcement_sigs = self.get_announcement_sigs( + node_signer, + chain_hash, + user_config, + height, + logger, + ); msgs = (Some(channel_ready), announcement_sigs); } } for inp in tx.input.iter() { if inp.previous_output == funding_txo.into_bitcoin_outpoint() { - log_info!(logger, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.compute_txid(), inp.previous_output.txid, inp.previous_output.vout, &self.context.channel_id()); + log_info!( + logger, + "Detected channel-closing tx {} spending {}:{}, closing channel {}", + tx.compute_txid(), + inp.previous_output.txid, + inp.previous_output.vout, + &self.context.channel_id() + ); return Err(ClosureReason::CommitmentTxConfirmed); } } @@ -8350,54 +10255,88 @@ impl FundedChannel where /// May return some HTLCs (and their payment_hash) which have timed out and should be failed /// back. pub fn best_block_updated( - &mut self, height: u32, highest_header_time: u32, chain_hash: ChainHash, - node_signer: &NS, user_config: &UserConfig, logger: &L - ) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> + &mut self, height: u32, highest_header_time: u32, chain_hash: ChainHash, node_signer: &NS, + user_config: &UserConfig, logger: &L, + ) -> Result< + ( + Option, + Vec<(HTLCSource, PaymentHash)>, + Option, + ), + ClosureReason, + > where NS::Target: NodeSigner, - L::Target: Logger + L::Target: Logger, { - self.do_best_block_updated(height, highest_header_time, Some((chain_hash, node_signer, user_config)), logger) + self.do_best_block_updated( + height, + highest_header_time, + Some((chain_hash, node_signer, user_config)), + logger, + ) } fn do_best_block_updated( &mut self, height: u32, highest_header_time: u32, - chain_node_signer: Option<(ChainHash, &NS, &UserConfig)>, logger: &L - ) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> + chain_node_signer: Option<(ChainHash, &NS, &UserConfig)>, logger: &L, + ) -> Result< + ( + Option, + Vec<(HTLCSource, PaymentHash)>, + Option, + ), + ClosureReason, + > where NS::Target: NodeSigner, - L::Target: Logger + L::Target: Logger, { let mut timed_out_htlcs = Vec::new(); // This mirrors the check in ChannelManager::decode_update_add_htlc_onion, refusing to // forward an HTLC when our counterparty should almost certainly just fail it for expiring // ~now. let unforwarded_htlc_cltv_limit = height + LATENCY_GRACE_PERIOD_BLOCKS; - self.context.holding_cell_htlc_updates.retain(|htlc_update| { - match htlc_update { - &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, .. } => { - if *cltv_expiry <= unforwarded_htlc_cltv_limit { - timed_out_htlcs.push((source.clone(), payment_hash.clone())); - false - } else { true } - }, - _ => true - } + self.context.holding_cell_htlc_updates.retain(|htlc_update| match htlc_update { + &HTLCUpdateAwaitingACK::AddHTLC { + ref payment_hash, + ref source, + ref cltv_expiry, + .. + } => { + if *cltv_expiry <= unforwarded_htlc_cltv_limit { + timed_out_htlcs.push((source.clone(), payment_hash.clone())); + false + } else { + true + } + }, + _ => true, }); - self.context.update_time_counter = cmp::max(self.context.update_time_counter, highest_header_time); + self.context.update_time_counter = + cmp::max(self.context.update_time_counter, highest_header_time); if let Some(channel_ready) = self.check_get_channel_ready(height, logger) { - let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer { - self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger) - } else { None }; - log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id); + let announcement_sigs = + if let Some((chain_hash, node_signer, user_config)) = chain_node_signer { + self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger) + } else { + None + }; + log_info!( + logger, + "Sending a channel_ready to our peer for channel {}", + &self.context.channel_id + ); return Ok((Some(channel_ready), timed_out_htlcs, announcement_sigs)); } - if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) || - self.context.channel_state.is_our_channel_ready() { - let mut funding_tx_confirmations = height as i64 - self.context.funding_tx_confirmation_height as i64 + 1; + if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) + || self.context.channel_state.is_our_channel_ready() + { + let mut funding_tx_confirmations = + height as i64 - self.context.funding_tx_confirmation_height as i64 + 1; if self.context.funding_tx_confirmation_height == 0 { // Note that check_get_channel_ready may reset funding_tx_confirmation_height to // zero if it has been reorged out, however in either case, our state flags @@ -8415,29 +10354,48 @@ impl FundedChannel where // `ChannelManager::short_to_chan_info` map being inconsistent, so we currently have // to. if funding_tx_confirmations == 0 && self.context.funding_tx_confirmed_in.is_some() { - let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.", - self.context.minimum_depth.unwrap(), funding_tx_confirmations); + let err_reason = format!( + "Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.", + self.context.minimum_depth.unwrap(), + funding_tx_confirmations + ); return Err(ClosureReason::ProcessingError { err: err_reason }); } - } else if !self.funding.is_outbound() && self.context.funding_tx_confirmed_in.is_none() && - height >= self.context.channel_creation_height + FUNDING_CONF_DEADLINE_BLOCKS { - log_info!(logger, "Closing channel {} due to funding timeout", &self.context.channel_id); + } else if !self.funding.is_outbound() + && self.context.funding_tx_confirmed_in.is_none() + && height >= self.context.channel_creation_height + FUNDING_CONF_DEADLINE_BLOCKS + { + log_info!( + logger, + "Closing channel {} due to funding timeout", + &self.context.channel_id + ); // If funding_tx_confirmed_in is unset, the channel must not be active - assert!(self.context.channel_state <= ChannelState::ChannelReady(ChannelReadyFlags::new())); + assert!( + self.context.channel_state <= ChannelState::ChannelReady(ChannelReadyFlags::new()) + ); assert!(!self.context.channel_state.is_our_channel_ready()); return Err(ClosureReason::FundingTimedOut); } - let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer { - self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger) - } else { None }; + let announcement_sigs = + if let Some((chain_hash, node_signer, user_config)) = chain_node_signer { + self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger) + } else { + None + }; Ok((None, timed_out_htlcs, announcement_sigs)) } /// Indicates the funding transaction is no longer confirmed in the main chain. This may /// force-close the channel, but may also indicate a harmless reorganization of a block or two /// before the channel has reached channel_ready and we can just wait for more blocks. - pub fn funding_transaction_unconfirmed(&mut self, logger: &L) -> Result<(), ClosureReason> where L::Target: Logger { + pub fn funding_transaction_unconfirmed( + &mut self, logger: &L, + ) -> Result<(), ClosureReason> + where + L::Target: Logger, + { if self.context.funding_tx_confirmation_height != 0 { // We handle the funding disconnection by calling best_block_updated with a height one // below where our funding was connected, implying a reorg back to conf_height - 1. @@ -8446,14 +10404,25 @@ impl FundedChannel where // larger. If we don't know that time has moved forward, we can just set it to the last // time we saw and it will be ignored. let best_time = self.context.update_time_counter; - match self.do_best_block_updated(reorg_height, best_time, None::<(ChainHash, &&dyn NodeSigner, &UserConfig)>, logger) { + match self.do_best_block_updated( + reorg_height, + best_time, + None::<(ChainHash, &&dyn NodeSigner, &UserConfig)>, + logger, + ) { Ok((channel_ready, timed_out_htlcs, announcement_sigs)) => { - assert!(channel_ready.is_none(), "We can't generate a funding with 0 confirmations?"); + assert!( + channel_ready.is_none(), + "We can't generate a funding with 0 confirmations?" + ); assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?"); - assert!(announcement_sigs.is_none(), "We can't generate an announcement_sigs with 0 confirmations?"); + assert!( + announcement_sigs.is_none(), + "We can't generate an announcement_sigs with 0 confirmations?" + ); Ok(()) }, - Err(e) => Err(e) + Err(e) => Err(e), } } else { // We never learned about the funding confirmation anyway, just ignore @@ -8477,18 +10446,29 @@ impl FundedChannel where /// [`ChannelReady`]: crate::ln::msgs::ChannelReady fn get_channel_announcement( &self, node_signer: &NS, chain_hash: ChainHash, user_config: &UserConfig, - ) -> Result where NS::Target: NodeSigner { + ) -> Result + where + NS::Target: NodeSigner, + { if !self.context.config.announce_for_forwarding { - return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned())); + return Err(ChannelError::Ignore( + "Channel is not available for public announcements".to_owned(), + )); } if !self.context.is_usable() { - return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned())); + return Err(ChannelError::Ignore( + "Cannot get a ChannelAnnouncement if the channel is not currently usable" + .to_owned(), + )); } - let short_channel_id = self.context.get_short_channel_id() - .ok_or(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel has not been confirmed yet".to_owned()))?; - let node_id = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node) - .map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?); + let short_channel_id = self.context.get_short_channel_id().ok_or(ChannelError::Ignore( + "Cannot get a ChannelAnnouncement if the channel has not been confirmed yet".to_owned(), + ))?; + let node_id = + NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node).map_err(|_| { + ChannelError::Ignore("Failed to retrieve own public key".to_owned()) + })?); let counterparty_node_id = NodeId::from_pubkey(&self.context.get_counterparty_node_id()); let were_node_one = node_id.as_slice() < counterparty_node_id.as_slice(); @@ -8498,8 +10478,16 @@ impl FundedChannel where short_channel_id, node_id_1: if were_node_one { node_id } else { counterparty_node_id }, node_id_2: if were_node_one { counterparty_node_id } else { node_id }, - bitcoin_key_1: NodeId::from_pubkey(if were_node_one { &self.funding.get_holder_pubkeys().funding_pubkey } else { self.funding.counterparty_funding_pubkey() }), - bitcoin_key_2: NodeId::from_pubkey(if were_node_one { self.funding.counterparty_funding_pubkey() } else { &self.funding.get_holder_pubkeys().funding_pubkey }), + bitcoin_key_1: NodeId::from_pubkey(if were_node_one { + &self.funding.get_holder_pubkeys().funding_pubkey + } else { + self.funding.counterparty_funding_pubkey() + }), + bitcoin_key_2: NodeId::from_pubkey(if were_node_one { + self.funding.counterparty_funding_pubkey() + } else { + &self.funding.get_holder_pubkeys().funding_pubkey + }), excess_data: Vec::new(), }; @@ -8508,13 +10496,15 @@ impl FundedChannel where fn get_announcement_sigs( &mut self, node_signer: &NS, chain_hash: ChainHash, user_config: &UserConfig, - best_block_height: u32, logger: &L + best_block_height: u32, logger: &L, ) -> Option where NS::Target: NodeSigner, - L::Target: Logger + L::Target: Logger, { - if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height { + if self.context.funding_tx_confirmation_height == 0 + || self.context.funding_tx_confirmation_height + 5 > best_block_height + { return None; } @@ -8523,7 +10513,10 @@ impl FundedChannel where } if self.context.channel_state.is_peer_disconnected() { - log_trace!(logger, "Cannot create an announcement_signatures as our peer is disconnected"); + log_trace!( + logger, + "Cannot create an announcement_signatures as our peer is disconnected" + ); return None; } @@ -8531,31 +10524,40 @@ impl FundedChannel where return None; } - log_trace!(logger, "Creating an announcement_signatures message for channel {}", &self.context.channel_id()); - let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) { + log_trace!( + logger, + "Creating an announcement_signatures message for channel {}", + &self.context.channel_id() + ); + let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) + { Ok(a) => a, Err(e) => { log_trace!(logger, "{:?}", e); return None; - } + }, }; - let our_node_sig = match node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) { + let our_node_sig = match node_signer + .sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) + { Err(_) => { log_error!(logger, "Failed to generate node signature for channel_announcement. Channel will not be announced!"); return None; }, - Ok(v) => v + Ok(v) => v, }; match &self.context.holder_signer { ChannelSignerType::Ecdsa(ecdsa) => { let our_bitcoin_sig = match ecdsa.sign_channel_announcement_with_funding_key( - &self.funding.channel_transaction_parameters, &announcement, &self.context.secp_ctx, + &self.funding.channel_transaction_parameters, + &announcement, + &self.context.secp_ctx, ) { Err(_) => { log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!"); return None; }, - Ok(v) => v + Ok(v) => v, }; let short_channel_id = match self.context.get_short_channel_id() { Some(scid) => scid, @@ -8573,39 +10575,64 @@ impl FundedChannel where }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), } } /// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are /// available. fn sign_channel_announcement( - &self, node_signer: &NS, announcement: msgs::UnsignedChannelAnnouncement - ) -> Result where NS::Target: NodeSigner { + &self, node_signer: &NS, announcement: msgs::UnsignedChannelAnnouncement, + ) -> Result + where + NS::Target: NodeSigner, + { if let Some((their_node_sig, their_bitcoin_sig)) = self.context.announcement_sigs { - let our_node_key = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node) - .map_err(|_| ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()))?); + let our_node_key = + NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node).map_err(|_| { + ChannelError::Ignore("Signer failed to retrieve own public key".to_owned()) + })?); let were_node_one = announcement.node_id_1 == our_node_key; - let our_node_sig = node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement(&announcement)) - .map_err(|_| ChannelError::Ignore("Failed to generate node signature for channel_announcement".to_owned()))?; + let our_node_sig = node_signer + .sign_gossip_message(msgs::UnsignedGossipMessage::ChannelAnnouncement( + &announcement, + )) + .map_err(|_| { + ChannelError::Ignore( + "Failed to generate node signature for channel_announcement".to_owned(), + ) + })?; match &self.context.holder_signer { ChannelSignerType::Ecdsa(ecdsa) => { - let our_bitcoin_sig = ecdsa.sign_channel_announcement_with_funding_key( - &self.funding.channel_transaction_parameters, &announcement, &self.context.secp_ctx, - ) - .map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?; + let our_bitcoin_sig = ecdsa + .sign_channel_announcement_with_funding_key( + &self.funding.channel_transaction_parameters, + &announcement, + &self.context.secp_ctx, + ) + .map_err(|_| { + ChannelError::Ignore("Signer rejected channel_announcement".to_owned()) + })?; Ok(msgs::ChannelAnnouncement { node_signature_1: if were_node_one { our_node_sig } else { their_node_sig }, node_signature_2: if were_node_one { their_node_sig } else { our_node_sig }, - bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { their_bitcoin_sig }, - bitcoin_signature_2: if were_node_one { their_bitcoin_sig } else { our_bitcoin_sig }, + bitcoin_signature_1: if were_node_one { + our_bitcoin_sig + } else { + their_bitcoin_sig + }, + bitcoin_signature_2: if were_node_one { + their_bitcoin_sig + } else { + our_bitcoin_sig + }, contents: announcement, }) }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), } } else { Err(ChannelError::Ignore("Attempted to sign channel announcement before we'd received announcement_signatures".to_string())) @@ -8617,25 +10644,44 @@ impl FundedChannel where /// signatures for later reconstruction/rebroadcast of the channel_announcement. pub fn announcement_signatures( &mut self, node_signer: &NS, chain_hash: ChainHash, best_block_height: u32, - msg: &msgs::AnnouncementSignatures, user_config: &UserConfig - ) -> Result where NS::Target: NodeSigner { + msg: &msgs::AnnouncementSignatures, user_config: &UserConfig, + ) -> Result + where + NS::Target: NodeSigner, + { let announcement = self.get_channel_announcement(node_signer, chain_hash, user_config)?; let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]); - if self.context.secp_ctx.verify_ecdsa(&msghash, &msg.node_signature, &self.context.get_counterparty_node_id()).is_err() { + if self + .context + .secp_ctx + .verify_ecdsa(&msghash, &msg.node_signature, &self.context.get_counterparty_node_id()) + .is_err() + { return Err(ChannelError::close(format!( "Bad announcement_signatures. Failed to verify node_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_node_key is {:?}", &announcement, self.context.get_counterparty_node_id()))); } - if self.context.secp_ctx.verify_ecdsa(&msghash, &msg.bitcoin_signature, self.funding.counterparty_funding_pubkey()).is_err() { + if self + .context + .secp_ctx + .verify_ecdsa( + &msghash, + &msg.bitcoin_signature, + self.funding.counterparty_funding_pubkey(), + ) + .is_err() + { return Err(ChannelError::close(format!( "Bad announcement_signatures. Failed to verify bitcoin_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_bitcoin_key is ({:?})", &announcement, self.funding.counterparty_funding_pubkey()))); } self.context.announcement_sigs = Some((msg.node_signature, msg.bitcoin_signature)); - if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height { + if self.context.funding_tx_confirmation_height == 0 + || self.context.funding_tx_confirmation_height + 5 > best_block_height + { return Err(ChannelError::Ignore( "Got announcement_signatures prior to the required six confirmations - we may not have received a block yet that our peer has".to_owned())); } @@ -8646,12 +10692,19 @@ impl FundedChannel where /// Gets a signed channel_announcement for this channel, if we previously received an /// announcement_signatures from our counterparty. pub fn get_signed_channel_announcement( - &self, node_signer: &NS, chain_hash: ChainHash, best_block_height: u32, user_config: &UserConfig - ) -> Option where NS::Target: NodeSigner { - if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height { + &self, node_signer: &NS, chain_hash: ChainHash, best_block_height: u32, + user_config: &UserConfig, + ) -> Option + where + NS::Target: NodeSigner, + { + if self.context.funding_tx_confirmation_height == 0 + || self.context.funding_tx_confirmation_height + 5 > best_block_height + { return None; } - let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) { + let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) + { Ok(res) => res, Err(_) => return None, }; @@ -8660,14 +10713,22 @@ impl FundedChannel where /// May panic if called on a channel that wasn't immediately-previously /// self.remove_uncommitted_htlcs_and_mark_paused()'d - fn get_channel_reestablish(&mut self, logger: &L) -> msgs::ChannelReestablish where L::Target: Logger { + fn get_channel_reestablish(&mut self, logger: &L) -> msgs::ChannelReestablish + where + L::Target: Logger, + { assert!(self.context.channel_state.is_peer_disconnected()); - assert_ne!(self.context.cur_counterparty_commitment_transaction_number, INITIAL_COMMITMENT_NUMBER); + assert_ne!( + self.context.cur_counterparty_commitment_transaction_number, + INITIAL_COMMITMENT_NUMBER + ); // This is generally the first function which gets called on any given channel once we're // up and running normally. Thus, we take this opportunity to attempt to resolve the // `holder_commitment_point` to get any keys which we are currently missing. self.holder_commitment_point.try_resolve_pending( - &self.context.holder_signer, &self.context.secp_ctx, logger, + &self.context.holder_signer, + &self.context.secp_ctx, + logger, ); // Prior to static_remotekey, my_current_per_commitment_point was critical to claiming // current to_remote balances. However, it no longer has any use, and thus is now simply @@ -8675,15 +10736,22 @@ impl FundedChannel where // fuzzing mode marks a subset of pubkeys as invalid so that we can hit "invalid pubkey" // branches, but we unwrap it below, so we arbitrarily select a dummy pubkey which is both // valid, and valid in fuzzing mode's arbitrary validity criteria: - let mut pk = [2; 33]; pk[1] = 0xff; + let mut pk = [2; 33]; + pk[1] = 0xff; let dummy_pubkey = PublicKey::from_slice(&pk).unwrap(); - let remote_last_secret = if self.context.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER { - let remote_last_secret = self.context.commitment_secrets.get_secret(self.context.cur_counterparty_commitment_transaction_number + 2).unwrap(); + let remote_last_secret = if self.context.cur_counterparty_commitment_transaction_number + 1 + < INITIAL_COMMITMENT_NUMBER + { + let remote_last_secret = self + .context + .commitment_secrets + .get_secret(self.context.cur_counterparty_commitment_transaction_number + 2) + .unwrap(); log_trace!(logger, "Enough info to generate a Data Loss Protect with per_commitment_secret {} for channel {}", log_bytes!(remote_last_secret), &self.context.channel_id()); remote_last_secret } else { log_info!(logger, "Sending a data_loss_protect with no previous remote per_commitment_secret for channel {}", &self.context.channel_id()); - [0;32] + [0; 32] }; msgs::ChannelReestablish { channel_id: self.context.channel_id(), @@ -8696,7 +10764,8 @@ impl FundedChannel where // next_local_commitment_number is the next commitment_signed number we expect to // receive (indicating if they need to resend one that we missed). - next_local_commitment_number: INITIAL_COMMITMENT_NUMBER - self.holder_commitment_point.transaction_number(), + next_local_commitment_number: INITIAL_COMMITMENT_NUMBER + - self.holder_commitment_point.transaction_number(), // We have to set next_remote_commitment_number to the next revoke_and_ack we expect to // receive, however we track it by the next commitment number for a remote transaction // (which is one further, as they always revoke previous commitment transaction, not @@ -8704,7 +10773,9 @@ impl FundedChannel where // cur_counterparty_commitment_transaction_number is INITIAL_COMMITMENT_NUMBER we will have // dropped this channel on disconnect as it hasn't yet reached AwaitingChannelReady so we can't // overflow here. - next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.context.cur_counterparty_commitment_transaction_number - 1, + next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER + - self.context.cur_counterparty_commitment_transaction_number + - 1, your_last_per_commitment_secret: remote_last_secret, my_current_per_commitment_point: dummy_pubkey, next_funding_txid: self.context.next_funding_txid, @@ -8715,33 +10786,40 @@ impl FundedChannel where /// - `our_funding_inputs`: the inputs we contribute to the new funding transaction. /// Includes the witness weight for this input (e.g. P2WPKH_WITNESS_WEIGHT=109 for typical P2WPKH inputs). #[cfg(splicing)] - pub fn splice_channel(&mut self, our_funding_contribution_satoshis: i64, - our_funding_inputs: &Vec<(TxIn, Transaction, Weight)>, - funding_feerate_per_kw: u32, locktime: u32, + pub fn splice_channel( + &mut self, our_funding_contribution_satoshis: i64, + our_funding_inputs: &Vec<(TxIn, Transaction, Weight)>, funding_feerate_per_kw: u32, + locktime: u32, ) -> Result { // Check if a splice has been initiated already. // Note: only a single outstanding splice is supported (per spec) if let Some(splice_info) = &self.pending_splice { - return Err(APIError::APIMisuseError { err: format!( + return Err(APIError::APIMisuseError { + err: format!( "Channel {} cannot be spliced, as it has already a splice pending (contribution {})", self.context.channel_id(), splice_info.our_funding_contribution - )}); + ), + }); } if !self.context.is_live() { - return Err(APIError::APIMisuseError { err: format!( - "Channel {} cannot be spliced, as channel is not live", - self.context.channel_id() - )}); + return Err(APIError::APIMisuseError { + err: format!( + "Channel {} cannot be spliced, as channel is not live", + self.context.channel_id() + ), + }); } // TODO(splicing): check for quiescence if our_funding_contribution_satoshis < 0 { - return Err(APIError::APIMisuseError { err: format!( + return Err(APIError::APIMisuseError { + err: format!( "TODO(splicing): Splice-out not supported, only splice in; channel ID {}, contribution {}", self.context.channel_id(), our_funding_contribution_satoshis, - )}); + ), + }); } // TODO(splicing): Once splice-out is supported, check that channel balance does not go below 0 @@ -8751,24 +10829,36 @@ impl FundedChannel where // (Cannot test for miminum required post-splice channel value) // Check that inputs are sufficient to cover our contribution. - let _fee = check_v2_funding_inputs_sufficient(our_funding_contribution_satoshis, &our_funding_inputs, true, true, funding_feerate_per_kw) - .map_err(|err| APIError::APIMisuseError { err: format!( + let _fee = check_v2_funding_inputs_sufficient( + our_funding_contribution_satoshis, + &our_funding_inputs, + true, + true, + funding_feerate_per_kw, + ) + .map_err(|err| APIError::APIMisuseError { + err: format!( "Insufficient inputs for splicing; channel ID {}, err {}", - self.context.channel_id(), err, - )})?; + self.context.channel_id(), + err, + ), + })?; - self.pending_splice = Some(PendingSplice { - our_funding_contribution: our_funding_contribution_satoshis, - }); + self.pending_splice = + Some(PendingSplice { our_funding_contribution: our_funding_contribution_satoshis }); - let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime); + let msg = self.get_splice_init( + our_funding_contribution_satoshis, + funding_feerate_per_kw, + locktime, + ); Ok(msg) } /// Get the splice message that can be sent during splice initiation. #[cfg(splicing)] - fn get_splice_init(&self, our_funding_contribution_satoshis: i64, - funding_feerate_per_kw: u32, locktime: u32, + fn get_splice_init( + &self, our_funding_contribution_satoshis: i64, funding_feerate_per_kw: u32, locktime: u32, ) -> msgs::SpliceInit { // TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542. // Note that channel_keys_id is supposed NOT to change @@ -8793,7 +10883,8 @@ impl FundedChannel where // Check if a splice has been initiated already. if let Some(splice_info) = &self.pending_splice { return Err(ChannelError::Warn(format!( - "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution, + "Channel has already a splice pending, contribution {}", + splice_info.our_funding_contribution, ))); } @@ -8801,14 +10892,18 @@ impl FundedChannel where // MUST send a warning and close the connection or send an error // and fail the channel. if !self.context.is_live() { - return Err(ChannelError::Warn(format!("Splicing requested on a channel that is not live"))); + return Err(ChannelError::Warn(format!( + "Splicing requested on a channel that is not live" + ))); } - if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0 { + if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0 + { return Err(ChannelError::Warn(format!( "Splice-out not supported, only splice in, contribution is {} ({} + {})", their_funding_contribution_satoshis + our_funding_contribution_satoshis, - their_funding_contribution_satoshis, our_funding_contribution_satoshis, + their_funding_contribution_satoshis, + our_funding_contribution_satoshis, ))); } @@ -8853,20 +10948,31 @@ impl FundedChannel where /// [`Self::maybe_free_holding_cell_htlcs`] in order to actually generate and send the /// commitment update. pub fn queue_add_htlc( - &mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, - onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option, - blinding_point: Option, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + &mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, + source: HTLCSource, onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option, + blinding_point: Option, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Result<(), (LocalHTLCFailureReason, String)> - where F::Target: FeeEstimator, L::Target: Logger + where + F::Target: FeeEstimator, + L::Target: Logger, { - self - .send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, true, - skimmed_fee_msat, blinding_point, fee_estimator, logger) - .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?")) - .map_err(|err| { - debug_assert!(err.0.is_temporary(), "Queuing HTLC should return temporary error"); - err - }) + self.send_htlc( + amount_msat, + payment_hash, + cltv_expiry, + source, + onion_routing_packet, + true, + skimmed_fee_msat, + blinding_point, + fee_estimator, + logger, + ) + .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?")) + .map_err(|err| { + debug_assert!(err.0.is_temporary(), "Queuing HTLC should return temporary error"); + err + }) } /// Adds a pending outbound HTLC to this channel, note that you probably want @@ -8886,16 +10992,18 @@ impl FundedChannel where /// /// `Err`'s will always be temporary channel failures. fn send_htlc( - &mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, - onion_routing_packet: msgs::OnionPacket, mut force_holding_cell: bool, + &mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, + source: HTLCSource, onion_routing_packet: msgs::OnionPacket, mut force_holding_cell: bool, skimmed_fee_msat: Option, blinding_point: Option, - fee_estimator: &LowerBoundedFeeEstimator, logger: &L + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Result, (LocalHTLCFailureReason, String)> - where F::Target: FeeEstimator, L::Target: Logger + where + F::Target: FeeEstimator, + L::Target: Logger, { - if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) || - self.context.channel_state.is_local_shutdown_sent() || - self.context.channel_state.is_remote_shutdown_sent() + if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) + || self.context.channel_state.is_local_shutdown_sent() + || self.context.channel_state.is_remote_shutdown_sent() { return Err((LocalHTLCFailureReason::ChannelNotReady, "Cannot send HTLC until channel is fully established and we haven't started shutting down".to_owned())); @@ -8912,13 +11020,23 @@ impl FundedChannel where let available_balances = self.get_available_balances(fee_estimator); if amount_msat < available_balances.next_outbound_htlc_minimum_msat { - return Err((LocalHTLCFailureReason::HTLCMinimum, format!("Cannot send less than our next-HTLC minimum - {} msat", - available_balances.next_outbound_htlc_minimum_msat))); + return Err(( + LocalHTLCFailureReason::HTLCMinimum, + format!( + "Cannot send less than our next-HTLC minimum - {} msat", + available_balances.next_outbound_htlc_minimum_msat + ), + )); } if amount_msat > available_balances.next_outbound_htlc_limit_msat { - return Err((LocalHTLCFailureReason::HTLCMaximum, format!("Cannot send more than our next-HTLC maximum - {} msat", - available_balances.next_outbound_htlc_limit_msat))); + return Err(( + LocalHTLCFailureReason::HTLCMaximum, + format!( + "Cannot send more than our next-HTLC maximum - {} msat", + available_balances.next_outbound_htlc_limit_msat + ), + )); } if self.context.channel_state.is_peer_disconnected() { @@ -8928,16 +11046,26 @@ impl FundedChannel where // disconnected during the time the previous hop was doing the commitment dance we may // end up getting here after the forwarding delay. In any case, returning an // IgnoreError will get ChannelManager to do the right thing and fail backwards now. - return Err((LocalHTLCFailureReason::PeerOffline, - "Cannot send an HTLC while disconnected from channel counterparty".to_owned())); + return Err(( + LocalHTLCFailureReason::PeerOffline, + "Cannot send an HTLC while disconnected from channel counterparty".to_owned(), + )); } let need_holding_cell = !self.context.channel_state.can_generate_new_commitment(); - log_debug!(logger, "Pushing new outbound HTLC with hash {} for {} msat {}", - payment_hash, amount_msat, - if force_holding_cell { "into holding cell" } - else if need_holding_cell { "into holding cell as we're awaiting an RAA or monitor" } - else { "to peer" }); + log_debug!( + logger, + "Pushing new outbound HTLC with hash {} for {} msat {}", + payment_hash, + amount_msat, + if force_holding_cell { + "into holding cell" + } else if need_holding_cell { + "into holding cell as we're awaiting an RAA or monitor" + } else { + "to peer" + } + ); if need_holding_cell { force_holding_cell = true; @@ -9000,33 +11128,45 @@ impl FundedChannel where core::iter::once(&self.funding) .chain(self.pending_funding.iter()) .map(|funding| self.context.get_available_balances_for_scope(funding, fee_estimator)) - .reduce(|acc, e| { - AvailableBalances { - inbound_capacity_msat: acc.inbound_capacity_msat.min(e.inbound_capacity_msat), - outbound_capacity_msat: acc.outbound_capacity_msat.min(e.outbound_capacity_msat), - next_outbound_htlc_limit_msat: acc.next_outbound_htlc_limit_msat.min(e.next_outbound_htlc_limit_msat), - next_outbound_htlc_minimum_msat: acc.next_outbound_htlc_minimum_msat.max(e.next_outbound_htlc_minimum_msat), - } + .reduce(|acc, e| AvailableBalances { + inbound_capacity_msat: acc.inbound_capacity_msat.min(e.inbound_capacity_msat), + outbound_capacity_msat: acc.outbound_capacity_msat.min(e.outbound_capacity_msat), + next_outbound_htlc_limit_msat: acc + .next_outbound_htlc_limit_msat + .min(e.next_outbound_htlc_limit_msat), + next_outbound_htlc_minimum_msat: acc + .next_outbound_htlc_minimum_msat + .max(e.next_outbound_htlc_minimum_msat), }) .expect("At least one FundingScope is always provided") } - fn build_commitment_no_status_check(&mut self, logger: &L) -> ChannelMonitorUpdate where L::Target: Logger { + fn build_commitment_no_status_check(&mut self, logger: &L) -> ChannelMonitorUpdate + where + L::Target: Logger, + { log_trace!(logger, "Updating HTLC state for a newly-sent commitment_signed..."); // We can upgrade the status of some HTLCs that are waiting on a commitment, even if we // fail to generate this, we still are at least at a position where upgrading their status // is acceptable. for htlc in self.context.pending_inbound_htlcs.iter_mut() { - let new_state = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(ref forward_info) = &htlc.state { - Some(InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info.clone())) - } else { None }; + let new_state = + if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(ref forward_info) = + &htlc.state + { + Some(InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info.clone())) + } else { + None + }; if let Some(state) = new_state { log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to AwaitingAnnouncedRemoteRevoke", &htlc.payment_hash); htlc.state = state; } } for htlc in self.context.pending_outbound_htlcs.iter_mut() { - if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state { + if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = + &mut htlc.state + { log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash); // Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)` let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])); @@ -9048,8 +11188,12 @@ impl FundedChannel where for funding in core::iter::once(&self.funding).chain(self.pending_funding.iter()) { let (htlcs_ref, counterparty_commitment_tx) = self.build_commitment_no_state_update(funding, logger); - let htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)> = - htlcs_ref.into_iter().map(|(htlc, htlc_source)| (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone())))).collect(); + let htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)> = htlcs_ref + .into_iter() + .map(|(htlc, htlc_source)| { + (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone()))) + }) + .collect(); if self.pending_funding.is_empty() { // Soon, we will switch this to `LatestCounterpartyCommitmentTX`, @@ -9058,10 +11202,17 @@ impl FundedChannel where commitment_txid: counterparty_commitment_tx.trust().txid(), htlc_outputs, commitment_number: self.context.cur_counterparty_commitment_transaction_number, - their_per_commitment_point: self.context.counterparty_cur_commitment_point.unwrap(), + their_per_commitment_point: self + .context + .counterparty_cur_commitment_point + .unwrap(), feerate_per_kw: Some(counterparty_commitment_tx.feerate_per_kw()), - to_broadcaster_value_sat: Some(counterparty_commitment_tx.to_broadcaster_value_sat()), - to_countersignatory_value_sat: Some(counterparty_commitment_tx.to_countersignatory_value_sat()), + to_broadcaster_value_sat: Some( + counterparty_commitment_tx.to_broadcaster_value_sat(), + ), + to_countersignatory_value_sat: Some( + counterparty_commitment_tx.to_countersignatory_value_sat(), + ), }); } else { updates.push(ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { @@ -9092,25 +11243,36 @@ impl FundedChannel where L::Target: Logger, { let commitment_data = self.context.build_commitment_transaction( - funding, self.context.cur_counterparty_commitment_transaction_number, - &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger, + funding, + self.context.cur_counterparty_commitment_transaction_number, + &self.context.counterparty_cur_commitment_point.unwrap(), + false, + true, + logger, ); let counterparty_commitment_tx = commitment_data.tx; #[cfg(any(test, fuzzing))] { if !funding.is_outbound() { - let projected_commit_tx_info = funding.next_remote_commitment_tx_fee_info_cached.lock().unwrap().take(); + let projected_commit_tx_info = + funding.next_remote_commitment_tx_fee_info_cached.lock().unwrap().take(); *funding.next_local_commitment_tx_fee_info_cached.lock().unwrap() = None; if let Some(info) = projected_commit_tx_info { - let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len(); + let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + + self.context.pending_outbound_htlcs.len(); if info.total_pending_htlcs == total_pending_htlcs && info.next_holder_htlc_id == self.context.next_holder_htlc_id && info.next_counterparty_htlc_id == self.context.next_counterparty_htlc_id - && info.feerate == self.context.feerate_per_kw { - let actual_fee = commit_tx_fee_sat(self.context.feerate_per_kw, counterparty_commitment_tx.nondust_htlcs().len(), self.funding.get_channel_type()) * 1000; - assert_eq!(actual_fee, info.fee); - } + && info.feerate == self.context.feerate_per_kw + { + let actual_fee = commit_tx_fee_sat( + self.context.feerate_per_kw, + counterparty_commitment_tx.nondust_htlcs().len(), + self.funding.get_channel_type(), + ) * 1000; + assert_eq!(actual_fee, info.fee); + } } } } @@ -9143,8 +11305,12 @@ impl FundedChannel where self.build_commitment_no_state_update(funding, logger); let commitment_data = self.context.build_commitment_transaction( - funding, self.context.cur_counterparty_commitment_transaction_number, - &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger, + funding, + self.context.cur_counterparty_commitment_transaction_number, + &self.context.counterparty_cur_commitment_point.unwrap(), + false, + true, + logger, ); let counterparty_commitment_tx = commitment_data.tx; @@ -9153,13 +11319,19 @@ impl FundedChannel where let (signature, htlc_signatures); { - let res = ecdsa.sign_counterparty_commitment( + let res = ecdsa + .sign_counterparty_commitment( &funding.channel_transaction_parameters, &counterparty_commitment_tx, commitment_data.inbound_htlc_preimages, commitment_data.outbound_htlc_preimages, &self.context.secp_ctx, - ).map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?; + ) + .map_err(|_| { + ChannelError::Ignore( + "Failed to get signatures for new commitment_signed".to_owned(), + ) + })?; signature = res.0; htlc_signatures = res.1; @@ -9171,7 +11343,9 @@ impl FundedChannel where let counterparty_keys = trusted_tx.keys(); debug_assert_eq!(htlc_signatures.len(), trusted_tx.nondust_htlcs().len()); - for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(trusted_tx.nondust_htlcs()) { + for (ref htlc_sig, ref htlc) in + htlc_signatures.iter().zip(trusted_tx.nondust_htlcs()) + { log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}", encode::serialize_hex(&chan_utils::build_htlc_transaction(&trusted_tx.txid(), trusted_tx.feerate_per_kw(), funding.get_holder_selected_contest_delay(), htlc, funding.get_channel_type(), &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)), encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, funding.get_channel_type(), &counterparty_keys)), @@ -9180,7 +11354,9 @@ impl FundedChannel where } } - let batch = if self.pending_funding.is_empty() { None } else { + let batch = if self.pending_funding.is_empty() { + None + } else { Some(msgs::CommitmentSignedBatch { batch_size: self.pending_funding.len() as u16 + 1, funding_txid: funding @@ -9200,7 +11376,7 @@ impl FundedChannel where }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), } } @@ -9212,20 +11388,39 @@ impl FundedChannel where pub fn send_htlc_and_commit( &mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option, - fee_estimator: &LowerBoundedFeeEstimator, logger: &L + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Result, ChannelError> - where F::Target: FeeEstimator, L::Target: Logger + where + F::Target: FeeEstimator, + L::Target: Logger, { - let send_res = self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, - onion_routing_packet, false, skimmed_fee_msat, None, fee_estimator, logger); + let send_res = self.send_htlc( + amount_msat, + payment_hash, + cltv_expiry, + source, + onion_routing_packet, + false, + skimmed_fee_msat, + None, + fee_estimator, + logger, + ); // All [`LocalHTLCFailureReason`] errors are temporary, so they are [`ChannelError::Ignore`]. match send_res.map_err(|(_, msg)| ChannelError::Ignore(msg))? { Some(_) => { let monitor_update = self.build_commitment_no_status_check(logger); - self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new()); + self.monitor_updating_paused( + false, + true, + false, + Vec::new(), + Vec::new(), + Vec::new(), + ); Ok(self.push_ret_blockable_mon_update(monitor_update)) }, - None => Ok(None) + None => Ok(None), } } @@ -9235,7 +11430,7 @@ impl FundedChannel where let new_forwarding_info = Some(CounterpartyForwardingInfo { fee_base_msat: msg.contents.fee_base_msat, fee_proportional_millionths: msg.contents.fee_proportional_millionths, - cltv_expiry_delta: msg.contents.cltv_expiry_delta + cltv_expiry_delta: msg.contents.cltv_expiry_delta, }); let did_change = self.context.counterparty_forwarding_info != new_forwarding_info; if did_change { @@ -9247,32 +11442,48 @@ impl FundedChannel where /// Begins the shutdown process, getting a message for the remote peer and returning all /// holding cell HTLCs for payment failure. - pub fn get_shutdown(&mut self, signer_provider: &SP, their_features: &InitFeatures, - target_feerate_sats_per_kw: Option, override_shutdown_script: Option) - -> Result<(msgs::Shutdown, Option, Vec<(HTLCSource, PaymentHash)>), APIError> - { + pub fn get_shutdown( + &mut self, signer_provider: &SP, their_features: &InitFeatures, + target_feerate_sats_per_kw: Option, override_shutdown_script: Option, + ) -> Result< + (msgs::Shutdown, Option, Vec<(HTLCSource, PaymentHash)>), + APIError, + > { if self.context.channel_state.is_local_stfu_sent() || self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() { - return Err(APIError::APIMisuseError { err: "Cannot begin shutdown while quiescent".to_owned() }); + return Err(APIError::APIMisuseError { + err: "Cannot begin shutdown while quiescent".to_owned(), + }); } for htlc in self.context.pending_outbound_htlcs.iter() { if let OutboundHTLCState::LocalAnnounced(_) = htlc.state { - return Err(APIError::APIMisuseError{err: "Cannot begin shutdown with pending HTLCs. Process pending events first".to_owned()}); + return Err(APIError::APIMisuseError { + err: "Cannot begin shutdown with pending HTLCs. Process pending events first" + .to_owned(), + }); } } if self.context.channel_state.is_local_shutdown_sent() { - return Err(APIError::APIMisuseError{err: "Shutdown already in progress".to_owned()}); - } - else if self.context.channel_state.is_remote_shutdown_sent() { - return Err(APIError::ChannelUnavailable{err: "Shutdown already in progress by remote".to_owned()}); + return Err(APIError::APIMisuseError { + err: "Shutdown already in progress".to_owned(), + }); + } else if self.context.channel_state.is_remote_shutdown_sent() { + return Err(APIError::ChannelUnavailable { + err: "Shutdown already in progress by remote".to_owned(), + }); } if self.context.shutdown_scriptpubkey.is_some() && override_shutdown_script.is_some() { - return Err(APIError::APIMisuseError{err: "Cannot override shutdown script for a channel with one already set".to_owned()}); + return Err(APIError::APIMisuseError { + err: "Cannot override shutdown script for a channel with one already set" + .to_owned(), + }); } assert!(!matches!(self.context.channel_state, ChannelState::ShutdownComplete)); - if self.context.channel_state.is_peer_disconnected() || self.context.channel_state.is_monitor_update_in_progress() { + if self.context.channel_state.is_peer_disconnected() + || self.context.channel_state.is_monitor_update_in_progress() + { return Err(APIError::ChannelUnavailable{err: "Cannot begin shutdown while peer is disconnected or we're waiting on a monitor update, maybe force-close instead?".to_owned()}); } @@ -9286,12 +11497,18 @@ impl FundedChannel where // otherwise, use the shutdown scriptpubkey provided by the signer match signer_provider.get_shutdown_scriptpubkey() { Ok(scriptpubkey) => scriptpubkey, - Err(_) => return Err(APIError::ChannelUnavailable{err: "Failed to get shutdown scriptpubkey".to_owned()}), + Err(_) => { + return Err(APIError::ChannelUnavailable { + err: "Failed to get shutdown scriptpubkey".to_owned(), + }) + }, } }, }; if !shutdown_scriptpubkey.is_compatible(their_features) { - return Err(APIError::IncompatibleShutdownScript { script: shutdown_scriptpubkey.clone() }); + return Err(APIError::IncompatibleShutdownScript { + script: shutdown_scriptpubkey.clone(), + }); } self.context.shutdown_scriptpubkey = Some(shutdown_scriptpubkey); true @@ -9318,7 +11535,9 @@ impl FundedChannel where }; self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new()); self.push_ret_blockable_mon_update(monitor_update) - } else { None }; + } else { + None + }; let shutdown = msgs::Shutdown { channel_id: self.context.channel_id, scriptpubkey: self.get_closing_scriptpubkey(), @@ -9327,35 +11546,42 @@ impl FundedChannel where // Go ahead and drop holding cell updates as we'd rather fail payments than wait to send // our shutdown until we've committed all of the pending changes. self.context.holding_cell_update_fee = None; - let mut dropped_outbound_htlcs = Vec::with_capacity(self.context.holding_cell_htlc_updates.len()); - self.context.holding_cell_htlc_updates.retain(|htlc_update| { - match htlc_update { - &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, .. } => { - dropped_outbound_htlcs.push((source.clone(), payment_hash.clone())); - false - }, - _ => true - } + let mut dropped_outbound_htlcs = + Vec::with_capacity(self.context.holding_cell_htlc_updates.len()); + self.context.holding_cell_htlc_updates.retain(|htlc_update| match htlc_update { + &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, .. } => { + dropped_outbound_htlcs.push((source.clone(), payment_hash.clone())); + false + }, + _ => true, }); - debug_assert!(!self.is_shutdown() || monitor_update.is_none(), - "we can't both complete shutdown and return a monitor update"); + debug_assert!( + !self.is_shutdown() || monitor_update.is_none(), + "we can't both complete shutdown and return a monitor update" + ); Ok((shutdown, monitor_update, dropped_outbound_htlcs)) } // Miscellaneous utilities - pub fn inflight_htlc_sources(&self) -> impl Iterator { - self.context.holding_cell_htlc_updates.iter() - .flat_map(|htlc_update| { - match htlc_update { - HTLCUpdateAwaitingACK::AddHTLC { source, payment_hash, .. } - => Some((source, payment_hash)), - _ => None, - } + pub fn inflight_htlc_sources(&self) -> impl Iterator { + self.context + .holding_cell_htlc_updates + .iter() + .flat_map(|htlc_update| match htlc_update { + HTLCUpdateAwaitingACK::AddHTLC { source, payment_hash, .. } => { + Some((source, payment_hash)) + }, + _ => None, }) - .chain(self.context.pending_outbound_htlcs.iter().map(|htlc| (&htlc.source, &htlc.payment_hash))) + .chain( + self.context + .pending_outbound_htlcs + .iter() + .map(|htlc| (&htlc.source, &htlc.payment_hash)), + ) } pub fn get_announced_htlc_max_msat(&self) -> u64 { @@ -9364,8 +11590,7 @@ impl FundedChannel where // to use full capacity. This is an effort to reduce routing failures, because in many cases // channel might have been used to route very small values (either by honest users or as DoS). self.funding.get_value_satoshis() * 1000 * 9 / 10, - - self.context.counterparty_max_htlc_value_in_flight_msat + self.context.counterparty_max_htlc_value_in_flight_msat, ); } @@ -9380,7 +11605,7 @@ impl FundedChannel where if !self.context.is_live() { return Err(ChannelError::Ignore( - "Channel is not in a live state to propose quiescence".to_owned() + "Channel is not in a live state to propose quiescence".to_owned(), )); } if self.context.channel_state.is_quiescent() { @@ -9414,7 +11639,7 @@ impl FundedChannel where || self.context.is_monitor_or_signer_pending_channel_update() { return Err(ChannelError::Ignore( - "We cannot send `stfu` while state machine is pending".to_owned() + "We cannot send `stfu` while state machine is pending".to_owned(), )); } @@ -9432,7 +11657,10 @@ impl FundedChannel where *initiator } else { - debug_assert!(false, "Quiescence initiator must have been set when we received stfu"); + debug_assert!( + false, + "Quiescence initiator must have been set when we received stfu" + ); false } } else { @@ -9447,20 +11675,24 @@ impl FundedChannel where } pub fn stfu( - &mut self, msg: &msgs::Stfu, logger: &L - ) -> Result, ChannelError> where L::Target: Logger { + &mut self, msg: &msgs::Stfu, logger: &L, + ) -> Result, ChannelError> + where + L::Target: Logger, + { if self.context.channel_state.is_quiescent() { return Err(ChannelError::Warn("Channel is already quiescent".to_owned())); } if self.context.channel_state.is_remote_stfu_sent() { return Err(ChannelError::Warn( - "Peer sent `stfu` when they already sent it and we've yet to become quiescent".to_owned() + "Peer sent `stfu` when they already sent it and we've yet to become quiescent" + .to_owned(), )); } if !self.context.is_live() { return Err(ChannelError::Warn( - "Peer sent `stfu` when we were not in a live state".to_owned() + "Peer sent `stfu` when we were not in a live state".to_owned(), )); } @@ -9469,7 +11701,7 @@ impl FundedChannel where { if !msg.initiator { return Err(ChannelError::WarnAndDisconnect( - "Peer sent unexpected `stfu` without signaling as initiator".to_owned() + "Peer sent unexpected `stfu` without signaling as initiator".to_owned(), )); } @@ -9507,7 +11739,7 @@ impl FundedChannel where // Since we've already sent `stfu`, it should not be possible for one of our updates to // be pending, so anything pending currently must be from a counterparty update. return Err(ChannelError::WarnAndDisconnect( - "Received counterparty stfu while having pending counterparty updates".to_owned() + "Received counterparty stfu while having pending counterparty updates".to_owned(), )); } @@ -9562,7 +11794,10 @@ impl FundedChannel where if self.context.channel_state.is_quiescent() { self.mark_response_received(); self.context.channel_state.clear_quiescent(); - self.context.is_holder_quiescence_initiator.take().expect("Must always be set while quiescent") + self.context + .is_holder_quiescence_initiator + .take() + .expect("Must always be set while quiescent") } else { false } @@ -9574,7 +11809,10 @@ impl FundedChannel where } /// A not-yet-funded outbound (from holder) channel using V1 channel establishment. -pub(super) struct OutboundV1Channel where SP::Target: SignerProvider { +pub(super) struct OutboundV1Channel +where + SP::Target: SignerProvider, +{ pub funding: FundingScope, pub context: ChannelContext, pub unfunded_context: UnfundedChannelContext, @@ -9584,31 +11822,42 @@ pub(super) struct OutboundV1Channel where SP::Target: SignerProvider pub signer_pending_open_channel: bool, } -impl OutboundV1Channel where SP::Target: SignerProvider { +impl OutboundV1Channel +where + SP::Target: SignerProvider, +{ #[allow(dead_code)] // TODO(dual_funding): Remove once opending V2 channels is enabled. pub fn new( - fee_estimator: &LowerBoundedFeeEstimator, entropy_source: &ES, signer_provider: &SP, counterparty_node_id: PublicKey, their_features: &InitFeatures, - channel_value_satoshis: u64, push_msat: u64, user_id: u128, config: &UserConfig, current_chain_height: u32, - outbound_scid_alias: u64, temporary_channel_id: Option, logger: L + fee_estimator: &LowerBoundedFeeEstimator, entropy_source: &ES, signer_provider: &SP, + counterparty_node_id: PublicKey, their_features: &InitFeatures, + channel_value_satoshis: u64, push_msat: u64, user_id: u128, config: &UserConfig, + current_chain_height: u32, outbound_scid_alias: u64, + temporary_channel_id: Option, logger: L, ) -> Result, APIError> - where ES::Target: EntropySource, - F::Target: FeeEstimator, - L::Target: Logger, + where + ES::Target: EntropySource, + F::Target: FeeEstimator, + L::Target: Logger, { - let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config); + let holder_selected_channel_reserve_satoshis = + get_holder_selected_channel_reserve_satoshis(channel_value_satoshis, config); if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { // Protocol level safety check in place, although it should never happen because // of `MIN_THEIR_CHAN_RESERVE_SATOSHIS` - return Err(APIError::APIMisuseError { err: format!("Holder selected channel reserve below \ - implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) }); + return Err(APIError::APIMisuseError { + err: format!( + "Holder selected channel reserve below \ + implemention limit dust_limit_satoshis {}", + holder_selected_channel_reserve_satoshis + ), + }); } let channel_keys_id = signer_provider.generate_channel_keys_id(false, user_id); let holder_signer = signer_provider.derive_channel_signer(channel_keys_id); - let temporary_channel_id_fn = temporary_channel_id.map(|id| { - move |_: &ChannelPublicKeys| id - }); + let temporary_channel_id_fn = + temporary_channel_id.map(|id| move |_: &ChannelPublicKeys| id); let (funding, context) = ChannelContext::new_for_outbound_channel( fee_estimator, @@ -9630,7 +11879,10 @@ impl OutboundV1Channel where SP::Target: SignerProvider { )?; let unfunded_context = UnfundedChannelContext { unfunded_channel_age_ticks: 0, - holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx), + holder_commitment_point: HolderCommitmentPoint::new( + &context.holder_signer, + &context.secp_ctx, + ), }; // We initialize `signer_pending_open_channel` to false, and leave setting the flag @@ -9640,21 +11892,37 @@ impl OutboundV1Channel where SP::Target: SignerProvider { } /// Only allowed after [`FundingScope::channel_transaction_parameters`] is set. - fn get_funding_created_msg(&mut self, logger: &L) -> Option where L::Target: Logger { - let commitment_data = self.context.build_commitment_transaction(&self.funding, + fn get_funding_created_msg(&mut self, logger: &L) -> Option + where + L::Target: Logger, + { + let commitment_data = self.context.build_commitment_transaction( + &self.funding, self.context.cur_counterparty_commitment_transaction_number, - &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger); + &self.context.counterparty_cur_commitment_point.unwrap(), + false, + false, + logger, + ); let counterparty_initial_commitment_tx = commitment_data.tx; let signature = match &self.context.holder_signer { // TODO (taproot|arik): move match into calling method for Taproot ChannelSignerType::Ecdsa(ecdsa) => { let channel_parameters = &self.funding.channel_transaction_parameters; - ecdsa.sign_counterparty_commitment(channel_parameters, &counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.context.secp_ctx) - .map(|(sig, _)| sig).ok() + ecdsa + .sign_counterparty_commitment( + channel_parameters, + &counterparty_initial_commitment_tx, + Vec::new(), + Vec::new(), + &self.context.secp_ctx, + ) + .map(|(sig, _)| sig) + .ok() }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), }; if signature.is_some() && self.context.signer_pending_funding { @@ -9667,8 +11935,20 @@ impl OutboundV1Channel where SP::Target: SignerProvider { signature.map(|signature| msgs::FundingCreated { temporary_channel_id: self.context.temporary_channel_id.unwrap(), - funding_txid: self.funding.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().txid, - funding_output_index: self.funding.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().index, + funding_txid: self + .funding + .channel_transaction_parameters + .funding_outpoint + .as_ref() + .unwrap() + .txid, + funding_output_index: self + .funding + .channel_transaction_parameters + .funding_outpoint + .as_ref() + .unwrap() + .index, signature, #[cfg(taproot)] partial_signature_with_nonce: None, @@ -9684,8 +11964,13 @@ impl OutboundV1Channel where SP::Target: SignerProvider { /// Note that channel_id changes during this call! /// Do NOT broadcast the funding transaction until after a successful funding_signed call! /// If an Err is returned, it is a ChannelError::Close. - pub fn get_funding_created(&mut self, funding_transaction: Transaction, funding_txo: OutPoint, is_batch_funding: bool, logger: &L) - -> Result, (Self, ChannelError)> where L::Target: Logger { + pub fn get_funding_created( + &mut self, funding_transaction: Transaction, funding_txo: OutPoint, is_batch_funding: bool, + logger: &L, + ) -> Result, (Self, ChannelError)> + where + L::Target: Logger, + { if !self.funding.is_outbound() { panic!("Tried to create outbound funding_created message on an inbound channel!"); } @@ -9695,7 +11980,10 @@ impl OutboundV1Channel where SP::Target: SignerProvider { ) { panic!("Tried to get a funding_created messsage at a time other than immediately after initial handshake completion (or tried to get funding_created twice)"); } - self.context.assert_no_commitment_advancement(self.unfunded_context.transaction_number(), "funding_created"); + self.context.assert_no_commitment_advancement( + self.unfunded_context.transaction_number(), + "funding_created", + ); self.funding.channel_transaction_parameters.funding_outpoint = Some(funding_txo); @@ -9706,9 +11994,10 @@ impl OutboundV1Channel where SP::Target: SignerProvider { // If the funding transaction is a coinbase transaction, we need to set the minimum depth to 100. // We can skip this if it is a zero-conf channel. - if funding_transaction.is_coinbase() && - self.context.minimum_depth.unwrap_or(0) > 0 && - self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY { + if funding_transaction.is_coinbase() + && self.context.minimum_depth.unwrap_or(0) > 0 + && self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY + { self.context.minimum_depth = Some(COINBASE_MATURITY); } @@ -9724,7 +12013,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { /// not of our ability to open any channel at all. Thus, on error, we should first call this /// and see if we get a new `OpenChannel` message, otherwise the channel is failed. pub(crate) fn maybe_handle_error_without_close( - &mut self, chain_hash: ChainHash, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + &mut self, chain_hash: ChainHash, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Result where F::Target: FeeEstimator, @@ -9736,13 +12025,16 @@ impl OutboundV1Channel where SP::Target: SignerProvider { /// Returns true if we can resume the channel by sending the [`msgs::OpenChannel`] again. pub fn is_resumable(&self) -> bool { - !self.context.have_received_message() && - self.unfunded_context.transaction_number() == INITIAL_COMMITMENT_NUMBER + !self.context.have_received_message() + && self.unfunded_context.transaction_number() == INITIAL_COMMITMENT_NUMBER } pub fn get_open_channel( - &mut self, chain_hash: ChainHash, _logger: &L - ) -> Option where L::Target: Logger { + &mut self, chain_hash: ChainHash, _logger: &L, + ) -> Option + where + L::Target: Logger, + { if !self.funding.is_outbound() { panic!("Tried to open a channel for an inbound channel?"); } @@ -9760,10 +12052,13 @@ impl OutboundV1Channel where SP::Target: SignerProvider { holder_commitment_point.current_point() }, _ => { - log_trace!(_logger, "Unable to generate open_channel message, waiting for commitment point"); + log_trace!( + _logger, + "Unable to generate open_channel message, waiting for commitment point" + ); self.signer_pending_open_channel = true; return None; - } + }, }; let keys = self.funding.get_holder_pubkeys(); @@ -9784,7 +12079,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(), htlc_basepoint: keys.htlc_basepoint.to_public_key(), first_per_commitment_point, - channel_flags: if self.context.config.announce_for_forwarding {1} else {0}, + channel_flags: if self.context.config.announce_for_forwarding { 1 } else { 0 }, shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey { Some(script) => script.clone().into_inner(), None => Builder::new().into_script(), @@ -9799,10 +12094,13 @@ impl OutboundV1Channel where SP::Target: SignerProvider { // Message handlers pub fn accept_channel( &mut self, msg: &msgs::AcceptChannel, default_limits: &ChannelHandshakeLimits, - their_features: &InitFeatures + their_features: &InitFeatures, ) -> Result<(), ChannelError> { self.context.do_accept_channel_checks( - &mut self.funding, default_limits, their_features, &msg.common_fields, + &mut self.funding, + default_limits, + their_features, + &msg.common_fields, msg.channel_reserve_satoshis, ) } @@ -9810,32 +12108,60 @@ impl OutboundV1Channel where SP::Target: SignerProvider { /// Handles a funding_signed message from the remote end. /// If this call is successful, broadcast the funding transaction (and not before!) pub fn funding_signed( - mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result<(FundedChannel, ChannelMonitor<::EcdsaSigner>), (OutboundV1Channel, ChannelError)> + mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, + logger: &L, + ) -> Result< + (FundedChannel, ChannelMonitor<::EcdsaSigner>), + (OutboundV1Channel, ChannelError), + > where - L::Target: Logger + L::Target: Logger, { if !self.funding.is_outbound() { - return Err((self, ChannelError::close("Received funding_signed for an inbound channel?".to_owned()))); + return Err(( + self, + ChannelError::close("Received funding_signed for an inbound channel?".to_owned()), + )); } if !matches!(self.context.channel_state, ChannelState::FundingNegotiated) { - return Err((self, ChannelError::close("Received funding_signed in strange state!".to_owned()))); + return Err(( + self, + ChannelError::close("Received funding_signed in strange state!".to_owned()), + )); } - let mut holder_commitment_point = match self.unfunded_context.holder_commitment_point { - Some(point) => point, - None => return Err((self, ChannelError::close("Received funding_signed before our first commitment point was available".to_owned()))), - }; - self.context.assert_no_commitment_advancement(holder_commitment_point.transaction_number(), "funding_signed"); + let mut holder_commitment_point = + match self.unfunded_context.holder_commitment_point { + Some(point) => point, + None => return Err(( + self, + ChannelError::close( + "Received funding_signed before our first commitment point was available" + .to_owned(), + ), + )), + }; + self.context.assert_no_commitment_advancement( + holder_commitment_point.transaction_number(), + "funding_signed", + ); let (channel_monitor, _) = match self.initial_commitment_signed( - self.context.channel_id(), msg.signature, - &mut holder_commitment_point, best_block, signer_provider, logger + self.context.channel_id(), + msg.signature, + &mut holder_commitment_point, + best_block, + signer_provider, + logger, ) { Ok(channel_monitor) => channel_monitor, Err(err) => return Err((self, err)), }; - log_info!(logger, "Received funding_signed from peer for channel {}", &self.context.channel_id()); + log_info!( + logger, + "Received funding_signed from peer for channel {}", + &self.context.channel_id() + ); let mut channel = FundedChannel { funding: self.funding, @@ -9850,33 +12176,52 @@ impl OutboundV1Channel where SP::Target: SignerProvider { let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some() || channel.context.signer_pending_channel_ready; - channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new()); + channel.monitor_updating_paused( + false, + false, + need_channel_ready, + Vec::new(), + Vec::new(), + Vec::new(), + ); Ok((channel, channel_monitor)) } /// Indicates that the signer may have some signatures for us, so we should retry if we're /// blocked. pub fn signer_maybe_unblocked( - &mut self, chain_hash: ChainHash, logger: &L - ) -> (Option, Option) where L::Target: Logger { + &mut self, chain_hash: ChainHash, logger: &L, + ) -> (Option, Option) + where + L::Target: Logger, + { // If we were pending a commitment point, retry the signer and advance to an // available state. if self.unfunded_context.holder_commitment_point.is_none() { - self.unfunded_context.holder_commitment_point = HolderCommitmentPoint::new(&self.context.holder_signer, &self.context.secp_ctx); + self.unfunded_context.holder_commitment_point = + HolderCommitmentPoint::new(&self.context.holder_signer, &self.context.secp_ctx); } if let Some(ref mut point) = self.unfunded_context.holder_commitment_point { if !point.is_available() { - point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger); + point.try_resolve_pending( + &self.context.holder_signer, + &self.context.secp_ctx, + logger, + ); } } let open_channel = if self.signer_pending_open_channel { log_trace!(logger, "Attempting to generate open_channel..."); self.get_open_channel(chain_hash, logger) - } else { None }; + } else { + None + }; let funding_created = if self.context.signer_pending_funding && self.funding.is_outbound() { log_trace!(logger, "Attempting to generate pending funding created..."); self.get_funding_created_msg(logger) - } else { None }; + } else { + None + }; (open_channel, funding_created) } @@ -9890,7 +12235,10 @@ impl OutboundV1Channel where SP::Target: SignerProvider { } /// A not-yet-funded inbound (from counterparty) channel using V1 channel establishment. -pub(super) struct InboundV1Channel where SP::Target: SignerProvider { +pub(super) struct InboundV1Channel +where + SP::Target: SignerProvider, +{ pub funding: FundingScope, pub context: ChannelContext, pub unfunded_context: UnfundedChannelContext, @@ -9901,38 +12249,52 @@ pub(super) struct InboundV1Channel where SP::Target: SignerProvider { /// [`msgs::CommonOpenChannelFields`]. pub(super) fn channel_type_from_open_channel( common_fields: &msgs::CommonOpenChannelFields, their_features: &InitFeatures, - our_supported_features: &ChannelTypeFeatures + our_supported_features: &ChannelTypeFeatures, ) -> Result { if let Some(channel_type) = &common_fields.channel_type { if channel_type.supports_any_optional_bits() { - return Err(ChannelError::close("Channel Type field contained optional bits - this is not allowed".to_owned())); + return Err(ChannelError::close( + "Channel Type field contained optional bits - this is not allowed".to_owned(), + )); } // We only support the channel types defined by the `ChannelManager` in // `provided_channel_type_features`. The channel type must always support // `static_remote_key`. if !channel_type.requires_static_remote_key() { - return Err(ChannelError::close("Channel Type was not understood - we require static remote key".to_owned())); + return Err(ChannelError::close( + "Channel Type was not understood - we require static remote key".to_owned(), + )); } // Make sure we support all of the features behind the channel type. if channel_type.requires_unknown_bits_from(&our_supported_features) { - return Err(ChannelError::close("Channel Type contains unsupported features".to_owned())); + return Err(ChannelError::close( + "Channel Type contains unsupported features".to_owned(), + )); } - let announce_for_forwarding = if (common_fields.channel_flags & 1) == 1 { true } else { false }; + let announce_for_forwarding = + if (common_fields.channel_flags & 1) == 1 { true } else { false }; if channel_type.requires_scid_privacy() && announce_for_forwarding { - return Err(ChannelError::close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned())); + return Err(ChannelError::close( + "SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned(), + )); } Ok(channel_type.clone()) } else { let channel_type = ChannelTypeFeatures::from_init(&their_features); if channel_type != ChannelTypeFeatures::only_static_remote_key() { - return Err(ChannelError::close("Only static_remote_key is supported for non-negotiated channel types".to_owned())); + return Err(ChannelError::close( + "Only static_remote_key is supported for non-negotiated channel types".to_owned(), + )); } Ok(channel_type) } } -impl InboundV1Channel where SP::Target: SignerProvider { +impl InboundV1Channel +where + SP::Target: SignerProvider, +{ /// Creates a new channel from a remote sides' request for one. /// Assumes chain_hash has already been checked and corresponds with what we expect! pub fn new( @@ -9941,23 +12303,38 @@ impl InboundV1Channel where SP::Target: SignerProvider { their_features: &InitFeatures, msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L, is_0conf: bool, ) -> Result, ChannelError> - where ES::Target: EntropySource, - F::Target: FeeEstimator, - L::Target: Logger, + where + ES::Target: EntropySource, + F::Target: FeeEstimator, + L::Target: Logger, { - let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.common_fields.temporary_channel_id), None); + let logger = WithContext::from( + logger, + Some(counterparty_node_id), + Some(msg.common_fields.temporary_channel_id), + None, + ); // First check the channel type is known, failing before we do anything else if we don't // support this channel type. - let channel_type = channel_type_from_open_channel(&msg.common_fields, their_features, our_supported_features)?; + let channel_type = channel_type_from_open_channel( + &msg.common_fields, + their_features, + our_supported_features, + )?; - let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(msg.common_fields.funding_satoshis, config); + let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis( + msg.common_fields.funding_satoshis, + config, + ); let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: msg.common_fields.funding_pubkey, revocation_basepoint: RevocationBasepoint::from(msg.common_fields.revocation_basepoint), payment_point: msg.common_fields.payment_basepoint, - delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.common_fields.delayed_payment_basepoint), - htlc_basepoint: HtlcBasepoint::from(msg.common_fields.htlc_basepoint) + delayed_payment_basepoint: DelayedPaymentBasepoint::from( + msg.common_fields.delayed_payment_basepoint, + ), + htlc_basepoint: HtlcBasepoint::from(msg.common_fields.htlc_basepoint), }; let (funding, context) = ChannelContext::new_for_inbound_channel( @@ -9972,7 +12349,6 @@ impl InboundV1Channel where SP::Target: SignerProvider { &&logger, is_0conf, 0, - counterparty_pubkeys, channel_type, holder_selected_channel_reserve_satoshis, @@ -9982,9 +12358,13 @@ impl InboundV1Channel where SP::Target: SignerProvider { )?; let unfunded_context = UnfundedChannelContext { unfunded_channel_age_ticks: 0, - holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx), + holder_commitment_point: HolderCommitmentPoint::new( + &context.holder_signer, + &context.secp_ctx, + ), }; - let chan = Self { funding, context, unfunded_context, signer_pending_accept_channel: false }; + let chan = + Self { funding, context, unfunded_context, signer_pending_accept_channel: false }; Ok(chan) } @@ -9992,9 +12372,10 @@ impl InboundV1Channel where SP::Target: SignerProvider { /// should be sent back to the counterparty node. /// /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel - pub fn accept_inbound_channel( - &mut self, logger: &L - ) -> Option where L::Target: Logger { + pub fn accept_inbound_channel(&mut self, logger: &L) -> Option + where + L::Target: Logger, + { if self.funding.is_outbound() { panic!("Tried to send accept_channel for an outbound channel?"); } @@ -10017,18 +12398,24 @@ impl InboundV1Channel where SP::Target: SignerProvider { /// /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel fn generate_accept_channel_message( - &mut self, _logger: &L - ) -> Option where L::Target: Logger { + &mut self, _logger: &L, + ) -> Option + where + L::Target: Logger, + { let first_per_commitment_point = match self.unfunded_context.holder_commitment_point { Some(holder_commitment_point) if holder_commitment_point.is_available() => { self.signer_pending_accept_channel = false; holder_commitment_point.current_point() }, _ => { - log_trace!(_logger, "Unable to generate accept_channel message, waiting for commitment point"); + log_trace!( + _logger, + "Unable to generate accept_channel message, waiting for commitment point" + ); self.signer_pending_accept_channel = true; return None; - } + }, }; let keys = self.funding.get_holder_pubkeys(); @@ -10065,19 +12452,33 @@ impl InboundV1Channel where SP::Target: SignerProvider { /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel #[cfg(test)] pub fn get_accept_channel_message( - &mut self, logger: &L - ) -> Option where L::Target: Logger { + &mut self, logger: &L, + ) -> Option + where + L::Target: Logger, + { self.generate_accept_channel_message(logger) } pub fn funding_created( - mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result<(FundedChannel, Option, ChannelMonitor<::EcdsaSigner>), (Self, ChannelError)> + mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, + logger: &L, + ) -> Result< + ( + FundedChannel, + Option, + ChannelMonitor<::EcdsaSigner>, + ), + (Self, ChannelError), + > where - L::Target: Logger + L::Target: Logger, { if self.funding.is_outbound() { - return Err((self, ChannelError::close("Received funding_created for an outbound channel?".to_owned()))); + return Err(( + self, + ChannelError::close("Received funding_created for an outbound channel?".to_owned()), + )); } if !matches!( self.context.channel_state, ChannelState::NegotiatingFunding(flags) @@ -10086,31 +12487,57 @@ impl InboundV1Channel where SP::Target: SignerProvider { // BOLT 2 says that if we disconnect before we send funding_signed we SHOULD NOT // remember the channel, so it's safe to just send an error_message here and drop the // channel. - return Err((self, ChannelError::close("Received funding_created after we got the channel!".to_owned()))); + return Err(( + self, + ChannelError::close( + "Received funding_created after we got the channel!".to_owned(), + ), + )); } - let mut holder_commitment_point = match self.unfunded_context.holder_commitment_point { - Some(point) => point, - None => return Err((self, ChannelError::close("Received funding_created before our first commitment point was available".to_owned()))), - }; - self.context.assert_no_commitment_advancement(holder_commitment_point.transaction_number(), "funding_created"); + let mut holder_commitment_point = + match self.unfunded_context.holder_commitment_point { + Some(point) => point, + None => return Err(( + self, + ChannelError::close( + "Received funding_created before our first commitment point was available" + .to_owned(), + ), + )), + }; + self.context.assert_no_commitment_advancement( + holder_commitment_point.transaction_number(), + "funding_created", + ); let funding_txo = OutPoint { txid: msg.funding_txid, index: msg.funding_output_index }; self.funding.channel_transaction_parameters.funding_outpoint = Some(funding_txo); - let (channel_monitor, counterparty_initial_commitment_tx) = match self.initial_commitment_signed( - ChannelId::v1_from_funding_outpoint(funding_txo), msg.signature, - &mut holder_commitment_point, best_block, signer_provider, logger - ) { + let (channel_monitor, counterparty_initial_commitment_tx) = match self + .initial_commitment_signed( + ChannelId::v1_from_funding_outpoint(funding_txo), + msg.signature, + &mut holder_commitment_point, + best_block, + signer_provider, + logger, + ) { Ok(channel_monitor) => channel_monitor, Err(err) => return Err((self, err)), }; let funding_signed = self.context.get_funding_signed_msg( - &self.funding.channel_transaction_parameters, logger, counterparty_initial_commitment_tx + &self.funding.channel_transaction_parameters, + logger, + counterparty_initial_commitment_tx, ); - log_info!(logger, "{} funding_signed for peer for channel {}", - if funding_signed.is_some() { "Generated" } else { "Waiting for signature on" }, &self.context.channel_id()); + log_info!( + logger, + "{} funding_signed for peer for channel {}", + if funding_signed.is_some() { "Generated" } else { "Waiting for signature on" }, + &self.context.channel_id() + ); // Promote the channel to a full-fledged one now that we have updated the state and have a // `ChannelMonitor`. @@ -10126,33 +12553,51 @@ impl InboundV1Channel where SP::Target: SignerProvider { }; let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some() || channel.context.signer_pending_channel_ready; - channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new()); + channel.monitor_updating_paused( + false, + false, + need_channel_ready, + Vec::new(), + Vec::new(), + Vec::new(), + ); Ok((channel, funding_signed, channel_monitor)) } /// Indicates that the signer may have some signatures for us, so we should retry if we're /// blocked. - pub fn signer_maybe_unblocked( - &mut self, logger: &L - ) -> Option where L::Target: Logger { + pub fn signer_maybe_unblocked(&mut self, logger: &L) -> Option + where + L::Target: Logger, + { if self.unfunded_context.holder_commitment_point.is_none() { - self.unfunded_context.holder_commitment_point = HolderCommitmentPoint::new(&self.context.holder_signer, &self.context.secp_ctx); + self.unfunded_context.holder_commitment_point = + HolderCommitmentPoint::new(&self.context.holder_signer, &self.context.secp_ctx); } if let Some(ref mut point) = self.unfunded_context.holder_commitment_point { if !point.is_available() { - point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger); + point.try_resolve_pending( + &self.context.holder_signer, + &self.context.secp_ctx, + logger, + ); } } if self.signer_pending_accept_channel { log_trace!(logger, "Attempting to generate accept_channel..."); self.generate_accept_channel_message(logger) - } else { None } + } else { + None + } } } // A not-yet-funded channel using V2 channel establishment. -pub(super) struct PendingV2Channel where SP::Target: SignerProvider { +pub(super) struct PendingV2Channel +where + SP::Target: SignerProvider, +{ pub funding: FundingScope, pub context: ChannelContext, pub unfunded_context: UnfundedChannelContext, @@ -10163,18 +12608,22 @@ pub(super) struct PendingV2Channel where SP::Target: SignerProvider { pub interactive_tx_signing_session: Option, } -impl PendingV2Channel where SP::Target: SignerProvider { +impl PendingV2Channel +where + SP::Target: SignerProvider, +{ #[allow(dead_code)] // TODO(dual_funding): Remove once creating V2 channels is enabled. pub fn new_outbound( fee_estimator: &LowerBoundedFeeEstimator, entropy_source: &ES, signer_provider: &SP, counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64, funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>, user_id: u128, config: &UserConfig, - current_chain_height: u32, outbound_scid_alias: u64, funding_confirmation_target: ConfirmationTarget, - logger: L, + current_chain_height: u32, outbound_scid_alias: u64, + funding_confirmation_target: ConfirmationTarget, logger: L, ) -> Result - where ES::Target: EntropySource, - F::Target: FeeEstimator, - L::Target: Logger, + where + ES::Target: EntropySource, + F::Target: FeeEstimator, + L::Target: Logger, { let channel_keys_id = signer_provider.generate_channel_keys_id(false, user_id); let holder_signer = signer_provider.derive_channel_signer(channel_keys_id); @@ -10183,10 +12632,11 @@ impl PendingV2Channel where SP::Target: SignerProvider { ChannelId::temporary_v2_from_revocation_basepoint(&pubkeys.revocation_basepoint) }); - let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis( - funding_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS); + let holder_selected_channel_reserve_satoshis = + get_v2_channel_reserve_satoshis(funding_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS); - let funding_feerate_sat_per_1000_weight = fee_estimator.bounded_sat_per_1000_weight(funding_confirmation_target); + let funding_feerate_sat_per_1000_weight = + fee_estimator.bounded_sat_per_1000_weight(funding_confirmation_target); let funding_tx_locktime = LockTime::from_height(current_chain_height) .map_err(|_| APIError::APIMisuseError { err: format!( @@ -10213,7 +12663,10 @@ impl PendingV2Channel where SP::Target: SignerProvider { )?; let unfunded_context = UnfundedChannelContext { unfunded_channel_age_ticks: 0, - holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx), + holder_commitment_point: HolderCommitmentPoint::new( + &context.holder_signer, + &context.secp_ctx, + ), }; let dual_funding_context = DualFundingChannelContext { our_funding_satoshis: funding_satoshis, @@ -10238,10 +12691,10 @@ impl PendingV2Channel where SP::Target: SignerProvider { /// not of our ability to open any channel at all. Thus, on error, we should first call this /// and see if we get a new `OpenChannelV2` message, otherwise the channel is failed. pub(crate) fn maybe_handle_error_without_close( - &mut self, chain_hash: ChainHash, fee_estimator: &LowerBoundedFeeEstimator + &mut self, chain_hash: ChainHash, fee_estimator: &LowerBoundedFeeEstimator, ) -> Result where - F::Target: FeeEstimator + F::Target: FeeEstimator, { self.context.maybe_downgrade_channel_features(&mut self.funding, fee_estimator)?; Ok(self.get_open_channel_v2(chain_hash)) @@ -10257,7 +12710,10 @@ impl PendingV2Channel where SP::Target: SignerProvider { } if self.unfunded_context.transaction_number() != INITIAL_COMMITMENT_NUMBER { - debug_assert!(false, "Tried to send an open_channel2 for a channel that has already advanced"); + debug_assert!( + false, + "Tried to send an open_channel2 for a channel that has already advanced" + ); } let first_per_commitment_point = self.context.holder_signer.as_ref() @@ -10287,7 +12743,7 @@ impl PendingV2Channel where SP::Target: SignerProvider { delayed_payment_basepoint: keys.delayed_payment_basepoint.to_public_key(), htlc_basepoint: keys.htlc_basepoint.to_public_key(), first_per_commitment_point, - channel_flags: if self.context.config.announce_for_forwarding {1} else {0}, + channel_flags: if self.context.config.announce_for_forwarding { 1 } else { 0 }, shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey { Some(script) => script.clone().into_inner(), None => Builder::new().into_script(), @@ -10307,38 +12763,51 @@ impl PendingV2Channel where SP::Target: SignerProvider { #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled. pub fn new_inbound( fee_estimator: &LowerBoundedFeeEstimator, entropy_source: &ES, signer_provider: &SP, - holder_node_id: PublicKey, counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures, - their_features: &InitFeatures, msg: &msgs::OpenChannelV2, - user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L, + holder_node_id: PublicKey, counterparty_node_id: PublicKey, + our_supported_features: &ChannelTypeFeatures, their_features: &InitFeatures, + msg: &msgs::OpenChannelV2, user_id: u128, config: &UserConfig, current_chain_height: u32, + logger: &L, ) -> Result - where ES::Target: EntropySource, - F::Target: FeeEstimator, - L::Target: Logger, + where + ES::Target: EntropySource, + F::Target: FeeEstimator, + L::Target: Logger, { // TODO(dual_funding): Take these as input once supported let our_funding_satoshis = 0u64; let our_funding_inputs = Vec::new(); - let channel_value_satoshis = our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis); + let channel_value_satoshis = + our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis); let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis( - channel_value_satoshis, msg.common_fields.dust_limit_satoshis); - let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis( - channel_value_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS); + channel_value_satoshis, + msg.common_fields.dust_limit_satoshis, + ); + let holder_selected_channel_reserve_satoshis = + get_v2_channel_reserve_satoshis(channel_value_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS); // First check the channel type is known, failing before we do anything else if we don't // support this channel type. if msg.common_fields.channel_type.is_none() { - return Err(ChannelError::close(format!("Rejecting V2 channel {} missing channel_type", - msg.common_fields.temporary_channel_id))) + return Err(ChannelError::close(format!( + "Rejecting V2 channel {} missing channel_type", + msg.common_fields.temporary_channel_id + ))); } - let channel_type = channel_type_from_open_channel(&msg.common_fields, their_features, our_supported_features)?; + let channel_type = channel_type_from_open_channel( + &msg.common_fields, + their_features, + our_supported_features, + )?; let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: msg.common_fields.funding_pubkey, revocation_basepoint: RevocationBasepoint(msg.common_fields.revocation_basepoint), payment_point: msg.common_fields.payment_basepoint, - delayed_payment_basepoint: DelayedPaymentBasepoint(msg.common_fields.delayed_payment_basepoint), - htlc_basepoint: HtlcBasepoint(msg.common_fields.htlc_basepoint) + delayed_payment_basepoint: DelayedPaymentBasepoint( + msg.common_fields.delayed_payment_basepoint, + ), + htlc_basepoint: HtlcBasepoint(msg.common_fields.htlc_basepoint), }; let (funding, mut context) = ChannelContext::new_for_inbound_channel( @@ -10352,31 +12821,30 @@ impl PendingV2Channel where SP::Target: SignerProvider { current_chain_height, logger, false, - our_funding_satoshis, - counterparty_pubkeys, channel_type, holder_selected_channel_reserve_satoshis, counterparty_selected_channel_reserve_satoshis, - 0 /* push_msat not used in dual-funding */, + 0, /* push_msat not used in dual-funding */ msg.common_fields.clone(), )?; let channel_id = ChannelId::v2_from_revocation_basepoints( &funding.get_holder_pubkeys().revocation_basepoint, - &funding.get_counterparty_pubkeys().revocation_basepoint); + &funding.get_counterparty_pubkeys().revocation_basepoint, + ); context.channel_id = channel_id; let dual_funding_context = DualFundingChannelContext { - our_funding_satoshis: our_funding_satoshis, + our_funding_satoshis, their_funding_satoshis: Some(msg.common_fields.funding_satoshis), funding_tx_locktime: LockTime::from_consensus(msg.locktime), funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight, our_funding_inputs: our_funding_inputs.clone(), }; - let interactive_tx_constructor = Some(InteractiveTxConstructor::new( - InteractiveTxConstructorArgs { + let interactive_tx_constructor = Some( + InteractiveTxConstructor::new(InteractiveTxConstructorArgs { entropy_source, holder_node_id, counterparty_node_id, @@ -10386,16 +12854,25 @@ impl PendingV2Channel where SP::Target: SignerProvider { is_initiator: false, inputs_to_contribute: our_funding_inputs, outputs_to_contribute: Vec::new(), - expected_remote_shared_funding_output: Some((funding.get_funding_redeemscript().to_p2wsh(), funding.get_value_satoshis())), - } - ).map_err(|_| ChannelError::Close(( - "V2 channel rejected due to sender error".into(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) } - )))?); + expected_remote_shared_funding_output: Some(( + funding.get_funding_redeemscript().to_p2wsh(), + funding.get_value_satoshis(), + )), + }) + .map_err(|_| { + ChannelError::Close(( + "V2 channel rejected due to sender error".into(), + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + )) + })?, + ); let unfunded_context = UnfundedChannelContext { unfunded_channel_age_ticks: 0, - holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx), + holder_commitment_point: HolderCommitmentPoint::new( + &context.holder_signer, + &context.secp_ctx, + ), }; Ok(Self { funding, @@ -10423,7 +12900,10 @@ impl PendingV2Channel where SP::Target: SignerProvider { debug_assert!(false, "Tried to send accept_channel2 after channel had moved forward"); } if self.unfunded_context.transaction_number() != INITIAL_COMMITMENT_NUMBER { - debug_assert!(false, "Tried to send an accept_channel2 for a channel that has already advanced"); + debug_assert!( + false, + "Tried to send an accept_channel2 for a channel that has already advanced" + ); } self.generate_accept_channel_v2_message() @@ -10484,23 +12964,27 @@ impl PendingV2Channel where SP::Target: SignerProvider { // Unfunded channel utilities -fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures { +fn get_initial_channel_type( + config: &UserConfig, their_features: &InitFeatures, +) -> ChannelTypeFeatures { // The default channel type (ie the first one we try) depends on whether the channel is // public - if it is, we just go with `only_static_remotekey` as it's the only option // available. If it's private, we first try `scid_privacy` as it provides better privacy // with no other changes, and fall back to `only_static_remotekey`. let mut ret = ChannelTypeFeatures::only_static_remote_key(); - if !config.channel_handshake_config.announce_for_forwarding && - config.channel_handshake_config.negotiate_scid_privacy && - their_features.supports_scid_privacy() { + if !config.channel_handshake_config.announce_for_forwarding + && config.channel_handshake_config.negotiate_scid_privacy + && their_features.supports_scid_privacy() + { ret.set_scid_privacy_required(); } // Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we // set it now. If they don't understand it, we'll fall back to our default of // `only_static_remotekey`. - if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx && - their_features.supports_anchors_zero_fee_htlc_tx() { + if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx + && their_features.supports_anchors_zero_fee_htlc_tx() + { ret.set_anchors_zero_fee_htlc_tx_required(); } @@ -10510,7 +12994,6 @@ fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) const SERIALIZATION_VERSION: u8 = 4; const MIN_SERIALIZATION_VERSION: u8 = 4; - impl Writeable for ChannelUpdateStatus { fn write(&self, writer: &mut W) -> Result<(), io::Error> { // We only care about writing out the current state as it was announced, ie only either @@ -10559,7 +13042,10 @@ impl Readable for AnnouncementSigsState { } } -impl Writeable for FundedChannel where SP::Target: SignerProvider { +impl Writeable for FundedChannel +where + SP::Target: SignerProvider, +{ fn write(&self, writer: &mut W) -> Result<(), io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been // called. @@ -10599,7 +13085,12 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider // Write out the old serialization for shutdown_pubkey for backwards compatibility, if // deserialized from that format. - match self.context.shutdown_scriptpubkey.as_ref().and_then(|script| script.as_legacy_pubkey()) { + match self + .context + .shutdown_scriptpubkey + .as_ref() + .and_then(|script| script.as_legacy_pubkey()) + { Some(shutdown_pubkey) => shutdown_pubkey.write(writer)?, None => [0u8; PUBLIC_KEY_SIZE].write(writer)?, } @@ -10641,7 +13132,10 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider &InboundHTLCState::LocalRemoved(ref removal_reason) => { 4u8.write(writer)?; match removal_reason { - InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket { data, attribution_data }) => { + InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket { + data, + attribution_data, + }) => { 0u8.write(writer)?; data.write(writer)?; removed_htlc_failure_attribution_data.push(&attribution_data); @@ -10692,7 +13186,7 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider } let reason: Option<&HTLCFailReason> = outcome.into(); reason.write(writer)?; - } + }, &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) => { 4u8.write(writer)?; if let OutboundHTLCOutcome::Success(preimage) = outcome { @@ -10700,24 +13194,32 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider } let reason: Option<&HTLCFailReason> = outcome.into(); reason.write(writer)?; - } + }, } pending_outbound_skimmed_fees.push(htlc.skimmed_fee_msat); pending_outbound_blinding_points.push(htlc.blinding_point); } let holding_cell_htlc_update_count = self.context.holding_cell_htlc_updates.len(); - let mut holding_cell_skimmed_fees: Vec> = Vec::with_capacity(holding_cell_htlc_update_count); - let mut holding_cell_blinding_points: Vec> = Vec::with_capacity(holding_cell_htlc_update_count); - let mut holding_cell_failure_attribution_data: Vec> = Vec::with_capacity(holding_cell_htlc_update_count); + let mut holding_cell_skimmed_fees: Vec> = + Vec::with_capacity(holding_cell_htlc_update_count); + let mut holding_cell_blinding_points: Vec> = + Vec::with_capacity(holding_cell_htlc_update_count); + let mut holding_cell_failure_attribution_data: Vec> = + Vec::with_capacity(holding_cell_htlc_update_count); // Vec of (htlc_id, failure_code, sha256_of_onion) let mut malformed_htlcs: Vec<(u64, u16, [u8; 32])> = Vec::new(); (holding_cell_htlc_update_count as u64).write(writer)?; for update in self.context.holding_cell_htlc_updates.iter() { match update { &HTLCUpdateAwaitingACK::AddHTLC { - ref amount_msat, ref cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet, - blinding_point, skimmed_fee_msat, + ref amount_msat, + ref cltv_expiry, + ref payment_hash, + ref source, + ref onion_routing_packet, + blinding_point, + skimmed_fee_msat, } => { 0u8.write(writer)?; amount_msat.write(writer)?; @@ -10740,10 +13242,13 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider err_packet.data.write(writer)?; // Store the attribution data for later writing. - holding_cell_failure_attribution_data.push(err_packet.attribution_data.as_ref()); - } + holding_cell_failure_attribution_data + .push(err_packet.attribution_data.as_ref()); + }, &HTLCUpdateAwaitingACK::FailMalformedHTLC { - htlc_id, failure_code, sha256_of_onion + htlc_id, + failure_code, + sha256_of_onion, } => { // We don't want to break downgrading by adding a new variant, so write a dummy // `::FailHTLC` variant and write the real malformed error as an optional TLV. @@ -10756,7 +13261,7 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider // Push 'None' attribution data for FailMalformedHTLC, because FailMalformedHTLC uses the same // type 2 and is deserialized as a FailHTLC. holding_cell_failure_attribution_data.push(None); - } + }, } } @@ -10776,7 +13281,9 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider } (self.context.monitor_pending_failures.len() as u64).write(writer)?; - for &(ref htlc_source, ref payment_hash, ref fail_reason) in self.context.monitor_pending_failures.iter() { + for &(ref htlc_source, ref payment_hash, ref fail_reason) in + self.context.monitor_pending_failures.iter() + { htlc_source.write(writer)?; payment_hash.write(writer)?; fail_reason.write(writer)?; @@ -10784,7 +13291,9 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider if self.funding.is_outbound() { self.context.pending_update_fee.map(|(a, _)| a).write(writer)?; - } else if let Some((feerate, FeeUpdateState::AwaitingRemoteRevokeToAnnounce)) = self.context.pending_update_fee { + } else if let Some((feerate, FeeUpdateState::AwaitingRemoteRevokeToAnnounce)) = + self.context.pending_update_fee + { Some(feerate).write(writer)?; } else { // As for inbound HTLCs, if the update was only announced and never committed in a @@ -10829,7 +13338,7 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider info.fee_proportional_millionths.write(writer)?; info.cltv_expiry_delta.write(writer)?; }, - None => 0u8.write(writer)? + None => 0u8.write(writer)?, } self.funding.channel_transaction_parameters.write(writer)?; @@ -10849,33 +13358,57 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider // older clients fail to deserialize this channel at all. If the type is // only-static-remote-key, we simply consider it "default" and don't write the channel type // out at all. - let chan_type = if self.funding.get_channel_type() != &ChannelTypeFeatures::only_static_remote_key() { - Some(self.funding.get_channel_type()) } else { None }; + let chan_type = + if self.funding.get_channel_type() != &ChannelTypeFeatures::only_static_remote_key() { + Some(self.funding.get_channel_type()) + } else { + None + }; // The same logic applies for `holder_selected_channel_reserve_satoshis` values other than // the default, and when `holder_max_htlc_value_in_flight_msat` is configured to be set to // a different percentage of the channel value then 10%, which older versions of LDK used // to set it to before the percentage was made configurable. let serialized_holder_selected_reserve = - if self.funding.holder_selected_channel_reserve_satoshis != get_legacy_default_holder_selected_channel_reserve_satoshis(self.funding.get_value_satoshis()) - { Some(self.funding.holder_selected_channel_reserve_satoshis) } else { None }; + if self.funding.holder_selected_channel_reserve_satoshis + != get_legacy_default_holder_selected_channel_reserve_satoshis( + self.funding.get_value_satoshis(), + ) { + Some(self.funding.holder_selected_channel_reserve_satoshis) + } else { + None + }; let mut old_max_in_flight_percent_config = UserConfig::default().channel_handshake_config; - old_max_in_flight_percent_config.max_inbound_htlc_value_in_flight_percent_of_channel = MAX_IN_FLIGHT_PERCENT_LEGACY; + old_max_in_flight_percent_config.max_inbound_htlc_value_in_flight_percent_of_channel = + MAX_IN_FLIGHT_PERCENT_LEGACY; let serialized_holder_htlc_max_in_flight = - if self.context.holder_max_htlc_value_in_flight_msat != get_holder_max_htlc_value_in_flight_msat(self.funding.get_value_satoshis(), &old_max_in_flight_percent_config) - { Some(self.context.holder_max_htlc_value_in_flight_msat) } else { None }; + if self.context.holder_max_htlc_value_in_flight_msat + != get_holder_max_htlc_value_in_flight_msat( + self.funding.get_value_satoshis(), + &old_max_in_flight_percent_config, + ) { + Some(self.context.holder_max_htlc_value_in_flight_msat) + } else { + None + }; let channel_pending_event_emitted = Some(self.context.channel_pending_event_emitted); let channel_ready_event_emitted = Some(self.context.channel_ready_event_emitted); - let funding_tx_broadcast_safe_event_emitted = Some(self.context.funding_tx_broadcast_safe_event_emitted); + let funding_tx_broadcast_safe_event_emitted = + Some(self.context.funding_tx_broadcast_safe_event_emitted); // `user_id` used to be a single u64 value. In order to remain backwards compatible with // versions prior to 0.0.113, the u128 is serialized as two separate u64 values. Therefore, // we write the high bytes as an option here. let user_id_high_opt = Some((self.context.user_id >> 64) as u64); - let holder_max_accepted_htlcs = if self.context.holder_max_accepted_htlcs == DEFAULT_MAX_HTLCS { None } else { Some(self.context.holder_max_accepted_htlcs) }; + let holder_max_accepted_htlcs = + if self.context.holder_max_accepted_htlcs == DEFAULT_MAX_HTLCS { + None + } else { + Some(self.context.holder_max_accepted_htlcs) + }; let mut monitor_pending_update_adds = None; if !self.context.monitor_pending_update_adds.is_empty() { @@ -10937,12 +13470,15 @@ impl Writeable for FundedChannel where SP::Target: SignerProvider } } -impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c ChannelTypeFeatures)> for FundedChannel - where - ES::Target: EntropySource, - SP::Target: SignerProvider +impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c ChannelTypeFeatures)> + for FundedChannel +where + ES::Target: EntropySource, + SP::Target: SignerProvider, { - fn read(reader: &mut R, args: (&'a ES, &'b SP, &'c ChannelTypeFeatures)) -> Result { + fn read( + reader: &mut R, args: (&'a ES, &'b SP, &'c ChannelTypeFeatures), + ) -> Result { let (entropy_source, signer_provider, our_supported_features) = args; let ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); if ver <= 2 { @@ -10961,7 +13497,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel } let channel_id: ChannelId = Readable::read(reader)?; - let channel_state = ChannelState::from_u32(Readable::read(reader)?).map_err(|_| DecodeError::InvalidValue)?; + let channel_state = ChannelState::from_u32(Readable::read(reader)?) + .map_err(|_| DecodeError::InvalidValue)?; let channel_value_satoshis = Readable::read(reader)?; let latest_monitor_update_id = Readable::read(reader)?; @@ -10979,7 +13516,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel let pending_inbound_htlc_count: u64 = Readable::read(reader)?; - let mut pending_inbound_htlcs = Vec::with_capacity(cmp::min(pending_inbound_htlc_count as usize, DEFAULT_MAX_HTLCS as usize)); + let mut pending_inbound_htlcs = Vec::with_capacity(cmp::min( + pending_inbound_htlc_count as usize, + DEFAULT_MAX_HTLCS as usize, + )); for _ in 0..pending_inbound_htlc_count { pending_inbound_htlcs.push(InboundHTLCOutput { htlc_id: Readable::read(reader)?, @@ -10989,7 +13529,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel state: match ::read(reader)? { 1 => { let resolution = if ver <= 3 { - InboundHTLCResolution::Resolved { pending_htlc_status: Readable::read(reader)? } + InboundHTLCResolution::Resolved { + pending_htlc_status: Readable::read(reader)?, + } } else { Readable::read(reader)? }; @@ -10997,7 +13539,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel }, 2 => { let resolution = if ver <= 3 { - InboundHTLCResolution::Resolved { pending_htlc_status: Readable::read(reader)? } + InboundHTLCResolution::Resolved { + pending_htlc_status: Readable::read(reader)?, + } } else { Readable::read(reader)? }; @@ -11022,7 +13566,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel } let pending_outbound_htlc_count: u64 = Readable::read(reader)?; - let mut pending_outbound_htlcs = Vec::with_capacity(cmp::min(pending_outbound_htlc_count as usize, DEFAULT_MAX_HTLCS as usize)); + let mut pending_outbound_htlcs = Vec::with_capacity(cmp::min( + pending_outbound_htlc_count as usize, + DEFAULT_MAX_HTLCS as usize, + )); for _ in 0..pending_outbound_htlc_count { pending_outbound_htlcs.push(OutboundHTLCOutput { htlc_id: Readable::read(reader)?, @@ -11069,7 +13616,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel } let holding_cell_htlc_update_count: u64 = Readable::read(reader)?; - let mut holding_cell_htlc_updates = Vec::with_capacity(cmp::min(holding_cell_htlc_update_count as usize, DEFAULT_MAX_HTLCS as usize*2)); + let mut holding_cell_htlc_updates = Vec::with_capacity(cmp::min( + holding_cell_htlc_update_count as usize, + DEFAULT_MAX_HTLCS as usize * 2, + )); for _ in 0..holding_cell_htlc_update_count { holding_cell_htlc_updates.push(match ::read(reader)? { 0 => HTLCUpdateAwaitingACK::AddHTLC { @@ -11107,15 +13657,25 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel let monitor_pending_commitment_signed = Readable::read(reader)?; let monitor_pending_forwards_count: u64 = Readable::read(reader)?; - let mut monitor_pending_forwards = Vec::with_capacity(cmp::min(monitor_pending_forwards_count as usize, DEFAULT_MAX_HTLCS as usize)); + let mut monitor_pending_forwards = Vec::with_capacity(cmp::min( + monitor_pending_forwards_count as usize, + DEFAULT_MAX_HTLCS as usize, + )); for _ in 0..monitor_pending_forwards_count { monitor_pending_forwards.push((Readable::read(reader)?, Readable::read(reader)?)); } let monitor_pending_failures_count: u64 = Readable::read(reader)?; - let mut monitor_pending_failures = Vec::with_capacity(cmp::min(monitor_pending_failures_count as usize, DEFAULT_MAX_HTLCS as usize)); + let mut monitor_pending_failures = Vec::with_capacity(cmp::min( + monitor_pending_failures_count as usize, + DEFAULT_MAX_HTLCS as usize, + )); for _ in 0..monitor_pending_failures_count { - monitor_pending_failures.push((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?)); + monitor_pending_failures.push(( + Readable::read(reader)?, + Readable::read(reader)?, + Readable::read(reader)?, + )); } let pending_update_fee_value: Option = Readable::read(reader)?; @@ -11173,7 +13733,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel _ => return Err(DecodeError::InvalidValue), }; - let channel_parameters: ChannelTransactionParameters = ReadableArgs::>::read(reader, Some(channel_value_satoshis))?; + let channel_parameters: ChannelTransactionParameters = + ReadableArgs::>::read(reader, Some(channel_value_satoshis))?; let funding_transaction: Option = Readable::read(reader)?; let counterparty_cur_commitment_point = Readable::read(reader)?; @@ -11187,11 +13748,14 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel let channel_update_status = Readable::read(reader)?; let pending_update_fee = if let Some(feerate) = pending_update_fee_value { - Some((feerate, if channel_parameters.is_outbound_from_holder { - FeeUpdateState::Outbound - } else { - FeeUpdateState::AwaitingRemoteRevokeToAnnounce - })) + Some(( + feerate, + if channel_parameters.is_outbound_from_holder { + FeeUpdateState::Outbound + } else { + FeeUpdateState::AwaitingRemoteRevokeToAnnounce + }, + )) } else { None }; @@ -11199,8 +13763,14 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel let mut announcement_sigs = None; let mut target_closing_feerate_sats_per_kw = None; let mut monitor_pending_finalized_fulfills = Some(Vec::new()); - let mut holder_selected_channel_reserve_satoshis = Some(get_legacy_default_holder_selected_channel_reserve_satoshis(channel_value_satoshis)); - let mut holder_max_htlc_value_in_flight_msat = Some(get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis, &UserConfig::default().channel_handshake_config)); + let mut holder_selected_channel_reserve_satoshis = Some( + get_legacy_default_holder_selected_channel_reserve_satoshis(channel_value_satoshis), + ); + let mut holder_max_htlc_value_in_flight_msat = + Some(get_holder_max_htlc_value_in_flight_msat( + channel_value_satoshis, + &UserConfig::default().channel_handshake_config, + )); // Prior to supporting channel type negotiation, all of our channels were static_remotekey // only, so we default to that if none was written. let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key()); @@ -11292,19 +13862,23 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel let mut iter = preimages.into_iter(); for htlc in pending_outbound_htlcs.iter_mut() { match &mut htlc.state { - OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(ref mut preimage)) => { + OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success( + ref mut preimage, + )) => { // This variant was initialized like this further above debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32])); // Flatten and unwrap the preimage; they are always set starting in 0.2. *preimage = iter.next().flatten().ok_or(DecodeError::InvalidValue)?; - } - OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(ref mut preimage)) => { + }, + OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success( + ref mut preimage, + )) => { // This variant was initialized like this further above debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32])); // Flatten and unwrap the preimage; they are always set starting in 0.2. *preimage = iter.next().flatten().ok_or(DecodeError::InvalidValue)?; - } - _ => {} + }, + _ => {}, } } // We expect all preimages to be consumed above @@ -11313,7 +13887,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel } let chan_features = channel_type.unwrap(); - if chan_features.supports_any_optional_bits() || chan_features.requires_unknown_bits_from(&our_supported_features) { + if chan_features.supports_any_optional_bits() + || chan_features.requires_unknown_bits_from(&our_supported_features) + { // If the channel was written by a new version and negotiated with features we don't // understand yet, refuse to read it. return Err(DecodeError::UnknownRequiredFeature); @@ -11339,7 +13915,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel htlc.skimmed_fee_msat = iter.next().ok_or(DecodeError::InvalidValue)?; } // We expect all skimmed fees to be consumed above - if iter.next().is_some() { return Err(DecodeError::InvalidValue) } + if iter.next().is_some() { + return Err(DecodeError::InvalidValue); + } } if let Some(skimmed_fees) = holding_cell_skimmed_fees_opt { let mut iter = skimmed_fees.into_iter(); @@ -11349,7 +13927,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel } } // We expect all skimmed fees to be consumed above - if iter.next().is_some() { return Err(DecodeError::InvalidValue) } + if iter.next().is_some() { + return Err(DecodeError::InvalidValue); + } } if let Some(blinding_pts) = pending_outbound_blinding_points_opt { let mut iter = blinding_pts.into_iter(); @@ -11357,7 +13937,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel htlc.blinding_point = iter.next().ok_or(DecodeError::InvalidValue)?; } // We expect all blinding points to be consumed above - if iter.next().is_some() { return Err(DecodeError::InvalidValue) } + if iter.next().is_some() { + return Err(DecodeError::InvalidValue); + } } if let Some(blinding_pts) = holding_cell_blinding_points_opt { let mut iter = blinding_pts.into_iter(); @@ -11367,87 +13949,131 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel } } // We expect all blinding points to be consumed above - if iter.next().is_some() { return Err(DecodeError::InvalidValue) } + if iter.next().is_some() { + return Err(DecodeError::InvalidValue); + } } if let Some(attribution_data_list) = removed_htlc_failure_attribution_data { let mut removed_htlc_relay_failures = - pending_inbound_htlcs.iter_mut().filter_map(|status| - if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(ref mut packet)) = &mut status.state { + pending_inbound_htlcs.iter_mut().filter_map(|status| { + if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay( + ref mut packet, + )) = &mut status.state + { Some(&mut packet.attribution_data) } else { None } - ); + }); for attribution_data in attribution_data_list { - *removed_htlc_relay_failures.next().ok_or(DecodeError::InvalidValue)? = attribution_data; + *removed_htlc_relay_failures.next().ok_or(DecodeError::InvalidValue)? = + attribution_data; + } + if removed_htlc_relay_failures.next().is_some() { + return Err(DecodeError::InvalidValue); } - if removed_htlc_relay_failures.next().is_some() { return Err(DecodeError::InvalidValue); } } if let Some(attribution_data_list) = holding_cell_failure_attribution_data { let mut holding_cell_failures = - holding_cell_htlc_updates.iter_mut().filter_map(|upd| - if let HTLCUpdateAwaitingACK::FailHTLC { err_packet: OnionErrorPacket { ref mut attribution_data, .. }, .. } = upd { + holding_cell_htlc_updates.iter_mut().filter_map(|upd| { + if let HTLCUpdateAwaitingACK::FailHTLC { + err_packet: OnionErrorPacket { ref mut attribution_data, .. }, + .. + } = upd + { Some(attribution_data) } else { None } - ); + }); for attribution_data in attribution_data_list { *holding_cell_failures.next().ok_or(DecodeError::InvalidValue)? = attribution_data; } - if holding_cell_failures.next().is_some() { return Err(DecodeError::InvalidValue); } + if holding_cell_failures.next().is_some() { + return Err(DecodeError::InvalidValue); + } } if let Some(malformed_htlcs) = malformed_htlcs { for (malformed_htlc_id, failure_code, sha256_of_onion) in malformed_htlcs { - let htlc_idx = holding_cell_htlc_updates.iter().position(|htlc| { - if let HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet } = htlc { - let matches = *htlc_id == malformed_htlc_id; - if matches { debug_assert!(err_packet.data.is_empty()) } - matches - } else { false } - }).ok_or(DecodeError::InvalidValue)?; + let htlc_idx = holding_cell_htlc_updates + .iter() + .position(|htlc| { + if let HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet } = htlc { + let matches = *htlc_id == malformed_htlc_id; + if matches { + debug_assert!(err_packet.data.is_empty()) + } + matches + } else { + false + } + }) + .ok_or(DecodeError::InvalidValue)?; let malformed_htlc = HTLCUpdateAwaitingACK::FailMalformedHTLC { - htlc_id: malformed_htlc_id, failure_code, sha256_of_onion + htlc_id: malformed_htlc_id, + failure_code, + sha256_of_onion, }; - let _ = core::mem::replace(&mut holding_cell_htlc_updates[htlc_idx], malformed_htlc); + let _ = + core::mem::replace(&mut holding_cell_htlc_updates[htlc_idx], malformed_htlc); } } // If we're restoring this channel for the first time after an upgrade, then we require that the // signer be available so that we can immediately populate the current commitment point. Channel // restoration will fail if this is not possible. - let holder_commitment_point = match (cur_holder_commitment_point_opt, next_holder_commitment_point_opt) { + let holder_commitment_point = match ( + cur_holder_commitment_point_opt, + next_holder_commitment_point_opt, + ) { (Some(current), Some(next)) => HolderCommitmentPoint::Available { - transaction_number: cur_holder_commitment_transaction_number, current, next + transaction_number: cur_holder_commitment_transaction_number, + current, + next, }, (Some(current), _) => HolderCommitmentPoint::PendingNext { - transaction_number: cur_holder_commitment_transaction_number, current, + transaction_number: cur_holder_commitment_transaction_number, + current, }, (_, _) => { let current = holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number, &secp_ctx) .expect("Must be able to derive the current commitment point upon channel restoration"); - let next = holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number - 1, &secp_ctx) - .expect("Must be able to derive the next commitment point upon channel restoration"); + let next = holder_signer + .get_per_commitment_point( + cur_holder_commitment_transaction_number - 1, + &secp_ctx, + ) + .expect( + "Must be able to derive the next commitment point upon channel restoration", + ); HolderCommitmentPoint::Available { - transaction_number: cur_holder_commitment_transaction_number, current, next, + transaction_number: cur_holder_commitment_transaction_number, + current, + next, } }, }; let is_v2_established = channel_id.is_v2_channel_id( &channel_parameters.holder_pubkeys.revocation_basepoint, - &channel_parameters.counterparty_parameters.as_ref() - .expect("Persisted channel must have counterparty parameters").pubkeys.revocation_basepoint); + &channel_parameters + .counterparty_parameters + .as_ref() + .expect("Persisted channel must have counterparty parameters") + .pubkeys + .revocation_basepoint, + ); Ok(FundedChannel { funding: FundingScope { value_to_self_msat, counterparty_selected_channel_reserve_satoshis, - holder_selected_channel_reserve_satoshis: holder_selected_channel_reserve_satoshis.unwrap(), + holder_selected_channel_reserve_satoshis: holder_selected_channel_reserve_satoshis + .unwrap(), #[cfg(debug_assertions)] holder_max_commitment_tx_output: Mutex::new((0, 0)), @@ -11562,7 +14188,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel // Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing outbound_scid_alias, - funding_tx_broadcast_safe_event_emitted: funding_tx_broadcast_safe_event_emitted.unwrap_or(false), + funding_tx_broadcast_safe_event_emitted: funding_tx_broadcast_safe_event_emitted + .unwrap_or(false), channel_pending_event_emitted: channel_pending_event_emitted.unwrap_or(true), channel_ready_event_emitted: channel_ready_event_emitted.unwrap_or(true), @@ -11597,72 +14224,94 @@ fn duration_since_epoch() -> Option { let now = None; #[cfg(feature = "std")] - let now = Some(std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH")); + let now = Some( + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH"), + ); now } #[cfg(test)] mod tests { - use std::cmp; - use bitcoin::amount::Amount; - use bitcoin::constants::ChainHash; - use bitcoin::script::{ScriptBuf, Builder}; - use bitcoin::transaction::{Transaction, TxOut, Version}; - #[cfg(splicing)] - use bitcoin::transaction::TxIn; - use bitcoin::opcodes; - use bitcoin::network::Network; - #[cfg(splicing)] - use bitcoin::Weight; - use crate::ln::onion_utils::{AttributionData, LocalHTLCFailureReason}; - use crate::types::payment::{PaymentHash, PaymentPreimage}; - use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint}; - use crate::ln::channelmanager::{self, HTLCSource, PaymentId}; + use crate::chain::chaininterface::{ + ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator, + }; + use crate::chain::transaction::OutPoint; + use crate::chain::BestBlock; + use crate::ln::chan_utils::{self, htlc_success_tx_weight, htlc_timeout_tx_weight}; use crate::ln::channel::InitFeatures; - use crate::ln::channel::{AwaitingChannelReadyFlags, ChannelState, FundedChannel, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat}; - use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS}; - use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; + use crate::ln::channel::{ + commit_tx_fee_sat, AwaitingChannelReadyFlags, ChannelState, FundedChannel, HTLCCandidate, + HTLCInitiator, HTLCUpdateAwaitingACK, InboundHTLCOutput, InboundHTLCState, + InboundV1Channel, OutboundHTLCOutput, OutboundHTLCState, OutboundV1Channel, + }; + use crate::ln::channel::{ + MAX_FUNDING_SATOSHIS_NO_WUMBO, MIN_THEIR_CHAN_RESERVE_SATOSHIS, + TOTAL_BITCOIN_SUPPLY_SATOSHIS, + }; + use crate::ln::channel_keys::{RevocationBasepoint, RevocationKey}; + use crate::ln::channelmanager::{self, HTLCSource, PaymentId}; use crate::ln::msgs; use crate::ln::msgs::{ChannelUpdate, UnsignedChannelUpdate, MAX_VALUE_MSAT}; + use crate::ln::onion_utils::{AttributionData, LocalHTLCFailureReason}; use crate::ln::script::ShutdownScript; - use crate::ln::chan_utils::{self, htlc_success_tx_weight, htlc_timeout_tx_weight}; - use crate::chain::BestBlock; - use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget}; - use crate::sign::{ChannelSigner, InMemorySigner, EntropySource, SignerProvider}; - use crate::chain::transaction::OutPoint; + use crate::prelude::*; use crate::routing::router::{Path, RouteHop}; + use crate::sign::{ChannelSigner, EntropySource, InMemorySigner, SignerProvider}; + use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; + use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::config::UserConfig; use crate::util::errors::APIError; use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_utils; use crate::util::test_utils::{OnGetShutdownScriptpubkey, TestKeysInterface}; - use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; - use bitcoin::secp256k1::ffi::Signature as FFISignature; - use bitcoin::secp256k1::{SecretKey,PublicKey}; + use bitcoin::amount::Amount; + use bitcoin::constants::ChainHash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; use bitcoin::hex::FromHex; use bitcoin::locktime::absolute::LockTime; - use bitcoin::{WitnessProgram, WitnessVersion, WPubkeyHash}; - use crate::prelude::*; + use bitcoin::network::Network; + use bitcoin::opcodes; + use bitcoin::script::{Builder, ScriptBuf}; + use bitcoin::secp256k1::ffi::Signature as FFISignature; + use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1}; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + #[cfg(splicing)] + use bitcoin::transaction::TxIn; + use bitcoin::transaction::{Transaction, TxOut, Version}; + #[cfg(splicing)] + use bitcoin::Weight; + use bitcoin::{WPubkeyHash, WitnessProgram, WitnessVersion}; + use std::cmp; #[test] fn test_channel_state_order() { - use crate::ln::channel::NegotiatingFundingFlags; use crate::ln::channel::AwaitingChannelReadyFlags; use crate::ln::channel::ChannelReadyFlags; + use crate::ln::channel::NegotiatingFundingFlags; - assert!(ChannelState::NegotiatingFunding(NegotiatingFundingFlags::new()) < ChannelState::FundingNegotiated); - assert!(ChannelState::FundingNegotiated < ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new())); - assert!(ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()) < ChannelState::ChannelReady(ChannelReadyFlags::new())); - assert!(ChannelState::ChannelReady(ChannelReadyFlags::new()) < ChannelState::ShutdownComplete); + assert!( + ChannelState::NegotiatingFunding(NegotiatingFundingFlags::new()) + < ChannelState::FundingNegotiated + ); + assert!( + ChannelState::FundingNegotiated + < ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()) + ); + assert!( + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()) + < ChannelState::ChannelReady(ChannelReadyFlags::new()) + ); + assert!( + ChannelState::ChannelReady(ChannelReadyFlags::new()) < ChannelState::ShutdownComplete + ); } struct TestFeeEstimator { - fee_est: u32 + fee_est: u32, } impl FeeEstimator for TestFeeEstimator { fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u32 { @@ -11673,8 +14322,10 @@ mod tests { #[test] fn test_max_funding_satoshis_no_wumbo() { assert_eq!(TOTAL_BITCOIN_SUPPLY_SATOSHIS, 21_000_000 * 100_000_000); - assert!(MAX_FUNDING_SATOSHIS_NO_WUMBO <= TOTAL_BITCOIN_SUPPLY_SATOSHIS, - "MAX_FUNDING_SATOSHIS_NO_WUMBO is greater than all satoshis in existence"); + assert!( + MAX_FUNDING_SATOSHIS_NO_WUMBO <= TOTAL_BITCOIN_SUPPLY_SATOSHIS, + "MAX_FUNDING_SATOSHIS_NO_WUMBO is greater than all satoshis in existence" + ); } struct Keys { @@ -11682,7 +14333,9 @@ mod tests { } impl EntropySource for Keys { - fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] } + fn get_secure_random_bytes(&self) -> [u8; 32] { + [0; 32] + } } impl SignerProvider for Keys { @@ -11700,22 +14353,47 @@ mod tests { fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result { let secp_ctx = Secp256k1::signing_only(); - let channel_monitor_claim_key = SecretKey::from_slice(&>::from_hex("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); - let channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); - Ok(Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(channel_monitor_claim_key_hash).into_script()) + let channel_monitor_claim_key = SecretKey::from_slice( + &>::from_hex( + "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + .unwrap()[..], + ) + .unwrap(); + let channel_monitor_claim_key_hash = WPubkeyHash::hash( + &PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize(), + ); + Ok(Builder::new() + .push_opcode(opcodes::all::OP_PUSHBYTES_0) + .push_slice(channel_monitor_claim_key_hash) + .into_script()) } fn get_shutdown_scriptpubkey(&self) -> Result { let secp_ctx = Secp256k1::signing_only(); - let channel_close_key = SecretKey::from_slice(&>::from_hex("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); - Ok(ShutdownScript::new_p2wpkh_from_pubkey(PublicKey::from_secret_key(&secp_ctx, &channel_close_key))) + let channel_close_key = SecretKey::from_slice( + &>::from_hex( + "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + .unwrap()[..], + ) + .unwrap(); + Ok(ShutdownScript::new_p2wpkh_from_pubkey(PublicKey::from_secret_key( + &secp_ctx, + &channel_close_key, + ))) } } #[cfg(ldk_test_vectors)] - fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { + fn public_from_secret_hex( + secp_ctx: &Secp256k1, hex: &str, + ) -> PublicKey { assert!(cfg!(not(feature = "grind_signatures"))); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap()) + PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(), + ) } #[test] @@ -11724,20 +14402,35 @@ mod tests { features.clear_shutdown_anysegwit(); let non_v0_segwit_shutdown_script = ShutdownScript::new_witness_program( &WitnessProgram::new(WitnessVersion::V16, &[0, 40]).unwrap(), - ).unwrap(); + ) + .unwrap(); let seed = [42; 32]; let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); - keys_provider.expect(OnGetShutdownScriptpubkey { - returns: non_v0_segwit_shutdown_script.clone(), - }); + keys_provider + .expect(OnGetShutdownScriptpubkey { returns: non_v0_segwit_shutdown_script.clone() }); let logger = test_utils::TestLogger::new(); let secp_ctx = Secp256k1::new(); - let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - match OutboundV1Channel::<&TestKeysInterface>::new(&LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), &&keys_provider, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42, None, &logger) { + match OutboundV1Channel::<&TestKeysInterface>::new( + &LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), + &&keys_provider, + &&keys_provider, + node_id, + &features, + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) { Err(APIError::IncompatibleShutdownScript { script }) => { assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner()); }, @@ -11751,7 +14444,7 @@ mod tests { #[test] fn test_open_channel_msg_fee() { let original_fee = 253; - let mut fee_est = TestFeeEstimator{fee_est: original_fee }; + let mut fee_est = TestFeeEstimator { fee_est: original_fee }; let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_est); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; @@ -11759,22 +14452,43 @@ mod tests { let keys_provider = test_utils::TestKeysInterface::new(&seed, network); let logger = test_utils::TestLogger::new(); - let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_a_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&bounded_fee_estimator, &&keys_provider, &&keys_provider, node_a_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, None, &logger).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new( + &bounded_fee_estimator, + &&keys_provider, + &&keys_provider, + node_a_node_id, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); // Now change the fee so we can check that the fee in the open_channel message is the // same as the old fee. fee_est.fee_est = 500; - let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); - assert_eq!(open_channel_msg.common_fields.commitment_feerate_sat_per_1000_weight, original_fee); + let open_channel_msg = node_a_chan + .get_open_channel(ChainHash::using_genesis_block(network), &&logger) + .unwrap(); + assert_eq!( + open_channel_msg.common_fields.commitment_feerate_sat_per_1000_weight, + original_fee + ); } #[test] fn test_holder_vs_counterparty_dust_limit() { // Test that when calculating the local and remote commitment transaction fees, the correct // dust limits are used. - let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; @@ -11786,34 +14500,94 @@ mod tests { // they have different dust limits. // Create Node A's channel pointing to Node B's pubkey - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, None, &logger).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); // Create Node B's channel by receiving Node A's open_channel message // Make sure A's dust limit is as we expect. - let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let open_channel_msg = node_a_chan + .get_open_channel(ChainHash::using_genesis_block(network), &&logger) + .unwrap(); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_channel_type_features(&config), + &channelmanager::provided_init_features(&config), + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); // Node B --> Node A: accept channel, explicitly setting B's dust limit. let mut accept_channel_msg = node_b_chan.accept_inbound_channel(&&logger).unwrap(); accept_channel_msg.common_fields.dust_limit_satoshis = 546; - node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features(&config)).unwrap(); + node_a_chan + .accept_channel( + &accept_channel_msg, + &config.channel_handshake_limits, + &channelmanager::provided_init_features(&config), + ) + .unwrap(); node_a_chan.context.holder_dust_limit_satoshis = 1560; // Node A --> Node B: funding created let output_script = node_a_chan.funding.get_funding_redeemscript(); - let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.compute_txid(), index: 0 }; - let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); - let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap(); + let tx = Transaction { + version: Version::ONE, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { + value: Amount::from_sat(10000000), + script_pubkey: output_script.clone(), + }], + }; + let funding_outpoint = OutPoint { txid: tx.compute_txid(), index: 0 }; + let funding_created_msg = node_a_chan + .get_funding_created(tx.clone(), funding_outpoint, false, &&logger) + .map_err(|_| ()) + .unwrap(); + let (_, funding_signed_msg, _) = node_b_chan + .funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger) + .map_err(|_| ()) + .unwrap(); // Node B --> Node A: funding signed - let res = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger); - let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; + let res = node_a_chan.funding_signed( + &funding_signed_msg.unwrap(), + best_block, + &&keys_provider, + &&logger, + ); + let (mut node_a_chan, _) = if let Ok(res) = res { + res + } else { + panic!(); + }; // Put some inbound and outbound HTLCs in A's channel. let htlc_amount_msat = 11_092_000; // put an amount below A's effective dust limit but above B's. @@ -11833,7 +14607,13 @@ mod tests { state: OutboundHTLCState::Committed, source: HTLCSource::OutboundRoute { path: Path { hops: Vec::new(), blinded_tail: None }, - session_priv: SecretKey::from_slice(&>::from_hex("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), + session_priv: SecretKey::from_slice( + &>::from_hex( + "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + .unwrap()[..], + ) + .unwrap(), first_hop_htlc_msat: 548, payment_id: PaymentId([42; 32]), }, @@ -11845,16 +14625,32 @@ mod tests { // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass // the dust limit check. let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered); - let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(&node_a_chan.funding, htlc_candidate, None); - let local_commit_fee_0_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.funding.get_channel_type()) * 1000; + let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat( + &node_a_chan.funding, + htlc_candidate, + None, + ); + let local_commit_fee_0_htlcs = commit_tx_fee_sat( + node_a_chan.context.feerate_per_kw, + 0, + node_a_chan.funding.get_channel_type(), + ) * 1000; assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs); // Finally, make sure that when Node A calculates the remote's commitment transaction fees, all // of the HTLCs are seen to be above the dust limit. node_a_chan.funding.channel_transaction_parameters.is_outbound_from_holder = false; - let remote_commit_fee_3_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.funding.get_channel_type()) * 1000; + let remote_commit_fee_3_htlcs = commit_tx_fee_sat( + node_a_chan.context.feerate_per_kw, + 3, + node_a_chan.funding.get_channel_type(), + ) * 1000; let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered); - let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(&node_a_chan.funding, Some(htlc_candidate), None); + let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat( + &node_a_chan.funding, + Some(htlc_candidate), + None, + ); assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs); } @@ -11864,51 +14660,91 @@ mod tests { // calculate the real dust limits for HTLCs (i.e. the dust limit given by the counterparty // *plus* the fees paid for the HTLC) they don't swap `HTLC_SUCCESS_TX_WEIGHT` for // `HTLC_TIMEOUT_TX_WEIGHT`, and vice versa. - let fee_est = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 253 }); + let fee_est = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); let logger = test_utils::TestLogger::new(); - let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut chan = OutboundV1Channel::<&TestKeysInterface>::new(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, None, &logger).unwrap(); + let mut chan = OutboundV1Channel::<&TestKeysInterface>::new( + &fee_est, + &&keys_provider, + &&keys_provider, + node_id, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); - let commitment_tx_fee_0_htlcs = commit_tx_fee_sat(chan.context.feerate_per_kw, 0, chan.funding.get_channel_type()) * 1000; - let commitment_tx_fee_1_htlc = commit_tx_fee_sat(chan.context.feerate_per_kw, 1, chan.funding.get_channel_type()) * 1000; + let commitment_tx_fee_0_htlcs = + commit_tx_fee_sat(chan.context.feerate_per_kw, 0, chan.funding.get_channel_type()) + * 1000; + let commitment_tx_fee_1_htlc = + commit_tx_fee_sat(chan.context.feerate_per_kw, 1, chan.funding.get_channel_type()) + * 1000; // If HTLC_SUCCESS_TX_WEIGHT and HTLC_TIMEOUT_TX_WEIGHT were swapped: then this HTLC would be // counted as dust when it shouldn't be. - let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000; - let htlc_candidate = HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered); - let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None); + let htlc_amt_above_timeout = ((253 + * htlc_timeout_tx_weight(chan.funding.get_channel_type()) + / 1000) + chan.context.holder_dust_limit_satoshis + + 1) * 1000; + let htlc_candidate = + HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered); + let commitment_tx_fee = + chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc); // If swapped: this HTLC would be counted as non-dust when it shouldn't be. - let dust_htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis - 1) * 1000; - let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered); - let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None); + let dust_htlc_amt_below_success = ((253 + * htlc_success_tx_weight(chan.funding.get_channel_type()) + / 1000) + chan.context.holder_dust_limit_satoshis + - 1) * 1000; + let htlc_candidate = + HTLCCandidate::new(dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered); + let commitment_tx_fee = + chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs); chan.funding.channel_transaction_parameters.is_outbound_from_holder = false; // If swapped: this HTLC would be counted as non-dust when it shouldn't be. - let dust_htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis + 1) * 1000; - let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered); - let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None); + let dust_htlc_amt_above_timeout = ((253 + * htlc_timeout_tx_weight(chan.funding.get_channel_type()) + / 1000) + chan.context.counterparty_dust_limit_satoshis + + 1) * 1000; + let htlc_candidate = + HTLCCandidate::new(dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered); + let commitment_tx_fee = + chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None); assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs); // If swapped: this HTLC would be counted as dust when it shouldn't be. - let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000; - let htlc_candidate = HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered); - let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None); + let htlc_amt_below_success = ((253 + * htlc_success_tx_weight(chan.funding.get_channel_type()) + / 1000) + chan.context.counterparty_dust_limit_satoshis + - 1) * 1000; + let htlc_candidate = + HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered); + let commitment_tx_fee = + chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None); assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc); } #[test] fn channel_reestablish_no_updates() { - let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let logger = test_utils::TestLogger::new(); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; @@ -11920,31 +14756,89 @@ mod tests { // Go through the flow of opening a channel between two nodes. // Create Node A's channel pointing to Node B's pubkey - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, None, &logger).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); // Create Node B's channel by receiving Node A's open_channel message let open_channel_msg = node_a_chan.get_open_channel(chain_hash, &&logger).unwrap(); - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_channel_type_features(&config), + &channelmanager::provided_init_features(&config), + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); // Node B --> Node A: accept channel let accept_channel_msg = node_b_chan.accept_inbound_channel(&&logger).unwrap(); - node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features(&config)).unwrap(); + node_a_chan + .accept_channel( + &accept_channel_msg, + &config.channel_handshake_limits, + &channelmanager::provided_init_features(&config), + ) + .unwrap(); // Node A --> Node B: funding created let output_script = node_a_chan.funding.get_funding_redeemscript(); - let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.compute_txid(), index: 0 }; - let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); - let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap(); + let tx = Transaction { + version: Version::ONE, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { + value: Amount::from_sat(10000000), + script_pubkey: output_script.clone(), + }], + }; + let funding_outpoint = OutPoint { txid: tx.compute_txid(), index: 0 }; + let funding_created_msg = node_a_chan + .get_funding_created(tx.clone(), funding_outpoint, false, &&logger) + .map_err(|_| ()) + .unwrap(); + let (mut node_b_chan, funding_signed_msg, _) = node_b_chan + .funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger) + .map_err(|_| ()) + .unwrap(); // Node B --> Node A: funding signed - let res = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger); - let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; + let res = node_a_chan.funding_signed( + &funding_signed_msg.unwrap(), + best_block, + &&keys_provider, + &&logger, + ); + let (mut node_a_chan, _) = if let Ok(res) = res { + res + } else { + panic!(); + }; // Now disconnect the two nodes and check that the commitment point in // Node B's channel_reestablish message is sane. @@ -11965,80 +14859,224 @@ mod tests { #[test] fn test_configured_holder_max_htlc_value_in_flight() { - let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let logger = test_utils::TestLogger::new(); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); - let outbound_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let inbound_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let outbound_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let inbound_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let mut config_2_percent = UserConfig::default(); - config_2_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 2; + config_2_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 2; let mut config_99_percent = UserConfig::default(); - config_99_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 99; + config_99_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 99; let mut config_0_percent = UserConfig::default(); - config_0_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 0; + config_0_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 0; let mut config_101_percent = UserConfig::default(); - config_101_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 101; + config_101_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 101; // Test that `OutboundV1Channel::new` creates a channel with the correct value for // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value, // which is set to the lower bound + 1 (2%) of the `channel_value`. - let mut chan_1 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_2_percent), 10000000, 100000, 42, &config_2_percent, 0, 42, None, &logger).unwrap(); + let mut chan_1 = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + outbound_node_id, + &channelmanager::provided_init_features(&config_2_percent), + 10000000, + 100000, + 42, + &config_2_percent, + 0, + 42, + None, + &logger, + ) + .unwrap(); let chan_1_value_msat = chan_1.funding.get_value_satoshis() * 1000; - assert_eq!(chan_1.context.holder_max_htlc_value_in_flight_msat, (chan_1_value_msat as f64 * 0.02) as u64); + assert_eq!( + chan_1.context.holder_max_htlc_value_in_flight_msat, + (chan_1_value_msat as f64 * 0.02) as u64 + ); // Test with the upper bound - 1 of valid values (99%). - let chan_2 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_99_percent), 10000000, 100000, 42, &config_99_percent, 0, 42, None, &logger).unwrap(); - let chan_2_value_msat = chan_2.funding.get_value_satoshis() * 1000; - assert_eq!(chan_2.context.holder_max_htlc_value_in_flight_msat, (chan_2_value_msat as f64 * 0.99) as u64); - - let chan_1_open_channel_msg = chan_1.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); - - // Test that `InboundV1Channel::new` creates a channel with the correct value for - // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value, - // which is set to the lower bound - 1 (2%) of the `channel_value`. - let chan_3 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_2_percent), &channelmanager::provided_init_features(&config_2_percent), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); - let chan_3_value_msat = chan_3.funding.get_value_satoshis() * 1000; - assert_eq!(chan_3.context.holder_max_htlc_value_in_flight_msat, (chan_3_value_msat as f64 * 0.02) as u64); + let chan_2 = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + outbound_node_id, + &channelmanager::provided_init_features(&config_99_percent), + 10000000, + 100000, + 42, + &config_99_percent, + 0, + 42, + None, + &logger, + ) + .unwrap(); + let chan_2_value_msat = chan_2.funding.get_value_satoshis() * 1000; + assert_eq!( + chan_2.context.holder_max_htlc_value_in_flight_msat, + (chan_2_value_msat as f64 * 0.99) as u64 + ); + + let chan_1_open_channel_msg = + chan_1.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); + + // Test that `InboundV1Channel::new` creates a channel with the correct value for + // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value, + // which is set to the lower bound - 1 (2%) of the `channel_value`. + let chan_3 = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + inbound_node_id, + &channelmanager::provided_channel_type_features(&config_2_percent), + &channelmanager::provided_init_features(&config_2_percent), + &chan_1_open_channel_msg, + 7, + &config_2_percent, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); + let chan_3_value_msat = chan_3.funding.get_value_satoshis() * 1000; + assert_eq!( + chan_3.context.holder_max_htlc_value_in_flight_msat, + (chan_3_value_msat as f64 * 0.02) as u64 + ); // Test with the upper bound - 1 of valid values (99%). - let chan_4 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_99_percent), &channelmanager::provided_init_features(&config_99_percent), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_4 = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + inbound_node_id, + &channelmanager::provided_channel_type_features(&config_99_percent), + &channelmanager::provided_init_features(&config_99_percent), + &chan_1_open_channel_msg, + 7, + &config_99_percent, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); let chan_4_value_msat = chan_4.funding.get_value_satoshis() * 1000; - assert_eq!(chan_4.context.holder_max_htlc_value_in_flight_msat, (chan_4_value_msat as f64 * 0.99) as u64); + assert_eq!( + chan_4.context.holder_max_htlc_value_in_flight_msat, + (chan_4_value_msat as f64 * 0.99) as u64 + ); // Test that `OutboundV1Channel::new` uses the lower bound of the configurable percentage values (1%) // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1. - let chan_5 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_0_percent), 10000000, 100000, 42, &config_0_percent, 0, 42, None, &logger).unwrap(); + let chan_5 = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + outbound_node_id, + &channelmanager::provided_init_features(&config_0_percent), + 10000000, + 100000, + 42, + &config_0_percent, + 0, + 42, + None, + &logger, + ) + .unwrap(); let chan_5_value_msat = chan_5.funding.get_value_satoshis() * 1000; - assert_eq!(chan_5.context.holder_max_htlc_value_in_flight_msat, (chan_5_value_msat as f64 * 0.01) as u64); + assert_eq!( + chan_5.context.holder_max_htlc_value_in_flight_msat, + (chan_5_value_msat as f64 * 0.01) as u64 + ); // Test that `OutboundV1Channel::new` uses the upper bound of the configurable percentage values // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value // than 100. - let chan_6 = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&config_101_percent), 10000000, 100000, 42, &config_101_percent, 0, 42, None, &logger).unwrap(); + let chan_6 = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + outbound_node_id, + &channelmanager::provided_init_features(&config_101_percent), + 10000000, + 100000, + 42, + &config_101_percent, + 0, + 42, + None, + &logger, + ) + .unwrap(); let chan_6_value_msat = chan_6.funding.get_value_satoshis() * 1000; assert_eq!(chan_6.context.holder_max_htlc_value_in_flight_msat, chan_6_value_msat); // Test that `InboundV1Channel::new` uses the lower bound of the configurable percentage values (1%) // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1. - let chan_7 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_0_percent), &channelmanager::provided_init_features(&config_0_percent), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_7 = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + inbound_node_id, + &channelmanager::provided_channel_type_features(&config_0_percent), + &channelmanager::provided_init_features(&config_0_percent), + &chan_1_open_channel_msg, + 7, + &config_0_percent, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); let chan_7_value_msat = chan_7.funding.get_value_satoshis() * 1000; - assert_eq!(chan_7.context.holder_max_htlc_value_in_flight_msat, (chan_7_value_msat as f64 * 0.01) as u64); + assert_eq!( + chan_7.context.holder_max_htlc_value_in_flight_msat, + (chan_7_value_msat as f64 * 0.01) as u64 + ); // Test that `InboundV1Channel::new` uses the upper bound of the configurable percentage values // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value // than 100. - let chan_8 = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&config_101_percent), &channelmanager::provided_init_features(&config_101_percent), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_8 = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + inbound_node_id, + &channelmanager::provided_channel_type_features(&config_101_percent), + &channelmanager::provided_init_features(&config_101_percent), + &chan_1_open_channel_msg, + 7, + &config_101_percent, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); let chan_8_value_msat = chan_8.funding.get_value_satoshis() * 1000; assert_eq!(chan_8.context.holder_max_htlc_value_in_flight_msat, chan_8_value_msat); } #[test] fn test_configured_holder_selected_channel_reserve_satoshis() { - // Test that `OutboundV1Channel::new` and `InboundV1Channel::new` create a channel with the correct // channel reserves, when `their_channel_reserve_proportional_millionths` is configured. test_self_and_counterparty_channel_reserve(10_000_000, 0.02, 0.02); @@ -12058,45 +15096,115 @@ mod tests { test_self_and_counterparty_channel_reserve(10_000_000, 0.60, 0.50); } - fn test_self_and_counterparty_channel_reserve(channel_value_satoshis: u64, outbound_selected_channel_reserve_perc: f64, inbound_selected_channel_reserve_perc: f64) { + fn test_self_and_counterparty_channel_reserve( + channel_value_satoshis: u64, outbound_selected_channel_reserve_perc: f64, + inbound_selected_channel_reserve_perc: f64, + ) { let fee_est = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15_000 }); let logger = test_utils::TestLogger::new(); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); - let outbound_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let inbound_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - + let outbound_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let inbound_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let mut outbound_node_config = UserConfig::default(); - outbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (outbound_selected_channel_reserve_perc * 1_000_000.0) as u32; - let mut chan = OutboundV1Channel::<&TestKeysInterface>::new(&&fee_est, &&keys_provider, &&keys_provider, outbound_node_id, &channelmanager::provided_init_features(&outbound_node_config), channel_value_satoshis, 100_000, 42, &outbound_node_config, 0, 42, None, &logger).unwrap(); + outbound_node_config + .channel_handshake_config + .their_channel_reserve_proportional_millionths = + (outbound_selected_channel_reserve_perc * 1_000_000.0) as u32; + let mut chan = OutboundV1Channel::<&TestKeysInterface>::new( + &&fee_est, + &&keys_provider, + &&keys_provider, + outbound_node_id, + &channelmanager::provided_init_features(&outbound_node_config), + channel_value_satoshis, + 100_000, + 42, + &outbound_node_config, + 0, + 42, + None, + &logger, + ) + .unwrap(); - let expected_outbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.funding.get_value_satoshis() as f64 * outbound_selected_channel_reserve_perc) as u64); - assert_eq!(chan.funding.holder_selected_channel_reserve_satoshis, expected_outbound_selected_chan_reserve); + let expected_outbound_selected_chan_reserve = cmp::max( + MIN_THEIR_CHAN_RESERVE_SATOSHIS, + (chan.funding.get_value_satoshis() as f64 * outbound_selected_channel_reserve_perc) + as u64, + ); + assert_eq!( + chan.funding.holder_selected_channel_reserve_satoshis, + expected_outbound_selected_chan_reserve + ); - let chan_open_channel_msg = chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); + let chan_open_channel_msg = + chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); let mut inbound_node_config = UserConfig::default(); - inbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (inbound_selected_channel_reserve_perc * 1_000_000.0) as u32; + inbound_node_config + .channel_handshake_config + .their_channel_reserve_proportional_millionths = + (inbound_selected_channel_reserve_perc * 1_000_000.0) as u32; if outbound_selected_channel_reserve_perc + inbound_selected_channel_reserve_perc < 1.0 { - let chan_inbound_node = InboundV1Channel::<&TestKeysInterface>::new(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let chan_inbound_node = InboundV1Channel::<&TestKeysInterface>::new( + &&fee_est, + &&keys_provider, + &&keys_provider, + inbound_node_id, + &channelmanager::provided_channel_type_features(&inbound_node_config), + &channelmanager::provided_init_features(&outbound_node_config), + &chan_open_channel_msg, + 7, + &inbound_node_config, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); - let expected_inbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.funding.get_value_satoshis() as f64 * inbound_selected_channel_reserve_perc) as u64); + let expected_inbound_selected_chan_reserve = cmp::max( + MIN_THEIR_CHAN_RESERVE_SATOSHIS, + (chan.funding.get_value_satoshis() as f64 * inbound_selected_channel_reserve_perc) + as u64, + ); - assert_eq!(chan_inbound_node.funding.holder_selected_channel_reserve_satoshis, expected_inbound_selected_chan_reserve); - assert_eq!(chan_inbound_node.funding.counterparty_selected_channel_reserve_satoshis.unwrap(), expected_outbound_selected_chan_reserve); + assert_eq!( + chan_inbound_node.funding.holder_selected_channel_reserve_satoshis, + expected_inbound_selected_chan_reserve + ); + assert_eq!( + chan_inbound_node.funding.counterparty_selected_channel_reserve_satoshis.unwrap(), + expected_outbound_selected_chan_reserve + ); } else { // Channel Negotiations failed - let result = InboundV1Channel::<&TestKeysInterface>::new(&&fee_est, &&keys_provider, &&keys_provider, inbound_node_id, &channelmanager::provided_channel_type_features(&inbound_node_config), &channelmanager::provided_init_features(&outbound_node_config), &chan_open_channel_msg, 7, &inbound_node_config, 0, &&logger, /*is_0conf=*/false); + let result = InboundV1Channel::<&TestKeysInterface>::new( + &&fee_est, + &&keys_provider, + &&keys_provider, + inbound_node_id, + &channelmanager::provided_channel_type_features(&inbound_node_config), + &channelmanager::provided_init_features(&outbound_node_config), + &chan_open_channel_msg, + 7, + &inbound_node_config, + 0, + &&logger, + /*is_0conf=*/ false, + ); assert!(result.is_err()); } } #[test] fn channel_update() { - let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let logger = test_utils::TestLogger::new(); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; @@ -12106,34 +15214,94 @@ mod tests { let keys_provider = test_utils::TestKeysInterface::new(&seed, network); // Create Node A's channel pointing to Node B's pubkey - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, None, &logger).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); // Create Node B's channel by receiving Node A's open_channel message // Make sure A's dust limit is as we expect. - let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); + let open_channel_msg = node_a_chan + .get_open_channel(ChainHash::using_genesis_block(network), &&logger) + .unwrap(); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_channel_type_features(&config), + &channelmanager::provided_init_features(&config), + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); // Node B --> Node A: accept channel, explicitly setting B's dust limit. let mut accept_channel_msg = node_b_chan.accept_inbound_channel(&&logger).unwrap(); accept_channel_msg.common_fields.dust_limit_satoshis = 546; - node_a_chan.accept_channel(&accept_channel_msg, &config.channel_handshake_limits, &channelmanager::provided_init_features(&config)).unwrap(); + node_a_chan + .accept_channel( + &accept_channel_msg, + &config.channel_handshake_limits, + &channelmanager::provided_init_features(&config), + ) + .unwrap(); node_a_chan.context.holder_dust_limit_satoshis = 1560; // Node A --> Node B: funding created let output_script = node_a_chan.funding.get_funding_redeemscript(); - let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.compute_txid(), index: 0 }; - let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); - let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap(); + let tx = Transaction { + version: Version::ONE, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { + value: Amount::from_sat(10000000), + script_pubkey: output_script.clone(), + }], + }; + let funding_outpoint = OutPoint { txid: tx.compute_txid(), index: 0 }; + let funding_created_msg = node_a_chan + .get_funding_created(tx.clone(), funding_outpoint, false, &&logger) + .map_err(|_| ()) + .unwrap(); + let (_, funding_signed_msg, _) = node_b_chan + .funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger) + .map_err(|_| ()) + .unwrap(); // Node B --> Node A: funding signed - let res = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger); - let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; + let res = node_a_chan.funding_signed( + &funding_signed_msg.unwrap(), + best_block, + &&keys_provider, + &&logger, + ); + let (mut node_a_chan, _) = if let Ok(res) = res { + res + } else { + panic!(); + }; // Make sure that receiving a channel update will update the Channel as expected. let update = ChannelUpdate { @@ -12150,7 +15318,7 @@ mod tests { fee_proportional_millionths: 11, excess_data: Vec::new(), }, - signature: Signature::from(unsafe { FFISignature::new() }) + signature: Signature::from(unsafe { FFISignature::new() }), }; assert!(node_a_chan.channel_update(&update).unwrap()); @@ -12163,7 +15331,7 @@ mod tests { assert_eq!(info.fee_base_msat, 110); assert_eq!(info.fee_proportional_millionths, 11); }, - None => panic!("expected counterparty forwarding info to be Some") + None => panic!("expected counterparty forwarding info to be Some"), } assert!(!node_a_chan.channel_update(&update).unwrap()); @@ -12174,30 +15342,78 @@ mod tests { // Ensure that channel blinding points, skimmed fees, and malformed HTLCs are (de)serialized // properly. let logger = test_utils::TestLogger::new(); - let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; let best_block = BestBlock::from_network(network); let keys_provider = test_utils::TestKeysInterface::new(&seed, network); - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); let features = channelmanager::provided_init_features(&config); let mut outbound_chan = OutboundV1Channel::<&TestKeysInterface>::new( - &feeest, &&keys_provider, &&keys_provider, node_b_node_id, &features, 10000000, 100000, 42, &config, 0, 42, None, &logger - ).unwrap(); + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &features, + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); let mut inbound_chan = InboundV1Channel::<&TestKeysInterface>::new( - &feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), - &features, &outbound_chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(), 7, &config, 0, &&logger, false - ).unwrap(); - outbound_chan.accept_channel(&inbound_chan.get_accept_channel_message(&&logger).unwrap(), &config.channel_handshake_limits, &features).unwrap(); - let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: Amount::from_sat(10000000), script_pubkey: outbound_chan.funding.get_funding_redeemscript(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.compute_txid(), index: 0 }; - let funding_created = outbound_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap().unwrap(); - let mut chan = match inbound_chan.funding_created(&funding_created, best_block, &&keys_provider, &&logger) { + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_channel_type_features(&config), + &features, + &outbound_chan + .get_open_channel(ChainHash::using_genesis_block(network), &&logger) + .unwrap(), + 7, + &config, + 0, + &&logger, + false, + ) + .unwrap(); + outbound_chan + .accept_channel( + &inbound_chan.get_accept_channel_message(&&logger).unwrap(), + &config.channel_handshake_limits, + &features, + ) + .unwrap(); + let tx = Transaction { + version: Version::ONE, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { + value: Amount::from_sat(10000000), + script_pubkey: outbound_chan.funding.get_funding_redeemscript(), + }], + }; + let funding_outpoint = OutPoint { txid: tx.compute_txid(), index: 0 }; + let funding_created = outbound_chan + .get_funding_created(tx.clone(), funding_outpoint, false, &&logger) + .map_err(|_| ()) + .unwrap() + .unwrap(); + let mut chan = match inbound_chan.funding_created( + &funding_created, + best_block, + &&keys_provider, + &&logger, + ) { Ok((chan, _, _)) => chan, Err((_, e)) => panic!("{}", e), }; @@ -12205,11 +15421,15 @@ mod tests { let dummy_htlc_source = HTLCSource::OutboundRoute { path: Path { hops: vec![RouteHop { - pubkey: test_utils::pubkey(2), channel_features: ChannelFeatures::empty(), - node_features: NodeFeatures::empty(), short_channel_id: 0, fee_msat: 0, - cltv_expiry_delta: 0, maybe_announced_channel: false, + pubkey: test_utils::pubkey(2), + channel_features: ChannelFeatures::empty(), + node_features: NodeFeatures::empty(), + short_channel_id: 0, + fee_msat: 0, + cltv_expiry_delta: 0, + maybe_announced_channel: false, }], - blinded_tail: None + blinded_tail: None, }, session_priv: test_utils::privkey(42), first_hop_htlc_msat: 0, @@ -12245,8 +15465,8 @@ mod tests { onion_routing_packet: msgs::OnionPacket { version: 0, public_key: Ok(test_utils::pubkey(1)), - hop_data: [0; 20*65], - hmac: [0; 32] + hop_data: [0; 20 * 65], + hmac: [0; 32], }, skimmed_fee_msat: None, blinding_point: None, @@ -12256,12 +15476,18 @@ mod tests { htlc_id: 0, }; let dummy_holding_cell_failed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailHTLC { - htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42], attribution_data: Some(AttributionData::new()) } - }; - let dummy_holding_cell_malformed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC { - htlc_id, failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(), - sha256_of_onion: [0; 32], + htlc_id, + err_packet: msgs::OnionErrorPacket { + data: vec![42], + attribution_data: Some(AttributionData::new()), + }, }; + let dummy_holding_cell_malformed_htlc = + |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC { + htlc_id, + failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(), + sha256_of_onion: [0; 32], + }; let mut holding_cell_htlc_updates = Vec::with_capacity(12); for i in 0..12 { if i % 5 == 0 { @@ -12271,11 +15497,16 @@ mod tests { } else if i % 5 == 2 { let mut dummy_add = dummy_holding_cell_add_htlc.clone(); if let HTLCUpdateAwaitingACK::AddHTLC { - ref mut blinding_point, ref mut skimmed_fee_msat, .. - } = &mut dummy_add { + ref mut blinding_point, + ref mut skimmed_fee_msat, + .. + } = &mut dummy_add + { *blinding_point = Some(test_utils::pubkey(42 + i)); *skimmed_fee_msat = Some(42); - } else { panic!() } + } else { + panic!() + } holding_cell_htlc_updates.push(dummy_add); } else if i % 5 == 3 { holding_cell_htlc_updates.push(dummy_holding_cell_malformed_htlc(i as u64)); @@ -12288,9 +15519,12 @@ mod tests { // Encode and decode the channel and ensure that the HTLCs within are the same. let encoded_chan = chan.encode(); let mut s = crate::io::Cursor::new(&encoded_chan); - let mut reader = crate::util::ser::FixedLengthReader::new(&mut s, encoded_chan.len() as u64); + let mut reader = + crate::util::ser::FixedLengthReader::new(&mut s, encoded_chan.len() as u64); let features = channelmanager::provided_channel_type_features(&config); - let decoded_chan = FundedChannel::read(&mut reader, (&&keys_provider, &&keys_provider, &features)).unwrap(); + let decoded_chan = + FundedChannel::read(&mut reader, (&&keys_provider, &&keys_provider, &features)) + .unwrap(); assert_eq!(decoded_chan.context.pending_outbound_htlcs, pending_outbound_htlcs); assert_eq!(decoded_chan.context.holding_cell_htlc_updates, holding_cell_htlc_updates); } @@ -12300,82 +15534,186 @@ mod tests { fn outbound_commitment_test() { assert!(cfg!(not(feature = "grind_signatures"))); - use bitcoin::sighash; + use crate::ln::chan_utils::{ + ChannelPublicKeys, CounterpartyChannelTransactionParameters, + HolderCommitmentTransaction, + }; + use crate::ln::channel::HTLCOutputInCommitment; + use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint}; + use crate::sign::{ecdsa::EcdsaChannelSigner, ChannelDerivationParameters, HTLCDescriptor}; + use crate::sync::Arc; + use crate::types::payment::PaymentPreimage; + use crate::util::logger::Logger; use bitcoin::consensus::encode::serialize; - use bitcoin::sighash::EcdsaSighashType; - use bitcoin::hex::FromHex; use bitcoin::hash_types::Txid; use bitcoin::hex::DisplayHex; + use bitcoin::hex::FromHex; use bitcoin::secp256k1::Message; - use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ecdsa::EcdsaChannelSigner}; - use crate::types::payment::PaymentPreimage; - use crate::ln::channel::HTLCOutputInCommitment; - use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint}; - use crate::ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; - use crate::util::logger::Logger; - use crate::sync::Arc; + use bitcoin::sighash; + use bitcoin::sighash::EcdsaSighashType; use core::str::FromStr; // Test vectors from BOLT 3 Appendices C and F (anchors): - let feeest = TestFeeEstimator{fee_est: 15000}; - let logger : Arc = Arc::new(test_utils::TestLogger::new()); + let feeest = TestFeeEstimator { fee_est: 15000 }; + let logger: Arc = Arc::new(test_utils::TestLogger::new()); let secp_ctx = Secp256k1::new(); let signer = InMemorySigner::new( &secp_ctx, - SecretKey::from_slice(&>::from_hex("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(), - SecretKey::from_slice(&>::from_hex("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), - SecretKey::from_slice(&>::from_hex("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(), - SecretKey::from_slice(&>::from_hex("3333333333333333333333333333333333333333333333333333333333333333").unwrap()[..]).unwrap(), - SecretKey::from_slice(&>::from_hex("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(), - + SecretKey::from_slice( + &>::from_hex( + "30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749", + ) + .unwrap()[..], + ) + .unwrap(), + SecretKey::from_slice( + &>::from_hex( + "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ) + .unwrap()[..], + ) + .unwrap(), + SecretKey::from_slice( + &>::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()[..], + ) + .unwrap(), + SecretKey::from_slice( + &>::from_hex( + "3333333333333333333333333333333333333333333333333333333333333333", + ) + .unwrap()[..], + ) + .unwrap(), + SecretKey::from_slice( + &>::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()[..], + ) + .unwrap(), // These aren't set in the test vectors: - [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], + [ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + ], [0; 32], [0; 32], ); let holder_pubkeys = signer.pubkeys(None, &secp_ctx); - assert_eq!(holder_pubkeys.funding_pubkey.serialize()[..], - >::from_hex("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]); + assert_eq!( + holder_pubkeys.funding_pubkey.serialize()[..], + >::from_hex( + "023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb" + ) + .unwrap()[..] + ); let keys_provider = Keys { signer: signer.clone() }; - let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let counterparty_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut config = UserConfig::default(); config.channel_handshake_config.announce_for_forwarding = false; - let mut chan = OutboundV1Channel::<&Keys>::new(&LowerBoundedFeeEstimator::new(&feeest), &&keys_provider, &&keys_provider, counterparty_node_id, &channelmanager::provided_init_features(&config), 10_000_000, 0, 42, &config, 0, 42, None, &*logger).unwrap(); // Nothing uses their network key in this test + let mut chan = OutboundV1Channel::<&Keys>::new( + &LowerBoundedFeeEstimator::new(&feeest), + &&keys_provider, + &&keys_provider, + counterparty_node_id, + &channelmanager::provided_init_features(&config), + 10_000_000, + 0, + 42, + &config, + 0, + 42, + None, + &*logger, + ) + .unwrap(); // Nothing uses their network key in this test chan.context.holder_dust_limit_satoshis = 546; chan.funding.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel - let funding_info = OutPoint{ txid: Txid::from_str("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), index: 0 }; + let funding_info = OutPoint { + txid: Txid::from_str( + "8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be", + ) + .unwrap(), + index: 0, + }; let counterparty_pubkeys = ChannelPublicKeys { - funding_pubkey: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"), - revocation_basepoint: RevocationBasepoint::from(PublicKey::from_slice(&>::from_hex("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap()), - payment_point: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444"), - delayed_payment_basepoint: DelayedPaymentBasepoint::from(public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13")), - htlc_basepoint: HtlcBasepoint::from(public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444")) + funding_pubkey: public_from_secret_hex( + &secp_ctx, + "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13", + ), + revocation_basepoint: RevocationBasepoint::from( + PublicKey::from_slice( + &>::from_hex( + "02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27", + ) + .unwrap()[..], + ) + .unwrap(), + ), + payment_point: public_from_secret_hex( + &secp_ctx, + "4444444444444444444444444444444444444444444444444444444444444444", + ), + delayed_payment_basepoint: DelayedPaymentBasepoint::from(public_from_secret_hex( + &secp_ctx, + "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13", + )), + htlc_basepoint: HtlcBasepoint::from(public_from_secret_hex( + &secp_ctx, + "4444444444444444444444444444444444444444444444444444444444444444", + )), }; - chan.funding.channel_transaction_parameters.counterparty_parameters = Some( - CounterpartyChannelTransactionParameters { + chan.funding.channel_transaction_parameters.counterparty_parameters = + Some(CounterpartyChannelTransactionParameters { pubkeys: counterparty_pubkeys.clone(), - selected_contest_delay: 144 + selected_contest_delay: 144, }); chan.funding.channel_transaction_parameters.funding_outpoint = Some(funding_info); - assert_eq!(counterparty_pubkeys.payment_point.serialize()[..], - >::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]); + assert_eq!( + counterparty_pubkeys.payment_point.serialize()[..], + >::from_hex( + "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991" + ) + .unwrap()[..] + ); - assert_eq!(counterparty_pubkeys.funding_pubkey.serialize()[..], - >::from_hex("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]); + assert_eq!( + counterparty_pubkeys.funding_pubkey.serialize()[..], + >::from_hex( + "030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1" + ) + .unwrap()[..] + ); - assert_eq!(counterparty_pubkeys.htlc_basepoint.to_public_key().serialize()[..], - >::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]); + assert_eq!( + counterparty_pubkeys.htlc_basepoint.to_public_key().serialize()[..], + >::from_hex( + "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991" + ) + .unwrap()[..] + ); // We can't just use build_holder_transaction_keys here as the per_commitment_secret is not // derived from a commitment_seed, so instead we copy it here and call // build_commitment_transaction. - let per_commitment_secret = SecretKey::from_slice(&>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); + let per_commitment_secret = SecretKey::from_slice( + &>::from_hex( + "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", + ) + .unwrap()[..], + ) + .unwrap(); let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); macro_rules! test_commitment { @@ -12510,29 +15848,41 @@ mod tests { "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80044a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994a508b6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004830450221008266ac6db5ea71aac3c95d97b0e172ff596844851a3216eb88382a8dddfd33d2022050e240974cfd5d708708b4365574517c18e7ae535ef732a3484d43d0d82be9f701483045022100f89034eba16b2be0e5581f750a0a6309192b75cce0f202f0ee2b4ec0cc394850022076c65dc507fe42276152b7a3d90e961e678adbe966e916ecfe85e64d430e75f301475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", {}); chan.context.pending_inbound_htlcs.push({ - let mut out = InboundHTLCOutput{ + let mut out = InboundHTLCOutput { htlc_id: 0, amount_msat: 1000000, cltv_expiry: 500, payment_hash: PaymentHash([0; 32]), state: InboundHTLCState::Committed, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(), + ) + .to_byte_array(); out }); chan.context.pending_inbound_htlcs.push({ - let mut out = InboundHTLCOutput{ + let mut out = InboundHTLCOutput { htlc_id: 1, amount_msat: 2000000, cltv_expiry: 501, payment_hash: PaymentHash([0; 32]), state: InboundHTLCState::Committed, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap(), + ) + .to_byte_array(); out }); chan.context.pending_outbound_htlcs.push({ - let mut out = OutboundHTLCOutput{ + let mut out = OutboundHTLCOutput { htlc_id: 2, amount_msat: 2000000, cltv_expiry: 502, @@ -12543,11 +15893,17 @@ mod tests { blinding_point: None, send_timestamp: None, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0202020202020202020202020202020202020202020202020202020202020202", + ) + .unwrap(), + ) + .to_byte_array(); out }); chan.context.pending_outbound_htlcs.push({ - let mut out = OutboundHTLCOutput{ + let mut out = OutboundHTLCOutput { htlc_id: 3, amount_msat: 3000000, cltv_expiry: 503, @@ -12558,18 +15914,30 @@ mod tests { blinding_point: None, send_timestamp: None, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0303030303030303030303030303030303030303030303030303030303030303").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0303030303030303030303030303030303030303030303030303030303030303", + ) + .unwrap(), + ) + .to_byte_array(); out }); chan.context.pending_inbound_htlcs.push({ - let mut out = InboundHTLCOutput{ + let mut out = InboundHTLCOutput { htlc_id: 4, amount_msat: 4000000, cltv_expiry: 504, payment_hash: PaymentHash([0; 32]), state: InboundHTLCState::Committed, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0404040404040404040404040404040404040404040404040404040404040404").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0404040404040404040404040404040404040404040404040404040404040404", + ) + .unwrap(), + ) + .to_byte_array(); out }); @@ -12802,7 +16170,8 @@ mod tests { chan.context.feerate_per_kw = 2185; chan.context.holder_dust_limit_satoshis = 2001; let cached_channel_type = chan.funding.get_channel_type().clone(); - chan.funding.channel_transaction_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + chan.funding.channel_transaction_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3044022040f63a16148cf35c8d3d41827f5ae7f7c3746885bb64d4d1b895892a83812b3e02202fcf95c2bf02c466163b3fa3ced6a24926fbb4035095a96842ef516e86ba54c0", "3045022100cd8479cfe1edb1e5a1d487391e0451a469c7171e51e680183f19eb4321f20e9b02204eab7d5a6384b1b08e03baa6e4d9748dfd2b5ab2bae7e39604a0d0055bbffdd5", @@ -12823,7 +16192,8 @@ mod tests { chan.funding.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 3702; chan.context.holder_dust_limit_satoshis = 546; - chan.funding.channel_transaction_parameters.channel_type_features = cached_channel_type.clone(); + chan.funding.channel_transaction_parameters.channel_type_features = + cached_channel_type.clone(); test_commitment!("304502210092a587aeb777f869e7ff0d7898ea619ee26a3dacd1f3672b945eea600be431100220077ee9eae3528d15251f2a52b607b189820e57a6ccfac8d1af502b132ee40169", "3045022100e5efb73c32d32da2d79702299b6317de6fb24a60476e3855926d78484dd1b3c802203557cb66a42c944ef06e00bcc4da35a5bcb2f185aab0f8e403e519e1d66aaf75", @@ -12858,7 +16228,8 @@ mod tests { chan.funding.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 3687; chan.context.holder_dust_limit_satoshis = 3001; - chan.funding.channel_transaction_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + chan.funding.channel_transaction_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3045022100ad6c71569856b2d7ff42e838b4abe74a713426b37f22fa667a195a4c88908c6902202b37272b02a42dc6d9f4f82cab3eaf84ac882d9ed762859e1e75455c2c228377", "3045022100c970799bcb33f43179eb43b3378a0a61991cf2923f69b36ef12548c3df0e6d500220413dc27d2e39ee583093adfcb7799be680141738babb31cc7b0669a777a31f5d", @@ -12874,7 +16245,8 @@ mod tests { chan.funding.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 4914; chan.context.holder_dust_limit_satoshis = 546; - chan.funding.channel_transaction_parameters.channel_type_features = cached_channel_type.clone(); + chan.funding.channel_transaction_parameters.channel_type_features = + cached_channel_type.clone(); test_commitment!("3045022100b4b16d5f8cc9fc4c1aff48831e832a0d8990e133978a66e302c133550954a44d022073573ce127e2200d316f6b612803a5c0c97b8d20e1e44dbe2ac0dd2fb8c95244", "3045022100d72638bc6308b88bb6d45861aae83e5b9ff6e10986546e13bce769c70036e2620220320be7c6d66d22f30b9fcd52af66531505b1310ca3b848c19285b38d8a1a8c19", @@ -12899,7 +16271,8 @@ mod tests { chan.funding.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 4894; chan.context.holder_dust_limit_satoshis = 4001; - chan.funding.channel_transaction_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + chan.funding.channel_transaction_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3045022100e784a66b1588575801e237d35e510fd92a81ae3a4a2a1b90c031ad803d07b3f3022021bc5f16501f167607d63b681442da193eb0a76b4b7fd25c2ed4f8b28fd35b95", "30450221009f16ac85d232e4eddb3fcd750a68ebf0b58e3356eaada45d3513ede7e817bf4c02207c2b043b4e5f971261975406cb955219fa56bffe5d834a833694b5abc1ce4cfd", @@ -12909,7 +16282,8 @@ mod tests { chan.funding.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 9651180; chan.context.holder_dust_limit_satoshis = 546; - chan.funding.channel_transaction_parameters.channel_type_features = cached_channel_type.clone(); + chan.funding.channel_transaction_parameters.channel_type_features = + cached_channel_type.clone(); test_commitment!("304402200a8544eba1d216f5c5e530597665fa9bec56943c0f66d98fc3d028df52d84f7002201e45fa5c6bc3a506cc2553e7d1c0043a9811313fc39c954692c0d47cfce2bbd3", "3045022100e11b638c05c650c2f63a421d36ef8756c5ce82f2184278643520311cdf50aa200220259565fb9c8e4a87ccaf17f27a3b9ca4f20625754a0920d9c6c239d8156a11de", @@ -12927,7 +16301,8 @@ mod tests { chan.funding.value_to_self_msat = 6993000000; // 7000000000 - 7000000 chan.context.feerate_per_kw = 6216010; chan.context.holder_dust_limit_satoshis = 4001; - chan.funding.channel_transaction_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + chan.funding.channel_transaction_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("30450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf", "30450221009ad80792e3038fe6968d12ff23e6888a565c3ddd065037f357445f01675d63f3022018384915e5f1f4ae157e15debf4f49b61c8d9d2b073c7d6f97c4a68caa3ed4c1", @@ -12948,19 +16323,25 @@ mod tests { chan.context.feerate_per_kw = 253; chan.context.pending_inbound_htlcs.clear(); chan.context.pending_inbound_htlcs.push({ - let mut out = InboundHTLCOutput{ + let mut out = InboundHTLCOutput { htlc_id: 1, amount_msat: 2000000, cltv_expiry: 501, payment_hash: PaymentHash([0; 32]), state: InboundHTLCState::Committed, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap(), + ) + .to_byte_array(); out }); chan.context.pending_outbound_htlcs.clear(); chan.context.pending_outbound_htlcs.push({ - let mut out = OutboundHTLCOutput{ + let mut out = OutboundHTLCOutput { htlc_id: 6, amount_msat: 5000001, cltv_expiry: 506, @@ -12971,11 +16352,17 @@ mod tests { blinding_point: None, send_timestamp: None, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0505050505050505050505050505050505050505050505050505050505050505", + ) + .unwrap(), + ) + .to_byte_array(); out }); chan.context.pending_outbound_htlcs.push({ - let mut out = OutboundHTLCOutput{ + let mut out = OutboundHTLCOutput { htlc_id: 5, amount_msat: 5000000, cltv_expiry: 505, @@ -12986,7 +16373,13 @@ mod tests { blinding_point: None, send_timestamp: None, }; - out.payment_hash.0 = Sha256::hash(&>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array(); + out.payment_hash.0 = Sha256::hash( + &>::from_hex( + "0505050505050505050505050505050505050505050505050505050505050505", + ) + .unwrap(), + ) + .to_byte_array(); out }); @@ -13008,7 +16401,8 @@ mod tests { "020000000001014bdccf28653066a2c554cafeffdfe1e678e64a69b056684deb0c4fba909423ec02000000000000000001e1120000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220471c9f3ad92e49b13b7b8059f43ecf8f7887b0dccbb9fdb54bfe23d62a8ae332022024bd22fae0740e86a44228c35330da9526fd7306dffb2b9dc362d5e78abef7cc0147304402207157f452f2506d73c315192311893800cfb3cc235cc1185b1cfcc136b55230db022014be242dbc6c5da141fec4034e7f387f74d6ff1899453d72ba957467540e1ecb01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9142002cc93ebefbb1b73f0af055dcc27a0b504ad7688ac6868fa010000" } } ); - chan.funding.channel_transaction_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + chan.funding.channel_transaction_parameters.channel_type_features = + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); test_commitment_with_anchors!("3044022027b38dfb654c34032ffb70bb43022981652fce923cbbe3cbe7394e2ade8b34230220584195b78da6e25c2e8da6b4308d9db25b65b64975db9266163ef592abb7c725", "3045022100b4014970d9d7962853f3f85196144671d7d5d87426250f0a5fdaf9a55292e92502205360910c9abb397467e19dbd63d081deb4a3240903114c98cec0a23591b79b76", "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b80074a010000000000002200202b1b5854183c12d3316565972c4668929d314d81c5dcdbb21cb45fe8a9a8114f4a01000000000000220020e9e86e4823faa62e222ebc858a226636856158f07e69898da3b0d1af0ddb3994d007000000000000220020fe0598d74fee2205cc3672e6e6647706b4f3099713b4661b62482c3addd04a5e881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7881300000000000022002018e40f9072c44350f134bdc887bab4d9bdfc8aa468a25616c80e21757ba5dac7c0c62d0000000000220020f3394e1e619b0eca1f91be2fb5ab4dfc59ba5b84ebe014ad1d43a564d012994aad9c6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100b4014970d9d7962853f3f85196144671d7d5d87426250f0a5fdaf9a55292e92502205360910c9abb397467e19dbd63d081deb4a3240903114c98cec0a23591b79b7601473044022027b38dfb654c34032ffb70bb43022981652fce923cbbe3cbe7394e2ade8b34230220584195b78da6e25c2e8da6b4308d9db25b65b64975db9266163ef592abb7c72501475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", { @@ -13033,23 +16427,53 @@ mod tests { // Test vectors from BOLT 3 Appendix D: let mut seed = [0; 32]; - seed[0..32].clone_from_slice(&>::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(&seed, 281474976710655), - >::from_hex("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()[..]); + seed[0..32].clone_from_slice( + &>::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(), + ); + assert_eq!( + chan_utils::build_commitment_secret(&seed, 281474976710655), + >::from_hex("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148") + .unwrap()[..] + ); - seed[0..32].clone_from_slice(&>::from_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(&seed, 281474976710655), - >::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()[..]); + seed[0..32].clone_from_slice( + &>::from_hex( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + ) + .unwrap(), + ); + assert_eq!( + chan_utils::build_commitment_secret(&seed, 281474976710655), + >::from_hex("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc") + .unwrap()[..] + ); - assert_eq!(chan_utils::build_commitment_secret(&seed, 0xaaaaaaaaaaa), - >::from_hex("56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528").unwrap()[..]); + assert_eq!( + chan_utils::build_commitment_secret(&seed, 0xaaaaaaaaaaa), + >::from_hex("56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528") + .unwrap()[..] + ); - assert_eq!(chan_utils::build_commitment_secret(&seed, 0x555555555555), - >::from_hex("9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31").unwrap()[..]); + assert_eq!( + chan_utils::build_commitment_secret(&seed, 0x555555555555), + >::from_hex("9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31") + .unwrap()[..] + ); - seed[0..32].clone_from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()); - assert_eq!(chan_utils::build_commitment_secret(&seed, 1), - >::from_hex("915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c").unwrap()[..]); + seed[0..32].clone_from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap(), + ); + assert_eq!( + chan_utils::build_commitment_secret(&seed, 1), + >::from_hex("915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c") + .unwrap()[..] + ); } #[test] @@ -13057,48 +16481,132 @@ mod tests { // Test vectors from BOLT 3 Appendix E: let secp_ctx = Secp256k1::new(); - let base_secret = SecretKey::from_slice(&>::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap(); - let per_commitment_secret = SecretKey::from_slice(&>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); + let base_secret = SecretKey::from_slice( + &>::from_hex( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + ) + .unwrap()[..], + ) + .unwrap(); + let per_commitment_secret = SecretKey::from_slice( + &>::from_hex( + "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", + ) + .unwrap()[..], + ) + .unwrap(); let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret); - assert_eq!(base_point.serialize()[..], >::from_hex("036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2").unwrap()[..]); + assert_eq!( + base_point.serialize()[..], + >::from_hex( + "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2" + ) + .unwrap()[..] + ); let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); - assert_eq!(per_commitment_point.serialize()[..], >::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]); + assert_eq!( + per_commitment_point.serialize()[..], + >::from_hex( + "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" + ) + .unwrap()[..] + ); - assert_eq!(chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &base_secret), - SecretKey::from_slice(&>::from_hex("cbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f").unwrap()[..]).unwrap()); + assert_eq!( + chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &base_secret), + SecretKey::from_slice( + &>::from_hex( + "cbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f" + ) + .unwrap()[..] + ) + .unwrap() + ); - assert_eq!(RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(base_point), &per_commitment_point).to_public_key().serialize()[..], - >::from_hex("02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0").unwrap()[..]); + assert_eq!( + RevocationKey::from_basepoint( + &secp_ctx, + &RevocationBasepoint::from(base_point), + &per_commitment_point + ) + .to_public_key() + .serialize()[..], + >::from_hex( + "02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0" + ) + .unwrap()[..] + ); - assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret), - SecretKey::from_slice(&>::from_hex("d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110").unwrap()[..]).unwrap()); + assert_eq!( + chan_utils::derive_private_revocation_key( + &secp_ctx, + &per_commitment_secret, + &base_secret + ), + SecretKey::from_slice( + &>::from_hex( + "d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110" + ) + .unwrap()[..] + ) + .unwrap() + ); } #[test] fn test_zero_conf_channel_type_support() { - let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); let logger = test_utils::TestLogger::new(); - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, - node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, None, &logger).unwrap(); + let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key(); channel_type_features.set_zero_conf_required(); - let mut open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); + let mut open_channel_msg = node_a_chan + .get_open_channel(ChainHash::using_genesis_block(network), &&logger) + .unwrap(); open_channel_msg.common_fields.channel_type = Some(channel_type_features); - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let res = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, - node_b_node_id, &channelmanager::provided_channel_type_features(&config), - &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let res = InboundV1Channel::<&TestKeysInterface>::new( + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &channelmanager::provided_channel_type_features(&config), + &channelmanager::provided_init_features(&config), + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, + ); assert!(res.is_ok()); } @@ -13107,13 +16615,15 @@ mod tests { // Tests that if both sides support and negotiate `anchors_zero_fee_htlc_tx`, it is the // resulting `channel_type`. let secp_ctx = Secp256k1::new(); - let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network); let logger = test_utils::TestLogger::new(); - let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap()); - let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap()); + let node_id_a = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap()); + let node_id_b = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap()); let mut config = UserConfig::default(); config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; @@ -13121,10 +16631,21 @@ mod tests { // It is not enough for just the initiator to signal `option_anchors_zero_fee_htlc_tx`, both // need to signal it. let channel_a = OutboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, - &channelmanager::provided_init_features(&UserConfig::default()), 10000000, 100000, 42, - &config, 0, 42, None, &logger - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&UserConfig::default()), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); assert!(!channel_a.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx()); let mut expected_channel_type = ChannelTypeFeatures::empty(); @@ -13132,17 +16653,39 @@ mod tests { expected_channel_type.set_anchors_zero_fee_htlc_tx_required(); let mut channel_a = OutboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, - &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, - None, &logger - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); - let open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); + let open_channel_msg = + channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); let channel_b = InboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, - &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), - &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_a, + &channelmanager::provided_channel_type_features(&config), + &channelmanager::provided_init_features(&config), + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); assert_eq!(channel_a.funding.get_channel_type(), &expected_channel_type); assert_eq!(channel_b.funding.get_channel_type(), &expected_channel_type); @@ -13153,13 +16696,15 @@ mod tests { // Tests that if `option_anchors` is being negotiated implicitly through the intersection of // each side's `InitFeatures`, it is rejected. let secp_ctx = Secp256k1::new(); - let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network); let logger = test_utils::TestLogger::new(); - let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap()); - let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap()); + let node_id_a = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap()); + let node_id_b = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap()); let config = UserConfig::default(); @@ -13167,24 +16712,46 @@ mod tests { let static_remote_key_required: u64 = 1 << 12; let simple_anchors_required: u64 = 1 << 20; let raw_init_features = static_remote_key_required | simple_anchors_required; - let init_features_with_simple_anchors = InitFeatures::from_le_bytes(raw_init_features.to_le_bytes().to_vec()); + let init_features_with_simple_anchors = + InitFeatures::from_le_bytes(raw_init_features.to_le_bytes().to_vec()); let mut channel_a = OutboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, - &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, - None, &logger - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); // Set `channel_type` to `None` to force the implicit feature negotiation. - let mut open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); + let mut open_channel_msg = + channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); open_channel_msg.common_fields.channel_type = None; // Since A supports both `static_remote_key` and `option_anchors`, but B only accepts // `static_remote_key`, it will fail the channel. let channel_b = InboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, - &channelmanager::provided_channel_type_features(&config), &init_features_with_simple_anchors, - &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_a, + &channelmanager::provided_channel_type_features(&config), + &init_features_with_simple_anchors, + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, ); assert!(channel_b.is_err()); } @@ -13194,13 +16761,15 @@ mod tests { // Tests that if `option_anchors` is being negotiated through the `channel_type` feature, // it is rejected. let secp_ctx = Secp256k1::new(); - let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let fee_estimator = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&[42; 32], network); let logger = test_utils::TestLogger::new(); - let node_id_a = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap()); - let node_id_b = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap()); + let node_id_a = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap()); + let node_id_b = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap()); let config = UserConfig::default(); @@ -13208,8 +16777,10 @@ mod tests { let static_remote_key_required: u64 = 1 << 12; let simple_anchors_required: u64 = 1 << 20; let simple_anchors_raw_features = static_remote_key_required | simple_anchors_required; - let simple_anchors_init = InitFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec()); - let simple_anchors_channel_type = ChannelTypeFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec()); + let simple_anchors_init = + InitFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec()); + let simple_anchors_channel_type = + ChannelTypeFeatures::from_le_bytes(simple_anchors_raw_features.to_le_bytes().to_vec()); assert!(!simple_anchors_init.requires_unknown_bits()); assert!(!simple_anchors_channel_type.requires_unknown_bits()); @@ -13217,18 +16788,39 @@ mod tests { // the original `option_anchors` feature (non zero fee htlc tx). This should be rejected by // B as it's not supported by LDK. let mut channel_a = OutboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, - &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42, - None, &logger - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); - let mut open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); + let mut open_channel_msg = + channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); open_channel_msg.common_fields.channel_type = Some(simple_anchors_channel_type.clone()); let res = InboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, - &channelmanager::provided_channel_type_features(&config), &simple_anchors_init, - &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_a, + &channelmanager::provided_channel_type_features(&config), + &simple_anchors_init, + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, ); assert!(res.is_err()); @@ -13237,30 +16829,55 @@ mod tests { // original `option_anchors` feature, which should be rejected by A as it's not supported by // LDK. let mut channel_a = OutboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_b, &simple_anchors_init, - 10000000, 100000, 42, &config, 0, 42, None, &logger - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &simple_anchors_init, + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + &logger, + ) + .unwrap(); - let open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); + let open_channel_msg = + channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); let mut channel_b = InboundV1Channel::<&TestKeysInterface>::new( - &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, - &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), - &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_a, + &channelmanager::provided_channel_type_features(&config), + &channelmanager::provided_init_features(&config), + &open_channel_msg, + 7, + &config, + 0, + &&logger, + /*is_0conf=*/ false, + ) + .unwrap(); let mut accept_channel_msg = channel_b.get_accept_channel_message(&&logger).unwrap(); accept_channel_msg.common_fields.channel_type = Some(simple_anchors_channel_type.clone()); let res = channel_a.accept_channel( - &accept_channel_msg, &config.channel_handshake_limits, &simple_anchors_init + &accept_channel_msg, + &config.channel_handshake_limits, + &simple_anchors_init, ); assert!(res.is_err()); } #[test] fn test_waiting_for_batch() { - let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000}); + let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 15000 }); let logger = test_utils::TestLogger::new(); let secp_ctx = Secp256k1::new(); let seed = [42; 32]; @@ -13275,7 +16892,8 @@ mod tests { config.channel_handshake_limits.trust_own_funding_0conf = true; // Create a channel from node a to node b that will be part of batch funding. - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new( &feeest, &&keys_provider, @@ -13289,11 +16907,15 @@ mod tests { 0, 42, None, - &logger - ).unwrap(); + &logger, + ) + .unwrap(); - let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); - let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); + let open_channel_msg = node_a_chan + .get_open_channel(ChainHash::using_genesis_block(network), &&logger) + .unwrap(); + let node_b_node_id = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new( &feeest, &&keys_provider, @@ -13306,15 +16928,18 @@ mod tests { &config, 0, &&logger, - true, // Allow node b to send a 0conf channel_ready. - ).unwrap(); + true, // Allow node b to send a 0conf channel_ready. + ) + .unwrap(); let accept_channel_msg = node_b_chan.accept_inbound_channel(&&logger).unwrap(); - node_a_chan.accept_channel( - &accept_channel_msg, - &config.channel_handshake_limits, - &channelmanager::provided_init_features(&config), - ).unwrap(); + node_a_chan + .accept_channel( + &accept_channel_msg, + &config.channel_handshake_limits, + &channelmanager::provided_init_features(&config), + ) + .unwrap(); // Fund the channel with a batch funding transaction. let output_script = node_a_chan.funding.get_funding_redeemscript(); @@ -13323,23 +16948,22 @@ mod tests { lock_time: LockTime::ZERO, input: Vec::new(), output: vec![ + TxOut { value: Amount::from_sat(10000000), script_pubkey: output_script.clone() }, TxOut { - value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), + value: Amount::from_sat(10000000), + script_pubkey: Builder::new().into_script(), }, - TxOut { - value: Amount::from_sat(10000000), script_pubkey: Builder::new().into_script(), - }, - ]}; - let funding_outpoint = OutPoint{ txid: tx.compute_txid(), index: 0 }; - let funding_created_msg = node_a_chan.get_funding_created( - tx.clone(), funding_outpoint, true, &&logger, - ).map_err(|_| ()).unwrap(); - let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created( - &funding_created_msg.unwrap(), - best_block, - &&keys_provider, - &&logger, - ).map_err(|_| ()).unwrap(); + ], + }; + let funding_outpoint = OutPoint { txid: tx.compute_txid(), index: 0 }; + let funding_created_msg = node_a_chan + .get_funding_created(tx.clone(), funding_outpoint, true, &&logger) + .map_err(|_| ()) + .unwrap(); + let (mut node_b_chan, funding_signed_msg, _) = node_b_chan + .funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger) + .map_err(|_| ()) + .unwrap(); let node_b_updates = node_b_chan.monitor_updating_restored( &&logger, &&keys_provider, @@ -13351,9 +16975,16 @@ mod tests { // Receive funding_signed, but the channel will be configured to hold sending channel_ready and // broadcasting the funding transaction until the batch is ready. let res = node_a_chan.funding_signed( - &funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger, + &funding_signed_msg.unwrap(), + best_block, + &&keys_provider, + &&logger, ); - let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); }; + let (mut node_a_chan, _) = if let Ok(res) = res { + res + } else { + panic!(); + }; let node_a_updates = node_a_chan.monitor_updating_restored( &&logger, &&keys_provider, @@ -13365,25 +16996,36 @@ mod tests { // as the funding transaction depends on all channels in the batch becoming ready. assert!(node_a_updates.channel_ready.is_none()); assert!(node_a_updates.funding_broadcastable.is_none()); - assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)); + assert_eq!( + node_a_chan.context.channel_state, + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) + ); // It is possible to receive a 0conf channel_ready from the remote node. - node_a_chan.channel_ready( - &node_b_updates.channel_ready.unwrap(), - &&keys_provider, - chain_hash, - &config, - &best_block, - &&logger, - ).unwrap(); + node_a_chan + .channel_ready( + &node_b_updates.channel_ready.unwrap(), + &&keys_provider, + chain_hash, + &config, + &best_block, + &&logger, + ) + .unwrap(); assert_eq!( node_a_chan.context.channel_state, - ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH | AwaitingChannelReadyFlags::THEIR_CHANNEL_READY) + ChannelState::AwaitingChannelReady( + AwaitingChannelReadyFlags::WAITING_FOR_BATCH + | AwaitingChannelReadyFlags::THEIR_CHANNEL_READY + ) ); // Clear the ChannelState::WaitingForBatch only when called by ChannelManager. node_a_chan.set_batch_ready(); - assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY)); + assert_eq!( + node_a_chan.context.channel_state, + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY) + ); assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some()); } @@ -13393,44 +17035,34 @@ mod tests { use bitcoin::Weight; // 2 inputs with weight 300, initiator, 2000 sat/kw feerate - assert_eq!( - estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 2000), - 1668 - ); + assert_eq!(estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 2000), 1668); // higher feerate - assert_eq!( - estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 3000), - 2502 - ); + assert_eq!(estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 3000), 2502); // only 1 input - assert_eq!( - estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(300), 2000), - 1348 - ); + assert_eq!(estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(300), 2000), 1348); // 0 input weight - assert_eq!( - estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(0), 2000), - 748 - ); + assert_eq!(estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(0), 2000), 748); // not initiator - assert_eq!( - estimate_v2_funding_transaction_fee(false, 1, Weight::from_wu(0), 2000), - 320 - ); + assert_eq!(estimate_v2_funding_transaction_fee(false, 1, Weight::from_wu(0), 2000), 320); } #[cfg(splicing)] fn funding_input_sats(input_value_sats: u64) -> (TxIn, Transaction, Weight) { use crate::sign::P2WPKH_WITNESS_WEIGHT; - let input_1_prev_out = TxOut { value: Amount::from_sat(input_value_sats), script_pubkey: ScriptBuf::default() }; + let input_1_prev_out = TxOut { + value: Amount::from_sat(input_value_sats), + script_pubkey: ScriptBuf::default(), + }; let input_1_prev_tx = Transaction { - input: vec![], output: vec![input_1_prev_out], - version: Version::TWO, lock_time: bitcoin::absolute::LockTime::ZERO, + input: vec![], + output: vec![input_1_prev_out], + version: Version::TWO, + lock_time: bitcoin::absolute::LockTime::ZERO, }; let input_1_txin = TxIn { previous_output: bitcoin::OutPoint { txid: input_1_prev_tx.compute_txid(), vout: 0 }, @@ -13448,14 +17080,12 @@ mod tests { assert_eq!( check_v2_funding_inputs_sufficient( 220_000, - &[ - funding_input_sats(200_000), - funding_input_sats(100_000), - ], + &[funding_input_sats(200_000), funding_input_sats(100_000),], true, true, 2000, - ).unwrap(), + ) + .unwrap(), 2268, ); @@ -13463,9 +17093,7 @@ mod tests { { let res = check_v2_funding_inputs_sufficient( 220_000, - &[ - funding_input_sats(100_000), - ], + &[funding_input_sats(100_000)], true, true, 2000, @@ -13482,14 +17110,12 @@ mod tests { assert_eq!( check_v2_funding_inputs_sufficient( (300_000 - expected_fee - 20) as i64, - &[ - funding_input_sats(200_000), - funding_input_sats(100_000), - ], + &[funding_input_sats(200_000), funding_input_sats(100_000),], true, true, 2000, - ).unwrap(), + ) + .unwrap(), expected_fee, ); } @@ -13498,10 +17124,7 @@ mod tests { { let res = check_v2_funding_inputs_sufficient( 298032, - &[ - funding_input_sats(200_000), - funding_input_sats(100_000), - ], + &[funding_input_sats(200_000), funding_input_sats(100_000)], true, true, 2200, @@ -13518,14 +17141,12 @@ mod tests { assert_eq!( check_v2_funding_inputs_sufficient( (300_000 - expected_fee - 20) as i64, - &[ - funding_input_sats(200_000), - funding_input_sats(100_000), - ], + &[funding_input_sats(200_000), funding_input_sats(100_000),], false, false, 2000, - ).unwrap(), + ) + .unwrap(), expected_fee, ); } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 363f2ffdb65..d2863d98bfd 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -18,54 +18,78 @@ //! imply it needs to fail HTLCs/payments/channels it manages). use bitcoin::block::Header; -use bitcoin::transaction::Transaction; use bitcoin::constants::ChainHash; use bitcoin::key::constants::SECRET_KEY_SIZE; use bitcoin::network::Network; +use bitcoin::transaction::Transaction; -use bitcoin::hashes::{Hash, HashEngine, HmacEngine}; +use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::hashes::hmac::Hmac; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hash_types::{BlockHash, Txid}; +use bitcoin::hashes::{Hash, HashEngine, HmacEngine}; -use bitcoin::secp256k1::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::{secp256k1, Sequence}; #[cfg(splicing)] use bitcoin::{TxIn, Weight}; -use crate::events::FundingInfo; use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, OffersContext}; -use crate::blinded_path::NodeIdLookUp; use crate::blinded_path::message::{BlindedMessagePath, MessageForwardNode}; -use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentPath, Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, UnauthenticatedReceiveTlvs}; +use crate::blinded_path::payment::{ + AsyncBolt12OfferContext, BlindedPaymentPath, Bolt12OfferContext, Bolt12RefundContext, + PaymentConstraints, PaymentContext, UnauthenticatedReceiveTlvs, +}; +use crate::blinded_path::NodeIdLookUp; use crate::chain; -use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock}; -use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator}; -use crate::chain::channelmonitor::{Balance, ChannelMonitor, ChannelMonitorUpdate, WithChannelMonitor, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER, MAX_BLOCKS_FOR_CONF, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent}; +use crate::chain::chaininterface::{ + BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator, +}; +use crate::chain::channelmonitor::{ + Balance, ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, MonitorEvent, + WithChannelMonitor, ANTI_REORG_DELAY, CLTV_CLAIM_BUFFER, HTLC_FAIL_BACK_BUFFER, + LATENCY_GRACE_PERIOD_BLOCKS, MAX_BLOCKS_FOR_CONF, +}; use crate::chain::transaction::{OutPoint, TransactionData}; -use crate::events::{self, Event, EventHandler, EventsProvider, InboundChannelFunds, ClosureReason, HTLCDestination, PaymentFailureReason, ReplayEvent}; +use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Watch}; +use crate::events::FundingInfo; +use crate::events::{ + self, ClosureReason, Event, EventHandler, EventsProvider, HTLCDestination, InboundChannelFunds, + PaymentFailureReason, ReplayEvent, +}; // Since this struct is returned in `list_channels` methods, expose it here in case users want to // construct one themselves. -use crate::ln::inbound_payment; -use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; -use crate::ln::channel::{self, Channel, ChannelError, ChannelUpdateStatus, FundedChannel, ShutdownResult, UpdateFulfillCommitFetch, OutboundV1Channel, ReconnectionMsg, InboundV1Channel, WithChannelContext}; use crate::ln::channel::PendingV2Channel; +use crate::ln::channel::{ + self, Channel, ChannelError, ChannelUpdateStatus, FundedChannel, InboundV1Channel, + OutboundV1Channel, ReconnectionMsg, ShutdownResult, UpdateFulfillCommitFetch, + WithChannelContext, +}; use crate::ln::channel_state::ChannelDetails; -use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; -#[cfg(any(feature = "_test_utils", test))] -use crate::types::features::Bolt11InvoiceFeatures; -use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, Payee, PaymentParameters, RouteParameters, RouteParametersConfig, Router, FixedRouter, Route}; -use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, HopConnector, InboundHTLCErr, NextPacketDetails, invalid_payment_err_data}; +use crate::ln::inbound_payment; use crate::ln::msgs; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, CommitmentUpdate, DecodeError, LightningError, + MessageSendEvent, +}; +use crate::ln::onion_payment::{ + check_incoming_htlc_cltv, create_fwd_pending_htlc_info, create_recv_pending_htlc_info, + decode_incoming_update_add_htlc_onion, invalid_payment_err_data, HopConnector, InboundHTLCErr, + NextPacketDetails, +}; use crate::ln::onion_utils::{self}; use crate::ln::onion_utils::{HTLCFailReason, LocalHTLCFailureReason}; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, CommitmentUpdate, DecodeError, LightningError, MessageSendEvent}; #[cfg(test)] use crate::ln::outbound_payment; -use crate::ln::outbound_payment::{Bolt11PaymentError, OutboundPayments, PendingOutboundPayment, RetryableInvoiceRequest, SendAlongPathArgs, StaleExpiration}; -use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice}; +use crate::ln::outbound_payment::{ + Bolt11PaymentError, OutboundPayments, PendingOutboundPayment, RetryableInvoiceRequest, + SendAlongPathArgs, StaleExpiration, +}; +use crate::ln::types::ChannelId; +use crate::offers::invoice::{ + Bolt12Invoice, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, + UnsignedBolt12Invoice, DEFAULT_RELATIVE_EXPIRY, +}; use crate::offers::invoice_error::InvoiceError; use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestBuilder}; use crate::offers::nonce::Nonce; @@ -73,37 +97,60 @@ use crate::offers::offer::{Offer, OfferBuilder}; use crate::offers::parse::Bolt12SemanticError; use crate::offers::refund::{Refund, RefundBuilder}; use crate::offers::signer; -use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler}; +use crate::onion_message::async_payments::{ + AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc, +}; use crate::onion_message::dns_resolution::HumanReadableName; -use crate::onion_message::messenger::{Destination, MessageRouter, Responder, ResponseInstruction, MessageSendInstructions}; +use crate::onion_message::messenger::{ + Destination, MessageRouter, MessageSendInstructions, Responder, ResponseInstruction, +}; use crate::onion_message::offers::{OffersMessage, OffersMessageHandler}; use crate::onion_message::packet::OnionMessageContents; -use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; +use crate::routing::router::{ + BlindedTail, FixedRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, + RouteParameters, RouteParametersConfig, Router, +}; use crate::sign::ecdsa::EcdsaChannelSigner; -use crate::util::config::{ChannelConfig, ChannelConfigUpdate, ChannelConfigOverrides, UserConfig}; -use crate::util::wakers::{Future, Notifier}; +use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; +#[cfg(any(feature = "_test_utils", test))] +use crate::types::features::Bolt11InvoiceFeatures; +use crate::types::features::{ + Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures, +}; +use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; +use crate::util::config::{ChannelConfig, ChannelConfigOverrides, ChannelConfigUpdate, UserConfig}; +use crate::util::errors::APIError; +use crate::util::logger::{Level, Logger, WithContext}; use crate::util::scid_utils::fake_scid; +use crate::util::ser::{ + BigSize, FixedLengthReader, LengthReadable, MaybeReadable, Readable, ReadableArgs, VecWriter, + Writeable, Writer, +}; use crate::util::string::UntrustedString; -use crate::util::ser::{BigSize, FixedLengthReader, LengthReadable, Readable, ReadableArgs, MaybeReadable, Writeable, Writer, VecWriter}; -use crate::util::logger::{Level, Logger, WithContext}; -use crate::util::errors::APIError; +use crate::util::wakers::{Future, Notifier}; -#[cfg(async_payments)] use { +#[cfg(async_payments)] +use { crate::offers::offer::Amount, - crate::offers::static_invoice::{DEFAULT_RELATIVE_EXPIRY as STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY, StaticInvoice, StaticInvoiceBuilder}, + crate::offers::static_invoice::{ + StaticInvoice, StaticInvoiceBuilder, + DEFAULT_RELATIVE_EXPIRY as STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY, + }, }; #[cfg(feature = "dnssec")] use crate::blinded_path::message::DNSResolverContext; #[cfg(feature = "dnssec")] -use crate::onion_message::dns_resolution::{DNSResolverMessage, DNSResolverMessageHandler, DNSSECQuery, DNSSECProof, OMNameResolver}; +use crate::onion_message::dns_resolution::{ + DNSResolverMessage, DNSResolverMessageHandler, DNSSECProof, DNSSECQuery, OMNameResolver, +}; #[cfg(not(c_bindings))] use { crate::offers::offer::DerivedMetadata, crate::onion_message::messenger::DefaultMessageRouter, - crate::routing::router::DefaultRouter, crate::routing::gossip::NetworkGraph, + crate::routing::router::DefaultRouter, crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters}, crate::sign::KeysManager, }; @@ -113,25 +160,30 @@ use { crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder, }; -use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, CreationError, Currency, Description, InvoiceBuilder as Bolt11InvoiceBuilder, SignOrCreationError, DEFAULT_EXPIRY_TIME}; +use lightning_invoice::{ + Bolt11Invoice, Bolt11InvoiceDescription, CreationError, Currency, Description, + InvoiceBuilder as Bolt11InvoiceBuilder, SignOrCreationError, DEFAULT_EXPIRY_TIME, +}; use alloc::collections::{btree_map, BTreeMap}; use crate::io; +use crate::io::Read; use crate::prelude::*; -use core::{cmp, mem}; +use crate::sync::{Arc, FairRwLock, LockHeldState, LockTestExt, Mutex, RwLock, RwLockReadGuard}; +use bitcoin::hex::impl_fmt_traits; use core::borrow::Borrow; use core::cell::RefCell; -use crate::io::Read; -use crate::sync::{Arc, Mutex, RwLock, RwLockReadGuard, FairRwLock, LockTestExt, LockHeldState}; -use core::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; -use core::time::Duration; use core::ops::Deref; -use bitcoin::hex::impl_fmt_traits; +use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use core::time::Duration; +use core::{cmp, mem}; // Re-export this for use in the public API. -pub use crate::ln::outbound_payment::{Bolt12PaymentError, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields}; #[cfg(any(test, feature = "_externalize_tests"))] pub(crate) use crate::ln::outbound_payment::PaymentSendFailure; +pub use crate::ln::outbound_payment::{ + Bolt12PaymentError, ProbeSendFailure, RecipientOnionFields, Retry, RetryableSendFailure, +}; use crate::ln::script::ShutdownScript; // We hold various information about HTLC relay in the HTLC objects in Channel itself: @@ -289,9 +341,15 @@ impl PendingHTLCRouting { fn blinded_failure(&self) -> Option { match self { Self::Forward { blinded: Some(BlindedForward { failure, .. }), .. } => Some(*failure), - Self::TrampolineForward { blinded: Some(BlindedForward { failure, .. }), .. } => Some(*failure), - Self::Receive { requires_blinded_error: true, .. } => Some(BlindedFailure::FromBlindedNode), - Self::ReceiveKeysend { requires_blinded_error: true, .. } => Some(BlindedFailure::FromBlindedNode), + Self::TrampolineForward { blinded: Some(BlindedForward { failure, .. }), .. } => { + Some(*failure) + }, + Self::Receive { requires_blinded_error: true, .. } => { + Some(BlindedFailure::FromBlindedNode) + }, + Self::ReceiveKeysend { requires_blinded_error: true, .. } => { + Some(BlindedFailure::FromBlindedNode) + }, _ => None, } } @@ -385,15 +443,8 @@ pub(super) struct PendingAddHTLCInfo { #[cfg_attr(test, derive(Clone, Debug, PartialEq))] pub(super) enum HTLCForwardInfo { AddHTLC(PendingAddHTLCInfo), - FailHTLC { - htlc_id: u64, - err_packet: msgs::OnionErrorPacket, - }, - FailMalformedHTLC { - htlc_id: u64, - failure_code: u16, - sha256_of_onion: [u8; 32], - }, + FailHTLC { htlc_id: u64, err_packet: msgs::OnionErrorPacket }, + FailMalformedHTLC { htlc_id: u64, failure_code: u16, sha256_of_onion: [u8; 32] }, } /// Whether this blinded HTLC is being failed backwards by the introduction node or a blinded node, @@ -461,9 +512,8 @@ impl PartialOrd for ClaimableHTLC { } impl Ord for ClaimableHTLC { fn cmp(&self, other: &ClaimableHTLC) -> cmp::Ordering { - let res = (self.prev_hop.channel_id, self.prev_hop.htlc_id).cmp( - &(other.prev_hop.channel_id, other.prev_hop.htlc_id) - ); + let res = (self.prev_hop.channel_id, self.prev_hop.htlc_id) + .cmp(&(other.prev_hop.channel_id, other.prev_hop.htlc_id)); if res.is_eq() { debug_assert!(self == other, "ClaimableHTLCs from the same source should be identical"); } @@ -566,7 +616,9 @@ impl Verification for PaymentId { } impl PaymentId { - fn for_inbound_from_htlcs>(key: &[u8; 32], htlcs: I) -> PaymentId { + fn for_inbound_from_htlcs>( + key: &[u8; 32], htlcs: I, + ) -> PaymentId { let mut prev_pair = None; let mut hasher = HmacEngine::new(key); for (channel_id, htlc_id) in htlcs { @@ -638,8 +690,9 @@ impl SentHTLCId { short_channel_id: hop_data.short_channel_id, htlc_id: hop_data.htlc_id, }, - HTLCSource::OutboundRoute { session_priv, .. } => - Self::OutboundRoute { session_priv: session_priv.secret_bytes() }, + HTLCSource::OutboundRoute { session_priv, .. } => { + Self::OutboundRoute { session_priv: session_priv.secret_bytes() } + }, } } } @@ -728,7 +781,9 @@ impl HTLCSource { /// Checks whether this HTLCSource could possibly match the given HTLC output in a commitment /// transaction. Useful to ensure different datastructures match up. - pub(crate) fn possibly_matches_output(&self, htlc: &super::chan_utils::HTLCOutputInCommitment) -> bool { + pub(crate) fn possibly_matches_output( + &self, htlc: &super::chan_utils::HTLCOutputInCommitment, + ) -> bool { if let HTLCSource::OutboundRoute { first_hop_htlc_msat, .. } = self { *first_hop_htlc_msat == htlc.amount_msat } else { @@ -777,7 +832,9 @@ impl Into for FailureCode { match self { FailureCode::TemporaryNodeFailure => LocalHTLCFailureReason::TemporaryNodeFailure, FailureCode::RequiredNodeFeatureMissing => LocalHTLCFailureReason::RequiredNodeFeature, - FailureCode::IncorrectOrUnknownPaymentDetails => LocalHTLCFailureReason::IncorrectPaymentDetails, + FailureCode::IncorrectOrUnknownPaymentDetails => { + LocalHTLCFailureReason::IncorrectPaymentDetails + }, FailureCode::InvalidOnionPayload(_) => LocalHTLCFailureReason::InvalidOnionPayload, } } @@ -800,10 +857,7 @@ impl MsgHandleErrInternal { err: LightningError { err: err.clone(), action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { - channel_id, - data: err - }, + msg: msgs::ErrorMessage { channel_id, data: err }, }, }, closes_channel: false, @@ -815,7 +869,10 @@ impl MsgHandleErrInternal { Self { err, closes_channel: false, shutdown_finish: None } } #[inline] - fn from_finish_shutdown(err: String, channel_id: ChannelId, shutdown_res: ShutdownResult, channel_update: Option) -> Self { + fn from_finish_shutdown( + err: String, channel_id: ChannelId, shutdown_res: ShutdownResult, + channel_update: Option, + ) -> Self { let err_msg = msgs::ErrorMessage { channel_id, data: err.clone() }; let action = if shutdown_res.monitor_update.is_some() { // We have a closing `ChannelMonitorUpdate`, which means the channel was funded and we @@ -835,36 +892,26 @@ impl MsgHandleErrInternal { fn from_chan_no_close(err: ChannelError, channel_id: ChannelId) -> Self { Self { err: match err { - ChannelError::Warn(msg) => LightningError { + ChannelError::Warn(msg) => LightningError { err: msg.clone(), action: msgs::ErrorAction::SendWarningMessage { - msg: msgs::WarningMessage { - channel_id, - data: msg - }, + msg: msgs::WarningMessage { channel_id, data: msg }, log_level: Level::Warn, }, }, - ChannelError::WarnAndDisconnect(msg) => LightningError { + ChannelError::WarnAndDisconnect(msg) => LightningError { err: msg.clone(), action: msgs::ErrorAction::DisconnectPeerWithWarning { - msg: msgs::WarningMessage { - channel_id, - data: msg - }, + msg: msgs::WarningMessage { channel_id, data: msg }, }, }, - ChannelError::Ignore(msg) => LightningError { - err: msg, - action: msgs::ErrorAction::IgnoreError, + ChannelError::Ignore(msg) => { + LightningError { err: msg, action: msgs::ErrorAction::IgnoreError } }, ChannelError::Close((msg, _)) | ChannelError::SendError(msg) => LightningError { err: msg.clone(), action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { - channel_id, - data: msg - }, + msg: msgs::ErrorMessage { channel_id, data: msg }, }, }, }, @@ -927,7 +974,7 @@ impl ClaimablePayment { fn inbound_payment_id(&self, secret: &[u8; 32]) -> PaymentId { PaymentId::for_inbound_from_htlcs( secret, - self.htlcs.iter().map(|htlc| (htlc.prev_hop.channel_id, htlc.prev_hop.htlc_id)) + self.htlcs.iter().map(|htlc| (htlc.prev_hop.channel_id, htlc.prev_hop.htlc_id)), ) } } @@ -1010,15 +1057,19 @@ impl ClaimablePayments { &mut self, payment_hash: PaymentHash, node_signer: &S, logger: &L, inbound_payment_id_secret: &[u8; 32], custom_tlvs_known: bool, ) -> Result<(Vec, ClaimingPayment), Vec> - where L::Target: Logger, S::Target: NodeSigner, + where + L::Target: Logger, + S::Target: NodeSigner, { match self.claimable_payments.remove(&payment_hash) { Some(payment) => { - let mut receiver_node_id = node_signer.get_node_id(Recipient::Node) + let mut receiver_node_id = node_signer + .get_node_id(Recipient::Node) .expect("Failed to get node_id for node recipient"); for htlc in payment.htlcs.iter() { if htlc.prev_hop.phantom_shared_secret.is_some() { - let phantom_pubkey = node_signer.get_node_id(Recipient::PhantomNode) + let phantom_pubkey = node_signer + .get_node_id(Recipient::PhantomNode) .expect("Failed to get node_id for phantom node recipient"); receiver_node_id = phantom_pubkey; break; @@ -1057,7 +1108,7 @@ impl ClaimablePayments { Ok((payment.htlcs, claiming_payment)) }, - None => Err(Vec::new()) + None => Err(Vec::new()), } } } @@ -1080,15 +1131,12 @@ enum BackgroundEvent { counterparty_node_id: PublicKey, funding_txo: OutPoint, channel_id: ChannelId, - update: ChannelMonitorUpdate + update: ChannelMonitorUpdate, }, /// Some [`ChannelMonitorUpdate`] (s) completed before we were serialized but we still have /// them marked pending, thus we need to run any [`MonitorUpdateCompletionAction`] (s) pending /// on a channel. - MonitorUpdatesComplete { - counterparty_node_id: PublicKey, - channel_id: ChannelId, - }, + MonitorUpdatesComplete { counterparty_node_id: PublicKey, channel_id: ChannelId }, } /// A pointer to a channel that is unblocked when an event is surfaced @@ -1285,7 +1333,9 @@ impl_writeable_tlv_based!(PaymentClaimDetails, { pub(crate) struct PendingMPPClaimPointer(Arc>); impl PartialEq for PendingMPPClaimPointer { - fn eq(&self, o: &Self) -> bool { Arc::ptr_eq(&self.0, &o.0) } + fn eq(&self, o: &Self) -> bool { + Arc::ptr_eq(&self.0, &o.0) + } } impl Eq for PendingMPPClaimPointer {} @@ -1315,9 +1365,7 @@ pub(crate) enum RAAMonitorUpdateBlockingAction { /// /// This variant is *not* written to disk, instead being inferred from [`ChannelMonitor`] /// state. - ClaimedMPPPayment { - pending_claim: PendingMPPClaimPointer, - } + ClaimedMPPPayment { pending_claim: PendingMPPClaimPointer }, } impl RAAMonitorUpdateBlockingAction { @@ -1341,7 +1389,10 @@ impl Readable for Option { } /// State we hold per-peer. -pub(super) struct PeerState where SP::Target: SignerProvider { +pub(super) struct PeerState +where + SP::Target: SignerProvider, +{ /// `channel_id` -> `Channel` /// /// Holds all channels where the peer is the counterparty. @@ -1409,20 +1460,26 @@ pub(super) struct PeerState where SP::Target: SignerProvider { peer_storage: Vec, } -impl PeerState where SP::Target: SignerProvider { +impl PeerState +where + SP::Target: SignerProvider, +{ /// Indicates that a peer meets the criteria where we're ok to remove it from our storage. /// If true is passed for `require_disconnected`, the function will return false if we haven't /// disconnected from the node already, ie. `PeerState::is_connected` is set to `true`. fn ok_to_remove(&self, require_disconnected: bool) -> bool { if require_disconnected && self.is_connected { - return false + return false; } for (_, updates) in self.in_flight_monitor_updates.values() { if !updates.is_empty() { return false; } } - !self.channel_by_id.iter().any(|(_, channel)| channel.is_funded() || channel.funding().is_outbound()) + !self + .channel_by_id + .iter() + .any(|(_, channel)| channel.is_funded() || channel.funding().is_outbound()) && self.monitor_update_blocked_actions.is_empty() && self.closed_channel_monitor_update_ids.is_empty() } @@ -1434,8 +1491,8 @@ impl PeerState where SP::Target: SignerProvider { // Returns a bool indicating if the given `channel_id` matches a channel we have with this peer. fn has_channel(&self, channel_id: &ChannelId) -> bool { - self.channel_by_id.contains_key(channel_id) || - self.inbound_channel_request_by_id.contains_key(channel_id) + self.channel_by_id.contains_key(channel_id) + || self.inbound_channel_request_by_id.contains_key(channel_id) } } @@ -1508,20 +1565,18 @@ pub type SimpleArcChannelManager = ChannelManager< Arc, Arc, Arc, - Arc>>, - Arc, - Arc, - Arc>>, Arc>>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer>>, Arc>, - >>, - Arc>>, - Arc, - Arc, - >>, - Arc + Arc< + DefaultRouter< + Arc>>, + Arc, + Arc, + Arc>>, Arc>>>, + ProbabilisticScoringFeeParameters, + ProbabilisticScorer>>, Arc>, + >, + >, + Arc>>, Arc, Arc>>, + Arc, >; /// [`SimpleRefChannelManager`] is a type alias for a ChannelManager reference, and is the reference @@ -1536,29 +1591,24 @@ pub type SimpleArcChannelManager = ChannelManager< /// /// This is not exported to bindings users as type aliases aren't supported in most languages. #[cfg(not(c_bindings))] -pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, M, T, F, L> = - ChannelManager< - &'a M, - &'b T, - &'c KeysManager, +pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, M, T, F, L> = ChannelManager< + &'a M, + &'b T, + &'c KeysManager, + &'c KeysManager, + &'c KeysManager, + &'d F, + &'e DefaultRouter< + &'f NetworkGraph<&'g L>, + &'g L, &'c KeysManager, - &'c KeysManager, - &'d F, - &'e DefaultRouter< - &'f NetworkGraph<&'g L>, - &'g L, - &'c KeysManager, - &'h RwLock, &'g L>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L> - >, - &'i DefaultMessageRouter< - &'f NetworkGraph<&'g L>, - &'g L, - &'c KeysManager, - >, - &'g L - >; + &'h RwLock, &'g L>>, + ProbabilisticScoringFeeParameters, + ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>, + >, + &'i DefaultMessageRouter<&'f NetworkGraph<&'g L>, &'g L, &'c KeysManager>, + &'g L, +>; /// A trivial trait which describes any [`ChannelManager`]. /// @@ -1584,7 +1634,7 @@ pub trait AChannelManager { /// A type implementing [`EcdsaChannelSigner`]. type Signer: EcdsaChannelSigner + Sized; /// A type implementing [`SignerProvider`] for [`Self::Signer`]. - type SignerProvider: SignerProvider + ?Sized; + type SignerProvider: SignerProvider + ?Sized; /// A type that may be dereferenced to [`Self::SignerProvider`]. type SP: Deref; /// A type implementing [`FeeEstimator`]. @@ -1604,11 +1654,32 @@ pub trait AChannelManager { /// A type that may be dereferenced to [`Self::Logger`]. type L: Deref; /// Returns a reference to the actual [`ChannelManager`] object. - fn get_cm(&self) -> &ChannelManager; + fn get_cm( + &self, + ) -> &ChannelManager< + Self::M, + Self::T, + Self::ES, + Self::NS, + Self::SP, + Self::F, + Self::R, + Self::MR, + Self::L, + >; } -impl AChannelManager -for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > AChannelManager for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -1639,7 +1710,9 @@ where type MR = MR; type Logger = L::Target; type L = L; - fn get_cm(&self) -> &ChannelManager { self } + fn get_cm(&self) -> &ChannelManager { + self + } } /// A lightning node's channel state machine and payment management logic, which facilitates @@ -2425,8 +2498,17 @@ where // | // |__`pending_background_events` // -pub struct ChannelManager -where +pub struct ChannelManager< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, +> where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, ES::Target: EntropySource, @@ -2712,19 +2794,23 @@ struct PersistenceNotifierGuard<'a, F: FnMut() -> NotifyOption> { _read_guard: RwLockReadGuard<'a, ()>, } -impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> { // We don't care what the concrete F is here, it's unused +impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> { + // We don't care what the concrete F is here, it's unused /// Notifies any waiters and indicates that we need to persist, in addition to possibly having /// events to handle. /// /// This must always be called if the changes included a `ChannelMonitorUpdate`, as well as in /// other cases where losing the changes on restart may result in a force-close or otherwise /// isn't ideal. - fn notify_on_drop(cm: &'a C) -> PersistenceNotifierGuard<'a, impl FnMut() -> NotifyOption> { + fn notify_on_drop( + cm: &'a C, + ) -> PersistenceNotifierGuard<'a, impl FnMut() -> NotifyOption> { Self::optionally_notify(cm, || -> NotifyOption { NotifyOption::DoPersist }) } - fn optionally_notify NotifyOption, C: AChannelManager>(cm: &'a C, mut persist_check: F) - -> PersistenceNotifierGuard<'a, impl FnMut() -> NotifyOption> { + fn optionally_notify NotifyOption, C: AChannelManager>( + cm: &'a C, mut persist_check: F, + ) -> PersistenceNotifierGuard<'a, impl FnMut() -> NotifyOption> { let read_guard = cm.get_cm().total_consistency_lock.read().unwrap(); let force_notify = cm.get_cm().process_background_events(); @@ -2738,8 +2824,12 @@ impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> { // We don't care w match (notify, force_notify) { (NotifyOption::DoPersist, _) => NotifyOption::DoPersist, (_, NotifyOption::DoPersist) => NotifyOption::DoPersist, - (NotifyOption::SkipPersistHandleEvents, _) => NotifyOption::SkipPersistHandleEvents, - (_, NotifyOption::SkipPersistHandleEvents) => NotifyOption::SkipPersistHandleEvents, + (NotifyOption::SkipPersistHandleEvents, _) => { + NotifyOption::SkipPersistHandleEvents + }, + (_, NotifyOption::SkipPersistHandleEvents) => { + NotifyOption::SkipPersistHandleEvents + }, _ => NotifyOption::SkipPersistNoEvents, } }, @@ -2750,8 +2840,9 @@ impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> { // We don't care w /// Note that if any [`ChannelMonitorUpdate`]s are possibly generated, /// [`ChannelManager::process_background_events`] MUST be called first (or /// [`Self::optionally_notify`] used). - fn optionally_notify_skipping_background_events NotifyOption, C: AChannelManager> - (cm: &'a C, persist_check: F) -> PersistenceNotifierGuard<'a, F> { + fn optionally_notify_skipping_background_events NotifyOption, C: AChannelManager>( + cm: &'a C, persist_check: F, + ) -> PersistenceNotifierGuard<'a, F> { let read_guard = cm.get_cm().total_consistency_lock.read().unwrap(); PersistenceNotifierGuard { @@ -2770,8 +2861,7 @@ impl<'a, F: FnMut() -> NotifyOption> Drop for PersistenceNotifierGuard<'a, F> { self.needs_persist_flag.store(true, Ordering::Release); self.event_persist_notifier.notify() }, - NotifyOption::SkipPersistHandleEvents => - self.event_persist_notifier.notify(), + NotifyOption::SkipPersistHandleEvents => self.event_persist_notifier.notify(), NotifyOption::SkipPersistNoEvents => {}, } } @@ -2798,7 +2888,7 @@ pub(crate) const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 2 * 6 * 24 * 7; // i.e. the node we forwarded the payment on to should always have enough room to reliably time out // the HTLC via a full update_fail_htlc/commitment_signed dance before we hit the // CLTV_CLAIM_BUFFER point (we static assert that it's at least 3 blocks more). -pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6*8; +pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6 * 8; // This should be long enough to allow a payment path drawn across multiple routing hops with substantial // `cltv_expiry_delta`. Indeed, the length of those values is the reaction delay offered to a routing node // in case of HTLC on-chain settlement. While appearing less competitive, a node operator could decide to @@ -2825,7 +2915,8 @@ pub const MIN_FINAL_CLTV_EXPIRY_DELTA: u16 = HTLC_FAIL_BACK_BUFFER as u16 + 3; // expiry, i.e. assuming the peer force-closes right at the expiry and we're behind by // LATENCY_GRACE_PERIOD_BLOCKS). const _CHECK_CLTV_EXPIRY_SANITY: () = assert!( - MIN_CLTV_EXPIRY_DELTA as u32 >= 2*LATENCY_GRACE_PERIOD_BLOCKS + 2*MAX_BLOCKS_FOR_CONF + ANTI_REORG_DELAY + MIN_CLTV_EXPIRY_DELTA as u32 + >= 2 * LATENCY_GRACE_PERIOD_BLOCKS + 2 * MAX_BLOCKS_FOR_CONF + ANTI_REORG_DELAY ); // Check that our MIN_CLTV_EXPIRY_DELTA gives us enough time to get the HTLC preimage back to our @@ -2841,7 +2932,8 @@ const _CHECK_COUNTERPARTY_REALISTIC: () = assert!(_ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER >= CLTV_CLAIM_BUFFER); const _CHECK_CLTV_EXPIRY_OFFCHAIN: () = assert!( - MIN_CLTV_EXPIRY_DELTA as u32 >= 2*LATENCY_GRACE_PERIOD_BLOCKS - 1 + _ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER + MIN_CLTV_EXPIRY_DELTA as u32 + >= 2 * LATENCY_GRACE_PERIOD_BLOCKS - 1 + _ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER ); /// The number of ticks of [`ChannelManager::timer_tick_occurred`] until expiry of incomplete MPPs @@ -2957,7 +3049,7 @@ pub struct PhantomRouteHints { } macro_rules! handle_error { - ($self: ident, $internal: expr, $counterparty_node_id: expr) => { { + ($self: ident, $internal: expr, $counterparty_node_id: expr) => {{ // In testing, ensure there are no deadlocks where the lock is already held upon // entering the macro. debug_assert_ne!($self.pending_events.held_by_thread(), LockHeldState::HeldByThread); @@ -2972,16 +3064,19 @@ macro_rules! handle_error { let counterparty_node_id = shutdown_res.counterparty_node_id; let channel_id = shutdown_res.channel_id; let logger = WithContext::from( - &$self.logger, Some(counterparty_node_id), Some(channel_id), None + &$self.logger, + Some(counterparty_node_id), + Some(channel_id), + None, ); log_error!(logger, "Force-closing channel: {}", err.err); $self.finish_close_channel(shutdown_res); if let Some(update) = update_option { - let mut pending_broadcast_messages = $self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + let mut pending_broadcast_messages = + $self.pending_broadcast_messages.lock().unwrap(); + pending_broadcast_messages + .push(MessageSendEvent::BroadcastChannelUpdate { msg: update }); } } else { log_error!($self.logger, "Got non-closing error: {}", err.err); @@ -2991,7 +3086,7 @@ macro_rules! handle_error { } else { msg_event = Some(MessageSendEvent::HandleError { node_id: $counterparty_node_id, - action: err.action.clone() + action: err.action.clone(), }); } @@ -3007,7 +3102,7 @@ macro_rules! handle_error { Err(err) }, } - } }; + }}; } /// When a channel is removed, two things need to happen: @@ -3020,15 +3115,24 @@ macro_rules! handle_error { macro_rules! locked_close_channel { ($self: ident, $peer_state: expr, $channel_context: expr, $shutdown_res_mut: expr) => {{ if let Some((_, funding_txo, _, update)) = $shutdown_res_mut.monitor_update.take() { - handle_new_monitor_update!($self, funding_txo, update, $peer_state, - $channel_context, REMAIN_LOCKED_UPDATE_ACTIONS_PROCESSED_LATER); + handle_new_monitor_update!( + $self, + funding_txo, + update, + $peer_state, + $channel_context, + REMAIN_LOCKED_UPDATE_ACTIONS_PROCESSED_LATER + ); } // If there's a possibility that we need to generate further monitor updates for this // channel, we need to store the last update_id of it. However, we don't want to insert // into the map (which prevents the `PeerState` from being cleaned up) for channels that // never even got confirmations (which would open us up to DoS attacks). let update_id = $channel_context.get_latest_monitor_update_id(); - if $channel_context.get_funding_tx_confirmation_height().is_some() || $channel_context.minimum_depth() == Some(0) || update_id > 1 { + if $channel_context.get_funding_tx_confirmation_height().is_some() + || $channel_context.minimum_depth() == Some(0) + || update_id > 1 + { let chan_id = $channel_context.channel_id(); $peer_state.closed_channel_monitor_update_ids.insert(chan_id, update_id); } @@ -3042,54 +3146,110 @@ macro_rules! locked_close_channel { // also don't want a counterparty to be able to trivially cause a memory leak by simply // opening a million channels with us which are closed before we ever reach the funding // stage. - let alias_removed = $self.outbound_scid_aliases.lock().unwrap().remove(&$channel_context.outbound_scid_alias()); + let alias_removed = $self + .outbound_scid_aliases + .lock() + .unwrap() + .remove(&$channel_context.outbound_scid_alias()); debug_assert!(alias_removed); } short_to_chan_info.remove(&$channel_context.outbound_scid_alias()); - }} + }}; } /// Returns (boolean indicating if we should remove the Channel object from memory, a mapped error) macro_rules! convert_channel_err { ($self: ident, $peer_state: expr, $err: expr, $context: expr, $funding: expr, $channel_id: expr, MANUAL_CHANNEL_UPDATE, $channel_update: expr) => { match $err { - ChannelError::Warn(msg) => { - (false, MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn(msg), *$channel_id)) - }, - ChannelError::WarnAndDisconnect(msg) => { - (false, MsgHandleErrInternal::from_chan_no_close(ChannelError::WarnAndDisconnect(msg), *$channel_id)) - }, - ChannelError::Ignore(msg) => { - (false, MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), *$channel_id)) - }, + ChannelError::Warn(msg) => ( + false, + MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn(msg), *$channel_id), + ), + ChannelError::WarnAndDisconnect(msg) => ( + false, + MsgHandleErrInternal::from_chan_no_close( + ChannelError::WarnAndDisconnect(msg), + *$channel_id, + ), + ), + ChannelError::Ignore(msg) => ( + false, + MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), *$channel_id), + ), ChannelError::Close((msg, reason)) => { let logger = WithChannelContext::from(&$self.logger, &$context, None); - log_error!(logger, "Closing channel {} due to close-required error: {}", $channel_id, msg); + log_error!( + logger, + "Closing channel {} due to close-required error: {}", + $channel_id, + msg + ); let mut shutdown_res = $context.force_shutdown($funding, true, reason); locked_close_channel!($self, $peer_state, $context, &mut shutdown_res); - let err = - MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, shutdown_res, $channel_update); + let err = MsgHandleErrInternal::from_finish_shutdown( + msg, + *$channel_id, + shutdown_res, + $channel_update, + ); (true, err) }, - ChannelError::SendError(msg) => { - (false, MsgHandleErrInternal::from_chan_no_close(ChannelError::SendError(msg), *$channel_id)) - }, + ChannelError::SendError(msg) => ( + false, + MsgHandleErrInternal::from_chan_no_close( + ChannelError::SendError(msg), + *$channel_id, + ), + ), } }; ($self: ident, $peer_state: expr, $err: expr, $funded_channel: expr, $channel_id: expr, FUNDED_CHANNEL) => { - convert_channel_err!($self, $peer_state, $err, $funded_channel.context, &$funded_channel.funding, $channel_id, MANUAL_CHANNEL_UPDATE, { $self.get_channel_update_for_broadcast(&$funded_channel).ok() }) + convert_channel_err!( + $self, + $peer_state, + $err, + $funded_channel.context, + &$funded_channel.funding, + $channel_id, + MANUAL_CHANNEL_UPDATE, + { $self.get_channel_update_for_broadcast(&$funded_channel).ok() } + ) }; ($self: ident, $peer_state: expr, $err: expr, $context: expr, $funding: expr, $channel_id: expr, UNFUNDED_CHANNEL) => { - convert_channel_err!($self, $peer_state, $err, $context, $funding, $channel_id, MANUAL_CHANNEL_UPDATE, None) + convert_channel_err!( + $self, + $peer_state, + $err, + $context, + $funding, + $channel_id, + MANUAL_CHANNEL_UPDATE, + None + ) }; ($self: ident, $peer_state: expr, $err: expr, $channel: expr, $channel_id: expr) => { match $channel.as_funded_mut() { Some(funded_channel) => { - convert_channel_err!($self, $peer_state, $err, funded_channel, $channel_id, FUNDED_CHANNEL) + convert_channel_err!( + $self, + $peer_state, + $err, + funded_channel, + $channel_id, + FUNDED_CHANNEL + ) }, None => { let (funding, context) = $channel.funding_and_context_mut(); - convert_channel_err!($self, $peer_state, $err, context, funding, $channel_id, UNFUNDED_CHANNEL) + convert_channel_err!( + $self, + $peer_state, + $err, + context, + funding, + $channel_id, + UNFUNDED_CHANNEL + ) }, } }; @@ -3101,14 +3261,15 @@ macro_rules! break_channel_entry { Ok(res) => res, Err(e) => { let key = *$entry.key(); - let (drop, res) = convert_channel_err!($self, $peer_state, e, $entry.get_mut(), &key); + let (drop, res) = + convert_channel_err!($self, $peer_state, e, $entry.get_mut(), &key); if drop { $entry.remove_entry(); } break Err(res); - } + }, } - } + }; } macro_rules! try_channel_entry { @@ -3117,24 +3278,23 @@ macro_rules! try_channel_entry { Ok(res) => res, Err(e) => { let key = *$entry.key(); - let (drop, res) = convert_channel_err!($self, $peer_state, e, $entry.get_mut(), &key); + let (drop, res) = + convert_channel_err!($self, $peer_state, e, $entry.get_mut(), &key); if drop { $entry.remove_entry(); } return Err(res); - } + }, } - } + }; } macro_rules! remove_channel_entry { - ($self: ident, $peer_state: expr, $entry: expr, $shutdown_res_mut: expr) => { - { - let channel = $entry.remove_entry().1; - locked_close_channel!($self, $peer_state, &channel.context(), $shutdown_res_mut); - channel - } - } + ($self: ident, $peer_state: expr, $entry: expr, $shutdown_res_mut: expr) => {{ + let channel = $entry.remove_entry().1; + locked_close_channel!($self, $peer_state, &channel.context(), $shutdown_res_mut); + channel + }}; } macro_rules! send_channel_ready { @@ -3175,32 +3335,42 @@ macro_rules! emit_funding_tx_broadcast_safe_event { macro_rules! emit_channel_pending_event { ($locked_events: expr, $channel: expr) => { if $channel.context.should_emit_channel_pending_event() { - $locked_events.push_back((events::Event::ChannelPending { - channel_id: $channel.context.channel_id(), - former_temporary_channel_id: $channel.context.temporary_channel_id(), - counterparty_node_id: $channel.context.get_counterparty_node_id(), - user_channel_id: $channel.context.get_user_id(), - funding_txo: $channel.funding.get_funding_txo().unwrap().into_bitcoin_outpoint(), - channel_type: Some($channel.funding.get_channel_type().clone()), - }, None)); + $locked_events.push_back(( + events::Event::ChannelPending { + channel_id: $channel.context.channel_id(), + former_temporary_channel_id: $channel.context.temporary_channel_id(), + counterparty_node_id: $channel.context.get_counterparty_node_id(), + user_channel_id: $channel.context.get_user_id(), + funding_txo: $channel + .funding + .get_funding_txo() + .unwrap() + .into_bitcoin_outpoint(), + channel_type: Some($channel.funding.get_channel_type().clone()), + }, + None, + )); $channel.context.set_channel_pending_event_emitted(); } - } + }; } macro_rules! emit_channel_ready_event { ($locked_events: expr, $channel: expr) => { if $channel.context.should_emit_channel_ready_event() { debug_assert!($channel.context.channel_pending_event_emitted()); - $locked_events.push_back((events::Event::ChannelReady { - channel_id: $channel.context.channel_id(), - user_channel_id: $channel.context.get_user_id(), - counterparty_node_id: $channel.context.get_counterparty_node_id(), - channel_type: $channel.funding.get_channel_type().clone(), - }, None)); + $locked_events.push_back(( + events::Event::ChannelReady { + channel_id: $channel.context.channel_id(), + user_channel_id: $channel.context.get_user_id(), + counterparty_node_id: $channel.context.get_counterparty_node_id(), + channel_type: $channel.funding.get_channel_type().clone(), + }, + None, + )); $channel.context.set_channel_ready_event_emitted(); } - } + }; } macro_rules! handle_monitor_update_completion { @@ -3431,7 +3601,11 @@ macro_rules! process_events_body { let mut handling_failed = false; let mut processed_all_events = false; while !handling_failed && !processed_all_events { - if $self.pending_events_processor.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + if $self + .pending_events_processor + .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) + .is_err() + { return; } @@ -3465,20 +3639,24 @@ macro_rules! process_events_body { log_trace!($self.logger, "Handling event {:?}...", event); $event_to_handle = event; let event_handling_result = $handle_event; - log_trace!($self.logger, "Done handling event, result: {:?}", event_handling_result); + log_trace!( + $self.logger, + "Done handling event, result: {:?}", + event_handling_result + ); match event_handling_result { Ok(()) => { if let Some(action) = action_opt { post_event_actions.push(action); } num_handled_events += 1; - } + }, Err(_e) => { // If we encounter an error we stop handling events and make sure to replay // any unhandled events on the next invocation. handling_failed = true; break; - } + }, } } @@ -3502,15 +3680,24 @@ macro_rules! process_events_body { $self.needs_persist_flag.store(true, Ordering::Release); $self.event_persist_notifier.notify(); }, - NotifyOption::SkipPersistHandleEvents => - $self.event_persist_notifier.notify(), + NotifyOption::SkipPersistHandleEvents => $self.event_persist_notifier.notify(), NotifyOption::SkipPersistNoEvents => {}, } } - } + }; } -impl ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -3562,7 +3749,10 @@ where pending_outbound_payments: OutboundPayments::new(new_hash_map()), forward_htlcs: Mutex::new(new_hash_map()), decode_update_add_htlcs: Mutex::new(new_hash_map()), - claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: new_hash_map(), pending_claiming_payments: new_hash_map() }), + claimable_payments: Mutex::new(ClaimablePayments { + claimable_payments: new_hash_map(), + pending_claiming_payments: new_hash_map(), + }), pending_intercepted_htlcs: Mutex::new(new_hash_map()), short_to_chan_info: FairRwLock::new(new_hash_map()), @@ -3625,16 +3815,26 @@ where let mut outbound_scid_alias = 0; let mut i = 0; loop { - if cfg!(fuzzing) { // fuzzing chacha20 doesn't use the key at all so we always get the same alias + if cfg!(fuzzing) { + // fuzzing chacha20 doesn't use the key at all so we always get the same alias outbound_scid_alias += 1; } else { - outbound_scid_alias = fake_scid::Namespace::OutboundAlias.get_fake_scid(height, &self.chain_hash, &self.fake_scid_rand_bytes, &self.entropy_source); + outbound_scid_alias = fake_scid::Namespace::OutboundAlias.get_fake_scid( + height, + &self.chain_hash, + &self.fake_scid_rand_bytes, + &self.entropy_source, + ); } - if outbound_scid_alias != 0 && self.outbound_scid_aliases.lock().unwrap().insert(outbound_scid_alias) { + if outbound_scid_alias != 0 + && self.outbound_scid_aliases.lock().unwrap().insert(outbound_scid_alias) + { break; } i += 1; - if i > 1_000_000 { panic!("Your RNG is busted or we ran out of possible outbound SCID aliases (which should never happen before we run out of memory to store channels"); } + if i > 1_000_000 { + panic!("Your RNG is busted or we ran out of possible outbound SCID aliases (which should never happen before we run out of memory to store channels"); + } } outbound_scid_alias } @@ -3671,9 +3871,18 @@ where /// [`Event::FundingGenerationReady::user_channel_id`]: events::Event::FundingGenerationReady::user_channel_id /// [`Event::FundingGenerationReady::temporary_channel_id`]: events::Event::FundingGenerationReady::temporary_channel_id /// [`Event::ChannelClosed::channel_id`]: events::Event::ChannelClosed::channel_id - pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_channel_id: u128, temporary_channel_id: Option, override_config: Option) -> Result { + pub fn create_channel( + &self, their_network_key: PublicKey, channel_value_satoshis: u64, push_msat: u64, + user_channel_id: u128, temporary_channel_id: Option, + override_config: Option, + ) -> Result { if channel_value_satoshis < 1000 { - return Err(APIError::APIMisuseError { err: format!("Channel value must be at least 1000 satoshis. It was {}", channel_value_satoshis) }); + return Err(APIError::APIMisuseError { + err: format!( + "Channel value must be at least 1000 satoshis. It was {}", + channel_value_satoshis + ), + }); } let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); @@ -3682,25 +3891,47 @@ where let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(&their_network_key) - .ok_or_else(|| APIError::APIMisuseError{ err: format!("Not connected to node: {}", their_network_key) })?; + let peer_state_mutex = + per_peer_state.get(&their_network_key).ok_or_else(|| APIError::APIMisuseError { + err: format!("Not connected to node: {}", their_network_key), + })?; let mut peer_state = peer_state_mutex.lock().unwrap(); if let Some(temporary_channel_id) = temporary_channel_id { if peer_state.channel_by_id.contains_key(&temporary_channel_id) { - return Err(APIError::APIMisuseError{ err: format!("Channel with temporary channel ID {} already exists!", temporary_channel_id)}); + return Err(APIError::APIMisuseError { + err: format!( + "Channel with temporary channel ID {} already exists!", + temporary_channel_id + ), + }); } } let mut channel = { let outbound_scid_alias = self.create_and_insert_outbound_scid_alias(); let their_features = &peer_state.latest_features; - let config = if override_config.is_some() { override_config.as_ref().unwrap() } else { &self.default_configuration }; - match OutboundV1Channel::new(&self.fee_estimator, &self.entropy_source, &self.signer_provider, their_network_key, - their_features, channel_value_satoshis, push_msat, user_channel_id, config, - self.best_block.read().unwrap().height, outbound_scid_alias, temporary_channel_id, &*self.logger) - { + let config = if override_config.is_some() { + override_config.as_ref().unwrap() + } else { + &self.default_configuration + }; + match OutboundV1Channel::new( + &self.fee_estimator, + &self.entropy_source, + &self.signer_provider, + their_network_key, + their_features, + channel_value_satoshis, + push_msat, + user_channel_id, + config, + self.best_block.read().unwrap().height, + outbound_scid_alias, + temporary_channel_id, + &*self.logger, + ) { Ok(res) => res, Err(e) => { self.outbound_scid_aliases.lock().unwrap().remove(&outbound_scid_alias); @@ -3720,19 +3951,22 @@ where panic!("RNG is bad???"); } }, - hash_map::Entry::Vacant(entry) => { entry.insert(Channel::from(channel)); } + hash_map::Entry::Vacant(entry) => { + entry.insert(Channel::from(channel)); + }, } if let Some(msg) = res { - peer_state.pending_msg_events.push(MessageSendEvent::SendOpenChannel { - node_id: their_network_key, - msg, - }); + peer_state + .pending_msg_events + .push(MessageSendEvent::SendOpenChannel { node_id: their_network_key, msg }); } Ok(temporary_channel_id) } - fn list_funded_channels_with_filter)) -> bool + Copy>(&self, f: Fn) -> Vec { + fn list_funded_channels_with_filter)) -> bool + Copy>( + &self, f: Fn, + ) -> Vec { // Allocate our best estimate of the number of channels we have in the `res` // Vec. Sadly the `short_to_chan_info` map doesn't cover channels without // a scid or a scid alias. Therefore reallocations may still occur, but is @@ -3745,16 +3979,21 @@ where for (_cp_id, peer_state_mutex) in per_peer_state.iter() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - res.extend(peer_state.channel_by_id.iter() - // Only `Channels` in the `Channel::Funded` phase can be considered funded. - .filter(|(_, chan)| chan.is_funded()) - .filter(f) - .map(|(_channel_id, channel)| { - ChannelDetails::from_channel( - channel, best_block_height, peer_state.latest_features.clone(), - &self.fee_estimator, - ) - }) + res.extend( + peer_state + .channel_by_id + .iter() + // Only `Channels` in the `Channel::Funded` phase can be considered funded. + .filter(|(_, chan)| chan.is_funded()) + .filter(f) + .map(|(_channel_id, channel)| { + ChannelDetails::from_channel( + channel, + best_block_height, + peer_state.latest_features.clone(), + &self.fee_estimator, + ) + }), ); } } @@ -3778,7 +4017,9 @@ where let peer_state = &mut *peer_state_lock; for (_, channel) in peer_state.channel_by_id.iter() { let details = ChannelDetails::from_channel( - channel, best_block_height, peer_state.latest_features.clone(), + channel, + best_block_height, + peer_state.latest_features.clone(), &self.fee_estimator, ); res.push(details); @@ -3802,7 +4043,9 @@ where } /// Gets the list of channels we have with a given counterparty, in random order. - pub fn list_channels_with_counterparty(&self, counterparty_node_id: &PublicKey) -> Vec { + pub fn list_channels_with_counterparty( + &self, counterparty_node_id: &PublicKey, + ) -> Vec { let best_block_height = self.best_block.read().unwrap().height; let per_peer_state = self.per_peer_state.read().unwrap(); @@ -3812,10 +4055,14 @@ where let features = &peer_state.latest_features; let channel_to_details = |channel| { ChannelDetails::from_channel( - channel, best_block_height, features.clone(), &self.fee_estimator, + channel, + best_block_height, + features.clone(), + &self.fee_estimator, ) }; - return peer_state.channel_by_id + return peer_state + .channel_by_id .iter() .map(|(_, chan)| (chan)) .map(channel_to_details) @@ -3833,7 +4080,11 @@ where /// /// [`Event::PaymentSent`]: events::Event::PaymentSent pub fn list_recent_payments(&self) -> Vec { - self.pending_outbound_payments.pending_outbound_payments.lock().unwrap().iter() + self.pending_outbound_payments + .pending_outbound_payments + .lock() + .unwrap() + .iter() .filter_map(|(payment_id, pending_outbound_payment)| match pending_outbound_payment { PendingOutboundPayment::AwaitingInvoice { .. } | PendingOutboundPayment::AwaitingOffer { .. } @@ -3863,7 +4114,11 @@ where .collect() } - fn close_channel_internal(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option, override_shutdown_script: Option) -> Result<(), APIError> { + fn close_channel_internal( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, + target_feerate_sats_per_1000_weight: Option, + override_shutdown_script: Option, + ) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let mut failed_htlcs: Vec<(HTLCSource, PaymentHash)> = Vec::new(); @@ -3872,8 +4127,14 @@ where { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + APIError::ChannelUnavailable { + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + } + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -3883,8 +4144,12 @@ where if let Some(chan) = chan_entry.get_mut().as_funded_mut() { let funding_txo_opt = chan.funding.get_funding_txo(); let their_features = &peer_state.latest_features; - let (shutdown_msg, mut monitor_update_opt, htlcs) = - chan.get_shutdown(&self.signer_provider, their_features, target_feerate_sats_per_1000_weight, override_shutdown_script)?; + let (shutdown_msg, mut monitor_update_opt, htlcs) = chan.get_shutdown( + &self.signer_provider, + their_features, + target_feerate_sats_per_1000_weight, + override_shutdown_script, + )?; failed_htlcs = htlcs; // We can send the `shutdown` message before updating the `ChannelMonitor` @@ -3895,17 +4160,30 @@ where msg: shutdown_msg, }); - debug_assert!(monitor_update_opt.is_none() || !chan.is_shutdown(), - "We can't both complete shutdown and generate a monitor update"); + debug_assert!( + monitor_update_opt.is_none() || !chan.is_shutdown(), + "We can't both complete shutdown and generate a monitor update" + ); // Update the monitor with the shutdown script if necessary. if let Some(monitor_update) = monitor_update_opt.take() { - handle_new_monitor_update!(self, funding_txo_opt.unwrap(), monitor_update, - peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo_opt.unwrap(), + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } } else { - let mut shutdown_res = chan_entry.get_mut() - .force_shutdown(false, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }); + let mut shutdown_res = chan_entry.get_mut().force_shutdown( + false, + ClosureReason::HolderForceClosed { + broadcasted_latest_txn: Some(false), + }, + ); remove_channel_entry!(self, peer_state, chan_entry, shutdown_res); shutdown_result = Some(shutdown_res); } @@ -3915,7 +4193,7 @@ where err: format!( "Channel with id {} not found for the passed counterparty node_id {}", channel_id, counterparty_node_id, - ) + ), }); }, } @@ -3924,7 +4202,10 @@ where for htlc_source in failed_htlcs.drain(..) { let failure_reason = LocalHTLCFailureReason::ChannelClosed; let reason = HTLCFailReason::from_failure_code(failure_reason); - let receiver = HTLCDestination::NextHopChannel { node_id: Some(*counterparty_node_id), channel_id: *channel_id }; + let receiver = HTLCDestination::NextHopChannel { + node_id: Some(*counterparty_node_id), + channel_id: *channel_id, + }; self.fail_htlc_backwards_internal(&htlc_source.0, &htlc_source.1, &reason, receiver); } @@ -3958,7 +4239,9 @@ where /// [`ChannelCloseMinimum`]: crate::chain::chaininterface::ConfirmationTarget::ChannelCloseMinimum /// [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee /// [`SendShutdown`]: MessageSendEvent::SendShutdown - pub fn close_channel(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey) -> Result<(), APIError> { + pub fn close_channel( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, + ) -> Result<(), APIError> { self.close_channel_internal(channel_id, counterparty_node_id, None, None) } @@ -3991,8 +4274,16 @@ where /// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis /// [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee /// [`SendShutdown`]: MessageSendEvent::SendShutdown - pub fn close_channel_with_feerate_and_script(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option, shutdown_script: Option) -> Result<(), APIError> { - self.close_channel_internal(channel_id, counterparty_node_id, target_feerate_sats_per_1000_weight, shutdown_script) + pub fn close_channel_with_feerate_and_script( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, + target_feerate_sats_per_1000_weight: Option, shutdown_script: Option, + ) -> Result<(), APIError> { + self.close_channel_internal( + channel_id, + counterparty_node_id, + target_feerate_sats_per_1000_weight, + shutdown_script, + ) } /// Applies a [`ChannelMonitorUpdate`] which may or may not be for a channel which is closed. @@ -4010,8 +4301,15 @@ where match peer_state.channel_by_id.entry(channel_id) { hash_map::Entry::Occupied(mut chan_entry) => { if let Some(chan) = chan_entry.get_mut().as_funded_mut() { - handle_new_monitor_update!(self, funding_txo, - monitor_update, peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo, + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); return; } else { debug_assert!(false, "We shouldn't have an update for a non-funded channel"); @@ -4021,8 +4319,15 @@ where } handle_new_monitor_update!( - self, funding_txo, monitor_update, peer_state_lock, peer_state, per_peer_state, - counterparty_node_id, channel_id, POST_CHANNEL_CLOSE + self, + funding_txo, + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + counterparty_node_id, + channel_id, + POST_CHANNEL_CLOSE ); } @@ -4039,21 +4344,34 @@ where } let logger = WithContext::from( - &self.logger, Some(shutdown_res.counterparty_node_id), Some(shutdown_res.channel_id), None + &self.logger, + Some(shutdown_res.counterparty_node_id), + Some(shutdown_res.channel_id), + None, ); - log_debug!(logger, "Finishing closure of channel due to {} with {} HTLCs to fail", - shutdown_res.closure_reason, shutdown_res.dropped_outbound_htlcs.len()); + log_debug!( + logger, + "Finishing closure of channel due to {} with {} HTLCs to fail", + shutdown_res.closure_reason, + shutdown_res.dropped_outbound_htlcs.len() + ); for htlc_source in shutdown_res.dropped_outbound_htlcs.drain(..) { let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source; let failure_reason = LocalHTLCFailureReason::ChannelClosed; let reason = HTLCFailReason::from_failure_code(failure_reason); - let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id }; + let receiver = + HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id }; self.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver); } if let Some((_, funding_txo, _channel_id, monitor_update)) = shutdown_res.monitor_update { debug_assert!(false, "This should have been handled in `locked_close_channel`"); - self.apply_post_close_monitor_update(shutdown_res.counterparty_node_id, shutdown_res.channel_id, funding_txo, monitor_update); + self.apply_post_close_monitor_update( + shutdown_res.counterparty_node_id, + shutdown_res.channel_id, + funding_txo, + monitor_update, + ); } if self.background_events_processed_since_startup.load(Ordering::Acquire) { // If a `ChannelMonitorUpdate` was applied (i.e. any time we have a funding txo and are @@ -4063,11 +4381,19 @@ where // `locked_close_channel` we can skip the locks here. if shutdown_res.channel_funding_txo.is_some() { let per_peer_state = self.per_peer_state.read().unwrap(); - if let Some(peer_state_mtx) = per_peer_state.get(&shutdown_res.counterparty_node_id) { + if let Some(peer_state_mtx) = per_peer_state.get(&shutdown_res.counterparty_node_id) + { let mut peer_state = peer_state_mtx.lock().unwrap(); - if peer_state.in_flight_monitor_updates.get(&shutdown_res.channel_id).map(|(_, updates)| updates.is_empty()).unwrap_or(true) { - let update_actions = peer_state.monitor_update_blocked_actions - .remove(&shutdown_res.channel_id).unwrap_or(Vec::new()); + if peer_state + .in_flight_monitor_updates + .get(&shutdown_res.channel_id) + .map(|(_, updates)| updates.is_empty()) + .unwrap_or(true) + { + let update_actions = peer_state + .monitor_update_blocked_actions + .remove(&shutdown_res.channel_id) + .unwrap_or(Vec::new()); mem::drop(peer_state); mem::drop(per_peer_state); @@ -4087,12 +4413,14 @@ where if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) { let mut peer_state = peer_state_mutex.lock().unwrap(); if let Some(mut chan) = peer_state.channel_by_id.remove(&channel_id) { - let mut close_res = chan.force_shutdown(false, ClosureReason::FundingBatchClosure); + let mut close_res = + chan.force_shutdown(false, ClosureReason::FundingBatchClosure); locked_close_channel!(self, &mut *peer_state, chan.context(), close_res); shutdown_results.push(close_res); } } - has_uncompleted_channel = Some(has_uncompleted_channel.map_or(!state, |v| v || !state)); + has_uncompleted_channel = + Some(has_uncompleted_channel.map_or(!state, |v| v || !state)); } debug_assert!( has_uncompleted_channel.unwrap_or(true), @@ -4102,15 +4430,18 @@ where { let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push_back((events::Event::ChannelClosed { - channel_id: shutdown_res.channel_id, - user_channel_id: shutdown_res.user_channel_id, - reason: shutdown_res.closure_reason, - counterparty_node_id: Some(shutdown_res.counterparty_node_id), - channel_capacity_sats: Some(shutdown_res.channel_capacity_satoshis), - channel_funding_txo: shutdown_res.channel_funding_txo, - last_local_balance_msat: Some(shutdown_res.last_local_balance_msat), - }, None)); + pending_events.push_back(( + events::Event::ChannelClosed { + channel_id: shutdown_res.channel_id, + user_channel_id: shutdown_res.user_channel_id, + reason: shutdown_res.closure_reason, + counterparty_node_id: Some(shutdown_res.counterparty_node_id), + channel_capacity_sats: Some(shutdown_res.channel_capacity_satoshis), + channel_funding_txo: shutdown_res.channel_funding_txo, + last_local_balance_msat: Some(shutdown_res.last_local_balance_msat), + }, + None, + )); if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx { let funding_info = if shutdown_res.is_manual_broadcast { @@ -4119,11 +4450,15 @@ where .expect("We had an unbroadcasted funding tx, so should also have had a funding outpoint"), } } else { - FundingInfo::Tx{ transaction } + FundingInfo::Tx { transaction } }; - pending_events.push_back((events::Event::DiscardFunding { - channel_id: shutdown_res.channel_id, funding_info - }, None)); + pending_events.push_back(( + events::Event::DiscardFunding { + channel_id: shutdown_res.channel_id, + funding_info, + }, + None, + )); } } for shutdown_result in shutdown_results.drain(..) { @@ -4133,28 +4468,38 @@ where /// `peer_msg` should be set when we receive a message from a peer, but not set when the /// user closes, which will be re-exposed as the `ChannelClosed` reason. - fn force_close_channel_with_peer(&self, channel_id: &ChannelId, peer_node_id: &PublicKey, peer_msg: Option<&String>, broadcast: bool) - -> Result { + fn force_close_channel_with_peer( + &self, channel_id: &ChannelId, peer_node_id: &PublicKey, peer_msg: Option<&String>, + broadcast: bool, + ) -> Result { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(peer_node_id) - .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", peer_node_id) })?; + let peer_state_mutex = + per_peer_state.get(peer_node_id).ok_or_else(|| APIError::ChannelUnavailable { + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + peer_node_id + ), + })?; let (update_opt, counterparty_node_id) = { let mut peer_state = peer_state_mutex.lock().unwrap(); let closure_reason = if let Some(peer_msg) = peer_msg { - ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(peer_msg.to_string()) } + ClosureReason::CounterpartyForceClosed { + peer_msg: UntrustedString(peer_msg.to_string()), + } } else { ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(broadcast) } }; - let logger = WithContext::from(&self.logger, Some(*peer_node_id), Some(*channel_id), None); - if let hash_map::Entry::Occupied(mut chan_entry) = peer_state.channel_by_id.entry(channel_id.clone()) { + let logger = + WithContext::from(&self.logger, Some(*peer_node_id), Some(*channel_id), None); + if let hash_map::Entry::Occupied(mut chan_entry) = + peer_state.channel_by_id.entry(channel_id.clone()) + { log_error!(logger, "Force-closing channel {}", channel_id); let (mut shutdown_res, update_opt) = match chan_entry.get_mut().as_funded_mut() { - Some(chan) => { - ( - chan.context.force_shutdown(&chan.funding, broadcast, closure_reason), - self.get_channel_update_for_broadcast(&chan).ok(), - ) - }, + Some(chan) => ( + chan.context.force_shutdown(&chan.funding, broadcast, closure_reason), + self.get_channel_update_for_broadcast(&chan).ok(), + ), None => { // Unfunded channel has no update (chan_entry.get_mut().force_shutdown(false, closure_reason), None) @@ -4172,42 +4517,53 @@ where // events anyway. (None, *peer_node_id) } else { - return Err(APIError::ChannelUnavailable{ err: format!("Channel with id {} not found for the passed counterparty node_id {}", channel_id, peer_node_id) }); + return Err(APIError::ChannelUnavailable { + err: format!( + "Channel with id {} not found for the passed counterparty node_id {}", + channel_id, peer_node_id + ), + }); } }; if let Some(update) = update_opt { // If we have some Channel Update to broadcast, we cache it and broadcast it later. let mut pending_broadcast_messages = self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + pending_broadcast_messages + .push(MessageSendEvent::BroadcastChannelUpdate { msg: update }); } Ok(counterparty_node_id) } - fn force_close_sending_error(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool, error_message: String) - -> Result<(), APIError> { + fn force_close_sending_error( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool, + error_message: String, + ) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - log_debug!(self.logger, - "Force-closing channel, The error message sent to the peer : {}", error_message); - match self.force_close_channel_with_peer(channel_id, &counterparty_node_id, None, broadcast) { + log_debug!( + self.logger, + "Force-closing channel, The error message sent to the peer : {}", + error_message + ); + match self.force_close_channel_with_peer(channel_id, &counterparty_node_id, None, broadcast) + { Ok(counterparty_node_id) => { let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) { let mut peer_state = peer_state_mutex.lock().unwrap(); - peer_state.pending_msg_events.push( - MessageSendEvent::HandleError { - node_id: counterparty_node_id, - action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { channel_id: *channel_id, data: error_message } + peer_state.pending_msg_events.push(MessageSendEvent::HandleError { + node_id: counterparty_node_id, + action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { + channel_id: *channel_id, + data: error_message, }, - } - ); + }, + }); } Ok(()) }, - Err(e) => Err(e) + Err(e) => Err(e), } } @@ -4219,8 +4575,9 @@ where /// /// Fails if `channel_id` is unknown to the manager, or if the `counterparty_node_id` /// isn't the counterparty of the corresponding channel. - pub fn force_close_broadcasting_latest_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, error_message: String) - -> Result<(), APIError> { + pub fn force_close_broadcasting_latest_txn( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, error_message: String, + ) -> Result<(), APIError> { self.force_close_sending_error(channel_id, counterparty_node_id, true, error_message) } @@ -4234,8 +4591,9 @@ where /// `counterparty_node_id` isn't the counterparty of the corresponding channel. /// You can always broadcast the latest local transaction(s) via /// [`ChannelMonitor::broadcast_latest_holder_commitment_txn`]. - pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, error_message: String) - -> Result<(), APIError> { + pub fn force_close_without_broadcasting_txn( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, error_message: String, + ) -> Result<(), APIError> { self.force_close_sending_error(channel_id, counterparty_node_id, false, error_message) } @@ -4246,7 +4604,11 @@ where /// be a human-readable description of what went wrong. pub fn force_close_all_channels_broadcasting_latest_txn(&self, error_message: String) { for chan in self.list_channels() { - let _ = self.force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id, error_message.clone()); + let _ = self.force_close_broadcasting_latest_txn( + &chan.channel_id, + &chan.counterparty.node_id, + error_message.clone(), + ); } } @@ -4257,7 +4619,11 @@ where /// should be a human-readable description of what went wrong. pub fn force_close_all_channels_without_broadcasting_txn(&self, error_message: String) { for chan in self.list_channels() { - let _ = self.force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id, error_message.clone()); + let _ = self.force_close_without_broadcasting_txn( + &chan.channel_id, + &chan.counterparty.node_id, + error_message.clone(), + ); } } @@ -4274,14 +4640,20 @@ where /// - `locktime`: Optional locktime for the new funding transaction. If None, set to the current block height. #[cfg(splicing)] pub fn splice_channel( - &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, our_funding_contribution_satoshis: i64, - our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, - funding_feerate_per_kw: u32, locktime: Option, + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, + our_funding_contribution_satoshis: i64, + our_funding_inputs: Vec<(TxIn, Transaction, Weight)>, funding_feerate_per_kw: u32, + locktime: Option, ) -> Result<(), APIError> { let mut res = Ok(()); PersistenceNotifierGuard::optionally_notify(self, || { let result = self.internal_splice_channel( - channel_id, counterparty_node_id, our_funding_contribution_satoshis, &our_funding_inputs, funding_feerate_per_kw, locktime + channel_id, + counterparty_node_id, + our_funding_contribution_satoshis, + &our_funding_inputs, + funding_feerate_per_kw, + locktime, ); res = result; match res { @@ -4295,14 +4667,21 @@ where /// See [`splice_channel`] #[cfg(splicing)] fn internal_splice_channel( - &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, our_funding_contribution_satoshis: i64, - our_funding_inputs: &Vec<(TxIn, Transaction, Weight)>, - funding_feerate_per_kw: u32, locktime: Option, + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, + our_funding_contribution_satoshis: i64, + our_funding_inputs: &Vec<(TxIn, Transaction, Weight)>, funding_feerate_per_kw: u32, + locktime: Option, ) -> Result<(), APIError> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = match per_peer_state.get(counterparty_node_id) - .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) }) { + let peer_state_mutex = match per_peer_state.get(counterparty_node_id).ok_or_else(|| { + APIError::ChannelUnavailable { + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + } + }) { Ok(p) => p, Err(e) => return Err(e), }; @@ -4315,7 +4694,12 @@ where hash_map::Entry::Occupied(mut chan_phase_entry) => { let locktime = locktime.unwrap_or_else(|| self.current_best_block().height); if let Some(chan) = chan_phase_entry.get_mut().as_funded_mut() { - let msg = chan.splice_channel(our_funding_contribution_satoshis, our_funding_inputs, funding_feerate_per_kw, locktime)?; + let msg = chan.splice_channel( + our_funding_contribution_satoshis, + our_funding_inputs, + funding_feerate_per_kw, + locktime, + )?; peer_state.pending_msg_events.push(MessageSendEvent::SendSpliceInit { node_id: *counterparty_node_id, msg, @@ -4326,42 +4710,51 @@ where err: format!( "Channel with id {} is not funded, cannot splice it", channel_id - ) + ), }) } }, - hash_map::Entry::Vacant(_) => { - Err(APIError::ChannelUnavailable { - err: format!( - "Channel with id {} not found for the passed counterparty node_id {}", - channel_id, counterparty_node_id, - ) - }) - }, + hash_map::Entry::Vacant(_) => Err(APIError::ChannelUnavailable { + err: format!( + "Channel with id {} not found for the passed counterparty node_id {}", + channel_id, counterparty_node_id, + ), + }), } } fn can_forward_htlc_to_outgoing_channel( - &self, chan: &mut FundedChannel, msg: &msgs::UpdateAddHTLC, next_packet: &NextPacketDetails + &self, chan: &mut FundedChannel, msg: &msgs::UpdateAddHTLC, + next_packet: &NextPacketDetails, ) -> Result<(), (&'static str, LocalHTLCFailureReason)> { - if !chan.context.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels { + if !chan.context.should_announce() + && !self.default_configuration.accept_forwards_to_priv_channels + { // Note that the behavior here should be identical to the above block - we // should NOT reveal the existence or non-existence of a private channel if // we don't allow forwards outbound over them. - return Err(("Refusing to forward to a private channel based on our config.", - LocalHTLCFailureReason::PrivateChannelForward)); + return Err(( + "Refusing to forward to a private channel based on our config.", + LocalHTLCFailureReason::PrivateChannelForward, + )); } if let HopConnector::ShortChannelId(outgoing_scid) = next_packet.outgoing_connector { - if chan.funding.get_channel_type().supports_scid_privacy() && outgoing_scid != chan.context.outbound_scid_alias() { + if chan.funding.get_channel_type().supports_scid_privacy() + && outgoing_scid != chan.context.outbound_scid_alias() + { // `option_scid_alias` (referred to in LDK as `scid_privacy`) means // "refuse to forward unless the SCID alias was used", so we pretend // we don't have the channel here. - return Err(("Refusing to forward over real channel SCID as our counterparty requested.", - LocalHTLCFailureReason::RealSCIDForward)); + return Err(( + "Refusing to forward over real channel SCID as our counterparty requested.", + LocalHTLCFailureReason::RealSCIDForward, + )); } } else { - return Err(("Cannot forward by Node ID without SCID.", - LocalHTLCFailureReason::InvalidTrampolineForward)); + return Err(( + "Cannot forward by Node ID without SCID.", + LocalHTLCFailureReason::InvalidTrampolineForward, + )); } // Note that we could technically not return an error yet here and just hope @@ -4371,18 +4764,28 @@ where // on a small/per-node/per-channel scale. if !chan.context.is_live() { if !chan.context.is_enabled() { - return Err(("Forwarding channel has been disconnected for some time.", - LocalHTLCFailureReason::ChannelDisabled)); + return Err(( + "Forwarding channel has been disconnected for some time.", + LocalHTLCFailureReason::ChannelDisabled, + )); } else { - return Err(("Forwarding channel is not in a ready state.", - LocalHTLCFailureReason::ChannelNotReady)); + return Err(( + "Forwarding channel is not in a ready state.", + LocalHTLCFailureReason::ChannelNotReady, + )); } } if next_packet.outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { - return Err(("HTLC amount was below the htlc_minimum_msat", - LocalHTLCFailureReason::AmountBelowMinimum)); + return Err(( + "HTLC amount was below the htlc_minimum_msat", + LocalHTLCFailureReason::AmountBelowMinimum, + )); } - chan.htlc_satisfies_config(msg, next_packet.outgoing_amt_msat, next_packet.outgoing_cltv_value)?; + chan.htlc_satisfies_config( + msg, + next_packet.outgoing_amt_msat, + next_packet.outgoing_cltv_value, + )?; Ok(()) } @@ -4392,10 +4795,11 @@ where fn do_funded_channel_callback) -> X>( &self, scid: u64, callback: C, ) -> Option { - let (counterparty_node_id, channel_id) = match self.short_to_chan_info.read().unwrap().get(&scid).cloned() { - None => return None, - Some((cp_id, id)) => (cp_id, id), - }; + let (counterparty_node_id, channel_id) = + match self.short_to_chan_info.read().unwrap().get(&scid).cloned() { + None => return None, + Some((cp_id, id)) => (cp_id, id), + }; let per_peer_state = self.per_peer_state.read().unwrap(); let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id); if peer_state_mutex_opt.is_none() { @@ -4410,14 +4814,16 @@ where } fn can_forward_htlc( - &self, msg: &msgs::UpdateAddHTLC, next_packet_details: &NextPacketDetails + &self, msg: &msgs::UpdateAddHTLC, next_packet_details: &NextPacketDetails, ) -> Result<(), (&'static str, LocalHTLCFailureReason)> { let outgoing_scid = match next_packet_details.outgoing_connector { HopConnector::ShortChannelId(scid) => scid, HopConnector::Trampoline(_) => { - return Err(("Cannot forward by Node ID without SCID.", - LocalHTLCFailureReason::InvalidTrampolineForward)); - } + return Err(( + "Cannot forward by Node ID without SCID.", + LocalHTLCFailureReason::InvalidTrampolineForward, + )); + }, }; match self.do_funded_channel_callback(outgoing_scid, |chan: &mut FundedChannel| { self.can_forward_htlc_to_outgoing_channel(chan, msg, next_packet_details) @@ -4427,18 +4833,31 @@ where None => { // If we couldn't find the channel info for the scid, it may be a phantom or // intercept forward. - if (self.default_configuration.accept_intercept_htlcs && - fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, outgoing_scid, &self.chain_hash)) || - fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, outgoing_scid, &self.chain_hash) - {} else { - return Err(("Don't have available channel for forwarding as requested.", - LocalHTLCFailureReason::UnknownNextPeer)); + if (self.default_configuration.accept_intercept_htlcs + && fake_scid::is_valid_intercept( + &self.fake_scid_rand_bytes, + outgoing_scid, + &self.chain_hash, + )) || fake_scid::is_valid_phantom( + &self.fake_scid_rand_bytes, + outgoing_scid, + &self.chain_hash, + ) { + } else { + return Err(( + "Don't have available channel for forwarding as requested.", + LocalHTLCFailureReason::UnknownNextPeer, + )); } - } + }, } let cur_height = self.best_block.read().unwrap().height + 1; - check_incoming_htlc_cltv(cur_height, next_packet_details.outgoing_cltv_value, msg.cltv_expiry)?; + check_incoming_htlc_cltv( + cur_height, + next_packet_details.outgoing_cltv_value, + msg.cltv_expiry, + )?; Ok(()) } @@ -4446,19 +4865,18 @@ where fn htlc_failure_from_update_add_err( &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, err_msg: &'static str, reason: LocalHTLCFailureReason, is_intro_node_blinded_forward: bool, - shared_secret: &[u8; 32] + shared_secret: &[u8; 32], ) -> HTLCFailureMsg { // at capacity, we write fields `htlc_msat` and `len` let mut res = VecWriter(Vec::with_capacity(8 + 2)); if reason.is_temporary() { - if reason == LocalHTLCFailureReason::AmountBelowMinimum || - reason == LocalHTLCFailureReason::FeeInsufficient { + if reason == LocalHTLCFailureReason::AmountBelowMinimum + || reason == LocalHTLCFailureReason::FeeInsufficient + { msg.amount_msat.write(&mut res).expect("Writes cannot fail"); - } - else if reason == LocalHTLCFailureReason::IncorrectCLTVExpiry { + } else if reason == LocalHTLCFailureReason::IncorrectCLTVExpiry { msg.cltv_expiry.write(&mut res).expect("Writes cannot fail"); - } - else if reason == LocalHTLCFailureReason::ChannelDisabled { + } else if reason == LocalHTLCFailureReason::ChannelDisabled { // TODO: underspecified, follow https://github.com/lightning/bolts/issues/791 0u16.write(&mut res).expect("Writes cannot fail"); } @@ -4467,8 +4885,14 @@ where } log_info!( - WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id), Some(msg.payment_hash)), - "Failed to accept/forward incoming HTLC: {}", err_msg + WithContext::from( + &self.logger, + Some(*counterparty_node_id), + Some(msg.channel_id), + Some(msg.payment_hash) + ), + "Failed to accept/forward incoming HTLC: {}", + err_msg ); // If `msg.blinding_point` is set, we must always fail with malformed. if msg.blinding_point.is_some() { @@ -4486,7 +4910,7 @@ where (reason, &res.0[..]) }; let failure = HTLCFailReason::reason(reason, err_data.to_vec()) - .get_encrypted_failure_packet(shared_secret, &None); + .get_encrypted_failure_packet(shared_secret, &None); HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { channel_id: msg.channel_id, htlc_id: msg.htlc_id, @@ -4497,24 +4921,27 @@ where fn construct_pending_htlc_fail_msg<'a>( &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, - shared_secret: [u8; 32], inbound_err: InboundHTLCErr + shared_secret: [u8; 32], inbound_err: InboundHTLCErr, ) -> HTLCFailureMsg { - let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id), Some(msg.payment_hash)); + let logger = WithContext::from( + &self.logger, + Some(*counterparty_node_id), + Some(msg.channel_id), + Some(msg.payment_hash), + ); log_info!(logger, "Failed to accept/forward incoming HTLC: {}", inbound_err.msg); if msg.blinding_point.is_some() { - return HTLCFailureMsg::Malformed( - msgs::UpdateFailMalformedHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - sha256_of_onion: [0; 32], - failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(), - } - ) + return HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + sha256_of_onion: [0; 32], + failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(), + }); } let failure = HTLCFailReason::reason(inbound_err.reason, inbound_err.err_data.to_vec()) - .get_encrypted_failure_packet(&shared_secret, &None); + .get_encrypted_failure_packet(&shared_secret, &None); return HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { channel_id: msg.channel_id, htlc_id: msg.htlc_id, @@ -4524,29 +4951,47 @@ where } fn get_pending_htlc_info<'a>( - &self, msg: &msgs::UpdateAddHTLC, shared_secret: [u8; 32], - decoded_hop: onion_utils::Hop, allow_underpay: bool, - next_packet_pubkey_opt: Option>, + &self, msg: &msgs::UpdateAddHTLC, shared_secret: [u8; 32], decoded_hop: onion_utils::Hop, + allow_underpay: bool, next_packet_pubkey_opt: Option>, ) -> Result { match decoded_hop { - onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } | - onion_utils::Hop::TrampolineReceive { .. } | onion_utils::Hop::TrampolineBlindedReceive { .. } => { + onion_utils::Hop::Receive { .. } + | onion_utils::Hop::BlindedReceive { .. } + | onion_utils::Hop::TrampolineReceive { .. } + | onion_utils::Hop::TrampolineBlindedReceive { .. } => { // OUR PAYMENT! // Note that we could obviously respond immediately with an update_fulfill_htlc // message, however that would leak that we are the recipient of this payment, so // instead we stay symmetric with the forwarding case, only responding (after a // delay) once they've send us a commitment_signed! let current_height: u32 = self.best_block.read().unwrap().height; - create_recv_pending_htlc_info(decoded_hop, shared_secret, msg.payment_hash, - msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat, - current_height) + create_recv_pending_htlc_info( + decoded_hop, + shared_secret, + msg.payment_hash, + msg.amount_msat, + msg.cltv_expiry, + None, + allow_underpay, + msg.skimmed_fee_msat, + current_height, + ) }, onion_utils::Hop::Forward { .. } | onion_utils::Hop::BlindedForward { .. } => { - create_fwd_pending_htlc_info(msg, decoded_hop, shared_secret, next_packet_pubkey_opt) - }, - onion_utils::Hop::TrampolineForward { .. } | onion_utils::Hop::TrampolineBlindedForward { .. } => { - create_fwd_pending_htlc_info(msg, decoded_hop, shared_secret, next_packet_pubkey_opt) + create_fwd_pending_htlc_info( + msg, + decoded_hop, + shared_secret, + next_packet_pubkey_opt, + ) }, + onion_utils::Hop::TrampolineForward { .. } + | onion_utils::Hop::TrampolineBlindedForward { .. } => create_fwd_pending_htlc_info( + msg, + decoded_hop, + shared_secret, + next_packet_pubkey_opt, + ), } } @@ -4560,18 +5005,27 @@ where /// /// [`channel_update`]: msgs::ChannelUpdate /// [`internal_closing_signed`]: Self::internal_closing_signed - fn get_channel_update_for_broadcast(&self, chan: &FundedChannel) -> Result { + fn get_channel_update_for_broadcast( + &self, chan: &FundedChannel, + ) -> Result { if !chan.context.should_announce() { return Err(LightningError { err: "Cannot broadcast a channel_update for a private channel".to_owned(), - action: msgs::ErrorAction::IgnoreError + action: msgs::ErrorAction::IgnoreError, }); } if chan.context.get_short_channel_id().is_none() { - return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Channel not yet established".to_owned(), + action: msgs::ErrorAction::IgnoreError, + }); } let logger = WithChannelContext::from(&self.logger, &chan.context, None); - log_trace!(logger, "Attempting to generate broadcast channel update for channel {}", &chan.context.channel_id()); + log_trace!( + logger, + "Attempting to generate broadcast channel update for channel {}", + &chan.context.channel_id() + ); self.get_channel_update_for_unicast(chan) } @@ -4586,17 +5040,33 @@ where /// /// [`channel_update`]: msgs::ChannelUpdate /// [`internal_closing_signed`]: Self::internal_closing_signed - fn get_channel_update_for_unicast(&self, chan: &FundedChannel) -> Result { + fn get_channel_update_for_unicast( + &self, chan: &FundedChannel, + ) -> Result { let logger = WithChannelContext::from(&self.logger, &chan.context, None); - log_trace!(logger, "Attempting to generate channel update for channel {}", chan.context.channel_id()); - let short_channel_id = match chan.context.get_short_channel_id().or(chan.context.latest_inbound_scid_alias()) { - None => return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}), + log_trace!( + logger, + "Attempting to generate channel update for channel {}", + chan.context.channel_id() + ); + let short_channel_id = match chan + .context + .get_short_channel_id() + .or(chan.context.latest_inbound_scid_alias()) + { + None => { + return Err(LightningError { + err: "Channel not yet established".to_owned(), + action: msgs::ErrorAction::IgnoreError, + }) + }, Some(id) => id, }; let logger = WithChannelContext::from(&self.logger, &chan.context, None); log_trace!(logger, "Generating channel update for channel {}", chan.context.channel_id()); - let were_node_one = self.our_network_pubkey.serialize()[..] < chan.context.get_counterparty_node_id().serialize()[..]; + let were_node_one = self.our_network_pubkey.serialize()[..] + < chan.context.get_counterparty_node_id().serialize()[..]; let enabled = chan.context.is_enabled(); let unsigned = msgs::UnsignedChannelUpdate { @@ -4616,27 +5086,45 @@ where // If we returned an error and the `node_signer` cannot provide a signature for whatever // reason`, we wouldn't be able to receive inbound payments through the corresponding // channel. - let sig = self.node_signer.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&unsigned)).unwrap(); + let sig = self + .node_signer + .sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&unsigned)) + .unwrap(); - Ok(msgs::ChannelUpdate { - signature: sig, - contents: unsigned - }) + Ok(msgs::ChannelUpdate { signature: sig, contents: unsigned }) } #[cfg(any(test, feature = "_externalize_tests"))] - pub(crate) fn test_send_payment_along_path(&self, path: &Path, payment_hash: &PaymentHash, recipient_onion: RecipientOnionFields, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option, session_priv_bytes: [u8; 32]) -> Result<(), APIError> { + pub(crate) fn test_send_payment_along_path( + &self, path: &Path, payment_hash: &PaymentHash, recipient_onion: RecipientOnionFields, + total_value: u64, cur_height: u32, payment_id: PaymentId, + keysend_preimage: &Option, session_priv_bytes: [u8; 32], + ) -> Result<(), APIError> { let _lck = self.total_consistency_lock.read().unwrap(); self.send_payment_along_path(SendAlongPathArgs { - path, payment_hash, recipient_onion: &recipient_onion, total_value, - cur_height, payment_id, keysend_preimage, invoice_request: None, session_priv_bytes + path, + payment_hash, + recipient_onion: &recipient_onion, + total_value, + cur_height, + payment_id, + keysend_preimage, + invoice_request: None, + session_priv_bytes, }) } fn send_payment_along_path(&self, args: SendAlongPathArgs) -> Result<(), APIError> { let SendAlongPathArgs { - path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, - invoice_request, session_priv_bytes + path, + payment_hash, + recipient_onion, + total_value, + cur_height, + payment_id, + keysend_preimage, + invoice_request, + session_priv_bytes, } = args; // The top-level caller should hold the total_consistency_lock read lock. debug_assert!(self.total_consistency_lock.try_write().is_err()); @@ -4644,52 +5132,119 @@ where let session_priv = SecretKey::from_slice(&session_priv_bytes[..]).expect("RNG is busted"); let (onion_packet, htlc_msat, htlc_cltv) = onion_utils::create_payment_onion( - &self.secp_ctx, &path, &session_priv, total_value, recipient_onion, cur_height, - payment_hash, keysend_preimage, invoice_request, prng_seed - ).map_err(|e| { - let logger = WithContext::from(&self.logger, Some(path.hops.first().unwrap().pubkey), None, Some(*payment_hash)); - log_error!(logger, "Failed to build an onion for path for payment hash {}", payment_hash); + &self.secp_ctx, + &path, + &session_priv, + total_value, + recipient_onion, + cur_height, + payment_hash, + keysend_preimage, + invoice_request, + prng_seed, + ) + .map_err(|e| { + let logger = WithContext::from( + &self.logger, + Some(path.hops.first().unwrap().pubkey), + None, + Some(*payment_hash), + ); + log_error!( + logger, + "Failed to build an onion for path for payment hash {}", + payment_hash + ); e })?; let err: Result<(), _> = loop { - let (counterparty_node_id, id) = match self.short_to_chan_info.read().unwrap().get(&path.hops.first().unwrap().short_channel_id) { + let (counterparty_node_id, id) = match self + .short_to_chan_info + .read() + .unwrap() + .get(&path.hops.first().unwrap().short_channel_id) + { None => { - let logger = WithContext::from(&self.logger, Some(path.hops.first().unwrap().pubkey), None, Some(*payment_hash)); - log_error!(logger, "Failed to find first-hop for payment hash {}", payment_hash); - return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!".to_owned()}) + let logger = WithContext::from( + &self.logger, + Some(path.hops.first().unwrap().pubkey), + None, + Some(*payment_hash), + ); + log_error!( + logger, + "Failed to find first-hop for payment hash {}", + payment_hash + ); + return Err(APIError::ChannelUnavailable { + err: "No channel available with first hop!".to_owned(), + }); }, Some((cp_id, chan_id)) => (cp_id.clone(), chan_id.clone()), }; - let logger = WithContext::from(&self.logger, Some(counterparty_node_id), Some(id), Some(*payment_hash)); - log_trace!(logger, + let logger = WithContext::from( + &self.logger, + Some(counterparty_node_id), + Some(id), + Some(*payment_hash), + ); + log_trace!( + logger, "Attempting to send payment with payment hash {} along path with next hop {}", - payment_hash, path.hops.first().unwrap().short_channel_id); + payment_hash, + path.hops.first().unwrap().short_channel_id + ); let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(&counterparty_node_id) - .ok_or_else(|| APIError::ChannelUnavailable{err: "No peer matching the path's first hop found!".to_owned() })?; + let peer_state_mutex = per_peer_state.get(&counterparty_node_id).ok_or_else(|| { + APIError::ChannelUnavailable { + err: "No peer matching the path's first hop found!".to_owned(), + } + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; if let hash_map::Entry::Occupied(mut chan_entry) = peer_state.channel_by_id.entry(id) { match chan_entry.get_mut().as_funded_mut() { Some(chan) => { if !chan.context.is_live() { - return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected".to_owned()}); + return Err(APIError::ChannelUnavailable { + err: "Peer for first hop currently disconnected".to_owned(), + }); } let funding_txo = chan.funding.get_funding_txo().unwrap(); - let logger = WithChannelContext::from(&self.logger, &chan.context, Some(*payment_hash)); - let send_res = chan.send_htlc_and_commit(htlc_msat, payment_hash.clone(), - htlc_cltv, HTLCSource::OutboundRoute { + let logger = WithChannelContext::from( + &self.logger, + &chan.context, + Some(*payment_hash), + ); + let send_res = chan.send_htlc_and_commit( + htlc_msat, + payment_hash.clone(), + htlc_cltv, + HTLCSource::OutboundRoute { path: path.clone(), session_priv: session_priv.clone(), first_hop_htlc_msat: htlc_msat, payment_id, - }, onion_packet, None, &self.fee_estimator, &&logger); + }, + onion_packet, + None, + &self.fee_estimator, + &&logger, + ); match break_channel_entry!(self, peer_state, send_res, chan_entry) { Some(monitor_update) => { - match handle_new_monitor_update!(self, funding_txo, monitor_update, peer_state_lock, peer_state, per_peer_state, chan) { + match handle_new_monitor_update!( + self, + funding_txo, + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ) { false => { // Note that MonitorUpdateInProgress here indicates (per function // docs) that we will resend the commitment update once monitor @@ -4705,22 +5260,26 @@ where None => {}, } }, - None => return Err(APIError::ChannelUnavailable{err: "Channel to first hop is unfunded".to_owned()}), + None => { + return Err(APIError::ChannelUnavailable { + err: "Channel to first hop is unfunded".to_owned(), + }) + }, }; } else { // The channel was likely removed after we fetched the id from the // `short_to_chan_info` map, but before we successfully locked the // `channel_by_id` map. // This can occur as no consistency guarantees exists between the two maps. - return Err(APIError::ChannelUnavailable{err: "No channel available with first hop!".to_owned()}); + return Err(APIError::ChannelUnavailable { + err: "No channel available with first hop!".to_owned(), + }); } return Ok(()); }; match handle_error!(self, err, path.hops.first().unwrap().pubkey) { Ok(_) => unreachable!(), - Err(e) => { - Err(APIError::ChannelUnavailable { err: e.err }) - }, + Err(e) => Err(APIError::ChannelUnavailable { err: e.err }), } } @@ -4730,25 +5289,47 @@ where /// [`Event::PaymentFailed`] is generated. pub fn send_payment_with_route( &self, mut route: Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, - payment_id: PaymentId + payment_id: PaymentId, ) -> Result<(), RetryableSendFailure> { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let route_params = route.route_params.clone().unwrap_or_else(|| { // Create a dummy route params since they're a required parameter but unused in this case - let (payee_node_id, cltv_delta) = route.paths.first() - .and_then(|path| path.hops.last().map(|hop| (hop.pubkey, hop.cltv_expiry_delta as u32))) - .unwrap_or_else(|| (PublicKey::from_slice(&[2; 32]).unwrap(), MIN_FINAL_CLTV_EXPIRY_DELTA as u32)); + let (payee_node_id, cltv_delta) = route + .paths + .first() + .and_then(|path| { + path.hops.last().map(|hop| (hop.pubkey, hop.cltv_expiry_delta as u32)) + }) + .unwrap_or_else(|| { + (PublicKey::from_slice(&[2; 32]).unwrap(), MIN_FINAL_CLTV_EXPIRY_DELTA as u32) + }); let dummy_payment_params = PaymentParameters::from_node_id(payee_node_id, cltv_delta); - RouteParameters::from_payment_params_and_value(dummy_payment_params, route.get_total_amount()) + RouteParameters::from_payment_params_and_value( + dummy_payment_params, + route.get_total_amount(), + ) }); - if route.route_params.is_none() { route.route_params = Some(route_params.clone()); } + if route.route_params.is_none() { + route.route_params = Some(route_params.clone()); + } let router = FixedRouter::new(route); - self.pending_outbound_payments - .send_payment(payment_hash, recipient_onion, payment_id, Retry::Attempts(0), - route_params, &&router, self.list_usable_channels(), || self.compute_inflight_htlcs(), - &self.entropy_source, &self.node_signer, best_block_height, &self.logger, - &self.pending_events, |args| self.send_payment_along_path(args)) + self.pending_outbound_payments.send_payment( + payment_hash, + recipient_onion, + payment_id, + Retry::Attempts(0), + route_params, + &&router, + self.list_usable_channels(), + || self.compute_inflight_htlcs(), + &self.entropy_source, + &self.node_signer, + best_block_height, + &self.logger, + &self.pending_events, + |args| self.send_payment_along_path(args), + ) } /// Sends a payment to the route found using the provided [`RouteParameters`], retrying failed @@ -4786,46 +5367,85 @@ where /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events /// [`ChannelMonitorUpdateStatus::InProgress`]: crate::chain::ChannelMonitorUpdateStatus::InProgress pub fn send_payment( - &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, - route_params: RouteParameters, retry_strategy: Retry + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry, ) -> Result<(), RetryableSendFailure> { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.pending_outbound_payments - .send_payment(payment_hash, recipient_onion, payment_id, retry_strategy, route_params, - &self.router, self.list_usable_channels(), || self.compute_inflight_htlcs(), - &self.entropy_source, &self.node_signer, best_block_height, &self.logger, - &self.pending_events, |args| self.send_payment_along_path(args)) + self.pending_outbound_payments.send_payment( + payment_hash, + recipient_onion, + payment_id, + retry_strategy, + route_params, + &self.router, + self.list_usable_channels(), + || self.compute_inflight_htlcs(), + &self.entropy_source, + &self.node_signer, + best_block_height, + &self.logger, + &self.pending_events, + |args| self.send_payment_along_path(args), + ) } #[cfg(any(test, feature = "_externalize_tests"))] - pub(super) fn test_send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, keysend_preimage: Option, payment_id: PaymentId, recv_value_msat: Option, onion_session_privs: Vec<[u8; 32]>) -> Result<(), PaymentSendFailure> { + pub(super) fn test_send_payment_internal( + &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + keysend_preimage: Option, payment_id: PaymentId, + recv_value_msat: Option, onion_session_privs: Vec<[u8; 32]>, + ) -> Result<(), PaymentSendFailure> { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.pending_outbound_payments.test_send_payment_internal(route, payment_hash, recipient_onion, - keysend_preimage, payment_id, recv_value_msat, onion_session_privs, &self.node_signer, - best_block_height, |args| self.send_payment_along_path(args)) + self.pending_outbound_payments.test_send_payment_internal( + route, + payment_hash, + recipient_onion, + keysend_preimage, + payment_id, + recv_value_msat, + onion_session_privs, + &self.node_signer, + best_block_height, + |args| self.send_payment_along_path(args), + ) } #[cfg(any(test, feature = "_externalize_tests"))] - pub(crate) fn test_add_new_pending_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route: &Route) -> Result, PaymentSendFailure> { + pub(crate) fn test_add_new_pending_payment( + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + payment_id: PaymentId, route: &Route, + ) -> Result, PaymentSendFailure> { let best_block_height = self.best_block.read().unwrap().height; - self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, recipient_onion, payment_id, route, None, &self.entropy_source, best_block_height) + self.pending_outbound_payments.test_add_new_pending_payment( + payment_hash, + recipient_onion, + payment_id, + route, + None, + &self.entropy_source, + best_block_height, + ) } #[cfg(all(test, async_payments))] - pub(crate) fn test_modify_pending_payment( - &self, payment_id: &PaymentId, mut callback: Fn - ) where Fn: FnMut(&mut PendingOutboundPayment) { - let mut outbounds = self.pending_outbound_payments.pending_outbound_payments.lock().unwrap(); + pub(crate) fn test_modify_pending_payment(&self, payment_id: &PaymentId, mut callback: Fn) + where + Fn: FnMut(&mut PendingOutboundPayment), + { + let mut outbounds = + self.pending_outbound_payments.pending_outbound_payments.lock().unwrap(); match outbounds.get_mut(payment_id) { Some(outb) => callback(outb), - _ => panic!() + _ => panic!(), } } #[cfg(test)] - pub(crate) fn test_set_payment_metadata(&self, payment_id: PaymentId, new_payment_metadata: Option>) { + pub(crate) fn test_set_payment_metadata( + &self, payment_id: PaymentId, new_payment_metadata: Option>, + ) { self.pending_outbound_payments.test_set_payment_metadata(payment_id, new_payment_metadata); } @@ -4846,15 +5466,26 @@ where /// To use default settings, call the function with `RouteParametersConfig::default()`. pub fn pay_for_bolt11_invoice( &self, invoice: &Bolt11Invoice, payment_id: PaymentId, amount_msats: Option, - route_params_config: RouteParametersConfig, retry_strategy: Retry + route_params_config: RouteParametersConfig, retry_strategy: Retry, ) -> Result<(), Bolt11PaymentError> { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.pending_outbound_payments - .pay_for_bolt11_invoice(invoice, payment_id, amount_msats, route_params_config, retry_strategy, - &self.router, self.list_usable_channels(), || self.compute_inflight_htlcs(), - &self.entropy_source, &self.node_signer, best_block_height, &self.logger, - &self.pending_events, |args| self.send_payment_along_path(args)) + self.pending_outbound_payments.pay_for_bolt11_invoice( + invoice, + payment_id, + amount_msats, + route_params_config, + retry_strategy, + &self.router, + self.list_usable_channels(), + || self.compute_inflight_htlcs(), + &self.entropy_source, + &self.node_signer, + best_block_height, + &self.logger, + &self.pending_events, + |args| self.send_payment_along_path(args), + ) } /// Pays the [`Bolt12Invoice`] associated with the `payment_id` encoded in its `payer_metadata`. @@ -4903,62 +5534,84 @@ where } } - fn send_payment_for_verified_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> { + fn send_payment_for_verified_bolt12_invoice( + &self, invoice: &Bolt12Invoice, payment_id: PaymentId, + ) -> Result<(), Bolt12PaymentError> { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let features = self.bolt12_invoice_features(); - self.pending_outbound_payments - .send_payment_for_bolt12_invoice( - invoice, payment_id, &self.router, self.list_usable_channels(), features, - || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, &self, - &self.secp_ctx, best_block_height, &self.logger, &self.pending_events, - |args| self.send_payment_along_path(args) - ) + self.pending_outbound_payments.send_payment_for_bolt12_invoice( + invoice, + payment_id, + &self.router, + self.list_usable_channels(), + features, + || self.compute_inflight_htlcs(), + &self.entropy_source, + &self.node_signer, + &self, + &self.secp_ctx, + best_block_height, + &self.logger, + &self.pending_events, + |args| self.send_payment_along_path(args), + ) } #[cfg(async_payments)] fn initiate_async_payment( - &self, invoice: &StaticInvoice, payment_id: PaymentId + &self, invoice: &StaticInvoice, payment_id: PaymentId, ) -> Result<(), Bolt12PaymentError> { let mut res = Ok(()); PersistenceNotifierGuard::optionally_notify(self, || { let best_block_height = self.best_block.read().unwrap().height; let features = self.bolt12_invoice_features(); let outbound_pmts_res = self.pending_outbound_payments.static_invoice_received( - invoice, payment_id, features, best_block_height, self.duration_since_epoch(), - &*self.entropy_source, &self.pending_events + invoice, + payment_id, + features, + best_block_height, + self.duration_since_epoch(), + &*self.entropy_source, + &self.pending_events, ); match outbound_pmts_res { Ok(()) => {}, - Err(Bolt12PaymentError::UnexpectedInvoice) | Err(Bolt12PaymentError::DuplicateInvoice) => { + Err(Bolt12PaymentError::UnexpectedInvoice) + | Err(Bolt12PaymentError::DuplicateInvoice) => { res = outbound_pmts_res.map(|_| ()); - return NotifyOption::SkipPersistNoEvents + return NotifyOption::SkipPersistNoEvents; }, Err(e) => { res = Err(e); - return NotifyOption::DoPersist - } + return NotifyOption::DoPersist; + }, }; let nonce = Nonce::from_entropy_source(&*self.entropy_source); let hmac = payment_id.hmac_for_async_payment(nonce, &self.inbound_payment_key); - let reply_paths = match self.create_blinded_paths( - MessageContext::AsyncPayments( - AsyncPaymentsContext::OutboundPayment { payment_id, nonce, hmac } - ) - ) { + let reply_paths = match self.create_blinded_paths(MessageContext::AsyncPayments( + AsyncPaymentsContext::OutboundPayment { payment_id, nonce, hmac }, + )) { Ok(paths) => paths, Err(()) => { - self.abandon_payment_with_reason(payment_id, PaymentFailureReason::BlindedPathCreationFailed); + self.abandon_payment_with_reason( + payment_id, + PaymentFailureReason::BlindedPathCreationFailed, + ); res = Err(Bolt12PaymentError::BlindedPathCreationFailed); - return NotifyOption::DoPersist - } + return NotifyOption::DoPersist; + }, }; - let mut pending_async_payments_messages = self.pending_async_payments_messages.lock().unwrap(); + let mut pending_async_payments_messages = + self.pending_async_payments_messages.lock().unwrap(); let message = AsyncPaymentsMessage::HeldHtlcAvailable(HeldHtlcAvailable {}); enqueue_onion_message_with_reply_paths( - message, invoice.message_paths(), reply_paths, &mut pending_async_payments_messages + message, + invoice.message_paths(), + reply_paths, + &mut pending_async_payments_messages, ); NotifyOption::DoPersist @@ -4969,25 +5622,35 @@ where #[cfg(async_payments)] fn send_payment_for_static_invoice( - &self, payment_id: PaymentId + &self, payment_id: PaymentId, ) -> Result<(), Bolt12PaymentError> { let best_block_height = self.best_block.read().unwrap().height; let mut res = Ok(()); PersistenceNotifierGuard::optionally_notify(self, || { let outbound_pmts_res = self.pending_outbound_payments.send_payment_for_static_invoice( - payment_id, &self.router, self.list_usable_channels(), || self.compute_inflight_htlcs(), - &self.entropy_source, &self.node_signer, &self, &self.secp_ctx, best_block_height, - &self.logger, &self.pending_events, |args| self.send_payment_along_path(args) + payment_id, + &self.router, + self.list_usable_channels(), + || self.compute_inflight_htlcs(), + &self.entropy_source, + &self.node_signer, + &self, + &self.secp_ctx, + best_block_height, + &self.logger, + &self.pending_events, + |args| self.send_payment_along_path(args), ); match outbound_pmts_res { - Err(Bolt12PaymentError::UnexpectedInvoice) | Err(Bolt12PaymentError::DuplicateInvoice) => { + Err(Bolt12PaymentError::UnexpectedInvoice) + | Err(Bolt12PaymentError::DuplicateInvoice) => { res = outbound_pmts_res.map(|_| ()); NotifyOption::SkipPersistNoEvents }, other_res => { res = other_res; NotifyOption::DoPersist - } + }, } }); res @@ -5046,14 +5709,26 @@ where /// [`PaymentParameters::for_keysend`]: crate::routing::router::PaymentParameters::for_keysend pub fn send_spontaneous_payment( &self, payment_preimage: Option, recipient_onion: RecipientOnionFields, - payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry + payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry, ) -> Result { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.pending_outbound_payments.send_spontaneous_payment(payment_preimage, recipient_onion, - payment_id, retry_strategy, route_params, &self.router, self.list_usable_channels(), - || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, - &self.logger, &self.pending_events, |args| self.send_payment_along_path(args)) + self.pending_outbound_payments.send_spontaneous_payment( + payment_preimage, + recipient_onion, + payment_id, + retry_strategy, + route_params, + &self.router, + self.list_usable_channels(), + || self.compute_inflight_htlcs(), + &self.entropy_source, + &self.node_signer, + best_block_height, + &self.logger, + &self.pending_events, + |args| self.send_payment_along_path(args), + ) } /// Send a payment that is probing the given route for liquidity. We calculate the @@ -5062,15 +5737,22 @@ where pub fn send_probe(&self, path: Path) -> Result<(PaymentHash, PaymentId), ProbeSendFailure> { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.pending_outbound_payments.send_probe(path, self.probing_cookie_secret, - &self.entropy_source, &self.node_signer, best_block_height, - |args| self.send_payment_along_path(args)) + self.pending_outbound_payments.send_probe( + path, + self.probing_cookie_secret, + &self.entropy_source, + &self.node_signer, + best_block_height, + |args| self.send_payment_along_path(args), + ) } /// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a /// payment probe. #[cfg(test)] - pub(crate) fn payment_is_probe(&self, payment_hash: &PaymentHash, payment_id: &PaymentId) -> bool { + pub(crate) fn payment_is_probe( + &self, payment_hash: &PaymentHash, payment_id: &PaymentId, + ) -> bool { outbound_payment::payment_is_probe(payment_hash, payment_id, self.probing_cookie_secret) } @@ -5082,10 +5764,10 @@ where &self, node_id: PublicKey, amount_msat: u64, final_cltv_expiry_delta: u32, liquidity_limit_multiplier: Option, ) -> Result, ProbeSendFailure> { - let payment_params = - PaymentParameters::from_node_id(node_id, final_cltv_expiry_delta); + let payment_params = PaymentParameters::from_node_id(node_id, final_cltv_expiry_delta); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, amount_msat); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, amount_msat); self.send_preflight_probes(route_params, liquidity_limit_multiplier) } @@ -5186,34 +5868,49 @@ where /// Handles the generation of a funding transaction, optionally (for tests) with a function /// which checks the correctness of the funding transaction given the associated channel. - fn funding_transaction_generated_intern) -> Result>( - &self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, funding_transaction: Transaction, is_batch_funding: bool, + fn funding_transaction_generated_intern< + FundingOutput: FnMut(&OutboundV1Channel) -> Result, + >( + &self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, + funding_transaction: Transaction, is_batch_funding: bool, mut find_funding_output: FundingOutput, is_manual_broadcast: bool, ) -> Result<(), APIError> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(&counterparty_node_id) - .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?; + let peer_state_mutex = per_peer_state.get(&counterparty_node_id).ok_or_else(|| { + APIError::ChannelUnavailable { + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + } + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - macro_rules! close_chan { ($err: expr, $api_err: expr, $chan: expr) => { { - let counterparty; - let err = if let ChannelError::Close((msg, reason)) = $err { - let channel_id = $chan.context.channel_id(); - counterparty = $chan.context.get_counterparty_node_id(); - let shutdown_res = $chan.context.force_shutdown(&$chan.funding, false, reason); - MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None) - } else { unreachable!(); }; + macro_rules! close_chan { + ($err: expr, $api_err: expr, $chan: expr) => {{ + let counterparty; + let err = if let ChannelError::Close((msg, reason)) = $err { + let channel_id = $chan.context.channel_id(); + counterparty = $chan.context.get_counterparty_node_id(); + let shutdown_res = $chan.context.force_shutdown(&$chan.funding, false, reason); + MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None) + } else { + unreachable!(); + }; - mem::drop(peer_state_lock); - mem::drop(per_peer_state); - let _: Result<(), _> = handle_error!(self, Err(err), counterparty); - Err($api_err) - } } } + mem::drop(peer_state_lock); + mem::drop(per_peer_state); + let _: Result<(), _> = handle_error!(self, Err(err), counterparty); + Err($api_err) + }}; + } let funding_txo; - let (mut chan, msg_opt) = match peer_state.channel_by_id.remove(&temporary_channel_id) + let (mut chan, msg_opt) = match peer_state + .channel_by_id + .remove(&temporary_channel_id) .map(Channel::into_unfunded_outbound_v1) { Some(Ok(mut chan)) => { @@ -5227,13 +5924,21 @@ where } let logger = WithChannelContext::from(&self.logger, &chan.context, None); - let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger); + let funding_res = chan.get_funding_created( + funding_transaction, + funding_txo, + is_batch_funding, + &&logger, + ); match funding_res { Ok(funding_msg) => (chan, funding_msg), Err((mut chan, chan_err)) => { - let api_err = APIError::ChannelUnavailable { err: "Signer refused to sign the initial commitment transaction".to_owned() }; + let api_err = APIError::ChannelUnavailable { + err: "Signer refused to sign the initial commitment transaction" + .to_owned(), + }; return close_chan!(chan_err, api_err, chan); - } + }, } }, Some(Err(chan)) => { @@ -5242,12 +5947,16 @@ where err: format!( "Channel with id {} for the passed counterparty node_id {} is not an unfunded, outbound V1 channel", temporary_channel_id, counterparty_node_id), + }); + }, + None => { + return Err(APIError::ChannelUnavailable { + err: format!( + "Channel with id {} not found for the passed counterparty node_id {}", + temporary_channel_id, counterparty_node_id + ), }) }, - None => return Err(APIError::ChannelUnavailable {err: format!( - "Channel with id {} not found for the passed counterparty node_id {}", - temporary_channel_id, counterparty_node_id), - }), }; match peer_state.channel_by_id.entry(chan.context.channel_id()) { @@ -5256,7 +5965,8 @@ where // channel and instead close the one pending. let err = format!( "An existing channel using ID {} is open with peer {}", - chan.context.channel_id(), chan.context.get_counterparty_node_id(), + chan.context.channel_id(), + chan.context.get_counterparty_node_id(), ); let chan_err = ChannelError::close(err.to_owned()); let api_err = APIError::APIMisuseError { err: err.to_owned() }; @@ -5276,16 +5986,24 @@ where e.insert(Channel::from(chan)); Ok(()) - } + }, } } #[cfg(any(test, feature = "_externalize_tests"))] - pub(crate) fn funding_transaction_generated_unchecked(&self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, funding_transaction: Transaction, output_index: u16) -> Result<(), APIError> { + pub(crate) fn funding_transaction_generated_unchecked( + &self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, + funding_transaction: Transaction, output_index: u16, + ) -> Result<(), APIError> { let txid = funding_transaction.compute_txid(); - self.funding_transaction_generated_intern(temporary_channel_id, counterparty_node_id, funding_transaction, false, |_| { - Ok(OutPoint { txid, index: output_index }) - }, false) + self.funding_transaction_generated_intern( + temporary_channel_id, + counterparty_node_id, + funding_transaction, + false, + |_| Ok(OutPoint { txid, index: output_index }), + false, + ) } /// Call this upon creation of a funding transaction for the given channel. @@ -5318,11 +6036,16 @@ where /// /// [`Event::FundingGenerationReady`]: crate::events::Event::FundingGenerationReady /// [`Event::ChannelClosed`]: crate::events::Event::ChannelClosed - pub fn funding_transaction_generated(&self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, funding_transaction: Transaction) -> Result<(), APIError> { - self.batch_funding_transaction_generated(&[(&temporary_channel_id, &counterparty_node_id)], funding_transaction) + pub fn funding_transaction_generated( + &self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, + funding_transaction: Transaction, + ) -> Result<(), APIError> { + self.batch_funding_transaction_generated( + &[(&temporary_channel_id, &counterparty_node_id)], + funding_transaction, + ) } - /// **Unsafe**: This method does not validate the spent output. It is the caller's /// responsibility to ensure the spent outputs are SegWit, as well as making sure the funding /// transaction has a final absolute locktime, i.e., its locktime is lower than the next block height. @@ -5350,12 +6073,16 @@ where /// [`Event::FundingTxBroadcastSafe`]: crate::events::Event::FundingTxBroadcastSafe /// [`Event::ChannelClosed`]: crate::events::Event::ChannelClosed /// [`ChannelManager::funding_transaction_generated`]: crate::ln::channelmanager::ChannelManager::funding_transaction_generated - pub fn unsafe_manual_funding_transaction_generated(&self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, funding: OutPoint) -> Result<(), APIError> { + pub fn unsafe_manual_funding_transaction_generated( + &self, temporary_channel_id: ChannelId, counterparty_node_id: PublicKey, funding: OutPoint, + ) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let temporary_channels = &[(&temporary_channel_id, &counterparty_node_id)]; - return self.batch_funding_transaction_generated_intern(temporary_channels, FundingType::Unchecked(funding)); - + return self.batch_funding_transaction_generated_intern( + temporary_channels, + FundingType::Unchecked(funding), + ); } /// Call this upon creation of a batch funding transaction for the given channels. @@ -5368,19 +6095,28 @@ where /// signature for each channel. /// /// If there is an error, all channels in the batch are to be considered closed. - pub fn batch_funding_transaction_generated(&self, temporary_channels: &[(&ChannelId, &PublicKey)], funding_transaction: Transaction) -> Result<(), APIError> { + pub fn batch_funding_transaction_generated( + &self, temporary_channels: &[(&ChannelId, &PublicKey)], funding_transaction: Transaction, + ) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.batch_funding_transaction_generated_intern(temporary_channels, FundingType::Checked(funding_transaction)) + self.batch_funding_transaction_generated_intern( + temporary_channels, + FundingType::Checked(funding_transaction), + ) } - fn batch_funding_transaction_generated_intern(&self, temporary_channels: &[(&ChannelId, &PublicKey)], funding: FundingType) -> Result<(), APIError> { + fn batch_funding_transaction_generated_intern( + &self, temporary_channels: &[(&ChannelId, &PublicKey)], funding: FundingType, + ) -> Result<(), APIError> { let mut result = Ok(()); if let FundingType::Checked(funding_transaction) = &funding { if !funding_transaction.is_coinbase() { for inp in funding_transaction.input.iter() { if inp.witness.is_empty() { result = result.and(Err(APIError::APIMisuseError { - err: "Funding transaction must be fully signed and spend Segwit outputs".to_owned() + err: + "Funding transaction must be fully signed and spend Segwit outputs" + .to_owned(), })); } } @@ -5388,7 +6124,8 @@ where if funding_transaction.output.len() > u16::max_value() as usize { result = result.and(Err(APIError::APIMisuseError { - err: "Transaction had more than 2^16 outputs, which is not supported".to_owned() + err: "Transaction had more than 2^16 outputs, which is not supported" + .to_owned(), })); } let height = self.best_block.read().unwrap().height; @@ -5396,91 +6133,104 @@ where // lower than the next block height. However, the modules constituting our Lightning // node might not have perfect sync about their blockchain views. Thus, if the wallet // module is ahead of LDK, only allow one more block of headroom. - if !funding_transaction.input.iter().all(|input| input.sequence == Sequence::MAX) && - funding_transaction.lock_time.is_block_height() && - funding_transaction.lock_time.to_consensus_u32() > height + 1 + if !funding_transaction.input.iter().all(|input| input.sequence == Sequence::MAX) + && funding_transaction.lock_time.is_block_height() + && funding_transaction.lock_time.to_consensus_u32() > height + 1 { result = result.and(Err(APIError::APIMisuseError { - err: "Funding transaction absolute timelock is non-final".to_owned() + err: "Funding transaction absolute timelock is non-final".to_owned(), })); } } let txid = funding.txid(); let is_batch_funding = temporary_channels.len() > 1; - let mut funding_batch_states = if is_batch_funding { - Some(self.funding_batch_states.lock().unwrap()) - } else { - None - }; - let mut funding_batch_state = funding_batch_states.as_mut().and_then(|states| { - match states.entry(txid) { - btree_map::Entry::Occupied(_) => { - result = result.clone().and(Err(APIError::APIMisuseError { - err: "Batch funding transaction with the same txid already exists".to_owned() - })); - None - }, - btree_map::Entry::Vacant(vacant) => Some(vacant.insert(Vec::new())), - } + let mut funding_batch_states = + if is_batch_funding { Some(self.funding_batch_states.lock().unwrap()) } else { None }; + let mut funding_batch_state = funding_batch_states.as_mut().and_then(|states| match states + .entry(txid) + { + btree_map::Entry::Occupied(_) => { + result = result.clone().and(Err(APIError::APIMisuseError { + err: "Batch funding transaction with the same txid already exists".to_owned(), + })); + None + }, + btree_map::Entry::Vacant(vacant) => Some(vacant.insert(Vec::new())), }); let is_manual_broadcast = funding.is_manual_broadcast(); for &(temporary_channel_id, counterparty_node_id) in temporary_channels { - result = result.and_then(|_| self.funding_transaction_generated_intern( - *temporary_channel_id, - *counterparty_node_id, - funding.transaction_or_dummy(), - is_batch_funding, - |chan| { - let mut output_index = None; - let expected_spk = chan.funding.get_funding_redeemscript().to_p2wsh(); - let outpoint = match &funding { - FundingType::Checked(tx) => { - for (idx, outp) in tx.output.iter().enumerate() { - if outp.script_pubkey == expected_spk && outp.value.to_sat() == chan.funding.get_value_satoshis() { - if output_index.is_some() { - return Err("Multiple outputs matched the expected script and value"); + result = result.and_then(|_| { + self.funding_transaction_generated_intern( + *temporary_channel_id, + *counterparty_node_id, + funding.transaction_or_dummy(), + is_batch_funding, + |chan| { + let mut output_index = None; + let expected_spk = chan.funding.get_funding_redeemscript().to_p2wsh(); + let outpoint = match &funding { + FundingType::Checked(tx) => { + for (idx, outp) in tx.output.iter().enumerate() { + if outp.script_pubkey == expected_spk + && outp.value.to_sat() == chan.funding.get_value_satoshis() + { + if output_index.is_some() { + return Err("Multiple outputs matched the expected script and value"); + } + output_index = Some(idx as u16); } - output_index = Some(idx as u16); } - } - if output_index.is_none() { - return Err("No output matched the script_pubkey and value in the FundingGenerationReady event"); - } - OutPoint { txid, index: output_index.unwrap() } - }, - FundingType::Unchecked(outpoint) => outpoint.clone(), - }; - if let Some(funding_batch_state) = funding_batch_state.as_mut() { - // TODO(dual_funding): We only do batch funding for V1 channels at the moment, but we'll probably - // need to fix this somehow to not rely on using the outpoint for the channel ID if we - // want to support V2 batching here as well. - funding_batch_state.push((ChannelId::v1_from_funding_outpoint(outpoint), *counterparty_node_id, false)); - } - Ok(outpoint) - }, - is_manual_broadcast) - ); + if output_index.is_none() { + return Err("No output matched the script_pubkey and value in the FundingGenerationReady event"); + } + OutPoint { txid, index: output_index.unwrap() } + }, + FundingType::Unchecked(outpoint) => outpoint.clone(), + }; + if let Some(funding_batch_state) = funding_batch_state.as_mut() { + // TODO(dual_funding): We only do batch funding for V1 channels at the moment, but we'll probably + // need to fix this somehow to not rely on using the outpoint for the channel ID if we + // want to support V2 batching here as well. + funding_batch_state.push(( + ChannelId::v1_from_funding_outpoint(outpoint), + *counterparty_node_id, + false, + )); + } + Ok(outpoint) + }, + is_manual_broadcast, + ) + }); } if let Err(ref e) = result { // Remaining channels need to be removed on any error. let e = format!("Error in transaction funding: {:?}", e); let mut channels_to_remove = Vec::new(); - channels_to_remove.extend(funding_batch_states.as_mut() - .and_then(|states| states.remove(&txid)) - .into_iter().flatten() - .map(|(chan_id, node_id, _state)| (chan_id, node_id)) - ); - channels_to_remove.extend(temporary_channels.iter() - .map(|(&chan_id, &node_id)| (chan_id, node_id)) + channels_to_remove.extend( + funding_batch_states + .as_mut() + .and_then(|states| states.remove(&txid)) + .into_iter() + .flatten() + .map(|(chan_id, node_id, _state)| (chan_id, node_id)), ); + channels_to_remove + .extend(temporary_channels.iter().map(|(&chan_id, &node_id)| (chan_id, node_id))); let mut shutdown_results = Vec::new(); { let per_peer_state = self.per_peer_state.read().unwrap(); for (channel_id, counterparty_node_id) in channels_to_remove { - per_peer_state.get(&counterparty_node_id) + per_peer_state + .get(&counterparty_node_id) .map(|peer_state_mutex| peer_state_mutex.lock().unwrap()) - .and_then(|mut peer_state| peer_state.channel_by_id.remove(&channel_id).map(|chan| (chan, peer_state))) + .and_then(|mut peer_state| { + peer_state + .channel_by_id + .remove(&channel_id) + .map(|chan| (chan, peer_state)) + }) .map(|(mut chan, mut peer_state)| { let closure_reason = ClosureReason::ProcessingError { err: e.clone() }; let mut close_res = chan.force_shutdown(false, closure_reason); @@ -5492,7 +6242,7 @@ where msg: msgs::ErrorMessage { channel_id, data: "Failed to fund channel".to_owned(), - } + }, }, }); }); @@ -5529,25 +6279,42 @@ where /// [`ChannelUnavailable`]: APIError::ChannelUnavailable /// [`APIMisuseError`]: APIError::APIMisuseError pub fn update_partial_channel_config( - &self, counterparty_node_id: &PublicKey, channel_ids: &[ChannelId], config_update: &ChannelConfigUpdate, + &self, counterparty_node_id: &PublicKey, channel_ids: &[ChannelId], + config_update: &ChannelConfigUpdate, ) -> Result<(), APIError> { - if config_update.cltv_expiry_delta.map(|delta| delta < MIN_CLTV_EXPIRY_DELTA).unwrap_or(false) { + if config_update + .cltv_expiry_delta + .map(|delta| delta < MIN_CLTV_EXPIRY_DELTA) + .unwrap_or(false) + { return Err(APIError::APIMisuseError { - err: format!("The chosen CLTV expiry delta is below the minimum of {}", MIN_CLTV_EXPIRY_DELTA), + err: format!( + "The chosen CLTV expiry delta is below the minimum of {}", + MIN_CLTV_EXPIRY_DELTA + ), }); } let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + APIError::ChannelUnavailable { + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + } + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; for channel_id in channel_ids { if !peer_state.has_channel(channel_id) { return Err(APIError::ChannelUnavailable { - err: format!("Channel with id {} not found for the passed counterparty node_id {}", channel_id, counterparty_node_id), + err: format!( + "Channel with id {} not found for the passed counterparty node_id {}", + channel_id, counterparty_node_id + ), }); }; } @@ -5560,8 +6327,10 @@ where } if let Some(channel) = channel.as_funded() { if let Ok(msg) = self.get_channel_update_for_broadcast(channel) { - let mut pending_broadcast_messages = self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { msg }); + let mut pending_broadcast_messages = + self.pending_broadcast_messages.lock().unwrap(); + pending_broadcast_messages + .push(MessageSendEvent::BroadcastChannelUpdate { msg }); } else if let Ok(msg) = self.get_channel_update_for_unicast(channel) { peer_state.pending_msg_events.push(MessageSendEvent::SendChannelUpdate { node_id: channel.context.get_counterparty_node_id(), @@ -5608,7 +6377,11 @@ where pub fn update_channel_config( &self, counterparty_node_id: &PublicKey, channel_ids: &[ChannelId], config: &ChannelConfig, ) -> Result<(), APIError> { - return self.update_partial_channel_config(counterparty_node_id, channel_ids, &(*config).into()); + return self.update_partial_channel_config( + counterparty_node_id, + channel_ids, + &(*config).into(), + ); } /// Attempts to forward an intercepted HTLC over the provided channel id and with the provided @@ -5636,59 +6409,89 @@ where /// [`HTLCIntercepted::expected_outbound_amount_msat`]: events::Event::HTLCIntercepted::expected_outbound_amount_msat // TODO: when we move to deciding the best outbound channel at forward time, only take // `next_node_id` and not `next_hop_channel_id` - pub fn forward_intercepted_htlc(&self, intercept_id: InterceptId, next_hop_channel_id: &ChannelId, next_node_id: PublicKey, amt_to_forward_msat: u64) -> Result<(), APIError> { + pub fn forward_intercepted_htlc( + &self, intercept_id: InterceptId, next_hop_channel_id: &ChannelId, next_node_id: PublicKey, + amt_to_forward_msat: u64, + ) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let next_hop_scid = { let peer_state_lock = self.per_peer_state.read().unwrap(); - let peer_state_mutex = peer_state_lock.get(&next_node_id) - .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", next_node_id) })?; + let peer_state_mutex = + peer_state_lock.get(&next_node_id).ok_or_else(|| APIError::ChannelUnavailable { + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + next_node_id + ), + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.get(next_hop_channel_id) { - Some(chan) => if let Some(funded_chan) = chan.as_funded() { - if !funded_chan.context.is_usable() { + Some(chan) => { + if let Some(funded_chan) = chan.as_funded() { + if !funded_chan.context.is_usable() { + return Err(APIError::ChannelUnavailable { + err: format!( + "Channel with id {} not fully established", + next_hop_channel_id + ), + }); + } + funded_chan + .context + .get_short_channel_id() + .unwrap_or(funded_chan.context.outbound_scid_alias()) + } else { return Err(APIError::ChannelUnavailable { - err: format!("Channel with id {} not fully established", next_hop_channel_id) - }) - } - funded_chan.context.get_short_channel_id().unwrap_or(funded_chan.context.outbound_scid_alias()) - } else { - return Err(APIError::ChannelUnavailable { err: format!("Channel with id {} for the passed counterparty node_id {} is still opening.", next_hop_channel_id, next_node_id) - }) + }); + } }, None => { - let error = format!("Channel with id {} not found for the passed counterparty node_id {}", - next_hop_channel_id, next_node_id); - let logger = WithContext::from(&self.logger, Some(next_node_id), Some(*next_hop_channel_id), None); + let error = format!( + "Channel with id {} not found for the passed counterparty node_id {}", + next_hop_channel_id, next_node_id + ); + let logger = WithContext::from( + &self.logger, + Some(next_node_id), + Some(*next_hop_channel_id), + None, + ); log_error!(logger, "{} when attempting to forward intercepted HTLC", error); - return Err(APIError::ChannelUnavailable { - err: error - }) + return Err(APIError::ChannelUnavailable { err: error }); }, } }; - let payment = self.pending_intercepted_htlcs.lock().unwrap().remove(&intercept_id) + let payment = self + .pending_intercepted_htlcs + .lock() + .unwrap() + .remove(&intercept_id) .ok_or_else(|| APIError::APIMisuseError { - err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) + err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)), })?; let routing = match payment.forward_info.routing { PendingHTLCRouting::Forward { onion_packet, blinded, incoming_cltv_expiry, .. } => { PendingHTLCRouting::Forward { - onion_packet, blinded, incoming_cltv_expiry, short_channel_id: next_hop_scid, + onion_packet, + blinded, + incoming_cltv_expiry, + short_channel_id: next_hop_scid, } }, - _ => unreachable!() // Only `PendingHTLCRouting::Forward`s are intercepted + _ => unreachable!(), // Only `PendingHTLCRouting::Forward`s are intercepted }; let skimmed_fee_msat = payment.forward_info.outgoing_amt_msat.saturating_sub(amt_to_forward_msat); let pending_htlc_info = PendingHTLCInfo { skimmed_fee_msat: if skimmed_fee_msat == 0 { None } else { Some(skimmed_fee_msat) }, - outgoing_amt_msat: amt_to_forward_msat, routing, ..payment.forward_info + outgoing_amt_msat: amt_to_forward_msat, + routing, + ..payment.forward_info }; let mut per_source_pending_forward = [( @@ -5697,7 +6500,7 @@ where payment.prev_funding_outpoint, payment.prev_channel_id, payment.prev_user_channel_id, - vec![(pending_htlc_info, payment.prev_htlc_id)] + vec![(pending_htlc_info, payment.prev_htlc_id)], )]; self.forward_htlcs(&mut per_source_pending_forward); Ok(()) @@ -5713,12 +6516,18 @@ where pub fn fail_intercepted_htlc(&self, intercept_id: InterceptId) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let payment = self.pending_intercepted_htlcs.lock().unwrap().remove(&intercept_id) + let payment = self + .pending_intercepted_htlcs + .lock() + .unwrap() + .remove(&intercept_id) .ok_or_else(|| APIError::APIMisuseError { - err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) + err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)), })?; - if let PendingHTLCRouting::Forward { short_channel_id, incoming_cltv_expiry, .. } = payment.forward_info.routing { + if let PendingHTLCRouting::Forward { short_channel_id, incoming_cltv_expiry, .. } = + payment.forward_info.routing + { let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id: payment.prev_short_channel_id, user_channel_id: Some(payment.prev_user_channel_id), @@ -5733,9 +6542,17 @@ where }); let reason = HTLCFailReason::from_failure_code(LocalHTLCFailureReason::UnknownNextPeer); - let destination = HTLCDestination::UnknownNextHop { requested_forward_scid: short_channel_id }; - self.fail_htlc_backwards_internal(&htlc_source, &payment.forward_info.payment_hash, &reason, destination); - } else { unreachable!() } // Only `PendingHTLCRouting::Forward`s are intercepted + let destination = + HTLCDestination::UnknownNextHop { requested_forward_scid: short_channel_id }; + self.fail_htlc_backwards_internal( + &htlc_source, + &payment.forward_info.payment_hash, + &reason, + destination, + ); + } else { + unreachable!() + } // Only `PendingHTLCRouting::Forward`s are intercepted Ok(()) } @@ -5744,36 +6561,48 @@ where let mut decode_update_add_htlcs = new_hash_map(); mem::swap(&mut decode_update_add_htlcs, &mut self.decode_update_add_htlcs.lock().unwrap()); - let get_failed_htlc_destination = |outgoing_scid_opt: Option, payment_hash: PaymentHash| { - if let Some(outgoing_scid) = outgoing_scid_opt { - match self.short_to_chan_info.read().unwrap().get(&outgoing_scid) { - Some((outgoing_counterparty_node_id, outgoing_channel_id)) => - HTLCDestination::NextHopChannel { - node_id: Some(*outgoing_counterparty_node_id), - channel_id: *outgoing_channel_id, + let get_failed_htlc_destination = + |outgoing_scid_opt: Option, payment_hash: PaymentHash| { + if let Some(outgoing_scid) = outgoing_scid_opt { + match self.short_to_chan_info.read().unwrap().get(&outgoing_scid) { + Some((outgoing_counterparty_node_id, outgoing_channel_id)) => { + HTLCDestination::NextHopChannel { + node_id: Some(*outgoing_counterparty_node_id), + channel_id: *outgoing_channel_id, + } }, - None => HTLCDestination::UnknownNextHop { - requested_forward_scid: outgoing_scid, - }, + None => HTLCDestination::UnknownNextHop { + requested_forward_scid: outgoing_scid, + }, + } + } else { + HTLCDestination::FailedPayment { payment_hash } } - } else { - HTLCDestination::FailedPayment { payment_hash } - } - }; + }; 'outer_loop: for (incoming_scid, update_add_htlcs) in decode_update_add_htlcs { - let incoming_channel_details_opt = self.do_funded_channel_callback(incoming_scid, |chan: &mut FundedChannel| { - let counterparty_node_id = chan.context.get_counterparty_node_id(); - let channel_id = chan.context.channel_id(); - let funding_txo = chan.funding.get_funding_txo().unwrap(); - let user_channel_id = chan.context.get_user_id(); - let accept_underpaying_htlcs = chan.context.config().accept_underpaying_htlcs; - (counterparty_node_id, channel_id, funding_txo, user_channel_id, accept_underpaying_htlcs) - }); + let incoming_channel_details_opt = + self.do_funded_channel_callback(incoming_scid, |chan: &mut FundedChannel| { + let counterparty_node_id = chan.context.get_counterparty_node_id(); + let channel_id = chan.context.channel_id(); + let funding_txo = chan.funding.get_funding_txo().unwrap(); + let user_channel_id = chan.context.get_user_id(); + let accept_underpaying_htlcs = chan.context.config().accept_underpaying_htlcs; + ( + counterparty_node_id, + channel_id, + funding_txo, + user_channel_id, + accept_underpaying_htlcs, + ) + }); let ( - incoming_counterparty_node_id, incoming_channel_id, incoming_funding_txo, - incoming_user_channel_id, incoming_accept_underpaying_htlcs - ) = if let Some(incoming_channel_details) = incoming_channel_details_opt { + incoming_counterparty_node_id, + incoming_channel_id, + incoming_funding_txo, + incoming_user_channel_id, + incoming_accept_underpaying_htlcs, + ) = if let Some(incoming_channel_details) = incoming_channel_details_opt { incoming_channel_details } else { // The incoming channel no longer exists, HTLCs should be resolved onchain instead. @@ -5783,39 +6612,54 @@ where let mut htlc_forwards = Vec::new(); let mut htlc_fails = Vec::new(); for update_add_htlc in &update_add_htlcs { - let (next_hop, next_packet_details_opt) = match decode_incoming_update_add_htlc_onion( - &update_add_htlc, &*self.node_signer, &*self.logger, &self.secp_ctx - ) { - Ok(decoded_onion) => decoded_onion, - Err((htlc_fail, _)) => { - htlc_fails.push((htlc_fail, HTLCDestination::InvalidOnion)); - continue; - }, - }; + let (next_hop, next_packet_details_opt) = + match decode_incoming_update_add_htlc_onion( + &update_add_htlc, + &*self.node_signer, + &*self.logger, + &self.secp_ctx, + ) { + Ok(decoded_onion) => decoded_onion, + Err((htlc_fail, _)) => { + htlc_fails.push((htlc_fail, HTLCDestination::InvalidOnion)); + continue; + }, + }; let is_intro_node_blinded_forward = next_hop.is_intro_node_blinded_forward(); - let outgoing_scid_opt = next_packet_details_opt.as_ref().and_then(|d| { - match d.outgoing_connector { - HopConnector::ShortChannelId(scid) => { Some(scid) } - HopConnector::Trampoline(_) => { None } - } - }); + let outgoing_scid_opt = + next_packet_details_opt.as_ref().and_then(|d| match d.outgoing_connector { + HopConnector::ShortChannelId(scid) => Some(scid), + HopConnector::Trampoline(_) => None, + }); let shared_secret = next_hop.shared_secret().secret_bytes(); // Process the HTLC on the incoming channel. - match self.do_funded_channel_callback(incoming_scid, |chan: &mut FundedChannel| { - let logger = WithChannelContext::from(&self.logger, &chan.context, Some(update_add_htlc.payment_hash)); - chan.can_accept_incoming_htlc( - update_add_htlc, &self.fee_estimator, &logger, - ) - }) { + match self.do_funded_channel_callback( + incoming_scid, + |chan: &mut FundedChannel| { + let logger = WithChannelContext::from( + &self.logger, + &chan.context, + Some(update_add_htlc.payment_hash), + ); + chan.can_accept_incoming_htlc(update_add_htlc, &self.fee_estimator, &logger) + }, + ) { Some(Ok(_)) => {}, Some(Err((err, reason))) => { let htlc_fail = self.htlc_failure_from_update_add_err( - &update_add_htlc, &incoming_counterparty_node_id, err, reason, - is_intro_node_blinded_forward, &shared_secret, + &update_add_htlc, + &incoming_counterparty_node_id, + err, + reason, + is_intro_node_blinded_forward, + &shared_secret, + ); + let htlc_destination = get_failed_htlc_destination( + outgoing_scid_opt, + update_add_htlc.payment_hash, ); - let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash); htlc_fails.push((htlc_fail, htlc_destination)); continue; }, @@ -5825,27 +6669,45 @@ where // Now process the HTLC on the outgoing channel if it's a forward. if let Some(next_packet_details) = next_packet_details_opt.as_ref() { - if let Err((err, reason)) = self.can_forward_htlc( - &update_add_htlc, next_packet_details - ) { + if let Err((err, reason)) = + self.can_forward_htlc(&update_add_htlc, next_packet_details) + { let htlc_fail = self.htlc_failure_from_update_add_err( - &update_add_htlc, &incoming_counterparty_node_id, err, reason, - is_intro_node_blinded_forward, &shared_secret, + &update_add_htlc, + &incoming_counterparty_node_id, + err, + reason, + is_intro_node_blinded_forward, + &shared_secret, + ); + let htlc_destination = get_failed_htlc_destination( + outgoing_scid_opt, + update_add_htlc.payment_hash, ); - let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash); htlc_fails.push((htlc_fail, htlc_destination)); continue; } } match self.get_pending_htlc_info( - &update_add_htlc, shared_secret, next_hop, incoming_accept_underpaying_htlcs, + &update_add_htlc, + shared_secret, + next_hop, + incoming_accept_underpaying_htlcs, next_packet_details_opt.map(|d| d.next_packet_pubkey), ) { Ok(info) => htlc_forwards.push((info, update_add_htlc.htlc_id)), Err(inbound_err) => { - let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash); - let htlc_fail = self.construct_pending_htlc_fail_msg(&update_add_htlc, &incoming_counterparty_node_id, shared_secret, inbound_err); + let htlc_destination = get_failed_htlc_destination( + outgoing_scid_opt, + update_add_htlc.payment_hash, + ); + let htlc_fail = self.construct_pending_htlc_fail_msg( + &update_add_htlc, + &incoming_counterparty_node_id, + shared_secret, + inbound_err, + ); htlc_fails.push((htlc_fail, htlc_destination)); }, } @@ -5854,8 +6716,12 @@ where // Process all of the forwards and failures for the channel in which the HTLCs were // proposed to as a batch. let pending_forwards = ( - incoming_scid, Some(incoming_counterparty_node_id), incoming_funding_txo, - incoming_channel_id, incoming_user_channel_id, htlc_forwards.drain(..).collect() + incoming_scid, + Some(incoming_counterparty_node_id), + incoming_funding_txo, + incoming_channel_id, + incoming_user_channel_id, + htlc_forwards.drain(..).collect(), ); self.forward_htlcs_without_forward_event(&mut [pending_forwards]); for (htlc_fail, htlc_destination) in htlc_fails.drain(..) { @@ -5864,17 +6730,22 @@ where htlc_id: fail_htlc.htlc_id, err_packet: fail_htlc.into(), }, - HTLCFailureMsg::Malformed(fail_malformed_htlc) => HTLCForwardInfo::FailMalformedHTLC { - htlc_id: fail_malformed_htlc.htlc_id, - sha256_of_onion: fail_malformed_htlc.sha256_of_onion, - failure_code: fail_malformed_htlc.failure_code.into(), + HTLCFailureMsg::Malformed(fail_malformed_htlc) => { + HTLCForwardInfo::FailMalformedHTLC { + htlc_id: fail_malformed_htlc.htlc_id, + sha256_of_onion: fail_malformed_htlc.sha256_of_onion, + failure_code: fail_malformed_htlc.failure_code.into(), + } }, }; self.forward_htlcs.lock().unwrap().entry(incoming_scid).or_default().push(failure); - self.pending_events.lock().unwrap().push_back((events::Event::HTLCHandlingFailed { - prev_channel_id: incoming_channel_id, - failed_next_destination: htlc_destination, - }, None)); + self.pending_events.lock().unwrap().push_back(( + events::Event::HTLCHandlingFailed { + prev_channel_id: incoming_channel_id, + failed_next_destination: htlc_destination, + }, + None, + )); } } } @@ -5890,7 +6761,14 @@ where let mut new_events = VecDeque::new(); let mut failed_forwards = Vec::new(); - let mut phantom_receives: Vec<(u64, Option, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)> = Vec::new(); + let mut phantom_receives: Vec<( + u64, + Option, + OutPoint, + ChannelId, + u128, + Vec<(PendingHTLCInfo, u64)>, + )> = Vec::new(); { let mut forward_htlcs = new_hash_map(); mem::swap(&mut forward_htlcs, &mut self.forward_htlcs.lock().unwrap()); @@ -6008,13 +6886,14 @@ where } } } - let chan_info_opt = self.short_to_chan_info.read().unwrap().get(&short_chan_id).cloned(); + let chan_info_opt = + self.short_to_chan_info.read().unwrap().get(&short_chan_id).cloned(); let (counterparty_node_id, forward_chan_id) = match chan_info_opt { Some((cp_id, chan_id)) => (cp_id, chan_id), None => { forwarding_channel_not_found!(pending_forwards.drain(..)); continue; - } + }, }; forwarding_counterparty = Some(counterparty_node_id); let per_peer_state = self.per_peer_state.read().unwrap(); @@ -6029,35 +6908,56 @@ where while let Some(forward_info) = draining_pending_forwards.next() { let queue_fail_htlc_res = match forward_info { HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, prev_htlc_id, prev_channel_id, prev_funding_outpoint, - prev_user_channel_id, prev_counterparty_node_id, forward_info: PendingHTLCInfo { - incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value, - routing: PendingHTLCRouting::Forward { - ref onion_packet, blinded, incoming_cltv_expiry, .. - }, skimmed_fee_msat, .. - }, + prev_short_channel_id, + prev_htlc_id, + prev_channel_id, + prev_funding_outpoint, + prev_user_channel_id, + prev_counterparty_node_id, + forward_info: + PendingHTLCInfo { + incoming_shared_secret, + payment_hash, + outgoing_amt_msat, + outgoing_cltv_value, + routing: + PendingHTLCRouting::Forward { + ref onion_packet, + blinded, + incoming_cltv_expiry, + .. + }, + skimmed_fee_msat, + .. + }, }) => { - let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: prev_short_channel_id, - user_channel_id: Some(prev_user_channel_id), - counterparty_node_id: prev_counterparty_node_id, - channel_id: prev_channel_id, - outpoint: prev_funding_outpoint, - htlc_id: prev_htlc_id, - incoming_packet_shared_secret: incoming_shared_secret, - // Phantom payments are only PendingHTLCRouting::Receive. - phantom_shared_secret: None, - blinded_failure: blinded.map(|b| b.failure), - cltv_expiry: incoming_cltv_expiry, - }); + let htlc_source = + HTLCSource::PreviousHopData(HTLCPreviousHopData { + short_channel_id: prev_short_channel_id, + user_channel_id: Some(prev_user_channel_id), + counterparty_node_id: prev_counterparty_node_id, + channel_id: prev_channel_id, + outpoint: prev_funding_outpoint, + htlc_id: prev_htlc_id, + incoming_packet_shared_secret: incoming_shared_secret, + // Phantom payments are only PendingHTLCRouting::Receive. + phantom_shared_secret: None, + blinded_failure: blinded.map(|b| b.failure), + cltv_expiry: incoming_cltv_expiry, + }); let next_blinding_point = blinded.and_then(|b| { b.next_blinding_override.or_else(|| { - let encrypted_tlvs_ss = self.node_signer.ecdh( - Recipient::Node, &b.inbound_blinding_point, None - ).unwrap().secret_bytes(); + let encrypted_tlvs_ss = self + .node_signer + .ecdh(Recipient::Node, &b.inbound_blinding_point, None) + .unwrap() + .secret_bytes(); onion_utils::next_hop_pubkey( - &self.secp_ctx, b.inbound_blinding_point, &encrypted_tlvs_ss - ).ok() + &self.secp_ctx, + b.inbound_blinding_point, + &encrypted_tlvs_ss, + ) + .ok() }) }); @@ -6065,61 +6965,99 @@ where // applying non-strict forwarding. // The channel with the least amount of outbound liquidity will be used to maximize the // probability of being able to successfully forward a subsequent HTLC. - let maybe_optimal_channel = peer_state.channel_by_id.values_mut() + let maybe_optimal_channel = peer_state + .channel_by_id + .values_mut() .filter_map(Channel::as_funded_mut) .filter_map(|chan| { - let balances = chan.get_available_balances(&self.fee_estimator); - if outgoing_amt_msat <= balances.next_outbound_htlc_limit_msat && - outgoing_amt_msat >= balances.next_outbound_htlc_minimum_msat && - chan.context.is_usable() { + let balances = + chan.get_available_balances(&self.fee_estimator); + if outgoing_amt_msat + <= balances.next_outbound_htlc_limit_msat + && outgoing_amt_msat + >= balances.next_outbound_htlc_minimum_msat && chan + .context + .is_usable() + { Some((chan, balances)) } else { None } }) - .min_by_key(|(_, balances)| balances.next_outbound_htlc_limit_msat).map(|(c, _)| c); + .min_by_key(|(_, balances)| { + balances.next_outbound_htlc_limit_msat + }) + .map(|(c, _)| c); let optimal_channel = match maybe_optimal_channel { Some(chan) => chan, None => { // Fall back to the specified channel to return an appropriate error. - if let Some(chan) = peer_state.channel_by_id + if let Some(chan) = peer_state + .channel_by_id .get_mut(&forward_chan_id) .and_then(Channel::as_funded_mut) { chan } else { - forwarding_channel_not_found!(core::iter::once(forward_info).chain(draining_pending_forwards)); + forwarding_channel_not_found!(core::iter::once( + forward_info + ) + .chain(draining_pending_forwards)); break; } - } + }, }; - let logger = WithChannelContext::from(&self.logger, &optimal_channel.context, Some(payment_hash)); - let channel_description = if optimal_channel.context.get_short_channel_id() == Some(short_chan_id) { - "specified" - } else { - "alternate" - }; + let logger = WithChannelContext::from( + &self.logger, + &optimal_channel.context, + Some(payment_hash), + ); + let channel_description = + if optimal_channel.context.get_short_channel_id() + == Some(short_chan_id) + { + "specified" + } else { + "alternate" + }; log_trace!(logger, "Forwarding HTLC from SCID {} with payment_hash {} and next hop SCID {} over {} channel {} with corresponding peer {}", prev_short_channel_id, &payment_hash, short_chan_id, channel_description, optimal_channel.context.channel_id(), &counterparty_node_id); - if let Err((reason, msg)) = optimal_channel.queue_add_htlc(outgoing_amt_msat, - payment_hash, outgoing_cltv_value, htlc_source.clone(), - onion_packet.clone(), skimmed_fee_msat, next_blinding_point, &self.fee_estimator, - &&logger) - { + if let Err((reason, msg)) = optimal_channel.queue_add_htlc( + outgoing_amt_msat, + payment_hash, + outgoing_cltv_value, + htlc_source.clone(), + onion_packet.clone(), + skimmed_fee_msat, + next_blinding_point, + &self.fee_estimator, + &&logger, + ) { log_trace!(logger, "Failed to forward HTLC with payment_hash {} to peer {}: {}", &payment_hash, &counterparty_node_id, msg); - if let Some(chan) = peer_state.channel_by_id + if let Some(chan) = peer_state + .channel_by_id .get_mut(&forward_chan_id) .and_then(Channel::as_funded_mut) { let data = self.get_htlc_inbound_temp_fail_data(reason); - failed_forwards.push((htlc_source, payment_hash, + failed_forwards.push(( + htlc_source, + payment_hash, HTLCFailReason::reason(reason, data), - HTLCDestination::NextHopChannel { node_id: Some(chan.context.get_counterparty_node_id()), channel_id: forward_chan_id } + HTLCDestination::NextHopChannel { + node_id: Some( + chan.context.get_counterparty_node_id(), + ), + channel_id: forward_chan_id, + }, )); } else { - forwarding_channel_not_found!(core::iter::once(forward_info).chain(draining_pending_forwards)); + forwarding_channel_not_found!(core::iter::once( + forward_info + ) + .chain(draining_pending_forwards)); break; } } @@ -6129,31 +7067,47 @@ where panic!("short_channel_id != 0 should imply any pending_forward entries are of type Forward"); }, HTLCForwardInfo::FailHTLC { htlc_id, ref err_packet } => { - if let Some(chan) = peer_state.channel_by_id + if let Some(chan) = peer_state + .channel_by_id .get_mut(&forward_chan_id) .and_then(Channel::as_funded_mut) { - let logger = WithChannelContext::from(&self.logger, &chan.context, None); + let logger = + WithChannelContext::from(&self.logger, &chan.context, None); log_trace!(logger, "Failing HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id); - Some((chan.queue_fail_htlc(htlc_id, err_packet.clone(), &&logger), htlc_id)) + Some(( + chan.queue_fail_htlc(htlc_id, err_packet.clone(), &&logger), + htlc_id, + )) } else { - forwarding_channel_not_found!(core::iter::once(forward_info).chain(draining_pending_forwards)); + forwarding_channel_not_found!(core::iter::once(forward_info) + .chain(draining_pending_forwards)); break; } }, - HTLCForwardInfo::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => { - if let Some(chan) = peer_state.channel_by_id + HTLCForwardInfo::FailMalformedHTLC { + htlc_id, + failure_code, + sha256_of_onion, + } => { + if let Some(chan) = peer_state + .channel_by_id .get_mut(&forward_chan_id) .and_then(Channel::as_funded_mut) { - let logger = WithChannelContext::from(&self.logger, &chan.context, None); + let logger = + WithChannelContext::from(&self.logger, &chan.context, None); log_trace!(logger, "Failing malformed HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id); let res = chan.queue_fail_malformed_htlc( - htlc_id, failure_code, sha256_of_onion, &&logger + htlc_id, + failure_code, + sha256_of_onion, + &&logger, ); Some((res, htlc_id)) } else { - forwarding_channel_not_found!(core::iter::once(forward_info).chain(draining_pending_forwards)); + forwarding_channel_not_found!(core::iter::once(forward_info) + .chain(draining_pending_forwards)); break; } }, @@ -6161,11 +7115,16 @@ where if let Some((queue_fail_htlc_res, htlc_id)) = queue_fail_htlc_res { if let Err(e) = queue_fail_htlc_res { if let ChannelError::Ignore(msg) = e { - if let Some(chan) = peer_state.channel_by_id + if let Some(chan) = peer_state + .channel_by_id .get_mut(&forward_chan_id) .and_then(Channel::as_funded_mut) { - let logger = WithChannelContext::from(&self.logger, &chan.context, None); + let logger = WithChannelContext::from( + &self.logger, + &chan.context, + None, + ); log_trace!(logger, "Failed to fail HTLC with ID {} backwards to short_id {}: {}", htlc_id, short_chan_id, msg); } } else { @@ -6181,46 +7140,92 @@ where 'next_forwardable_htlc: for forward_info in pending_forwards.drain(..) { match forward_info { HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, prev_htlc_id, prev_channel_id, prev_funding_outpoint, - prev_user_channel_id, prev_counterparty_node_id, forward_info: PendingHTLCInfo { - routing, incoming_shared_secret, payment_hash, incoming_amt_msat, outgoing_amt_msat, - skimmed_fee_msat, .. - } + prev_short_channel_id, + prev_htlc_id, + prev_channel_id, + prev_funding_outpoint, + prev_user_channel_id, + prev_counterparty_node_id, + forward_info: + PendingHTLCInfo { + routing, + incoming_shared_secret, + payment_hash, + incoming_amt_msat, + outgoing_amt_msat, + skimmed_fee_msat, + .. + }, }) => { let blinded_failure = routing.blinded_failure(); let ( - cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret, - mut onion_fields, has_recipient_created_payment_secret, invoice_request_opt + cltv_expiry, + onion_payload, + payment_data, + payment_context, + phantom_shared_secret, + mut onion_fields, + has_recipient_created_payment_secret, + invoice_request_opt, ) = match routing { PendingHTLCRouting::Receive { - payment_data, payment_metadata, payment_context, - incoming_cltv_expiry, phantom_shared_secret, custom_tlvs, - requires_blinded_error: _ + payment_data, + payment_metadata, + payment_context, + incoming_cltv_expiry, + phantom_shared_secret, + custom_tlvs, + requires_blinded_error: _, } => { let _legacy_hop_data = Some(payment_data.clone()); - let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret), - payment_metadata, custom_tlvs }; - (incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data }, - Some(payment_data), payment_context, phantom_shared_secret, onion_fields, - true, None) + let onion_fields = RecipientOnionFields { + payment_secret: Some(payment_data.payment_secret), + payment_metadata, + custom_tlvs, + }; + ( + incoming_cltv_expiry, + OnionPayload::Invoice { _legacy_hop_data }, + Some(payment_data), + payment_context, + phantom_shared_secret, + onion_fields, + true, + None, + ) }, PendingHTLCRouting::ReceiveKeysend { - payment_data, payment_preimage, payment_metadata, - incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _, - has_recipient_created_payment_secret, payment_context, invoice_request, + payment_data, + payment_preimage, + payment_metadata, + incoming_cltv_expiry, + custom_tlvs, + requires_blinded_error: _, + has_recipient_created_payment_secret, + payment_context, + invoice_request, } => { let onion_fields = RecipientOnionFields { - payment_secret: payment_data.as_ref().map(|data| data.payment_secret), + payment_secret: payment_data + .as_ref() + .map(|data| data.payment_secret), payment_metadata, custom_tlvs, }; - (incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage), - payment_data, payment_context, None, onion_fields, - has_recipient_created_payment_secret, invoice_request) + ( + incoming_cltv_expiry, + OnionPayload::Spontaneous(payment_preimage), + payment_data, + payment_context, + None, + onion_fields, + has_recipient_created_payment_secret, + invoice_request, + ) }, _ => { panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive"); - } + }, }; let claimable_htlc = ClaimableHTLC { prev_hop: HTLCPreviousHopData { @@ -6242,7 +7247,11 @@ where sender_intended_value: outgoing_amt_msat, timer_ticks: 0, total_value_received: None, - total_msat: if let Some(data) = &payment_data { data.total_msat } else { outgoing_amt_msat }, + total_msat: if let Some(data) = &payment_data { + data.total_msat + } else { + outgoing_amt_msat + }, cltv_expiry, onion_payload, counterparty_skimmed_fee_msat: skimmed_fee_msat, @@ -6253,29 +7262,46 @@ where macro_rules! fail_htlc { ($htlc: expr, $payment_hash: expr) => { debug_assert!(!committed_to_claimable); - let err_data = invalid_payment_err_data($htlc.value, self.best_block.read().unwrap().height); - failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData { + let err_data = invalid_payment_err_data( + $htlc.value, + self.best_block.read().unwrap().height, + ); + failed_forwards.push(( + HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id: $htlc.prev_hop.short_channel_id, user_channel_id: $htlc.prev_hop.user_channel_id, - counterparty_node_id: $htlc.prev_hop.counterparty_node_id, + counterparty_node_id: $htlc + .prev_hop + .counterparty_node_id, channel_id: prev_channel_id, outpoint: prev_funding_outpoint, htlc_id: $htlc.prev_hop.htlc_id, - incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret, + incoming_packet_shared_secret: $htlc + .prev_hop + .incoming_packet_shared_secret, phantom_shared_secret, blinded_failure, cltv_expiry: Some(cltv_expiry), - }), payment_hash, - HTLCFailReason::reason(LocalHTLCFailureReason::IncorrectPaymentDetails, err_data), - HTLCDestination::FailedPayment { payment_hash: $payment_hash }, + }), + payment_hash, + HTLCFailReason::reason( + LocalHTLCFailureReason::IncorrectPaymentDetails, + err_data, + ), + HTLCDestination::FailedPayment { + payment_hash: $payment_hash, + }, )); continue 'next_forwardable_htlc; - } + }; } - let phantom_shared_secret = claimable_htlc.prev_hop.phantom_shared_secret; + let phantom_shared_secret = + claimable_htlc.prev_hop.phantom_shared_secret; let mut receiver_node_id = self.our_network_pubkey; if phantom_shared_secret.is_some() { - receiver_node_id = self.node_signer.get_node_id(Recipient::PhantomNode) + receiver_node_id = self + .node_signer + .get_node_id(Recipient::PhantomNode) .expect("Failed to get node_id for phantom node recipient"); } @@ -6378,15 +7404,27 @@ where // associated with the same payment_hash pending or not. let payment_preimage = if has_recipient_created_payment_secret { if let Some(ref payment_data) = payment_data { - let (payment_preimage, min_final_cltv_expiry_delta) = match inbound_payment::verify(payment_hash, &payment_data, self.highest_seen_timestamp.load(Ordering::Acquire) as u64, &self.inbound_payment_key, &self.logger) { - Ok(result) => result, - Err(()) => { - log_trace!(self.logger, "Failing new HTLC with payment_hash {} as payment verification failed", &payment_hash); - fail_htlc!(claimable_htlc, payment_hash); - } - }; - if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta { - let expected_min_expiry_height = (self.current_best_block().height + min_final_cltv_expiry_delta as u32) as u64; + let (payment_preimage, min_final_cltv_expiry_delta) = + match inbound_payment::verify( + payment_hash, + &payment_data, + self.highest_seen_timestamp.load(Ordering::Acquire) + as u64, + &self.inbound_payment_key, + &self.logger, + ) { + Ok(result) => result, + Err(()) => { + log_trace!(self.logger, "Failing new HTLC with payment_hash {} as payment verification failed", &payment_hash); + fail_htlc!(claimable_htlc, payment_hash); + }, + }; + if let Some(min_final_cltv_expiry_delta) = + min_final_cltv_expiry_delta + { + let expected_min_expiry_height = + (self.current_best_block().height + + min_final_cltv_expiry_delta as u32) as u64; if (cltv_expiry as u64) < expected_min_expiry_height { log_trace!(self.logger, "Failing new HTLC with payment_hash {} as its CLTV expiry was too soon (had {}, earliest expected {})", &payment_hash, cltv_expiry, expected_min_expiry_height); @@ -6394,8 +7432,12 @@ where } } payment_preimage - } else { fail_htlc!(claimable_htlc, payment_hash); } - } else { None }; + } else { + fail_htlc!(claimable_htlc, payment_hash); + } + } else { + None + }; match claimable_htlc.onion_payload { OnionPayload::Invoice { .. } => { let payment_data = payment_data.unwrap(); @@ -6412,9 +7454,12 @@ where check_total_value!(purpose); }, OnionPayload::Spontaneous(keysend_preimage) => { - let purpose = if let Some(PaymentContext::AsyncBolt12Offer( - AsyncBolt12OfferContext { offer_nonce } - )) = payment_context { + let purpose = if let Some( + PaymentContext::AsyncBolt12Offer( + AsyncBolt12OfferContext { offer_nonce }, + ), + ) = payment_context + { let payment_data = match payment_data { Some(data) => data, None => { @@ -6424,48 +7469,64 @@ where }; let verified_invreq = match invoice_request_opt - .and_then(|invreq| invreq.verify_using_recipient_data( - offer_nonce, &self.inbound_payment_key, &self.secp_ctx - ).ok()) - { + .and_then(|invreq| { + invreq + .verify_using_recipient_data( + offer_nonce, + &self.inbound_payment_key, + &self.secp_ctx, + ) + .ok() + }) { Some(verified_invreq) => { - if let Some(invreq_amt_msat) = verified_invreq.amount_msats() { - if payment_data.total_msat < invreq_amt_msat { - fail_htlc!(claimable_htlc, payment_hash); + if let Some(invreq_amt_msat) = + verified_invreq.amount_msats() + { + if payment_data.total_msat < invreq_amt_msat + { + fail_htlc!( + claimable_htlc, + payment_hash + ); } } verified_invreq }, None => { fail_htlc!(claimable_htlc, payment_hash); - } + }, }; - let payment_purpose_context = PaymentContext::Bolt12Offer(Bolt12OfferContext { - offer_id: verified_invreq.offer_id, - invoice_request: verified_invreq.fields(), - }); + let payment_purpose_context = + PaymentContext::Bolt12Offer(Bolt12OfferContext { + offer_id: verified_invreq.offer_id, + invoice_request: verified_invreq.fields(), + }); match events::PaymentPurpose::from_parts( - Some(keysend_preimage), payment_data.payment_secret, + Some(keysend_preimage), + payment_data.payment_secret, Some(payment_purpose_context), ) { Ok(purpose) => purpose, Err(()) => { fail_htlc!(claimable_htlc, payment_hash); - } + }, } } else if payment_context.is_some() { log_trace!(self.logger, "Failing new HTLC with payment_hash {}: received a keysend payment to a non-async payments context {:#?}", payment_hash, payment_context); fail_htlc!(claimable_htlc, payment_hash); } else { - events::PaymentPurpose::SpontaneousPayment(keysend_preimage) + events::PaymentPurpose::SpontaneousPayment( + keysend_preimage, + ) }; check_total_value!(purpose); - } + }, } }, - HTLCForwardInfo::FailHTLC { .. } | HTLCForwardInfo::FailMalformedHTLC { .. } => { + HTLCForwardInfo::FailHTLC { .. } + | HTLCForwardInfo::FailMalformedHTLC { .. } => { panic!("Got pending fail of our own HTLC"); - } + }, } } } @@ -6473,12 +7534,25 @@ where } let best_block_height = self.best_block.read().unwrap().height; - self.pending_outbound_payments.check_retry_payments(&self.router, || self.list_usable_channels(), - || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, - &self.pending_events, &self.logger, |args| self.send_payment_along_path(args)); + self.pending_outbound_payments.check_retry_payments( + &self.router, + || self.list_usable_channels(), + || self.compute_inflight_htlcs(), + &self.entropy_source, + &self.node_signer, + best_block_height, + &self.pending_events, + &self.logger, + |args| self.send_payment_along_path(args), + ); for (htlc_source, payment_hash, failure_reason, destination) in failed_forwards.drain(..) { - self.fail_htlc_backwards_internal(&htlc_source, &payment_hash, &failure_reason, destination); + self.fail_htlc_backwards_internal( + &htlc_source, + &payment_hash, + &failure_reason, + destination, + ); } self.forward_htlcs(&mut phantom_receives); @@ -6488,7 +7562,9 @@ where // network stack. self.check_free_holding_cells(); - if new_events.is_empty() { return } + if new_events.is_empty() { + return; + } let mut events = self.pending_events.lock().unwrap(); events.append(&mut new_events); } @@ -6497,7 +7573,10 @@ where /// /// Expects the caller to have a total_consistency_lock read lock. fn process_background_events(&self) -> NotifyOption { - debug_assert_ne!(self.total_consistency_lock.held_by_thread(), LockHeldState::NotHeldByThread); + debug_assert_ne!( + self.total_consistency_lock.held_by_thread(), + LockHeldState::NotHeldByThread + ); self.background_events_processed_since_startup.store(true, Ordering::Release); @@ -6509,22 +7588,41 @@ where for event in background_events.drain(..) { match event { - BackgroundEvent::MonitorUpdateRegeneratedOnStartup { counterparty_node_id, funding_txo, channel_id, update } => { - self.apply_post_close_monitor_update(counterparty_node_id, channel_id, funding_txo, update); + BackgroundEvent::MonitorUpdateRegeneratedOnStartup { + counterparty_node_id, + funding_txo, + channel_id, + update, + } => { + self.apply_post_close_monitor_update( + counterparty_node_id, + channel_id, + funding_txo, + update, + ); }, BackgroundEvent::MonitorUpdatesComplete { counterparty_node_id, channel_id } => { let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - if let Some(chan) = peer_state.channel_by_id + if let Some(chan) = peer_state + .channel_by_id .get_mut(&channel_id) .and_then(Channel::as_funded_mut) { - handle_monitor_update_completion!(self, peer_state_lock, peer_state, per_peer_state, chan); + handle_monitor_update_completion!( + self, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } else { - let update_actions = peer_state.monitor_update_blocked_actions - .remove(&channel_id).unwrap_or(Vec::new()); + let update_actions = peer_state + .monitor_update_blocked_actions + .remove(&channel_id) + .unwrap_or(Vec::new()); mem::drop(peer_state_lock); mem::drop(per_peer_state); self.handle_monitor_update_completion_actions(update_actions); @@ -6543,13 +7641,19 @@ where let _ = self.process_background_events(); } - fn update_channel_fee(&self, chan_id: &ChannelId, chan: &mut FundedChannel, new_feerate: u32) -> NotifyOption { - if !chan.funding.is_outbound() { return NotifyOption::SkipPersistNoEvents; } + fn update_channel_fee( + &self, chan_id: &ChannelId, chan: &mut FundedChannel, new_feerate: u32, + ) -> NotifyOption { + if !chan.funding.is_outbound() { + return NotifyOption::SkipPersistNoEvents; + } let logger = WithChannelContext::from(&self.logger, &chan.context, None); // If the feerate has decreased by less than half, don't bother - if new_feerate <= chan.context.get_feerate_sat_per_1000_weight() && new_feerate * 2 > chan.context.get_feerate_sat_per_1000_weight() { + if new_feerate <= chan.context.get_feerate_sat_per_1000_weight() + && new_feerate * 2 > chan.context.get_feerate_sat_per_1000_weight() + { return NotifyOption::SkipPersistNoEvents; } if !chan.context.is_live() { @@ -6557,8 +7661,13 @@ where chan_id, chan.context.get_feerate_sat_per_1000_weight(), new_feerate); return NotifyOption::SkipPersistNoEvents; } - log_trace!(logger, "Channel {} qualifies for a feerate change from {} to {}.", - &chan_id, chan.context.get_feerate_sat_per_1000_weight(), new_feerate); + log_trace!( + logger, + "Channel {} qualifies for a feerate change from {} to {}.", + &chan_id, + chan.context.get_feerate_sat_per_1000_weight(), + new_feerate + ); chan.queue_update_fee(new_feerate, &self.fee_estimator, &&logger); NotifyOption::DoPersist @@ -6573,23 +7682,32 @@ where PersistenceNotifierGuard::optionally_notify(self, || { let mut should_persist = NotifyOption::SkipPersistNoEvents; - let non_anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); - let anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee); + let non_anchor_feerate = self + .fee_estimator + .bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); + let anchor_feerate = self + .fee_estimator + .bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee); let per_peer_state = self.per_peer_state.read().unwrap(); for (_cp_id, peer_state_mutex) in per_peer_state.iter() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - for (chan_id, chan) in peer_state.channel_by_id.iter_mut() + for (chan_id, chan) in peer_state + .channel_by_id + .iter_mut() .filter_map(|(chan_id, chan)| chan.as_funded_mut().map(|chan| (chan_id, chan))) { - let new_feerate = if chan.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - anchor_feerate - } else { - non_anchor_feerate - }; + let new_feerate = + if chan.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + anchor_feerate + } else { + non_anchor_feerate + }; let chan_needs_persist = self.update_channel_fee(chan_id, chan, new_feerate); - if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; } + if chan_needs_persist == NotifyOption::DoPersist { + should_persist = NotifyOption::DoPersist; + } } } @@ -6622,8 +7740,12 @@ where PersistenceNotifierGuard::optionally_notify(self, || { let mut should_persist = NotifyOption::SkipPersistNoEvents; - let non_anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); - let anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee); + let non_anchor_feerate = self + .fee_estimator + .bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); + let anchor_feerate = self + .fee_estimator + .bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee); let mut handle_errors: Vec<(Result<(), _>, _)> = Vec::new(); let mut timed_out_mpp_htlcs = Vec::new(); @@ -6637,98 +7759,163 @@ where let peer_state = &mut *peer_state_lock; let pending_msg_events = &mut peer_state.pending_msg_events; let counterparty_node_id = *counterparty_node_id; - peer_state.channel_by_id.retain(|chan_id, chan| { - match chan.as_funded_mut() { - Some(funded_chan) => { - let new_feerate = if funded_chan.funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - anchor_feerate - } else { - non_anchor_feerate - }; - let chan_needs_persist = self.update_channel_fee(chan_id, funded_chan, new_feerate); - if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; } + peer_state.channel_by_id.retain(|chan_id, chan| match chan.as_funded_mut() { + Some(funded_chan) => { + let new_feerate = if funded_chan + .funding + .get_channel_type() + .supports_anchors_zero_fee_htlc_tx() + { + anchor_feerate + } else { + non_anchor_feerate + }; + let chan_needs_persist = + self.update_channel_fee(chan_id, funded_chan, new_feerate); + if chan_needs_persist == NotifyOption::DoPersist { + should_persist = NotifyOption::DoPersist; + } - if let Err(e) = funded_chan.timer_check_closing_negotiation_progress() { - let (needs_close, err) = convert_channel_err!(self, peer_state, e, funded_chan, chan_id, FUNDED_CHANNEL); - handle_errors.push((Err(err), counterparty_node_id)); - if needs_close { return false; } + if let Err(e) = funded_chan.timer_check_closing_negotiation_progress() { + let (needs_close, err) = convert_channel_err!( + self, + peer_state, + e, + funded_chan, + chan_id, + FUNDED_CHANNEL + ); + handle_errors.push((Err(err), counterparty_node_id)); + if needs_close { + return false; } + } - match funded_chan.channel_update_status() { - ChannelUpdateStatus::Enabled if !funded_chan.context.is_live() => funded_chan.set_channel_update_status(ChannelUpdateStatus::DisabledStaged(0)), - ChannelUpdateStatus::Disabled if funded_chan.context.is_live() => funded_chan.set_channel_update_status(ChannelUpdateStatus::EnabledStaged(0)), - ChannelUpdateStatus::DisabledStaged(_) if funded_chan.context.is_live() - => funded_chan.set_channel_update_status(ChannelUpdateStatus::Enabled), - ChannelUpdateStatus::EnabledStaged(_) if !funded_chan.context.is_live() - => funded_chan.set_channel_update_status(ChannelUpdateStatus::Disabled), - ChannelUpdateStatus::DisabledStaged(mut n) if !funded_chan.context.is_live() => { - n += 1; - if n >= DISABLE_GOSSIP_TICKS { - funded_chan.set_channel_update_status(ChannelUpdateStatus::Disabled); - if let Ok(update) = self.get_channel_update_for_broadcast(&funded_chan) { - let mut pending_broadcast_messages = self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); - } - should_persist = NotifyOption::DoPersist; - } else { - funded_chan.set_channel_update_status(ChannelUpdateStatus::DisabledStaged(n)); + match funded_chan.channel_update_status() { + ChannelUpdateStatus::Enabled if !funded_chan.context.is_live() => { + funded_chan.set_channel_update_status( + ChannelUpdateStatus::DisabledStaged(0), + ) + }, + ChannelUpdateStatus::Disabled if funded_chan.context.is_live() => { + funded_chan.set_channel_update_status( + ChannelUpdateStatus::EnabledStaged(0), + ) + }, + ChannelUpdateStatus::DisabledStaged(_) + if funded_chan.context.is_live() => + { + funded_chan + .set_channel_update_status(ChannelUpdateStatus::Enabled) + }, + ChannelUpdateStatus::EnabledStaged(_) + if !funded_chan.context.is_live() => + { + funded_chan + .set_channel_update_status(ChannelUpdateStatus::Disabled) + }, + ChannelUpdateStatus::DisabledStaged(mut n) + if !funded_chan.context.is_live() => + { + n += 1; + if n >= DISABLE_GOSSIP_TICKS { + funded_chan.set_channel_update_status( + ChannelUpdateStatus::Disabled, + ); + if let Ok(update) = + self.get_channel_update_for_broadcast(&funded_chan) + { + let mut pending_broadcast_messages = + self.pending_broadcast_messages.lock().unwrap(); + pending_broadcast_messages.push( + MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } - }, - ChannelUpdateStatus::EnabledStaged(mut n) if funded_chan.context.is_live() => { - n += 1; - if n >= ENABLE_GOSSIP_TICKS { - funded_chan.set_channel_update_status(ChannelUpdateStatus::Enabled); - if let Ok(update) = self.get_channel_update_for_broadcast(&funded_chan) { - let mut pending_broadcast_messages = self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); - } - should_persist = NotifyOption::DoPersist; - } else { - funded_chan.set_channel_update_status(ChannelUpdateStatus::EnabledStaged(n)); + should_persist = NotifyOption::DoPersist; + } else { + funded_chan.set_channel_update_status( + ChannelUpdateStatus::DisabledStaged(n), + ); + } + }, + ChannelUpdateStatus::EnabledStaged(mut n) + if funded_chan.context.is_live() => + { + n += 1; + if n >= ENABLE_GOSSIP_TICKS { + funded_chan.set_channel_update_status( + ChannelUpdateStatus::Enabled, + ); + if let Ok(update) = + self.get_channel_update_for_broadcast(&funded_chan) + { + let mut pending_broadcast_messages = + self.pending_broadcast_messages.lock().unwrap(); + pending_broadcast_messages.push( + MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } - }, - _ => {}, - } + should_persist = NotifyOption::DoPersist; + } else { + funded_chan.set_channel_update_status( + ChannelUpdateStatus::EnabledStaged(n), + ); + } + }, + _ => {}, + } - funded_chan.context.maybe_expire_prev_config(); + funded_chan.context.maybe_expire_prev_config(); - if peer_state.is_connected { - if funded_chan.should_disconnect_peer_awaiting_response() { - let logger = WithChannelContext::from(&self.logger, &funded_chan.context, None); - log_debug!(logger, "Disconnecting peer {} due to not making any progress on channel {}", + if peer_state.is_connected { + if funded_chan.should_disconnect_peer_awaiting_response() { + let logger = WithChannelContext::from( + &self.logger, + &funded_chan.context, + None, + ); + log_debug!(logger, "Disconnecting peer {} due to not making any progress on channel {}", counterparty_node_id, chan_id); - pending_msg_events.push(MessageSendEvent::HandleError { - node_id: counterparty_node_id, - action: msgs::ErrorAction::DisconnectPeerWithWarning { - msg: msgs::WarningMessage { - channel_id: *chan_id, - data: "Disconnecting due to timeout awaiting response".to_owned(), - }, + pending_msg_events.push(MessageSendEvent::HandleError { + node_id: counterparty_node_id, + action: msgs::ErrorAction::DisconnectPeerWithWarning { + msg: msgs::WarningMessage { + channel_id: *chan_id, + data: + "Disconnecting due to timeout awaiting response" + .to_owned(), }, - }); - } + }, + }); } + } - true - }, - None => { - chan.context_mut().maybe_expire_prev_config(); - let unfunded_context = chan.unfunded_context_mut().expect("channel should be unfunded"); - if unfunded_context.should_expire_unfunded_channel() { - let context = chan.context(); - let logger = WithChannelContext::from(&self.logger, context, None); - log_error!(logger, + true + }, + None => { + chan.context_mut().maybe_expire_prev_config(); + let unfunded_context = + chan.unfunded_context_mut().expect("channel should be unfunded"); + if unfunded_context.should_expire_unfunded_channel() { + let context = chan.context(); + let logger = WithChannelContext::from(&self.logger, context, None); + log_error!(logger, "Force-closing pending channel with ID {} for not establishing in a timely manner", context.channel_id()); - let mut close_res = chan.force_shutdown(false, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }); - let context = chan.context_mut(); - locked_close_channel!(self, peer_state, context, close_res); - shutdown_channels.push(close_res); - pending_msg_events.push(MessageSendEvent::HandleError { + let mut close_res = chan.force_shutdown( + false, + ClosureReason::HolderForceClosed { + broadcasted_latest_txn: Some(false), + }, + ); + let context = chan.context_mut(); + locked_close_channel!(self, peer_state, context, close_res); + shutdown_channels.push(close_res); + pending_msg_events.push(MessageSendEvent::HandleError { node_id: context.get_counterparty_node_id(), action: msgs::ErrorAction::SendErrorMessage { msg: msgs::ErrorMessage { @@ -6737,29 +7924,40 @@ where }, }, }); - false - } else { - true - } - }, - } + false + } else { + true + } + }, }); for (chan_id, req) in peer_state.inbound_channel_request_by_id.iter_mut() { - if { req.ticks_remaining -= 1 ; req.ticks_remaining } <= 0 { - let logger = WithContext::from(&self.logger, Some(counterparty_node_id), Some(*chan_id), None); + if { + req.ticks_remaining -= 1; + req.ticks_remaining + } <= 0 + { + let logger = WithContext::from( + &self.logger, + Some(counterparty_node_id), + Some(*chan_id), + None, + ); log_error!(logger, "Force-closing unaccepted inbound channel {} for not accepting in a timely manner", &chan_id); - peer_state.pending_msg_events.push( - MessageSendEvent::HandleError { - node_id: counterparty_node_id, - action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { channel_id: chan_id.clone(), data: "Channel force-closed".to_owned() } + peer_state.pending_msg_events.push(MessageSendEvent::HandleError { + node_id: counterparty_node_id, + action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { + channel_id: chan_id.clone(), + data: "Channel force-closed".to_owned(), }, - } - ); + }, + }); } } - peer_state.inbound_channel_request_by_id.retain(|_, req| req.ticks_remaining > 0); + peer_state + .inbound_channel_request_by_id + .retain(|_, req| req.ticks_remaining > 0); if peer_state.ok_to_remove(true) { pending_peers_awaiting_removal.push(counterparty_node_id); @@ -6789,37 +7987,47 @@ where entry.remove_entry(); } }, - hash_map::Entry::Vacant(_) => { /* The PeerState has already been removed */ } + hash_map::Entry::Vacant(_) => { /* The PeerState has already been removed */ + }, } } } - self.claimable_payments.lock().unwrap().claimable_payments.retain(|payment_hash, payment| { - if payment.htlcs.is_empty() { - // This should be unreachable - debug_assert!(false); - return false; - } - if let OnionPayload::Invoice { .. } = payment.htlcs[0].onion_payload { - // Check if we've received all the parts we need for an MPP (the value of the parts adds to total_msat). - // In this case we're not going to handle any timeouts of the parts here. - // This condition determining whether the MPP is complete here must match - // exactly the condition used in `process_pending_htlc_forwards`. - if payment.htlcs[0].total_msat <= payment.htlcs.iter() - .fold(0, |total, htlc| total + htlc.sender_intended_value) - { - return true; - } else if payment.htlcs.iter_mut().any(|htlc| { - htlc.timer_ticks += 1; - return htlc.timer_ticks >= MPP_TIMEOUT_TICKS - }) { - timed_out_mpp_htlcs.extend(payment.htlcs.drain(..) - .map(|htlc: ClaimableHTLC| (htlc.prev_hop, *payment_hash))); + self.claimable_payments.lock().unwrap().claimable_payments.retain( + |payment_hash, payment| { + if payment.htlcs.is_empty() { + // This should be unreachable + debug_assert!(false); return false; } - } - true - }); + if let OnionPayload::Invoice { .. } = payment.htlcs[0].onion_payload { + // Check if we've received all the parts we need for an MPP (the value of the parts adds to total_msat). + // In this case we're not going to handle any timeouts of the parts here. + // This condition determining whether the MPP is complete here must match + // exactly the condition used in `process_pending_htlc_forwards`. + if payment.htlcs[0].total_msat + <= payment + .htlcs + .iter() + .fold(0, |total, htlc| total + htlc.sender_intended_value) + { + return true; + } else if payment.htlcs.iter_mut().any(|htlc| { + htlc.timer_ticks += 1; + return htlc.timer_ticks >= MPP_TIMEOUT_TICKS; + }) { + timed_out_mpp_htlcs.extend( + payment + .htlcs + .drain(..) + .map(|htlc: ClaimableHTLC| (htlc.prev_hop, *payment_hash)), + ); + return false; + } + } + true + }, + ); for htlc_source in timed_out_mpp_htlcs.drain(..) { let source = HTLCSource::PreviousHopData(htlc_source.0.clone()); @@ -6843,12 +8051,11 @@ where .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH"); #[cfg(not(feature = "std"))] let duration_since_epoch = Duration::from_secs( - self.highest_seen_timestamp.load(Ordering::Acquire).saturating_sub(7200) as u64 + self.highest_seen_timestamp.load(Ordering::Acquire).saturating_sub(7200) as u64, ); - self.pending_outbound_payments.remove_stale_payments( - duration_since_epoch, &self.pending_events - ); + self.pending_outbound_payments + .remove_stale_payments(duration_since_epoch, &self.pending_events); // Technically we don't need to do this here, but if we have holding cell entries in a // channel that need freeing, it's better to do that here and block a background task @@ -6875,17 +8082,23 @@ where /// [`events::Event::PaymentClaimed`] events even for payments you intend to fail, especially on /// startup during which time claims that were in-progress at shutdown may be replayed. pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) { - self.fail_htlc_backwards_with_reason(payment_hash, FailureCode::IncorrectOrUnknownPaymentDetails); + self.fail_htlc_backwards_with_reason( + payment_hash, + FailureCode::IncorrectOrUnknownPaymentDetails, + ); } /// This is a variant of [`ChannelManager::fail_htlc_backwards`] that allows you to specify the /// reason for the failure. /// /// See [`FailureCode`] for valid failure codes. - pub fn fail_htlc_backwards_with_reason(&self, payment_hash: &PaymentHash, failure_code: FailureCode) { + pub fn fail_htlc_backwards_with_reason( + &self, payment_hash: &PaymentHash, failure_code: FailureCode, + ) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let removed_source = self.claimable_payments.lock().unwrap().claimable_payments.remove(payment_hash); + let removed_source = + self.claimable_payments.lock().unwrap().claimable_payments.remove(payment_hash); if let Some(payment) = removed_source { for htlc in payment.htlcs { let reason = self.get_htlc_fail_reason_from_failure_code(failure_code, &htlc); @@ -6897,13 +8110,20 @@ where } /// Gets error data to form an [`HTLCFailReason`] given a [`FailureCode`] and [`ClaimableHTLC`]. - fn get_htlc_fail_reason_from_failure_code(&self, failure_code: FailureCode, htlc: &ClaimableHTLC) -> HTLCFailReason { + fn get_htlc_fail_reason_from_failure_code( + &self, failure_code: FailureCode, htlc: &ClaimableHTLC, + ) -> HTLCFailReason { match failure_code { - FailureCode::TemporaryNodeFailure => HTLCFailReason::from_failure_code(failure_code.into()), - FailureCode::RequiredNodeFeatureMissing => HTLCFailReason::from_failure_code(failure_code.into()), + FailureCode::TemporaryNodeFailure => { + HTLCFailReason::from_failure_code(failure_code.into()) + }, + FailureCode::RequiredNodeFeatureMissing => { + HTLCFailReason::from_failure_code(failure_code.into()) + }, FailureCode::IncorrectOrUnknownPaymentDetails => { let mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec(); - htlc_msat_height_data.extend_from_slice(&self.best_block.read().unwrap().height.to_be_bytes()); + htlc_msat_height_data + .extend_from_slice(&self.best_block.read().unwrap().height.to_be_bytes()); HTLCFailReason::reason(failure_code.into(), htlc_msat_height_data) }, FailureCode::InvalidOnionPayload(data) => { @@ -6912,7 +8132,7 @@ where None => Vec::new(), }; HTLCFailReason::reason(failure_code.into(), fail_data) - } + }, } } @@ -6943,7 +8163,7 @@ where // be surfaced to the user. fn fail_holding_cell_htlcs( &self, mut htlcs_to_fail: Vec<(HTLCSource, PaymentHash)>, channel_id: ChannelId, - counterparty_node_id: &PublicKey + counterparty_node_id: &PublicKey, ) { let (failure_reason, onion_failure_data) = { let per_peer_state = self.per_peer_state.read().unwrap(); @@ -6962,26 +8182,46 @@ where (LocalHTLCFailureReason::UnknownNextPeer, Vec::new()) } }, - hash_map::Entry::Vacant(_) => (LocalHTLCFailureReason::UnknownNextPeer, Vec::new()) + hash_map::Entry::Vacant(_) => { + (LocalHTLCFailureReason::UnknownNextPeer, Vec::new()) + }, } - } else { (LocalHTLCFailureReason::UnknownNextPeer, Vec::new()) } + } else { + (LocalHTLCFailureReason::UnknownNextPeer, Vec::new()) + } }; for (htlc_src, payment_hash) in htlcs_to_fail.drain(..) { let reason = HTLCFailReason::reason(failure_reason, onion_failure_data.clone()); - let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id.clone()), channel_id }; + let receiver = HTLCDestination::NextHopChannel { + node_id: Some(counterparty_node_id.clone()), + channel_id, + }; self.fail_htlc_backwards_internal(&htlc_src, &payment_hash, &reason, receiver); } } - fn fail_htlc_backwards_internal(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) { - let push_forward_event = self.fail_htlc_backwards_internal_without_forward_event(source, payment_hash, onion_error, destination); - if push_forward_event { self.push_pending_forwards_ev(); } + fn fail_htlc_backwards_internal( + &self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, + destination: HTLCDestination, + ) { + let push_forward_event = self.fail_htlc_backwards_internal_without_forward_event( + source, + payment_hash, + onion_error, + destination, + ); + if push_forward_event { + self.push_pending_forwards_ev(); + } } /// Fails an HTLC backwards to the sender of it to us. /// Note that we do not assume that channels corresponding to failed HTLCs are still available. - fn fail_htlc_backwards_internal_without_forward_event(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) -> bool { + fn fail_htlc_backwards_internal_without_forward_event( + &self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, + destination: HTLCDestination, + ) -> bool { // Ensure that no peer state channel storage lock is held when calling this function. // This ensures that future code doesn't introduce a lock-order requirement for // `forward_htlcs` to be locked after the `per_peer_state` peer locks, which calling @@ -7002,40 +8242,60 @@ where let mut push_forward_event; match source { HTLCSource::OutboundRoute { ref path, ref session_priv, ref payment_id, .. } => { - push_forward_event = self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path, - session_priv, payment_id, self.probing_cookie_secret, &self.secp_ctx, - &self.pending_events, &self.logger); + push_forward_event = self.pending_outbound_payments.fail_htlc( + source, + payment_hash, + onion_error, + path, + session_priv, + payment_id, + self.probing_cookie_secret, + &self.secp_ctx, + &self.pending_events, + &self.logger, + ); }, HTLCSource::PreviousHopData(HTLCPreviousHopData { - ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, - ref phantom_shared_secret, outpoint: _, ref blinded_failure, ref channel_id, .. + ref short_channel_id, + ref htlc_id, + ref incoming_packet_shared_secret, + ref phantom_shared_secret, + outpoint: _, + ref blinded_failure, + ref channel_id, + .. }) => { log_trace!( WithContext::from(&self.logger, None, Some(*channel_id), Some(*payment_hash)), "Failing {}HTLC with payment_hash {} backwards from us: {:?}", - if blinded_failure.is_some() { "blinded " } else { "" }, &payment_hash, onion_error + if blinded_failure.is_some() { "blinded " } else { "" }, + &payment_hash, + onion_error ); let failure = match blinded_failure { Some(BlindedFailure::FromIntroductionNode) => { - let blinded_onion_error = HTLCFailReason::reason(LocalHTLCFailureReason::InvalidOnionBlinding, vec![0; 32]); + let blinded_onion_error = HTLCFailReason::reason( + LocalHTLCFailureReason::InvalidOnionBlinding, + vec![0; 32], + ); let err_packet = blinded_onion_error.get_encrypted_failure_packet( - incoming_packet_shared_secret, phantom_shared_secret + incoming_packet_shared_secret, + phantom_shared_secret, ); HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet } }, - Some(BlindedFailure::FromBlindedNode) => { - HTLCForwardInfo::FailMalformedHTLC { - htlc_id: *htlc_id, - failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(), - sha256_of_onion: [0; 32] - } + Some(BlindedFailure::FromBlindedNode) => HTLCForwardInfo::FailMalformedHTLC { + htlc_id: *htlc_id, + failure_code: LocalHTLCFailureReason::InvalidOnionBlinding.failure_code(), + sha256_of_onion: [0; 32], }, None => { let err_packet = onion_error.get_encrypted_failure_packet( - incoming_packet_shared_secret, phantom_shared_secret + incoming_packet_shared_secret, + phantom_shared_secret, ); HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet } - } + }, }; push_forward_event = self.decode_update_add_htlcs.lock().unwrap().is_empty(); @@ -7046,15 +8306,18 @@ where entry.get_mut().push(failure); }, hash_map::Entry::Vacant(entry) => { - entry.insert(vec!(failure)); - } + entry.insert(vec![failure]); + }, } mem::drop(forward_htlcs); let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push_back((events::Event::HTLCHandlingFailed { - prev_channel_id: *channel_id, - failed_next_destination: destination, - }, None)); + pending_events.push_back(( + events::Event::HTLCHandlingFailed { + prev_channel_id: *channel_id, + failed_next_destination: destination, + }, + None, + )); }, } push_forward_event @@ -7108,7 +8371,10 @@ where let (sources, claiming_payment) = { let res = self.claimable_payments.lock().unwrap().begin_claiming_payment( - payment_hash, &self.node_signer, &self.logger, &self.inbound_payment_id_secret, + payment_hash, + &self.node_signer, + &self.logger, + &self.inbound_payment_id_secret, custom_tlvs_known, ); @@ -7116,13 +8382,21 @@ where Ok((htlcs, payment_info)) => (htlcs, payment_info), Err(htlcs) => { for htlc in htlcs { - let reason = self.get_htlc_fail_reason_from_failure_code(FailureCode::InvalidOnionPayload(None), &htlc); + let reason = self.get_htlc_fail_reason_from_failure_code( + FailureCode::InvalidOnionPayload(None), + &htlc, + ); let source = HTLCSource::PreviousHopData(htlc.prev_hop); let receiver = HTLCDestination::FailedPayment { payment_hash }; - self.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver); + self.fail_htlc_backwards_internal( + &source, + &payment_hash, + &reason, + receiver, + ); } return; - } + }, } }; debug_assert!(!sources.is_empty()); @@ -7158,7 +8432,10 @@ where mem::drop(per_peer_state); if sources.is_empty() || expected_amt_msat.is_none() { self.claimable_payments.lock().unwrap().pending_claiming_payments.remove(&payment_hash); - log_info!(self.logger, "Attempted to claim an incomplete payment which no longer had any available HTLCs!"); + log_info!( + self.logger, + "Attempted to claim an incomplete payment which no longer had any available HTLCs!" + ); return; } if claimable_amt_msat != expected_amt_msat.unwrap() { @@ -7168,18 +8445,21 @@ where return; } if valid_mpp { - let mpp_parts: Vec<_> = sources.iter().filter_map(|htlc| { - if let Some(cp_id) = htlc.prev_hop.counterparty_node_id { - Some(MPPClaimHTLCSource { - counterparty_node_id: cp_id, - funding_txo: htlc.prev_hop.outpoint, - channel_id: htlc.prev_hop.channel_id, - htlc_id: htlc.prev_hop.htlc_id, - }) - } else { - None - } - }).collect(); + let mpp_parts: Vec<_> = sources + .iter() + .filter_map(|htlc| { + if let Some(cp_id) = htlc.prev_hop.counterparty_node_id { + Some(MPPClaimHTLCSource { + counterparty_node_id: cp_id, + funding_txo: htlc.prev_hop.outpoint, + channel_id: htlc.prev_hop.channel_id, + htlc_id: htlc.prev_hop.htlc_id, + }) + } else { + None + } + }) + .collect(); let pending_mpp_claim_ptr_opt = if sources.len() > 1 { let mut channels_without_preimage = Vec::with_capacity(mpp_parts.len()); for part in mpp_parts.iter() { @@ -7197,32 +8477,48 @@ where }; let payment_info = Some(PaymentClaimDetails { mpp_parts, claiming_payment }); for htlc in sources { - let this_mpp_claim = pending_mpp_claim_ptr_opt.as_ref().and_then(|pending_mpp_claim| - if let Some(cp_id) = htlc.prev_hop.counterparty_node_id { - let claim_ptr = PendingMPPClaimPointer(Arc::clone(pending_mpp_claim)); - Some((cp_id, htlc.prev_hop.channel_id, claim_ptr)) - } else { - None - } - ); + let this_mpp_claim = + pending_mpp_claim_ptr_opt.as_ref().and_then(|pending_mpp_claim| { + if let Some(cp_id) = htlc.prev_hop.counterparty_node_id { + let claim_ptr = PendingMPPClaimPointer(Arc::clone(pending_mpp_claim)); + Some((cp_id, htlc.prev_hop.channel_id, claim_ptr)) + } else { + None + } + }); let raa_blocker = pending_mpp_claim_ptr_opt.as_ref().map(|pending_claim| { RAAMonitorUpdateBlockingAction::ClaimedMPPPayment { pending_claim: PendingMPPClaimPointer(Arc::clone(pending_claim)), } }); self.claim_funds_from_hop( - htlc.prev_hop, payment_preimage, payment_info.clone(), + htlc.prev_hop, + payment_preimage, + payment_info.clone(), |_, definitely_duplicate| { - debug_assert!(!definitely_duplicate, "We shouldn't claim duplicatively from a payment"); - (Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash, pending_mpp_claim: this_mpp_claim }), raa_blocker) - } - ); + debug_assert!( + !definitely_duplicate, + "We shouldn't claim duplicatively from a payment" + ); + ( + Some(MonitorUpdateCompletionAction::PaymentClaimed { + payment_hash, + pending_mpp_claim: this_mpp_claim, + }), + raa_blocker, + ) + }, + ); } } else { for htlc in sources { - let err_data = invalid_payment_err_data(htlc.value, self.best_block.read().unwrap().height); + let err_data = + invalid_payment_err_data(htlc.value, self.best_block.read().unwrap().height); let source = HTLCSource::PreviousHopData(htlc.prev_hop); - let reason = HTLCFailReason::reason(LocalHTLCFailureReason::IncorrectPaymentDetails, err_data); + let reason = HTLCFailReason::reason( + LocalHTLCFailureReason::IncorrectPaymentDetails, + err_data, + ); let receiver = HTLCDestination::FailedPayment { payment_hash }; self.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver); } @@ -7237,7 +8533,10 @@ where } fn claim_funds_from_hop< - ComplFunc: FnOnce(Option, bool) -> (Option, Option) + ComplFunc: FnOnce( + Option, + bool, + ) -> (Option, Option), >( &self, prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, payment_info: Option, completion_action: ComplFunc, @@ -7257,7 +8556,10 @@ where } fn claim_mpp_part< - ComplFunc: FnOnce(Option, bool) -> (Option, Option) + ComplFunc: FnOnce( + Option, + bool, + ) -> (Option, Option), >( &self, prev_hop: HTLCClaimSource, payment_preimage: PaymentPreimage, payment_info: Option, completion_action: ComplFunc, @@ -7282,33 +8584,58 @@ where // Note here that `peer_state_opt` is always `Some` if `prev_hop.counterparty_node_id` is // `Some`. This is relied on in the closed-channel case below. - let mut peer_state_opt = prev_hop.counterparty_node_id.as_ref().map( - |counterparty_node_id| per_peer_state.get(counterparty_node_id) - .map(|peer_mutex| peer_mutex.lock().unwrap()) - .expect(MISSING_MON_ERROR) - ); + let mut peer_state_opt = + prev_hop.counterparty_node_id.as_ref().map(|counterparty_node_id| { + per_peer_state + .get(counterparty_node_id) + .map(|peer_mutex| peer_mutex.lock().unwrap()) + .expect(MISSING_MON_ERROR) + }); if let Some(peer_state_lock) = peer_state_opt.as_mut() { let peer_state = &mut **peer_state_lock; - if let hash_map::Entry::Occupied(mut chan_entry) = peer_state.channel_by_id.entry(chan_id) { + if let hash_map::Entry::Occupied(mut chan_entry) = + peer_state.channel_by_id.entry(chan_id) + { if let Some(chan) = chan_entry.get_mut().as_funded_mut() { let logger = WithChannelContext::from(&self.logger, &chan.context, None); - let fulfill_res = chan.get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, payment_info, &&logger); + let fulfill_res = chan.get_update_fulfill_htlc_and_commit( + prev_hop.htlc_id, + payment_preimage, + payment_info, + &&logger, + ); match fulfill_res { UpdateFulfillCommitFetch::NewClaim { htlc_value_msat, monitor_update } => { - let (action_opt, raa_blocker_opt) = completion_action(Some(htlc_value_msat), false); + let (action_opt, raa_blocker_opt) = + completion_action(Some(htlc_value_msat), false); if let Some(action) = action_opt { log_trace!(logger, "Tracking monitor update completion action for channel {}: {:?}", chan_id, action); - peer_state.monitor_update_blocked_actions.entry(chan_id).or_insert(Vec::new()).push(action); + peer_state + .monitor_update_blocked_actions + .entry(chan_id) + .or_insert(Vec::new()) + .push(action); } if let Some(raa_blocker) = raa_blocker_opt { - peer_state.actions_blocking_raa_monitor_updates.entry(chan_id).or_insert_with(Vec::new).push(raa_blocker); + peer_state + .actions_blocking_raa_monitor_updates + .entry(chan_id) + .or_insert_with(Vec::new) + .push(raa_blocker); } - handle_new_monitor_update!(self, prev_hop.funding_txo, monitor_update, peer_state_opt, - peer_state, per_peer_state, chan); - } + handle_new_monitor_update!( + self, + prev_hop.funding_txo, + monitor_update, + peer_state_opt, + peer_state, + per_peer_state, + chan + ); + }, UpdateFulfillCommitFetch::DuplicateClaim {} => { let (action_opt, raa_blocker_opt) = completion_action(None, true); if let Some(raa_blocker) = raa_blocker_opt { @@ -7320,8 +8647,14 @@ where // // In any other case, the RAA blocker must still be present and // blocking RAAs. - debug_assert!(during_init || - peer_state.actions_blocking_raa_monitor_updates.get(&chan_id).unwrap().contains(&raa_blocker)); + debug_assert!( + during_init + || peer_state + .actions_blocking_raa_monitor_updates + .get(&chan_id) + .unwrap() + .contains(&raa_blocker) + ); } let action = if let Some(action) = action_opt { action @@ -7336,8 +8669,10 @@ where if let MonitorUpdateCompletionAction::FreeOtherChannelImmediately { downstream_counterparty_node_id: node_id, downstream_funding_outpoint: _, - blocking_action: blocker, downstream_channel_id: channel_id, - } = action { + blocking_action: blocker, + downstream_channel_id: channel_id, + } = action + { if let Some(peer_state_mtx) = per_peer_state.get(&node_id) { let mut peer_state = peer_state_mtx.lock().unwrap(); if let Some(blockers) = peer_state @@ -7350,7 +8685,9 @@ where // which case we need to only remove the one // blocker which was added duplicatively. let first_blocker = !found_blocker; - if *iter == blocker { found_blocker = true; } + if *iter == blocker { + found_blocker = true; + } *iter != blocker || !first_blocker }); debug_assert!(found_blocker); @@ -7358,7 +8695,10 @@ where } else { debug_assert!(false); } - } else if matches!(action, MonitorUpdateCompletionAction::PaymentClaimed { .. }) { + } else if matches!( + action, + MonitorUpdateCompletionAction::PaymentClaimed { .. } + ) { debug_assert!(during_init, "Duplicate claims should always either be for forwarded payments(freeing another channel immediately) or during init (for claim replay)"); mem::drop(per_peer_state); @@ -7368,7 +8708,7 @@ where "Duplicate claims should always either be for forwarded payments(freeing another channel immediately) or during init (for claim replay)"); return; }; - } + }, } } return; @@ -7383,10 +8723,14 @@ where payment_preimage, ); } - let counterparty_node_id = prev_hop.counterparty_node_id.expect("Checked immediately above"); - let mut peer_state = peer_state_opt.expect("peer_state_opt is always Some when the counterparty_node_id is Some"); + let counterparty_node_id = + prev_hop.counterparty_node_id.expect("Checked immediately above"); + let mut peer_state = peer_state_opt + .expect("peer_state_opt is always Some when the counterparty_node_id is Some"); - let update_id = if let Some(latest_update_id) = peer_state.closed_channel_monitor_update_ids.get_mut(&chan_id) { + let update_id = if let Some(latest_update_id) = + peer_state.closed_channel_monitor_update_ids.get_mut(&chan_id) + { *latest_update_id = latest_update_id.saturating_add(1); *latest_update_id } else { @@ -7414,7 +8758,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let (action_opt, raa_blocker_opt) = completion_action(None, false); if let Some(raa_blocker) = raa_blocker_opt { - peer_state.actions_blocking_raa_monitor_updates + peer_state + .actions_blocking_raa_monitor_updates .entry(prev_hop.channel_id) .or_default() .push(raa_blocker); @@ -7423,17 +8768,37 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ // Given the fact that we're in a bit of a weird edge case, its worth hashing the preimage // to include the `payment_hash` in the log metadata here. let payment_hash = payment_preimage.into(); - let logger = WithContext::from(&self.logger, Some(counterparty_node_id), Some(chan_id), Some(payment_hash)); + let logger = WithContext::from( + &self.logger, + Some(counterparty_node_id), + Some(chan_id), + Some(payment_hash), + ); if let Some(action) = action_opt { - log_trace!(logger, "Tracking monitor update completion action for closed channel {}: {:?}", - chan_id, action); - peer_state.monitor_update_blocked_actions.entry(chan_id).or_insert(Vec::new()).push(action); + log_trace!( + logger, + "Tracking monitor update completion action for closed channel {}: {:?}", + chan_id, + action + ); + peer_state + .monitor_update_blocked_actions + .entry(chan_id) + .or_insert(Vec::new()) + .push(action); } handle_new_monitor_update!( - self, prev_hop.funding_txo, preimage_update, peer_state, peer_state, per_peer_state, - counterparty_node_id, chan_id, POST_CHANNEL_CLOSE + self, + prev_hop.funding_txo, + preimage_update, + peer_state, + peer_state, + per_peer_state, + counterparty_node_id, + chan_id, + POST_CHANNEL_CLOSE ); } @@ -7441,10 +8806,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ self.pending_outbound_payments.finalize_claims(sources, &self.pending_events); } - fn claim_funds_internal(&self, source: HTLCSource, payment_preimage: PaymentPreimage, + fn claim_funds_internal( + &self, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option, skimmed_fee_msat: Option, from_onchain: bool, startup_replay: bool, next_channel_counterparty_node_id: PublicKey, - next_channel_outpoint: OutPoint, next_channel_id: ChannelId, next_user_channel_id: Option, + next_channel_outpoint: OutPoint, next_channel_id: ChannelId, + next_user_channel_id: Option, ) { match source { HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => { @@ -7452,25 +8819,37 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ "We don't support claim_htlc claims during startup - monitors may not be available yet"); debug_assert_eq!(next_channel_counterparty_node_id, path.hops[0].pubkey); let ev_completion_action = EventCompletionAction::ReleaseRAAChannelMonitorUpdate { - channel_funding_outpoint: next_channel_outpoint, channel_id: next_channel_id, + channel_funding_outpoint: next_channel_outpoint, + channel_id: next_channel_id, counterparty_node_id: path.hops[0].pubkey, }; - self.pending_outbound_payments.claim_htlc(payment_id, payment_preimage, - session_priv, path, from_onchain, ev_completion_action, &self.pending_events, - &self.logger); + self.pending_outbound_payments.claim_htlc( + payment_id, + payment_preimage, + session_priv, + path, + from_onchain, + ev_completion_action, + &self.pending_events, + &self.logger, + ); }, HTLCSource::PreviousHopData(hop_data) => { let prev_channel_id = hop_data.channel_id; let prev_user_channel_id = hop_data.user_channel_id; let prev_node_id = hop_data.counterparty_node_id; - let completed_blocker = RAAMonitorUpdateBlockingAction::from_prev_hop_data(&hop_data); - self.claim_funds_from_hop(hop_data, payment_preimage, None, + let completed_blocker = + RAAMonitorUpdateBlockingAction::from_prev_hop_data(&hop_data); + self.claim_funds_from_hop( + hop_data, + payment_preimage, + None, |htlc_claim_value_msat, definitely_duplicate| { let chan_to_release = Some(EventUnblockedChannel { counterparty_node_id: next_channel_counterparty_node_id, funding_txo: next_channel_outpoint, channel_id: next_channel_id, - blocking_action: completed_blocker + blocking_action: completed_blocker, }); if definitely_duplicate && startup_replay { @@ -7487,32 +8866,45 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ downstream_channel_id: other_chan.channel_id, blocking_action: other_chan.blocking_action, }), None) - } else { (None, None) } + } else { + (None, None) + } } else { - let total_fee_earned_msat = if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat { - if let Some(claimed_htlc_value) = htlc_claim_value_msat { - Some(claimed_htlc_value - forwarded_htlc_value) - } else { None } - } else { None }; - debug_assert!(skimmed_fee_msat <= total_fee_earned_msat, - "skimmed_fee_msat must always be included in total_fee_earned_msat"); - (Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { - event: events::Event::PaymentForwarded { - prev_channel_id: Some(prev_channel_id), - next_channel_id: Some(next_channel_id), - prev_user_channel_id, - next_user_channel_id, - prev_node_id, - next_node_id: Some(next_channel_counterparty_node_id), - total_fee_earned_msat, - skimmed_fee_msat, - claim_from_onchain_tx: from_onchain, - outbound_amount_forwarded_msat: forwarded_htlc_value_msat, - }, - downstream_counterparty_and_funding_outpoint: chan_to_release, - }), None) + let total_fee_earned_msat = + if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat { + if let Some(claimed_htlc_value) = htlc_claim_value_msat { + Some(claimed_htlc_value - forwarded_htlc_value) + } else { + None + } + } else { + None + }; + debug_assert!( + skimmed_fee_msat <= total_fee_earned_msat, + "skimmed_fee_msat must always be included in total_fee_earned_msat" + ); + ( + Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { + event: events::Event::PaymentForwarded { + prev_channel_id: Some(prev_channel_id), + next_channel_id: Some(next_channel_id), + prev_user_channel_id, + next_user_channel_id, + prev_node_id, + next_node_id: Some(next_channel_counterparty_node_id), + total_fee_earned_msat, + skimmed_fee_msat, + claim_from_onchain_tx: from_onchain, + outbound_amount_forwarded_msat: forwarded_htlc_value_msat, + }, + downstream_counterparty_and_funding_outpoint: chan_to_release, + }), + None, + ) } - }); + }, + ); }, } } @@ -7522,7 +8914,11 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ self.our_network_pubkey } - fn handle_monitor_update_completion_actions>(&self, actions: I) { + fn handle_monitor_update_completion_actions< + I: IntoIterator, + >( + &self, actions: I, + ) { debug_assert_ne!(self.pending_events.held_by_thread(), LockHeldState::HeldByThread); debug_assert_ne!(self.claimable_payments.held_by_thread(), LockHeldState::HeldByThread); debug_assert_ne!(self.per_peer_state.held_by_thread(), LockHeldState::HeldByThread); @@ -7531,36 +8927,64 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ for action in actions.into_iter() { match action { - MonitorUpdateCompletionAction::PaymentClaimed { payment_hash, pending_mpp_claim } => { + MonitorUpdateCompletionAction::PaymentClaimed { + payment_hash, + pending_mpp_claim, + } => { if let Some((counterparty_node_id, chan_id, claim_ptr)) = pending_mpp_claim { let per_peer_state = self.per_peer_state.read().unwrap(); per_peer_state.get(&counterparty_node_id).map(|peer_state_mutex| { let mut peer_state = peer_state_mutex.lock().unwrap(); - let blockers_entry = peer_state.actions_blocking_raa_monitor_updates.entry(chan_id); + let blockers_entry = + peer_state.actions_blocking_raa_monitor_updates.entry(chan_id); if let btree_map::Entry::Occupied(mut blockers) = blockers_entry { - blockers.get_mut().retain(|blocker| - if let &RAAMonitorUpdateBlockingAction::ClaimedMPPPayment { pending_claim } = &blocker { + blockers.get_mut().retain(|blocker| { + if let &RAAMonitorUpdateBlockingAction::ClaimedMPPPayment { + pending_claim, + } = &blocker + { if *pending_claim == claim_ptr { - let mut pending_claim_state_lock = pending_claim.0.lock().unwrap(); - let pending_claim_state = &mut *pending_claim_state_lock; - pending_claim_state.channels_without_preimage.retain(|(cp, op, cid)| { - let this_claim = - *cp == counterparty_node_id && *cid == chan_id; - if this_claim { - pending_claim_state.channels_with_preimage.push((*cp, *op, *cid)); - false - } else { true } - }); - if pending_claim_state.channels_without_preimage.is_empty() { - for (cp, op, cid) in pending_claim_state.channels_with_preimage.iter() { - let freed_chan = (*cp, *op, *cid, blocker.clone()); + let mut pending_claim_state_lock = + pending_claim.0.lock().unwrap(); + let pending_claim_state = + &mut *pending_claim_state_lock; + pending_claim_state.channels_without_preimage.retain( + |(cp, op, cid)| { + let this_claim = *cp == counterparty_node_id + && *cid == chan_id; + if this_claim { + pending_claim_state + .channels_with_preimage + .push((*cp, *op, *cid)); + false + } else { + true + } + }, + ); + if pending_claim_state + .channels_without_preimage + .is_empty() + { + for (cp, op, cid) in pending_claim_state + .channels_with_preimage + .iter() + { + let freed_chan = + (*cp, *op, *cid, blocker.clone()); freed_channels.push(freed_chan); } } - !pending_claim_state.channels_without_preimage.is_empty() - } else { true } - } else { true } - ); + !pending_claim_state + .channels_without_preimage + .is_empty() + } else { + true + } + } else { + true + } + }); if blockers.get().is_empty() { blockers.remove(); } @@ -7568,7 +8992,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ }); } - let payment = self.claimable_payments.lock().unwrap().pending_claiming_payments.remove(&payment_hash); + let payment = self + .claimable_payments + .lock() + .unwrap() + .pending_claiming_payments + .remove(&payment_hash); if let Some(ClaimingPayment { amount_msat, payment_purpose: purpose, @@ -7577,7 +9006,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ sender_intended_value: sender_intended_total_msat, onion_fields, payment_id, - }) = payment { + }) = payment + { let event = events::Event::PaymentClaimed { payment_hash, purpose, @@ -7600,18 +9030,24 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } }, MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { - event, downstream_counterparty_and_funding_outpoint + event, + downstream_counterparty_and_funding_outpoint, } => { self.pending_events.lock().unwrap().push_back((event, None)); if let Some(unblocked) = downstream_counterparty_and_funding_outpoint { self.handle_monitor_update_release( - unblocked.counterparty_node_id, unblocked.funding_txo, - unblocked.channel_id, Some(unblocked.blocking_action), + unblocked.counterparty_node_id, + unblocked.funding_txo, + unblocked.channel_id, + Some(unblocked.blocking_action), ); } }, MonitorUpdateCompletionAction::FreeOtherChannelImmediately { - downstream_counterparty_node_id, downstream_funding_outpoint, downstream_channel_id, blocking_action, + downstream_counterparty_node_id, + downstream_funding_outpoint, + downstream_channel_id, + blocking_action, } => { self.handle_monitor_update_release( downstream_counterparty_node_id, @@ -7624,20 +9060,29 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } for (node_id, funding_outpoint, channel_id, blocker) in freed_channels { - self.handle_monitor_update_release(node_id, funding_outpoint, channel_id, Some(blocker)); + self.handle_monitor_update_release( + node_id, + funding_outpoint, + channel_id, + Some(blocker), + ); } } /// Handles a channel reentering a functional state, either due to reconnect or a monitor /// update completion. - fn handle_channel_resumption(&self, pending_msg_events: &mut Vec, - channel: &mut FundedChannel, raa: Option, - commitment_update: Option, order: RAACommitmentOrder, - pending_forwards: Vec<(PendingHTLCInfo, u64)>, pending_update_adds: Vec, - funding_broadcastable: Option, - channel_ready: Option, announcement_sigs: Option, - tx_signatures: Option - ) -> (Option<(u64, Option, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)>, Option<(u64, Vec)>) { + fn handle_channel_resumption( + &self, pending_msg_events: &mut Vec, channel: &mut FundedChannel, + raa: Option, commitment_update: Option, + order: RAACommitmentOrder, pending_forwards: Vec<(PendingHTLCInfo, u64)>, + pending_update_adds: Vec, funding_broadcastable: Option, + channel_ready: Option, + announcement_sigs: Option, + tx_signatures: Option, + ) -> ( + Option<(u64, Option, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)>, + Option<(u64, Vec)>, + ) { let logger = WithChannelContext::from(&self.logger, &channel.context, None); log_trace!(logger, "Handling channel resumption for channel {} with {} RAA, {} commitment update, {} pending forwards, {} pending update_add_htlcs, {}broadcasting funding, {} channel ready, {} announcement, {} tx_signatures", &channel.context.channel_id(), @@ -7651,14 +9096,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ ); let counterparty_node_id = channel.context.get_counterparty_node_id(); - let short_channel_id = channel.context.get_short_channel_id().unwrap_or(channel.context.outbound_scid_alias()); + let short_channel_id = + channel.context.get_short_channel_id().unwrap_or(channel.context.outbound_scid_alias()); let mut htlc_forwards = None; if !pending_forwards.is_empty() { htlc_forwards = Some(( - short_channel_id, Some(channel.context.get_counterparty_node_id()), - channel.funding.get_funding_txo().unwrap(), channel.context.channel_id(), - channel.context.get_user_id(), pending_forwards + short_channel_id, + Some(channel.context.get_counterparty_node_id()), + channel.funding.get_funding_txo().unwrap(), + channel.context.channel_id(), + channel.context.get_user_id(), + pending_forwards, )); } let mut decode_update_add_htlcs = None; @@ -7676,29 +9125,31 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ }); } if let Some(msg) = tx_signatures { - pending_msg_events.push(MessageSendEvent::SendTxSignatures { - node_id: counterparty_node_id, - msg, - }); + pending_msg_events + .push(MessageSendEvent::SendTxSignatures { node_id: counterparty_node_id, msg }); } - macro_rules! handle_cs { () => { - if let Some(update) = commitment_update { - pending_msg_events.push(MessageSendEvent::UpdateHTLCs { - node_id: counterparty_node_id, - channel_id: channel.context.channel_id(), - updates: update, - }); - } - } } - macro_rules! handle_raa { () => { - if let Some(revoke_and_ack) = raa { - pending_msg_events.push(MessageSendEvent::SendRevokeAndACK { - node_id: counterparty_node_id, - msg: revoke_and_ack, - }); - } - } } + macro_rules! handle_cs { + () => { + if let Some(update) = commitment_update { + pending_msg_events.push(MessageSendEvent::UpdateHTLCs { + node_id: counterparty_node_id, + channel_id: channel.context.channel_id(), + updates: update, + }); + } + }; + } + macro_rules! handle_raa { + () => { + if let Some(revoke_and_ack) = raa { + pending_msg_events.push(MessageSendEvent::SendRevokeAndACK { + node_id: counterparty_node_id, + msg: revoke_and_ack, + }); + } + }; + } match order { RAACommitmentOrder::CommitmentFirst => { handle_cs!(); @@ -7712,19 +9163,34 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if let Some(tx) = funding_broadcastable { if channel.context.is_manual_broadcast() { - log_info!(logger, "Not broadcasting funding transaction with txid {} as it is manually managed", tx.compute_txid()); + log_info!( + logger, + "Not broadcasting funding transaction with txid {} as it is manually managed", + tx.compute_txid() + ); let mut pending_events = self.pending_events.lock().unwrap(); match channel.funding.get_funding_txo() { Some(funding_txo) => { - emit_funding_tx_broadcast_safe_event!(pending_events, channel, funding_txo.into_bitcoin_outpoint()) + emit_funding_tx_broadcast_safe_event!( + pending_events, + channel, + funding_txo.into_bitcoin_outpoint() + ) }, None => { - debug_assert!(false, "Channel resumed without a funding txo, this should never happen!"); + debug_assert!( + false, + "Channel resumed without a funding txo, this should never happen!" + ); return (htlc_forwards, decode_update_add_htlcs); - } + }, }; } else { - log_info!(logger, "Broadcasting funding transaction with txid {}", tx.compute_txid()); + log_info!( + logger, + "Broadcasting funding transaction with txid {}", + tx.compute_txid() + ); self.tx_broadcaster.broadcast_transactions(&[&tx]); } } @@ -7738,13 +9204,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ (htlc_forwards, decode_update_add_htlcs) } - fn channel_monitor_updated(&self, channel_id: &ChannelId, highest_applied_update_id: u64, counterparty_node_id: &PublicKey) { + fn channel_monitor_updated( + &self, channel_id: &ChannelId, highest_applied_update_id: u64, + counterparty_node_id: &PublicKey, + ) { debug_assert!(self.total_consistency_lock.try_write().is_err()); // Caller holds read lock let per_peer_state = self.per_peer_state.read().unwrap(); let mut peer_state_lock; let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id); - if peer_state_mutex_opt.is_none() { return } + if peer_state_mutex_opt.is_none() { + return; + } peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -7752,30 +9223,46 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if let Some((_, pending)) = peer_state.in_flight_monitor_updates.get_mut(channel_id) { pending.retain(|upd| upd.update_id > highest_applied_update_id); pending.len() - } else { 0 }; + } else { + 0 + }; - let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(*channel_id), None); - log_trace!(logger, "ChannelMonitor updated to {}. {} pending in-flight updates.", - highest_applied_update_id, remaining_in_flight); + let logger = + WithContext::from(&self.logger, Some(*counterparty_node_id), Some(*channel_id), None); + log_trace!( + logger, + "ChannelMonitor updated to {}. {} pending in-flight updates.", + highest_applied_update_id, + remaining_in_flight + ); if remaining_in_flight != 0 { return; } - if let Some(chan) = peer_state.channel_by_id - .get_mut(channel_id) - .and_then(Channel::as_funded_mut) + if let Some(chan) = + peer_state.channel_by_id.get_mut(channel_id).and_then(Channel::as_funded_mut) { if chan.is_awaiting_monitor_update() { log_trace!(logger, "Channel is open and awaiting update, resuming it"); - handle_monitor_update_completion!(self, peer_state_lock, peer_state, per_peer_state, chan); + handle_monitor_update_completion!( + self, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } else { log_trace!(logger, "Channel is open but not awaiting update"); } } else { - let update_actions = peer_state.monitor_update_blocked_actions - .remove(channel_id).unwrap_or(Vec::new()); - log_trace!(logger, "Channel is closed, applying {} post-update actions", update_actions.len()); + let update_actions = + peer_state.monitor_update_blocked_actions.remove(channel_id).unwrap_or(Vec::new()); + log_trace!( + logger, + "Channel is closed, applying {} post-update actions", + update_actions.len() + ); mem::drop(peer_state_lock); mem::drop(per_peer_state); self.handle_monitor_update_completion_actions(update_actions); @@ -7802,8 +9289,17 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ /// /// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest /// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id - pub fn accept_inbound_channel(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, user_channel_id: u128, config_overrides: Option) -> Result<(), APIError> { - self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, false, user_channel_id, config_overrides) + pub fn accept_inbound_channel( + &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, + user_channel_id: u128, config_overrides: Option, + ) -> Result<(), APIError> { + self.do_accept_inbound_channel( + temporary_channel_id, + counterparty_node_id, + false, + user_channel_id, + config_overrides, + ) } /// Accepts a request to open a channel after a [`events::Event::OpenChannelRequest`], treating @@ -7824,16 +9320,25 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ /// /// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest /// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id - pub fn accept_inbound_channel_from_trusted_peer_0conf(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, user_channel_id: u128, config_overrides: Option) -> Result<(), APIError> { - self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, true, user_channel_id, config_overrides) + pub fn accept_inbound_channel_from_trusted_peer_0conf( + &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, + user_channel_id: u128, config_overrides: Option, + ) -> Result<(), APIError> { + self.do_accept_inbound_channel( + temporary_channel_id, + counterparty_node_id, + true, + user_channel_id, + config_overrides, + ) } /// TODO(dual_funding): Allow contributions, pass intended amount and inputs fn do_accept_inbound_channel( - &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, accept_0conf: bool, - user_channel_id: u128, config_overrides: Option + &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, + accept_0conf: bool, user_channel_id: u128, + config_overrides: Option, ) -> Result<(), APIError> { - let mut config = self.default_configuration.clone(); // Apply configuration overrides. @@ -7841,15 +9346,22 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ config.apply(&overrides); }; - let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(*temporary_channel_id), None); + let logger = WithContext::from( + &self.logger, + Some(*counterparty_node_id), + Some(*temporary_channel_id), + None, + ); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let peers_without_funded_channels = - self.peers_without_funded_channels(|peer| { peer.total_channel_count() > 0 }); + self.peers_without_funded_channels(|peer| peer.total_channel_count() > 0); let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - let err_str = format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id); + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + let err_str = format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ); log_error!(logger, "{}", err_str); APIError::ChannelUnavailable { err: err_str } @@ -7866,46 +9378,70 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Some(unaccepted_channel) => { let best_block_height = self.best_block.read().unwrap().height; match unaccepted_channel.open_channel_msg { - OpenChannelMessage::V1(open_channel_msg) => { - InboundV1Channel::new( - &self.fee_estimator, &self.entropy_source, &self.signer_provider, *counterparty_node_id, - &self.channel_type_features(), &peer_state.latest_features, &open_channel_msg, - user_channel_id, &config, best_block_height, &self.logger, accept_0conf - ).map_err(|err| MsgHandleErrInternal::from_chan_no_close(err, *temporary_channel_id) - ).map(|mut channel| { - let logger = WithChannelContext::from(&self.logger, &channel.context, None); - let message_send_event = channel.accept_inbound_channel(&&logger).map(|msg| { + OpenChannelMessage::V1(open_channel_msg) => InboundV1Channel::new( + &self.fee_estimator, + &self.entropy_source, + &self.signer_provider, + *counterparty_node_id, + &self.channel_type_features(), + &peer_state.latest_features, + &open_channel_msg, + user_channel_id, + &config, + best_block_height, + &self.logger, + accept_0conf, + ) + .map_err(|err| { + MsgHandleErrInternal::from_chan_no_close(err, *temporary_channel_id) + }) + .map(|mut channel| { + let logger = WithChannelContext::from(&self.logger, &channel.context, None); + let message_send_event = + channel.accept_inbound_channel(&&logger).map(|msg| { MessageSendEvent::SendAcceptChannel { node_id: *counterparty_node_id, msg, } }); - (*temporary_channel_id, Channel::from(channel), message_send_event) - }) - }, - OpenChannelMessage::V2(open_channel_msg) => { - PendingV2Channel::new_inbound( - &self.fee_estimator, &self.entropy_source, &self.signer_provider, - self.get_our_node_id(), *counterparty_node_id, - &self.channel_type_features(), &peer_state.latest_features, - &open_channel_msg, - user_channel_id, &config, best_block_height, - &self.logger, - ).map_err(|_| MsgHandleErrInternal::from_chan_no_close( - ChannelError::Close( - ( - "V2 channel rejected due to sender error".into(), - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, - ) - ), *temporary_channel_id) - ).map(|channel| { - let message_send_event = MessageSendEvent::SendAcceptChannelV2 { - node_id: channel.context.get_counterparty_node_id(), - msg: channel.accept_inbound_dual_funded_channel() - }; - (channel.context.channel_id(), Channel::from(channel), Some(message_send_event)) - }) - }, + (*temporary_channel_id, Channel::from(channel), message_send_event) + }), + OpenChannelMessage::V2(open_channel_msg) => PendingV2Channel::new_inbound( + &self.fee_estimator, + &self.entropy_source, + &self.signer_provider, + self.get_our_node_id(), + *counterparty_node_id, + &self.channel_type_features(), + &peer_state.latest_features, + &open_channel_msg, + user_channel_id, + &config, + best_block_height, + &self.logger, + ) + .map_err(|_| { + MsgHandleErrInternal::from_chan_no_close( + ChannelError::Close(( + "V2 channel rejected due to sender error".into(), + ClosureReason::HolderForceClosed { + broadcasted_latest_txn: Some(false), + }, + )), + *temporary_channel_id, + ) + }) + .map(|channel| { + let message_send_event = MessageSendEvent::SendAcceptChannelV2 { + node_id: channel.context.get_counterparty_node_id(), + msg: channel.accept_inbound_dual_funded_channel(), + }; + ( + channel.context.channel_id(), + Channel::from(channel), + Some(message_send_event), + ) + }), } }, None => { @@ -7913,7 +9449,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ log_error!(logger, "{}", err_str); return Err(APIError::APIMisuseError { err: err_str }); - } + }, }; // We have to match below instead of map_err on the above as in the map_err closure the borrow checker @@ -7924,13 +9460,19 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ mem::drop(peer_state_lock); mem::drop(per_peer_state); // TODO(dunxen): Find/make less icky way to do this. - match handle_error!(self, Result::<(), MsgHandleErrInternal>::Err(err), *counterparty_node_id) { - Ok(_) => unreachable!("`handle_error` only returns Err as we've passed in an Err"), + match handle_error!( + self, + Result::<(), MsgHandleErrInternal>::Err(err), + *counterparty_node_id + ) { + Ok(_) => { + unreachable!("`handle_error` only returns Err as we've passed in an Err") + }, Err(e) => { return Err(APIError::ChannelUnavailable { err: e.err }); }, } - } + }, }; if accept_0conf { @@ -7939,9 +9481,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } else if channel.funding().get_channel_type().requires_zero_conf() { let send_msg_err_event = MessageSendEvent::HandleError { node_id: channel.context().get_counterparty_node_id(), - action: msgs::ErrorAction::SendErrorMessage{ - msg: msgs::ErrorMessage { channel_id: *temporary_channel_id, data: "No zero confirmation channels accepted".to_owned(), } - } + action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { + channel_id: *temporary_channel_id, + data: "No zero confirmation channels accepted".to_owned(), + }, + }, }; peer_state.pending_msg_events.push(send_msg_err_event); let err_str = "Please use accept_inbound_channel_from_trusted_peer_0conf to accept channels with zero confirmations.".to_owned(); @@ -7955,12 +9500,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if is_only_peer_channel && peers_without_funded_channels >= MAX_UNFUNDED_CHANNEL_PEERS { let send_msg_err_event = MessageSendEvent::HandleError { node_id: channel.context().get_counterparty_node_id(), - action: msgs::ErrorAction::SendErrorMessage{ - msg: msgs::ErrorMessage { channel_id: *temporary_channel_id, data: "Have too many peers with unfunded channels, not accepting new ones".to_owned(), } - } + action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { + channel_id: *temporary_channel_id, + data: + "Have too many peers with unfunded channels, not accepting new ones" + .to_owned(), + }, + }, }; peer_state.pending_msg_events.push(send_msg_err_event); - let err_str = "Too many peers with unfunded channels, refusing to accept new ones".to_owned(); + let err_str = + "Too many peers with unfunded channels, refusing to accept new ones".to_owned(); log_error!(logger, "{}", err_str); return Err(APIError::APIMisuseError { err: err_str }); @@ -7985,14 +9536,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ /// The filter is called for each peer and provided with the number of unfunded, inbound, and /// non-0-conf channels we have with the peer. fn peers_without_funded_channels(&self, maybe_count_peer: Filter) -> usize - where Filter: Fn(&PeerState) -> bool { + where + Filter: Fn(&PeerState) -> bool, + { let mut peers_without_funded_channels = 0; let best_block_height = self.best_block.read().unwrap().height; { let peer_state_lock = self.per_peer_state.read().unwrap(); for (_, peer_mtx) in peer_state_lock.iter() { let peer = peer_mtx.lock().unwrap(); - if !maybe_count_peer(&*peer) { continue; } + if !maybe_count_peer(&*peer) { + continue; + } let num_unfunded_channels = Self::unfunded_channel_count(&peer, best_block_height); if num_unfunded_channels == peer.total_channel_count() { peers_without_funded_channels += 1; @@ -8002,17 +9557,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ return peers_without_funded_channels; } - fn unfunded_channel_count( - peer: &PeerState, best_block_height: u32 - ) -> usize { + fn unfunded_channel_count(peer: &PeerState, best_block_height: u32) -> usize { let mut num_unfunded_channels = 0; for (_, chan) in peer.channel_by_id.iter() { match chan.as_funded() { Some(funded_chan) => { // This covers non-zero-conf inbound `Channel`s that we are currently monitoring, but those // which have not yet had any confirmations on-chain. - if !funded_chan.funding.is_outbound() && funded_chan.context.minimum_depth().unwrap_or(1) != 0 && - funded_chan.context.get_funding_tx_confirmations(best_block_height) == 0 + if !funded_chan.funding.is_outbound() + && funded_chan.context.minimum_depth().unwrap_or(1) != 0 + && funded_chan.context.get_funding_tx_confirmations(best_block_height) == 0 { num_unfunded_channels += 1; } @@ -8042,7 +9596,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ num_unfunded_channels + peer.inbound_channel_request_by_id.len() } - fn internal_open_channel(&self, counterparty_node_id: &PublicKey, msg: OpenChannelMessageRef<'_>) -> Result<(), MsgHandleErrInternal> { + fn internal_open_channel( + &self, counterparty_node_id: &PublicKey, msg: OpenChannelMessageRef<'_>, + ) -> Result<(), MsgHandleErrInternal> { let common_fields = match msg { OpenChannelMessageRef::V1(msg) => &msg.common_fields, OpenChannelMessageRef::V2(msg) => &msg.common_fields, @@ -8053,13 +9609,17 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ // Note that the ChannelManager is NOT re-persisted on disk after this, so any changes are // likely to be lost on restart! if common_fields.chain_hash != self.chain_hash { - return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), - common_fields.temporary_channel_id)); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "Unknown genesis block hash".to_owned(), + common_fields.temporary_channel_id, + )); } if !self.default_configuration.accept_inbound_channels { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), - common_fields.temporary_channel_id)); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No inbound channels accepted".to_owned(), + common_fields.temporary_channel_id, + )); } // Get the number of peers with channels, but without funded ones. We don't care too much @@ -8069,33 +9629,40 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ self.peers_without_funded_channels(|node| node.total_channel_count() > 0); let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close( - format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), - common_fields.temporary_channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + common_fields.temporary_channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; // If this peer already has some channels, a new channel won't increase our number of peers // with unfunded channels, so as long as we aren't over the maximum number of unfunded // channels per-peer we can accept channels from a peer with existing ones. - if peer_state.total_channel_count() == 0 && - channeled_peers_without_funding >= MAX_UNFUNDED_CHANNEL_PEERS && - !self.default_configuration.manually_accept_inbound_channels + if peer_state.total_channel_count() == 0 + && channeled_peers_without_funding >= MAX_UNFUNDED_CHANNEL_PEERS + && !self.default_configuration.manually_accept_inbound_channels { return Err(MsgHandleErrInternal::send_err_msg_no_close( "Have too many peers with unfunded channels, not accepting new ones".to_owned(), - common_fields.temporary_channel_id)); + common_fields.temporary_channel_id, + )); } let best_block_height = self.best_block.read().unwrap().height; - if Self::unfunded_channel_count(peer_state, best_block_height) >= MAX_UNFUNDED_CHANS_PER_PEER { + if Self::unfunded_channel_count(peer_state, best_block_height) + >= MAX_UNFUNDED_CHANS_PER_PEER + { return Err(MsgHandleErrInternal::send_err_msg_no_close( format!("Refusing more than {} unfunded channels.", MAX_UNFUNDED_CHANS_PER_PEER), - common_fields.temporary_channel_id)); + common_fields.temporary_channel_id, + )); } let channel_id = common_fields.temporary_channel_id; @@ -8103,38 +9670,52 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if channel_exists { return Err(MsgHandleErrInternal::send_err_msg_no_close( "temporary_channel_id collision for the same peer!".to_owned(), - common_fields.temporary_channel_id)); + common_fields.temporary_channel_id, + )); } // We can get the channel type at this point already as we'll need it immediately in both the // manual and the automatic acceptance cases. let channel_type = channel::channel_type_from_open_channel( - common_fields, &peer_state.latest_features, &self.channel_type_features() - ).map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, common_fields.temporary_channel_id))?; + common_fields, + &peer_state.latest_features, + &self.channel_type_features(), + ) + .map_err(|e| { + MsgHandleErrInternal::from_chan_no_close(e, common_fields.temporary_channel_id) + })?; // If we're doing manual acceptance checks on the channel, then defer creation until we're sure we want to accept. if self.default_configuration.manually_accept_inbound_channels { let mut pending_events = self.pending_events.lock().unwrap(); let is_announced = (common_fields.channel_flags & 1) == 1; - pending_events.push_back((events::Event::OpenChannelRequest { - temporary_channel_id: common_fields.temporary_channel_id, - counterparty_node_id: *counterparty_node_id, - funding_satoshis: common_fields.funding_satoshis, - channel_negotiation_type: match msg { - OpenChannelMessageRef::V1(msg) => InboundChannelFunds::PushMsat(msg.push_msat), - OpenChannelMessageRef::V2(_) => InboundChannelFunds::DualFunded, + pending_events.push_back(( + events::Event::OpenChannelRequest { + temporary_channel_id: common_fields.temporary_channel_id, + counterparty_node_id: *counterparty_node_id, + funding_satoshis: common_fields.funding_satoshis, + channel_negotiation_type: match msg { + OpenChannelMessageRef::V1(msg) => { + InboundChannelFunds::PushMsat(msg.push_msat) + }, + OpenChannelMessageRef::V2(_) => InboundChannelFunds::DualFunded, + }, + channel_type, + is_announced, + params: common_fields.channel_parameters(), }, - channel_type, - is_announced, - params: common_fields.channel_parameters(), - }, None)); - peer_state.inbound_channel_request_by_id.insert(channel_id, InboundChannelRequest { - open_channel_msg: match msg { - OpenChannelMessageRef::V1(msg) => OpenChannelMessage::V1(msg.clone()), - OpenChannelMessageRef::V2(msg) => OpenChannelMessage::V2(msg.clone()), + None, + )); + peer_state.inbound_channel_request_by_id.insert( + channel_id, + InboundChannelRequest { + open_channel_msg: match msg { + OpenChannelMessageRef::V1(msg) => OpenChannelMessage::V1(msg.clone()), + OpenChannelMessageRef::V2(msg) => OpenChannelMessage::V2(msg.clone()), + }, + ticks_remaining: UNACCEPTED_INBOUND_CHANNEL_AGE_LIMIT_TICKS, }, - ticks_remaining: UNACCEPTED_INBOUND_CHANNEL_AGE_LIMIT_TICKS, - }); + ); return Ok(()); } @@ -8144,35 +9725,67 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let user_channel_id = u128::from_be_bytes(random_bytes); if channel_type.requires_zero_conf() { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No zero confirmation channels accepted".to_owned(), common_fields.temporary_channel_id)); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No zero confirmation channels accepted".to_owned(), + common_fields.temporary_channel_id, + )); } if channel_type.requires_anchors_zero_fee_htlc_tx() { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No channels with anchor outputs accepted".to_owned(), common_fields.temporary_channel_id)); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No channels with anchor outputs accepted".to_owned(), + common_fields.temporary_channel_id, + )); } let (mut channel, message_send_event) = match msg { OpenChannelMessageRef::V1(msg) => { let mut channel = InboundV1Channel::new( - &self.fee_estimator, &self.entropy_source, &self.signer_provider, *counterparty_node_id, - &self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id, - &self.default_configuration, best_block_height, &self.logger, /*is_0conf=*/false - ).map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id))?; + &self.fee_estimator, + &self.entropy_source, + &self.signer_provider, + *counterparty_node_id, + &self.channel_type_features(), + &peer_state.latest_features, + msg, + user_channel_id, + &self.default_configuration, + best_block_height, + &self.logger, + /*is_0conf=*/ false, + ) + .map_err(|e| { + MsgHandleErrInternal::from_chan_no_close( + e, + msg.common_fields.temporary_channel_id, + ) + })?; let logger = WithChannelContext::from(&self.logger, &channel.context, None); let message_send_event = channel.accept_inbound_channel(&&logger).map(|msg| { - MessageSendEvent::SendAcceptChannel { - node_id: *counterparty_node_id, - msg, - } + MessageSendEvent::SendAcceptChannel { node_id: *counterparty_node_id, msg } }); (Channel::from(channel), message_send_event) }, OpenChannelMessageRef::V2(msg) => { let channel = PendingV2Channel::new_inbound( - &self.fee_estimator, &self.entropy_source, &self.signer_provider, - self.get_our_node_id(), *counterparty_node_id, &self.channel_type_features(), - &peer_state.latest_features, msg, user_channel_id, - &self.default_configuration, best_block_height, &self.logger, - ).map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id))?; + &self.fee_estimator, + &self.entropy_source, + &self.signer_provider, + self.get_our_node_id(), + *counterparty_node_id, + &self.channel_type_features(), + &peer_state.latest_features, + msg, + user_channel_id, + &self.default_configuration, + best_block_height, + &self.logger, + ) + .map_err(|e| { + MsgHandleErrInternal::from_chan_no_close( + e, + msg.common_fields.temporary_channel_id, + ) + })?; let message_send_event = MessageSendEvent::SendAcceptChannelV2 { node_id: *counterparty_node_id, msg: channel.accept_inbound_dual_funded_channel(), @@ -8192,16 +9805,23 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_accept_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::AcceptChannel) -> Result<(), MsgHandleErrInternal> { + fn internal_accept_channel( + &self, counterparty_node_id: &PublicKey, msg: &msgs::AcceptChannel, + ) -> Result<(), MsgHandleErrInternal> { // Note that the ChannelManager is NOT re-persisted on disk after this, so any changes are // likely to be lost on restart! let (value, output_script, user_id) = { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.common_fields.temporary_channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.common_fields.temporary_channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.common_fields.temporary_channel_id) { @@ -8220,25 +9840,35 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } }; let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push_back((events::Event::FundingGenerationReady { - temporary_channel_id: msg.common_fields.temporary_channel_id, - counterparty_node_id: *counterparty_node_id, - channel_value_satoshis: value, - output_script, - user_channel_id: user_id, - }, None)); + pending_events.push_back(( + events::Event::FundingGenerationReady { + temporary_channel_id: msg.common_fields.temporary_channel_id, + counterparty_node_id: *counterparty_node_id, + channel_value_satoshis: value, + output_script, + user_channel_id: user_id, + }, + None, + )); Ok(()) } - fn internal_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> { + fn internal_funding_created( + &self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated, + ) -> Result<(), MsgHandleErrInternal> { let best_block = *self.best_block.read().unwrap(); let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.temporary_channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -8272,16 +9902,27 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let funded_channel_id = chan.context.channel_id(); - macro_rules! fail_chan { ($err: expr) => { { - // Note that at this point we've filled in the funding outpoint on our - // channel, but its actually in conflict with another channel. Thus, if - // we call `convert_channel_err` immediately (thus calling - // `locked_close_channel`), we'll remove the existing channel from `outpoint_to_peer`. - // Thus, we must first unset the funding outpoint on the channel. - let err = ChannelError::close($err.to_owned()); - chan.unset_funding_info(); - return Err(convert_channel_err!(self, peer_state, err, chan.context, &chan.funding, &funded_channel_id, UNFUNDED_CHANNEL).1); - } } } + macro_rules! fail_chan { + ($err: expr) => {{ + // Note that at this point we've filled in the funding outpoint on our + // channel, but its actually in conflict with another channel. Thus, if + // we call `convert_channel_err` immediately (thus calling + // `locked_close_channel`), we'll remove the existing channel from `outpoint_to_peer`. + // Thus, we must first unset the funding outpoint on the channel. + let err = ChannelError::close($err.to_owned()); + chan.unset_funding_info(); + return Err(convert_channel_err!( + self, + peer_state, + err, + chan.context, + &chan.funding, + &funded_channel_id, + UNFUNDED_CHANNEL + ) + .1); + }}; + } match peer_state.channel_by_id.entry(funded_channel_id) { hash_map::Entry::Occupied(_) => { @@ -8302,8 +9943,15 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } if let Some(funded_chan) = e.insert(Channel::from(chan)).as_funded_mut() { - handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state, - per_peer_state, funded_chan, INITIAL_MONITOR); + handle_new_monitor_update!( + self, + persist_state, + peer_state_lock, + peer_state, + per_peer_state, + funded_chan, + INITIAL_MONITOR + ); } else { unreachable!("This must be a funded channel as we just inserted it."); } @@ -8313,28 +9961,38 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ log_error!(logger, "Persisting initial ChannelMonitor failed, implying the channel ID was duplicated"); fail_chan!("Duplicate channel ID"); } - } + }, } } - fn internal_peer_storage_retrieval(&self, counterparty_node_id: PublicKey, _msg: msgs::PeerStorageRetrieval) -> Result<(), MsgHandleErrInternal> { + fn internal_peer_storage_retrieval( + &self, counterparty_node_id: PublicKey, _msg: msgs::PeerStorageRetrieval, + ) -> Result<(), MsgHandleErrInternal> { // TODO: Decrypt and check if have any stale or missing ChannelMonitor. let logger = WithContext::from(&self.logger, Some(counterparty_node_id), None, None); log_debug!(logger, "Received unexpected peer_storage_retrieval from {}. This is unusual since we do not yet distribute peer storage. Sending a warning.", log_pubkey!(counterparty_node_id)); - Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn( - "Invalid peer_storage_retrieval message received.".into(), - ), ChannelId([0; 32]))) + Err(MsgHandleErrInternal::from_chan_no_close( + ChannelError::Warn("Invalid peer_storage_retrieval message received.".into()), + ChannelId([0; 32]), + )) } - fn internal_peer_storage(&self, counterparty_node_id: PublicKey, msg: msgs::PeerStorage) -> Result<(), MsgHandleErrInternal> { + fn internal_peer_storage( + &self, counterparty_node_id: PublicKey, msg: msgs::PeerStorage, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(&counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), ChannelId([0; 32])) - })?; + let peer_state_mutex = per_peer_state.get(&counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + ChannelId([0; 32]), + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -8352,9 +10010,13 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if msg.data.len() > MAX_PEER_STORAGE_SIZE { log_debug!(logger, "Sending warning to peer and ignoring peer storage request from {} as its over 1KiB", log_pubkey!(counterparty_node_id)); - return Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn( - format!("Supports only data up to {} bytes in peer storage.", MAX_PEER_STORAGE_SIZE) - ), ChannelId([0; 32]))); + return Err(MsgHandleErrInternal::from_chan_no_close( + ChannelError::Warn(format!( + "Supports only data up to {} bytes in peer storage.", + MAX_PEER_STORAGE_SIZE + )), + ChannelId([0; 32]), + )); } log_trace!(logger, "Received peer_storage from {}", log_pubkey!(counterparty_node_id)); @@ -8363,14 +10025,21 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_funding_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), MsgHandleErrInternal> { + fn internal_funding_signed( + &self, counterparty_node_id: &PublicKey, msg: &msgs::FundingSigned, + ) -> Result<(), MsgHandleErrInternal> { let best_block = *self.best_block.read().unwrap(); let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -8391,30 +10060,48 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ ChannelError::close("Channel ID was a duplicate".to_owned()) }) .map(|persist_status| (funded_chan, persist_status)) - }) - { + }) { Ok((funded_chan, persist_status)) => { - handle_new_monitor_update!(self, persist_status, peer_state_lock, peer_state, per_peer_state, funded_chan, INITIAL_MONITOR); + handle_new_monitor_update!( + self, + persist_status, + peer_state_lock, + peer_state, + per_peer_state, + funded_chan, + INITIAL_MONITOR + ); Ok(()) }, Err(e) => try_channel_entry!(self, peer_state, Err(e), chan_entry), } }, - hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id)) + hash_map::Entry::Vacant(_) => { + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "Failed to find corresponding channel".to_owned(), + msg.channel_id, + )) + }, } } - fn internal_tx_msg) -> Result>( - &self, counterparty_node_id: &PublicKey, channel_id: ChannelId, tx_msg_handler: HandleTxMsgFn + fn internal_tx_msg< + HandleTxMsgFn: Fn(&mut Channel) -> Result, + >( + &self, counterparty_node_id: &PublicKey, channel_id: ChannelId, + tx_msg_handler: HandleTxMsgFn, ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close( - format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), - channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(channel_id) { @@ -8438,7 +10125,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } - fn internal_tx_add_input(&self, counterparty_node_id: PublicKey, msg: &msgs::TxAddInput) -> Result<(), MsgHandleErrInternal> { + fn internal_tx_add_input( + &self, counterparty_node_id: PublicKey, msg: &msgs::TxAddInput, + ) -> Result<(), MsgHandleErrInternal> { self.internal_tx_msg(&counterparty_node_id, msg.channel_id, |channel: &mut Channel| { match channel.as_unfunded_v2_mut() { Some(unfunded_channel) => { @@ -8449,48 +10138,59 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ }) } - fn internal_tx_add_output(&self, counterparty_node_id: PublicKey, msg: &msgs::TxAddOutput) -> Result<(), MsgHandleErrInternal> { + fn internal_tx_add_output( + &self, counterparty_node_id: PublicKey, msg: &msgs::TxAddOutput, + ) -> Result<(), MsgHandleErrInternal> { self.internal_tx_msg(&counterparty_node_id, msg.channel_id, |channel: &mut Channel| { match channel.as_unfunded_v2_mut() { - Some(unfunded_channel) => { - Ok(unfunded_channel.tx_add_output(msg).into_msg_send_event(counterparty_node_id)) - }, + Some(unfunded_channel) => Ok(unfunded_channel + .tx_add_output(msg) + .into_msg_send_event(counterparty_node_id)), None => Err("tx_add_output"), } }) } - fn internal_tx_remove_input(&self, counterparty_node_id: PublicKey, msg: &msgs::TxRemoveInput) -> Result<(), MsgHandleErrInternal> { + fn internal_tx_remove_input( + &self, counterparty_node_id: PublicKey, msg: &msgs::TxRemoveInput, + ) -> Result<(), MsgHandleErrInternal> { self.internal_tx_msg(&counterparty_node_id, msg.channel_id, |channel: &mut Channel| { match channel.as_unfunded_v2_mut() { - Some(unfunded_channel) => { - Ok(unfunded_channel.tx_remove_input(msg).into_msg_send_event(counterparty_node_id)) - }, + Some(unfunded_channel) => Ok(unfunded_channel + .tx_remove_input(msg) + .into_msg_send_event(counterparty_node_id)), None => Err("tx_remove_input"), } }) } - fn internal_tx_remove_output(&self, counterparty_node_id: PublicKey, msg: &msgs::TxRemoveOutput) -> Result<(), MsgHandleErrInternal> { + fn internal_tx_remove_output( + &self, counterparty_node_id: PublicKey, msg: &msgs::TxRemoveOutput, + ) -> Result<(), MsgHandleErrInternal> { self.internal_tx_msg(&counterparty_node_id, msg.channel_id, |channel: &mut Channel| { match channel.as_unfunded_v2_mut() { - Some(unfunded_channel) => { - Ok(unfunded_channel.tx_remove_output(msg).into_msg_send_event(counterparty_node_id)) - }, + Some(unfunded_channel) => Ok(unfunded_channel + .tx_remove_output(msg) + .into_msg_send_event(counterparty_node_id)), None => Err("tx_remove_output"), } }) } - fn internal_tx_complete(&self, counterparty_node_id: PublicKey, msg: &msgs::TxComplete) -> Result<(), MsgHandleErrInternal> { + fn internal_tx_complete( + &self, counterparty_node_id: PublicKey, msg: &msgs::TxComplete, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(&counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close( - format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), - msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(&counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8537,16 +10237,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } - fn internal_tx_signatures(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxSignatures) - -> Result<(), MsgHandleErrInternal> { + fn internal_tx_signatures( + &self, counterparty_node_id: &PublicKey, msg: &msgs::TxSignatures, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close( - format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), - msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8583,16 +10287,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } - fn internal_tx_abort(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxAbort) - -> Result<(), MsgHandleErrInternal> { + fn internal_tx_abort( + &self, counterparty_node_id: &PublicKey, msg: &msgs::TxAbort, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close( - format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), - msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8645,15 +10353,22 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } - fn internal_channel_ready(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReady) -> Result<(), MsgHandleErrInternal> { + fn internal_channel_ready( + &self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReady, + ) -> Result<(), MsgHandleErrInternal> { // Note that the ChannelManager is NOT re-persisted on disk after this (unless we error // closing a channel), so any changes are likely to be lost on restart! let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8700,31 +10415,45 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } - fn internal_shutdown(&self, counterparty_node_id: &PublicKey, msg: &msgs::Shutdown) -> Result<(), MsgHandleErrInternal> { + fn internal_shutdown( + &self, counterparty_node_id: &PublicKey, msg: &msgs::Shutdown, + ) -> Result<(), MsgHandleErrInternal> { let mut dropped_htlcs: Vec<(HTLCSource, PaymentHash)> = Vec::new(); let mut finish_shutdown = None; { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - if let hash_map::Entry::Occupied(mut chan_entry) = peer_state.channel_by_id.entry(msg.channel_id.clone()) { + if let hash_map::Entry::Occupied(mut chan_entry) = + peer_state.channel_by_id.entry(msg.channel_id.clone()) + { match chan_entry.get_mut().as_funded_mut() { Some(chan) => { if !chan.received_shutdown() { - let logger = WithChannelContext::from(&self.logger, &chan.context, None); + let logger = + WithChannelContext::from(&self.logger, &chan.context, None); log_info!(logger, "Received a shutdown message from our counterparty for channel {}{}.", msg.channel_id, if chan.sent_shutdown() { " after we initiated shutdown" } else { "" }); } let funding_txo_opt = chan.funding.get_funding_txo(); - let (shutdown, monitor_update_opt, htlcs) = try_channel_entry!(self, peer_state, - chan.shutdown(&self.signer_provider, &peer_state.latest_features, &msg), chan_entry); + let (shutdown, monitor_update_opt, htlcs) = try_channel_entry!( + self, + peer_state, + chan.shutdown(&self.signer_provider, &peer_state.latest_features, &msg), + chan_entry + ); dropped_htlcs = htlcs; if let Some(msg) = shutdown { @@ -8738,24 +10467,41 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } // Update the monitor with the shutdown script if necessary. if let Some(monitor_update) = monitor_update_opt { - handle_new_monitor_update!(self, funding_txo_opt.unwrap(), monitor_update, - peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo_opt.unwrap(), + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } }, None => { - let logger = WithChannelContext::from(&self.logger, chan_entry.get().context(), None); + let logger = WithChannelContext::from( + &self.logger, + chan_entry.get().context(), + None, + ); log_error!(logger, "Immediately closing unfunded channel {} as peer asked to cooperatively shut it down (which is unnecessary)", &msg.channel_id); - let mut close_res = chan_entry.get_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel); + let mut close_res = chan_entry.get_mut().force_shutdown( + false, + ClosureReason::CounterpartyCoopClosedUnfundedChannel, + ); remove_channel_entry!(self, peer_state, chan_entry, close_res); finish_shutdown = Some(close_res); }, } } else { - return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id)) + return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id)); } } for htlc_source in dropped_htlcs.drain(..) { - let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id.clone()), channel_id: msg.channel_id }; + let receiver = HTLCDestination::NextHopChannel { + node_id: Some(counterparty_node_id.clone()), + channel_id: msg.channel_id, + }; let reason = HTLCFailReason::from_failure_code(LocalHTLCFailureReason::ChannelClosed); self.fail_htlc_backwards_internal(&htlc_source.0, &htlc_source.1, &reason, receiver); } @@ -8766,13 +10512,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_closing_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::ClosingSigned) -> Result<(), MsgHandleErrInternal> { + fn internal_closing_signed( + &self, counterparty_node_id: &PublicKey, msg: &msgs::ClosingSigned, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let (tx, chan_option, shutdown_result) = { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -8811,15 +10564,19 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ }; if let Some(broadcast_tx) = tx { let channel_id = chan_option.as_ref().map(|channel| channel.context().channel_id()); - log_info!(WithContext::from(&self.logger, Some(*counterparty_node_id), channel_id, None), "Broadcasting {}", log_tx!(broadcast_tx)); + log_info!( + WithContext::from(&self.logger, Some(*counterparty_node_id), channel_id, None), + "Broadcasting {}", + log_tx!(broadcast_tx) + ); self.tx_broadcaster.broadcast_transactions(&[&broadcast_tx]); } if let Some(chan) = chan_option.as_ref().and_then(Channel::as_funded) { if let Ok(update) = self.get_channel_update_for_broadcast(chan) { - let mut pending_broadcast_messages = self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + let mut pending_broadcast_messages = + self.pending_broadcast_messages.lock().unwrap(); + pending_broadcast_messages + .push(MessageSendEvent::BroadcastChannelUpdate { msg: update }); } } mem::drop(per_peer_state); @@ -8829,7 +10586,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_update_add_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateAddHTLC) -> Result<(), MsgHandleErrInternal> { + fn internal_update_add_htlc( + &self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateAddHTLC, + ) -> Result<(), MsgHandleErrInternal> { //TODO: BOLT 4 points out a specific attack where a peer may re-send an onion packet and //determine the state of the payment based on our response/if we forward anything/the time //we take to respond. We should take care to avoid allowing such an attack. @@ -8843,11 +10602,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ // closing a channel), so any changes are likely to be lost on restart! let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8864,16 +10628,23 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_update_fulfill_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> { + fn internal_update_fulfill_htlc( + &self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC, + ) -> Result<(), MsgHandleErrInternal> { let funding_txo; let next_user_channel_id; let (htlc_source, forwarded_htlc_value, skimmed_fee_msat) = { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8906,23 +10677,38 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id)) } }; - self.claim_funds_internal(htlc_source, msg.payment_preimage.clone(), - Some(forwarded_htlc_value), skimmed_fee_msat, false, false, *counterparty_node_id, - funding_txo, msg.channel_id, Some(next_user_channel_id), + self.claim_funds_internal( + htlc_source, + msg.payment_preimage.clone(), + Some(forwarded_htlc_value), + skimmed_fee_msat, + false, + false, + *counterparty_node_id, + funding_txo, + msg.channel_id, + Some(next_user_channel_id), ); Ok(()) } - fn internal_update_fail_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), MsgHandleErrInternal> { + fn internal_update_fail_htlc( + &self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC, + ) -> Result<(), MsgHandleErrInternal> { // Note that the ChannelManager is NOT re-persisted on disk after this (unless we error // closing a channel), so any changes are likely to be lost on restart! let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8939,15 +10725,22 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_update_fail_malformed_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), MsgHandleErrInternal> { + fn internal_update_fail_malformed_htlc( + &self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC, + ) -> Result<(), MsgHandleErrInternal> { // Note that the ChannelManager is NOT re-persisted on disk after this (unless we error // closing a channel), so any changes are likely to be lost on restart! let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -8968,14 +10761,21 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } - fn internal_commitment_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(), MsgHandleErrInternal> { + fn internal_commitment_signed( + &self, counterparty_node_id: &PublicKey, msg: &msgs::CommitmentSigned, + ) -> Result<(), MsgHandleErrInternal> { let best_block = *self.best_block.read().unwrap(); let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -9014,13 +10814,21 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } - fn internal_commitment_signed_batch(&self, counterparty_node_id: &PublicKey, channel_id: ChannelId, batch: &BTreeMap) -> Result<(), MsgHandleErrInternal> { + fn internal_commitment_signed_batch( + &self, counterparty_node_id: &PublicKey, channel_id: ChannelId, + batch: &BTreeMap, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(channel_id) { @@ -9052,22 +10860,59 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ push_forward_event &= decode_update_add_htlcs.is_empty(); let scid = update_add_htlcs.0; match decode_update_add_htlcs.entry(scid) { - hash_map::Entry::Occupied(mut e) => { e.get_mut().append(&mut update_add_htlcs.1); }, - hash_map::Entry::Vacant(e) => { e.insert(update_add_htlcs.1); }, + hash_map::Entry::Occupied(mut e) => { + e.get_mut().append(&mut update_add_htlcs.1); + }, + hash_map::Entry::Vacant(e) => { + e.insert(update_add_htlcs.1); + }, + } + if push_forward_event { + self.push_pending_forwards_ev(); } - if push_forward_event { self.push_pending_forwards_ev(); } } #[inline] - fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, Option, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)]) { - let push_forward_event = self.forward_htlcs_without_forward_event(per_source_pending_forwards); - if push_forward_event { self.push_pending_forwards_ev() } + fn forward_htlcs( + &self, + per_source_pending_forwards: &mut [( + u64, + Option, + OutPoint, + ChannelId, + u128, + Vec<(PendingHTLCInfo, u64)>, + )], + ) { + let push_forward_event = + self.forward_htlcs_without_forward_event(per_source_pending_forwards); + if push_forward_event { + self.push_pending_forwards_ev() + } } #[inline] - fn forward_htlcs_without_forward_event(&self, per_source_pending_forwards: &mut [(u64, Option, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)]) -> bool { + fn forward_htlcs_without_forward_event( + &self, + per_source_pending_forwards: &mut [( + u64, + Option, + OutPoint, + ChannelId, + u128, + Vec<(PendingHTLCInfo, u64)>, + )], + ) -> bool { let mut push_forward_event = false; - for &mut (prev_short_channel_id, prev_counterparty_node_id, prev_funding_outpoint, prev_channel_id, prev_user_channel_id, ref mut pending_forwards) in per_source_pending_forwards { + for &mut ( + prev_short_channel_id, + prev_counterparty_node_id, + prev_funding_outpoint, + prev_channel_id, + prev_user_channel_id, + ref mut pending_forwards, + ) in per_source_pending_forwards + { let mut new_intercept_events = VecDeque::new(); let mut failed_intercept_forwards = Vec::new(); if !pending_forwards.is_empty() { @@ -9081,74 +10926,129 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ // Pull this now to avoid introducing a lock order with `forward_htlcs`. let is_our_scid = self.short_to_chan_info.read().unwrap().contains_key(&scid); - let decode_update_add_htlcs_empty = self.decode_update_add_htlcs.lock().unwrap().is_empty(); + let decode_update_add_htlcs_empty = + self.decode_update_add_htlcs.lock().unwrap().is_empty(); let mut forward_htlcs = self.forward_htlcs.lock().unwrap(); let forward_htlcs_empty = forward_htlcs.is_empty(); match forward_htlcs.entry(scid) { hash_map::Entry::Occupied(mut entry) => { entry.get_mut().push(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, prev_counterparty_node_id, prev_funding_outpoint, - prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info + prev_short_channel_id, + prev_counterparty_node_id, + prev_funding_outpoint, + prev_channel_id, + prev_htlc_id, + prev_user_channel_id, + forward_info, })); }, hash_map::Entry::Vacant(entry) => { - if !is_our_scid && forward_info.incoming_amt_msat.is_some() && - fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, scid, &self.chain_hash) - { - let intercept_id = InterceptId(Sha256::hash(&forward_info.incoming_shared_secret).to_byte_array()); - let mut pending_intercepts = self.pending_intercepted_htlcs.lock().unwrap(); + if !is_our_scid + && forward_info.incoming_amt_msat.is_some() + && fake_scid::is_valid_intercept( + &self.fake_scid_rand_bytes, + scid, + &self.chain_hash, + ) { + let intercept_id = InterceptId( + Sha256::hash(&forward_info.incoming_shared_secret) + .to_byte_array(), + ); + let mut pending_intercepts = + self.pending_intercepted_htlcs.lock().unwrap(); match pending_intercepts.entry(intercept_id) { hash_map::Entry::Vacant(entry) => { - new_intercept_events.push_back((events::Event::HTLCIntercepted { - requested_next_hop_scid: scid, - payment_hash: forward_info.payment_hash, - inbound_amount_msat: forward_info.incoming_amt_msat.unwrap(), - expected_outbound_amount_msat: forward_info.outgoing_amt_msat, - intercept_id - }, None)); + new_intercept_events.push_back(( + events::Event::HTLCIntercepted { + requested_next_hop_scid: scid, + payment_hash: forward_info.payment_hash, + inbound_amount_msat: forward_info + .incoming_amt_msat + .unwrap(), + expected_outbound_amount_msat: forward_info + .outgoing_amt_msat, + intercept_id, + }, + None, + )); entry.insert(PendingAddHTLCInfo { - prev_short_channel_id, prev_counterparty_node_id, prev_funding_outpoint, - prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info + prev_short_channel_id, + prev_counterparty_node_id, + prev_funding_outpoint, + prev_channel_id, + prev_htlc_id, + prev_user_channel_id, + forward_info, }); }, hash_map::Entry::Occupied(_) => { - let logger = WithContext::from(&self.logger, None, Some(prev_channel_id), Some(forward_info.payment_hash)); + let logger = WithContext::from( + &self.logger, + None, + Some(prev_channel_id), + Some(forward_info.payment_hash), + ); log_info!(logger, "Failed to forward incoming HTLC: detected duplicate intercepted payment over short channel id {}", scid); - let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: prev_short_channel_id, - user_channel_id: Some(prev_user_channel_id), - counterparty_node_id: prev_counterparty_node_id, - outpoint: prev_funding_outpoint, - channel_id: prev_channel_id, - htlc_id: prev_htlc_id, - incoming_packet_shared_secret: forward_info.incoming_shared_secret, - phantom_shared_secret: None, - blinded_failure: forward_info.routing.blinded_failure(), - cltv_expiry: forward_info.routing.incoming_cltv_expiry(), - }); + let htlc_source = + HTLCSource::PreviousHopData(HTLCPreviousHopData { + short_channel_id: prev_short_channel_id, + user_channel_id: Some(prev_user_channel_id), + counterparty_node_id: prev_counterparty_node_id, + outpoint: prev_funding_outpoint, + channel_id: prev_channel_id, + htlc_id: prev_htlc_id, + incoming_packet_shared_secret: forward_info + .incoming_shared_secret, + phantom_shared_secret: None, + blinded_failure: forward_info + .routing + .blinded_failure(), + cltv_expiry: forward_info + .routing + .incoming_cltv_expiry(), + }); - failed_intercept_forwards.push((htlc_source, forward_info.payment_hash, - HTLCFailReason::from_failure_code(LocalHTLCFailureReason::UnknownNextPeer), - HTLCDestination::InvalidForward { requested_forward_scid: scid }, + failed_intercept_forwards.push(( + htlc_source, + forward_info.payment_hash, + HTLCFailReason::from_failure_code( + LocalHTLCFailureReason::UnknownNextPeer, + ), + HTLCDestination::InvalidForward { + requested_forward_scid: scid, + }, )); - } + }, } } else { // We don't want to generate a PendingHTLCsForwardable event if only intercepted // payments are being processed. - push_forward_event |= forward_htlcs_empty && decode_update_add_htlcs_empty; - entry.insert(vec!(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, prev_counterparty_node_id, prev_funding_outpoint, - prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info - }))); + push_forward_event |= + forward_htlcs_empty && decode_update_add_htlcs_empty; + entry.insert(vec![HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { + prev_short_channel_id, + prev_counterparty_node_id, + prev_funding_outpoint, + prev_channel_id, + prev_htlc_id, + prev_user_channel_id, + forward_info, + })]); } - } + }, } } } - for (htlc_source, payment_hash, failure_reason, destination) in failed_intercept_forwards.drain(..) { - push_forward_event |= self.fail_htlc_backwards_internal_without_forward_event(&htlc_source, &payment_hash, &failure_reason, destination); + for (htlc_source, payment_hash, failure_reason, destination) in + failed_intercept_forwards.drain(..) + { + push_forward_event |= self.fail_htlc_backwards_internal_without_forward_event( + &htlc_source, + &payment_hash, + &failure_reason, + destination, + ); } if !new_intercept_events.is_empty() { @@ -9162,9 +11062,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ fn push_pending_forwards_ev(&self) { let mut pending_events = self.pending_events.lock().unwrap(); let is_processing_events = self.pending_events_processor.load(Ordering::Acquire); - let num_forward_events = pending_events.iter().filter(|(ev, _)| - if let events::Event::PendingHTLCsForwardable { .. } = ev { true } else { false } - ).count(); + let num_forward_events = pending_events + .iter() + .filter(|(ev, _)| { + if let events::Event::PendingHTLCsForwardable { .. } = ev { + true + } else { + false + } + }) + .count(); // We only want to push a PendingHTLCsForwardable event if no others are queued. Processing // events is done in batches and they are not removed until we're done processing each // batch. Since handling a `PendingHTLCsForwardable` event will call back into the @@ -9172,9 +11079,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ // payments will need an additional forwarding event before being claimed to make them look // real by taking more time. if (is_processing_events && num_forward_events <= 1) || num_forward_events < 1 { - pending_events.push_back((Event::PendingHTLCsForwardable { - time_forwardable: Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS), - }, None)); + pending_events.push_back(( + Event::PendingHTLCsForwardable { + time_forwardable: Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS), + }, + None, + )); } } @@ -9182,24 +11092,31 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ /// [`msgs::RevokeAndACK`] should be held for the given channel until some other action /// completes. Note that this needs to happen in the same [`PeerState`] mutex as any release of /// the [`ChannelMonitorUpdate`] in question. - fn raa_monitor_updates_held(&self, - actions_blocking_raa_monitor_updates: &BTreeMap>, - channel_funding_outpoint: OutPoint, channel_id: ChannelId, counterparty_node_id: PublicKey + fn raa_monitor_updates_held( + &self, + actions_blocking_raa_monitor_updates: &BTreeMap< + ChannelId, + Vec, + >, + channel_funding_outpoint: OutPoint, channel_id: ChannelId, counterparty_node_id: PublicKey, ) -> bool { actions_blocking_raa_monitor_updates - .get(&channel_id).map(|v| !v.is_empty()).unwrap_or(false) - || self.pending_events.lock().unwrap().iter().any(|(_, action)| { - action == &Some(EventCompletionAction::ReleaseRAAChannelMonitorUpdate { - channel_funding_outpoint, - channel_id, - counterparty_node_id, + .get(&channel_id) + .map(|v| !v.is_empty()) + .unwrap_or(false) + || self.pending_events.lock().unwrap().iter().any(|(_, action)| { + action + == &Some(EventCompletionAction::ReleaseRAAChannelMonitorUpdate { + channel_funding_outpoint, + channel_id, + counterparty_node_id, + }) }) - }) } #[cfg(any(test, feature = "_test_utils"))] - pub(crate) fn test_raa_monitor_updates_held(&self, - counterparty_node_id: PublicKey, channel_id: ChannelId + pub(crate) fn test_raa_monitor_updates_held( + &self, counterparty_node_id: PublicKey, channel_id: ChannelId, ) -> bool { let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mtx) = per_peer_state.get(&counterparty_node_id) { @@ -9207,21 +11124,35 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let peer_state = &mut *peer_state_lck; if let Some(chan) = peer_state.channel_by_id.get(&channel_id) { - return self.raa_monitor_updates_held(&peer_state.actions_blocking_raa_monitor_updates, - chan.funding().get_funding_txo().unwrap(), channel_id, counterparty_node_id); + return self.raa_monitor_updates_held( + &peer_state.actions_blocking_raa_monitor_updates, + chan.funding().get_funding_txo().unwrap(), + channel_id, + counterparty_node_id, + ); } } false } - fn internal_revoke_and_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::RevokeAndACK) -> Result<(), MsgHandleErrInternal> { + fn internal_revoke_and_ack( + &self, counterparty_node_id: &PublicKey, msg: &msgs::RevokeAndACK, + ) -> Result<(), MsgHandleErrInternal> { let htlcs_to_fail = { let per_peer_state = self.per_peer_state.read().unwrap(); - let mut peer_state_lock = per_peer_state.get(counterparty_node_id) + let mut peer_state_lock = per_peer_state + .get(counterparty_node_id) .ok_or_else(|| { debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - }).map(|mtx| mtx.lock().unwrap())?; + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + }) + .map(|mtx| mtx.lock().unwrap())?; let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { hash_map::Entry::Occupied(mut chan_entry) => { @@ -9254,13 +11185,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_update_fee(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFee) -> Result<(), MsgHandleErrInternal> { + fn internal_update_fee( + &self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFee, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -9278,13 +11216,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(()) } - fn internal_stfu(&self, counterparty_node_id: &PublicKey, msg: &msgs::Stfu) -> Result { + fn internal_stfu( + &self, counterparty_node_id: &PublicKey, msg: &msgs::Stfu, + ) -> Result { let per_peer_state = self.per_peer_state.read().unwrap(); let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { debug_assert!(false); MsgHandleErrInternal::send_err_msg_no_close( - format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), - msg.channel_id + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, ) })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); @@ -9292,7 +11235,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if !self.init_features().supports_quiescence() { return Err(MsgHandleErrInternal::from_chan_no_close( - ChannelError::Warn("Quiescense not supported".to_string()), msg.channel_id + ChannelError::Warn("Quiescense not supported".to_string()), + msg.channel_id, )); } @@ -9330,13 +11274,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Ok(sent_stfu) } - fn internal_announcement_signatures(&self, counterparty_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures) -> Result<(), MsgHandleErrInternal> { + fn internal_announcement_signatures( + &self, counterparty_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -9366,18 +11317,21 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } /// Returns DoPersist if anything changed, otherwise either SkipPersistNoEvents or an Err. - fn internal_channel_update(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelUpdate) -> Result { - let (chan_counterparty_node_id, chan_id) = match self.short_to_chan_info.read().unwrap().get(&msg.contents.short_channel_id) { - Some((cp_id, chan_id)) => (cp_id.clone(), chan_id.clone()), - None => { - // It's not a local channel - return Ok(NotifyOption::SkipPersistNoEvents) - } - }; + fn internal_channel_update( + &self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelUpdate, + ) -> Result { + let (chan_counterparty_node_id, chan_id) = + match self.short_to_chan_info.read().unwrap().get(&msg.contents.short_channel_id) { + Some((cp_id, chan_id)) => (cp_id.clone(), chan_id.clone()), + None => { + // It's not a local channel + return Ok(NotifyOption::SkipPersistNoEvents); + }, + }; let per_peer_state = self.per_peer_state.read().unwrap(); let peer_state_mutex_opt = per_peer_state.get(&chan_counterparty_node_id); if peer_state_mutex_opt.is_none() { - return Ok(NotifyOption::SkipPersistNoEvents) + return Ok(NotifyOption::SkipPersistNoEvents); } let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -9393,14 +11347,25 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id)); } - let were_node_one = self.get_our_node_id().serialize()[..] < chan.context.get_counterparty_node_id().serialize()[..]; + let were_node_one = self.get_our_node_id().serialize()[..] + < chan.context.get_counterparty_node_id().serialize()[..]; let msg_from_node_one = msg.contents.channel_flags & 1 == 0; if were_node_one == msg_from_node_one { return Ok(NotifyOption::SkipPersistNoEvents); } else { let logger = WithChannelContext::from(&self.logger, &chan.context, None); - log_debug!(logger, "Received channel_update {:?} for channel {}.", msg, chan_id); - let did_change = try_channel_entry!(self, peer_state, chan.channel_update(&msg), chan_entry); + log_debug!( + logger, + "Received channel_update {:?} for channel {}.", + msg, + chan_id + ); + let did_change = try_channel_entry!( + self, + peer_state, + chan.channel_update(&msg), + chan_entry + ); // If nothing changed after applying their update, we don't need to bother // persisting. if !did_change { @@ -9408,28 +11373,43 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } } else { - return try_channel_entry!(self, peer_state, Err(ChannelError::close( - "Got a channel_update for an unfunded channel!".into())), chan_entry); + return try_channel_entry!( + self, + peer_state, + Err(ChannelError::close( + "Got a channel_update for an unfunded channel!".into() + )), + chan_entry + ); } }, - hash_map::Entry::Vacant(_) => return Ok(NotifyOption::SkipPersistNoEvents) + hash_map::Entry::Vacant(_) => return Ok(NotifyOption::SkipPersistNoEvents), } Ok(NotifyOption::DoPersist) } - fn internal_channel_reestablish(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReestablish) -> Result { + fn internal_channel_reestablish( + &self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReestablish, + ) -> Result { let need_lnd_workaround = { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close( - format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), - msg.channel_id - ) - })?; - let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id), None); + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; + let logger = WithContext::from( + &self.logger, + Some(*counterparty_node_id), + Some(msg.channel_id), + None, + ); let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.entry(msg.channel_id) { @@ -9439,9 +11419,19 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ // disconnect, so Channel's reestablish will never hand us any holding cell // freed HTLCs to fail backwards. If in the future we no longer drop pending // add-HTLCs on disconnect, we may be handed HTLCs to fail backwards here. - let responses = try_channel_entry!(self, peer_state, chan.channel_reestablish( - msg, &&logger, &self.node_signer, self.chain_hash, - &self.default_configuration, &*self.best_block.read().unwrap()), chan_entry); + let responses = try_channel_entry!( + self, + peer_state, + chan.channel_reestablish( + msg, + &&logger, + &self.node_signer, + self.chain_hash, + &self.default_configuration, + &*self.best_block.read().unwrap() + ), + chan_entry + ); let mut channel_update = None; if let Some(msg) = responses.shutdown_msg { peer_state.pending_msg_events.push(MessageSendEvent::SendShutdown { @@ -9460,9 +11450,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } } let need_lnd_workaround = chan.context.workaround_lnd_bug_4006.take(); - let (htlc_forwards, decode_update_add_htlcs) = self.handle_channel_resumption( - &mut peer_state.pending_msg_events, chan, responses.raa, responses.commitment_update, responses.order, - Vec::new(), Vec::new(), None, responses.channel_ready, responses.announcement_sigs, None); + let (htlc_forwards, decode_update_add_htlcs) = self + .handle_channel_resumption( + &mut peer_state.pending_msg_events, + chan, + responses.raa, + responses.commitment_update, + responses.order, + Vec::new(), + Vec::new(), + None, + responses.channel_ready, + responses.announcement_sigs, + None, + ); debug_assert!(htlc_forwards.is_none()); debug_assert!(decode_update_add_htlcs.is_none()); if let Some(upd) = channel_update { @@ -9470,8 +11471,14 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } need_lnd_workaround } else { - return try_channel_entry!(self, peer_state, Err(ChannelError::close( - "Got a channel_reestablish message for an unfunded channel!".into())), chan_entry); + return try_channel_entry!( + self, + peer_state, + Err(ChannelError::close( + "Got a channel_reestablish message for an unfunded channel!".into() + )), + chan_entry + ); } }, hash_map::Entry::Vacant(_) => { @@ -9498,15 +11505,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ next_local_commitment_number: 0, next_remote_commitment_number: 0, your_last_per_commitment_secret: [1u8; 32], - my_current_per_commitment_point: PublicKey::from_slice(&[2u8; 33]).unwrap(), + my_current_per_commitment_point: PublicKey::from_slice(&[2u8; 33]) + .unwrap(), next_funding_txid: None, }, }); return Err(MsgHandleErrInternal::send_err_msg_no_close( format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id) - ) - } + ); + }, } }; @@ -9518,13 +11526,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ /// Handle incoming splice request, transition channel to splice-pending (unless some check fails). #[cfg(splicing)] - fn internal_splice_init(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceInit) -> Result<(), MsgHandleErrInternal> { + fn internal_splice_init( + &self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceInit, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -9557,13 +11572,20 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ /// Handle incoming splice request ack, transition channel to splice-pending (unless some check fails). #[cfg(splicing)] - fn internal_splice_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceAck) -> Result<(), MsgHandleErrInternal> { + fn internal_splice_ack( + &self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceAck, + ) -> Result<(), MsgHandleErrInternal> { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| { - debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + debug_assert!(false); + MsgHandleErrInternal::send_err_msg_no_close( + format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + msg.channel_id, + ) + })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -9588,7 +11610,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ // Start splice funding transaction negotiation // etc. - Err(MsgHandleErrInternal::send_err_msg_no_close("TODO(splicing): Splicing is not implemented (splice_ack)".to_owned(), msg.channel_id)) + Err(MsgHandleErrInternal::send_err_msg_no_close( + "TODO(splicing): Splicing is not implemented (splice_ack)".to_owned(), + msg.channel_id, + )) } /// Process pending events from the [`chain::Watch`], returning whether any events were processed. @@ -9598,55 +11623,105 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let mut failed_channels = Vec::new(); let mut pending_monitor_events = self.chain_monitor.release_pending_monitor_events(); let has_pending_monitor_events = !pending_monitor_events.is_empty(); - for (funding_outpoint, channel_id, mut monitor_events, counterparty_node_id) in pending_monitor_events.drain(..) { + for (funding_outpoint, channel_id, mut monitor_events, counterparty_node_id) in + pending_monitor_events.drain(..) + { for monitor_event in monitor_events.drain(..) { match monitor_event { MonitorEvent::HTLCEvent(htlc_update) => { - let logger = WithContext::from(&self.logger, Some(counterparty_node_id), Some(channel_id), Some(htlc_update.payment_hash)); + let logger = WithContext::from( + &self.logger, + Some(counterparty_node_id), + Some(channel_id), + Some(htlc_update.payment_hash), + ); if let Some(preimage) = htlc_update.payment_preimage { - log_trace!(logger, "Claiming HTLC with preimage {} from our monitor", preimage); + log_trace!( + logger, + "Claiming HTLC with preimage {} from our monitor", + preimage + ); self.claim_funds_internal( - htlc_update.source, preimage, - htlc_update.htlc_value_satoshis.map(|v| v * 1000), None, true, - false, counterparty_node_id, funding_outpoint, channel_id, None, + htlc_update.source, + preimage, + htlc_update.htlc_value_satoshis.map(|v| v * 1000), + None, + true, + false, + counterparty_node_id, + funding_outpoint, + channel_id, + None, ); } else { - log_trace!(logger, "Failing HTLC with hash {} from our monitor", &htlc_update.payment_hash); + log_trace!( + logger, + "Failing HTLC with hash {} from our monitor", + &htlc_update.payment_hash + ); let failure_reason = LocalHTLCFailureReason::OnChainTimeout; - let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id }; + let receiver = HTLCDestination::NextHopChannel { + node_id: Some(counterparty_node_id), + channel_id, + }; let reason = HTLCFailReason::from_failure_code(failure_reason); - self.fail_htlc_backwards_internal(&htlc_update.source, &htlc_update.payment_hash, &reason, receiver); + self.fail_htlc_backwards_internal( + &htlc_update.source, + &htlc_update.payment_hash, + &reason, + receiver, + ); } }, - MonitorEvent::HolderForceClosed(_) | MonitorEvent::HolderForceClosedWithInfo { .. } => { + MonitorEvent::HolderForceClosed(_) + | MonitorEvent::HolderForceClosedWithInfo { .. } => { let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; let pending_msg_events = &mut peer_state.pending_msg_events; - if let hash_map::Entry::Occupied(mut chan_entry) = peer_state.channel_by_id.entry(channel_id) { - let reason = if let MonitorEvent::HolderForceClosedWithInfo { reason, .. } = monitor_event { + if let hash_map::Entry::Occupied(mut chan_entry) = + peer_state.channel_by_id.entry(channel_id) + { + let reason = if let MonitorEvent::HolderForceClosedWithInfo { + reason, + .. + } = monitor_event + { reason } else { - ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) } + ClosureReason::HolderForceClosed { + broadcasted_latest_txn: Some(true), + } }; - let mut shutdown_res = chan_entry.get_mut().force_shutdown(false, reason.clone()); - let chan = remove_channel_entry!(self, peer_state, chan_entry, shutdown_res); + let mut shutdown_res = + chan_entry.get_mut().force_shutdown(false, reason.clone()); + let chan = remove_channel_entry!( + self, + peer_state, + chan_entry, + shutdown_res + ); failed_channels.push(shutdown_res); if let Some(funded_chan) = chan.as_funded() { - if let Ok(update) = self.get_channel_update_for_broadcast(funded_chan) { - let mut pending_broadcast_messages = self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + if let Ok(update) = + self.get_channel_update_for_broadcast(funded_chan) + { + let mut pending_broadcast_messages = + self.pending_broadcast_messages.lock().unwrap(); + pending_broadcast_messages.push( + MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } pending_msg_events.push(MessageSendEvent::HandleError { node_id: counterparty_node_id, action: msgs::ErrorAction::DisconnectPeer { msg: Some(msgs::ErrorMessage { channel_id: funded_chan.context.channel_id(), - data: reason.to_string() - }) + data: reason.to_string(), + }), }, }); } @@ -9654,7 +11729,11 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } }, MonitorEvent::Completed { channel_id, monitor_update_id, .. } => { - self.channel_monitor_updated(&channel_id, monitor_update_id, &counterparty_node_id); + self.channel_monitor_updated( + &channel_id, + monitor_update_id, + &counterparty_node_id, + ); }, } } @@ -9693,22 +11772,36 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ 'chan_loop: loop { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state: &mut PeerState<_> = &mut *peer_state_lock; - for (channel_id, chan) in peer_state.channel_by_id - .iter_mut() - .filter_map(|(chan_id, chan)| chan.as_funded_mut().map(|chan| (chan_id, chan))) - { + for (channel_id, chan) in + peer_state.channel_by_id.iter_mut().filter_map(|(chan_id, chan)| { + chan.as_funded_mut().map(|chan| (chan_id, chan)) + }) { let counterparty_node_id = chan.context.get_counterparty_node_id(); let funding_txo = chan.funding.get_funding_txo(); - let (monitor_opt, holding_cell_failed_htlcs) = - chan.maybe_free_holding_cell_htlcs(&self.fee_estimator, &&WithChannelContext::from(&self.logger, &chan.context, None)); + let (monitor_opt, holding_cell_failed_htlcs) = chan + .maybe_free_holding_cell_htlcs( + &self.fee_estimator, + &&WithChannelContext::from(&self.logger, &chan.context, None), + ); if !holding_cell_failed_htlcs.is_empty() { - failed_htlcs.push((holding_cell_failed_htlcs, *channel_id, counterparty_node_id)); + failed_htlcs.push(( + holding_cell_failed_htlcs, + *channel_id, + counterparty_node_id, + )); } if let Some(monitor_update) = monitor_opt { has_monitor_update = true; - handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, - peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo.unwrap(), + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); continue 'peer_loop; } } @@ -9737,43 +11830,37 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); // Returns whether we should remove this channel as it's just been closed. - let unblock_chan = |chan: &mut Channel, pending_msg_events: &mut Vec| -> Option { + let unblock_chan = |chan: &mut Channel, + pending_msg_events: &mut Vec| + -> Option { let logger = WithChannelContext::from(&self.logger, &chan.context(), None); let node_id = chan.context().get_counterparty_node_id(); if let Some(msgs) = chan.signer_maybe_unblocked(self.chain_hash, &&logger) { if let Some(msg) = msgs.open_channel { - pending_msg_events.push(MessageSendEvent::SendOpenChannel { - node_id, - msg, - }); + pending_msg_events.push(MessageSendEvent::SendOpenChannel { node_id, msg }); } if let Some(msg) = msgs.funding_created { - pending_msg_events.push(MessageSendEvent::SendFundingCreated { - node_id, - msg, - }); + pending_msg_events.push(MessageSendEvent::SendFundingCreated { node_id, msg }); } if let Some(msg) = msgs.accept_channel { - pending_msg_events.push(MessageSendEvent::SendAcceptChannel { - node_id, - msg, - }); + pending_msg_events.push(MessageSendEvent::SendAcceptChannel { node_id, msg }); } let cu_msg = msgs.commitment_update.map(|updates| MessageSendEvent::UpdateHTLCs { node_id, channel_id: chan.context().channel_id(), updates, }); - let raa_msg = msgs.revoke_and_ack.map(|msg| MessageSendEvent::SendRevokeAndACK { - node_id, - msg, - }); + let raa_msg = msgs + .revoke_and_ack + .map(|msg| MessageSendEvent::SendRevokeAndACK { node_id, msg }); match (cu_msg, raa_msg) { (Some(cu), Some(raa)) if msgs.order == RAACommitmentOrder::CommitmentFirst => { pending_msg_events.push(cu); pending_msg_events.push(raa); }, - (Some(cu), Some(raa)) if msgs.order == RAACommitmentOrder::RevokeAndACKFirst => { + (Some(cu), Some(raa)) + if msgs.order == RAACommitmentOrder::RevokeAndACKFirst => + { pending_msg_events.push(raa); pending_msg_events.push(cu); }, @@ -9782,16 +11869,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ (_, _) => {}, } if let Some(msg) = msgs.funding_signed { - pending_msg_events.push(MessageSendEvent::SendFundingSigned { - node_id, - msg, - }); + pending_msg_events.push(MessageSendEvent::SendFundingSigned { node_id, msg }); } if let Some(msg) = msgs.closing_signed { - pending_msg_events.push(MessageSendEvent::SendClosingSigned { - node_id, - msg, - }); + pending_msg_events.push(MessageSendEvent::SendClosingSigned { node_id, msg }); } if let Some(funded_chan) = chan.as_funded() { if let Some(msg) = msgs.channel_ready { @@ -9802,9 +11883,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ self.tx_broadcaster.broadcast_transactions(&[&broadcast_tx]); if let Ok(update) = self.get_channel_update_for_broadcast(&funded_chan) { - pending_msg_events.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + pending_msg_events + .push(MessageSendEvent::BroadcastChannelUpdate { msg: update }); } } } else { @@ -9824,7 +11904,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let per_peer_state_iter = per_peer_state.iter().filter(|(cp_id, _)| { if let Some((counterparty_node_id, _)) = channel_opt { **cp_id == counterparty_node_id - } else { true } + } else { + true + } }); for (_cp_id, peer_state_mutex) in per_peer_state_iter { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); @@ -9837,7 +11919,11 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if let Some(mut shutdown_result) = shutdown_result { let context = &chan.context(); let logger = WithChannelContext::from(&self.logger, context, None); - log_trace!(logger, "Removing channel {} now that the signer is unblocked", context.channel_id()); + log_trace!( + logger, + "Removing channel {} now that the signer is unblocked", + context.channel_id() + ); locked_close_channel!(self, peer_state, context, shutdown_result); shutdown_results.push(shutdown_result); false @@ -9869,41 +11955,74 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ peer_state.channel_by_id.retain(|channel_id, chan| { match chan.as_funded_mut() { Some(funded_chan) => { - let logger = WithChannelContext::from(&self.logger, &funded_chan.context, None); - match funded_chan.maybe_propose_closing_signed(&self.fee_estimator, &&logger) { + let logger = + WithChannelContext::from(&self.logger, &funded_chan.context, None); + match funded_chan + .maybe_propose_closing_signed(&self.fee_estimator, &&logger) + { Ok((msg_opt, tx_opt, shutdown_result_opt)) => { if let Some(msg) = msg_opt { has_update = true; - pending_msg_events.push(MessageSendEvent::SendClosingSigned { - node_id: funded_chan.context.get_counterparty_node_id(), msg, - }); + pending_msg_events.push( + MessageSendEvent::SendClosingSigned { + node_id: funded_chan + .context + .get_counterparty_node_id(), + msg, + }, + ); } - debug_assert_eq!(shutdown_result_opt.is_some(), funded_chan.is_shutdown()); + debug_assert_eq!( + shutdown_result_opt.is_some(), + funded_chan.is_shutdown() + ); if let Some(mut shutdown_result) = shutdown_result_opt { - locked_close_channel!(self, peer_state, &funded_chan.context, shutdown_result); + locked_close_channel!( + self, + peer_state, + &funded_chan.context, + shutdown_result + ); shutdown_results.push(shutdown_result); } if let Some(tx) = tx_opt { // We're done with this channel. We got a closing_signed and sent back // a closing_signed with a closing transaction to broadcast. - if let Ok(update) = self.get_channel_update_for_broadcast(&funded_chan) { - let mut pending_broadcast_messages = self.pending_broadcast_messages.lock().unwrap(); - pending_broadcast_messages.push(MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + if let Ok(update) = + self.get_channel_update_for_broadcast(&funded_chan) + { + let mut pending_broadcast_messages = + self.pending_broadcast_messages.lock().unwrap(); + pending_broadcast_messages.push( + MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } log_info!(logger, "Broadcasting {}", log_tx!(tx)); self.tx_broadcaster.broadcast_transactions(&[&tx]); false - } else { true } + } else { + true + } }, Err(e) => { has_update = true; - let (close_channel, res) = convert_channel_err!(self, peer_state, e, funded_chan, channel_id, FUNDED_CHANNEL); - handle_errors.push((funded_chan.context.get_counterparty_node_id(), Err(res))); + let (close_channel, res) = convert_channel_err!( + self, + peer_state, + e, + funded_chan, + channel_id, + FUNDED_CHANNEL + ); + handle_errors.push(( + funded_chan.context.get_counterparty_node_id(), + Err(res), + )); !close_channel - } + }, } }, None => true, // Retain unfunded channels if present. @@ -9932,7 +12051,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ for (channel_id, chan) in &mut peer_state.channel_by_id { if let Some(funded_chan) = chan.as_funded_mut() { let logger = WithContext::from( - &self.logger, Some(*counterparty_node_id), Some(*channel_id), None + &self.logger, + Some(*counterparty_node_id), + Some(*channel_id), + None, ); match funded_chan.try_send_stfu(&&logger) { Ok(None) => {}, @@ -9944,7 +12066,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ }, Err(e) => { log_debug!(logger, "Could not advance quiescence handshake: {}", e); - } + }, } } } @@ -9952,7 +12074,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } #[cfg(any(test, fuzzing))] - pub fn maybe_propose_quiescence(&self, counterparty_node_id: &PublicKey, channel_id: &ChannelId) -> Result<(), APIError> { + pub fn maybe_propose_quiescence( + &self, counterparty_node_id: &PublicKey, channel_id: &ChannelId, + ) -> Result<(), APIError> { let mut result = Ok(()); PersistenceNotifierGuard::optionally_notify(self, || { let mut notify = NotifyOption::SkipPersistNoEvents; @@ -9961,14 +12085,19 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id); if peer_state_mutex_opt.is_none() { result = Err(APIError::ChannelUnavailable { - err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), }); return notify; } let mut peer_state = peer_state_mutex_opt.unwrap().lock().unwrap(); if !peer_state.latest_features.supports_quiescence() { - result = Err(APIError::ChannelUnavailable { err: "Peer does not support quiescence".to_owned() }); + result = Err(APIError::ChannelUnavailable { + err: "Peer does not support quiescence".to_owned(), + }); return notify; } @@ -9976,14 +12105,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ hash_map::Entry::Occupied(mut chan_entry) => { if let Some(chan) = chan_entry.get_mut().as_funded_mut() { let logger = WithContext::from( - &self.logger, Some(*counterparty_node_id), Some(*channel_id), None + &self.logger, + Some(*counterparty_node_id), + Some(*channel_id), + None, ); match chan.propose_quiescence(&&logger) { Ok(None) => {}, Ok(Some(stfu)) => { peer_state.pending_msg_events.push(MessageSendEvent::SendStfu { - node_id: *counterparty_node_id, msg: stfu + node_id: *counterparty_node_id, + msg: stfu, }); notify = NotifyOption::SkipPersistHandleEvents; }, @@ -9997,8 +12130,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ }, hash_map::Entry::Vacant(_) => { result = Err(APIError::ChannelUnavailable { - err: format!("Channel with id {} not found for the passed counterparty node_id {}", - channel_id, counterparty_node_id), + err: format!( + "Channel with id {} not found for the passed counterparty node_id {}", + channel_id, counterparty_node_id + ), }); }, } @@ -10010,12 +12145,18 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } #[cfg(any(test, fuzzing))] - pub fn exit_quiescence(&self, counterparty_node_id: &PublicKey, channel_id: &ChannelId) -> Result { + pub fn exit_quiescence( + &self, counterparty_node_id: &PublicKey, channel_id: &ChannelId, + ) -> Result { let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex = per_peer_state.get(counterparty_node_id) - .ok_or_else(|| APIError::ChannelUnavailable { - err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) - })?; + let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| { + APIError::ChannelUnavailable { + err: format!( + "Can't find a peer matching the passed counterparty node_id {}", + counterparty_node_id + ), + } + })?; let mut peer_state = peer_state_mutex.lock().unwrap(); let initiator = match peer_state.channel_by_id.entry(*channel_id) { hash_map::Entry::Occupied(mut chan_entry) => { @@ -10024,13 +12165,17 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } else { return Err(APIError::APIMisuseError { err: format!("Unfunded channel {} cannot be quiescent", channel_id), - }) + }); } }, - hash_map::Entry::Vacant(_) => return Err(APIError::ChannelUnavailable { - err: format!("Channel with id {} not found for the passed counterparty node_id {}", - channel_id, counterparty_node_id), - }), + hash_map::Entry::Vacant(_) => { + return Err(APIError::ChannelUnavailable { + err: format!( + "Channel with id {} not found for the passed counterparty node_id {}", + channel_id, counterparty_node_id + ), + }) + }, }; Ok(initiator) } @@ -10043,7 +12188,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ &self, params: Bolt11InvoiceParameters, ) -> Result> { let Bolt11InvoiceParameters { - amount_msats, description, invoice_expiry_delta_secs, min_final_cltv_expiry_delta, + amount_msats, + description, + invoice_expiry_delta_secs, + min_final_cltv_expiry_delta, payment_hash, } = params; @@ -10053,7 +12201,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ #[cfg(feature = "std")] let duration_since_epoch = { use std::time::SystemTime; - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) .expect("SystemTime::now() should be after SystemTime::UNIX_EPOCH") }; @@ -10066,7 +12215,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta { if min_final_cltv_expiry_delta.saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA { - return Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort)); + return Err(SignOrCreationError::CreationError( + CreationError::MinFinalCltvExpiryDeltaTooShort, + )); } } @@ -10074,28 +12225,32 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ Some(payment_hash) => { let payment_secret = self .create_inbound_payment_for_hash( - payment_hash, amount_msats, + payment_hash, + amount_msats, invoice_expiry_delta_secs.unwrap_or(DEFAULT_EXPIRY_TIME as u32), min_final_cltv_expiry_delta, ) - .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?; + .map_err(|()| { + SignOrCreationError::CreationError(CreationError::InvalidAmount) + })?; (payment_hash, payment_secret) }, - None => { - self - .create_inbound_payment( - amount_msats, invoice_expiry_delta_secs.unwrap_or(DEFAULT_EXPIRY_TIME as u32), - min_final_cltv_expiry_delta, - ) - .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))? - }, + None => self + .create_inbound_payment( + amount_msats, + invoice_expiry_delta_secs.unwrap_or(DEFAULT_EXPIRY_TIME as u32), + min_final_cltv_expiry_delta, + ) + .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?, }; log_trace!(self.logger, "Creating invoice with payment hash {}", &payment_hash); let invoice = Bolt11InvoiceBuilder::new(currency); let invoice = match description { - Bolt11InvoiceDescription::Direct(description) => invoice.description(description.into_inner().0), + Bolt11InvoiceDescription::Direct(description) => { + invoice.description(description.into_inner().0) + }, Bolt11InvoiceDescription::Hash(hash) => invoice.description_hash(hash.0), }; @@ -10107,10 +12262,13 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ .basic_mpp() .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(), ); - if let Some(invoice_expiry_delta_secs) = invoice_expiry_delta_secs{ + if let Some(invoice_expiry_delta_secs) = invoice_expiry_delta_secs { invoice = invoice.expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into())); } @@ -10119,7 +12277,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } let channels = self.list_channels(); - let route_hints = super::invoice_utils::sort_and_filter_channels(channels, amount_msats, &self.logger); + let route_hints = + super::invoice_utils::sort_and_filter_channels(channels, amount_msats, &self.logger); for hint in route_hints { invoice = invoice.private_route(hint); } @@ -10319,7 +12478,17 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { /// even if multiple invoices are received. const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10; -impl ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -10351,10 +12520,10 @@ where /// aforementioned always-online node. #[cfg(async_payments)] pub fn create_async_receive_offer_builder( - &self, message_paths_to_always_online_node: Vec + &self, message_paths_to_always_online_node: Vec, ) -> Result<(OfferBuilder, Nonce), Bolt12SemanticError> { if message_paths_to_always_online_node.is_empty() { - return Err(Bolt12SemanticError::MissingPaths) + return Err(Bolt12SemanticError::MissingPaths); } let node_id = self.get_our_node_id(); @@ -10363,9 +12532,9 @@ where let secp_ctx = &self.secp_ctx; let nonce = Nonce::from_entropy_source(entropy); - let mut builder = OfferBuilder::deriving_signing_pubkey( - node_id, expanded_key, nonce, secp_ctx - ).chain_hash(self.chain_hash); + let mut builder = + OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx) + .chain_hash(self.chain_hash); for path in message_paths_to_always_online_node { builder = builder.path(path); @@ -10379,20 +12548,17 @@ where /// invoice's expiry will default to [`STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY`]. #[cfg(async_payments)] pub fn create_static_invoice_builder<'a>( - &self, offer: &'a Offer, offer_nonce: Nonce, relative_expiry: Option + &self, offer: &'a Offer, offer_nonce: Nonce, relative_expiry: Option, ) -> Result, Bolt12SemanticError> { let expanded_key = &self.inbound_payment_key; let entropy = &*self.entropy_source; let secp_ctx = &self.secp_ctx; - let payment_context = PaymentContext::AsyncBolt12Offer( - AsyncBolt12OfferContext { offer_nonce } - ); - let amount_msat = offer.amount().and_then(|amount| { - match amount { - Amount::Bitcoin { amount_msats } => Some(amount_msats), - Amount::Currency { .. } => None - } + let payment_context = + PaymentContext::AsyncBolt12Offer(AsyncBolt12OfferContext { offer_nonce }); + let amount_msat = offer.amount().and_then(|amount| match amount { + Amount::Bitcoin { amount_msats } => Some(amount_msats), + Amount::Currency { .. } => None, }); let relative_expiry = relative_expiry.unwrap_or(STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY); @@ -10400,28 +12566,47 @@ where let created_at = self.duration_since_epoch(); let payment_secret = inbound_payment::create_for_spontaneous_payment( - &self.inbound_payment_key, amount_msat, relative_expiry_secs, created_at.as_secs(), None - ).map_err(|()| Bolt12SemanticError::InvalidAmount)?; - - let payment_paths = self.create_blinded_payment_paths( - amount_msat, payment_secret, payment_context, relative_expiry_secs - ).map_err(|()| Bolt12SemanticError::MissingPaths)?; + &self.inbound_payment_key, + amount_msat, + relative_expiry_secs, + created_at.as_secs(), + None, + ) + .map_err(|()| Bolt12SemanticError::InvalidAmount)?; + + let payment_paths = self + .create_blinded_payment_paths( + amount_msat, + payment_secret, + payment_context, + relative_expiry_secs, + ) + .map_err(|()| Bolt12SemanticError::MissingPaths)?; let nonce = Nonce::from_entropy_source(entropy); let hmac = signer::hmac_for_held_htlc_available_context(nonce, expanded_key); - let path_absolute_expiry = Duration::from_secs( - inbound_payment::calculate_absolute_expiry(created_at.as_secs(), relative_expiry_secs) - ); - let context = MessageContext::AsyncPayments( - AsyncPaymentsContext::InboundPayment { nonce, hmac, path_absolute_expiry } - ); - let async_receive_message_paths = self.create_blinded_paths(context) - .map_err(|()| Bolt12SemanticError::MissingPaths)?; + let path_absolute_expiry = Duration::from_secs(inbound_payment::calculate_absolute_expiry( + created_at.as_secs(), + relative_expiry_secs, + )); + let context = MessageContext::AsyncPayments(AsyncPaymentsContext::InboundPayment { + nonce, + hmac, + path_absolute_expiry, + }); + let async_receive_message_paths = + self.create_blinded_paths(context).map_err(|()| Bolt12SemanticError::MissingPaths)?; StaticInvoiceBuilder::for_offer_using_derived_keys( - offer, payment_paths, async_receive_message_paths, created_at, expanded_key, - offer_nonce, secp_ctx - ).map(|inv| inv.allow_mpp().relative_expiry(relative_expiry_secs)) + offer, + payment_paths, + async_receive_message_paths, + created_at, + expanded_key, + offer_nonce, + secp_ctx, + ) + .map(|inv| inv.allow_mpp().relative_expiry(relative_expiry_secs)) } /// Pays for an [`Offer`] using the given parameters by creating an [`InvoiceRequest`] and @@ -10480,25 +12665,38 @@ where pub fn pay_for_offer( &self, offer: &Offer, quantity: Option, amount_msats: Option, payer_note: Option, payment_id: PaymentId, retry_strategy: Retry, - route_params_config: RouteParametersConfig + route_params_config: RouteParametersConfig, ) -> Result<(), Bolt12SemanticError> { - self.pay_for_offer_intern(offer, quantity, amount_msats, payer_note, payment_id, None, |invoice_request, nonce| { - let expiration = StaleExpiration::TimerTicks(1); - let retryable_invoice_request = RetryableInvoiceRequest { - invoice_request: invoice_request.clone(), - nonce, - needs_retry: true, - }; - self.pending_outbound_payments - .add_new_awaiting_invoice( - payment_id, expiration, retry_strategy, route_params_config, - Some(retryable_invoice_request) - ) - .map_err(|_| Bolt12SemanticError::DuplicatePaymentId) - }) + self.pay_for_offer_intern( + offer, + quantity, + amount_msats, + payer_note, + payment_id, + None, + |invoice_request, nonce| { + let expiration = StaleExpiration::TimerTicks(1); + let retryable_invoice_request = RetryableInvoiceRequest { + invoice_request: invoice_request.clone(), + nonce, + needs_retry: true, + }; + self.pending_outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + retry_strategy, + route_params_config, + Some(retryable_invoice_request), + ) + .map_err(|_| Bolt12SemanticError::DuplicatePaymentId) + }, + ) } - fn pay_for_offer_intern Result<(), Bolt12SemanticError>>( + fn pay_for_offer_intern< + CPP: FnOnce(&InvoiceRequest, Nonce) -> Result<(), Bolt12SemanticError>, + >( &self, offer: &Offer, quantity: Option, amount_msats: Option, payer_note: Option, payment_id: PaymentId, human_readable_name: Option, create_pending_payment: CPP, @@ -10508,9 +12706,8 @@ where let secp_ctx = &self.secp_ctx; let nonce = Nonce::from_entropy_source(entropy); - let builder: InvoiceRequestBuilder = offer - .request_invoice(expanded_key, nonce, secp_ctx, payment_id)? - .into(); + let builder: InvoiceRequestBuilder = + offer.request_invoice(expanded_key, nonce, secp_ctx, payment_id)?.into(); let builder = builder.chain_hash(self.chain_hash)?; let builder = match quantity { @@ -10532,11 +12729,13 @@ where let invoice_request = builder.build_and_sign()?; let hmac = payment_id.hmac_for_offer_payment(nonce, expanded_key); - let context = MessageContext::Offers( - OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) } - ); - let reply_paths = self.create_blinded_paths(context) - .map_err(|_| Bolt12SemanticError::MissingPaths)?; + let context = MessageContext::Offers(OffersContext::OutboundPayment { + payment_id, + nonce, + hmac: Some(hmac), + }); + let reply_paths = + self.create_blinded_paths(context).map_err(|_| Bolt12SemanticError::MissingPaths)?; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); @@ -10546,15 +12745,16 @@ where } fn enqueue_invoice_request( - &self, - invoice_request: InvoiceRequest, - reply_paths: Vec, + &self, invoice_request: InvoiceRequest, reply_paths: Vec, ) -> Result<(), Bolt12SemanticError> { let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap(); if !invoice_request.paths().is_empty() { let message = OffersMessage::InvoiceRequest(invoice_request.clone()); enqueue_onion_message_with_reply_paths( - message, invoice_request.paths(), reply_paths, &mut pending_offers_messages + message, + invoice_request.paths(), + reply_paths, + &mut pending_offers_messages, ); } else if let Some(node_id) = invoice_request.issuer_signing_pubkey() { for reply_path in reply_paths { @@ -10596,7 +12796,7 @@ where /// /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn request_refund_payment( - &self, refund: &Refund + &self, refund: &Refund, ) -> Result { let expanded_key = &self.inbound_payment_key; let entropy = &*self.entropy_source; @@ -10614,22 +12814,31 @@ where match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) { Ok((payment_hash, payment_secret)) => { let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {}); - let payment_paths = self.create_blinded_payment_paths( - Some(amount_msats), payment_secret, payment_context, relative_expiry, - ) + let payment_paths = self + .create_blinded_payment_paths( + Some(amount_msats), + payment_secret, + payment_context, + relative_expiry, + ) .map_err(|_| Bolt12SemanticError::MissingPaths)?; #[cfg(feature = "std")] let builder = refund.respond_using_derived_keys( - payment_paths, payment_hash, expanded_key, entropy + payment_paths, + payment_hash, + expanded_key, + entropy, )?; #[cfg(not(feature = "std"))] - let created_at = Duration::from_secs( - self.highest_seen_timestamp.load(Ordering::Acquire) as u64 - ); + let created_at = Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64); #[cfg(not(feature = "std"))] let builder = refund.respond_using_derived_keys_no_std( - payment_paths, payment_hash, created_at, expanded_key, entropy + payment_paths, + payment_hash, + created_at, + expanded_key, + entropy, )?; let builder: InvoiceBuilder = builder.into(); let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?; @@ -10637,9 +12846,12 @@ where let nonce = Nonce::from_entropy_source(entropy); let hmac = payment_hash.hmac_for_offer_payment(nonce, expanded_key); let context = MessageContext::Offers(OffersContext::InboundPayment { - payment_hash: invoice.payment_hash(), nonce, hmac + payment_hash: invoice.payment_hash(), + nonce, + hmac, }); - let reply_paths = self.create_blinded_paths(context) + let reply_paths = self + .create_blinded_paths(context) .map_err(|_| Bolt12SemanticError::MissingPaths)?; let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap(); @@ -10655,7 +12867,10 @@ where } else { let message = OffersMessage::Invoice(invoice.clone()); enqueue_onion_message_with_reply_paths( - message, refund.paths(), reply_paths, &mut pending_offers_messages + message, + refund.paths(), + reply_paths, + &mut pending_offers_messages, ); } @@ -10715,7 +12930,13 @@ where self.hrn_resolver.resolve_name(payment_id, name, &*self.entropy_source)?; let reply_paths = self.create_blinded_paths(MessageContext::DNSResolver(context))?; let expiration = StaleExpiration::TimerTicks(1); - self.pending_outbound_payments.add_new_awaiting_offer(payment_id, expiration, retry_strategy, route_params_config, amount_msats)?; + self.pending_outbound_payments.add_new_awaiting_offer( + payment_id, + expiration, + retry_strategy, + route_params_config, + amount_msats, + )?; let message_params = dns_resolvers .iter() .flat_map(|destination| reply_paths.iter().map(move |path| (path, destination))) @@ -10762,11 +12983,18 @@ where /// [`PaymentClaimable::purpose`]: events::Event::PaymentClaimable::purpose /// [`PaymentPurpose::preimage`]: events::PaymentPurpose::preimage /// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash - pub fn create_inbound_payment(&self, min_value_msat: Option, invoice_expiry_delta_secs: u32, - min_final_cltv_expiry_delta: Option) -> Result<(PaymentHash, PaymentSecret), ()> { - inbound_payment::create(&self.inbound_payment_key, min_value_msat, invoice_expiry_delta_secs, - &self.entropy_source, self.highest_seen_timestamp.load(Ordering::Acquire) as u64, - min_final_cltv_expiry_delta) + pub fn create_inbound_payment( + &self, min_value_msat: Option, invoice_expiry_delta_secs: u32, + min_final_cltv_expiry_delta: Option, + ) -> Result<(PaymentHash, PaymentSecret), ()> { + inbound_payment::create( + &self.inbound_payment_key, + min_value_msat, + invoice_expiry_delta_secs, + &self.entropy_source, + self.highest_seen_timestamp.load(Ordering::Acquire) as u64, + min_final_cltv_expiry_delta, + ) } /// Gets a [`PaymentSecret`] for a given [`PaymentHash`], for which the payment preimage is @@ -10815,19 +13043,32 @@ where /// /// [`create_inbound_payment`]: Self::create_inbound_payment /// [`PaymentClaimable`]: events::Event::PaymentClaimable - pub fn create_inbound_payment_for_hash(&self, payment_hash: PaymentHash, min_value_msat: Option, - invoice_expiry_delta_secs: u32, min_final_cltv_expiry: Option) -> Result { - inbound_payment::create_from_hash(&self.inbound_payment_key, min_value_msat, payment_hash, - invoice_expiry_delta_secs, self.highest_seen_timestamp.load(Ordering::Acquire) as u64, - min_final_cltv_expiry) + pub fn create_inbound_payment_for_hash( + &self, payment_hash: PaymentHash, min_value_msat: Option, + invoice_expiry_delta_secs: u32, min_final_cltv_expiry: Option, + ) -> Result { + inbound_payment::create_from_hash( + &self.inbound_payment_key, + min_value_msat, + payment_hash, + invoice_expiry_delta_secs, + self.highest_seen_timestamp.load(Ordering::Acquire) as u64, + min_final_cltv_expiry, + ) } /// Gets an LDK-generated payment preimage from a payment hash and payment secret that were /// previously returned from [`create_inbound_payment`]. /// /// [`create_inbound_payment`]: Self::create_inbound_payment - pub fn get_payment_preimage(&self, payment_hash: PaymentHash, payment_secret: PaymentSecret) -> Result { - inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key) + pub fn get_payment_preimage( + &self, payment_hash: PaymentHash, payment_secret: PaymentSecret, + ) -> Result { + inbound_payment::get_payment_preimage( + payment_hash, + payment_secret, + &self.inbound_payment_key, + ) } /// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on @@ -10851,9 +13092,7 @@ where pub(super) fn duration_since_epoch(&self) -> Duration { #[cfg(not(feature = "std"))] - let now = Duration::from_secs( - self.highest_seen_timestamp.load(Ordering::Acquire) as u64 - ); + let now = Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64); #[cfg(feature = "std")] let now = std::time::SystemTime::now() .duration_since(std::time::SystemTime::UNIX_EPOCH) @@ -10870,7 +13109,10 @@ where let recipient = self.get_our_node_id(); let secp_ctx = &self.secp_ctx; - let peers = self.per_peer_state.read().unwrap() + let peers = self + .per_peer_state + .read() + .unwrap() .iter() .map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap())) .filter(|(_, peer)| peer.is_connected) @@ -10887,18 +13129,24 @@ where /// [`MessageRouter::create_compact_blinded_paths`]. /// /// Errors if the `MessageRouter` errors. - fn create_compact_blinded_paths(&self, context: OffersContext) -> Result, ()> { + fn create_compact_blinded_paths( + &self, context: OffersContext, + ) -> Result, ()> { let recipient = self.get_our_node_id(); let secp_ctx = &self.secp_ctx; - let peers = self.per_peer_state.read().unwrap() + let peers = self + .per_peer_state + .read() + .unwrap() .iter() .map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap())) .filter(|(_, peer)| peer.is_connected) .filter(|(_, peer)| peer.latest_features.supports_onion_messages()) .map(|(node_id, peer)| MessageForwardNode { node_id: *node_id, - short_channel_id: peer.channel_by_id + short_channel_id: peer + .channel_by_id .iter() .filter(|(_, channel)| channel.context().is_usable()) .min_by_key(|(_, channel)| channel.context().channel_creation_height) @@ -10907,15 +13155,20 @@ where .collect::>(); self.message_router - .create_compact_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx) + .create_compact_blinded_paths( + recipient, + MessageContext::Offers(context), + peers, + secp_ctx, + ) .and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(())) } /// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to /// [`Router::create_blinded_payment_paths`]. fn create_blinded_payment_paths( - &self, amount_msats: Option, payment_secret: PaymentSecret, payment_context: PaymentContext, - relative_expiry_seconds: u32 + &self, amount_msats: Option, payment_secret: PaymentSecret, + payment_context: PaymentContext, relative_expiry_seconds: u32, ) -> Result, ()> { let expanded_key = &self.inbound_payment_key; let entropy = &*self.entropy_source; @@ -10933,27 +13186,31 @@ where let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, - payment_constraints: PaymentConstraints { - max_cltv_expiry, - htlc_minimum_msat: 1, - }, + payment_constraints: PaymentConstraints { max_cltv_expiry, htlc_minimum_msat: 1 }, payment_context, }; let nonce = Nonce::from_entropy_source(entropy); let payee_tlvs = payee_tlvs.authenticate(nonce, expanded_key); self.router.create_blinded_payment_paths( - payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx + payee_node_id, + first_hops, + payee_tlvs, + amount_msats, + secp_ctx, ) } #[cfg(all(test, async_payments))] pub(super) fn test_create_blinded_payment_paths( - &self, amount_msats: Option, payment_secret: PaymentSecret, payment_context: PaymentContext, - relative_expiry_seconds: u32 + &self, amount_msats: Option, payment_secret: PaymentSecret, + payment_context: PaymentContext, relative_expiry_seconds: u32, ) -> Result, ()> { self.create_blinded_payment_paths( - amount_msats, payment_secret, payment_context, relative_expiry_seconds + amount_msats, + payment_secret, + payment_context, + relative_expiry_seconds, ) } @@ -10965,11 +13222,16 @@ where let best_block_height = self.best_block.read().unwrap().height; let short_to_chan_info = self.short_to_chan_info.read().unwrap(); loop { - let scid_candidate = fake_scid::Namespace::Phantom.get_fake_scid(best_block_height, &self.chain_hash, &self.fake_scid_rand_bytes, &self.entropy_source); + let scid_candidate = fake_scid::Namespace::Phantom.get_fake_scid( + best_block_height, + &self.chain_hash, + &self.fake_scid_rand_bytes, + &self.entropy_source, + ); // Ensure the generated scid doesn't conflict with a real channel. match short_to_chan_info.get(&scid_candidate) { Some(_) => continue, - None => return scid_candidate + None => return scid_candidate, } } } @@ -10995,10 +13257,17 @@ where let best_block_height = self.best_block.read().unwrap().height; let short_to_chan_info = self.short_to_chan_info.read().unwrap(); loop { - let scid_candidate = fake_scid::Namespace::Intercept.get_fake_scid(best_block_height, &self.chain_hash, &self.fake_scid_rand_bytes, &self.entropy_source); + let scid_candidate = fake_scid::Namespace::Intercept.get_fake_scid( + best_block_height, + &self.chain_hash, + &self.fake_scid_rand_bytes, + &self.entropy_source, + ); // Ensure the generated scid doesn't conflict with a real channel. - if short_to_chan_info.contains_key(&scid_candidate) { continue } - return scid_candidate + if short_to_chan_info.contains_key(&scid_candidate) { + continue; + } + return scid_candidate; } } @@ -11080,13 +13349,12 @@ where /// [`Event`] being handled) completes, this should be called to restore the channel to normal /// operation. It will double-check that nothing *else* is also blocking the same channel from /// making progress and then let any blocked [`ChannelMonitorUpdate`]s fly. - fn handle_monitor_update_release(&self, counterparty_node_id: PublicKey, - channel_funding_outpoint: OutPoint, channel_id: ChannelId, - mut completed_blocker: Option) { - - let logger = WithContext::from( - &self.logger, Some(counterparty_node_id), Some(channel_id), None - ); + fn handle_monitor_update_release( + &self, counterparty_node_id: PublicKey, channel_funding_outpoint: OutPoint, + channel_id: ChannelId, mut completed_blocker: Option, + ) { + let logger = + WithContext::from(&self.logger, Some(counterparty_node_id), Some(channel_id), None); loop { let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mtx) = per_peer_state.get(&counterparty_node_id) { @@ -11094,15 +13362,19 @@ where let peer_state = &mut *peer_state_lck; if let Some(blocker) = completed_blocker.take() { // Only do this on the first iteration of the loop. - if let Some(blockers) = peer_state.actions_blocking_raa_monitor_updates - .get_mut(&channel_id) + if let Some(blockers) = + peer_state.actions_blocking_raa_monitor_updates.get_mut(&channel_id) { blockers.retain(|iter| iter != &blocker); } } - if self.raa_monitor_updates_held(&peer_state.actions_blocking_raa_monitor_updates, - channel_funding_outpoint, channel_id, counterparty_node_id) { + if self.raa_monitor_updates_held( + &peer_state.actions_blocking_raa_monitor_updates, + channel_funding_outpoint, + channel_id, + counterparty_node_id, + ) { // Check that, while holding the peer lock, we don't have anything else // blocking monitor updates for this channel. If we do, release the monitor // update(s) when those blockers complete. @@ -11111,15 +13383,31 @@ where break; } - if let hash_map::Entry::Occupied(mut chan_entry) = peer_state.channel_by_id.entry( - channel_id) { + if let hash_map::Entry::Occupied(mut chan_entry) = + peer_state.channel_by_id.entry(channel_id) + { if let Some(chan) = chan_entry.get_mut().as_funded_mut() { - debug_assert_eq!(chan.funding.get_funding_txo().unwrap(), channel_funding_outpoint); - if let Some((monitor_update, further_update_exists)) = chan.unblock_next_blocked_monitor_update() { - log_debug!(logger, "Unlocking monitor updating for channel {} and updating monitor", - channel_id); - handle_new_monitor_update!(self, channel_funding_outpoint, monitor_update, - peer_state_lck, peer_state, per_peer_state, chan); + debug_assert_eq!( + chan.funding.get_funding_txo().unwrap(), + channel_funding_outpoint + ); + if let Some((monitor_update, further_update_exists)) = + chan.unblock_next_blocked_monitor_update() + { + log_debug!( + logger, + "Unlocking monitor updating for channel {} and updating monitor", + channel_id + ); + handle_new_monitor_update!( + self, + channel_funding_outpoint, + monitor_update, + peer_state_lck, + peer_state, + per_peer_state, + chan + ); if further_update_exists { // If there are more `ChannelMonitorUpdate`s to process, restart at the // top of the loop. @@ -11132,9 +13420,11 @@ where } } } else { - log_debug!(logger, + log_debug!( + logger, "Got a release post-RAA monitor update for peer {} but the channel is gone", - log_pubkey!(counterparty_node_id)); + log_pubkey!(counterparty_node_id) + ); } break; } @@ -11144,10 +13434,17 @@ where for action in actions { match action { EventCompletionAction::ReleaseRAAChannelMonitorUpdate { - channel_funding_outpoint, channel_id, counterparty_node_id + channel_funding_outpoint, + channel_id, + counterparty_node_id, } => { - self.handle_monitor_update_release(counterparty_node_id, channel_funding_outpoint, channel_id, None); - } + self.handle_monitor_update_release( + counterparty_node_id, + channel_funding_outpoint, + channel_id, + None, + ); + }, } } } @@ -11156,15 +13453,28 @@ where /// using the given event handler. /// /// See the trait-level documentation of [`EventsProvider`] for requirements. - pub async fn process_pending_events_async>, H: Fn(Event) -> Future>( - &self, handler: H + pub async fn process_pending_events_async< + Future: core::future::Future>, + H: Fn(Event) -> Future, + >( + &self, handler: H, ) { let mut ev; process_events_body!(self, ev, { handler(ev).await }); } } -impl BaseMessageHandler for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > BaseMessageHandler for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -11185,8 +13495,9 @@ where } fn peer_disconnected(&self, counterparty_node_id: PublicKey) { - let _persistence_guard = PersistenceNotifierGuard::optionally_notify( - self, || NotifyOption::SkipPersistHandleEvents); + let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { + NotifyOption::SkipPersistHandleEvents + }); let mut failed_channels = Vec::new(); let mut per_peer_state = self.per_peer_state.write().unwrap(); let remove_peer = { @@ -11274,7 +13585,10 @@ where debug_assert!(peer_state.is_connected, "A disconnected peer cannot disconnect"); peer_state.is_connected = false; peer_state.ok_to_remove(true) - } else { debug_assert!(false, "Unconnected peer disconnected"); true } + } else { + debug_assert!(false, "Unconnected peer disconnected"); + true + } }; if remove_peer { per_peer_state.remove(&counterparty_node_id); @@ -11286,10 +13600,16 @@ where } } - fn peer_connected(&self, counterparty_node_id: PublicKey, init_msg: &msgs::Init, inbound: bool) -> Result<(), ()> { + fn peer_connected( + &self, counterparty_node_id: PublicKey, init_msg: &msgs::Init, inbound: bool, + ) -> Result<(), ()> { let logger = WithContext::from(&self.logger, Some(counterparty_node_id), None, None); if !init_msg.features.supports_static_remote_key() { - log_debug!(logger, "Peer {} does not support static remote key, disconnecting", log_pubkey!(counterparty_node_id)); + log_debug!( + logger, + "Peer {} does not support static remote key, disconnecting", + log_pubkey!(counterparty_node_id) + ); return Err(()); } @@ -11300,8 +13620,10 @@ where // peer immediately (as long as it doesn't have funded channels). If we have a bunch of // unfunded channels taking up space in memory for disconnected peers, we still let new // peers connect, but we'll reject new channels from them. - let connected_peers_without_funded_channels = self.peers_without_funded_channels(|node| node.is_connected); - let inbound_peer_limited = inbound && connected_peers_without_funded_channels >= MAX_NO_CHANNEL_PEERS; + let connected_peers_without_funded_channels = + self.peers_without_funded_channels(|node| node.is_connected); + let inbound_peer_limited = + inbound && connected_peers_without_funded_channels >= MAX_NO_CHANNEL_PEERS; { let mut peer_state_lock = self.per_peer_state.write().unwrap(); @@ -11329,21 +13651,28 @@ where peer_state.latest_features = init_msg.features.clone(); let best_block_height = self.best_block.read().unwrap().height; - if inbound_peer_limited && - Self::unfunded_channel_count(&*peer_state, best_block_height) == - peer_state.channel_by_id.len() + if inbound_peer_limited + && Self::unfunded_channel_count(&*peer_state, best_block_height) + == peer_state.channel_by_id.len() { res = Err(()); return NotifyOption::SkipPersistNoEvents; } - debug_assert!(!peer_state.is_connected, "A peer shouldn't be connected twice"); + debug_assert!( + !peer_state.is_connected, + "A peer shouldn't be connected twice" + ); peer_state.is_connected = true; }, } } - log_debug!(logger, "Generating channel_reestablish events for {}", log_pubkey!(counterparty_node_id)); + log_debug!( + logger, + "Generating channel_reestablish events for {}", + log_pubkey!(counterparty_node_id) + ); let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) { @@ -11354,27 +13683,26 @@ where if !peer_state.peer_storage.is_empty() { pending_msg_events.push(MessageSendEvent::SendPeerStorageRetrieval { node_id: counterparty_node_id.clone(), - msg: msgs::PeerStorageRetrieval { - data: peer_state.peer_storage.clone() - }, + msg: msgs::PeerStorageRetrieval { data: peer_state.peer_storage.clone() }, }); } for (_, chan) in peer_state.channel_by_id.iter_mut() { let logger = WithChannelContext::from(&self.logger, &chan.context(), None); match chan.peer_connected_get_handshake(self.chain_hash, &&logger) { - ReconnectionMsg::Reestablish(msg) => + ReconnectionMsg::Reestablish(msg) => { pending_msg_events.push(MessageSendEvent::SendChannelReestablish { node_id: chan.context().get_counterparty_node_id(), msg, - }), - ReconnectionMsg::Open(OpenChannelMessage::V1(msg)) => - pending_msg_events.push(MessageSendEvent::SendOpenChannel { + }) + }, + ReconnectionMsg::Open(OpenChannelMessage::V1(msg)) => pending_msg_events + .push(MessageSendEvent::SendOpenChannel { node_id: chan.context().get_counterparty_node_id(), msg, }), - ReconnectionMsg::Open(OpenChannelMessage::V2(msg)) => - pending_msg_events.push(MessageSendEvent::SendOpenChannelV2 { + ReconnectionMsg::Open(OpenChannelMessage::V2(msg)) => pending_msg_events + .push(MessageSendEvent::SendOpenChannelV2 { node_id: chan.context().get_counterparty_node_id(), msg, }), @@ -11453,7 +13781,17 @@ where } } -impl EventsProvider for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > EventsProvider for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -11469,13 +13807,26 @@ where /// /// An [`EventHandler`] may safely call back to the provider in order to handle an event. /// However, it must not call [`Writeable::write`] as doing so would result in a deadlock. - fn process_pending_events(&self, handler: H) where H::Target: EventHandler { + fn process_pending_events(&self, handler: H) + where + H::Target: EventHandler, + { let mut ev; process_events_body!(self, ev, handler.handle_event(ev)); } } -impl chain::Listen for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > chain::Listen for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -11503,7 +13854,9 @@ where fn block_disconnected(&self, header: &Header, height: u32) { let _persistence_guard = PersistenceNotifierGuard::optionally_notify_skipping_background_events( - self, || -> NotifyOption { NotifyOption::DoPersist }); + self, + || -> NotifyOption { NotifyOption::DoPersist }, + ); let new_height = height - 1; { let mut best_block = self.best_block.write().unwrap(); @@ -11514,11 +13867,30 @@ where *best_block = BestBlock::new(header.prev_blockhash, new_height) } - self.do_chain_event(Some(new_height), |channel| channel.best_block_updated(new_height, header.time, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None))); + self.do_chain_event(Some(new_height), |channel| { + channel.best_block_updated( + new_height, + header.time, + self.chain_hash, + &self.node_signer, + &self.default_configuration, + &&WithChannelContext::from(&self.logger, &channel.context, None), + ) + }); } } -impl chain::Confirm for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > chain::Confirm for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -11536,18 +13908,46 @@ where // See the docs for `ChannelManagerReadArgs` for more. let block_hash = header.block_hash(); - log_trace!(self.logger, "{} transactions included in block {} at height {} provided", txdata.len(), block_hash, height); + log_trace!( + self.logger, + "{} transactions included in block {} at height {} provided", + txdata.len(), + block_hash, + height + ); let _persistence_guard = PersistenceNotifierGuard::optionally_notify_skipping_background_events( - self, || -> NotifyOption { NotifyOption::DoPersist }); - self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None)) - .map(|(a, b)| (a, Vec::new(), b))); + self, + || -> NotifyOption { NotifyOption::DoPersist }, + ); + self.do_chain_event(Some(height), |channel| { + channel + .transactions_confirmed( + &block_hash, + height, + txdata, + self.chain_hash, + &self.node_signer, + &self.default_configuration, + &&WithChannelContext::from(&self.logger, &channel.context, None), + ) + .map(|(a, b)| (a, Vec::new(), b)) + }); let last_best_block_height = self.best_block.read().unwrap().height; if height < last_best_block_height { let timestamp = self.highest_seen_timestamp.load(Ordering::Acquire); - self.do_chain_event(Some(last_best_block_height), |channel| channel.best_block_updated(last_best_block_height, timestamp as u32, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None))); + self.do_chain_event(Some(last_best_block_height), |channel| { + channel.best_block_updated( + last_best_block_height, + timestamp as u32, + self.chain_hash, + &self.node_signer, + &self.default_configuration, + &&WithChannelContext::from(&self.logger, &channel.context, None), + ) + }); } } @@ -11561,7 +13961,9 @@ where let _persistence_guard = PersistenceNotifierGuard::optionally_notify_skipping_background_events( - self, || -> NotifyOption { NotifyOption::DoPersist }); + self, + || -> NotifyOption { NotifyOption::DoPersist }, + ); *self.best_block.write().unwrap() = BestBlock::new(block_hash, height); let mut min_anchor_feerate = None; @@ -11572,10 +13974,12 @@ where if last_days_feerates.len() >= FEERATE_TRACKING_BLOCKS { last_days_feerates.pop_front(); } - let anchor_feerate = self.fee_estimator + let anchor_feerate = self + .fee_estimator .bounded_sat_per_1000_weight(ConfirmationTarget::MinAllowedAnchorChannelRemoteFee); - let non_anchor_feerate = self.fee_estimator - .bounded_sat_per_1000_weight(ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee); + let non_anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight( + ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee, + ); last_days_feerates.push_back((anchor_feerate, non_anchor_feerate)); if last_days_feerates.len() >= FEERATE_TRACKING_BLOCKS { min_anchor_feerate = last_days_feerates.iter().map(|(f, _)| f).min().copied(); @@ -11594,7 +13998,14 @@ where channel.check_for_stale_feerate(&logger, feerate)?; } } - channel.best_block_updated(height, header.time, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None)) + channel.best_block_updated( + height, + header.time, + self.chain_hash, + &self.node_signer, + &self.default_configuration, + &&WithChannelContext::from(&self.logger, &channel.context, None), + ) }); macro_rules! max_time { @@ -11606,15 +14017,26 @@ where // Just in case we end up in a race, we loop until we either successfully // update $timestamp or decide we don't need to. let old_serial = $timestamp.load(Ordering::Acquire); - if old_serial >= header.time as usize { break; } - if $timestamp.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() { + if old_serial >= header.time as usize { + break; + } + if $timestamp + .compare_exchange( + old_serial, + header.time as usize, + Ordering::AcqRel, + Ordering::Relaxed, + ) + .is_ok() + { break; } } - } + }; } max_time!(self.highest_seen_timestamp); - #[cfg(feature = "dnssec")] { + #[cfg(feature = "dnssec")] + { let timestamp = self.highest_seen_timestamp.load(Ordering::Relaxed) as u32; self.hrn_resolver.new_best_block(height, timestamp); } @@ -11629,7 +14051,9 @@ where let txid_opt = chan.funding.get_funding_txo(); let height_opt = chan.context.get_funding_tx_confirmation_height(); let hash_opt = chan.context.get_funding_tx_confirmed_in(); - if let (Some(funding_txo), Some(conf_height), Some(block_hash)) = (txid_opt, height_opt, hash_opt) { + if let (Some(funding_txo), Some(conf_height), Some(block_hash)) = + (txid_opt, height_opt, hash_opt) + { res.push((funding_txo.txid, conf_height, Some(block_hash))); } } @@ -11640,18 +14064,40 @@ where fn transaction_unconfirmed(&self, txid: &Txid) { let _persistence_guard = PersistenceNotifierGuard::optionally_notify_skipping_background_events( - self, || -> NotifyOption { NotifyOption::DoPersist }); + self, + || -> NotifyOption { NotifyOption::DoPersist }, + ); self.do_chain_event(None, |channel| { if let Some(funding_txo) = channel.funding.get_funding_txo() { if funding_txo.txid == *txid { - channel.funding_transaction_unconfirmed(&&WithChannelContext::from(&self.logger, &channel.context, None)).map(|()| (None, Vec::new(), None)) - } else { Ok((None, Vec::new(), None)) } - } else { Ok((None, Vec::new(), None)) } + channel + .funding_transaction_unconfirmed(&&WithChannelContext::from( + &self.logger, + &channel.context, + None, + )) + .map(|()| (None, Vec::new(), None)) + } else { + Ok((None, Vec::new(), None)) + } + } else { + Ok((None, Vec::new(), None)) + } }); } } -impl ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -11666,8 +14112,20 @@ where /// Calls a function which handles an on-chain event (blocks dis/connected, transactions /// un/confirmed, etc) on each channel, handling any resulting errors or messages generated by /// the function. - fn do_chain_event) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason>> - (&self, height_opt: Option, f: FN) { + fn do_chain_event< + FN: Fn( + &mut FundedChannel, + ) -> Result< + ( + Option, + Vec<(HTLCSource, PaymentHash)>, + Option, + ), + ClosureReason, + >, + >( + &self, height_opt: Option, f: FN, + ) { // Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called // during initialization prior to the chain_monitor being fully configured in some cases. // See the docs for `ChannelManagerReadArgs` for more. @@ -11804,22 +14262,34 @@ where } if let Some(height) = height_opt { - self.claimable_payments.lock().unwrap().claimable_payments.retain(|payment_hash, payment| { - payment.htlcs.retain(|htlc| { - // If height is approaching the number of blocks we think it takes us to get - // our commitment transaction confirmed before the HTLC expires, plus the - // number of blocks we generally consider it to take to do a commitment update, - // just give up on it and fail the HTLC. - if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER { - let reason = LocalHTLCFailureReason::PaymentClaimBuffer; - timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), - HTLCFailReason::reason(reason, invalid_payment_err_data(htlc.value, height)), - HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() })); - false - } else { true } - }); - !payment.htlcs.is_empty() // Only retain this entry if htlcs has at least one entry. - }); + self.claimable_payments.lock().unwrap().claimable_payments.retain( + |payment_hash, payment| { + payment.htlcs.retain(|htlc| { + // If height is approaching the number of blocks we think it takes us to get + // our commitment transaction confirmed before the HTLC expires, plus the + // number of blocks we generally consider it to take to do a commitment update, + // just give up on it and fail the HTLC. + if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER { + let reason = LocalHTLCFailureReason::PaymentClaimBuffer; + timed_out_htlcs.push(( + HTLCSource::PreviousHopData(htlc.prev_hop.clone()), + payment_hash.clone(), + HTLCFailReason::reason( + reason, + invalid_payment_err_data(htlc.value, height), + ), + HTLCDestination::FailedPayment { + payment_hash: payment_hash.clone(), + }, + )); + false + } else { + true + } + }); + !payment.htlcs.is_empty() // Only retain this entry if htlcs has at least one entry. + }, + ); let mut intercepted_htlcs = self.pending_intercepted_htlcs.lock().unwrap(); intercepted_htlcs.retain(|_, htlc| { @@ -11841,15 +14311,29 @@ where PendingHTLCRouting::Forward { short_channel_id, .. } => short_channel_id, _ => unreachable!(), }; - timed_out_htlcs.push((prev_hop_data, htlc.forward_info.payment_hash, - HTLCFailReason::from_failure_code(LocalHTLCFailureReason::ForwardExpiryBuffer), - HTLCDestination::InvalidForward { requested_forward_scid })); + timed_out_htlcs.push(( + prev_hop_data, + htlc.forward_info.payment_hash, + HTLCFailReason::from_failure_code( + LocalHTLCFailureReason::ForwardExpiryBuffer, + ), + HTLCDestination::InvalidForward { requested_forward_scid }, + )); let logger = WithContext::from( - &self.logger, None, Some(htlc.prev_channel_id), Some(htlc.forward_info.payment_hash) + &self.logger, + None, + Some(htlc.prev_channel_id), + Some(htlc.forward_info.payment_hash), + ); + log_trace!( + logger, + "Timing out intercepted HTLC with requested forward scid {}", + requested_forward_scid ); - log_trace!(logger, "Timing out intercepted HTLC with requested forward scid {}", requested_forward_scid); false - } else { true } + } else { + true + } }); } @@ -11934,8 +14418,17 @@ where } } -impl - ChannelMessageHandler for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > ChannelMessageHandler for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -11952,7 +14445,8 @@ where // open_channel message - pre-funded channels are never written so there should be no // change to the contents. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let res = self.internal_open_channel(&counterparty_node_id, OpenChannelMessageRef::V1(msg)); + let res = + self.internal_open_channel(&counterparty_node_id, OpenChannelMessageRef::V1(msg)); let persist = match &res { Err(e) if e.closes_channel() => { debug_assert!(false, "We shouldn't close a new channel"); @@ -11970,7 +14464,8 @@ where // open_channel message - pre-funded channels are never written so there should be no // change to the contents. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let res = self.internal_open_channel(&counterparty_node_id, OpenChannelMessageRef::V2(msg)); + let res = + self.internal_open_channel(&counterparty_node_id, OpenChannelMessageRef::V2(msg)); let persist = match &res { Err(e) if e.closes_channel() => { debug_assert!(false, "We shouldn't close a new channel"); @@ -11988,35 +14483,66 @@ where // accept_channel message - pre-funded channels are never written so there should be no // change to the contents. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let _ = handle_error!(self, self.internal_accept_channel(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_accept_channel(&counterparty_node_id, msg), + counterparty_node_id + ); NotifyOption::SkipPersistHandleEvents }); } - fn handle_accept_channel_v2(&self, counterparty_node_id: PublicKey, msg: &msgs::AcceptChannelV2) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Dual-funded channels not supported".to_owned(), - msg.common_fields.temporary_channel_id.clone())), counterparty_node_id); + fn handle_accept_channel_v2( + &self, counterparty_node_id: PublicKey, msg: &msgs::AcceptChannelV2, + ) { + let _: Result<(), _> = handle_error!( + self, + Err(MsgHandleErrInternal::send_err_msg_no_close( + "Dual-funded channels not supported".to_owned(), + msg.common_fields.temporary_channel_id.clone() + )), + counterparty_node_id + ); } fn handle_funding_created(&self, counterparty_node_id: PublicKey, msg: &msgs::FundingCreated) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_funding_created(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_funding_created(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_funding_signed(&self, counterparty_node_id: PublicKey, msg: &msgs::FundingSigned) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_funding_signed(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_funding_signed(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_peer_storage(&self, counterparty_node_id: PublicKey, msg: msgs::PeerStorage) { - let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || NotifyOption::SkipPersistNoEvents); - let _ = handle_error!(self, self.internal_peer_storage(counterparty_node_id, msg), counterparty_node_id); + let _persistence_guard = + PersistenceNotifierGuard::optionally_notify(self, || NotifyOption::SkipPersistNoEvents); + let _ = handle_error!( + self, + self.internal_peer_storage(counterparty_node_id, msg), + counterparty_node_id + ); } - fn handle_peer_storage_retrieval(&self, counterparty_node_id: PublicKey, msg: msgs::PeerStorageRetrieval) { - let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || NotifyOption::SkipPersistNoEvents); - let _ = handle_error!(self, self.internal_peer_storage_retrieval(counterparty_node_id, msg), counterparty_node_id); + fn handle_peer_storage_retrieval( + &self, counterparty_node_id: PublicKey, msg: msgs::PeerStorageRetrieval, + ) { + let _persistence_guard = + PersistenceNotifierGuard::optionally_notify(self, || NotifyOption::SkipPersistNoEvents); + let _ = handle_error!( + self, + self.internal_peer_storage_retrieval(counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_channel_ready(&self, counterparty_node_id: PublicKey, msg: &msgs::ChannelReady) { @@ -12041,10 +14567,12 @@ where let persist = match &res { Err(e) if e.closes_channel() => NotifyOption::DoPersist, Err(_) => NotifyOption::SkipPersistHandleEvents, - Ok(sent_stfu) => if *sent_stfu { - NotifyOption::SkipPersistHandleEvents - } else { - NotifyOption::SkipPersistNoEvents + Ok(sent_stfu) => { + if *sent_stfu { + NotifyOption::SkipPersistHandleEvents + } else { + NotifyOption::SkipPersistNoEvents + } }, }; let _ = handle_error!(self, res, counterparty_node_id); @@ -12082,19 +14610,32 @@ where #[cfg(splicing)] fn handle_splice_locked(&self, counterparty_node_id: PublicKey, msg: &msgs::SpliceLocked) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Splicing not supported (splice_locked)".to_owned(), - msg.channel_id)), counterparty_node_id); + let _: Result<(), _> = handle_error!( + self, + Err(MsgHandleErrInternal::send_err_msg_no_close( + "Splicing not supported (splice_locked)".to_owned(), + msg.channel_id + )), + counterparty_node_id + ); } fn handle_shutdown(&self, counterparty_node_id: PublicKey, msg: &msgs::Shutdown) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_shutdown(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_shutdown(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_closing_signed(&self, counterparty_node_id: PublicKey, msg: &msgs::ClosingSigned) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_closing_signed(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_closing_signed(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_update_add_htlc(&self, counterparty_node_id: PublicKey, msg: &msgs::UpdateAddHTLC) { @@ -12113,9 +14654,15 @@ where }); } - fn handle_update_fulfill_htlc(&self, counterparty_node_id: PublicKey, msg: &msgs::UpdateFulfillHTLC) { + fn handle_update_fulfill_htlc( + &self, counterparty_node_id: PublicKey, msg: &msgs::UpdateFulfillHTLC, + ) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_update_fulfill_htlc(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_update_fulfill_htlc(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_update_fail_htlc(&self, counterparty_node_id: PublicKey, msg: &msgs::UpdateFailHTLC) { @@ -12134,7 +14681,9 @@ where }); } - fn handle_update_fail_malformed_htlc(&self, counterparty_node_id: PublicKey, msg: &msgs::UpdateFailMalformedHTLC) { + fn handle_update_fail_malformed_htlc( + &self, counterparty_node_id: PublicKey, msg: &msgs::UpdateFailMalformedHTLC, + ) { // Note that we never need to persist the updated ChannelManager for an inbound // update_fail_malformed_htlc message - the message itself doesn't change our channel state // only the `commitment_signed` message afterwards will. @@ -12150,19 +14699,36 @@ where }); } - fn handle_commitment_signed(&self, counterparty_node_id: PublicKey, msg: &msgs::CommitmentSigned) { + fn handle_commitment_signed( + &self, counterparty_node_id: PublicKey, msg: &msgs::CommitmentSigned, + ) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_commitment_signed(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_commitment_signed(&counterparty_node_id, msg), + counterparty_node_id + ); } - fn handle_commitment_signed_batch(&self, counterparty_node_id: PublicKey, channel_id: ChannelId, batch: BTreeMap) { + fn handle_commitment_signed_batch( + &self, counterparty_node_id: PublicKey, channel_id: ChannelId, + batch: BTreeMap, + ) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_commitment_signed_batch(&counterparty_node_id, channel_id, &batch), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_commitment_signed_batch(&counterparty_node_id, channel_id, &batch), + counterparty_node_id + ); } fn handle_revoke_and_ack(&self, counterparty_node_id: PublicKey, msg: &msgs::RevokeAndACK) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_revoke_and_ack(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_revoke_and_ack(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_update_fee(&self, counterparty_node_id: PublicKey, msg: &msgs::UpdateFee) { @@ -12181,14 +14747,24 @@ where }); } - fn handle_announcement_signatures(&self, counterparty_node_id: PublicKey, msg: &msgs::AnnouncementSignatures) { + fn handle_announcement_signatures( + &self, counterparty_node_id: PublicKey, msg: &msgs::AnnouncementSignatures, + ) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_announcement_signatures(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_announcement_signatures(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_channel_update(&self, counterparty_node_id: PublicKey, msg: &msgs::ChannelUpdate) { PersistenceNotifierGuard::optionally_notify(self, || { - if let Ok(persist) = handle_error!(self, self.internal_channel_update(&counterparty_node_id, msg), counterparty_node_id) { + if let Ok(persist) = handle_error!( + self, + self.internal_channel_update(&counterparty_node_id, msg), + counterparty_node_id + ) { persist } else { NotifyOption::DoPersist @@ -12196,7 +14772,9 @@ where }); } - fn handle_channel_reestablish(&self, counterparty_node_id: PublicKey, msg: &msgs::ChannelReestablish) { + fn handle_channel_reestablish( + &self, counterparty_node_id: PublicKey, msg: &msgs::ChannelReestablish, + ) { let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { let res = self.internal_channel_reestablish(&counterparty_node_id, msg); let persist = match &res { @@ -12211,9 +14789,7 @@ where fn handle_error(&self, counterparty_node_id: PublicKey, msg: &msgs::ErrorMessage) { match &msg.data as &str { - "cannot co-op close channel w/ active htlcs"| - "link failed to shutdown" => - { + "cannot co-op close channel w/ active htlcs" | "link failed to shutdown" => { // LND hasn't properly handled shutdown messages ever, and force-closes any time we // send one while HTLCs are still present. The issue is tracked at // https://github.com/lightningnetwork/lnd/issues/6039 and has had multiple patches @@ -12222,24 +14798,27 @@ where // We're not going to bother handling this in a sensible way, instead simply // repeating the Shutdown message on repeat until morale improves. if !msg.channel_id.is_zero() { - PersistenceNotifierGuard::optionally_notify( - self, - || -> NotifyOption { - let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id); - if peer_state_mutex_opt.is_none() { return NotifyOption::SkipPersistNoEvents; } - let mut peer_state = peer_state_mutex_opt.unwrap().lock().unwrap(); - if let Some(chan) = peer_state.channel_by_id - .get(&msg.channel_id) - .and_then(Channel::as_funded) - { - if let Some(msg) = chan.get_outbound_shutdown() { - peer_state.pending_msg_events.push(MessageSendEvent::SendShutdown { + PersistenceNotifierGuard::optionally_notify(self, || -> NotifyOption { + let per_peer_state = self.per_peer_state.read().unwrap(); + let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id); + if peer_state_mutex_opt.is_none() { + return NotifyOption::SkipPersistNoEvents; + } + let mut peer_state = peer_state_mutex_opt.unwrap().lock().unwrap(); + if let Some(chan) = peer_state + .channel_by_id + .get(&msg.channel_id) + .and_then(Channel::as_funded) + { + if let Some(msg) = chan.get_outbound_shutdown() { + peer_state.pending_msg_events.push( + MessageSendEvent::SendShutdown { node_id: counterparty_node_id, msg, - }); - } - peer_state.pending_msg_events.push(MessageSendEvent::HandleError { + }, + ); + } + peer_state.pending_msg_events.push(MessageSendEvent::HandleError { node_id: counterparty_node_id, action: msgs::ErrorAction::SendWarningMessage { msg: msgs::WarningMessage { @@ -12249,17 +14828,16 @@ where log_level: Level::Trace, } }); - // This can happen in a fairly tight loop, so we absolutely cannot trigger - // a `ChannelManager` write here. - return NotifyOption::SkipPersistHandleEvents; - } - NotifyOption::SkipPersistNoEvents + // This can happen in a fairly tight loop, so we absolutely cannot trigger + // a `ChannelManager` write here. + return NotifyOption::SkipPersistHandleEvents; } - ); + NotifyOption::SkipPersistNoEvents + }); } return; - } - _ => {} + }, + _ => {}, } let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); @@ -12268,7 +14846,9 @@ where let channel_ids: Vec = { let per_peer_state = self.per_peer_state.read().unwrap(); let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id); - if peer_state_mutex_opt.is_none() { return; } + if peer_state_mutex_opt.is_none() { + return; + } let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; // Note that we don't bother generating any events for pre-accept channels - @@ -12278,19 +14858,28 @@ where }; for channel_id in channel_ids { // Untrusted messages from peer, we throw away the error if id points to a non-existent channel - let _ = self.force_close_channel_with_peer(&channel_id, &counterparty_node_id, Some(&msg.data), true); + let _ = self.force_close_channel_with_peer( + &channel_id, + &counterparty_node_id, + Some(&msg.data), + true, + ); } } else { { // First check if we can advance the channel type and try again. let per_peer_state = self.per_peer_state.read().unwrap(); let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id); - if peer_state_mutex_opt.is_none() { return; } + if peer_state_mutex_opt.is_none() { + return; + } let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; match peer_state.channel_by_id.get_mut(&msg.channel_id) { Some(chan) => match chan.maybe_handle_error_without_close( - self.chain_hash, &self.fee_estimator, &self.logger, + self.chain_hash, + &self.fee_estimator, + &self.logger, ) { Ok(Some(OpenChannelMessage::V1(msg))) => { peer_state.pending_msg_events.push(MessageSendEvent::SendOpenChannel { @@ -12300,10 +14889,12 @@ where return; }, Ok(Some(OpenChannelMessage::V2(msg))) => { - peer_state.pending_msg_events.push(MessageSendEvent::SendOpenChannelV2 { - node_id: counterparty_node_id, - msg, - }); + peer_state.pending_msg_events.push( + MessageSendEvent::SendOpenChannelV2 { + node_id: counterparty_node_id, + msg, + }, + ); return; }, Ok(None) | Err(()) => {}, @@ -12313,7 +14904,12 @@ where } // Untrusted messages from peer, we throw away the error if id points to a non-existent channel - let _ = self.force_close_channel_with_peer(&msg.channel_id, &counterparty_node_id, Some(&msg.data), true); + let _ = self.force_close_channel_with_peer( + &msg.channel_id, + &counterparty_node_id, + Some(&msg.data), + true, + ); } } @@ -12326,7 +14922,11 @@ where // tx_add_input message - interactive transaction construction does not need to // be persisted before any signatures are exchanged. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let _ = handle_error!(self, self.internal_tx_add_input(counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_tx_add_input(counterparty_node_id, msg), + counterparty_node_id + ); NotifyOption::SkipPersistHandleEvents }); } @@ -12336,7 +14936,11 @@ where // tx_add_output message - interactive transaction construction does not need to // be persisted before any signatures are exchanged. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let _ = handle_error!(self, self.internal_tx_add_output(counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_tx_add_output(counterparty_node_id, msg), + counterparty_node_id + ); NotifyOption::SkipPersistHandleEvents }); } @@ -12346,7 +14950,11 @@ where // tx_remove_input message - interactive transaction construction does not need to // be persisted before any signatures are exchanged. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let _ = handle_error!(self, self.internal_tx_remove_input(counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_tx_remove_input(counterparty_node_id, msg), + counterparty_node_id + ); NotifyOption::SkipPersistHandleEvents }); } @@ -12356,7 +14964,11 @@ where // tx_remove_output message - interactive transaction construction does not need to // be persisted before any signatures are exchanged. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let _ = handle_error!(self, self.internal_tx_remove_output(counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_tx_remove_output(counterparty_node_id, msg), + counterparty_node_id + ); NotifyOption::SkipPersistHandleEvents }); } @@ -12366,26 +14978,44 @@ where // tx_complete message - interactive transaction construction does not need to // be persisted before any signatures are exchanged. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let _ = handle_error!(self, self.internal_tx_complete(counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_tx_complete(counterparty_node_id, msg), + counterparty_node_id + ); NotifyOption::SkipPersistHandleEvents }); } fn handle_tx_signatures(&self, counterparty_node_id: PublicKey, msg: &msgs::TxSignatures) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let _ = handle_error!(self, self.internal_tx_signatures(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_tx_signatures(&counterparty_node_id, msg), + counterparty_node_id + ); } fn handle_tx_init_rbf(&self, counterparty_node_id: PublicKey, msg: &msgs::TxInitRbf) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Dual-funded channels not supported".to_owned(), - msg.channel_id.clone())), counterparty_node_id); + let _: Result<(), _> = handle_error!( + self, + Err(MsgHandleErrInternal::send_err_msg_no_close( + "Dual-funded channels not supported".to_owned(), + msg.channel_id.clone() + )), + counterparty_node_id + ); } fn handle_tx_ack_rbf(&self, counterparty_node_id: PublicKey, msg: &msgs::TxAckRbf) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Dual-funded channels not supported".to_owned(), - msg.channel_id.clone())), counterparty_node_id); + let _: Result<(), _> = handle_error!( + self, + Err(MsgHandleErrInternal::send_err_msg_no_close( + "Dual-funded channels not supported".to_owned(), + msg.channel_id.clone() + )), + counterparty_node_id + ); } fn handle_tx_abort(&self, counterparty_node_id: PublicKey, msg: &msgs::TxAbort) { @@ -12393,47 +15023,62 @@ where // tx_abort message - interactive transaction construction does not need to // be persisted before any signatures are exchanged. let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || { - let _ = handle_error!(self, self.internal_tx_abort(&counterparty_node_id, msg), counterparty_node_id); + let _ = handle_error!( + self, + self.internal_tx_abort(&counterparty_node_id, msg), + counterparty_node_id + ); NotifyOption::SkipPersistHandleEvents }); } fn message_received(&self) { - for (payment_id, retryable_invoice_request) in self - .pending_outbound_payments - .release_invoice_requests_awaiting_invoice() + for (payment_id, retryable_invoice_request) in + self.pending_outbound_payments.release_invoice_requests_awaiting_invoice() { let RetryableInvoiceRequest { invoice_request, nonce, .. } = retryable_invoice_request; let hmac = payment_id.hmac_for_offer_payment(nonce, &self.inbound_payment_key); let context = MessageContext::Offers(OffersContext::OutboundPayment { payment_id, nonce, - hmac: Some(hmac) + hmac: Some(hmac), }); match self.create_blinded_paths(context) { - Ok(reply_paths) => match self.enqueue_invoice_request(invoice_request, reply_paths) { - Ok(_) => {} + Ok(reply_paths) => match self.enqueue_invoice_request(invoice_request, reply_paths) + { + Ok(_) => {}, Err(_) => { - log_warn!(self.logger, + log_warn!( + self.logger, "Retry failed for an invoice request with payment_id: {}", payment_id ); - } + }, }, Err(_) => { - log_warn!(self.logger, + log_warn!( + self.logger, "Retry failed for an invoice request with payment_id: {}. \ Reason: router could not find a blinded path to include as the reply path", payment_id ); - } + }, } } } } -impl -OffersMessageHandler for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > OffersMessageHandler for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -12456,7 +15101,8 @@ where let error = match $res { Err(Bolt12PaymentError::UnknownRequiredFeatures) => { log_trace!( - $logger, "Invoice requires unknown features: {:?}", + $logger, + "Invoice requires unknown features: {:?}", $invoice.invoice_features() ); InvoiceError::from(Bolt12SemanticError::UnknownRequiredFeatures) @@ -12472,18 +15118,20 @@ where InvoiceError::from_string(err_msg.to_string()) }, Err(Bolt12PaymentError::UnexpectedInvoice) - | Err(Bolt12PaymentError::DuplicateInvoice) - | Ok(()) => return None, + | Err(Bolt12PaymentError::DuplicateInvoice) + | Ok(()) => return None, }; match responder { - Some(responder) => return Some((OffersMessage::InvoiceError(error), responder.respond())), + Some(responder) => { + return Some((OffersMessage::InvoiceError(error), responder.respond())) + }, None => { log_trace!($logger, "No reply path to send error: {:?}", error); - return None + return None; }, } - }} + }}; } match message { @@ -12501,7 +15149,9 @@ where let invoice_request = match nonce { Some(nonce) => match invoice_request.verify_using_recipient_data( - nonce, expanded_key, secp_ctx, + nonce, + expanded_key, + secp_ctx, ) { Ok(invoice_request) => invoice_request, Err(()) => return None, @@ -12513,50 +15163,61 @@ where }; let amount_msats = match InvoiceBuilder::::amount_msats( - &invoice_request.inner + &invoice_request.inner, ) { Ok(amount_msats) => amount_msats, - Err(error) => return Some((OffersMessage::InvoiceError(error.into()), responder.respond())), + Err(error) => { + return Some(( + OffersMessage::InvoiceError(error.into()), + responder.respond(), + )) + }, }; let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32; - let (payment_hash, payment_secret) = match self.create_inbound_payment( - Some(amount_msats), relative_expiry, None - ) { - Ok((payment_hash, payment_secret)) => (payment_hash, payment_secret), - Err(()) => { - let error = Bolt12SemanticError::InvalidAmount; - return Some((OffersMessage::InvoiceError(error.into()), responder.respond())); - }, - }; + let (payment_hash, payment_secret) = + match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) { + Ok((payment_hash, payment_secret)) => (payment_hash, payment_secret), + Err(()) => { + let error = Bolt12SemanticError::InvalidAmount; + return Some(( + OffersMessage::InvoiceError(error.into()), + responder.respond(), + )); + }, + }; let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext { offer_id: invoice_request.offer_id, invoice_request: invoice_request.fields(), }); let payment_paths = match self.create_blinded_payment_paths( - Some(amount_msats), payment_secret, payment_context, relative_expiry + Some(amount_msats), + payment_secret, + payment_context, + relative_expiry, ) { Ok(payment_paths) => payment_paths, Err(()) => { let error = Bolt12SemanticError::MissingPaths; - return Some((OffersMessage::InvoiceError(error.into()), responder.respond())); + return Some(( + OffersMessage::InvoiceError(error.into()), + responder.respond(), + )); }, }; #[cfg(not(feature = "std"))] - let created_at = Duration::from_secs( - self.highest_seen_timestamp.load(Ordering::Acquire) as u64 - ); + let created_at = Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64); let response = if invoice_request.keys.is_some() { #[cfg(feature = "std")] - let builder = invoice_request.respond_using_derived_keys( - payment_paths, payment_hash - ); + let builder = invoice_request.respond_using_derived_keys(payment_paths, payment_hash); #[cfg(not(feature = "std"))] let builder = invoice_request.respond_using_derived_keys_no_std( - payment_paths, payment_hash, created_at + payment_paths, + payment_hash, + created_at, ); builder .map(InvoiceBuilder::::from) @@ -12566,9 +15227,7 @@ where #[cfg(feature = "std")] let builder = invoice_request.respond_with(payment_paths, payment_hash); #[cfg(not(feature = "std"))] - let builder = invoice_request.respond_with_no_std( - payment_paths, payment_hash, created_at - ); + let builder = invoice_request.respond_with_no_std(payment_paths, payment_hash, created_at); builder .map(InvoiceBuilder::::from) .and_then(|builder| builder.allow_mpp().build()) @@ -12577,9 +15236,9 @@ where #[cfg(c_bindings)] let mut invoice = invoice; invoice - .sign(|invoice: &UnsignedBolt12Invoice| + .sign(|invoice: &UnsignedBolt12Invoice| { self.node_signer.sign_bolt12_invoice(invoice) - ) + }) .map_err(InvoiceError::from) }) }; @@ -12588,10 +15247,19 @@ where Ok(invoice) => { let nonce = Nonce::from_entropy_source(&*self.entropy_source); let hmac = payment_hash.hmac_for_offer_payment(nonce, expanded_key); - let context = MessageContext::Offers(OffersContext::InboundPayment { payment_hash, nonce, hmac }); - Some((OffersMessage::Invoice(invoice), responder.respond_with_reply_path(context))) + let context = MessageContext::Offers(OffersContext::InboundPayment { + payment_hash, + nonce, + hmac, + }); + Some(( + OffersMessage::Invoice(invoice), + responder.respond_with_reply_path(context), + )) + }, + Err(error) => { + Some((OffersMessage::InvoiceError(error.into()), responder.respond())) }, - Err(error) => Some((OffersMessage::InvoiceError(error.into()), responder.respond())), } }, OffersMessage::Invoice(invoice) => { @@ -12600,14 +15268,11 @@ where Err(()) => return None, }; - let logger = WithContext::from( - &self.logger, None, None, Some(invoice.payment_hash()), - ); + let logger = + WithContext::from(&self.logger, None, None, Some(invoice.payment_hash())); if self.default_configuration.manually_handle_bolt12_invoices { - let event = Event::InvoiceReceived { - payment_id, invoice, context, responder, - }; + let event = Event::InvoiceReceived { payment_id, invoice, context, responder }; self.pending_events.lock().unwrap().push_back((event, None)); return None; } @@ -12618,13 +15283,17 @@ where #[cfg(async_payments)] OffersMessage::StaticInvoice(invoice) => { let payment_id = match context { - Some(OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) }) => { + Some(OffersContext::OutboundPayment { + payment_id, + nonce, + hmac: Some(hmac), + }) => { if payment_id.verify_for_offer_payment(hmac, nonce, expanded_key).is_err() { - return None + return None; } payment_id }, - _ => return None + _ => return None, }; let res = self.initiate_async_payment(&invoice, payment_id); handle_pay_invoice_res!(res, invoice, self.logger); @@ -12644,10 +15313,17 @@ where log_trace!(logger, "Received invoice_error: {}", invoice_error); match context { - Some(OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) }) => { - if let Ok(()) = payment_id.verify_for_offer_payment(hmac, nonce, expanded_key) { + Some(OffersContext::OutboundPayment { + payment_id, + nonce, + hmac: Some(hmac), + }) => { + if let Ok(()) = + payment_id.verify_for_offer_payment(hmac, nonce, expanded_key) + { self.abandon_payment_with_reason( - payment_id, PaymentFailureReason::InvoiceRequestRejected, + payment_id, + PaymentFailureReason::InvoiceRequestRejected, ); } }, @@ -12664,8 +15340,17 @@ where } } -impl -AsyncPaymentsMessageHandler for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > AsyncPaymentsMessageHandler for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -12679,36 +15364,50 @@ where { fn handle_held_htlc_available( &self, _message: HeldHtlcAvailable, _context: AsyncPaymentsContext, - _responder: Option + _responder: Option, ) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> { - #[cfg(async_payments)] { + #[cfg(async_payments)] + { match _context { AsyncPaymentsContext::InboundPayment { nonce, hmac, path_absolute_expiry } => { if let Err(()) = signer::verify_held_htlc_available_context( - nonce, hmac, &self.inbound_payment_key - ) { return None } - if self.duration_since_epoch() > path_absolute_expiry { return None } + nonce, + hmac, + &self.inbound_payment_key, + ) { + return None; + } + if self.duration_since_epoch() > path_absolute_expiry { + return None; + } }, - _ => return None + _ => return None, } - return _responder.map(|responder| (ReleaseHeldHtlc {}, responder.respond())) + return _responder.map(|responder| (ReleaseHeldHtlc {}, responder.respond())); } #[cfg(not(async_payments))] - return None + return None; } fn handle_release_held_htlc(&self, _message: ReleaseHeldHtlc, _context: AsyncPaymentsContext) { - #[cfg(async_payments)] { + #[cfg(async_payments)] + { let (payment_id, nonce, hmac) = match _context { AsyncPaymentsContext::OutboundPayment { payment_id, hmac, nonce } => { (payment_id, nonce, hmac) }, - _ => return + _ => return, }; - if payment_id.verify_for_async_payment(hmac, nonce, &self.inbound_payment_key).is_err() { return } + if payment_id.verify_for_async_payment(hmac, nonce, &self.inbound_payment_key).is_err() + { + return; + } if let Err(e) = self.send_payment_for_static_invoice(payment_id) { log_trace!( - self.logger, "Failed to release held HTLC with payment id {}: {:?}", payment_id, e + self.logger, + "Failed to release held HTLC with payment id {}: {:?}", + payment_id, + e ); } } @@ -12720,8 +15419,17 @@ where } #[cfg(feature = "dnssec")] -impl -DNSResolverMessageHandler for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > DNSResolverMessageHandler for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -12745,24 +15453,37 @@ where if let Some((completed_requests, mut offer)) = offer_opt { for (name, payment_id) in completed_requests { #[cfg(feature = "_test_utils")] - if let Some(replacement_offer) = self.testing_dnssec_proof_offer_resolution_override.lock().unwrap().remove(&name) { + if let Some(replacement_offer) = self + .testing_dnssec_proof_offer_resolution_override + .lock() + .unwrap() + .remove(&name) + { // If we have multiple pending requests we may end up over-using the override // offer, but tests can deal with that. offer = replacement_offer; } - if let Ok(amt_msats) = self.pending_outbound_payments.amt_msats_for_payment_awaiting_offer(payment_id) { - let offer_pay_res = - self.pay_for_offer_intern(&offer, None, Some(amt_msats), None, payment_id, Some(name), - |invoice_request, nonce| { - let retryable_invoice_request = RetryableInvoiceRequest { - invoice_request: invoice_request.clone(), - nonce, - needs_retry: true, - }; - self.pending_outbound_payments - .received_offer(payment_id, Some(retryable_invoice_request)) - .map_err(|_| Bolt12SemanticError::DuplicatePaymentId) - }); + if let Ok(amt_msats) = + self.pending_outbound_payments.amt_msats_for_payment_awaiting_offer(payment_id) + { + let offer_pay_res = self.pay_for_offer_intern( + &offer, + None, + Some(amt_msats), + None, + payment_id, + Some(name), + |invoice_request, nonce| { + let retryable_invoice_request = RetryableInvoiceRequest { + invoice_request: invoice_request.clone(), + nonce, + needs_retry: true, + }; + self.pending_outbound_payments + .received_offer(payment_id, Some(retryable_invoice_request)) + .map_err(|_| Bolt12SemanticError::DuplicatePaymentId) + }, + ); if offer_pay_res.is_err() { // The offer we tried to pay is the canonical current offer for the name we // wanted to pay. If we can't pay it, there's no way to recover so fail the @@ -12770,7 +15491,9 @@ where // Note that the PaymentFailureReason should be ignored for an // AwaitingInvoice payment. self.pending_outbound_payments.abandon_payment( - payment_id, PaymentFailureReason::RouteNotFound, &self.pending_events, + payment_id, + PaymentFailureReason::RouteNotFound, + &self.pending_events, ); } } @@ -12783,8 +15506,17 @@ where } } -impl -NodeIdLookUp for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > NodeIdLookUp for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -12803,15 +15535,11 @@ where fn enqueue_onion_message_with_reply_paths( message: T, message_paths: &[BlindedMessagePath], reply_paths: Vec, - queue: &mut Vec<(T, MessageSendInstructions)> + queue: &mut Vec<(T, MessageSendInstructions)>, ) { reply_paths .iter() - .flat_map(|reply_path| - message_paths - .iter() - .map(move |path| (path, reply_path)) - ) + .flat_map(|reply_path| message_paths.iter().map(move |path| (path, reply_path))) .take(OFFERS_MESSAGE_REQUEST_LIMIT) .for_each(|(path, reply_path)| { let instructions = MessageSendInstructions::WithSpecifiedReplyPath { @@ -12950,11 +15678,15 @@ impl_writeable_tlv_based!(PendingHTLCInfo, { (10, skimmed_fee_msat, option), }); - impl Writeable for HTLCFailureMsg { fn write(&self, writer: &mut W) -> Result<(), io::Error> { match self { - HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { channel_id, htlc_id, reason, attribution_data }) => { + HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { + channel_id, + htlc_id, + reason, + attribution_data, + }) => { 0u8.write(writer)?; channel_id.write(writer)?; htlc_id.write(writer)?; @@ -12965,7 +15697,10 @@ impl Writeable for HTLCFailureMsg { debug_assert!(attribution_data.is_none()); }, HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { - channel_id, htlc_id, sha256_of_onion, failure_code + channel_id, + htlc_id, + sha256_of_onion, + failure_code, }) => { 1u8.write(writer)?; channel_id.write(writer)?; @@ -12982,22 +15717,18 @@ impl Readable for HTLCFailureMsg { fn read(reader: &mut R) -> Result { let id: u8 = Readable::read(reader)?; match id { - 0 => { - Ok(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { - channel_id: Readable::read(reader)?, - htlc_id: Readable::read(reader)?, - reason: Readable::read(reader)?, - attribution_data: None, - })) - }, - 1 => { - Ok(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { - channel_id: Readable::read(reader)?, - htlc_id: Readable::read(reader)?, - sha256_of_onion: Readable::read(reader)?, - failure_code: Readable::read(reader)?, - })) - }, + 0 => Ok(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { + channel_id: Readable::read(reader)?, + htlc_id: Readable::read(reader)?, + reason: Readable::read(reader)?, + attribution_data: None, + })), + 1 => Ok(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { + channel_id: Readable::read(reader)?, + htlc_id: Readable::read(reader)?, + sha256_of_onion: Readable::read(reader)?, + failure_code: Readable::read(reader)?, + })), // In versions prior to 0.0.101, HTLCFailureMsg objects were written with type 0 or 1 but // weren't length-prefixed and thus didn't support reading the TLV stream suffix of the network // messages contained in the variants. @@ -13051,9 +15782,7 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, { impl Writeable for ClaimableHTLC { fn write(&self, writer: &mut W) -> Result<(), io::Error> { let (payment_data, keysend_preimage) = match &self.onion_payload { - OnionPayload::Invoice { _legacy_hop_data } => { - (_legacy_hop_data.as_ref(), None) - }, + OnionPayload::Invoice { _legacy_hop_data } => (_legacy_hop_data.as_ref(), None), OnionPayload::Spontaneous(preimage) => (None, Some(preimage)), }; write_tlv_fields!(writer, { @@ -13089,7 +15818,7 @@ impl Readable for ClaimableHTLC { let onion_payload = match keysend_preimage { Some(p) => { if payment_data.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } if total_msat.is_none() { total_msat = Some(value); @@ -13099,7 +15828,7 @@ impl Readable for ClaimableHTLC { None => { if total_msat.is_none() { if payment_data.is_none() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } total_msat = Some(payment_data.as_ref().unwrap().total_msat); } @@ -13125,7 +15854,8 @@ impl Readable for HTLCSource { let id: u8 = Readable::read(reader)?; match id { 0 => { - let mut session_priv: crate::util::ser::RequiredWrapper = crate::util::ser::RequiredWrapper(None); + let mut session_priv: crate::util::ser::RequiredWrapper = + crate::util::ser::RequiredWrapper(None); let mut first_hop_htlc_msat: u64 = 0; let mut path_hops = Vec::new(); let mut payment_id = None; @@ -13151,7 +15881,8 @@ impl Readable for HTLCSource { if let Some(params) = payment_params.as_mut() { if let Payee::Clear { ref mut final_cltv_expiry_delta, .. } = params.payee { if final_cltv_expiry_delta == &0 { - *final_cltv_expiry_delta = path.final_cltv_expiry_delta().ok_or(DecodeError::InvalidValue)?; + *final_cltv_expiry_delta = + path.final_cltv_expiry_delta().ok_or(DecodeError::InvalidValue)?; } } } @@ -13161,7 +15892,7 @@ impl Readable for HTLCSource { path, payment_id: payment_id.unwrap(), }) - } + }, 1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)), _ => Err(DecodeError::UnknownRequiredFeature), } @@ -13171,23 +15902,28 @@ impl Readable for HTLCSource { impl Writeable for HTLCSource { fn write(&self, writer: &mut W) -> Result<(), crate::io::Error> { match self { - HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id } => { + HTLCSource::OutboundRoute { + ref session_priv, + ref first_hop_htlc_msat, + ref path, + payment_id, + } => { 0u8.write(writer)?; let payment_id_opt = Some(payment_id); write_tlv_fields!(writer, { - (0, session_priv, required), - (1, payment_id_opt, option), - (2, first_hop_htlc_msat, required), - // 3 was previously used to write a PaymentSecret for the payment. - (4, path.hops, required_vec), - (5, None::, option), // payment_params in LDK versions prior to 0.0.115 - (6, path.blinded_tail, option), - }); - } + (0, session_priv, required), + (1, payment_id_opt, option), + (2, first_hop_htlc_msat, required), + // 3 was previously used to write a PaymentSecret for the payment. + (4, path.hops, required_vec), + (5, None::, option), // payment_params in LDK versions prior to 0.0.115 + (6, path.blinded_tail, option), + }); + }, HTLCSource::PreviousHopData(ref field) => { 1u8.write(writer)?; field.write(writer)?; - } + }, } Ok(()) } @@ -13265,7 +16001,10 @@ impl Readable for HTLCForwardInfo { htlc_id: _init_tlv_based_struct_field!(htlc_id, required), err_packet: crate::ln::msgs::OnionErrorPacket { data: _init_tlv_based_struct_field!(err_packet, required), - attribution_data: _init_tlv_based_struct_field!(attribution_data, option), + attribution_data: _init_tlv_based_struct_field!( + attribution_data, + option + ), }, } } @@ -13283,7 +16022,17 @@ impl_writeable_tlv_based!(PendingInboundPayment, { (8, min_value_msat, required), }); -impl Writeable for ChannelManager +impl< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > Writeable for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -13319,7 +16068,8 @@ where serializable_peer_count += 1; } - number_of_funded_channels += peer_state.channel_by_id + number_of_funded_channels += peer_state + .channel_by_id .values() .filter_map(Channel::as_funded) .filter(|chan| chan.context.is_funding_broadcast()) @@ -13331,7 +16081,8 @@ where for (_, peer_state_mutex) in per_peer_state.iter() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - for channel in peer_state.channel_by_id + for channel in peer_state + .channel_by_id .values() .filter_map(Channel::as_funded) .filter(|channel| channel.context.is_funding_broadcast()) @@ -13360,7 +16111,8 @@ where } let claimable_payments = self.claimable_payments.lock().unwrap(); - let pending_outbound_payments = self.pending_outbound_payments.pending_outbound_payments.lock().unwrap(); + let pending_outbound_payments = + self.pending_outbound_payments.pending_outbound_payments.lock().unwrap(); let mut htlc_purposes: Vec<&events::PaymentPurpose> = Vec::new(); let mut htlc_onion_fields: Vec<&_> = Vec::new(); @@ -13449,12 +16201,12 @@ where num_pending_outbounds_compat.write(writer)?; for (_, outbound) in pending_outbound_payments.iter() { match outbound { - PendingOutboundPayment::Legacy { session_privs } | - PendingOutboundPayment::Retryable { session_privs, .. } => { + PendingOutboundPayment::Legacy { session_privs } + | PendingOutboundPayment::Retryable { session_privs, .. } => { for session_priv in session_privs.iter() { session_priv.write(writer)?; } - } + }, PendingOutboundPayment::AwaitingInvoice { .. } => {}, PendingOutboundPayment::AwaitingOffer { .. } => {}, PendingOutboundPayment::InvoiceReceived { .. } => {}, @@ -13465,11 +16217,12 @@ where } // Encode without retry info for 0.0.101 compatibility. - let mut pending_outbound_payments_no_retry: HashMap> = new_hash_map(); + let mut pending_outbound_payments_no_retry: HashMap> = + new_hash_map(); for (id, outbound) in pending_outbound_payments.iter() { match outbound { - PendingOutboundPayment::Legacy { session_privs } | - PendingOutboundPayment::Retryable { session_privs, .. } => { + PendingOutboundPayment::Legacy { session_privs } + | PendingOutboundPayment::Retryable { session_privs, .. } => { pending_outbound_payments_no_retry.insert(*id, session_privs.clone()); }, _ => {}, @@ -13489,14 +16242,21 @@ where pending_claiming_payments = None; } - let mut legacy_in_flight_monitor_updates: Option>> = None; - let mut in_flight_monitor_updates: Option>> = None; + let mut legacy_in_flight_monitor_updates: Option< + HashMap<(&PublicKey, &OutPoint), &Vec>, + > = None; + let mut in_flight_monitor_updates: Option< + HashMap<(&PublicKey, &ChannelId), &Vec>, + > = None; for ((counterparty_id, _), peer_state) in per_peer_state.iter().zip(peer_states.iter()) { - for (channel_id, (funding_txo, updates)) in peer_state.in_flight_monitor_updates.iter() { + for (channel_id, (funding_txo, updates)) in peer_state.in_flight_monitor_updates.iter() + { if !updates.is_empty() { - legacy_in_flight_monitor_updates.get_or_insert_with(|| new_hash_map()) + legacy_in_flight_monitor_updates + .get_or_insert_with(|| new_hash_map()) .insert((counterparty_id, funding_txo), updates); - in_flight_monitor_updates.get_or_insert_with(|| new_hash_map()) + in_flight_monitor_updates + .get_or_insert_with(|| new_hash_map()) .insert((counterparty_id, channel_id), updates); } } @@ -13531,7 +16291,8 @@ impl Writeable for VecDeque<(Event, Option)> { for (event, action) in self.iter() { event.write(w)?; action.write(w)?; - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { // Events are MaybeReadable, in some cases indicating that they shouldn't actually // be persisted and are regenerated on restart. However, if such an event has a // post-event-handling action we'll write nothing for the event and would have to @@ -13540,7 +16301,9 @@ impl Writeable for VecDeque<(Event, Option)> { let event_encoded = event.encode(); let event_read: Option = MaybeReadable::read(&mut &event_encoded[..]).unwrap(); - if action.is_some() { assert!(event_read.is_some()); } + if action.is_some() { + assert!(event_read.is_some()); + } } } Ok(()) @@ -13551,8 +16314,10 @@ impl Readable for VecDeque<(Event, Option)> { let len: u64 = Readable::read(reader)?; const MAX_ALLOC_SIZE: u64 = 1024 * 16; let mut events: Self = VecDeque::with_capacity(cmp::min( - MAX_ALLOC_SIZE/mem::size_of::<(events::Event, Option)>() as u64, - len) as usize); + MAX_ALLOC_SIZE + / mem::size_of::<(events::Event, Option)>() as u64, + len, + ) as usize); for _ in 0..len { let ev_opt = MaybeReadable::read(reader)?; let action = Readable::read(reader)?; @@ -13601,8 +16366,18 @@ impl Readable for VecDeque<(Event, Option)> { /// which you've already broadcasted the transaction. /// /// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor -pub struct ChannelManagerReadArgs<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> -where +pub struct ChannelManagerReadArgs< + 'a, + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, +> where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, ES::Target: EntropySource, @@ -13665,11 +16440,22 @@ where /// this struct. /// /// This is not exported to bindings users because we have no HashMap bindings - pub channel_monitors: HashMap::EcdsaSigner>>, + pub channel_monitors: + HashMap::EcdsaSigner>>, } -impl<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> - ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L> +impl< + 'a, + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L> where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -13691,10 +16477,18 @@ where mut channel_monitors: Vec<&'a ChannelMonitor<::EcdsaSigner>>, ) -> Self { Self { - entropy_source, node_signer, signer_provider, fee_estimator, chain_monitor, - tx_broadcaster, router, message_router, logger, default_config, + entropy_source, + node_signer, + signer_provider, + fee_estimator, + chain_monitor, + tx_broadcaster, + router, + message_router, + logger, + default_config, channel_monitors: hash_map_from_iter( - channel_monitors.drain(..).map(|monitor| { (monitor.channel_id(), monitor) }) + channel_monitors.drain(..).map(|monitor| (monitor.channel_id(), monitor)), ), } } @@ -13702,8 +16496,19 @@ where // Implement ReadableArgs for an Arc'd ChannelManager to make it a bit easier to work with the // SipmleArcChannelManager type: -impl<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> - ReadableArgs> for (BlockHash, Arc>) +impl< + 'a, + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > ReadableArgs> + for (BlockHash, Arc>) where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -13715,14 +16520,28 @@ where MR::Target: MessageRouter, L::Target: Logger, { - fn read(reader: &mut Reader, args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>) -> Result { - let (blockhash, chan_manager) = <(BlockHash, ChannelManager)>::read(reader, args)?; + fn read( + reader: &mut Reader, args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>, + ) -> Result { + let (blockhash, chan_manager) = + <(BlockHash, ChannelManager)>::read(reader, args)?; Ok((blockhash, Arc::new(chan_manager))) } } -impl<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> - ReadableArgs> for (BlockHash, ChannelManager) +impl< + 'a, + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, + > ReadableArgs> + for (BlockHash, ChannelManager) where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -13734,101 +16553,145 @@ where MR::Target: MessageRouter, L::Target: Logger, { - fn read(reader: &mut Reader, mut args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>) -> Result { + fn read( + reader: &mut Reader, mut args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, MR, L>, + ) -> Result { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let chain_hash: ChainHash = Readable::read(reader)?; let best_block_height: u32 = Readable::read(reader)?; let best_block_hash: BlockHash = Readable::read(reader)?; - let empty_peer_state = || { - PeerState { - channel_by_id: new_hash_map(), - inbound_channel_request_by_id: new_hash_map(), - latest_features: InitFeatures::empty(), - pending_msg_events: Vec::new(), - in_flight_monitor_updates: BTreeMap::new(), - monitor_update_blocked_actions: BTreeMap::new(), - actions_blocking_raa_monitor_updates: BTreeMap::new(), - closed_channel_monitor_update_ids: BTreeMap::new(), - peer_storage: Vec::new(), - is_connected: false, - } + let empty_peer_state = || PeerState { + channel_by_id: new_hash_map(), + inbound_channel_request_by_id: new_hash_map(), + latest_features: InitFeatures::empty(), + pending_msg_events: Vec::new(), + in_flight_monitor_updates: BTreeMap::new(), + monitor_update_blocked_actions: BTreeMap::new(), + actions_blocking_raa_monitor_updates: BTreeMap::new(), + closed_channel_monitor_update_ids: BTreeMap::new(), + peer_storage: Vec::new(), + is_connected: false, }; let mut failed_htlcs = Vec::new(); let channel_count: u64 = Readable::read(reader)?; let mut channel_id_set = hash_set_with_capacity(cmp::min(channel_count as usize, 128)); - let mut per_peer_state = hash_map_with_capacity(cmp::min(channel_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(PublicKey, Mutex>)>())); + let mut per_peer_state = hash_map_with_capacity(cmp::min( + channel_count as usize, + MAX_ALLOC_SIZE / mem::size_of::<(PublicKey, Mutex>)>(), + )); let mut short_to_chan_info = hash_map_with_capacity(cmp::min(channel_count as usize, 128)); let mut channel_closures = VecDeque::new(); let mut close_background_events = Vec::new(); for _ in 0..channel_count { - let mut channel: FundedChannel = FundedChannel::read(reader, ( - &args.entropy_source, &args.signer_provider, &provided_channel_type_features(&args.default_config) - ))?; + let mut channel: FundedChannel = FundedChannel::read( + reader, + ( + &args.entropy_source, + &args.signer_provider, + &provided_channel_type_features(&args.default_config), + ), + )?; let logger = WithChannelContext::from(&args.logger, &channel.context, None); let channel_id = channel.context.channel_id(); channel_id_set.insert(channel_id); if let Some(ref mut monitor) = args.channel_monitors.get_mut(&channel_id) { - if channel.get_cur_holder_commitment_transaction_number() > monitor.get_cur_holder_commitment_number() || - channel.get_revoked_counterparty_commitment_transaction_number() > monitor.get_min_seen_secret() || - channel.get_cur_counterparty_commitment_transaction_number() > monitor.get_cur_counterparty_commitment_number() || - channel.context.get_latest_monitor_update_id() < monitor.get_latest_update_id() { + if channel.get_cur_holder_commitment_transaction_number() + > monitor.get_cur_holder_commitment_number() + || channel.get_revoked_counterparty_commitment_transaction_number() + > monitor.get_min_seen_secret() + || channel.get_cur_counterparty_commitment_transaction_number() + > monitor.get_cur_counterparty_commitment_number() + || channel.context.get_latest_monitor_update_id() + < monitor.get_latest_update_id() + { // But if the channel is behind of the monitor, close the channel: - log_error!(logger, "A ChannelManager is stale compared to the current ChannelMonitor!"); + log_error!( + logger, + "A ChannelManager is stale compared to the current ChannelMonitor!" + ); log_error!(logger, " The channel will be force-closed and the latest commitment transaction from the ChannelMonitor broadcast."); - if channel.context.get_latest_monitor_update_id() < monitor.get_latest_update_id() { + if channel.context.get_latest_monitor_update_id() + < monitor.get_latest_update_id() + { log_error!(logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.", &channel.context.channel_id(), monitor.get_latest_update_id(), channel.context.get_latest_monitor_update_id()); } - if channel.get_cur_holder_commitment_transaction_number() > monitor.get_cur_holder_commitment_number() { + if channel.get_cur_holder_commitment_transaction_number() + > monitor.get_cur_holder_commitment_number() + { log_error!(logger, " The ChannelMonitor for channel {} is at holder commitment number {} but the ChannelManager is at holder commitment number {}.", &channel.context.channel_id(), monitor.get_cur_holder_commitment_number(), channel.get_cur_holder_commitment_transaction_number()); } - if channel.get_revoked_counterparty_commitment_transaction_number() > monitor.get_min_seen_secret() { + if channel.get_revoked_counterparty_commitment_transaction_number() + > monitor.get_min_seen_secret() + { log_error!(logger, " The ChannelMonitor for channel {} is at revoked counterparty transaction number {} but the ChannelManager is at revoked counterparty transaction number {}.", &channel.context.channel_id(), monitor.get_min_seen_secret(), channel.get_revoked_counterparty_commitment_transaction_number()); } - if channel.get_cur_counterparty_commitment_transaction_number() > monitor.get_cur_counterparty_commitment_number() { + if channel.get_cur_counterparty_commitment_transaction_number() + > monitor.get_cur_counterparty_commitment_number() + { log_error!(logger, " The ChannelMonitor for channel {} is at counterparty commitment transaction number {} but the ChannelManager is at counterparty commitment transaction number {}.", &channel.context.channel_id(), monitor.get_cur_counterparty_commitment_number(), channel.get_cur_counterparty_commitment_transaction_number()); } - let mut shutdown_result = channel.context.force_shutdown(&channel.funding, true, ClosureReason::OutdatedChannelManager); + let mut shutdown_result = channel.context.force_shutdown( + &channel.funding, + true, + ClosureReason::OutdatedChannelManager, + ); if shutdown_result.unbroadcasted_batch_funding_txid.is_some() { return Err(DecodeError::InvalidValue); } - if let Some((counterparty_node_id, funding_txo, channel_id, mut update)) = shutdown_result.monitor_update { + if let Some((counterparty_node_id, funding_txo, channel_id, mut update)) = + shutdown_result.monitor_update + { // Our channel information is out of sync with the `ChannelMonitor`, so // force the update to use the `ChannelMonitor`'s update_id for the close // update. let latest_update_id = monitor.get_latest_update_id().saturating_add(1); update.update_id = latest_update_id; - per_peer_state.entry(counterparty_node_id) + per_peer_state + .entry(counterparty_node_id) .or_insert_with(|| Mutex::new(empty_peer_state())) - .lock().unwrap() - .closed_channel_monitor_update_ids.entry(channel_id) - .and_modify(|v| *v = cmp::max(latest_update_id, *v)) - .or_insert(latest_update_id); + .lock() + .unwrap() + .closed_channel_monitor_update_ids + .entry(channel_id) + .and_modify(|v| *v = cmp::max(latest_update_id, *v)) + .or_insert(latest_update_id); - close_background_events.push(BackgroundEvent::MonitorUpdateRegeneratedOnStartup { - counterparty_node_id, funding_txo, channel_id, update - }); + close_background_events.push( + BackgroundEvent::MonitorUpdateRegeneratedOnStartup { + counterparty_node_id, + funding_txo, + channel_id, + update, + }, + ); } failed_htlcs.append(&mut shutdown_result.dropped_outbound_htlcs); - channel_closures.push_back((events::Event::ChannelClosed { - channel_id: channel.context.channel_id(), - user_channel_id: channel.context.get_user_id(), - reason: ClosureReason::OutdatedChannelManager, - counterparty_node_id: Some(channel.context.get_counterparty_node_id()), - channel_capacity_sats: Some(channel.funding.get_value_satoshis()), - channel_funding_txo: channel.funding.get_funding_txo(), - last_local_balance_msat: Some(channel.funding.get_value_to_self_msat()), - }, None)); + channel_closures.push_back(( + events::Event::ChannelClosed { + channel_id: channel.context.channel_id(), + user_channel_id: channel.context.get_user_id(), + reason: ClosureReason::OutdatedChannelManager, + counterparty_node_id: Some(channel.context.get_counterparty_node_id()), + channel_capacity_sats: Some(channel.funding.get_value_satoshis()), + channel_funding_txo: channel.funding.get_funding_txo(), + last_local_balance_msat: Some(channel.funding.get_value_to_self_msat()), + }, + None, + )); for (channel_htlc_source, payment_hash) in channel.inflight_htlc_sources() { let mut found_htlc = false; for (monitor_htlc_source, _) in monitor.get_all_current_outbound_htlcs() { - if *channel_htlc_source == monitor_htlc_source { found_htlc = true; break; } + if *channel_htlc_source == monitor_htlc_source { + found_htlc = true; + break; + } } if !found_htlc { // If we have some HTLCs in the channel which are not present in the newer @@ -13838,45 +16701,80 @@ where // claim update ChannelMonitor updates were persisted prior to persising // the ChannelMonitor update for the forward leg, so attempting to fail the // backwards leg of the HTLC will simply be rejected. - let logger = WithChannelContext::from(&args.logger, &channel.context, Some(*payment_hash)); + let logger = WithChannelContext::from( + &args.logger, + &channel.context, + Some(*payment_hash), + ); log_info!(logger, "Failing HTLC with hash {} as it is missing in the ChannelMonitor for channel {} but was present in the (stale) ChannelManager", &channel.context.channel_id(), &payment_hash); - failed_htlcs.push((channel_htlc_source.clone(), *payment_hash, channel.context.get_counterparty_node_id(), channel.context.channel_id())); + failed_htlcs.push(( + channel_htlc_source.clone(), + *payment_hash, + channel.context.get_counterparty_node_id(), + channel.context.channel_id(), + )); } } } else { - channel.on_startup_drop_completed_blocked_mon_updates_through(&logger, monitor.get_latest_update_id()); + channel.on_startup_drop_completed_blocked_mon_updates_through( + &logger, + monitor.get_latest_update_id(), + ); log_info!(logger, "Successfully loaded channel {} at update_id {} against monitor at update id {} with {} blocked updates", &channel.context.channel_id(), channel.context.get_latest_monitor_update_id(), monitor.get_latest_update_id(), channel.blocked_monitor_updates_pending()); if let Some(short_channel_id) = channel.context.get_short_channel_id() { - short_to_chan_info.insert(short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id())); + short_to_chan_info.insert( + short_channel_id, + ( + channel.context.get_counterparty_node_id(), + channel.context.channel_id(), + ), + ); } - per_peer_state.entry(channel.context.get_counterparty_node_id()) + per_peer_state + .entry(channel.context.get_counterparty_node_id()) .or_insert_with(|| Mutex::new(empty_peer_state())) - .get_mut().unwrap() - .channel_by_id.insert(channel.context.channel_id(), Channel::from(channel)); + .get_mut() + .unwrap() + .channel_by_id + .insert(channel.context.channel_id(), Channel::from(channel)); } } else if channel.is_awaiting_initial_mon_persist() { // If we were persisted and shut down while the initial ChannelMonitor persistence // was in-progress, we never broadcasted the funding transaction and can still // safely discard the channel. - let _ = channel.context.force_shutdown(&channel.funding, false, ClosureReason::DisconnectedPeer); - channel_closures.push_back((events::Event::ChannelClosed { - channel_id: channel.context.channel_id(), - user_channel_id: channel.context.get_user_id(), - reason: ClosureReason::DisconnectedPeer, - counterparty_node_id: Some(channel.context.get_counterparty_node_id()), - channel_capacity_sats: Some(channel.funding.get_value_satoshis()), - channel_funding_txo: channel.funding.get_funding_txo(), - last_local_balance_msat: Some(channel.funding.get_value_to_self_msat()), - }, None)); + let _ = channel.context.force_shutdown( + &channel.funding, + false, + ClosureReason::DisconnectedPeer, + ); + channel_closures.push_back(( + events::Event::ChannelClosed { + channel_id: channel.context.channel_id(), + user_channel_id: channel.context.get_user_id(), + reason: ClosureReason::DisconnectedPeer, + counterparty_node_id: Some(channel.context.get_counterparty_node_id()), + channel_capacity_sats: Some(channel.funding.get_value_satoshis()), + channel_funding_txo: channel.funding.get_funding_txo(), + last_local_balance_msat: Some(channel.funding.get_value_to_self_msat()), + }, + None, + )); } else { - log_error!(logger, "Missing ChannelMonitor for channel {} needed by ChannelManager.", &channel.context.channel_id()); + log_error!( + logger, + "Missing ChannelMonitor for channel {} needed by ChannelManager.", + &channel.context.channel_id() + ); log_error!(logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,"); log_error!(logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!"); - log_error!(logger, " Without the ChannelMonitor we cannot continue without risking funds."); + log_error!( + logger, + " Without the ChannelMonitor we cannot continue without risking funds." + ); log_error!(logger, " Please ensure the chain::Watch API requirements are met and file a bug report at https://github.com/lightningdevkit/rust-lightning"); return Err(DecodeError::InvalidValue); } @@ -13899,12 +16797,15 @@ where if should_queue_fc_update { latest_update_id += 1; } - per_peer_state.entry(counterparty_node_id) + per_peer_state + .entry(counterparty_node_id) .or_insert_with(|| Mutex::new(empty_peer_state())) - .lock().unwrap() - .closed_channel_monitor_update_ids.entry(monitor.channel_id()) - .and_modify(|v| *v = cmp::max(latest_update_id, *v)) - .or_insert(latest_update_id); + .lock() + .unwrap() + .closed_channel_monitor_update_ids + .entry(monitor.channel_id()) + .and_modify(|v| *v = cmp::max(latest_update_id, *v)) + .or_insert(latest_update_id); } if !should_queue_fc_update { @@ -13913,11 +16814,16 @@ where let logger = WithChannelMonitor::from(&args.logger, monitor, None); let channel_id = monitor.channel_id(); - log_info!(logger, "Queueing monitor update to ensure missing channel {} is force closed", - &channel_id); + log_info!( + logger, + "Queueing monitor update to ensure missing channel {} is force closed", + &channel_id + ); let monitor_update = ChannelMonitorUpdate { update_id: monitor.get_latest_update_id().saturating_add(1), - updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast: true }], + updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { + should_broadcast: true, + }], channel_id: Some(monitor.channel_id()), }; let funding_txo = monitor.get_funding_txo(); @@ -13937,7 +16843,10 @@ where for _ in 0..forward_htlcs_count { let short_channel_id = Readable::read(reader)?; let pending_forwards_count: u64 = Readable::read(reader)?; - let mut pending_forwards = Vec::with_capacity(cmp::min(pending_forwards_count as usize, MAX_ALLOC_SIZE/mem::size_of::())); + let mut pending_forwards = Vec::with_capacity(cmp::min( + pending_forwards_count as usize, + MAX_ALLOC_SIZE / mem::size_of::(), + )); for _ in 0..pending_forwards_count { pending_forwards.push(Readable::read(reader)?); } @@ -13945,11 +16854,15 @@ where } let claimable_htlcs_count: u64 = Readable::read(reader)?; - let mut claimable_htlcs_list = Vec::with_capacity(cmp::min(claimable_htlcs_count as usize, 128)); + let mut claimable_htlcs_list = + Vec::with_capacity(cmp::min(claimable_htlcs_count as usize, 128)); for _ in 0..claimable_htlcs_count { let payment_hash = Readable::read(reader)?; let previous_hops_len: u64 = Readable::read(reader)?; - let mut previous_hops = Vec::with_capacity(cmp::min(previous_hops_len as usize, MAX_ALLOC_SIZE/mem::size_of::())); + let mut previous_hops = Vec::with_capacity(cmp::min( + previous_hops_len as usize, + MAX_ALLOC_SIZE / mem::size_of::(), + )); for _ in 0..previous_hops_len { previous_hops.push(::read(reader)?); } @@ -13967,7 +16880,10 @@ where let event_count: u64 = Readable::read(reader)?; let mut pending_events_read: VecDeque<(events::Event, Option)> = - VecDeque::with_capacity(cmp::min(event_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(events::Event, Option)>())); + VecDeque::with_capacity(cmp::min( + event_count as usize, + MAX_ALLOC_SIZE / mem::size_of::<(events::Event, Option)>(), + )); for _ in 0..event_count { match MaybeReadable::read(reader)? { Some(event) => pending_events_read.push_back((event, None)), @@ -13984,7 +16900,7 @@ where // on-startup monitor updates. let _: OutPoint = Readable::read(reader)?; let _: ChannelMonitorUpdate = Readable::read(reader)?; - } + }, _ => return Err(DecodeError::InvalidValue), } } @@ -13998,38 +16914,53 @@ where let payment_hash: PaymentHash = Readable::read(reader)?; let logger = WithContext::from(&args.logger, None, None, Some(payment_hash)); let inbound: PendingInboundPayment = Readable::read(reader)?; - log_warn!(logger, "Ignoring deprecated pending inbound payment with payment hash {}: {:?}", payment_hash, inbound); + log_warn!( + logger, + "Ignoring deprecated pending inbound payment with payment hash {}: {:?}", + payment_hash, + inbound + ); } let pending_outbound_payments_count_compat: u64 = Readable::read(reader)?; let mut pending_outbound_payments_compat: HashMap = - hash_map_with_capacity(cmp::min(pending_outbound_payments_count_compat as usize, MAX_ALLOC_SIZE/32)); + hash_map_with_capacity(cmp::min( + pending_outbound_payments_count_compat as usize, + MAX_ALLOC_SIZE / 32, + )); for _ in 0..pending_outbound_payments_count_compat { let session_priv = Readable::read(reader)?; let payment = PendingOutboundPayment::Legacy { session_privs: hash_set_from_iter([session_priv]), }; if pending_outbound_payments_compat.insert(PaymentId(session_priv), payment).is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); }; } // pending_outbound_payments_no_retry is for compatibility with 0.0.101 clients. - let mut pending_outbound_payments_no_retry: Option>> = None; + let mut pending_outbound_payments_no_retry: Option>> = + None; let mut pending_outbound_payments = None; - let mut pending_intercepted_htlcs: Option> = Some(new_hash_map()); + let mut pending_intercepted_htlcs: Option> = + Some(new_hash_map()); let mut received_network_pubkey: Option = None; let mut fake_scid_rand_bytes: Option<[u8; 32]> = None; let mut probing_cookie_secret: Option<[u8; 32]> = None; let mut claimable_htlc_purposes = None; let mut claimable_htlc_onion_fields = None; let mut pending_claiming_payments = Some(new_hash_map()); - let mut monitor_update_blocked_actions_per_peer: Option>)>> = Some(Vec::new()); + let mut monitor_update_blocked_actions_per_peer: Option>)>> = + Some(Vec::new()); let mut events_override = None; - let mut legacy_in_flight_monitor_updates: Option>> = None; + let mut legacy_in_flight_monitor_updates: Option< + HashMap<(PublicKey, OutPoint), Vec>, + > = None; // We use this one over the legacy since they represent the same data, just with a different // key. We still need to read the legacy one as it's an even TLV. - let mut in_flight_monitor_updates: Option>> = None; + let mut in_flight_monitor_updates: Option< + HashMap<(PublicKey, ChannelId), Vec>, + > = None; let mut decode_update_add_htlcs: Option>> = None; let mut inbound_payment_id_secret = None; let mut peer_storage_dir: Option)>> = None; @@ -14097,7 +17028,8 @@ where return Err(DecodeError::InvalidValue); } if in_flight_monitor_updates.is_none() { - let in_flight_upds = in_flight_monitor_updates.get_or_insert_with(|| new_hash_map()); + let in_flight_upds = + in_flight_monitor_updates.get_or_insert_with(|| new_hash_map()); for ((counterparty_node_id, funding_txo), updates) in legacy_in_flight_upds { // All channels with legacy in flight monitor updates are v1 channels. let channel_id = ChannelId::v1_from_funding_outpoint(funding_txo); @@ -14126,42 +17058,56 @@ where macro_rules! handle_in_flight_updates { ($counterparty_node_id: expr, $chan_in_flight_upds: expr, $monitor: expr, $peer_state: expr, $logger: expr, $channel_info_log: expr - ) => { { + ) => {{ let mut max_in_flight_update_id = 0; $chan_in_flight_upds.retain(|upd| upd.update_id > $monitor.get_latest_update_id()); let funding_txo = $monitor.get_funding_txo(); for update in $chan_in_flight_upds.iter() { - log_trace!($logger, "Replaying ChannelMonitorUpdate {} for {}channel {}", - update.update_id, $channel_info_log, &$monitor.channel_id()); + log_trace!( + $logger, + "Replaying ChannelMonitorUpdate {} for {}channel {}", + update.update_id, + $channel_info_log, + &$monitor.channel_id() + ); max_in_flight_update_id = cmp::max(max_in_flight_update_id, update.update_id); pending_background_events.push( BackgroundEvent::MonitorUpdateRegeneratedOnStartup { counterparty_node_id: $counterparty_node_id, - funding_txo: funding_txo, + funding_txo, channel_id: $monitor.channel_id(), update: update.clone(), - }); + }, + ); } if $chan_in_flight_upds.is_empty() { // We had some updates to apply, but it turns out they had completed before we // were serialized, we just weren't notified of that. Thus, we may have to run // the completion actions for any monitor updates, but otherwise are done. - pending_background_events.push( - BackgroundEvent::MonitorUpdatesComplete { - counterparty_node_id: $counterparty_node_id, - channel_id: $monitor.channel_id(), - }); + pending_background_events.push(BackgroundEvent::MonitorUpdatesComplete { + counterparty_node_id: $counterparty_node_id, + channel_id: $monitor.channel_id(), + }); } else { - $peer_state.closed_channel_monitor_update_ids.entry($monitor.channel_id()) + $peer_state + .closed_channel_monitor_update_ids + .entry($monitor.channel_id()) .and_modify(|v| *v = cmp::max(max_in_flight_update_id, *v)) .or_insert(max_in_flight_update_id); } - if $peer_state.in_flight_monitor_updates.insert($monitor.channel_id(), (funding_txo, $chan_in_flight_upds)).is_some() { - log_error!($logger, "Duplicate in-flight monitor update set for the same channel!"); + if $peer_state + .in_flight_monitor_updates + .insert($monitor.channel_id(), (funding_txo, $chan_in_flight_upds)) + .is_some() + { + log_error!( + $logger, + "Duplicate in-flight monitor update set for the same channel!" + ); return Err(DecodeError::InvalidValue); } max_in_flight_update_id - } } + }}; } for (counterparty_id, peer_state_mtx) in per_peer_state.iter_mut() { @@ -14173,22 +17119,40 @@ where // Channels that were persisted have to be funded, otherwise they should have been // discarded. - let monitor = args.channel_monitors.get(chan_id) + let monitor = args + .channel_monitors + .get(chan_id) .expect("We already checked for monitor presence when loading channels"); let mut max_in_flight_update_id = monitor.get_latest_update_id(); if let Some(in_flight_upds) = &mut in_flight_monitor_updates { - if let Some(mut chan_in_flight_upds) = in_flight_upds.remove(&(*counterparty_id, *chan_id)) { - max_in_flight_update_id = cmp::max(max_in_flight_update_id, - handle_in_flight_updates!(*counterparty_id, chan_in_flight_upds, - monitor, peer_state, logger, "")); + if let Some(mut chan_in_flight_upds) = + in_flight_upds.remove(&(*counterparty_id, *chan_id)) + { + max_in_flight_update_id = cmp::max( + max_in_flight_update_id, + handle_in_flight_updates!( + *counterparty_id, + chan_in_flight_upds, + monitor, + peer_state, + logger, + "" + ), + ); } } - if funded_chan.get_latest_unblocked_monitor_update_id() > max_in_flight_update_id { + if funded_chan.get_latest_unblocked_monitor_update_id() + > max_in_flight_update_id + { // If the channel is ahead of the monitor, return DangerousValue: log_error!(logger, "A ChannelMonitor is stale compared to the current ChannelManager! This indicates a potentially-critical violation of the chain::Watch API!"); log_error!(logger, " The ChannelMonitor for channel {} is at update_id {} with update_id through {} in-flight", chan_id, monitor.get_latest_update_id(), max_in_flight_update_id); - log_error!(logger, " but the ChannelManager is at update_id {}.", funded_chan.get_latest_unblocked_monitor_update_id()); + log_error!( + logger, + " but the ChannelManager is at update_id {}.", + funded_chan.get_latest_unblocked_monitor_update_id() + ); log_error!(logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,"); log_error!(logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!"); log_error!(logger, " Without the latest ChannelMonitor we cannot continue without risking funds."); @@ -14206,25 +17170,40 @@ where if let Some(in_flight_upds) = in_flight_monitor_updates { for ((counterparty_id, channel_id), mut chan_in_flight_updates) in in_flight_upds { - let logger = WithContext::from(&args.logger, Some(counterparty_id), Some(channel_id), None); + let logger = + WithContext::from(&args.logger, Some(counterparty_id), Some(channel_id), None); if let Some(monitor) = args.channel_monitors.get(&channel_id) { // Now that we've removed all the in-flight monitor updates for channels that are // still open, we need to replay any monitor updates that are for closed channels, // creating the neccessary peer_state entries as we go. - let peer_state_mutex = per_peer_state.entry(counterparty_id).or_insert_with(|| { - Mutex::new(empty_peer_state()) - }); + let peer_state_mutex = per_peer_state + .entry(counterparty_id) + .or_insert_with(|| Mutex::new(empty_peer_state())); let mut peer_state = peer_state_mutex.lock().unwrap(); - handle_in_flight_updates!(counterparty_id, chan_in_flight_updates, monitor, - peer_state, logger, "closed "); + handle_in_flight_updates!( + counterparty_id, + chan_in_flight_updates, + monitor, + peer_state, + logger, + "closed " + ); } else { log_error!(logger, "A ChannelMonitor is missing even though we have in-flight updates for it! This indicates a potentially-critical violation of the chain::Watch API!"); - log_error!(logger, " The ChannelMonitor for channel {} is missing.", channel_id); + log_error!( + logger, + " The ChannelMonitor for channel {} is missing.", + channel_id + ); log_error!(logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,"); log_error!(logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!"); log_error!(logger, " Without the latest ChannelMonitor we cannot continue without risking funds."); log_error!(logger, " Please ensure the chain::Watch API requirements are met and file a bug report at https://github.com/lightningdevkit/rust-lightning"); - log_error!(logger, " Pending in-flight updates are: {:?}", chan_in_flight_updates); + log_error!( + logger, + " Pending in-flight updates are: {:?}", + chan_in_flight_updates + ); return Err(DecodeError::InvalidValue); } } @@ -14235,22 +17214,34 @@ where pending_background_events.reserve(close_background_events.len()); 'each_bg_event: for mut new_event in close_background_events { if let BackgroundEvent::MonitorUpdateRegeneratedOnStartup { - counterparty_node_id, funding_txo, channel_id, update, - } = &mut new_event { + counterparty_node_id, + funding_txo, + channel_id, + update, + } = &mut new_event + { debug_assert_eq!(update.updates.len(), 1); - debug_assert!(matches!(update.updates[0], ChannelMonitorUpdateStep::ChannelForceClosed { .. })); + debug_assert!(matches!( + update.updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); let mut updated_id = false; for pending_event in pending_background_events.iter() { if let BackgroundEvent::MonitorUpdateRegeneratedOnStartup { - counterparty_node_id: pending_cp, funding_txo: pending_funding, - channel_id: pending_chan_id, update: pending_update, - } = pending_event { + counterparty_node_id: pending_cp, + funding_txo: pending_funding, + channel_id: pending_chan_id, + update: pending_update, + } = pending_event + { let for_same_channel = counterparty_node_id == pending_cp && funding_txo == pending_funding && channel_id == pending_chan_id; if for_same_channel { debug_assert!(update.update_id >= pending_update.update_id); - if pending_update.updates.iter().any(|upd| matches!(upd, ChannelMonitorUpdateStep::ChannelForceClosed { .. })) { + if pending_update.updates.iter().any(|upd| { + matches!(upd, ChannelMonitorUpdateStep::ChannelForceClosed { .. }) + }) { // If the background event we're looking at is just // force-closing the channel which already has a pending // force-close update, no need to duplicate it. @@ -14261,18 +17252,23 @@ where } } } - let mut per_peer_state = per_peer_state.get(counterparty_node_id) + let mut per_peer_state = per_peer_state + .get(counterparty_node_id) .expect("If we have pending updates for a channel it must have an entry") - .lock().unwrap(); + .lock() + .unwrap(); if updated_id { per_peer_state - .closed_channel_monitor_update_ids.entry(*channel_id) + .closed_channel_monitor_update_ids + .entry(*channel_id) .and_modify(|v| *v = cmp::max(update.update_id, *v)) .or_insert(update.update_id); } - let in_flight_updates = &mut per_peer_state.in_flight_monitor_updates + let in_flight_updates = &mut per_peer_state + .in_flight_monitor_updates .entry(*channel_id) - .or_insert_with(|| (*funding_txo, Vec::new())).1; + .or_insert_with(|| (*funding_txo, Vec::new())) + .1; debug_assert!(!in_flight_updates.iter().any(|upd| upd == update)); in_flight_updates.push(update.clone()); } @@ -14303,9 +17299,17 @@ where } if is_channel_closed { - for (htlc_source, (htlc, _)) in monitor.get_pending_or_resolved_outbound_htlcs() { - let logger = WithChannelMonitor::from(&args.logger, monitor, Some(htlc.payment_hash)); - if let HTLCSource::OutboundRoute { payment_id, session_priv, path, .. } = htlc_source { + for (htlc_source, (htlc, _)) in monitor.get_pending_or_resolved_outbound_htlcs() + { + let logger = WithChannelMonitor::from( + &args.logger, + monitor, + Some(htlc.payment_hash), + ); + if let HTLCSource::OutboundRoute { + payment_id, session_priv, path, .. + } = htlc_source + { if path.hops.is_empty() { log_error!(logger, "Got an empty path for a pending payment"); return Err(DecodeError::InvalidValue); @@ -14314,17 +17318,28 @@ where let mut session_priv_bytes = [0; 32]; session_priv_bytes[..].copy_from_slice(&session_priv[..]); pending_outbounds.insert_from_monitor_on_startup( - payment_id, htlc.payment_hash, session_priv_bytes, &path, best_block_height, logger + payment_id, + htlc.payment_hash, + session_priv_bytes, + &path, + best_block_height, + logger, ); } } - for (htlc_source, (htlc, preimage_opt)) in monitor.get_all_current_outbound_htlcs() { - let logger = WithChannelMonitor::from(&args.logger, monitor, Some(htlc.payment_hash)); + for (htlc_source, (htlc, preimage_opt)) in + monitor.get_all_current_outbound_htlcs() + { + let logger = WithChannelMonitor::from( + &args.logger, + monitor, + Some(htlc.payment_hash), + ); match htlc_source { HTLCSource::PreviousHopData(prev_hop_data) => { let pending_forward_matches_htlc = |info: &PendingAddHTLCInfo| { - info.prev_funding_outpoint == prev_hop_data.outpoint && - info.prev_htlc_id == prev_hop_data.htlc_id + info.prev_funding_outpoint == prev_hop_data.outpoint + && info.prev_htlc_id == prev_hop_data.htlc_id }; // The ChannelMonitor is now responsible for this HTLC's // failure/success and will let us know what its outcome is. If we @@ -14368,7 +17383,9 @@ where } else { true } }); }, - HTLCSource::OutboundRoute { payment_id, session_priv, path, .. } => { + HTLCSource::OutboundRoute { + payment_id, session_priv, path, .. + } => { if let Some(preimage) = preimage_opt { let pending_events = Mutex::new(pending_events_read); // Note that we set `from_onchain` to "false" here, @@ -14385,8 +17402,16 @@ where channel_id: monitor.channel_id(), counterparty_node_id: path.hops[0].pubkey, }; - pending_outbounds.claim_htlc(payment_id, preimage, session_priv, - path, false, compl_action, &pending_events, &&logger); + pending_outbounds.claim_htlc( + payment_id, + preimage, + session_priv, + path, + false, + compl_action, + &pending_events, + &&logger, + ); pending_events_read = pending_events.into_inner().unwrap(); } }, @@ -14509,15 +17534,19 @@ where } } - if !forward_htlcs.is_empty() || !decode_update_add_htlcs.is_empty() || pending_outbounds.needs_abandon() { + if !forward_htlcs.is_empty() + || !decode_update_add_htlcs.is_empty() + || pending_outbounds.needs_abandon() + { // If we have pending HTLCs to forward, assume we either dropped a // `PendingHTLCsForwardable` or the user received it but never processed it as they // shut down before the timer hit. Either way, set the time_forwardable to a small // constant as enough time has likely passed that we should simply handle the forwards // now, or at least after the user gets a chance to reconnect to our peers. - pending_events_read.push_back((events::Event::PendingHTLCsForwardable { - time_forwardable: Duration::from_secs(2), - }, None)); + pending_events_read.push_back(( + events::Event::PendingHTLCsForwardable { time_forwardable: Duration::from_secs(2) }, + None, + )); } let expanded_inbound_key = args.node_signer.get_inbound_payment_key(); @@ -14531,20 +17560,29 @@ where if onion_fields.len() != claimable_htlcs_list.len() { return Err(DecodeError::InvalidValue); } - for (purpose, (onion, (payment_hash, htlcs))) in - purposes.into_iter().zip(onion_fields.into_iter().zip(claimable_htlcs_list.into_iter())) + for (purpose, (onion, (payment_hash, htlcs))) in purposes + .into_iter() + .zip(onion_fields.into_iter().zip(claimable_htlcs_list.into_iter())) { - let existing_payment = claimable_payments.insert(payment_hash, ClaimablePayment { - purpose, htlcs, onion_fields: onion, - }); - if existing_payment.is_some() { return Err(DecodeError::InvalidValue); } + let existing_payment = claimable_payments.insert( + payment_hash, + ClaimablePayment { purpose, htlcs, onion_fields: onion }, + ); + if existing_payment.is_some() { + return Err(DecodeError::InvalidValue); + } } } else { - for (purpose, (payment_hash, htlcs)) in purposes.into_iter().zip(claimable_htlcs_list.into_iter()) { - let existing_payment = claimable_payments.insert(payment_hash, ClaimablePayment { - purpose, htlcs, onion_fields: None, - }); - if existing_payment.is_some() { return Err(DecodeError::InvalidValue); } + for (purpose, (payment_hash, htlcs)) in + purposes.into_iter().zip(claimable_htlcs_list.into_iter()) + { + let existing_payment = claimable_payments.insert( + payment_hash, + ClaimablePayment { purpose, htlcs, onion_fields: None }, + ); + if existing_payment.is_some() { + return Err(DecodeError::InvalidValue); + } } } } else { @@ -14558,26 +17596,31 @@ where OnionPayload::Invoice { _legacy_hop_data } => { if let Some(hop_data) = _legacy_hop_data { events::PaymentPurpose::Bolt11InvoicePayment { - payment_preimage: - match inbound_payment::verify( - payment_hash, &hop_data, 0, &expanded_inbound_key, &args.logger - ) { - Ok((payment_preimage, _)) => payment_preimage, - Err(()) => { - log_error!(args.logger, "Failed to read claimable payment data for HTLC with payment hash {} - was not a pending inbound payment and didn't match our payment key", &payment_hash); - return Err(DecodeError::InvalidValue); - } + payment_preimage: match inbound_payment::verify( + payment_hash, + &hop_data, + 0, + &expanded_inbound_key, + &args.logger, + ) { + Ok((payment_preimage, _)) => payment_preimage, + Err(()) => { + log_error!(args.logger, "Failed to read claimable payment data for HTLC with payment hash {} - was not a pending inbound payment and didn't match our payment key", &payment_hash); + return Err(DecodeError::InvalidValue); }, + }, payment_secret: hop_data.payment_secret, } - } else { return Err(DecodeError::InvalidValue); } + } else { + return Err(DecodeError::InvalidValue); + } + }, + OnionPayload::Spontaneous(payment_preimage) => { + events::PaymentPurpose::SpontaneousPayment(*payment_preimage) }, - OnionPayload::Spontaneous(payment_preimage) => - events::PaymentPurpose::SpontaneousPayment(*payment_preimage), }; - claimable_payments.insert(payment_hash, ClaimablePayment { - purpose, htlcs, onion_fields: None, - }); + claimable_payments + .insert(payment_hash, ClaimablePayment { purpose, htlcs, onion_fields: None }); } } @@ -14613,7 +17656,7 @@ where let our_network_pubkey = match args.node_signer.get_node_id(Recipient::Node) { Ok(key) => key, - Err(()) => return Err(DecodeError::InvalidValue) + Err(()) => return Err(DecodeError::InvalidValue), }; if let Some(network_pubkey) = received_network_pubkey { if network_pubkey != our_network_pubkey { @@ -14633,21 +17676,44 @@ where let mut outbound_scid_alias; loop { outbound_scid_alias = fake_scid::Namespace::OutboundAlias - .get_fake_scid(best_block_height, &chain_hash, fake_scid_rand_bytes.as_ref().unwrap(), &args.entropy_source); - if outbound_scid_aliases.insert(outbound_scid_alias) { break; } + .get_fake_scid( + best_block_height, + &chain_hash, + fake_scid_rand_bytes.as_ref().unwrap(), + &args.entropy_source, + ); + if outbound_scid_aliases.insert(outbound_scid_alias) { + break; + } } funded_chan.context.set_outbound_scid_alias(outbound_scid_alias); - } else if !outbound_scid_aliases.insert(funded_chan.context.outbound_scid_alias()) { + } else if !outbound_scid_aliases + .insert(funded_chan.context.outbound_scid_alias()) + { // Note that in rare cases its possible to hit this while reading an older // channel if we just happened to pick a colliding outbound alias above. - log_error!(logger, "Got duplicate outbound SCID alias; {}", funded_chan.context.outbound_scid_alias()); + log_error!( + logger, + "Got duplicate outbound SCID alias; {}", + funded_chan.context.outbound_scid_alias() + ); return Err(DecodeError::InvalidValue); } if funded_chan.context.is_usable() { - if short_to_chan_info.insert(funded_chan.context.outbound_scid_alias(), (funded_chan.context.get_counterparty_node_id(), *chan_id)).is_some() { + if short_to_chan_info + .insert( + funded_chan.context.outbound_scid_alias(), + (funded_chan.context.get_counterparty_node_id(), *chan_id), + ) + .is_some() + { // Note that in rare cases its possible to hit this while reading an older // channel if we just happened to pick a colliding outbound alias above. - log_error!(logger, "Got duplicate outbound SCID alias; {}", funded_chan.context.outbound_scid_alias()); + log_error!( + logger, + "Got duplicate outbound SCID alias; {}", + funded_chan.context.outbound_scid_alias() + ); return Err(DecodeError::InvalidValue); } } @@ -14662,10 +17728,13 @@ where let bounded_fee_estimator = LowerBoundedFeeEstimator::new(args.fee_estimator); - for (node_id, monitor_update_blocked_actions) in monitor_update_blocked_actions_per_peer.unwrap() { + for (node_id, monitor_update_blocked_actions) in + monitor_update_blocked_actions_per_peer.unwrap() + { if let Some(peer_state) = per_peer_state.get(&node_id) { for (channel_id, actions) in monitor_update_blocked_actions.iter() { - let logger = WithContext::from(&args.logger, Some(node_id), Some(*channel_id), None); + let logger = + WithContext::from(&args.logger, Some(node_id), Some(*channel_id), None); for action in actions.iter() { if let MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { downstream_counterparty_and_funding_outpoint: @@ -14674,15 +17743,21 @@ where funding_txo: _, channel_id: blocked_channel_id, blocking_action, - }), .. - } = action { + }), + .. + } = action + { if let Some(blocked_peer_state) = per_peer_state.get(blocked_node_id) { log_trace!(logger, "Holding the next revoke_and_ack from {} until the preimage is durably persisted in the inbound edge's ChannelMonitor", blocked_channel_id); - blocked_peer_state.lock().unwrap().actions_blocking_raa_monitor_updates + blocked_peer_state + .lock() + .unwrap() + .actions_blocking_raa_monitor_updates .entry(*blocked_channel_id) - .or_insert_with(Vec::new).push(blocking_action.clone()); + .or_insert_with(Vec::new) + .push(blocking_action.clone()); } else { // If the channel we were blocking has closed, we don't need to // worry about it - the blocked monitor update should never have @@ -14691,14 +17766,22 @@ where // anymore. } } - if let MonitorUpdateCompletionAction::FreeOtherChannelImmediately { .. } = action { + if let MonitorUpdateCompletionAction::FreeOtherChannelImmediately { + .. + } = action + { debug_assert!(false, "Non-event-generating channel freeing should not appear in our queue"); } } } - peer_state.lock().unwrap().monitor_update_blocked_actions = monitor_update_blocked_actions; + peer_state.lock().unwrap().monitor_update_blocked_actions = + monitor_update_blocked_actions; } else { - log_error!(WithContext::from(&args.logger, Some(node_id), None, None), "Got blocked actions without a per-peer-state for {}", node_id); + log_error!( + WithContext::from(&args.logger, Some(node_id), None, None), + "Got blocked actions without a per-peer-state for {}", + node_id + ); return Err(DecodeError::InvalidValue); } } @@ -14719,7 +17802,10 @@ where forward_htlcs: Mutex::new(forward_htlcs), decode_update_add_htlcs: Mutex::new(decode_update_add_htlcs), - claimable_payments: Mutex::new(ClaimablePayments { claimable_payments, pending_claiming_payments: pending_claiming_payments.unwrap() }), + claimable_payments: Mutex::new(ClaimablePayments { + claimable_payments, + pending_claiming_payments: pending_claiming_payments.unwrap(), + }), outbound_scid_aliases: Mutex::new(outbound_scid_aliases), short_to_chan_info: FairRwLock::new(short_to_chan_info), fake_scid_rand_bytes: fake_scid_rand_bytes.unwrap(), @@ -14770,7 +17856,8 @@ where let mut processed_claims: HashSet> = new_hash_set(); for (_, monitor) in args.channel_monitors.iter() { - for (payment_hash, (payment_preimage, payment_claims)) in monitor.get_stored_preimages() { + for (payment_hash, (payment_preimage, payment_claims)) in monitor.get_stored_preimages() + { if !payment_claims.is_empty() { for payment_claim in payment_claims { if processed_claims.contains(&payment_claim.mpp_parts) { @@ -14783,8 +17870,16 @@ where if payment_claim.mpp_parts.is_empty() { return Err(DecodeError::InvalidValue); } - let mut channels_without_preimage = payment_claim.mpp_parts.iter() - .map(|htlc_info| (htlc_info.counterparty_node_id, htlc_info.funding_txo, htlc_info.channel_id)) + let mut channels_without_preimage = payment_claim + .mpp_parts + .iter() + .map(|htlc_info| { + ( + htlc_info.counterparty_node_id, + htlc_info.funding_txo, + htlc_info.channel_id, + ) + }) .collect::>(); // If we have multiple MPP parts which were received over the same channel, // we only track it once as once we get a preimage durably in the @@ -14805,16 +17900,26 @@ where // preimages eventually timing out from ChannelMonitors to prevent us from // doing so forever. - let claim_found = - channel_manager.claimable_payments.lock().unwrap().begin_claiming_payment( - payment_hash, &channel_manager.node_signer, &channel_manager.logger, - &channel_manager.inbound_payment_id_secret, true, + let claim_found = channel_manager + .claimable_payments + .lock() + .unwrap() + .begin_claiming_payment( + payment_hash, + &channel_manager.node_signer, + &channel_manager.logger, + &channel_manager.inbound_payment_id_secret, + true, ); if claim_found.is_err() { - let mut claimable_payments = channel_manager.claimable_payments.lock().unwrap(); + let mut claimable_payments = + channel_manager.claimable_payments.lock().unwrap(); match claimable_payments.pending_claiming_payments.entry(payment_hash) { hash_map::Entry::Occupied(_) => { - debug_assert!(false, "Entry was added in begin_claiming_payment"); + debug_assert!( + false, + "Entry was added in begin_claiming_payment" + ); return Err(DecodeError::InvalidValue); }, hash_map::Entry::Vacant(entry) => { @@ -14824,22 +17929,34 @@ where } for part in payment_claim.mpp_parts.iter() { - let pending_mpp_claim = pending_claim_ptr_opt.as_ref().map(|ptr| ( - part.counterparty_node_id, part.channel_id, - PendingMPPClaimPointer(Arc::clone(&ptr)) - )); - let pending_claim_ptr = pending_claim_ptr_opt.as_ref().map(|ptr| + let pending_mpp_claim = pending_claim_ptr_opt.as_ref().map(|ptr| { + ( + part.counterparty_node_id, + part.channel_id, + PendingMPPClaimPointer(Arc::clone(&ptr)), + ) + }); + let pending_claim_ptr = pending_claim_ptr_opt.as_ref().map(|ptr| { RAAMonitorUpdateBlockingAction::ClaimedMPPPayment { pending_claim: PendingMPPClaimPointer(Arc::clone(&ptr)), } - ); + }); // Note that we don't need to pass the `payment_info` here - its // already (clearly) durably on disk in the `ChannelMonitor` so there's // no need to worry about getting it into others. channel_manager.claim_mpp_part( - part.into(), payment_preimage, None, - |_, _| - (Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash, pending_mpp_claim }), pending_claim_ptr) + part.into(), + payment_preimage, + None, + |_, _| { + ( + Some(MonitorUpdateCompletionAction::PaymentClaimed { + payment_hash, + pending_mpp_claim, + }), + pending_claim_ptr, + ) + }, ); } processed_claims.insert(payment_claim.mpp_parts); @@ -14855,7 +17972,9 @@ where let mut receiver_node_id = Some(our_network_pubkey); let phantom_shared_secret = payment.htlcs[0].prev_hop.phantom_shared_secret; if phantom_shared_secret.is_some() { - let phantom_pubkey = channel_manager.node_signer.get_node_id(Recipient::PhantomNode) + let phantom_pubkey = channel_manager + .node_signer + .get_node_id(Recipient::PhantomNode) .expect("Failed to get node_id for phantom node recipient"); receiver_node_id = Some(phantom_pubkey) } @@ -14883,17 +18002,27 @@ where let peer_state_mutex = per_peer_state.get(&peer_node_id).unwrap(); let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - if let Some(channel) = peer_state.channel_by_id + if let Some(channel) = peer_state + .channel_by_id .get_mut(&previous_channel_id) .and_then(Channel::as_funded_mut) { - let logger = WithChannelContext::from(&channel_manager.logger, &channel.context, Some(payment_hash)); - channel.claim_htlc_while_disconnected_dropping_mon_update_legacy( - claimable_htlc.prev_hop.htlc_id, payment_preimage, &&logger + let logger = WithChannelContext::from( + &channel_manager.logger, + &channel.context, + Some(payment_hash), ); + channel + .claim_htlc_while_disconnected_dropping_mon_update_legacy( + claimable_htlc.prev_hop.htlc_id, + payment_preimage, + &&logger, + ); } } - if let Some(previous_hop_monitor) = args.channel_monitors.get(&claimable_htlc.prev_hop.channel_id) { + if let Some(previous_hop_monitor) = + args.channel_monitors.get(&claimable_htlc.prev_hop.channel_id) + { // Note that this is unsafe as we no longer require the // `ChannelMonitor`s to be re-persisted prior to this // `ChannelManager` being persisted after we get started running. @@ -14907,23 +18036,37 @@ where // for nodes during upgrade, and we explicitly require the old // persistence semantics on upgrade in the release notes. previous_hop_monitor.provide_payment_preimage_unsafe_legacy( - &payment_hash, &payment_preimage, &channel_manager.tx_broadcaster, - &channel_manager.fee_estimator, &channel_manager.logger + &payment_hash, + &payment_preimage, + &channel_manager.tx_broadcaster, + &channel_manager.fee_estimator, + &channel_manager.logger, ); } } let mut pending_events = channel_manager.pending_events.lock().unwrap(); - let payment_id = payment.inbound_payment_id(&inbound_payment_id_secret.unwrap()); - pending_events.push_back((events::Event::PaymentClaimed { - receiver_node_id, - payment_hash, - purpose: payment.purpose, - amount_msat: claimable_amt_msat, - htlcs: payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(), - sender_intended_total_msat: payment.htlcs.first().map(|htlc| htlc.total_msat), - onion_fields: payment.onion_fields, - payment_id: Some(payment_id), - }, None)); + let payment_id = + payment.inbound_payment_id(&inbound_payment_id_secret.unwrap()); + pending_events.push_back(( + events::Event::PaymentClaimed { + receiver_node_id, + payment_hash, + purpose: payment.purpose, + amount_msat: claimable_amt_msat, + htlcs: payment + .htlcs + .iter() + .map(events::ClaimedHTLC::from) + .collect(), + sender_intended_total_msat: payment + .htlcs + .first() + .map(|htlc| htlc.total_msat), + onion_fields: payment.onion_fields, + payment_id: Some(payment_id), + }, + None, + )); } } } @@ -14932,18 +18075,36 @@ where for htlc_source in failed_htlcs.drain(..) { let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source; let failure_reason = LocalHTLCFailureReason::ChannelClosed; - let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id }; + let receiver = + HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id }; let reason = HTLCFailReason::from_failure_code(failure_reason); channel_manager.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver); } - for (source, preimage, downstream_value, downstream_closed, downstream_node_id, downstream_funding, downstream_channel_id) in pending_claims_to_replay { + for ( + source, + preimage, + downstream_value, + downstream_closed, + downstream_node_id, + downstream_funding, + downstream_channel_id, + ) in pending_claims_to_replay + { // We use `downstream_closed` in place of `from_onchain` here just as a guess - we // don't remember in the `ChannelMonitor` where we got a preimage from, but if the // channel is closed we just assume that it probably came from an on-chain claim. - channel_manager.claim_funds_internal(source, preimage, Some(downstream_value), None, - downstream_closed, true, downstream_node_id, downstream_funding, - downstream_channel_id, None + channel_manager.claim_funds_internal( + source, + preimage, + Some(downstream_value), + None, + downstream_closed, + true, + downstream_node_id, + downstream_funding, + downstream_channel_id, + None, ); } @@ -14956,25 +18117,31 @@ where #[cfg(test)] mod tests { - use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; - use bitcoin::secp256k1::ecdh::SharedSecret; - use core::sync::atomic::Ordering; - use crate::events::{Event, HTLCDestination, ClosureReason}; - use crate::ln::onion_utils::AttributionData; - use crate::ln::types::ChannelId; - use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret}; - use crate::ln::channelmanager::{create_recv_pending_htlc_info, inbound_payment, ChannelConfigOverrides, HTLCForwardInfo, InterceptId, PaymentId, RecipientOnionFields}; + use crate::events::{ClosureReason, Event, HTLCDestination}; + use crate::ln::channelmanager::{ + create_recv_pending_htlc_info, inbound_payment, ChannelConfigOverrides, HTLCForwardInfo, + InterceptId, PaymentId, RecipientOnionFields, + }; use crate::ln::functional_test_utils::*; - use crate::ln::msgs::{self, BaseMessageHandler, ChannelMessageHandler, AcceptChannel, ErrorAction, MessageSendEvent}; + use crate::ln::msgs::{ + self, AcceptChannel, BaseMessageHandler, ChannelMessageHandler, ErrorAction, + MessageSendEvent, + }; + use crate::ln::onion_utils::AttributionData; use crate::ln::onion_utils::{self, LocalHTLCFailureReason}; use crate::ln::outbound_payment::Retry; + use crate::ln::types::ChannelId; use crate::prelude::*; - use crate::routing::router::{PaymentParameters, RouteParameters, find_route}; + use crate::routing::router::{find_route, PaymentParameters, RouteParameters}; + use crate::sign::EntropySource; + use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; + use crate::util::config::{ChannelConfig, ChannelConfigUpdate, ChannelHandshakeConfigUpdate}; use crate::util::errors::APIError; use crate::util::ser::Writeable; use crate::util::test_utils; - use crate::util::config::{ChannelConfig, ChannelConfigUpdate, ChannelHandshakeConfigUpdate}; - use crate::sign::EntropySource; + use bitcoin::secp256k1::ecdh::SharedSecret; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; + use core::sync::atomic::Ordering; #[test] fn test_notify_limits() { @@ -14997,10 +18164,16 @@ mod tests { // to connect messages with new values chan.0.contents.fee_base_msat *= 2; chan.1.contents.fee_base_msat *= 2; - let node_a_chan_info = nodes[0].node.list_channels_with_counterparty( - &nodes[1].node.get_our_node_id()).pop().unwrap(); - let node_b_chan_info = nodes[1].node.list_channels_with_counterparty( - &nodes[0].node.get_our_node_id()).pop().unwrap(); + let node_a_chan_info = nodes[0] + .node + .list_channels_with_counterparty(&nodes[1].node.get_our_node_id()) + .pop() + .unwrap(); + let node_b_chan_info = nodes[1] + .node + .list_channels_with_counterparty(&nodes[0].node.get_our_node_id()) + .pop() + .unwrap(); // The first two nodes (which opened a channel) should now require fresh persistence assert!(nodes[0].node.get_event_or_persistence_needed_future().poll_is_complete()); @@ -15033,9 +18206,22 @@ mod tests { // An earlier version of handle_channel_update didn't check the directionality of the // update message and would always update the local fee info, even if our peer was // (spuriously) forwarding us our own channel_update. - let as_node_one = nodes[0].node.get_our_node_id().serialize()[..] < nodes[1].node.get_our_node_id().serialize()[..]; - let as_update = if as_node_one == (chan.0.contents.channel_flags & 1 == 0 /* chan.0 is from node one */) { &chan.0 } else { &chan.1 }; - let bs_update = if as_node_one == (chan.0.contents.channel_flags & 1 == 0 /* chan.0 is from node one */) { &chan.1 } else { &chan.0 }; + let as_node_one = nodes[0].node.get_our_node_id().serialize()[..] + < nodes[1].node.get_our_node_id().serialize()[..]; + let as_update = if as_node_one + == (chan.0.contents.channel_flags & 1 == 0/* chan.0 is from node one */) + { + &chan.0 + } else { + &chan.1 + }; + let bs_update = if as_node_one + == (chan.0.contents.channel_flags & 1 == 0/* chan.0 is from node one */) + { + &chan.1 + } else { + &chan.0 + }; // First deliver each peers' own message, checking that the node doesn't need to be // persisted and that its channel info remains the same. @@ -15067,7 +18253,8 @@ mod tests { create_announced_chan_between_nodes(&nodes, 0, 1); // First, send a partial MPP payment. - let (route, our_payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100_000); + let (route, our_payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[1], 100_000); let mut mpp_route = route.clone(); mpp_route.paths.push(mpp_route.paths[0].clone()); @@ -15075,30 +18262,68 @@ mod tests { // Use the utility function send_payment_along_path to send the payment with MPP data which // indicates there are more HTLCs coming. let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match. - let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id, &mpp_route).unwrap(); - nodes[0].node.test_send_payment_along_path(&mpp_route.paths[0], &our_payment_hash, - RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[0]).unwrap(); + let session_privs = nodes[0] + .node + .test_add_new_pending_payment( + our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + &mpp_route, + ) + .unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &mpp_route.paths[0], + &our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), + 200_000, + cur_height, + payment_id, + &None, + session_privs[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); - pass_along_path(&nodes[0], &[&nodes[1]], 200_000, our_payment_hash, Some(payment_secret), events.drain(..).next().unwrap(), false, None); + pass_along_path( + &nodes[0], + &[&nodes[1]], + 200_000, + our_payment_hash, + Some(payment_secret), + events.drain(..).next().unwrap(), + false, + None, + ); // Next, send a keysend payment with the same payment_hash and make sure it fails. - nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), - PaymentId(payment_preimage.0), route.route_params.clone().unwrap(), Retry::Attempts(0) - ).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_preimage.0), + route.route_params.clone().unwrap(), + 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); let ev = events.drain(..).next().unwrap(); let payment_event = SendEvent::from_event(ev); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }] + ); check_added_monitors!(nodes[1], 1); let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -15106,17 +18331,40 @@ mod tests { assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, true, true); expect_payment_failed!(nodes[0], our_payment_hash, true); // Send the second half of the original MPP payment. - nodes[0].node.test_send_payment_along_path(&mpp_route.paths[1], &our_payment_hash, - RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[1]).unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &mpp_route.paths[1], + &our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), + 200_000, + cur_height, + payment_id, + &None, + session_privs[1], + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[1]], 200_000, our_payment_hash, Some(payment_secret), events.drain(..).next().unwrap(), true, None); + pass_along_path( + &nodes[0], + &[&nodes[1]], + 200_000, + our_payment_hash, + Some(payment_secret), + events.drain(..).next().unwrap(), + true, + None, + ); // Claim the full MPP payment. Note that we can't use a test utility like // claim_funds_along_route because the ordering of the messages causes the second half of the @@ -15127,29 +18375,59 @@ mod tests { check_added_monitors!(nodes[1], 2); let bs_first_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_first_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_first_updates.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_updates.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_first_updates.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let (as_first_raa, as_first_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (as_first_raa, as_first_cs) = + get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_first_raa); check_added_monitors!(nodes[1], 1); let bs_second_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_first_cs); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_first_cs); check_added_monitors!(nodes[1], 1); - let bs_first_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_second_updates.update_fulfill_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_updates.commitment_signed); + let bs_first_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_second_updates.update_fulfill_htlcs[0], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_second_updates.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_second_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_first_raa); let as_second_updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); check_added_monitors!(nodes[0], 1); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_second_raa); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_second_updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_second_updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_third_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_third_raa); check_added_monitors!(nodes[0], 1); @@ -15158,7 +18436,11 @@ mod tests { let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => { + Event::PaymentPathSuccessful { + payment_id: ref actual_payment_id, + ref payment_hash, + ref path, + } => { assert_eq!(payment_id, *actual_payment_id); assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap()); assert_eq!(route.paths[0], *path); @@ -15166,7 +18448,11 @@ mod tests { _ => panic!("Unexpected event"), } match events[1] { - Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => { + Event::PaymentPathSuccessful { + payment_id: ref actual_payment_id, + ref payment_hash, + ref path, + } => { assert_eq!(payment_id, *actual_payment_id); assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap()); assert_eq!(route.paths[0], *path); @@ -15186,43 +18472,68 @@ mod tests { // Since we do not send peer storage, we manually simulate receiving a dummy // `PeerStorage` from the channel partner. - nodes[0].node.handle_peer_storage(nodes[1].node.get_our_node_id(), msgs::PeerStorage{data: vec![0; 100]}); + nodes[0].node.handle_peer_storage( + nodes[1].node.get_our_node_id(), + msgs::PeerStorage { data: vec![0; 100] }, + ); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let node_0_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(node_0_events.len(), 2); - for msg in node_0_events{ + for msg in node_0_events { if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg { nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), msg); assert_eq!(*node_id, nodes[1].node.get_our_node_id()); - } else if let MessageSendEvent::SendPeerStorageRetrieval { ref node_id, ref msg } = msg { - nodes[1].node.handle_peer_storage_retrieval(nodes[0].node.get_our_node_id(), msg.clone()); + } else if let MessageSendEvent::SendPeerStorageRetrieval { ref node_id, ref msg } = msg + { + nodes[1] + .node + .handle_peer_storage_retrieval(nodes[0].node.get_our_node_id(), msg.clone()); assert_eq!(*node_id, nodes[1].node.get_our_node_id()); } else { panic!("Unexpected event") } } - let msg_events_after_peer_storage_retrieval = nodes[1].node.get_and_clear_pending_msg_events(); + let msg_events_after_peer_storage_retrieval = + nodes[1].node.get_and_clear_pending_msg_events(); // Check if we receive a warning message. let peer_storage_warning: Vec<&MessageSendEvent> = msg_events_after_peer_storage_retrieval - .iter() - .filter(|event| match event { - MessageSendEvent::HandleError { .. } => true, - _ => false, - }) - .collect(); + .iter() + .filter(|event| match event { + MessageSendEvent::HandleError { .. } => true, + _ => false, + }) + .collect(); assert_eq!(peer_storage_warning.len(), 1); @@ -15230,11 +18541,13 @@ mod tests { MessageSendEvent::HandleError { node_id, action } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); match action { - ErrorAction::SendWarningMessage { msg, .. } => - assert_eq!(msg.data, "Invalid peer_storage_retrieval message received.".to_owned()), + ErrorAction::SendWarningMessage { msg, .. } => assert_eq!( + msg.data, + "Invalid peer_storage_retrieval message received.".to_owned() + ), _ => panic!("Unexpected error action"), } - } + }, _ => panic!("Unexpected event"), } } @@ -15258,28 +18571,45 @@ mod tests { // To start (1), send a regular payment but don't claim it. let expected_route = [&nodes[1]]; - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &expected_route, 100_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &expected_route, 100_000); // Next, attempt a keysend payment and make sure it fails. let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), - TEST_FINAL_CLTV, false), 100_000); - nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), - PaymentId(payment_preimage.0), route_params.clone(), Retry::Attempts(0) - ).unwrap(); + PaymentParameters::for_keysend( + expected_route.last().unwrap().node.get_our_node_id(), + TEST_FINAL_CLTV, + false, + ), + 100_000, + ); + nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_preimage.0), + route_params.clone(), + 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); let ev = events.drain(..).next().unwrap(); let payment_event = SendEvent::from_event(ev); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); // We have to forward pending HTLCs twice - once tries to forward the payment forward (and // fails), the second will process the resulting failure and fail the HTLC backward expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[1], 1); let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -15287,7 +18617,10 @@ mod tests { assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, true, true); expect_payment_failed!(nodes[0], payment_hash, true); @@ -15297,34 +18630,68 @@ mod tests { // To start (2), send a keysend payment but don't claim it. let payment_preimage = PaymentPreimage([42; 32]); let route = find_route( - &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, - None, nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes - ).unwrap(); - let payment_hash = nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), - PaymentId(payment_preimage.0), route.route_params.clone().unwrap(), Retry::Attempts(0) - ).unwrap(); + &nodes[0].node.get_our_node_id(), + &route_params, + &nodes[0].network_graph, + None, + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); + let payment_hash = nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_preimage.0), + route.route_params.clone().unwrap(), + 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); let event = events.pop().unwrap(); let path = vec![&nodes[1]]; - pass_along_path(&nodes[0], &path, 100_000, payment_hash, None, event, true, Some(payment_preimage)); + pass_along_path( + &nodes[0], + &path, + 100_000, + payment_hash, + None, + event, + true, + Some(payment_preimage), + ); // Next, attempt a regular payment and make sure it fails. let payment_secret = PaymentSecret([43; 32]); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.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); let ev = events.drain(..).next().unwrap(); let payment_event = SendEvent::from_event(ev); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[1], 1); let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -15332,7 +18699,10 @@ mod tests { assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, true, true); expect_payment_failed!(nodes[0], payment_hash, true); @@ -15341,37 +18711,67 @@ mod tests { // To start (3), send a keysend payment but don't claim it. let payment_id_1 = PaymentId([44; 32]); - let payment_hash = nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_1, - route.route_params.clone().unwrap(), Retry::Attempts(0) - ).unwrap(); + let payment_hash = nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_1, + route.route_params.clone().unwrap(), + 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); let event = events.pop().unwrap(); let path = vec![&nodes[1]]; - pass_along_path(&nodes[0], &path, 100_000, payment_hash, None, event, true, Some(payment_preimage)); + pass_along_path( + &nodes[0], + &path, + 100_000, + payment_hash, + None, + event, + true, + Some(payment_preimage), + ); // Next, attempt a keysend payment and make sure it fails. let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV, false), - 100_000 + PaymentParameters::for_keysend( + expected_route.last().unwrap().node.get_our_node_id(), + TEST_FINAL_CLTV, + false, + ), + 100_000, ); let payment_id_2 = PaymentId([45; 32]); - nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_2, route_params, - Retry::Attempts(0) - ).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_2, + route_params, + 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); let ev = events.drain(..).next().unwrap(); let payment_event = SendEvent::from_event(ev); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[1], 1); let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -15379,7 +18779,10 @@ mod tests { assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, true, true); expect_payment_failed!(nodes[0], payment_hash, true); @@ -15401,22 +18804,48 @@ mod tests { let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]); let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(payee_pubkey, 40, false), 10_000); + PaymentParameters::for_keysend(payee_pubkey, 40, false), + 10_000, + ); let network_graph = nodes[0].network_graph; let first_hops = nodes[0].node.list_usable_channels(); let scorer = test_utils::TestScorer::new(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let route = find_route( - &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::>()), - nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes - ).unwrap(); + &payer_pubkey, + &route_params, + &network_graph, + Some(&first_hops.iter().collect::>()), + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let test_preimage = PaymentPreimage([42; 32]); let mismatch_payment_hash = PaymentHash([43; 32]); - let session_privs = nodes[0].node.test_add_new_pending_payment(mismatch_payment_hash, - RecipientOnionFields::spontaneous_empty(), PaymentId(mismatch_payment_hash.0), &route).unwrap(); - nodes[0].node.test_send_payment_internal(&route, mismatch_payment_hash, - RecipientOnionFields::spontaneous_empty(), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap(); + let session_privs = nodes[0] + .node + .test_add_new_pending_payment( + mismatch_payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(mismatch_payment_hash.0), + &route, + ) + .unwrap(); + nodes[0] + .node + .test_send_payment_internal( + &route, + mismatch_payment_hash, + RecipientOnionFields::spontaneous_empty(), + Some(test_preimage), + PaymentId(mismatch_payment_hash.0), + None, + session_privs, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -15425,14 +18854,23 @@ mod tests { assert!(updates.update_fail_htlcs.is_empty()); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], &updates.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash: mismatch_payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash: mismatch_payment_hash }] + ); check_added_monitors(&nodes[1], 1); let _ = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Payment preimage didn't match payment hash", 1); + nodes[1].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Payment preimage didn't match payment hash", + 1, + ); } #[test] @@ -15442,13 +18880,18 @@ mod tests { let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); - let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; - let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2).0.contents.short_channel_id; - let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3).0.contents.short_channel_id; - let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3).0.contents.short_channel_id; + let chan_1_id = + create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; + let chan_2_id = + create_announced_chan_between_nodes(&nodes, 0, 2).0.contents.short_channel_id; + let chan_3_id = + create_announced_chan_between_nodes(&nodes, 1, 3).0.contents.short_channel_id; + let chan_4_id = + create_announced_chan_between_nodes(&nodes, 2, 3).0.contents.short_channel_id; // Marshall an MPP route. - let (mut route, payment_hash, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); + let (mut route, payment_hash, _, _) = + get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); let path = route.paths[0].clone(); route.paths.push(path); route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -15458,17 +18901,28 @@ mod tests { route.paths[1].hops[0].short_channel_id = chan_2_id; route.paths[1].hops[1].short_channel_id = chan_4_id; - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + ) + .unwrap(); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { Event::PaymentFailed { reason, .. } => { assert_eq!(reason.unwrap(), crate::events::PaymentFailureReason::UnexpectedError); - } - _ => panic!() + }, + _ => panic!(), } - nodes[0].logger.assert_log_contains("lightning::ln::outbound_payment", "Payment secret is required for multi-path payments", 2); + nodes[0].logger.assert_log_contains( + "lightning::ln::outbound_payment", + "Payment secret is required for multi-path payments", + 2, + ); assert!(nodes[0].node.list_recent_payments().is_empty()); } @@ -15481,9 +18935,18 @@ mod tests { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - nodes[0].node.force_close_channel_with_peer(&chan.2, &nodes[1].node.get_our_node_id(), None, true).unwrap(); + nodes[0] + .node + .force_close_channel_with_peer(&chan.2, &nodes[1].node.get_our_node_id(), None, true) + .unwrap(); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); // Confirm that the channel_update was not sent immediately to node[1] but was cached. let node_1_events = nodes[1].node.get_and_clear_pending_msg_events(); @@ -15491,7 +18954,8 @@ mod tests { { // Assert that ChannelUpdate message has been added to node[0] pending broadcast messages - let pending_broadcast_messages= nodes[0].node.pending_broadcast_messages.lock().unwrap(); + let pending_broadcast_messages = + nodes[0].node.pending_broadcast_messages.lock().unwrap(); assert_eq!(pending_broadcast_messages.len(), 1); } @@ -15506,12 +18970,30 @@ mod tests { assert_eq!(node_0_events.len(), 0); // Now we reconnect to a peer - nodes[0].node.peer_connected(nodes[2].node.get_our_node_id(), &msgs::Init { - features: nodes[2].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[2].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[2].node.get_our_node_id(), + &msgs::Init { + features: nodes[2].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[2] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); // Confirm that get_and_clear_pending_msg_events correctly captures pending broadcast messages let node_0_events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -15522,7 +19004,8 @@ mod tests { } { // Assert that ChannelUpdate message has been cleared from nodes[0] pending broadcast messages - let pending_broadcast_messages= nodes[0].node.pending_broadcast_messages.lock().unwrap(); + let pending_broadcast_messages = + nodes[0].node.pending_broadcast_messages.lock().unwrap(); assert_eq!(pending_broadcast_messages.len(), 0); } } @@ -15540,9 +19023,22 @@ mod tests { nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); let chan_id = nodes[0].node.list_channels()[0].channel_id; let error_message = "Channel force-closed"; - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 1_000_000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); { // Assert that nodes[1] is awaiting removal for nodes[0] once nodes[1] has been @@ -15572,14 +19068,26 @@ mod tests { let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1, "Unexpected events {:?}", events); match events[0] { - Event::FundingGenerationReady { .. } => {} + Event::FundingGenerationReady { .. } => {}, _ => panic!("Unexpected event {:?}", events), } nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - check_closed_event!(nodes[0], 1, ClosureReason::DisconnectedPeer, [nodes[1].node.get_our_node_id()], 1_000_000); - check_closed_event!(nodes[1], 1, ClosureReason::DisconnectedPeer, [nodes[0].node.get_our_node_id()], 1_000_000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::DisconnectedPeer, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::DisconnectedPeer, + [nodes[0].node.get_our_node_id()], + 1_000_000 + ); // At this point the state for the peers should have been removed. assert_eq!(nodes[0].node.per_peer_state.read().unwrap().len(), 0); @@ -15595,38 +19103,62 @@ mod tests { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[0]); - let payment_data = msgs::FinalOnionHopData { - payment_secret, - total_msat: 100_000, - }; + let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat: 100_000 }; // Ensure that if the payment hash given to `inbound_payment::verify` differs from the original, // payment verification fails as expected. let mut bad_payment_hash = payment_hash.clone(); bad_payment_hash.0[0] += 1; - match inbound_payment::verify(bad_payment_hash, &payment_data, nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, &nodes[0].node.inbound_payment_key, &nodes[0].logger) { + match inbound_payment::verify( + bad_payment_hash, + &payment_data, + nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, + &nodes[0].node.inbound_payment_key, + &nodes[0].logger, + ) { Ok(_) => panic!("Unexpected ok"), Err(()) => { - nodes[0].logger.assert_log_contains("lightning::ln::inbound_payment", "Failing HTLC with user-generated payment_hash", 1); - } + nodes[0].logger.assert_log_contains( + "lightning::ln::inbound_payment", + "Failing HTLC with user-generated payment_hash", + 1, + ); + }, } // Check that using the original payment hash succeeds. - assert!(inbound_payment::verify(payment_hash, &payment_data, nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, &nodes[0].node.inbound_payment_key, &nodes[0].logger).is_ok()); + assert!(inbound_payment::verify( + payment_hash, + &payment_data, + nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, + &nodes[0].node.inbound_payment_key, + &nodes[0].logger + ) + .is_ok()); } - fn check_not_connected_to_peer_error(res_err: Result, expected_public_key: PublicKey) { + fn check_not_connected_to_peer_error( + res_err: Result, expected_public_key: PublicKey, + ) { let expected_message = format!("Not connected to node: {}", expected_public_key); check_api_error_message(expected_message, res_err) } fn check_unkown_peer_error(res_err: Result, expected_public_key: PublicKey) { - let expected_message = format!("Can't find a peer matching the passed counterparty node_id {}", expected_public_key); + let expected_message = format!( + "Can't find a peer matching the passed counterparty node_id {}", + expected_public_key + ); check_api_error_message(expected_message, res_err) } - fn check_channel_unavailable_error(res_err: Result, expected_channel_id: ChannelId, peer_node_id: PublicKey) { - let expected_message = format!("Channel with id {} not found for the passed counterparty node_id {}", expected_channel_id, peer_node_id); + fn check_channel_unavailable_error( + res_err: Result, expected_channel_id: ChannelId, peer_node_id: PublicKey, + ) { + let expected_message = format!( + "Channel with id {} not found for the passed counterparty node_id {}", + expected_channel_id, peer_node_id + ); check_api_error_message(expected_message, res_err) } @@ -15660,24 +19192,65 @@ mod tests { // Dummy values let channel_id = ChannelId::from_bytes([4; 32]); - let unkown_public_key = PublicKey::from_secret_key(&Secp256k1::signing_only(), &SecretKey::from_slice(&[42; 32]).unwrap()); + let unkown_public_key = PublicKey::from_secret_key( + &Secp256k1::signing_only(), + &SecretKey::from_slice(&[42; 32]).unwrap(), + ); let intercept_id = InterceptId([0; 32]); let error_message = "Channel force-closed"; // Test the API functions. - check_not_connected_to_peer_error(nodes[0].node.create_channel(unkown_public_key, 1_000_000, 500_000_000, 42, None, None), unkown_public_key); + check_not_connected_to_peer_error( + nodes[0].node.create_channel(unkown_public_key, 1_000_000, 500_000_000, 42, None, None), + unkown_public_key, + ); - check_unkown_peer_error(nodes[0].node.accept_inbound_channel(&channel_id, &unkown_public_key, 42, None), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.accept_inbound_channel(&channel_id, &unkown_public_key, 42, None), + unkown_public_key, + ); - check_unkown_peer_error(nodes[0].node.close_channel(&channel_id, &unkown_public_key), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.close_channel(&channel_id, &unkown_public_key), + unkown_public_key, + ); - check_unkown_peer_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key, error_message.to_string()), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.force_close_broadcasting_latest_txn( + &channel_id, + &unkown_public_key, + error_message.to_string(), + ), + unkown_public_key, + ); - check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key, error_message.to_string()), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.force_close_without_broadcasting_txn( + &channel_id, + &unkown_public_key, + error_message.to_string(), + ), + unkown_public_key, + ); - check_unkown_peer_error(nodes[0].node.forward_intercepted_htlc(intercept_id, &channel_id, unkown_public_key, 1_000_000), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.forward_intercepted_htlc( + intercept_id, + &channel_id, + unkown_public_key, + 1_000_000, + ), + unkown_public_key, + ); - check_unkown_peer_error(nodes[0].node.update_channel_config(&unkown_public_key, &[channel_id], &ChannelConfig::default()), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.update_channel_config( + &unkown_public_key, + &[channel_id], + &ChannelConfig::default(), + ), + unkown_public_key, + ); } #[test] @@ -15698,17 +19271,59 @@ mod tests { let error_message = "Channel force-closed"; // Test the API functions. - check_api_misuse_error(nodes[0].node.accept_inbound_channel(&channel_id, &counterparty_node_id, 42, None)); - - check_channel_unavailable_error(nodes[0].node.close_channel(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id); + check_api_misuse_error(nodes[0].node.accept_inbound_channel( + &channel_id, + &counterparty_node_id, + 42, + None, + )); + + check_channel_unavailable_error( + nodes[0].node.close_channel(&channel_id, &counterparty_node_id), + channel_id, + counterparty_node_id, + ); - check_channel_unavailable_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id, error_message.to_string()), channel_id, counterparty_node_id); + check_channel_unavailable_error( + nodes[0].node.force_close_broadcasting_latest_txn( + &channel_id, + &counterparty_node_id, + error_message.to_string(), + ), + channel_id, + counterparty_node_id, + ); - check_channel_unavailable_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id, error_message.to_string()), channel_id, counterparty_node_id); + check_channel_unavailable_error( + nodes[0].node.force_close_without_broadcasting_txn( + &channel_id, + &counterparty_node_id, + error_message.to_string(), + ), + channel_id, + counterparty_node_id, + ); - check_channel_unavailable_error(nodes[0].node.forward_intercepted_htlc(InterceptId([0; 32]), &channel_id, counterparty_node_id, 1_000_000), channel_id, counterparty_node_id); + check_channel_unavailable_error( + nodes[0].node.forward_intercepted_htlc( + InterceptId([0; 32]), + &channel_id, + counterparty_node_id, + 1_000_000, + ), + channel_id, + counterparty_node_id, + ); - check_channel_unavailable_error(nodes[0].node.update_channel_config(&counterparty_node_id, &[channel_id], &ChannelConfig::default()), channel_id, counterparty_node_id); + check_channel_unavailable_error( + nodes[0].node.update_channel_config( + &counterparty_node_id, + &[channel_id], + &ChannelConfig::default(), + ), + channel_id, + counterparty_node_id, + ); } #[test] @@ -15721,58 +19336,120 @@ mod tests { // Note that create_network connects the nodes together for us - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let mut open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); let mut funding_tx = None; for idx in 0..super::MAX_UNFUNDED_CHANS_PER_PEER { nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); if idx == 0 { - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); + nodes[0] + .node + .handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); + let (temporary_channel_id, tx, _) = create_funding_transaction( + &nodes[0], + &nodes[1].node.get_our_node_id(), + 100_000, + 42, + ); funding_tx = Some(tx.clone()); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx).unwrap(); - let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx, + ) + .unwrap(); + let funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); - nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); + nodes[1] + .node + .handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); - nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed); + nodes[0] + .node + .handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed); check_added_monitors!(nodes[0], 1); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); } - open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = + ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } // A MAX_UNFUNDED_CHANS_PER_PEER + 1 channel will be summarily rejected - open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source( - &nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = + ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); - assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, - open_channel_msg.common_fields.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, + open_channel_msg.common_fields.temporary_channel_id + ); // Further, because all of our channels with nodes[0] are inbound, and none of them funded, // it doesn't count as a "protected" peer, i.e. it counts towards the MAX_NO_CHANNEL_PEERS // limit. let mut peer_pks = Vec::with_capacity(super::MAX_NO_CHANNEL_PEERS); for _ in 1..super::MAX_NO_CHANNEL_PEERS { - let random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx, - &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap()); + let random_pk = PublicKey::from_secret_key( + &nodes[0].node.secp_ctx, + &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap(), + ); peer_pks.push(random_pk); - nodes[1].node.peer_connected(random_pk, &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[1] + .node + .peer_connected( + random_pk, + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); } - let last_random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx, - &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap()); - nodes[1].node.peer_connected(last_random_pk, &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap_err(); + let last_random_pk = PublicKey::from_secret_key( + &nodes[0].node.secp_ctx, + &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap(), + ); + nodes[1] + .node + .peer_connected( + last_random_pk, + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap_err(); // Also importantly, because nodes[0] isn't "protected", we will refuse a reconnection from // them if we have too many un-channel'd peers. @@ -15780,19 +19457,49 @@ mod tests { let chan_closed_events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(chan_closed_events.len(), super::MAX_UNFUNDED_CHANS_PER_PEER - 1); for ev in chan_closed_events { - if let Event::ChannelClosed { .. } = ev { } else { panic!(); } + if let Event::ChannelClosed { .. } = ev { + } else { + panic!(); + } } - nodes[1].node.peer_connected(last_random_pk, &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap_err(); + nodes[1] + .node + .peer_connected( + last_random_pk, + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap_err(); // but of course if the connection is outbound its allowed... - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); // Now nodes[0] is disconnected but still has a pending, un-funded channel lying around. @@ -15802,11 +19509,14 @@ mod tests { for i in 0..super::MAX_UNFUNDED_CHANNEL_PEERS - 1 { nodes[1].node.handle_open_channel(peer_pks[i], &open_channel_msg); get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, peer_pks[i]); - open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = + ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } nodes[1].node.handle_open_channel(last_random_pk, &open_channel_msg); - assert_eq!(get_err_msg(&nodes[1], &last_random_pk).channel_id, - open_channel_msg.common_fields.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &last_random_pk).channel_id, + open_channel_msg.common_fields.temporary_channel_id + ); // Of course, however, outbound channels are always allowed nodes[1].node.create_channel(last_random_pk, 100_000, 0, 42, None, None).unwrap(); @@ -15815,10 +19525,23 @@ mod tests { // If we fund the first channel, nodes[0] has a live on-chain channel with us, it is now // "protected" and can connect again. mine_transaction(&nodes[1], funding_tx.as_ref().unwrap()); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelReestablish, + nodes[0].node.get_our_node_id() + ); // Further, because the first channel was funded, we can open another channel with // last_random_pk. @@ -15836,29 +19559,52 @@ mod tests { // Note that create_network connects the nodes together for us - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let mut open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); for _ in 0..super::MAX_UNFUNDED_CHANS_PER_PEER { nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); - get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); - open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); + open_channel_msg.common_fields.temporary_channel_id = + ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } // Once we have MAX_UNFUNDED_CHANS_PER_PEER unfunded channels, new inbound channels will be // rejected. nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); - assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, - open_channel_msg.common_fields.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, + open_channel_msg.common_fields.temporary_channel_id + ); // but we can still open an outbound channel. - nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .create_channel(nodes[0].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + get_event_msg!( + nodes[1], + MessageSendEvent::SendOpenChannel, + nodes[0].node.get_our_node_id() + ); // but even with such an outbound channel, additional inbound channels will still fail. nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); - assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, - open_channel_msg.common_fields.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, + open_channel_msg.common_fields.temporary_channel_id + ); } #[test] @@ -15874,57 +19620,107 @@ mod tests { // Note that create_network connects the nodes together for us - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let mut open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); // First, get us up to MAX_UNFUNDED_CHANNEL_PEERS so we can test at the edge for _ in 0..super::MAX_UNFUNDED_CHANNEL_PEERS - 1 { - let random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx, - &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap()); - nodes[1].node.peer_connected(random_pk, &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + let random_pk = PublicKey::from_secret_key( + &nodes[0].node.secp_ctx, + &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap(), + ); + nodes[1] + .node + .peer_connected( + random_pk, + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); nodes[1].node.handle_open_channel(random_pk, &open_channel_msg); let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &random_pk, 23, None).unwrap(); - } + nodes[1] + .node + .accept_inbound_channel(&temporary_channel_id, &random_pk, 23, None) + .unwrap(); + }, _ => panic!("Unexpected event"), } get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, random_pk); - open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = + ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } // If we try to accept a channel from another peer non-0conf it will fail. - let last_random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx, - &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap()); - nodes[1].node.peer_connected(last_random_pk, &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + let last_random_pk = PublicKey::from_secret_key( + &nodes[0].node.secp_ctx, + &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap(), + ); + nodes[1] + .node + .peer_connected( + last_random_pk, + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); nodes[1].node.handle_open_channel(last_random_pk, &open_channel_msg); let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - match nodes[1].node.accept_inbound_channel(&temporary_channel_id, &last_random_pk, 23, None) { - Err(APIError::APIMisuseError { err }) => - assert_eq!(err, "Too many peers with unfunded channels, refusing to accept new ones"), + match nodes[1].node.accept_inbound_channel( + &temporary_channel_id, + &last_random_pk, + 23, + None, + ) { + Err(APIError::APIMisuseError { err }) => assert_eq!( + err, + "Too many peers with unfunded channels, refusing to accept new ones" + ), _ => panic!(), } - } + }, _ => panic!("Unexpected event"), } - assert_eq!(get_err_msg(&nodes[1], &last_random_pk).channel_id, - open_channel_msg.common_fields.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &last_random_pk).channel_id, + open_channel_msg.common_fields.temporary_channel_id + ); // ...however if we accept the same channel 0conf it should work just fine. nodes[1].node.handle_open_channel(last_random_pk, &open_channel_msg); let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &last_random_pk, 23, None).unwrap(); - } + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &last_random_pk, + 23, + None, + ) + .unwrap(); + }, _ => panic!("Unexpected event"), } get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, last_random_pk); @@ -15956,16 +19752,26 @@ mod tests { // intended amount, we fail the payment. let current_height: u32 = node[0].node.best_block.read().unwrap().height; if let Err(crate::ln::channelmanager::InboundHTLCErr { reason, .. }) = - create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]), - sender_intended_amt_msat - extra_fee_msat - 1, 42, None, true, Some(extra_fee_msat), - current_height) - { + create_recv_pending_htlc_info( + hop_data, + [0; 32], + PaymentHash([0; 32]), + sender_intended_amt_msat - extra_fee_msat - 1, + 42, + None, + true, + Some(extra_fee_msat), + current_height, + ) { assert_eq!(reason, LocalHTLCFailureReason::FinalIncorrectHTLCAmount); - } else { panic!(); } + } else { + panic!(); + } // If amt_received + extra_fee is equal to the sender intended amount, we're fine. let hop_data = onion_utils::Hop::Receive { - hop_data: msgs::InboundOnionReceivePayload { // This is the same payload as above, InboundOnionPayload doesn't implement Clone + hop_data: msgs::InboundOnionReceivePayload { + // This is the same payload as above, InboundOnionPayload doesn't implement Clone sender_intended_htlc_amt_msat: 100, cltv_expiry_height: 42, payment_metadata: None, @@ -15979,33 +19785,52 @@ mod tests { shared_secret: SharedSecret::from_bytes([0; 32]), }; let current_height: u32 = node[0].node.best_block.read().unwrap().height; - assert!(create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]), - sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat), - current_height).is_ok()); + assert!(create_recv_pending_htlc_info( + hop_data, + [0; 32], + PaymentHash([0; 32]), + sender_intended_amt_msat - extra_fee_msat, + 42, + None, + true, + Some(extra_fee_msat), + current_height + ) + .is_ok()); } #[test] - fn test_final_incorrect_cltv(){ + fn test_final_incorrect_cltv() { let chanmon_cfg = create_chanmon_cfgs(1); let node_cfg = create_node_cfgs(1, &chanmon_cfg); let node_chanmgr = create_node_chanmgrs(1, &node_cfg, &[None]); let node = create_network(1, &node_cfg, &node_chanmgr); let current_height: u32 = node[0].node.best_block.read().unwrap().height; - let result = create_recv_pending_htlc_info(onion_utils::Hop::Receive { - hop_data: msgs::InboundOnionReceivePayload { - sender_intended_htlc_amt_msat: 100, - cltv_expiry_height: TEST_FINAL_CLTV, - payment_metadata: None, - keysend_preimage: None, - payment_data: Some(msgs::FinalOnionHopData { - payment_secret: PaymentSecret([0; 32]), - total_msat: 100, - }), - custom_tlvs: Vec::new(), + let result = create_recv_pending_htlc_info( + onion_utils::Hop::Receive { + hop_data: msgs::InboundOnionReceivePayload { + sender_intended_htlc_amt_msat: 100, + cltv_expiry_height: TEST_FINAL_CLTV, + payment_metadata: None, + keysend_preimage: None, + payment_data: Some(msgs::FinalOnionHopData { + payment_secret: PaymentSecret([0; 32]), + total_msat: 100, + }), + custom_tlvs: Vec::new(), + }, + shared_secret: SharedSecret::from_bytes([0; 32]), }, - shared_secret: SharedSecret::from_bytes([0; 32]), - }, [0; 32], PaymentHash([0; 32]), 100, TEST_FINAL_CLTV + 1, None, true, None, current_height); + [0; 32], + PaymentHash([0; 32]), + 100, + TEST_FINAL_CLTV + 1, + None, + true, + None, + current_height, + ); // Should not return an error as this condition: // https://github.com/lightning/bolts/blob/4dcc377209509b13cf89a4b91fde7d478f5b46d8/04-onion-routing.md?plain=1#L334 @@ -16041,7 +19866,9 @@ mod tests { assert_eq!(accept_message.channel_reserve_satoshis, 2_000); } - fn test_inbound_anchors_manual_acceptance_with_override(config_overrides: Option) -> AcceptChannel { + fn test_inbound_anchors_manual_acceptance_with_override( + config_overrides: Option, + ) -> AcceptChannel { // Tests that we properly limit inbound channels when we have the manual-channel-acceptance // flag set and (sometimes) accept channels as 0conf. let mut anchors_cfg = test_default_channel_config(); @@ -16052,12 +19879,26 @@ mod tests { let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, - &[Some(anchors_cfg.clone()), Some(anchors_cfg.clone()), Some(anchors_manual_accept_cfg.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[ + Some(anchors_cfg.clone()), + Some(anchors_cfg.clone()), + Some(anchors_manual_accept_cfg.clone()), + ], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); @@ -16066,22 +19907,34 @@ mod tests { MessageSendEvent::HandleError { node_id, action } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); match action { - ErrorAction::SendErrorMessage { msg } => - assert_eq!(msg.data, "No channels with anchor outputs accepted".to_owned()), + ErrorAction::SendErrorMessage { msg } => { + assert_eq!(msg.data, "No channels with anchor outputs accepted".to_owned()) + }, _ => panic!("Unexpected error action"), } - } + }, _ => panic!("Unexpected event"), } nodes[2].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); let events = nodes[2].node.get_and_clear_pending_events(); match events[0] { - Event::OpenChannelRequest { temporary_channel_id, .. } => - nodes[2].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 23, config_overrides).unwrap(), + Event::OpenChannelRequest { temporary_channel_id, .. } => nodes[2] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 23, + config_overrides, + ) + .unwrap(), _ => panic!("Unexpected event"), } - get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()) + get_event_msg!( + nodes[2], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ) } #[test] @@ -16094,28 +19947,59 @@ mod tests { let mut anchors_config = test_default_channel_config(); anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; anchors_config.manually_accept_inbound_channels = true; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 2, + &node_cfgs, + &[Some(anchors_config.clone()), Some(anchors_config.clone())], + ); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let error_message = "Channel force-closed"; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - assert!(open_channel_msg.common_fields.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None) + .unwrap(); + let open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); + assert!(open_channel_msg + .common_fields + .channel_type + .as_ref() + .unwrap() + .supports_anchors_zero_fee_htlc_tx()); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); - } + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); + }, _ => panic!("Unexpected event"), } let error_msg = get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()); nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &error_msg); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - assert!(!open_channel_msg.common_fields.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx()); + let open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); + assert!(!open_channel_msg + .common_fields + .channel_type + .unwrap() + .supports_anchors_zero_fee_htlc_tx()); // Since nodes[1] should not have accepted the channel, it should // not have generated any events. @@ -16127,18 +20011,39 @@ mod tests { let chanmon_cfg = create_chanmon_cfgs(2); let node_cfg = create_node_cfgs(2, &chanmon_cfg); let mut user_config = test_default_channel_config(); - let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[Some(user_config.clone()), Some(user_config.clone())]); + let node_chanmgr = create_node_chanmgrs( + 2, + &node_cfg, + &[Some(user_config.clone()), Some(user_config.clone())], + ); let nodes = create_network(2, &node_cfg, &node_chanmgr); let _ = create_announced_chan_between_nodes(&nodes, 0, 1); let channel = &nodes[0].node.list_channels()[0]; - nodes[0].node.update_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &user_config.channel_config).unwrap(); + nodes[0] + .node + .update_channel_config( + &channel.counterparty.node_id, + &[channel.channel_id], + &user_config.channel_config, + ) + .unwrap(); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 0); user_config.channel_config.forwarding_fee_base_msat += 10; - nodes[0].node.update_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &user_config.channel_config).unwrap(); - assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_base_msat, user_config.channel_config.forwarding_fee_base_msat); + nodes[0] + .node + .update_channel_config( + &channel.counterparty.node_id, + &[channel.channel_id], + &user_config.channel_config, + ) + .unwrap(); + assert_eq!( + nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_base_msat, + user_config.channel_config.forwarding_fee_base_msat + ); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match &events[0] { @@ -16146,16 +20051,33 @@ mod tests { _ => panic!("expected BroadcastChannelUpdate event"), } - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate::default()).unwrap(); + nodes[0] + .node + .update_partial_channel_config( + &channel.counterparty.node_id, + &[channel.channel_id], + &ChannelConfigUpdate::default(), + ) + .unwrap(); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 0); let new_cltv_expiry_delta = user_config.channel_config.cltv_expiry_delta + 6; - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate { - cltv_expiry_delta: Some(new_cltv_expiry_delta), - ..Default::default() - }).unwrap(); - assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().cltv_expiry_delta, new_cltv_expiry_delta); + nodes[0] + .node + .update_partial_channel_config( + &channel.counterparty.node_id, + &[channel.channel_id], + &ChannelConfigUpdate { + cltv_expiry_delta: Some(new_cltv_expiry_delta), + ..Default::default() + }, + ) + .unwrap(); + assert_eq!( + nodes[0].node.list_channels()[0].config.unwrap().cltv_expiry_delta, + new_cltv_expiry_delta + ); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match &events[0] { @@ -16164,13 +20086,26 @@ mod tests { } let new_fee = user_config.channel_config.forwarding_fee_proportional_millionths + 100; - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate { - forwarding_fee_proportional_millionths: Some(new_fee), - accept_underpaying_htlcs: Some(true), - ..Default::default() - }).unwrap(); - assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().cltv_expiry_delta, new_cltv_expiry_delta); - assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_proportional_millionths, new_fee); + nodes[0] + .node + .update_partial_channel_config( + &channel.counterparty.node_id, + &[channel.channel_id], + &ChannelConfigUpdate { + forwarding_fee_proportional_millionths: Some(new_fee), + accept_underpaying_htlcs: Some(true), + ..Default::default() + }, + ) + .unwrap(); + assert_eq!( + nodes[0].node.list_channels()[0].config.unwrap().cltv_expiry_delta, + new_cltv_expiry_delta + ); + assert_eq!( + nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_proportional_millionths, + new_fee + ); assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().accept_underpaying_htlcs, true); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -16182,19 +20117,25 @@ mod tests { // If we provide a channel_id not associated with the peer, we should get an error and no updates // should be applied to ensure update atomicity as specified in the API docs. let bad_channel_id = ChannelId::v1_from_funding_txid(&[10; 32], 10); - let current_fee = nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_proportional_millionths; + let current_fee = + nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_proportional_millionths; let new_fee = current_fee + 100; - assert!( - matches!( - nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id, bad_channel_id], &ChannelConfigUpdate { + assert!(matches!( + nodes[0].node.update_partial_channel_config( + &channel.counterparty.node_id, + &[channel.channel_id, bad_channel_id], + &ChannelConfigUpdate { forwarding_fee_proportional_millionths: Some(new_fee), ..Default::default() - }), - Err(APIError::ChannelUnavailable { err: _ }), - ) - ); + } + ), + Err(APIError::ChannelUnavailable { err: _ }), + )); // Check that the fee hasn't changed for the channel that exists. - assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_proportional_millionths, current_fee); + assert_eq!( + nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_proportional_millionths, + current_fee + ); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 0); } @@ -16202,11 +20143,20 @@ mod tests { #[test] fn test_payment_display() { let payment_id = PaymentId([42; 32]); - assert_eq!(format!("{}", &payment_id), "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"); + assert_eq!( + format!("{}", &payment_id), + "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" + ); let payment_hash = PaymentHash([42; 32]); - assert_eq!(format!("{}", &payment_hash), "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"); + assert_eq!( + format!("{}", &payment_hash), + "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" + ); let payment_preimage = PaymentPreimage([42; 32]); - assert_eq!(format!("{}", &payment_preimage), "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"); + assert_eq!( + format!("{}", &payment_preimage), + "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" + ); } #[test] @@ -16214,7 +20164,8 @@ mod tests { let chanmon_cfg = create_chanmon_cfgs(2); let node_cfg = create_node_cfgs(2, &chanmon_cfg); let user_config = test_default_channel_config(); - let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgr = + create_node_chanmgrs(2, &node_cfg, &[Some(user_config.clone()), Some(user_config)]); let nodes = create_network(2, &node_cfg, &node_chanmgr); let error_message = "Channel force-closed"; @@ -16222,10 +20173,23 @@ mod tests { let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); { let txn = nodes[0].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -16235,17 +20199,39 @@ mod tests { // Since they're disconnected, Bob won't receive Alice's `Error` message. Reconnect them // such that Bob sends a `ChannelReestablish` to Alice since the channel is still open from // their side. - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); let channel_reestablish = get_event_msg!( - nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id() + nodes[1], + MessageSendEvent::SendChannelReestablish, + nodes[0].node.get_our_node_id() ); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &channel_reestablish); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &channel_reestablish); // Alice should respond with an error since the channel isn't known, but a bogus // `ChannelReestablish` should be sent first, such that we actually trigger Bob to force @@ -16257,13 +20243,22 @@ mod tests { assert_eq!(msg.next_local_commitment_number, 0); assert_eq!(msg.next_remote_commitment_number, 0); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &msg); - } else { panic!() }; + } else { + panic!() + }; check_closed_broadcast(&nodes[1], 1, true); check_added_monitors(&nodes[1], 1); let expected_close_reason = ClosureReason::ProcessingError { - err: "Peer sent an invalid channel_reestablish to force close in a non-standard way".to_string() + err: "Peer sent an invalid channel_reestablish to force close in a non-standard way" + .to_string(), }; - check_closed_event!(nodes[1], 1, expected_close_reason, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + expected_close_reason, + [nodes[0].node.get_our_node_id()], + 100000 + ); { let txn = nodes[1].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -16282,33 +20277,38 @@ mod tests { let deserialized_chanmgr; let mut nodes = create_network(1, &node_cfg, &chanmgrs); - let dummy_failed_htlc = |htlc_id| { - HTLCForwardInfo::FailHTLC { htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42], attribution_data: Some(AttributionData::new()) } } + let dummy_failed_htlc = |htlc_id| HTLCForwardInfo::FailHTLC { + htlc_id, + err_packet: msgs::OnionErrorPacket { + data: vec![42], + attribution_data: Some(AttributionData::new()), + }, }; - let dummy_malformed_htlc = |htlc_id| { - HTLCForwardInfo::FailMalformedHTLC { - htlc_id, - failure_code: LocalHTLCFailureReason::InvalidOnionPayload.failure_code(), - sha256_of_onion: [0; 32], - } + let dummy_malformed_htlc = |htlc_id| HTLCForwardInfo::FailMalformedHTLC { + htlc_id, + failure_code: LocalHTLCFailureReason::InvalidOnionPayload.failure_code(), + sha256_of_onion: [0; 32], }; - let dummy_htlcs_1: Vec = (1..10).map(|htlc_id| { - if htlc_id % 2 == 0 { - dummy_failed_htlc(htlc_id) - } else { - dummy_malformed_htlc(htlc_id) - } - }).collect(); - - let dummy_htlcs_2: Vec = (1..10).map(|htlc_id| { - if htlc_id % 2 == 1 { - dummy_failed_htlc(htlc_id) - } else { - dummy_malformed_htlc(htlc_id) - } - }).collect(); + let dummy_htlcs_1: Vec = (1..10) + .map(|htlc_id| { + if htlc_id % 2 == 0 { + dummy_failed_htlc(htlc_id) + } else { + dummy_malformed_htlc(htlc_id) + } + }) + .collect(); + let dummy_htlcs_2: Vec = (1..10) + .map(|htlc_id| { + if htlc_id % 2 == 1 { + dummy_failed_htlc(htlc_id) + } else { + dummy_malformed_htlc(htlc_id) + } + }) + .collect(); let (scid_1, scid_2) = (42, 43); let mut forward_htlcs = new_hash_map(); @@ -16319,7 +20319,14 @@ mod tests { *chanmgr_fwd_htlcs = forward_htlcs.clone(); core::mem::drop(chanmgr_fwd_htlcs); - reload_node!(nodes[0], nodes[0].node.encode(), &[], persister, chain_monitor, deserialized_chanmgr); + reload_node!( + nodes[0], + nodes[0].node.encode(), + &[], + persister, + chain_monitor, + deserialized_chanmgr + ); let mut deserialized_fwd_htlcs = nodes[0].node.forward_htlcs.lock().unwrap(); for scid in [scid_1, scid_2].iter() { @@ -16335,53 +20342,80 @@ mod tests { #[cfg(ldk_bench)] pub mod bench { - use crate::chain::Listen; use crate::chain::chainmonitor::{ChainMonitor, Persist}; - use crate::sign::{KeysManager, InMemorySigner}; + use crate::chain::Listen; use crate::events::Event; - use crate::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentId, RecipientOnionFields, Retry}; + use crate::ln::channelmanager::{ + BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentId, PaymentPreimage, + RecipientOnionFields, Retry, + }; use crate::ln::functional_test_utils::*; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, Init, MessageSendEvent}; use crate::routing::gossip::NetworkGraph; use crate::routing::router::{PaymentParameters, RouteParameters}; + use crate::sign::{InMemorySigner, KeysManager}; + use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::test_utils; - use crate::util::config::{UserConfig, MaxDustHTLCExposure}; use bitcoin::amount::Amount; - use bitcoin::locktime::absolute::LockTime; - use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; - use bitcoin::{Transaction, TxOut}; + use bitcoin::hashes::Hash; + use bitcoin::locktime::absolute::LockTime; use bitcoin::transaction::Version; + use bitcoin::{Transaction, TxOut}; use crate::sync::{Arc, RwLock}; use criterion::Criterion; type Manager<'a, P> = ChannelManager< - &'a ChainMonitor, - &'a test_utils::TestBroadcaster, &'a KeysManager, &'a KeysManager, &'a KeysManager, - &'a test_utils::TestFeeEstimator, &'a test_utils::TestRouter<'a>, - &'a test_utils::TestMessageRouter<'a>, &'a test_utils::TestLogger>; + &'a ChainMonitor< + InMemorySigner, + &'a test_utils::TestChainSource, + &'a test_utils::TestBroadcaster, + &'a test_utils::TestFeeEstimator, + &'a test_utils::TestLogger, + &'a P, + >, + &'a test_utils::TestBroadcaster, + &'a KeysManager, + &'a KeysManager, + &'a KeysManager, + &'a test_utils::TestFeeEstimator, + &'a test_utils::TestRouter<'a>, + &'a test_utils::TestMessageRouter<'a>, + &'a test_utils::TestLogger, + >; struct ANodeHolder<'node_cfg, 'chan_mon_cfg: 'node_cfg, P: Persist> { node: &'node_cfg Manager<'chan_mon_cfg, P>, } - impl<'node_cfg, 'chan_mon_cfg: 'node_cfg, P: Persist> NodeHolder for ANodeHolder<'node_cfg, 'chan_mon_cfg, P> { + impl<'node_cfg, 'chan_mon_cfg: 'node_cfg, P: Persist> NodeHolder + for ANodeHolder<'node_cfg, 'chan_mon_cfg, P> + { type CM = Manager<'chan_mon_cfg, P>; #[inline] - fn node(&self) -> &Manager<'chan_mon_cfg, P> { self.node } + fn node(&self) -> &Manager<'chan_mon_cfg, P> { + self.node + } #[inline] - fn chain_monitor(&self) -> Option<&test_utils::TestChainMonitor> { None } + fn chain_monitor(&self) -> Option<&test_utils::TestChainMonitor> { + None + } } pub fn bench_sends(bench: &mut Criterion) { - bench_two_sends(bench, "bench_sends", test_utils::TestPersister::new(), test_utils::TestPersister::new()); + bench_two_sends( + bench, + "bench_sends", + test_utils::TestPersister::new(), + test_utils::TestPersister::new(), + ); } - pub fn bench_two_sends>(bench: &mut Criterion, bench_name: &str, persister_a: P, persister_b: P) { + pub fn bench_two_sends>( + bench: &mut Criterion, bench_name: &str, persister_a: P, persister_b: P, + ) { // Do a simple benchmark of sending a payment back and forth between two nodes. // Note that this is unrealistic as each payment send will require at least two fsync // calls per node. @@ -16393,65 +20427,157 @@ pub mod bench { let logger_a = test_utils::TestLogger::with_id("node a".to_owned()); let scorer = RwLock::new(test_utils::TestScorer::new()); let entropy = test_utils::TestKeysInterface::new(&[0u8; 32], network); - let router = test_utils::TestRouter::new(Arc::new(NetworkGraph::new(network, &logger_a)), &logger_a, &scorer); - let message_router = test_utils::TestMessageRouter::new(Arc::new(NetworkGraph::new(network, &logger_a)), &entropy); + let router = test_utils::TestRouter::new( + Arc::new(NetworkGraph::new(network, &logger_a)), + &logger_a, + &scorer, + ); + let message_router = test_utils::TestMessageRouter::new( + Arc::new(NetworkGraph::new(network, &logger_a)), + &entropy, + ); let mut config: UserConfig = Default::default(); - config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); + config.channel_config.max_dust_htlc_exposure = + MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); config.channel_handshake_config.minimum_depth = 1; - let chain_monitor_a = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a); + let chain_monitor_a = + ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a); let seed_a = [1u8; 32]; let keys_manager_a = KeysManager::new(&seed_a, 42, 42); - let node_a = ChannelManager::new(&fee_estimator, &chain_monitor_a, &tx_broadcaster, &router, &message_router, &logger_a, &keys_manager_a, &keys_manager_a, &keys_manager_a, config.clone(), ChainParameters { - network, - best_block: BestBlock::from_network(network), - }, genesis_block.header.time); + let node_a = ChannelManager::new( + &fee_estimator, + &chain_monitor_a, + &tx_broadcaster, + &router, + &message_router, + &logger_a, + &keys_manager_a, + &keys_manager_a, + &keys_manager_a, + config.clone(), + ChainParameters { network, best_block: BestBlock::from_network(network) }, + genesis_block.header.time, + ); let node_a_holder = ANodeHolder { node: &node_a }; let logger_b = test_utils::TestLogger::with_id("node a".to_owned()); - let chain_monitor_b = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_b); + let chain_monitor_b = + ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_b); let seed_b = [2u8; 32]; let keys_manager_b = KeysManager::new(&seed_b, 42, 42); - let node_b = ChannelManager::new(&fee_estimator, &chain_monitor_b, &tx_broadcaster, &router, &message_router, &logger_b, &keys_manager_b, &keys_manager_b, &keys_manager_b, config.clone(), ChainParameters { - network, - best_block: BestBlock::from_network(network), - }, genesis_block.header.time); + let node_b = ChannelManager::new( + &fee_estimator, + &chain_monitor_b, + &tx_broadcaster, + &router, + &message_router, + &logger_b, + &keys_manager_b, + &keys_manager_b, + &keys_manager_b, + config.clone(), + ChainParameters { network, best_block: BestBlock::from_network(network) }, + genesis_block.header.time, + ); let node_b_holder = ANodeHolder { node: &node_b }; - node_a.peer_connected(node_b.get_our_node_id(), &Init { - features: node_b.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - node_b.peer_connected(node_a.get_our_node_id(), &Init { - features: node_a.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); - node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None, None).unwrap(); - node_b.handle_open_channel(node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id())); - node_a.handle_accept_channel(node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendAcceptChannel, node_a.get_our_node_id())); + node_a + .peer_connected( + node_b.get_our_node_id(), + &Init { + features: node_b.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + node_b + .peer_connected( + node_a.get_our_node_id(), + &Init { + features: node_a.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); + node_a + .create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None, None) + .unwrap(); + node_b.handle_open_channel( + node_a.get_our_node_id(), + &get_event_msg!( + node_a_holder, + MessageSendEvent::SendOpenChannel, + node_b.get_our_node_id() + ), + ); + node_a.handle_accept_channel( + node_b.get_our_node_id(), + &get_event_msg!( + node_b_holder, + MessageSendEvent::SendAcceptChannel, + node_a.get_our_node_id() + ), + ); let tx; - if let Event::FundingGenerationReady { temporary_channel_id, output_script, .. } = get_event!(node_a_holder, Event::FundingGenerationReady) { - tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: Amount::from_sat(8_000_000), script_pubkey: output_script, - }]}; - node_a.funding_transaction_generated(temporary_channel_id, node_b.get_our_node_id(), tx.clone()).unwrap(); - } else { panic!(); } - - node_b.handle_funding_created(node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendFundingCreated, node_b.get_our_node_id())); + if let Event::FundingGenerationReady { temporary_channel_id, output_script, .. } = + get_event!(node_a_holder, Event::FundingGenerationReady) + { + tx = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { + value: Amount::from_sat(8_000_000), + script_pubkey: output_script, + }], + }; + node_a + .funding_transaction_generated( + temporary_channel_id, + node_b.get_our_node_id(), + tx.clone(), + ) + .unwrap(); + } else { + panic!(); + } + + node_b.handle_funding_created( + node_a.get_our_node_id(), + &get_event_msg!( + node_a_holder, + MessageSendEvent::SendFundingCreated, + node_b.get_our_node_id() + ), + ); let events_b = node_b.get_and_clear_pending_events(); assert_eq!(events_b.len(), 1); match events_b[0] { - Event::ChannelPending{ ref counterparty_node_id, .. } => { + Event::ChannelPending { ref counterparty_node_id, .. } => { assert_eq!(*counterparty_node_id, node_a.get_our_node_id()); }, _ => panic!("Unexpected event"), } - node_a.handle_funding_signed(node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendFundingSigned, node_a.get_our_node_id())); + node_a.handle_funding_signed( + node_b.get_our_node_id(), + &get_event_msg!( + node_b_holder, + MessageSendEvent::SendFundingSigned, + node_a.get_our_node_id() + ), + ); let events_a = node_a.get_and_clear_pending_events(); assert_eq!(events_a.len(), 1); match events_a[0] { - Event::ChannelPending{ ref counterparty_node_id, .. } => { + Event::ChannelPending { ref counterparty_node_id, .. } => { assert_eq!(*counterparty_node_id, node_b.get_our_node_id()); }, _ => panic!("Unexpected event"), @@ -16463,13 +20589,24 @@ pub mod bench { Listen::block_connected(&node_a, &block, 1); Listen::block_connected(&node_b, &block, 1); - node_a.handle_channel_ready(node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendChannelReady, node_a.get_our_node_id())); + node_a.handle_channel_ready( + node_b.get_our_node_id(), + &get_event_msg!( + node_b_holder, + MessageSendEvent::SendChannelReady, + node_a.get_our_node_id() + ), + ); let msg_events = node_a.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 2); match msg_events[0] { MessageSendEvent::SendChannelReady { ref msg, .. } => { node_b.handle_channel_ready(node_a.get_our_node_id(), msg); - get_event_msg!(node_b_holder, MessageSendEvent::SendChannelUpdate, node_a.get_our_node_id()); + get_event_msg!( + node_b_holder, + MessageSendEvent::SendChannelUpdate, + node_a.get_our_node_id() + ); }, _ => panic!(), } @@ -16481,7 +20618,7 @@ pub mod bench { let events_a = node_a.get_and_clear_pending_events(); assert_eq!(events_a.len(), 1); match events_a[0] { - Event::ChannelReady{ ref counterparty_node_id, .. } => { + Event::ChannelReady { ref counterparty_node_id, .. } => { assert_eq!(*counterparty_node_id, node_b.get_our_node_id()); }, _ => panic!("Unexpected event"), @@ -16490,7 +20627,7 @@ pub mod bench { let events_b = node_b.get_and_clear_pending_events(); assert_eq!(events_b.len(), 1); match events_b[0] { - Event::ChannelReady{ ref counterparty_node_id, .. } => { + Event::ChannelReady { ref counterparty_node_id, .. } => { assert_eq!(*counterparty_node_id, node_a.get_our_node_id()); }, _ => panic!("Unexpected event"), @@ -16499,52 +20636,100 @@ pub mod bench { let mut payment_count: u64 = 0; macro_rules! send_payment { ($node_a: expr, $node_b: expr) => { - let payment_params = PaymentParameters::from_node_id($node_b.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features($node_b.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id($node_b.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features($node_b.bolt11_invoice_features()) + .unwrap(); let mut payment_preimage = PaymentPreimage([0; 32]); payment_preimage.0[0..8].copy_from_slice(&payment_count.to_le_bytes()); payment_count += 1; - let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()); - let payment_secret = $node_b.create_inbound_payment_for_hash(payment_hash, None, 7200, None).unwrap(); - - $node_a.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), - RouteParameters::from_payment_params_and_value(payment_params, 10_000), - Retry::Attempts(0)).unwrap(); - let payment_event = SendEvent::from_event($node_a.get_and_clear_pending_msg_events().pop().unwrap()); + let payment_hash = + PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()); + let payment_secret = $node_b + .create_inbound_payment_for_hash(payment_hash, None, 7200, None) + .unwrap(); + + $node_a + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + RouteParameters::from_payment_params_and_value(payment_params, 10_000), + Retry::Attempts(0), + ) + .unwrap(); + let payment_event = SendEvent::from_event( + $node_a.get_and_clear_pending_msg_events().pop().unwrap(), + ); $node_b.handle_update_add_htlc($node_a.get_our_node_id(), &payment_event.msgs[0]); - $node_b.handle_commitment_signed_batch_test($node_a.get_our_node_id(), &payment_event.commitment_msg); - let (raa, cs) = get_revoke_commit_msgs(&ANodeHolder { node: &$node_b }, &$node_a.get_our_node_id()); + $node_b.handle_commitment_signed_batch_test( + $node_a.get_our_node_id(), + &payment_event.commitment_msg, + ); + let (raa, cs) = get_revoke_commit_msgs( + &ANodeHolder { node: &$node_b }, + &$node_a.get_our_node_id(), + ); $node_a.handle_revoke_and_ack($node_b.get_our_node_id(), &raa); $node_a.handle_commitment_signed_batch_test($node_b.get_our_node_id(), &cs); - $node_b.handle_revoke_and_ack($node_a.get_our_node_id(), &get_event_msg!(ANodeHolder { node: &$node_a }, MessageSendEvent::SendRevokeAndACK, $node_b.get_our_node_id())); + $node_b.handle_revoke_and_ack( + $node_a.get_our_node_id(), + &get_event_msg!( + ANodeHolder { node: &$node_a }, + MessageSendEvent::SendRevokeAndACK, + $node_b.get_our_node_id() + ), + ); expect_pending_htlcs_forwardable!(ANodeHolder { node: &$node_b }); - expect_payment_claimable!(ANodeHolder { node: &$node_b }, payment_hash, payment_secret, 10_000); + expect_payment_claimable!( + ANodeHolder { node: &$node_b }, + payment_hash, + payment_secret, + 10_000 + ); $node_b.claim_funds(payment_preimage); expect_payment_claimed!(ANodeHolder { node: &$node_b }, payment_hash, 10_000); match $node_b.get_and_clear_pending_msg_events().pop().unwrap() { MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, updates } => { assert_eq!(node_id, $node_a.get_our_node_id()); - $node_a.handle_update_fulfill_htlc($node_b.get_our_node_id(), &updates.update_fulfill_htlcs[0]); - $node_a.handle_commitment_signed_batch_test($node_b.get_our_node_id(), &updates.commitment_signed); + $node_a.handle_update_fulfill_htlc( + $node_b.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); + $node_a.handle_commitment_signed_batch_test( + $node_b.get_our_node_id(), + &updates.commitment_signed, + ); }, _ => panic!("Failed to generate claim event"), } - let (raa, cs) = get_revoke_commit_msgs(&ANodeHolder { node: &$node_a }, &$node_b.get_our_node_id()); + let (raa, cs) = get_revoke_commit_msgs( + &ANodeHolder { node: &$node_a }, + &$node_b.get_our_node_id(), + ); $node_b.handle_revoke_and_ack($node_a.get_our_node_id(), &raa); $node_b.handle_commitment_signed_batch_test($node_a.get_our_node_id(), &cs); - $node_a.handle_revoke_and_ack($node_b.get_our_node_id(), &get_event_msg!(ANodeHolder { node: &$node_b }, MessageSendEvent::SendRevokeAndACK, $node_a.get_our_node_id())); + $node_a.handle_revoke_and_ack( + $node_b.get_our_node_id(), + &get_event_msg!( + ANodeHolder { node: &$node_b }, + MessageSendEvent::SendRevokeAndACK, + $node_a.get_our_node_id() + ), + ); expect_payment_sent!(ANodeHolder { node: &$node_a }, payment_preimage); - } + }; } - bench.bench_function(bench_name, |b| b.iter(|| { - send_payment!(node_a, node_b); - send_payment!(node_b, node_a); - })); + bench.bench_function(bench_name, |b| { + b.iter(|| { + send_payment!(node_a, node_b); + send_payment!(node_b, node_a); + }) + }); } } diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 45336543483..6eb76417bbf 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -10,57 +10,67 @@ //! A bunch of useful utilities for building networks of nodes and exchanging messages between //! nodes for functional tests. -use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; use crate::chain::channelmonitor::ChannelMonitor; use crate::chain::transaction::OutPoint; -use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, PaidBolt12Invoice, PathFailure, PaymentFailureReason, PaymentPurpose}; -use crate::events::bump_transaction::{BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource}; -use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret}; -use crate::ln::channelmanager::{AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA}; -use crate::types::features::InitFeatures; +use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; +use crate::events::bump_transaction::{ + BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource, +}; +use crate::events::{ + ClaimedHTLC, ClosureReason, Event, HTLCDestination, PaidBolt12Invoice, PathFailure, + PaymentFailureReason, PaymentPurpose, +}; +use crate::ln::channelmanager::{ + AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, PaymentId, + RAACommitmentOrder, RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::msgs; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent, RoutingMessageHandler}; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, MessageSendEvent, RoutingMessageHandler, +}; +use crate::ln::onion_utils::LocalHTLCFailureReason; use crate::ln::outbound_payment::Retry; use crate::ln::peer_handler::IgnoringMessageHandler; +use crate::ln::types::ChannelId; use crate::onion_message::messenger::OnionMessenger; -use crate::ln::onion_utils::LocalHTLCFailureReason; -use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate}; +use crate::routing::gossip::{NetworkGraph, NetworkUpdate, P2PGossipSync}; use crate::routing::router::{self, PaymentParameters, Route, RouteParameters}; use crate::sign::{EntropySource, RandomBytes}; +use crate::types::features::InitFeatures; +use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::logger::Logger; use crate::util::scid_utils; -use crate::util::test_channel_signer::TestChannelSigner; +use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_channel_signer::SignerOp; +use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_utils; -use crate::util::test_utils::{TestChainMonitor, TestScorer, TestKeysInterface}; -use crate::util::ser::{ReadableArgs, Writeable}; +use crate::util::test_utils::{TestChainMonitor, TestKeysInterface, TestScorer}; -use bitcoin::{Weight, WPubkeyHash}; use bitcoin::amount::Amount; use bitcoin::block::{Block, Header, Version as BlockVersion}; -use bitcoin::locktime::absolute::{LockTime, LOCK_TIME_THRESHOLD}; -use bitcoin::transaction::{Sequence, Transaction, TxIn, TxOut}; use bitcoin::hash_types::{BlockHash, TxMerkleNode}; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash as _; +use bitcoin::locktime::absolute::{LockTime, LOCK_TIME_THRESHOLD}; use bitcoin::network::Network; use bitcoin::pow::CompactTarget; use bitcoin::script::ScriptBuf; use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::transaction::{self, Version as TxVersion}; +use bitcoin::transaction::{Sequence, Transaction, TxIn, TxOut}; use bitcoin::witness::Witness; +use bitcoin::{WPubkeyHash, Weight}; +use crate::io; +use crate::prelude::*; +use crate::sign::P2WPKH_WITNESS_WEIGHT; +use crate::sync::{Arc, LockTestExt, Mutex, RwLock}; use alloc::rc::Rc; use core::cell::RefCell; use core::iter::repeat; use core::mem; use core::ops::Deref; -use crate::io; -use crate::prelude::*; -use crate::sign::P2WPKH_WITNESS_WEIGHT; -use crate::sync::{Arc, Mutex, LockTestExt, RwLock}; pub const CHAN_CONFIRM_DEPTH: u32 = 10; @@ -89,7 +99,9 @@ pub fn mine_transactions<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: &[&Tra } /// Mine a single block containing the given transaction without extra consistency checks which may /// impact ChannelManager state. -pub fn mine_transaction_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) { +pub fn mine_transaction_without_consistency_checks<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, tx: &Transaction, +) { let height = node.best_block_info().1 + 1; let mut block = Block { header: Header { @@ -102,8 +114,14 @@ pub fn mine_transaction_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Nod }, txdata: Vec::new(), }; - for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count - block.txdata.push(Transaction { version: transaction::Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }); + for _ in 0..*node.network_chan_count.borrow() { + // Make sure we don't end up with channels at the same short id by offsetting by chan_count + block.txdata.push(Transaction { + version: transaction::Version(0), + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }); } block.txdata.push((*tx).clone()); do_connect_block_without_consistency_checks(node, block, false); @@ -113,15 +131,23 @@ pub fn mine_transaction_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Nod /// /// Returns the SCID a channel confirmed in the given transaction will have, assuming the funding /// output is the 1st output in the transaction. -pub fn confirm_transactions_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: &[&Transaction], conf_height: u32) -> u64 { +pub fn confirm_transactions_at<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, txn: &[&Transaction], conf_height: u32, +) -> u64 { let first_connect_height = node.best_block_info().1 + 1; assert!(first_connect_height <= conf_height); if conf_height > first_connect_height { connect_blocks(node, conf_height - first_connect_height); } let mut txdata = Vec::new(); - for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count - txdata.push(Transaction { version: transaction::Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }); + for _ in 0..*node.network_chan_count.borrow() { + // Make sure we don't end up with channels at the same short id by offsetting by chan_count + txdata.push(Transaction { + version: transaction::Version(0), + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }); } for tx in txn { txdata.push((*tx).clone()); @@ -130,7 +156,9 @@ pub fn confirm_transactions_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: connect_block(node, &block); scid_utils::scid_from_parts(conf_height as u64, block.txdata.len() as u64 - 1, 0).unwrap() } -pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) -> u64 { +pub fn confirm_transaction_at<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32, +) -> u64 { confirm_transactions_at(node, &[tx], conf_height) } @@ -260,14 +288,18 @@ fn call_claimable_balances<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) { } } -fn do_connect_block_with_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: Block, skip_intermediaries: bool) { +fn do_connect_block_with_consistency_checks<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, block: Block, skip_intermediaries: bool, +) { call_claimable_balances(node); do_connect_block_without_consistency_checks(node, block, skip_intermediaries); call_claimable_balances(node); node.node.test_process_background_events(); } -fn do_connect_block_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: Block, skip_intermediaries: bool) { +fn do_connect_block_without_consistency_checks<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, block: Block, skip_intermediaries: bool, +) { let height = node.best_block_info().1 + 1; eprintln!("Connecting block using Block Connection Style: {:?}", *node.connect_style.borrow()); // Update the block internally before handing it over to LDK, to ensure our assertions regarding @@ -276,17 +308,27 @@ fn do_connect_block_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b if !skip_intermediaries { let txdata: Vec<_> = block.txdata.iter().enumerate().collect(); match *node.connect_style.borrow() { - ConnectStyle::BestBlockFirst|ConnectStyle::BestBlockFirstSkippingBlocks|ConnectStyle::BestBlockFirstReorgsOnlyTip => { + ConnectStyle::BestBlockFirst + | ConnectStyle::BestBlockFirstSkippingBlocks + | ConnectStyle::BestBlockFirstReorgsOnlyTip => { node.chain_monitor.chain_monitor.best_block_updated(&block.header, height); call_claimable_balances(node); - node.chain_monitor.chain_monitor.transactions_confirmed(&block.header, &txdata, height); + node.chain_monitor.chain_monitor.transactions_confirmed( + &block.header, + &txdata, + height, + ); node.node.best_block_updated(&block.header, height); node.node.transactions_confirmed(&block.header, &txdata, height); }, - ConnectStyle::TransactionsFirst|ConnectStyle::TransactionsFirstSkippingBlocks| - ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks|ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks| - ConnectStyle::TransactionsFirstReorgsOnlyTip => { - if *node.connect_style.borrow() == ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks { + ConnectStyle::TransactionsFirst + | ConnectStyle::TransactionsFirstSkippingBlocks + | ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks + | ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks + | ConnectStyle::TransactionsFirstReorgsOnlyTip => { + if *node.connect_style.borrow() + == ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks + { let mut connections = Vec::new(); for (block, height) in node.blocks.lock().unwrap().iter() { if !block.txdata.is_empty() { @@ -301,13 +343,26 @@ fn do_connect_block_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b } } for (old_block, height) in connections { - node.chain_monitor.chain_monitor.transactions_confirmed(&old_block.header, - &old_block.txdata.iter().enumerate().collect::>(), height); + node.chain_monitor.chain_monitor.transactions_confirmed( + &old_block.header, + &old_block.txdata.iter().enumerate().collect::>(), + height, + ); } } - node.chain_monitor.chain_monitor.transactions_confirmed(&block.header, &txdata, height); - if *node.connect_style.borrow() == ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks { - node.chain_monitor.chain_monitor.transactions_confirmed(&block.header, &txdata, height); + node.chain_monitor.chain_monitor.transactions_confirmed( + &block.header, + &txdata, + height, + ); + if *node.connect_style.borrow() + == ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks + { + node.chain_monitor.chain_monitor.transactions_confirmed( + &block.header, + &txdata, + height, + ); } call_claimable_balances(node); node.chain_monitor.chain_monitor.best_block_updated(&block.header, height); @@ -317,7 +372,7 @@ fn do_connect_block_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b ConnectStyle::FullBlockViaListen => { node.chain_monitor.chain_monitor.block_connected(&block, height); node.node.block_connected(&block, height); - } + }, } } @@ -337,7 +392,11 @@ fn do_connect_block_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) { call_claimable_balances(node); - eprintln!("Disconnecting {} blocks using Block Connection Style: {:?}", count, *node.connect_style.borrow()); + eprintln!( + "Disconnecting {} blocks using Block Connection Style: {:?}", + count, + *node.connect_style.borrow() + ); for i in 0..count { let orig = node.blocks.lock().unwrap().pop().unwrap(); assert!(orig.1 > 0); // Cannot disconnect genesis @@ -348,14 +407,17 @@ pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) node.chain_monitor.chain_monitor.block_disconnected(&orig.0.header, orig.1); Listen::block_disconnected(node.node, &orig.0.header, orig.1); }, - ConnectStyle::BestBlockFirstSkippingBlocks|ConnectStyle::TransactionsFirstSkippingBlocks| - ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks|ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks => { + ConnectStyle::BestBlockFirstSkippingBlocks + | ConnectStyle::TransactionsFirstSkippingBlocks + | ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks + | ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks => { if i == count - 1 { node.chain_monitor.chain_monitor.best_block_updated(&prev.0.header, prev.1); node.node.best_block_updated(&prev.0.header, prev.1); } }, - ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::TransactionsFirstReorgsOnlyTip => { + ConnectStyle::BestBlockFirstReorgsOnlyTip + | ConnectStyle::TransactionsFirstReorgsOnlyTip => { for tx in orig.0.txdata { node.chain_monitor.chain_monitor.transaction_unconfirmed(&tx.compute_txid()); node.node.transaction_unconfirmed(&tx.compute_txid()); @@ -445,7 +507,9 @@ pub struct DedicatedEntropy(RandomBytes); impl Deref for DedicatedEntropy { type Target = RandomBytes; - fn deref(&self) -> &Self::Target { &self.0 } + fn deref(&self) -> &Self::Target { + &self.0 + } } pub struct Node<'chan_man, 'node_cfg: 'chan_man, 'chan_mon_cfg: 'node_cfg> { @@ -459,7 +523,11 @@ pub struct Node<'chan_man, 'node_cfg: 'chan_man, 'chan_mon_cfg: 'node_cfg> { pub node: &'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>, pub onion_messenger: TestOnionMessenger<'chan_man, 'node_cfg, 'chan_mon_cfg>, pub network_graph: &'node_cfg NetworkGraph<&'chan_mon_cfg test_utils::TestLogger>, - pub gossip_sync: P2PGossipSync<&'node_cfg NetworkGraph<&'chan_mon_cfg test_utils::TestLogger>, &'chan_mon_cfg test_utils::TestChainSource, &'chan_mon_cfg test_utils::TestLogger>, + pub gossip_sync: P2PGossipSync< + &'node_cfg NetworkGraph<&'chan_mon_cfg test_utils::TestLogger>, + &'chan_mon_cfg test_utils::TestChainSource, + &'chan_mon_cfg test_utils::TestLogger, + >, pub node_seed: [u8; 32], pub network_payment_count: Rc>, pub network_chan_count: Rc>, @@ -478,8 +546,9 @@ pub struct Node<'chan_man, 'node_cfg: 'chan_man, 'chan_mon_cfg: 'node_cfg> { impl<'a, 'b, 'c> Node<'a, 'b, 'c> { pub fn init_features(&self, peer_node_id: PublicKey) -> InitFeatures { - self.override_init_features.borrow().clone() - .unwrap_or_else(|| self.node.init_features() | self.onion_messenger.provided_init_features(peer_node_id)) + self.override_init_features.borrow().clone().unwrap_or_else(|| { + self.node.init_features() | self.onion_messenger.provided_init_features(peer_node_id) + }) } } @@ -515,7 +584,9 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> { /// Toggles this node's signer to be available for the given signer operation. /// This is useful for testing behavior for restoring an async signer that previously /// could not return a signature immediately. - pub fn enable_channel_signer_op(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp) { + pub fn enable_channel_signer_op( + &self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp, + ) { self.set_channel_signer_ops(peer_id, chan_id, signer_op, true); } @@ -523,7 +594,9 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> { /// This is useful for testing behavior for an async signer that cannot return a signature /// immediately. #[cfg(test)] - pub fn disable_channel_signer_op(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp) { + pub fn disable_channel_signer_op( + &self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp, + ) { self.set_channel_signer_ops(peer_id, chan_id, signer_op, false); } @@ -534,15 +607,24 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> { /// will behave normally, returning `Ok`. When set to `false`, and the channel signer will /// act like an off-line remote signer, returning `Err`. This applies to the signer in all /// relevant places, i.e. the channel manager, chain monitor, and the keys manager. - fn set_channel_signer_ops(&self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp, available: bool) { + fn set_channel_signer_ops( + &self, peer_id: &PublicKey, chan_id: &ChannelId, signer_op: SignerOp, available: bool, + ) { use crate::sign::ChannelSigner; - log_debug!(self.logger, "Setting channel signer for {} as available={}", chan_id, available); + log_debug!( + self.logger, + "Setting channel signer for {} as available={}", + chan_id, + available + ); let per_peer_state = self.node.per_peer_state.read().unwrap(); let mut chan_lock = per_peer_state.get(peer_id).unwrap().lock().unwrap(); let mut channel_keys_id = None; - if let Some(context) = chan_lock.channel_by_id.get_mut(chan_id).map(|chan| chan.context_mut()) { + if let Some(context) = + chan_lock.channel_by_id.get_mut(chan_id).map(|chan| chan.context_mut()) + { let signer = context.get_mut_signer().as_mut_ecdsa().unwrap(); if available { signer.enable_op(signer_op); @@ -596,10 +678,11 @@ impl NodePtr { unsafe impl Send for NodePtr {} unsafe impl Sync for NodePtr {} - pub trait NodeHolder { type CM: AChannelManager; - fn node(&self) -> &ChannelManager< + fn node( + &self, + ) -> &ChannelManager< ::M, ::T, ::ES, @@ -608,12 +691,15 @@ pub trait NodeHolder { ::F, ::R, ::MR, - ::L>; + ::L, + >; fn chain_monitor(&self) -> Option<&test_utils::TestChainMonitor>; } impl NodeHolder for &H { type CM = H::CM; - fn node(&self) -> &ChannelManager< + fn node( + &self, + ) -> &ChannelManager< ::M, ::T, ::ES, @@ -622,13 +708,22 @@ impl NodeHolder for &H { ::F, ::R, ::MR, - ::L> { (*self).node() } - fn chain_monitor(&self) -> Option<&test_utils::TestChainMonitor> { (*self).chain_monitor() } + ::L, + > { + (*self).node() + } + fn chain_monitor(&self) -> Option<&test_utils::TestChainMonitor> { + (*self).chain_monitor() + } } impl<'a, 'b: 'a, 'c: 'b> NodeHolder for Node<'a, 'b, 'c> { type CM = TestChannelManager<'b, 'c>; - fn node(&self) -> &TestChannelManager<'b, 'c> { &self.node } - fn chain_monitor(&self) -> Option<&test_utils::TestChainMonitor> { Some(self.chain_monitor) } + fn node(&self) -> &TestChannelManager<'b, 'c> { + &self.node + } + fn chain_monitor(&self) -> Option<&test_utils::TestChainMonitor> { + Some(self.chain_monitor) + } } impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { @@ -645,27 +740,33 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { } let added_monitors = self.chain_monitor.added_monitors.lock().unwrap().split_off(0); if !added_monitors.is_empty() { - panic!("Had {} excess added monitors on node {}", added_monitors.len(), self.logger.id); + panic!( + "Had {} excess added monitors on node {}", + added_monitors.len(), + self.logger.id + ); } let raa_blockers = self.node.get_and_clear_pending_raa_blockers(); if !raa_blockers.is_empty() { - panic!( "Had excess RAA blockers on node {}: {:?}", self.logger.id, raa_blockers); + panic!("Had excess RAA blockers on node {}: {:?}", self.logger.id, raa_blockers); } // Check that if we serialize the network graph, we can deserialize it again. let network_graph = { let mut w = test_utils::TestVecWriter(Vec::new()); self.network_graph.write(&mut w).unwrap(); - let network_graph_deser = >::read(&mut io::Cursor::new(&w.0), self.logger).unwrap(); + let network_graph_deser = + >::read(&mut io::Cursor::new(&w.0), self.logger).unwrap(); assert!(network_graph_deser == *self.network_graph); - let gossip_sync = P2PGossipSync::new( - &network_graph_deser, Some(self.chain_source), self.logger - ); + let gossip_sync = + P2PGossipSync::new(&network_graph_deser, Some(self.chain_source), self.logger); let mut chan_progress = 0; loop { - let orig_announcements = self.gossip_sync.get_next_channel_announcement(chan_progress); - let deserialized_announcements = gossip_sync.get_next_channel_announcement(chan_progress); + let orig_announcements = + self.gossip_sync.get_next_channel_announcement(chan_progress); + let deserialized_announcements = + gossip_sync.get_next_channel_announcement(chan_progress); assert!(orig_announcements == deserialized_announcements); chan_progress = match orig_announcements { Some(announcement) => announcement.0.contents.short_channel_id + 1, @@ -674,8 +775,10 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { } let mut node_progress = None; loop { - let orig_announcements = self.gossip_sync.get_next_node_announcement(node_progress.as_ref()); - let deserialized_announcements = gossip_sync.get_next_node_announcement(node_progress.as_ref()); + let orig_announcements = + self.gossip_sync.get_next_node_announcement(node_progress.as_ref()); + let deserialized_announcements = + gossip_sync.get_next_node_announcement(node_progress.as_ref()); assert!(orig_announcements == deserialized_announcements); node_progress = match orig_announcements { Some(announcement) => Some(announcement.contents.node_id), @@ -693,15 +796,26 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { { for channel_id in self.chain_monitor.chain_monitor.list_monitors() { let mut w = test_utils::TestVecWriter(Vec::new()); - self.chain_monitor.chain_monitor.get_monitor(channel_id).unwrap().write(&mut w).unwrap(); - let (_, deserialized_monitor) = <(BlockHash, ChannelMonitor)>::read( - &mut io::Cursor::new(&w.0), (self.keys_manager, self.keys_manager)).unwrap(); + self.chain_monitor + .chain_monitor + .get_monitor(channel_id) + .unwrap() + .write(&mut w) + .unwrap(); + let (_, deserialized_monitor) = + <(BlockHash, ChannelMonitor)>::read( + &mut io::Cursor::new(&w.0), + (self.keys_manager, self.keys_manager), + ) + .unwrap(); deserialized_monitors.push(deserialized_monitor); } } let broadcaster = test_utils::TestBroadcaster { - txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()), + txn_broadcasted: Mutex::new( + self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone(), + ), blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())), }; @@ -716,89 +830,144 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let scorer = RwLock::new(test_utils::TestScorer::new()); let mut w = test_utils::TestVecWriter(Vec::new()); self.node.write(&mut w).unwrap(); - <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestMessageRouter, &test_utils::TestLogger>)>::read(&mut io::Cursor::new(w.0), ChannelManagerReadArgs { - default_config: self.node.get_current_default_configuration().clone(), - entropy_source: self.keys_manager, - node_signer: self.keys_manager, - signer_provider: self.keys_manager, - fee_estimator: &test_utils::TestFeeEstimator::new(253), - router: &test_utils::TestRouter::new(Arc::clone(&network_graph), &self.logger, &scorer), - message_router: &test_utils::TestMessageRouter::new(network_graph, self.keys_manager), - chain_monitor: self.chain_monitor, - tx_broadcaster: &broadcaster, - logger: &self.logger, - channel_monitors, - }).unwrap(); + <( + BlockHash, + ChannelManager< + &test_utils::TestChainMonitor, + &test_utils::TestBroadcaster, + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestFeeEstimator, + &test_utils::TestRouter, + &test_utils::TestMessageRouter, + &test_utils::TestLogger, + >, + )>::read( + &mut io::Cursor::new(w.0), + ChannelManagerReadArgs { + default_config: self.node.get_current_default_configuration().clone(), + entropy_source: self.keys_manager, + node_signer: self.keys_manager, + signer_provider: self.keys_manager, + fee_estimator: &test_utils::TestFeeEstimator::new(253), + router: &test_utils::TestRouter::new( + Arc::clone(&network_graph), + &self.logger, + &scorer, + ), + message_router: &test_utils::TestMessageRouter::new( + network_graph, + self.keys_manager, + ), + chain_monitor: self.chain_monitor, + tx_broadcaster: &broadcaster, + logger: &self.logger, + channel_monitors, + }, + ) + .unwrap(); } let persister = test_utils::TestPersister::new(); let chain_source = test_utils::TestChainSource::new(Network::Testnet); - let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &broadcaster, &self.logger, &feeest, &persister, &self.keys_manager); + let chain_monitor = test_utils::TestChainMonitor::new( + Some(&chain_source), + &broadcaster, + &self.logger, + &feeest, + &persister, + &self.keys_manager, + ); for deserialized_monitor in deserialized_monitors.drain(..) { let channel_id = deserialized_monitor.channel_id(); - if chain_monitor.watch_channel(channel_id, deserialized_monitor) != Ok(ChannelMonitorUpdateStatus::Completed) { + if chain_monitor.watch_channel(channel_id, deserialized_monitor) + != Ok(ChannelMonitorUpdateStatus::Completed) + { panic!(); } } - assert_eq!(*chain_source.watched_txn.unsafe_well_ordered_double_lock_self(), *self.chain_source.watched_txn.unsafe_well_ordered_double_lock_self()); - assert_eq!(*chain_source.watched_outputs.unsafe_well_ordered_double_lock_self(), *self.chain_source.watched_outputs.unsafe_well_ordered_double_lock_self()); + assert_eq!( + *chain_source.watched_txn.unsafe_well_ordered_double_lock_self(), + *self.chain_source.watched_txn.unsafe_well_ordered_double_lock_self() + ); + assert_eq!( + *chain_source.watched_outputs.unsafe_well_ordered_double_lock_self(), + *self.chain_source.watched_outputs.unsafe_well_ordered_double_lock_self() + ); } } } -pub fn create_chan_between_nodes<'a, 'b, 'c: 'd, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { +pub fn create_chan_between_nodes<'a, 'b, 'c: 'd, 'd>( + node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, +) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { create_chan_between_nodes_with_value(node_a, node_b, 100000, 10001) } -pub fn create_chan_between_nodes_with_value<'a, 'b, 'c: 'd, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, channel_value: u64, push_msat: u64) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { - let (channel_ready, channel_id, tx) = create_chan_between_nodes_with_value_a(node_a, node_b, channel_value, push_msat); - let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(node_a, node_b, &channel_ready); +pub fn create_chan_between_nodes_with_value<'a, 'b, 'c: 'd, 'd>( + node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, channel_value: u64, push_msat: u64, +) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { + let (channel_ready, channel_id, tx) = + create_chan_between_nodes_with_value_a(node_a, node_b, channel_value, push_msat); + let (announcement, as_update, bs_update) = + create_chan_between_nodes_with_value_b(node_a, node_b, &channel_ready); (announcement, as_update, bs_update, channel_id, tx) } /// Gets an RAA and CS which were sent in response to a commitment update -pub fn get_revoke_commit_msgs>(node: &H, recipient: &PublicKey) -> (msgs::RevokeAndACK, Vec) { +pub fn get_revoke_commit_msgs>( + node: &H, recipient: &PublicKey, +) -> (msgs::RevokeAndACK, Vec) { let events = node.node().get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); - (match events[0] { - MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - assert_eq!(node_id, recipient); - (*msg).clone() + ( + match events[0] { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(node_id, recipient); + (*msg).clone() + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }, match events[1] { - MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, ref updates } => { - assert_eq!(node_id, recipient); - assert!(updates.update_add_htlcs.is_empty()); - assert!(updates.update_fulfill_htlcs.is_empty()); - assert!(updates.update_fail_htlcs.is_empty()); - assert!(updates.update_fail_malformed_htlcs.is_empty()); - assert!(updates.update_fee.is_none()); - assert!(updates.commitment_signed.iter().all(|cs| cs.channel_id == *channel_id)); - updates.commitment_signed.clone() + match events[1] { + MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, ref updates } => { + assert_eq!(node_id, recipient); + assert!(updates.update_add_htlcs.is_empty()); + assert!(updates.update_fulfill_htlcs.is_empty()); + assert!(updates.update_fail_htlcs.is_empty()); + assert!(updates.update_fail_malformed_htlcs.is_empty()); + assert!(updates.update_fee.is_none()); + assert!(updates.commitment_signed.iter().all(|cs| cs.channel_id == *channel_id)); + updates.commitment_signed.clone() + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }) + ) } /// Gets a `UpdateHTLCs` and `revoke_and_ack` (i.e. after we get a responding `commitment_signed` /// while we have updates in the holding cell). -pub fn get_updates_and_revoke>(node: &H, recipient: &PublicKey) -> (msgs::CommitmentUpdate, msgs::RevokeAndACK) { +pub fn get_updates_and_revoke>( + node: &H, recipient: &PublicKey, +) -> (msgs::CommitmentUpdate, msgs::RevokeAndACK) { let events = node.node().get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); - (match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, ref updates } => { - assert_eq!(node_id, recipient); - (*updates).clone() + ( + match events[0] { + MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, ref updates } => { + assert_eq!(node_id, recipient); + (*updates).clone() + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }, match events[1] { - MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - assert_eq!(node_id, recipient); - (*msg).clone() + match events[1] { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(node_id, recipient); + (*msg).clone() + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }) + ) } #[macro_export] @@ -808,25 +977,23 @@ pub fn get_updates_and_revoke>(node: & macro_rules! get_revoke_commit_msgs { ($node: expr, $node_id: expr) => { $crate::ln::functional_test_utils::get_revoke_commit_msgs(&$node, &$node_id) - } + }; } /// Get an specific event message from the pending events queue. #[macro_export] macro_rules! get_event_msg { - ($node: expr, $event_type: path, $node_id: expr) => { - { - let events = $node.node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match events[0] { - $event_type { ref node_id, ref msg } => { - assert_eq!(*node_id, $node_id); - (*msg).clone() - }, - _ => panic!("Unexpected event {:?}", events[0]), - } + ($node: expr, $event_type: path, $node_id: expr) => {{ + let events = $node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + $event_type { ref node_id, ref msg } => { + assert_eq!(*node_id, $node_id); + (*msg).clone() + }, + _ => panic!("Unexpected event {:?}", events[0]), } - } + }}; } /// Get an error message from the pending events queue. @@ -835,13 +1002,15 @@ pub fn get_err_msg(node: &Node, recipient: &PublicKey) -> msgs::ErrorMessage { assert_eq!(events.len(), 1); match events[0] { MessageSendEvent::HandleError { - action: msgs::ErrorAction::SendErrorMessage { ref msg }, ref node_id + action: msgs::ErrorAction::SendErrorMessage { ref msg }, + ref node_id, } => { assert_eq!(node_id, recipient); (*msg).clone() }, MessageSendEvent::HandleError { - action: msgs::ErrorAction::DisconnectPeer { ref msg }, ref node_id + action: msgs::ErrorAction::DisconnectPeer { ref msg }, + ref node_id, } => { assert_eq!(node_id, recipient); msg.as_ref().unwrap().clone() @@ -853,19 +1022,15 @@ pub fn get_err_msg(node: &Node, recipient: &PublicKey) -> msgs::ErrorMessage { /// Get a specific event from the pending events queue. #[macro_export] macro_rules! get_event { - ($node: expr, $event_type: path) => { - { - let mut events = $node.node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - let ev = events.pop().unwrap(); - match ev { - $event_type { .. } => { - ev - }, - _ => panic!("Unexpected event"), - } + ($node: expr, $event_type: path) => {{ + let mut events = $node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + let ev = events.pop().unwrap(); + match ev { + $event_type { .. } => ev, + _ => panic!("Unexpected event"), } - } + }}; } /// Gets an UpdateHTLCs MessageSendEvent @@ -888,7 +1053,7 @@ pub fn get_htlc_update_msgs(node: &Node, recipient: &PublicKey) -> msgs::Commitm macro_rules! get_htlc_update_msgs { ($node: expr, $node_id: expr) => { $crate::ln::functional_test_utils::get_htlc_update_msgs(&$node, &$node_id) - } + }; } /// Fetches the first `msg_event` to the passed `node_id` in the passed `msg_events` vec. @@ -897,123 +1062,49 @@ macro_rules! get_htlc_update_msgs { /// Note that even though `BroadcastChannelAnnouncement` and `BroadcastChannelUpdate` /// `msg_events` are stored under specific peers, this function does not fetch such `msg_events` as /// such messages are intended to all peers. -pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &mut Vec) -> MessageSendEvent { - let ev_index = msg_events.iter().position(|e| { match e { - MessageSendEvent::SendPeerStorage { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendPeerStorageRetrieval { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendAcceptChannel { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendOpenChannel { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendFundingCreated { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendFundingSigned { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendChannelReady { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendAnnouncementSignatures { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::UpdateHTLCs { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendRevokeAndACK { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendClosingSigned { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendShutdown { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendChannelReestablish { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendChannelAnnouncement { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::BroadcastChannelAnnouncement { .. } => { - false - }, - MessageSendEvent::BroadcastChannelUpdate { .. } => { - false - }, - MessageSendEvent::BroadcastNodeAnnouncement { .. } => { - false - }, - MessageSendEvent::SendChannelUpdate { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::HandleError { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendChannelRangeQuery { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendShortIdsQuery { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendReplyChannelRange { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendGossipTimestampFilter { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendAcceptChannelV2 { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendOpenChannelV2 { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendStfu { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendSpliceInit { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendSpliceAck { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendSpliceLocked { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxAddInput { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxAddOutput { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxRemoveInput { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxRemoveOutput { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxComplete { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxSignatures { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxInitRbf { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxAckRbf { node_id, .. } => { - node_id == msg_node_id - }, - MessageSendEvent::SendTxAbort { node_id, .. } => { - node_id == msg_node_id - }, - }}); +pub fn remove_first_msg_event_to_node( + msg_node_id: &PublicKey, msg_events: &mut Vec, +) -> MessageSendEvent { + let ev_index = msg_events.iter().position(|e| match e { + MessageSendEvent::SendPeerStorage { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendPeerStorageRetrieval { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendAcceptChannel { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendOpenChannel { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendFundingCreated { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendFundingSigned { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendChannelReady { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendAnnouncementSignatures { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::UpdateHTLCs { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendRevokeAndACK { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendClosingSigned { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendShutdown { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendChannelReestablish { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendChannelAnnouncement { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::BroadcastChannelAnnouncement { .. } => false, + MessageSendEvent::BroadcastChannelUpdate { .. } => false, + MessageSendEvent::BroadcastNodeAnnouncement { .. } => false, + MessageSendEvent::SendChannelUpdate { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::HandleError { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendChannelRangeQuery { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendShortIdsQuery { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendReplyChannelRange { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendGossipTimestampFilter { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendAcceptChannelV2 { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendOpenChannelV2 { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendStfu { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendSpliceInit { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendSpliceAck { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendSpliceLocked { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxAddInput { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxAddOutput { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxRemoveInput { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxRemoveOutput { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxComplete { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxSignatures { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxInitRbf { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxAckRbf { node_id, .. } => node_id == msg_node_id, + MessageSendEvent::SendTxAbort { node_id, .. } => node_id == msg_node_id, + }); if ev_index.is_some() { msg_events.remove(ev_index.unwrap()) } else { @@ -1023,57 +1114,64 @@ pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &mut #[cfg(any(test, feature = "_externalize_tests"))] macro_rules! get_channel_ref { - ($node: expr, $counterparty_node: expr, $per_peer_state_lock: ident, $peer_state_lock: ident, $channel_id: expr) => { - { - $per_peer_state_lock = $node.node.per_peer_state.read().unwrap(); - $peer_state_lock = $per_peer_state_lock.get(&$counterparty_node.node.get_our_node_id()).unwrap().lock().unwrap(); - $peer_state_lock.channel_by_id.get_mut(&$channel_id).unwrap() - } - } + ($node: expr, $counterparty_node: expr, $per_peer_state_lock: ident, $peer_state_lock: ident, $channel_id: expr) => {{ + $per_peer_state_lock = $node.node.per_peer_state.read().unwrap(); + $peer_state_lock = $per_peer_state_lock + .get(&$counterparty_node.node.get_our_node_id()) + .unwrap() + .lock() + .unwrap(); + $peer_state_lock.channel_by_id.get_mut(&$channel_id).unwrap() + }}; } #[cfg(any(test, feature = "_externalize_tests"))] macro_rules! get_feerate { - ($node: expr, $counterparty_node: expr, $channel_id: expr) => { - { - let mut per_peer_state_lock; - let mut peer_state_lock; - let chan = get_channel_ref!($node, $counterparty_node, per_peer_state_lock, peer_state_lock, $channel_id); - chan.context().get_feerate_sat_per_1000_weight() - } - } + ($node: expr, $counterparty_node: expr, $channel_id: expr) => {{ + let mut per_peer_state_lock; + let mut peer_state_lock; + let chan = get_channel_ref!( + $node, + $counterparty_node, + per_peer_state_lock, + peer_state_lock, + $channel_id + ); + chan.context().get_feerate_sat_per_1000_weight() + }}; } #[cfg(any(test, feature = "_externalize_tests"))] macro_rules! get_channel_type_features { - ($node: expr, $counterparty_node: expr, $channel_id: expr) => { - { - let mut per_peer_state_lock; - let mut peer_state_lock; - let chan = get_channel_ref!($node, $counterparty_node, per_peer_state_lock, peer_state_lock, $channel_id); - chan.funding().get_channel_type().clone() - } - } + ($node: expr, $counterparty_node: expr, $channel_id: expr) => {{ + let mut per_peer_state_lock; + let mut peer_state_lock; + let chan = get_channel_ref!( + $node, + $counterparty_node, + per_peer_state_lock, + peer_state_lock, + $channel_id + ); + chan.funding().get_channel_type().clone() + }}; } /// Returns a channel monitor given a channel id, making some naive assumptions #[macro_export] macro_rules! get_monitor { - ($node: expr, $channel_id: expr) => { - { - $node.chain_monitor.chain_monitor.get_monitor($channel_id).unwrap() - } - } + ($node: expr, $channel_id: expr) => {{ + $node.chain_monitor.chain_monitor.get_monitor($channel_id).unwrap() + }}; } /// Returns any local commitment transactions for the channel. #[macro_export] macro_rules! get_local_commitment_txn { - ($node: expr, $channel_id: expr) => { - { - $crate::get_monitor!($node, $channel_id).unsafe_get_latest_holder_commitment_txn(&$node.logger) - } - } + ($node: expr, $channel_id: expr) => {{ + $crate::get_monitor!($node, $channel_id) + .unsafe_get_latest_holder_commitment_txn(&$node.logger) + }}; } /// Check the error from attempting a payment. @@ -1084,28 +1182,24 @@ macro_rules! unwrap_send_err { let events = $node.node.get_and_clear_pending_events(); assert!(events.len() == 2); match &events[0] { - crate::events::Event::PaymentPathFailed { failure, .. } => { - match failure { - crate::events::PathFailure::InitialSend { err } => { - match err { - $type => { $check }, - _ => panic!() - } - }, - _ => panic!() - } + crate::events::Event::PaymentPathFailed { failure, .. } => match failure { + crate::events::PathFailure::InitialSend { err } => match err { + $type => $check, + _ => panic!(), + }, + _ => panic!(), }, - _ => panic!() + _ => panic!(), } match &events[1] { crate::events::Event::PaymentFailed { .. } => {}, - _ => panic!() + _ => panic!(), } - } + }; } /// Check whether N channel monitor(s) have been added. -pub fn check_added_monitors>(node: &H, count: usize) { +pub fn check_added_monitors>(node: &H, count: usize) { if let Some(chain_monitor) = node.chain_monitor() { let mut added_monitors = chain_monitor.added_monitors.lock().unwrap(); let n = added_monitors.len(); @@ -1121,21 +1215,26 @@ pub fn check_added_monitors>(node: &H, macro_rules! check_added_monitors { ($node: expr, $count: expr) => { $crate::ln::functional_test_utils::check_added_monitors(&$node, $count); - } + }; } -fn claimed_htlc_matches_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], htlc: &ClaimedHTLC) -> bool { +fn claimed_htlc_matches_path<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], htlc: &ClaimedHTLC, +) -> bool { let mut nodes = path.iter().rev(); let dest = nodes.next().expect("path should have a destination").node; let prev = nodes.next().unwrap_or(&origin_node).node; let dest_channels = dest.list_channels(); - let ch = dest_channels.iter().find(|ch| ch.channel_id == htlc.channel_id) + let ch = dest_channels + .iter() + .find(|ch| ch.channel_id == htlc.channel_id) .expect("HTLC's channel should be one of destination node's channels"); - htlc.user_channel_id == ch.user_channel_id && - ch.counterparty.node_id == prev.get_our_node_id() + htlc.user_channel_id == ch.user_channel_id && ch.counterparty.node_id == prev.get_our_node_id() } -fn check_claimed_htlcs_match_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: &[&[&Node<'a, 'b, 'c>]], htlcs: &[ClaimedHTLC]) { +fn check_claimed_htlcs_match_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, route: &[&[&Node<'a, 'b, 'c>]], htlcs: &[ClaimedHTLC], +) { assert_eq!(route.len(), htlcs.len()); for path in route { let mut found_matching_htlc = false; @@ -1149,12 +1248,18 @@ fn check_claimed_htlcs_match_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, r } } -pub fn _reload_node<'a, 'b, 'c>(node: &'a Node<'a, 'b, 'c>, default_config: UserConfig, chanman_encoded: &[u8], monitors_encoded: &[&[u8]]) -> TestChannelManager<'b, 'c> { +pub fn _reload_node<'a, 'b, 'c>( + node: &'a Node<'a, 'b, 'c>, default_config: UserConfig, chanman_encoded: &[u8], + monitors_encoded: &[&[u8]], +) -> TestChannelManager<'b, 'c> { let mut monitors_read = Vec::with_capacity(monitors_encoded.len()); for encoded in monitors_encoded { let mut monitor_read = &encoded[..]; - let (_, monitor) = <(BlockHash, ChannelMonitor)> - ::read(&mut monitor_read, (node.keys_manager, node.keys_manager)).unwrap(); + let (_, monitor) = <(BlockHash, ChannelMonitor)>::read( + &mut monitor_read, + (node.keys_manager, node.keys_manager), + ) + .unwrap(); assert!(monitor_read.is_empty()); monitors_read.push(monitor); } @@ -1165,26 +1270,32 @@ pub fn _reload_node<'a, 'b, 'c>(node: &'a Node<'a, 'b, 'c>, default_config: User for monitor in monitors_read.iter() { assert!(channel_monitors.insert(monitor.channel_id(), monitor).is_none()); } - <(BlockHash, TestChannelManager<'b, 'c>)>::read(&mut node_read, ChannelManagerReadArgs { - default_config, - entropy_source: node.keys_manager, - node_signer: node.keys_manager, - signer_provider: node.keys_manager, - fee_estimator: node.fee_estimator, - router: node.router, - message_router: node.message_router, - chain_monitor: node.chain_monitor, - tx_broadcaster: node.tx_broadcaster, - logger: node.logger, - channel_monitors, - }).unwrap() + <(BlockHash, TestChannelManager<'b, 'c>)>::read( + &mut node_read, + ChannelManagerReadArgs { + default_config, + entropy_source: node.keys_manager, + node_signer: node.keys_manager, + signer_provider: node.keys_manager, + fee_estimator: node.fee_estimator, + router: node.router, + message_router: node.message_router, + chain_monitor: node.chain_monitor, + tx_broadcaster: node.tx_broadcaster, + logger: node.logger, + channel_monitors, + }, + ) + .unwrap() }; assert!(node_read.is_empty()); for monitor in monitors_read.drain(..) { let channel_id = monitor.channel_id(); - assert_eq!(node.chain_monitor.watch_channel(channel_id, monitor), - Ok(ChannelMonitorUpdateStatus::Completed)); + assert_eq!( + node.chain_monitor.watch_channel(channel_id, monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); check_added_monitors!(node, 1); } @@ -1197,57 +1308,95 @@ macro_rules! reload_node { let chanman_encoded = $chanman_encoded; $persister = $crate::util::test_utils::TestPersister::new(); - $new_chain_monitor = $crate::util::test_utils::TestChainMonitor::new(Some($node.chain_source), $node.tx_broadcaster.clone(), $node.logger, $node.fee_estimator, &$persister, &$node.keys_manager); + $new_chain_monitor = $crate::util::test_utils::TestChainMonitor::new( + Some($node.chain_source), + $node.tx_broadcaster.clone(), + $node.logger, + $node.fee_estimator, + &$persister, + &$node.keys_manager, + ); $node.chain_monitor = &$new_chain_monitor; - $new_channelmanager = _reload_node(&$node, $new_config, &chanman_encoded, $monitors_encoded); + $new_channelmanager = + _reload_node(&$node, $new_config, &chanman_encoded, $monitors_encoded); $node.node = &$new_channelmanager; $node.onion_messenger.set_offers_handler(&$new_channelmanager); }; ($node: expr, $chanman_encoded: expr, $monitors_encoded: expr, $persister: ident, $new_chain_monitor: ident, $new_channelmanager: ident) => { - reload_node!($node, $crate::util::config::UserConfig::default(), $chanman_encoded, $monitors_encoded, $persister, $new_chain_monitor, $new_channelmanager); + reload_node!( + $node, + $crate::util::config::UserConfig::default(), + $chanman_encoded, + $monitors_encoded, + $persister, + $new_chain_monitor, + $new_channelmanager + ); }; } -pub fn create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, - expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, expected_user_chan_id: u128) - -> (ChannelId, Transaction, OutPoint) -{ - internal_create_funding_transaction(node, expected_counterparty_node_id, expected_chan_value, expected_user_chan_id, false) +pub fn create_funding_transaction<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, + expected_user_chan_id: u128, +) -> (ChannelId, Transaction, OutPoint) { + internal_create_funding_transaction( + node, + expected_counterparty_node_id, + expected_chan_value, + expected_user_chan_id, + false, + ) } -pub fn create_coinbase_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, - expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, expected_user_chan_id: u128) - -> (ChannelId, Transaction, OutPoint) -{ - internal_create_funding_transaction(node, expected_counterparty_node_id, expected_chan_value, expected_user_chan_id, true) +pub fn create_coinbase_funding_transaction<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, + expected_user_chan_id: u128, +) -> (ChannelId, Transaction, OutPoint) { + internal_create_funding_transaction( + node, + expected_counterparty_node_id, + expected_chan_value, + expected_user_chan_id, + true, + ) } -fn internal_create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, - expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, expected_user_chan_id: u128, - coinbase: bool) -> (ChannelId, Transaction, OutPoint) { +fn internal_create_funding_transaction<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, + expected_user_chan_id: u128, coinbase: bool, +) -> (ChannelId, Transaction, OutPoint) { let chan_id = *node.network_chan_count.borrow(); let events = node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::FundingGenerationReady { ref temporary_channel_id, ref counterparty_node_id, ref channel_value_satoshis, ref output_script, user_channel_id } => { + Event::FundingGenerationReady { + ref temporary_channel_id, + ref counterparty_node_id, + ref channel_value_satoshis, + ref output_script, + user_channel_id, + } => { assert_eq!(counterparty_node_id, expected_counterparty_node_id); assert_eq!(*channel_value_satoshis, expected_chan_value); assert_eq!(user_channel_id, expected_user_chan_id); let input = if coinbase { - vec![TxIn { - previous_output: bitcoin::OutPoint::null(), - ..Default::default() - }] + vec![TxIn { previous_output: bitcoin::OutPoint::null(), ..Default::default() }] } else { Vec::new() }; - let tx = Transaction { version: transaction::Version(chan_id as i32), lock_time: LockTime::ZERO, input, output: vec![TxOut { - value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(), - }]}; + let tx = Transaction { + version: transaction::Version(chan_id as i32), + lock_time: LockTime::ZERO, + input, + output: vec![TxOut { + value: Amount::from_sat(*channel_value_satoshis), + script_pubkey: output_script.clone(), + }], + }; let funding_outpoint = OutPoint { txid: tx.compute_txid(), index: 0 }; (*temporary_channel_id, tx, funding_outpoint) }, @@ -1264,22 +1413,27 @@ pub fn create_dual_funding_utxos_with_prev_txs( let tx = Transaction { version: TxVersion::TWO, lock_time: LockTime::from_height( - u32::from_be_bytes(node.keys_manager.get_secure_random_bytes()[0..4].try_into().unwrap()) % LOCK_TIME_THRESHOLD - ).unwrap(), + u32::from_be_bytes( + node.keys_manager.get_secure_random_bytes()[0..4].try_into().unwrap(), + ) % LOCK_TIME_THRESHOLD, + ) + .unwrap(), input: vec![], - output: utxo_values_in_satoshis.iter().map(|value_satoshis| TxOut { - value: Amount::from_sat(*value_satoshis), script_pubkey: ScriptBuf::new_p2wpkh(&WPubkeyHash::all_zeros()), - }).collect() + output: utxo_values_in_satoshis + .iter() + .map(|value_satoshis| TxOut { + value: Amount::from_sat(*value_satoshis), + script_pubkey: ScriptBuf::new_p2wpkh(&WPubkeyHash::all_zeros()), + }) + .collect(), }; let mut inputs = vec![]; for i in 0..utxo_values_in_satoshis.len() { - inputs.push( - (TxIn { - previous_output: OutPoint { - txid: tx.compute_txid(), - index: i as u16, - }.into_bitcoin_outpoint(), + inputs.push(( + TxIn { + previous_output: OutPoint { txid: tx.compute_txid(), index: i as u16 } + .into_bitcoin_outpoint(), script_sig: ScriptBuf::new(), sequence: Sequence::ZERO, witness: Witness::new(), @@ -1292,18 +1446,31 @@ pub fn create_dual_funding_utxos_with_prev_txs( inputs } -pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, expected_temporary_channel_id: ChannelId) -> Transaction { - let (temporary_channel_id, tx, _) = create_funding_transaction(node_a, &node_b.node.get_our_node_id(), channel_value, 42); +pub fn sign_funding_transaction<'a, 'b, 'c>( + node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, + expected_temporary_channel_id: ChannelId, +) -> Transaction { + let (temporary_channel_id, tx, _) = + create_funding_transaction(node_a, &node_b.node.get_our_node_id(), channel_value, 42); assert_eq!(temporary_channel_id, expected_temporary_channel_id); - assert!(node_a.node.funding_transaction_generated(temporary_channel_id, node_b.node.get_our_node_id(), tx.clone()).is_ok()); + assert!(node_a + .node + .funding_transaction_generated( + temporary_channel_id, + node_b.node.get_our_node_id(), + tx.clone() + ) + .is_ok()); check_added_monitors!(node_a, 0); - let funding_created_msg = get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id()); + let funding_created_msg = + get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id()); assert_eq!(funding_created_msg.temporary_channel_id, expected_temporary_channel_id); let channel_id = ChannelId::v1_from_funding_txid( - funding_created_msg.funding_txid.as_byte_array(), funding_created_msg.funding_output_index + funding_created_msg.funding_txid.as_byte_array(), + funding_created_msg.funding_output_index, ); node_b.node.handle_funding_created(node_a.node.get_our_node_id(), &funding_created_msg); @@ -1315,7 +1482,10 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: & } expect_channel_pending_event(&node_b, &node_a.node.get_our_node_id()); - node_a.node.handle_funding_signed(node_b.node.get_our_node_id(), &get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a.node.get_our_node_id())); + node_a.node.handle_funding_signed( + node_b.node.get_our_node_id(), + &get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a.node.get_our_node_id()), + ); { let mut added_monitors = node_a.chain_monitor.added_monitors.lock().unwrap(); assert_eq!(added_monitors.len(), 1); @@ -1332,7 +1502,14 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: & node_a.tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); // Ensure that funding_transaction_generated is idempotent. - assert!(node_a.node.funding_transaction_generated(temporary_channel_id, node_b.node.get_our_node_id(), tx.clone()).is_err()); + assert!(node_a + .node + .funding_transaction_generated( + temporary_channel_id, + node_b.node.get_our_node_id(), + tx.clone() + ) + .is_err()); assert!(node_a.node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(node_a, 0); @@ -1340,30 +1517,71 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: & } // Receiver must have been initialized with manually_accept_inbound_channels set to true. -pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, receiver: &'a Node<'b, 'c, 'd>, initiator_config: Option) -> (bitcoin::Transaction, ChannelId) { +pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>( + initiator: &'a Node<'b, 'c, 'd>, receiver: &'a Node<'b, 'c, 'd>, + initiator_config: Option, +) -> (bitcoin::Transaction, ChannelId) { let initiator_channels = initiator.node.list_usable_channels().len(); let receiver_channels = receiver.node.list_usable_channels().len(); - initiator.node.create_channel(receiver.node.get_our_node_id(), 100_000, 10_001, 42, None, initiator_config).unwrap(); - let open_channel = get_event_msg!(initiator, MessageSendEvent::SendOpenChannel, receiver.node.get_our_node_id()); + initiator + .node + .create_channel( + receiver.node.get_our_node_id(), + 100_000, + 10_001, + 42, + None, + initiator_config, + ) + .unwrap(); + let open_channel = get_event_msg!( + initiator, + MessageSendEvent::SendOpenChannel, + receiver.node.get_our_node_id() + ); receiver.node.handle_open_channel(initiator.node.get_our_node_id(), &open_channel); let events = receiver.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - receiver.node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &initiator.node.get_our_node_id(), 0, None).unwrap(); + receiver + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &initiator.node.get_our_node_id(), + 0, + None, + ) + .unwrap(); }, _ => panic!("Unexpected event"), }; - let accept_channel = get_event_msg!(receiver, MessageSendEvent::SendAcceptChannel, initiator.node.get_our_node_id()); + let accept_channel = get_event_msg!( + receiver, + MessageSendEvent::SendAcceptChannel, + initiator.node.get_our_node_id() + ); assert_eq!(accept_channel.common_fields.minimum_depth, 0); initiator.node.handle_accept_channel(receiver.node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, _) = create_funding_transaction(&initiator, &receiver.node.get_our_node_id(), 100_000, 42); - initiator.node.funding_transaction_generated(temporary_channel_id, receiver.node.get_our_node_id(), tx.clone()).unwrap(); - let funding_created = get_event_msg!(initiator, MessageSendEvent::SendFundingCreated, receiver.node.get_our_node_id()); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&initiator, &receiver.node.get_our_node_id(), 100_000, 42); + initiator + .node + .funding_transaction_generated( + temporary_channel_id, + receiver.node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); + let funding_created = get_event_msg!( + initiator, + MessageSendEvent::SendFundingCreated, + receiver.node.get_our_node_id() + ); receiver.node.handle_funding_created(initiator.node.get_our_node_id(), &funding_created); check_added_monitors!(receiver, 1); @@ -1379,10 +1597,17 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, r check_added_monitors!(initiator, 1); assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); - assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], tx); - - as_channel_ready = get_event_msg!(initiator, MessageSendEvent::SendChannelReady, receiver.node.get_our_node_id()); - } + assert_eq!( + initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], + tx + ); + + as_channel_ready = get_event_msg!( + initiator, + MessageSendEvent::SendChannelReady, + receiver.node.get_our_node_id() + ); + }, _ => panic!("Unexpected event"), } match &bs_signed_locked[1] { @@ -1390,15 +1615,23 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, r assert_eq!(*node_id, initiator.node.get_our_node_id()); initiator.node.handle_channel_ready(receiver.node.get_our_node_id(), &msg); expect_channel_ready_event(&initiator, &receiver.node.get_our_node_id()); - } + }, _ => panic!("Unexpected event"), } receiver.node.handle_channel_ready(initiator.node.get_our_node_id(), &as_channel_ready); expect_channel_ready_event(&receiver, &initiator.node.get_our_node_id()); - let as_channel_update = get_event_msg!(initiator, MessageSendEvent::SendChannelUpdate, receiver.node.get_our_node_id()); - let bs_channel_update = get_event_msg!(receiver, MessageSendEvent::SendChannelUpdate, initiator.node.get_our_node_id()); + let as_channel_update = get_event_msg!( + initiator, + MessageSendEvent::SendChannelUpdate, + receiver.node.get_our_node_id() + ); + let bs_channel_update = get_event_msg!( + receiver, + MessageSendEvent::SendChannelUpdate, + initiator.node.get_our_node_id() + ); initiator.node.handle_channel_update(receiver.node.get_our_node_id(), &bs_channel_update); receiver.node.handle_channel_update(initiator.node.get_our_node_id(), &as_channel_update); @@ -1409,69 +1642,122 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, r (tx, as_channel_ready.channel_id) } -pub fn exchange_open_accept_chan<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> ChannelId { - let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id()); +pub fn exchange_open_accept_chan<'a, 'b, 'c>( + node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64, +) -> ChannelId { + let create_chan_id = node_a + .node + .create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None) + .unwrap(); + let open_channel_msg = + get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id()); assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); - assert_eq!(node_a.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 42); + assert_eq!( + node_a + .node + .list_channels() + .iter() + .find(|channel| channel.channel_id == create_chan_id) + .unwrap() + .user_channel_id, + 42 + ); node_b.node.handle_open_channel(node_a.node.get_our_node_id(), &open_channel_msg); if node_b.node.get_current_default_configuration().manually_accept_inbound_channels { let events = node_b.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match &events[0] { - Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, .. } => - node_b.node.accept_inbound_channel(temporary_channel_id, counterparty_node_id, 42, None).unwrap(), + Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, .. } => node_b + .node + .accept_inbound_channel(temporary_channel_id, counterparty_node_id, 42, None) + .unwrap(), _ => panic!("Unexpected event"), }; } - let accept_channel_msg = get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id()); + let accept_channel_msg = + get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id()); assert_eq!(accept_channel_msg.common_fields.temporary_channel_id, create_chan_id); node_a.node.handle_accept_channel(node_b.node.get_our_node_id(), &accept_channel_msg); - assert_ne!(node_b.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 0); + assert_ne!( + node_b + .node + .list_channels() + .iter() + .find(|channel| channel.channel_id == create_chan_id) + .unwrap() + .user_channel_id, + 0 + ); create_chan_id } -pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> Transaction { +pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>( + node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64, +) -> Transaction { let create_chan_id = exchange_open_accept_chan(node_a, node_b, channel_value, push_msat); sign_funding_transaction(node_a, node_b, channel_value, create_chan_id) } -pub fn create_chan_between_nodes_with_value_confirm_first<'a, 'b, 'c, 'd>(node_recv: &'a Node<'b, 'c, 'c>, node_conf: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) { +pub fn create_chan_between_nodes_with_value_confirm_first<'a, 'b, 'c, 'd>( + node_recv: &'a Node<'b, 'c, 'c>, node_conf: &'a Node<'b, 'c, 'd>, tx: &Transaction, + conf_height: u32, +) { confirm_transaction_at(node_conf, tx, conf_height); connect_blocks(node_conf, CHAN_CONFIRM_DEPTH - 1); - node_recv.node.handle_channel_ready(node_conf.node.get_our_node_id(), &get_event_msg!(node_conf, MessageSendEvent::SendChannelReady, node_recv.node.get_our_node_id())); + node_recv.node.handle_channel_ready( + node_conf.node.get_our_node_id(), + &get_event_msg!( + node_conf, + MessageSendEvent::SendChannelReady, + node_recv.node.get_our_node_id() + ), + ); } -pub fn create_chan_between_nodes_with_value_confirm_second<'a, 'b, 'c>(node_recv: &Node<'a, 'b, 'c>, node_conf: &Node<'a, 'b, 'c>) -> ((msgs::ChannelReady, msgs::AnnouncementSignatures), ChannelId) { +pub fn create_chan_between_nodes_with_value_confirm_second<'a, 'b, 'c>( + node_recv: &Node<'a, 'b, 'c>, node_conf: &Node<'a, 'b, 'c>, +) -> ((msgs::ChannelReady, msgs::AnnouncementSignatures), ChannelId) { let channel_id; let events_6 = node_conf.node.get_and_clear_pending_msg_events(); assert_eq!(events_6.len(), 3); - let announcement_sigs_idx = if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = events_6[1] { - assert_eq!(*node_id, node_recv.node.get_our_node_id()); - 2 - } else if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = events_6[2] { - assert_eq!(*node_id, node_recv.node.get_our_node_id()); - 1 - } else { panic!("Unexpected event: {:?}", events_6[1]); }; - ((match events_6[0] { - MessageSendEvent::SendChannelReady { ref node_id, ref msg } => { - channel_id = msg.channel_id.clone(); + let announcement_sigs_idx = + if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = events_6[1] { assert_eq!(*node_id, node_recv.node.get_our_node_id()); - msg.clone() - }, - _ => panic!("Unexpected event"), - }, match events_6[announcement_sigs_idx] { - MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } => { + 2 + } else if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = events_6[2] { assert_eq!(*node_id, node_recv.node.get_our_node_id()); - msg.clone() - }, - _ => panic!("Unexpected event"), - }), channel_id) + 1 + } else { + panic!("Unexpected event: {:?}", events_6[1]); + }; + ( + ( + match events_6[0] { + MessageSendEvent::SendChannelReady { ref node_id, ref msg } => { + channel_id = msg.channel_id.clone(); + assert_eq!(*node_id, node_recv.node.get_our_node_id()); + msg.clone() + }, + _ => panic!("Unexpected event"), + }, + match events_6[announcement_sigs_idx] { + MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } => { + assert_eq!(*node_id, node_recv.node.get_our_node_id()); + msg.clone() + }, + _ => panic!("Unexpected event"), + }, + ), + channel_id, + ) } -pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c: 'd, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, tx: &Transaction) -> ((msgs::ChannelReady, msgs::AnnouncementSignatures), ChannelId) { - let conf_height = core::cmp::max(node_a.best_block_info().1 + 1, node_b.best_block_info().1 + 1); +pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c: 'd, 'd>( + node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, tx: &Transaction, +) -> ((msgs::ChannelReady, msgs::AnnouncementSignatures), ChannelId) { + let conf_height = + core::cmp::max(node_a.best_block_info().1 + 1, node_b.best_block_info().1 + 1); create_chan_between_nodes_with_value_confirm_first(node_a, node_b, tx, conf_height); confirm_transaction_at(node_a, tx, conf_height); connect_blocks(node_a, CHAN_CONFIRM_DEPTH - 1); @@ -1479,15 +1765,24 @@ pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c: 'd, 'd>(node_a: create_chan_between_nodes_with_value_confirm_second(node_b, node_a) } -pub fn create_chan_between_nodes_with_value_a<'a, 'b, 'c: 'd, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, channel_value: u64, push_msat: u64) -> ((msgs::ChannelReady, msgs::AnnouncementSignatures), ChannelId, Transaction) { +pub fn create_chan_between_nodes_with_value_a<'a, 'b, 'c: 'd, 'd>( + node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, channel_value: u64, push_msat: u64, +) -> ((msgs::ChannelReady, msgs::AnnouncementSignatures), ChannelId, Transaction) { let tx = create_chan_between_nodes_with_value_init(node_a, node_b, channel_value, push_msat); let (msgs, chan_id) = create_chan_between_nodes_with_value_confirm(node_a, node_b, &tx); (msgs, chan_id, tx) } -pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, as_funding_msgs: &(msgs::ChannelReady, msgs::AnnouncementSignatures)) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate) { +pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>( + node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, + as_funding_msgs: &(msgs::ChannelReady, msgs::AnnouncementSignatures), +) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate) { node_b.node.handle_channel_ready(node_a.node.get_our_node_id(), &as_funding_msgs.0); - let bs_announcement_sigs = get_event_msg!(node_b, MessageSendEvent::SendAnnouncementSignatures, node_a.node.get_our_node_id()); + let bs_announcement_sigs = get_event_msg!( + node_b, + MessageSendEvent::SendAnnouncementSignatures, + node_a.node.get_our_node_id() + ); node_b.node.handle_announcement_signatures(node_a.node.get_our_node_id(), &as_funding_msgs.1); let events_7 = node_b.node.get_and_clear_pending_msg_events(); @@ -1499,14 +1794,19 @@ pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>(node_a: &Node<'a, 'b, _ => panic!("Unexpected event"), }; - node_a.node.handle_announcement_signatures(node_b.node.get_our_node_id(), &bs_announcement_sigs); + node_a + .node + .handle_announcement_signatures(node_b.node.get_our_node_id(), &bs_announcement_sigs); let events_8 = node_a.node.get_and_clear_pending_msg_events(); assert_eq!(events_8.len(), 1); let as_update = match events_8[0] { MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => { assert!(*announcement == *msg); let update_msg = update_msg.clone().unwrap(); - assert_eq!(update_msg.contents.short_channel_id, announcement.contents.short_channel_id); + assert_eq!( + update_msg.contents.short_channel_id, + announcement.contents.short_channel_id + ); assert_eq!(update_msg.contents.short_channel_id, bs_update.contents.short_channel_id); update_msg }, @@ -1519,31 +1819,82 @@ pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>(node_a: &Node<'a, 'b, ((*announcement).clone(), as_update, bs_update) } -pub fn create_announced_chan_between_nodes<'a, 'b, 'c: 'd, 'd>(nodes: &'a Vec>, a: usize, b: usize) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { +pub fn create_announced_chan_between_nodes<'a, 'b, 'c: 'd, 'd>( + nodes: &'a Vec>, a: usize, b: usize, +) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { create_announced_chan_between_nodes_with_value(nodes, a, b, 100000, 10001) } -pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c: 'd, 'd>(nodes: &'a Vec>, a: usize, b: usize, channel_value: u64, push_msat: u64) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { - let chan_announcement = create_chan_between_nodes_with_value(&nodes[a], &nodes[b], channel_value, push_msat); - update_nodes_with_chan_announce(nodes, a, b, &chan_announcement.0, &chan_announcement.1, &chan_announcement.2); +pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c: 'd, 'd>( + nodes: &'a Vec>, a: usize, b: usize, channel_value: u64, push_msat: u64, +) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction) { + let chan_announcement = + create_chan_between_nodes_with_value(&nodes[a], &nodes[b], channel_value, push_msat); + update_nodes_with_chan_announce( + nodes, + a, + b, + &chan_announcement.0, + &chan_announcement.1, + &chan_announcement.2, + ); (chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4) } -pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a Vec>, a: usize, b: usize, channel_value: u64, push_msat: u64) -> (msgs::ChannelReady, Transaction) { +pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>( + nodes: &'a Vec>, a: usize, b: usize, channel_value: u64, push_msat: u64, +) -> (msgs::ChannelReady, Transaction) { let mut no_announce_cfg = nodes[a].node.get_current_default_configuration().clone(); no_announce_cfg.channel_handshake_config.announce_for_forwarding = false; - nodes[a].node.create_channel(nodes[b].node.get_our_node_id(), channel_value, push_msat, 42, None, Some(no_announce_cfg)).unwrap(); - let open_channel = get_event_msg!(nodes[a], MessageSendEvent::SendOpenChannel, nodes[b].node.get_our_node_id()); + nodes[a] + .node + .create_channel( + nodes[b].node.get_our_node_id(), + channel_value, + push_msat, + 42, + None, + Some(no_announce_cfg), + ) + .unwrap(); + let open_channel = get_event_msg!( + nodes[a], + MessageSendEvent::SendOpenChannel, + nodes[b].node.get_our_node_id() + ); nodes[b].node.handle_open_channel(nodes[a].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[b], MessageSendEvent::SendAcceptChannel, nodes[a].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[b], + MessageSendEvent::SendAcceptChannel, + nodes[a].node.get_our_node_id() + ); nodes[a].node.handle_accept_channel(nodes[b].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[a], &nodes[b].node.get_our_node_id(), channel_value, 42); - nodes[a].node.funding_transaction_generated(temporary_channel_id, nodes[b].node.get_our_node_id(), tx.clone()).unwrap(); - nodes[b].node.handle_funding_created(nodes[a].node.get_our_node_id(), &get_event_msg!(nodes[a], MessageSendEvent::SendFundingCreated, nodes[b].node.get_our_node_id())); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[a], &nodes[b].node.get_our_node_id(), channel_value, 42); + nodes[a] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[b].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); + nodes[b].node.handle_funding_created( + nodes[a].node.get_our_node_id(), + &get_event_msg!( + nodes[a], + MessageSendEvent::SendFundingCreated, + nodes[b].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[b], 1); - let cs_funding_signed = get_event_msg!(nodes[b], MessageSendEvent::SendFundingSigned, nodes[a].node.get_our_node_id()); + let cs_funding_signed = get_event_msg!( + nodes[b], + MessageSendEvent::SendFundingSigned, + nodes[a].node.get_our_node_id() + ); expect_channel_pending_event(&nodes[b], &nodes[a].node.get_our_node_id()); nodes[a].node.handle_funding_signed(nodes[b].node.get_our_node_id(), &cs_funding_signed); @@ -1554,18 +1905,38 @@ pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: & assert_eq!(nodes[a].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx); nodes[a].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); - let conf_height = core::cmp::max(nodes[a].best_block_info().1 + 1, nodes[b].best_block_info().1 + 1); + let conf_height = + core::cmp::max(nodes[a].best_block_info().1 + 1, nodes[b].best_block_info().1 + 1); confirm_transaction_at(&nodes[a], &tx, conf_height); connect_blocks(&nodes[a], CHAN_CONFIRM_DEPTH - 1); confirm_transaction_at(&nodes[b], &tx, conf_height); connect_blocks(&nodes[b], CHAN_CONFIRM_DEPTH - 1); - let as_channel_ready = get_event_msg!(nodes[a], MessageSendEvent::SendChannelReady, nodes[b].node.get_our_node_id()); - nodes[a].node.handle_channel_ready(nodes[b].node.get_our_node_id(), &get_event_msg!(nodes[b], MessageSendEvent::SendChannelReady, nodes[a].node.get_our_node_id())); + let as_channel_ready = get_event_msg!( + nodes[a], + MessageSendEvent::SendChannelReady, + nodes[b].node.get_our_node_id() + ); + nodes[a].node.handle_channel_ready( + nodes[b].node.get_our_node_id(), + &get_event_msg!( + nodes[b], + MessageSendEvent::SendChannelReady, + nodes[a].node.get_our_node_id() + ), + ); expect_channel_ready_event(&nodes[a], &nodes[b].node.get_our_node_id()); - let as_update = get_event_msg!(nodes[a], MessageSendEvent::SendChannelUpdate, nodes[b].node.get_our_node_id()); + let as_update = get_event_msg!( + nodes[a], + MessageSendEvent::SendChannelUpdate, + nodes[b].node.get_our_node_id() + ); nodes[b].node.handle_channel_ready(nodes[a].node.get_our_node_id(), &as_channel_ready); expect_channel_ready_event(&nodes[b], &nodes[a].node.get_our_node_id()); - let bs_update = get_event_msg!(nodes[b], MessageSendEvent::SendChannelUpdate, nodes[a].node.get_our_node_id()); + let bs_update = get_event_msg!( + nodes[b], + MessageSendEvent::SendChannelUpdate, + nodes[a].node.get_our_node_id() + ); nodes[a].node.handle_channel_update(nodes[b].node.get_our_node_id(), &bs_update); nodes[b].node.handle_channel_update(nodes[a].node.get_our_node_id(), &as_update); @@ -1593,7 +1964,10 @@ pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: & (as_channel_ready, tx) } -pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate) { +pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>( + nodes: &'a Vec>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, + upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate, +) { for node in nodes { let node_id_a = nodes[a].node.get_our_node_id(); let node_id_b = nodes[b].node.get_our_node_id(); @@ -1608,9 +1982,14 @@ pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec Option>(tx: &Transaction, get_output: F) { +pub fn do_check_spends Option>( + tx: &Transaction, get_output: F, +) { for outp in tx.output.iter() { - assert!(outp.value >= outp.script_pubkey.minimal_non_dust(), "Spending tx output didn't meet dust limit"); + assert!( + outp.value >= outp.script_pubkey.minimal_non_dust(), + "Spending tx output didn't meet dust limit" + ); } let mut total_value_in = 0; for input in tx.input.iter() { @@ -1621,7 +2000,7 @@ pub fn do_check_spends Option>( total_value_out += output.value.to_sat(); } let min_fee = (tx.weight().to_wu() as u64 + 3) / 4; // One sat per vbyte (ie per weight/4, rounded up) - // Input amount - output amount = fee, so check that out + min_fee is smaller than input + // Input amount - output amount = fee, so check that out + min_fee is smaller than input assert!(total_value_out + min_fee <= total_value_in); tx.verify(get_output).unwrap(); } @@ -1649,17 +2028,18 @@ macro_rules! check_spends { } macro_rules! get_closing_signed_broadcast { - ($node: expr, $dest_pubkey: expr) => { - { - let events = $node.get_and_clear_pending_msg_events(); - assert!(events.len() == 1 || events.len() == 2); - (match events[events.len() - 1] { + ($node: expr, $dest_pubkey: expr) => {{ + let events = $node.get_and_clear_pending_msg_events(); + assert!(events.len() == 1 || events.len() == 2); + ( + match events[events.len() - 1] { MessageSendEvent::BroadcastChannelUpdate { ref msg } => { assert_eq!(msg.contents.channel_flags & 2, 2); msg.clone() }, _ => panic!("Unexpected event"), - }, if events.len() == 2 { + }, + if events.len() == 2 { match events[0] { MessageSendEvent::SendClosingSigned { ref node_id, ref msg } => { assert_eq!(*node_id, $dest_pubkey); @@ -1667,9 +2047,11 @@ macro_rules! get_closing_signed_broadcast { }, _ => panic!("Unexpected event"), } - } else { None }) - } - } + } else { + None + }, + ) + }}; } #[cfg(test)] @@ -1678,14 +2060,17 @@ macro_rules! check_warn_msg { let msg_events = $node.node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); match msg_events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendWarningMessage { ref msg, log_level: _ }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendWarningMessage { ref msg, log_level: _ }, + node_id, + } => { assert_eq!(node_id, $recipient_node_id); assert_eq!(msg.channel_id, $chan_id); msg.data.clone() }, _ => panic!("Unexpected event"), } - }} + }}; } /// Checks if at least one peer is connected. @@ -1693,14 +2078,18 @@ fn is_any_peer_connected(node: &Node) -> bool { let peer_state = node.node.per_peer_state.read().unwrap(); for (_, peer_mutex) in peer_state.iter() { let peer = peer_mutex.lock().unwrap(); - if peer.is_connected { return true; } + if peer.is_connected { + return true; + } } false } /// Check that a channel's closing channel update has been broadcasted, and optionally /// check whether an error message event has occurred. -pub fn check_closed_broadcast(node: &Node, num_channels: usize, with_error_msg: bool) -> Vec { +pub fn check_closed_broadcast( + node: &Node, num_channels: usize, with_error_msg: bool, +) -> Vec { let mut dummy_connected = false; if !is_any_peer_connected(&node) { connect_dummy_node(&node); @@ -1711,25 +2100,34 @@ pub fn check_closed_broadcast(node: &Node, num_channels: usize, with_error_msg: if dummy_connected { disconnect_dummy_node(&node); } - msg_events.into_iter().filter_map(|msg_event| { - match msg_event { - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - assert_eq!(msg.contents.channel_flags & 2, 2); - None - }, - MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { msg }, node_id: _ } => { - assert!(with_error_msg); - // TODO: Check node_id - Some(msg) - }, - MessageSendEvent::HandleError { action: msgs::ErrorAction::DisconnectPeer { msg }, node_id: _ } => { - assert!(with_error_msg); - // TODO: Check node_id - Some(msg.unwrap()) - }, - _ => panic!("Unexpected event"), - } - }).collect() + msg_events + .into_iter() + .filter_map(|msg_event| { + match msg_event { + MessageSendEvent::BroadcastChannelUpdate { ref msg } => { + assert_eq!(msg.contents.channel_flags & 2, 2); + None + }, + MessageSendEvent::HandleError { + action: msgs::ErrorAction::SendErrorMessage { msg }, + node_id: _, + } => { + assert!(with_error_msg); + // TODO: Check node_id + Some(msg) + }, + MessageSendEvent::HandleError { + action: msgs::ErrorAction::DisconnectPeer { msg }, + node_id: _, + } => { + assert!(with_error_msg); + // TODO: Check node_id + Some(msg.unwrap()) + }, + _ => panic!("Unexpected event"), + } + }) + .collect() } /// Check that a channel's closing channel update has been broadcasted, and optionally @@ -1740,7 +2138,7 @@ pub fn check_closed_broadcast(node: &Node, num_channels: usize, with_error_msg: macro_rules! check_closed_broadcast { ($node: expr, $with_error_msg: expr) => { $crate::ln::functional_test_utils::check_closed_broadcast(&$node, 1, $with_error_msg).pop() - } + }; } #[derive(Default)] @@ -1755,7 +2153,9 @@ pub struct ExpectedCloseEvent { } impl ExpectedCloseEvent { - pub fn from_id_reason(channel_id: ChannelId, discard_funding: bool, reason: ClosureReason) -> Self { + pub fn from_id_reason( + channel_id: ChannelId, discard_funding: bool, reason: ClosureReason, + ) -> Self { Self { channel_capacity_sats: None, channel_id: Some(channel_id), @@ -1799,30 +2199,36 @@ pub fn check_closed_events(node: &Node, expected_close_events: &[ExpectedCloseEv ) ))); } - assert_eq!(events.iter().filter(|e| matches!( - e, - Event::DiscardFunding { .. }, - )).count(), discard_events_count); + assert_eq!( + events.iter().filter(|e| matches!(e, Event::DiscardFunding { .. },)).count(), + discard_events_count + ); } /// Check that a channel's closing channel events has been issued -pub fn check_closed_event(node: &Node, events_count: usize, expected_reason: ClosureReason, is_check_discard_funding: bool, - expected_counterparty_node_ids: &[PublicKey], expected_channel_capacity: u64) { +pub fn check_closed_event( + node: &Node, events_count: usize, expected_reason: ClosureReason, + is_check_discard_funding: bool, expected_counterparty_node_ids: &[PublicKey], + expected_channel_capacity: u64, +) { let expected_events_count = if is_check_discard_funding { 2 * expected_counterparty_node_ids.len() } else { expected_counterparty_node_ids.len() }; assert_eq!(events_count, expected_events_count); - let expected_close_events = expected_counterparty_node_ids.iter().map(|node_id| ExpectedCloseEvent { - channel_capacity_sats: Some(expected_channel_capacity), - channel_id: None, - counterparty_node_id: Some(*node_id), - discard_funding: is_check_discard_funding, - reason: Some(expected_reason.clone()), - channel_funding_txo: None, - user_channel_id: None, - }).collect::>(); + let expected_close_events = expected_counterparty_node_ids + .iter() + .map(|node_id| ExpectedCloseEvent { + channel_capacity_sats: Some(expected_channel_capacity), + channel_id: None, + counterparty_node_id: Some(*node_id), + discard_funding: is_check_discard_funding, + reason: Some(expected_reason.clone()), + channel_funding_txo: None, + user_channel_id: None, + }) + .collect::>(); check_closed_events(node, expected_close_events.as_slice()); } @@ -1832,12 +2238,25 @@ pub fn check_closed_event(node: &Node, events_count: usize, expected_reason: Clo #[macro_export] macro_rules! check_closed_event { ($node: expr, $events: expr, $reason: expr, $counterparty_node_ids: expr, $channel_capacity: expr) => { - check_closed_event!($node, $events, $reason, false, $counterparty_node_ids, $channel_capacity); + check_closed_event!( + $node, + $events, + $reason, + false, + $counterparty_node_ids, + $channel_capacity + ); }; ($node: expr, $events: expr, $reason: expr, $is_check_discard_funding: expr, $counterparty_node_ids: expr, $channel_capacity: expr) => { - $crate::ln::functional_test_utils::check_closed_event(&$node, $events, $reason, - $is_check_discard_funding, &$counterparty_node_ids, $channel_capacity); - } + $crate::ln::functional_test_utils::check_closed_event( + &$node, + $events, + $reason, + $is_check_discard_funding, + &$counterparty_node_ids, + $channel_capacity, + ); + }; } pub fn handle_bump_htlc_event(node: &Node, count: usize) { @@ -1846,8 +2265,10 @@ pub fn handle_bump_htlc_event(node: &Node, count: usize) { for event in events { match event { Event::BumpTransaction(bump_event) => { - if let BumpTransactionEvent::HTLCResolution { .. } = &bump_event {} - else { panic!(); } + if let BumpTransactionEvent::HTLCResolution { .. } = &bump_event { + } else { + panic!(); + } node.bump_tx_handler.handle_event(&bump_event); }, _ => panic!(), @@ -1855,13 +2276,27 @@ pub fn handle_bump_htlc_event(node: &Node, count: usize) { } } -pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: &Node<'a, 'b, 'c>, channel_id: &ChannelId, funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Transaction) { - let (node_a, broadcaster_a, struct_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) } else { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) }; - let (node_b, broadcaster_b, struct_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) } else { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) }; +pub fn close_channel<'a, 'b, 'c>( + outbound_node: &Node<'a, 'b, 'c>, inbound_node: &Node<'a, 'b, 'c>, channel_id: &ChannelId, + funding_tx: Transaction, close_inbound_first: bool, +) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Transaction) { + let (node_a, broadcaster_a, struct_a) = if close_inbound_first { + (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) + } else { + (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) + }; + let (node_b, broadcaster_b, struct_b) = if close_inbound_first { + (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) + } else { + (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) + }; let (tx_a, tx_b); node_a.close_channel(channel_id, &node_b.get_our_node_id()).unwrap(); - node_b.handle_shutdown(node_a.get_our_node_id(), &get_event_msg!(struct_a, MessageSendEvent::SendShutdown, node_b.get_our_node_id())); + node_b.handle_shutdown( + node_a.get_our_node_id(), + &get_event_msg!(struct_a, MessageSendEvent::SendShutdown, node_b.get_our_node_id()), + ); let events_1 = node_b.get_and_clear_pending_msg_events(); assert!(events_1.len() >= 1); @@ -1891,10 +2326,18 @@ pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: assert!(node_a.get_and_clear_pending_msg_events().is_empty()); node_a.handle_closing_signed(node_b.get_our_node_id(), &closing_signed_b.unwrap()); - node_b.handle_closing_signed(node_a.get_our_node_id(), &get_event_msg!(struct_a, MessageSendEvent::SendClosingSigned, node_b.get_our_node_id())); + node_b.handle_closing_signed( + node_a.get_our_node_id(), + &get_event_msg!( + struct_a, + MessageSendEvent::SendClosingSigned, + node_b.get_our_node_id() + ), + ); assert_eq!(broadcaster_b.txn_broadcasted.lock().unwrap().len(), 1); tx_b = broadcaster_b.txn_broadcasted.lock().unwrap().remove(0); - let (bs_update, closing_signed_b) = get_closing_signed_broadcast!(node_b, node_a.get_our_node_id()); + let (bs_update, closing_signed_b) = + get_closing_signed_broadcast!(node_b, node_a.get_our_node_id()); node_a.handle_closing_signed(node_b.get_our_node_id(), &closing_signed_b.unwrap()); let (as_update, none_a) = get_closing_signed_broadcast!(node_a, node_b.get_our_node_id()); @@ -1903,14 +2346,23 @@ pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: tx_a = broadcaster_a.txn_broadcasted.lock().unwrap().remove(0); (as_update, bs_update) } else { - let closing_signed_a = get_event_msg!(struct_a, MessageSendEvent::SendClosingSigned, node_b.get_our_node_id()); + let closing_signed_a = + get_event_msg!(struct_a, MessageSendEvent::SendClosingSigned, node_b.get_our_node_id()); node_b.handle_closing_signed(node_a.get_our_node_id(), &closing_signed_a); - node_a.handle_closing_signed(node_b.get_our_node_id(), &get_event_msg!(struct_b, MessageSendEvent::SendClosingSigned, node_a.get_our_node_id())); + node_a.handle_closing_signed( + node_b.get_our_node_id(), + &get_event_msg!( + struct_b, + MessageSendEvent::SendClosingSigned, + node_a.get_our_node_id() + ), + ); assert_eq!(broadcaster_a.txn_broadcasted.lock().unwrap().len(), 1); tx_a = broadcaster_a.txn_broadcasted.lock().unwrap().remove(0); - let (as_update, closing_signed_a) = get_closing_signed_broadcast!(node_a, node_b.get_our_node_id()); + let (as_update, closing_signed_a) = + get_closing_signed_broadcast!(node_a, node_b.get_our_node_id()); node_b.handle_closing_signed(node_a.get_our_node_id(), &closing_signed_a.unwrap()); let (bs_update, none_b) = get_closing_signed_broadcast!(node_b, node_a.get_our_node_id()); @@ -1932,17 +2384,26 @@ pub struct SendEvent { pub commitment_msg: Vec, } impl SendEvent { - pub fn from_commitment_update(node_id: PublicKey, channel_id: ChannelId, updates: msgs::CommitmentUpdate) -> SendEvent { + pub fn from_commitment_update( + node_id: PublicKey, channel_id: ChannelId, updates: msgs::CommitmentUpdate, + ) -> SendEvent { assert!(updates.update_fulfill_htlcs.is_empty()); assert!(updates.update_fail_htlcs.is_empty()); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - SendEvent { node_id, channel_id, msgs: updates.update_add_htlcs, commitment_msg: updates.commitment_signed } + SendEvent { + node_id, + channel_id, + msgs: updates.update_add_htlcs, + commitment_msg: updates.commitment_signed, + } } pub fn from_event(event: MessageSendEvent) -> SendEvent { match event { - MessageSendEvent::UpdateHTLCs { node_id, channel_id, updates } => SendEvent::from_commitment_update(node_id, channel_id, updates), + MessageSendEvent::UpdateHTLCs { node_id, channel_id, updates } => { + SendEvent::from_commitment_update(node_id, channel_id, updates) + }, _ => panic!("Unexpected event type!"), } } @@ -1958,8 +2419,11 @@ impl SendEvent { /// Don't use this, use the identically-named function instead. macro_rules! expect_pending_htlcs_forwardable_conditions { ($node: expr, $expected_failures: expr) => { - $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions($node.node.get_and_clear_pending_events(), &$expected_failures); - } + $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions( + $node.node.get_and_clear_pending_events(), + &$expected_failures, + ); + }; } #[macro_export] @@ -1968,8 +2432,10 @@ macro_rules! expect_htlc_handling_failed_destinations { let mut num_expected_failures = $expected_failures.len(); for event in $events { match event { - $crate::events::Event::PendingHTLCsForwardable { .. } => { }, - $crate::events::Event::HTLCHandlingFailed { ref failed_next_destination, .. } => { + $crate::events::Event::PendingHTLCsForwardable { .. } => {}, + $crate::events::Event::HTLCHandlingFailed { + ref failed_next_destination, .. + } => { assert!($expected_failures.contains(&failed_next_destination)); num_expected_failures -= 1; }, @@ -1977,16 +2443,21 @@ macro_rules! expect_htlc_handling_failed_destinations { } } assert_eq!(num_expected_failures, 0); - }} + }}; } /// Checks that an [`Event::PendingHTLCsForwardable`] is available in the given events and, if /// there are any [`Event::HTLCHandlingFailed`] events their [`HTLCDestination`] is included in the /// `expected_failures` set. -pub fn expect_pending_htlcs_forwardable_conditions(events: Vec, expected_failures: &[HTLCDestination]) { +pub fn expect_pending_htlcs_forwardable_conditions( + events: Vec, expected_failures: &[HTLCDestination], +) { let count = expected_failures.len() + 1; assert_eq!(events.len(), count); - assert!(events.iter().find(|event| matches!(event, Event::PendingHTLCsForwardable { .. })).is_some()); + assert!(events + .iter() + .find(|event| matches!(event, Event::PendingHTLCsForwardable { .. })) + .is_some()); if expected_failures.len() > 0 { expect_htlc_handling_failed_destinations!(events, expected_failures) } @@ -1999,8 +2470,11 @@ pub fn expect_pending_htlcs_forwardable_conditions(events: Vec, expected_ /// set instead. macro_rules! expect_pending_htlcs_forwardable_ignore { ($node: expr) => { - $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions($node.node.get_and_clear_pending_events(), &[]); - } + $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions( + $node.node.get_and_clear_pending_events(), + &[], + ); + }; } #[macro_export] @@ -2009,15 +2483,21 @@ macro_rules! expect_pending_htlcs_forwardable_ignore { /// Don't use this, call [`expect_pending_htlcs_forwardable_conditions()`] instead. macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore { ($node: expr, $expected_failures: expr) => { - $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions($node.node.get_and_clear_pending_events(), &$expected_failures); - } + $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions( + $node.node.get_and_clear_pending_events(), + &$expected_failures, + ); + }; } #[macro_export] /// Handles a PendingHTLCsForwardable event macro_rules! expect_pending_htlcs_forwardable { ($node: expr) => {{ - $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions($node.node.get_and_clear_pending_events(), &[]); + $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions( + $node.node.get_and_clear_pending_events(), + &[], + ); $node.node.process_pending_htlc_forwards(); // Ensure process_pending_htlc_forwards is idempotent. @@ -2029,12 +2509,15 @@ macro_rules! expect_pending_htlcs_forwardable { /// Handles a PendingHTLCsForwardable and HTLCHandlingFailed event macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed { ($node: expr, $expected_failures: expr) => {{ - $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions($node.node.get_and_clear_pending_events(), &$expected_failures); + $crate::ln::functional_test_utils::expect_pending_htlcs_forwardable_conditions( + $node.node.get_and_clear_pending_events(), + &$expected_failures, + ); $node.node.process_pending_htlc_forwards(); // Ensure process_pending_htlc_forwards is idempotent. $node.node.process_pending_htlc_forwards(); - }} + }}; } #[cfg(any(test, feature = "_externalize_tests"))] @@ -2042,7 +2525,7 @@ macro_rules! expect_pending_htlcs_forwardable_from_events { ($node: expr, $events: expr, $ignore: expr) => {{ assert_eq!($events.len(), 1); match $events[0] { - Event::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event"), }; if $ignore { @@ -2051,7 +2534,7 @@ macro_rules! expect_pending_htlcs_forwardable_from_events { // Ensure process_pending_htlc_forwards is idempotent. $node.node.process_pending_htlc_forwards(); } - }} + }}; } #[macro_export] @@ -2059,28 +2542,56 @@ macro_rules! expect_pending_htlcs_forwardable_from_events { /// commitment update. macro_rules! commitment_signed_dance { ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */) => { - $crate::ln::functional_test_utils::do_commitment_signed_dance(&$node_a, &$node_b, &$commitment_signed, $fail_backwards, true); + $crate::ln::functional_test_utils::do_commitment_signed_dance( + &$node_a, + &$node_b, + &$commitment_signed, + $fail_backwards, + true, + ); }; ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, true /* return extra message */, true /* return last RAA */) => { - $crate::ln::functional_test_utils::do_main_commitment_signed_dance(&$node_a, &$node_b, $fail_backwards) - }; - ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */, false /* return extra message */, true /* return last RAA */) => { - { - $crate::ln::functional_test_utils::check_added_monitors(&$node_a, 0); - assert!($node_a.node.get_and_clear_pending_msg_events().is_empty()); - $node_a.node.handle_commitment_signed_batch_test($node_b.node.get_our_node_id(), &$commitment_signed); - check_added_monitors(&$node_a, 1); - let (extra_msg_option, bs_revoke_and_ack) = $crate::ln::functional_test_utils::do_main_commitment_signed_dance(&$node_a, &$node_b, $fail_backwards); - assert!(extra_msg_option.is_none()); - bs_revoke_and_ack - } + $crate::ln::functional_test_utils::do_main_commitment_signed_dance( + &$node_a, + &$node_b, + $fail_backwards, + ) }; + ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */, false /* return extra message */, true /* return last RAA */) => {{ + $crate::ln::functional_test_utils::check_added_monitors(&$node_a, 0); + assert!($node_a.node.get_and_clear_pending_msg_events().is_empty()); + $node_a.node.handle_commitment_signed_batch_test( + $node_b.node.get_our_node_id(), + &$commitment_signed, + ); + check_added_monitors(&$node_a, 1); + let (extra_msg_option, bs_revoke_and_ack) = + $crate::ln::functional_test_utils::do_main_commitment_signed_dance( + &$node_a, + &$node_b, + $fail_backwards, + ); + assert!(extra_msg_option.is_none()); + bs_revoke_and_ack + }}; ($node_a: expr, $node_b: expr, (), $fail_backwards: expr, true /* skip last step */, false /* no extra message */, $incl_claim: expr) => { - assert!($crate::ln::functional_test_utils::commitment_signed_dance_through_cp_raa(&$node_a, &$node_b, $fail_backwards, $incl_claim).is_none()); + assert!($crate::ln::functional_test_utils::commitment_signed_dance_through_cp_raa( + &$node_a, + &$node_b, + $fail_backwards, + $incl_claim + ) + .is_none()); }; ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr) => { - $crate::ln::functional_test_utils::do_commitment_signed_dance(&$node_a, &$node_b, &$commitment_signed, $fail_backwards, false); - } + $crate::ln::functional_test_utils::do_commitment_signed_dance( + &$node_a, + &$node_b, + &$commitment_signed, + $fail_backwards, + false, + ); + }; } /// Runs the commitment_signed dance after the initial commitment_signed is delivered through to @@ -2093,8 +2604,12 @@ macro_rules! commitment_signed_dance { /// the commitment we're exchanging. `includes_claim` provides that information. /// /// Returns any additional message `node_b` generated in addition to the `revoke_and_ack` response. -pub fn commitment_signed_dance_through_cp_raa(node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, fail_backwards: bool, includes_claim: bool) -> Option { - let (extra_msg_option, bs_revoke_and_ack) = do_main_commitment_signed_dance(node_a, node_b, fail_backwards); +pub fn commitment_signed_dance_through_cp_raa( + node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, fail_backwards: bool, + includes_claim: bool, +) -> Option { + let (extra_msg_option, bs_revoke_and_ack) = + do_main_commitment_signed_dance(node_a, node_b, fail_backwards); node_a.node.handle_revoke_and_ack(node_b.node.get_our_node_id(), &bs_revoke_and_ack); check_added_monitors(node_a, if includes_claim { 0 } else { 1 }); extra_msg_option @@ -2104,25 +2619,34 @@ pub fn commitment_signed_dance_through_cp_raa(node_a: &Node<'_, '_, '_>, node_b: /// been delivered, this method picks up and delivers the response `revoke_and_ack` and /// `commitment_signed`, returning the recipient's `revoke_and_ack` and any extra message it may /// have included. -pub fn do_main_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, fail_backwards: bool) -> (Option, msgs::RevokeAndACK) { - let (as_revoke_and_ack, as_commitment_signed) = get_revoke_commit_msgs!(node_a, node_b.node.get_our_node_id()); +pub fn do_main_commitment_signed_dance( + node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, fail_backwards: bool, +) -> (Option, msgs::RevokeAndACK) { + let (as_revoke_and_ack, as_commitment_signed) = + get_revoke_commit_msgs!(node_a, node_b.node.get_our_node_id()); check_added_monitors!(node_b, 0); assert!(node_b.node.get_and_clear_pending_msg_events().is_empty()); node_b.node.handle_revoke_and_ack(node_a.node.get_our_node_id(), &as_revoke_and_ack); assert!(node_b.node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(node_b, 1); - node_b.node.handle_commitment_signed_batch_test(node_a.node.get_our_node_id(), &as_commitment_signed); + node_b + .node + .handle_commitment_signed_batch_test(node_a.node.get_our_node_id(), &as_commitment_signed); let (bs_revoke_and_ack, extra_msg_option) = { let mut events = node_b.node.get_and_clear_pending_msg_events(); assert!(events.len() <= 2); - let node_a_event = remove_first_msg_event_to_node(&node_a.node.get_our_node_id(), &mut events); - (match node_a_event { - MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - assert_eq!(*node_id, node_a.node.get_our_node_id()); - (*msg).clone() + let node_a_event = + remove_first_msg_event_to_node(&node_a.node.get_our_node_id(), &mut events); + ( + match node_a_event { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, node_a.node.get_our_node_id()); + (*msg).clone() + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }, events.get(0).map(|e| e.clone())) + events.get(0).map(|e| e.clone()), + ) }; check_added_monitors!(node_b, 1); if fail_backwards { @@ -2137,23 +2661,38 @@ pub fn do_main_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node< /// /// If `skip_last_step` is unset, also checks for the payment failure update for the previous hop /// on failure or that no new messages are left over on success. -pub fn do_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, commitment_signed: &Vec, fail_backwards: bool, skip_last_step: bool) { +pub fn do_commitment_signed_dance( + node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, + commitment_signed: &Vec, fail_backwards: bool, skip_last_step: bool, +) { check_added_monitors!(node_a, 0); assert!(node_a.node.get_and_clear_pending_msg_events().is_empty()); - node_a.node.handle_commitment_signed_batch_test(node_b.node.get_our_node_id(), commitment_signed); + node_a + .node + .handle_commitment_signed_batch_test(node_b.node.get_our_node_id(), commitment_signed); check_added_monitors!(node_a, 1); // If this commitment signed dance was due to a claim, don't check for an RAA monitor update. let channel_id = commitment_signed[0].channel_id; - let got_claim = node_a.node.test_raa_monitor_updates_held(node_b.node.get_our_node_id(), channel_id); - if fail_backwards { assert!(!got_claim); } + let got_claim = + node_a.node.test_raa_monitor_updates_held(node_b.node.get_our_node_id(), channel_id); + if fail_backwards { + assert!(!got_claim); + } commitment_signed_dance!(node_a, node_b, (), fail_backwards, true, false, got_claim); - if skip_last_step { return; } + if skip_last_step { + return; + } if fail_backwards { - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(node_a, - vec![crate::events::HTLCDestination::NextHopChannel{ node_id: Some(node_b.node.get_our_node_id()), channel_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + node_a, + vec![crate::events::HTLCDestination::NextHopChannel { + node_id: Some(node_b.node.get_our_node_id()), + channel_id + }] + ); check_added_monitors!(node_a, 1); let node_a_per_peer_state = node_a.node.per_peer_state.read().unwrap(); @@ -2165,7 +2704,9 @@ pub fn do_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node<'_, ' if cp_pending_msg_events.len() == 1 { if let MessageSendEvent::UpdateHTLCs { .. } = cp_pending_msg_events[0] { assert_ne!(*cp_id, node_b.node.get_our_node_id()); - } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } } } // Expecting the failure backwards event to the previous hop (not `node_b`) @@ -2176,12 +2717,22 @@ pub fn do_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node<'_, ' } /// Get a payment preimage and hash. -pub fn get_payment_preimage_hash(recipient: &Node, min_value_msat: Option, min_final_cltv_expiry_delta: Option) -> (PaymentPreimage, PaymentHash, PaymentSecret) { +pub fn get_payment_preimage_hash( + recipient: &Node, min_value_msat: Option, min_final_cltv_expiry_delta: Option, +) -> (PaymentPreimage, PaymentHash, PaymentSecret) { let mut payment_count = recipient.network_payment_count.borrow_mut(); let payment_preimage = PaymentPreimage([*payment_count; 32]); *payment_count += 1; let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()); - let payment_secret = recipient.node.create_inbound_payment_for_hash(payment_hash, min_value_msat, 7200, min_final_cltv_expiry_delta).unwrap(); + let payment_secret = recipient + .node + .create_inbound_payment_for_hash( + payment_hash, + min_value_msat, + 7200, + min_final_cltv_expiry_delta, + ) + .unwrap(); (payment_preimage, payment_hash, payment_secret) } @@ -2197,7 +2748,11 @@ macro_rules! get_payment_preimage_hash { crate::get_payment_preimage_hash!($dest_node, $min_value_msat, None) }; ($dest_node: expr, $min_value_msat: expr, $min_final_cltv_expiry_delta: expr) => { - $crate::ln::functional_test_utils::get_payment_preimage_hash(&$dest_node, $min_value_msat, $min_final_cltv_expiry_delta) + $crate::ln::functional_test_utils::get_payment_preimage_hash( + &$dest_node, + $min_value_msat, + $min_final_cltv_expiry_delta, + ) }; } @@ -2207,9 +2762,14 @@ pub fn get_route(send_node: &Node, route_params: &RouteParameters) -> Result>()), - send_node.logger, &scorer, &Default::default(), &random_seed_bytes + send_node.logger, + &scorer, + &Default::default(), + &random_seed_bytes, ) } @@ -2219,9 +2779,14 @@ pub fn find_route(send_node: &Node, route_params: &RouteParameters) -> Result>()), - send_node.logger, &scorer, &Default::default(), &random_seed_bytes + send_node.logger, + &scorer, + &Default::default(), + &random_seed_bytes, ) } @@ -2231,29 +2796,50 @@ pub fn find_route(send_node: &Node, route_params: &RouteParameters) -> Result {{ - let route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value($payment_params, $recv_value); + let route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value( + $payment_params, + $recv_value, + ); $crate::ln::functional_test_utils::get_route(&$send_node, &route_params) - }} + }}; } #[macro_export] macro_rules! get_route_and_payment_hash { ($send_node: expr, $recv_node: expr, $recv_value: expr) => {{ - let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features($recv_node.node.bolt11_invoice_features()).unwrap(); + let payment_params = $crate::routing::router::PaymentParameters::from_node_id( + $recv_node.node.get_our_node_id(), + TEST_FINAL_CLTV, + ) + .with_bolt11_features($recv_node.node.bolt11_invoice_features()) + .unwrap(); $crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value) }}; ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr) => {{ - $crate::get_route_and_payment_hash!($send_node, $recv_node, $payment_params, $recv_value, None) + $crate::get_route_and_payment_hash!( + $send_node, + $recv_node, + $payment_params, + $recv_value, + None + ) }}; ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr, $max_total_routing_fee_msat: expr) => {{ - let mut route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value($payment_params, $recv_value); + let mut route_params = + $crate::routing::router::RouteParameters::from_payment_params_and_value( + $payment_params, + $recv_value, + ); route_params.max_total_routing_fee_msat = $max_total_routing_fee_msat; let (payment_preimage, payment_hash, payment_secret) = - $crate::ln::functional_test_utils::get_payment_preimage_hash(&$recv_node, Some($recv_value), None); + $crate::ln::functional_test_utils::get_payment_preimage_hash( + &$recv_node, + Some($recv_value), + None, + ); let route = $crate::ln::functional_test_utils::get_route(&$send_node, &route_params); (route.unwrap(), payment_hash, payment_preimage, payment_secret) - }} + }}; } pub fn check_payment_claimable( @@ -2262,12 +2848,20 @@ pub fn check_payment_claimable( expected_receiver_node_id: PublicKey, ) { match event { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + .. + } => { assert_eq!(expected_payment_hash, *payment_hash); assert_eq!(expected_recv_value, *amount_msat); assert_eq!(expected_receiver_node_id, receiver_node_id.unwrap()); match purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert_eq!(&expected_payment_preimage, payment_preimage); assert_eq!(expected_payment_secret, *payment_secret); }, @@ -2275,7 +2869,9 @@ pub fn check_payment_claimable( assert_eq!(&expected_payment_preimage, payment_preimage); assert_eq!(expected_payment_secret, *payment_secret); }, - PaymentPurpose::Bolt12RefundPayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt12RefundPayment { + payment_preimage, payment_secret, .. + } => { assert_eq!(&expected_payment_preimage, payment_preimage); assert_eq!(expected_payment_secret, *payment_secret); }, @@ -2290,12 +2886,26 @@ pub fn check_payment_claimable( #[cfg(any(test, ldk_bench, feature = "_test_utils"))] macro_rules! expect_payment_claimable { ($node: expr, $expected_payment_hash: expr, $expected_payment_secret: expr, $expected_recv_value: expr) => { - expect_payment_claimable!($node, $expected_payment_hash, $expected_payment_secret, $expected_recv_value, None, $node.node.get_our_node_id()) + expect_payment_claimable!( + $node, + $expected_payment_hash, + $expected_payment_secret, + $expected_recv_value, + None, + $node.node.get_our_node_id() + ) }; ($node: expr, $expected_payment_hash: expr, $expected_payment_secret: expr, $expected_recv_value: expr, $expected_payment_preimage: expr, $expected_receiver_node_id: expr) => { let events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); - $crate::ln::functional_test_utils::check_payment_claimable(&events[0], $expected_payment_hash, $expected_payment_secret, $expected_recv_value, $expected_payment_preimage, $expected_receiver_node_id) + $crate::ln::functional_test_utils::check_payment_claimable( + &events[0], + $expected_payment_hash, + $expected_payment_secret, + $expected_recv_value, + $expected_payment_preimage, + $expected_receiver_node_id, + ) }; } @@ -2312,16 +2922,18 @@ macro_rules! expect_payment_claimed { }, _ => panic!("Unexpected event"), } - } + }; } -pub fn expect_payment_sent>(node: &H, - expected_payment_preimage: PaymentPreimage, expected_fee_msat_opt: Option>, - expect_per_path_claims: bool, expect_post_ev_mon_update: bool, +pub fn expect_payment_sent>( + node: &H, expected_payment_preimage: PaymentPreimage, + expected_fee_msat_opt: Option>, expect_per_path_claims: bool, + expect_post_ev_mon_update: bool, ) -> Option { let events = node.node().get_and_clear_pending_events(); let expected_payment_hash = PaymentHash( - bitcoin::hashes::sha256::Hash::hash(&expected_payment_preimage.0).to_byte_array()); + bitcoin::hashes::sha256::Hash::hash(&expected_payment_preimage.0).to_byte_array(), + ); if expect_per_path_claims { assert!(events.len() > 1); } else { @@ -2333,7 +2945,14 @@ pub fn expect_payment_sent>(node: &H, // We return the invoice because some test may want to check the invoice details. let invoice; let expected_payment_id = match events[0] { - Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat, ref bolt12_invoice } => { + Event::PaymentSent { + ref payment_id, + ref payment_preimage, + ref payment_hash, + ref amount_msat, + ref fee_paid_msat, + ref bolt12_invoice, + } => { assert_eq!(expected_payment_preimage, *payment_preimage); assert_eq!(expected_payment_hash, *payment_hash); assert!(amount_msat.is_some()); @@ -2367,12 +2986,22 @@ macro_rules! expect_payment_sent { $crate::expect_payment_sent!($node, $expected_payment_preimage, None::, true) }; ($node: expr, $expected_payment_preimage: expr, $expected_fee_msat_opt: expr) => { - $crate::expect_payment_sent!($node, $expected_payment_preimage, $expected_fee_msat_opt, true) + $crate::expect_payment_sent!( + $node, + $expected_payment_preimage, + $expected_fee_msat_opt, + true + ) }; ($node: expr, $expected_payment_preimage: expr, $expected_fee_msat_opt: expr, $expect_paths: expr) => { - $crate::ln::functional_test_utils::expect_payment_sent(&$node, $expected_payment_preimage, - $expected_fee_msat_opt.map(|o| Some(o)), $expect_paths, true) - } + $crate::ln::functional_test_utils::expect_payment_sent( + &$node, + $expected_payment_preimage, + $expected_fee_msat_opt.map(|o| Some(o)), + $expect_paths, + true, + ) + }; } #[macro_export] @@ -2384,20 +3013,27 @@ macro_rules! expect_payment_path_successful { $crate::events::Event::PaymentPathSuccessful { .. } => {}, _ => panic!("Unexpected event"), } - } + }; } /// Returns the total fee earned by this HTLC forward, in msat. -pub fn expect_payment_forwarded>( +pub fn expect_payment_forwarded>( event: Event, node: &H, prev_node: &H, next_node: &H, expected_fee: Option, expected_extra_fees_msat: Option, upstream_force_closed: bool, downstream_force_closed: bool, allow_1_msat_fee_overpay: bool, ) -> Option { match event { Event::PaymentForwarded { - prev_channel_id, next_channel_id, prev_user_channel_id, next_user_channel_id, - prev_node_id, next_node_id, total_fee_earned_msat, - skimmed_fee_msat, claim_from_onchain_tx, .. + prev_channel_id, + next_channel_id, + prev_user_channel_id, + next_user_channel_id, + prev_node_id, + next_node_id, + total_fee_earned_msat, + skimmed_fee_msat, + claim_from_onchain_tx, + .. } => { if allow_1_msat_fee_overpay { // Aggregating fees for blinded paths may result in a rounding error, causing slight @@ -2414,12 +3050,11 @@ pub fn expect_payment_forwarded>( assert!(skimmed_fee_msat == expected_extra_fees_msat); if !upstream_force_closed { // Is the event prev_channel_id in one of the channels between the two nodes? - assert!(node.node().list_channels().iter().any(|x| - x.counterparty.node_id == prev_node.node().get_our_node_id() && - prev_node.node().get_our_node_id() == prev_node_id.unwrap() && - x.channel_id == prev_channel_id.unwrap() && - x.user_channel_id == prev_user_channel_id.unwrap() - )); + assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id + == prev_node.node().get_our_node_id() + && prev_node.node().get_our_node_id() == prev_node_id.unwrap() + && x.channel_id == prev_channel_id.unwrap() + && x.user_channel_id == prev_user_channel_id.unwrap())); } // We check for force closures since a force closed channel is removed from the // node's channel list @@ -2429,18 +3064,19 @@ pub fn expect_payment_forwarded>( // introducing yet another variable, we use the latter's state as a flag to detect // this and only check if it's `Some`. if total_fee_earned_msat.is_none() { - assert!(node.node().list_channels().iter().any(|x| - x.counterparty.node_id == next_node.node().get_our_node_id() && - next_node.node().get_our_node_id() == next_node_id.unwrap() && - x.channel_id == next_channel_id.unwrap() - )); + assert!(node + .node() + .list_channels() + .iter() + .any(|x| x.counterparty.node_id == next_node.node().get_our_node_id() + && next_node.node().get_our_node_id() == next_node_id.unwrap() + && x.channel_id == next_channel_id.unwrap())); } else { - assert!(node.node().list_channels().iter().any(|x| - x.counterparty.node_id == next_node.node().get_our_node_id() && - next_node.node().get_our_node_id() == next_node_id.unwrap() && - x.channel_id == next_channel_id.unwrap() && - x.user_channel_id == next_user_channel_id.unwrap() - )); + assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id + == next_node.node().get_our_node_id() + && next_node.node().get_our_node_id() == next_node_id.unwrap() + && x.channel_id == next_channel_id.unwrap() + && x.user_channel_id == next_user_channel_id.unwrap())); } } assert_eq!(claim_from_onchain_tx, downstream_force_closed); @@ -2456,23 +3092,37 @@ macro_rules! expect_payment_forwarded { let mut events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); $crate::ln::functional_test_utils::expect_payment_forwarded( - events.pop().unwrap(), &$node, &$prev_node, &$next_node, $expected_fee, None, - $upstream_force_closed, $downstream_force_closed, false + events.pop().unwrap(), + &$node, + &$prev_node, + &$next_node, + $expected_fee, + None, + $upstream_force_closed, + $downstream_force_closed, + false, ); - } + }; } #[macro_export] macro_rules! expect_channel_shutdown_state { ($node: expr, $chan_id: expr, $state: path) => { - let chan_details = $node.node.list_channels().into_iter().filter(|cd| cd.channel_id == $chan_id).collect::>(); + let chan_details = $node + .node + .list_channels() + .into_iter() + .filter(|cd| cd.channel_id == $chan_id) + .collect::>(); assert_eq!(chan_details.len(), 1); assert_eq!(chan_details[0].channel_shutdown_state, Some($state)); - } + }; } #[cfg(any(test, ldk_bench, feature = "_test_utils"))] -pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) -> ChannelId { +pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey, +) -> ChannelId { let events = node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match &events[0] { @@ -2485,31 +3135,37 @@ pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, } #[cfg(any(test, ldk_bench, feature = "_test_utils"))] -pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) { +pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey, +) { let events = node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - crate::events::Event::ChannelReady{ ref counterparty_node_id, .. } => { + crate::events::Event::ChannelReady { ref counterparty_node_id, .. } => { assert_eq!(*expected_counterparty_node_id, *counterparty_node_id); }, _ => panic!("Unexpected event"), } } -pub fn expect_probe_successful_events(node: &Node, mut probe_results: Vec<(PaymentHash, PaymentId)>) { +pub fn expect_probe_successful_events( + node: &Node, mut probe_results: Vec<(PaymentHash, PaymentId)>, +) { let mut events = node.node.get_and_clear_pending_events(); for event in events.drain(..) { match event { - Event::ProbeSuccessful { payment_hash: ev_ph, payment_id: ev_pid, ..} => { - let result_idx = probe_results.iter().position(|(payment_hash, payment_id)| *payment_hash == ev_ph && *payment_id == ev_pid); + Event::ProbeSuccessful { payment_hash: ev_ph, payment_id: ev_pid, .. } => { + let result_idx = probe_results.iter().position(|(payment_hash, payment_id)| { + *payment_hash == ev_ph && *payment_id == ev_pid + }); assert!(result_idx.is_some()); probe_results.remove(result_idx.unwrap()); }, _ => panic!(), } - }; + } // Ensure that we received a ProbeSuccessful event for each probe result. assert!(probe_results.is_empty()); @@ -2545,7 +3201,9 @@ impl<'a> PaymentFailedConditions<'a> { self.expected_blamed_chan_closed = Some(closed); self } - pub fn expected_htlc_error_data(mut self, reason: LocalHTLCFailureReason, data: &'a [u8]) -> Self { + pub fn expected_htlc_error_data( + mut self, reason: LocalHTLCFailureReason, data: &'a [u8], + ) -> Self { self.expected_htlc_error_data = Some((reason, data)); self } @@ -2559,10 +3217,14 @@ impl<'a> PaymentFailedConditions<'a> { macro_rules! expect_payment_failed_with_update { ($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr, $scid: expr, $chan_closed: expr) => { $crate::ln::functional_test_utils::expect_payment_failed_conditions( - &$node, $expected_payment_hash, $payment_failed_permanently, + &$node, + $expected_payment_hash, + $payment_failed_permanently, $crate::ln::functional_test_utils::PaymentFailedConditions::new() - .blamed_scid($scid).blamed_chan_closed($chan_closed)); - } + .blamed_scid($scid) + .blamed_chan_closed($chan_closed), + ); + }; } #[cfg(any(test, feature = "_externalize_tests"))] @@ -2579,16 +3241,28 @@ macro_rules! expect_payment_failed { pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( payment_failed_events: Vec, expected_payment_hash: PaymentHash, - expected_payment_failed_permanently: bool, conditions: PaymentFailedConditions<'e> + expected_payment_failed_permanently: bool, conditions: PaymentFailedConditions<'e>, ) { - if conditions.expected_mpp_parts_remain { assert_eq!(payment_failed_events.len(), 1); } else { assert_eq!(payment_failed_events.len(), 2); } + if conditions.expected_mpp_parts_remain { + assert_eq!(payment_failed_events.len(), 1); + } else { + assert_eq!(payment_failed_events.len(), 2); + } let expected_payment_id = match &payment_failed_events[0] { - Event::PaymentPathFailed { payment_hash, payment_failed_permanently, payment_id, failure, - error_code, - error_data, .. + Event::PaymentPathFailed { + payment_hash, + payment_failed_permanently, + payment_id, + failure, + error_code, + error_data, + .. } => { assert_eq!(*payment_hash, expected_payment_hash, "unexpected payment_hash"); - assert_eq!(*payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently value"); + assert_eq!( + *payment_failed_permanently, expected_payment_failed_permanently, + "unexpected payment_failed_permanently value" + ); { assert!(error_code.is_some(), "expected error_code.is_some() = true"); assert!(error_data.is_some(), "expected error_data.is_some() = true"); @@ -2610,7 +3284,9 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( }, _ => panic!("Unexpected update type"), } - } else { panic!("Expected network update"); } + } else { + panic!("Expected network update"); + } } payment_id.unwrap() @@ -2620,14 +3296,21 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( if !conditions.expected_mpp_parts_remain && !conditions.retry_expected { match &payment_failed_events[1] { Event::PaymentFailed { ref payment_hash, ref payment_id, ref reason } => { - assert_eq!(*payment_hash, Some(expected_payment_hash), "unexpected second payment_hash"); + assert_eq!( + *payment_hash, + Some(expected_payment_hash), + "unexpected second payment_hash" + ); assert_eq!(*payment_id, expected_payment_id); - assert_eq!(reason.unwrap(), if expected_payment_failed_permanently { - PaymentFailureReason::RecipientRejected - } else { - PaymentFailureReason::RetriesExhausted - }); - } + assert_eq!( + reason.unwrap(), + if expected_payment_failed_permanently { + PaymentFailureReason::RecipientRejected + } else { + PaymentFailureReason::RetriesExhausted + } + ); + }, _ => panic!("Unexpected second event"), } } else if conditions.retry_expected { @@ -2639,20 +3322,34 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( } pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>( - node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, expected_payment_failed_permanently: bool, - conditions: PaymentFailedConditions<'e> + node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, + expected_payment_failed_permanently: bool, conditions: PaymentFailedConditions<'e>, ) { let events = node.node.get_and_clear_pending_events(); - expect_payment_failed_conditions_event(events, expected_payment_hash, expected_payment_failed_permanently, conditions); + expect_payment_failed_conditions_event( + events, + expected_payment_hash, + expected_payment_failed_permanently, + conditions, + ); } -pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) -> PaymentId { +pub fn send_along_route_with_secret<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], + recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret, +) -> PaymentId { let payment_id = PaymentId(origin_node.keys_manager.backing.get_secure_random_bytes()); origin_node.router.expect_find_route(route.route_params.clone().unwrap(), Ok(route.clone())); - origin_node.node.send_payment( - our_payment_hash, RecipientOnionFields::secret_only(our_payment_secret), payment_id, - route.route_params.unwrap(), Retry::Attempts(0) - ).unwrap(); + origin_node + .node + .send_payment( + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + payment_id, + route.route_params.unwrap(), + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors!(origin_node, expected_paths.len()); pass_along_route(origin_node, expected_paths, recv_value, our_payment_hash, our_payment_secret); payment_id @@ -2664,7 +3361,9 @@ fn fail_payment_along_path<'a, 'b, 'c>(expected_path: &[&Node<'a, 'b, 'c>]) { // iterate from the receiving node to the origin node and handle update fail htlc. for (&node, &prev_node) in expected_path.iter().rev().zip(expected_path.iter().rev().skip(1)) { let updates = get_htlc_update_msgs!(node, prev_node.node.get_our_node_id()); - prev_node.node.handle_update_fail_htlc(node.node.get_our_node_id(), &updates.update_fail_htlcs[0]); + prev_node + .node + .handle_update_fail_htlc(node.node.get_our_node_id(), &updates.update_fail_htlcs[0]); check_added_monitors!(prev_node, 0); let is_first_hop = origin_node_id == prev_node.node.get_our_node_id(); @@ -2691,13 +3390,23 @@ pub struct PassAlongPathArgs<'a, 'b, 'c, 'd> { impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> { pub fn new( - origin_node: &'a Node<'b, 'c, 'd>, expected_path: &'a [&'a Node<'b, 'c, 'd>], recv_value: u64, - payment_hash: PaymentHash, event: MessageSendEvent, + origin_node: &'a Node<'b, 'c, 'd>, expected_path: &'a [&'a Node<'b, 'c, 'd>], + recv_value: u64, payment_hash: PaymentHash, event: MessageSendEvent, ) -> Self { Self { - origin_node, expected_path, recv_value, payment_hash, payment_secret: None, event, - payment_claimable_expected: true, clear_recipient_events: true, expected_preimage: None, - is_probe: false, custom_tlvs: Vec::new(), payment_metadata: None, expected_failure: None, + origin_node, + expected_path, + recv_value, + payment_hash, + payment_secret: None, + event, + payment_claimable_expected: true, + clear_recipient_events: true, + expected_preimage: None, + is_probe: false, + custom_tlvs: Vec::new(), + payment_metadata: None, + expected_failure: None, } } pub fn without_clearing_recipient_events(mut self) -> Self { @@ -2738,10 +3447,19 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> { pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option { let PassAlongPathArgs { - origin_node, expected_path, recv_value, payment_hash: our_payment_hash, - payment_secret: our_payment_secret, event: ev, payment_claimable_expected, - clear_recipient_events, expected_preimage, is_probe, custom_tlvs, payment_metadata, - expected_failure + origin_node, + expected_path, + recv_value, + payment_hash: our_payment_hash, + payment_secret: our_payment_secret, + event: ev, + payment_claimable_expected, + clear_recipient_events, + expected_preimage, + is_probe, + custom_tlvs, + payment_metadata, + expected_failure, } = args; let mut payment_event = SendEvent::from_event(ev); @@ -2769,43 +3487,85 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option if payment_claimable_expected { assert_eq!(events_2.len(), 1); match &events_2[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, - receiver_node_id, ref via_channel_id, ref via_user_channel_id, - claim_deadline, onion_fields, .. + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + ref via_channel_id, + ref via_user_channel_id, + claim_deadline, + onion_fields, + .. } => { assert_eq!(our_payment_hash, *payment_hash); assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap()); assert!(onion_fields.is_some()); assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs); - assert_eq!(onion_fields.as_ref().unwrap().payment_metadata, payment_metadata); + assert_eq!( + onion_fields.as_ref().unwrap().payment_metadata, + payment_metadata + ); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, + payment_secret, + .. + } => { assert_eq!(expected_preimage, *payment_preimage); assert_eq!(our_payment_secret.unwrap(), *payment_secret); - assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret); + assert_eq!( + Some(*payment_secret), + onion_fields.as_ref().unwrap().payment_secret + ); }, - PaymentPurpose::Bolt12OfferPayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt12OfferPayment { + payment_preimage, + payment_secret, + .. + } => { if let Some(preimage) = expected_preimage { assert_eq!(preimage, payment_preimage.unwrap()); } if let Some(secret) = our_payment_secret { assert_eq!(secret, *payment_secret); } - assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret); + assert_eq!( + Some(*payment_secret), + onion_fields.as_ref().unwrap().payment_secret + ); }, - PaymentPurpose::Bolt12RefundPayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt12RefundPayment { + payment_preimage, + payment_secret, + .. + } => { assert_eq!(expected_preimage, *payment_preimage); assert_eq!(our_payment_secret.unwrap(), *payment_secret); - assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret); + assert_eq!( + Some(*payment_secret), + onion_fields.as_ref().unwrap().payment_secret + ); }, PaymentPurpose::SpontaneousPayment(payment_preimage) => { assert_eq!(expected_preimage.unwrap(), *payment_preimage); - assert_eq!(our_payment_secret, onion_fields.as_ref().unwrap().payment_secret); + assert_eq!( + our_payment_secret, + onion_fields.as_ref().unwrap().payment_secret + ); }, } assert_eq!(*amount_msat, recv_value); - assert!(node.node.list_channels().iter().any(|details| details.channel_id == via_channel_id.unwrap())); - assert!(node.node.list_channels().iter().any(|details| details.user_channel_id == via_user_channel_id.unwrap())); + assert!(node + .node + .list_channels() + .iter() + .any(|details| details.channel_id == via_channel_id.unwrap())); + assert!(node + .node + .list_channels() + .iter() + .any(|details| details.user_channel_id == via_user_channel_id.unwrap())); assert!(claim_deadline.unwrap() > node.best_block_info().1); }, _ => panic!("Unexpected event"), @@ -2836,8 +3596,13 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option event } -pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option, ev: MessageSendEvent, payment_claimable_expected: bool, expected_preimage: Option) -> Option { - let mut args = PassAlongPathArgs::new(origin_node, expected_path, recv_value, our_payment_hash, ev); +pub fn pass_along_path<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, + our_payment_hash: PaymentHash, our_payment_secret: Option, ev: MessageSendEvent, + payment_claimable_expected: bool, expected_preimage: Option, +) -> Option { + let mut args = + PassAlongPathArgs::new(origin_node, expected_path, recv_value, our_payment_hash, ev); if !payment_claimable_expected { args = args.without_claimable_event(); } @@ -2850,7 +3615,9 @@ pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path do_pass_along_path(args) } -pub fn send_probe_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[(&[&Node<'a, 'b, 'c>], PaymentHash)]) { +pub fn send_probe_along_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_route: &[(&[&Node<'a, 'b, 'c>], PaymentHash)], +) { let mut events = origin_node.node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_route.len()); @@ -2859,11 +3626,14 @@ pub fn send_probe_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expect for (path, payment_hash) in expected_route.iter() { let ev = remove_first_msg_event_to_node(&path[0].node.get_our_node_id(), &mut events); - do_pass_along_path(PassAlongPathArgs::new(origin_node, path, 0, *payment_hash, ev) - .is_probe() - .without_clearing_recipient_events()); + do_pass_along_path( + PassAlongPathArgs::new(origin_node, path, 0, *payment_hash, ev) + .is_probe() + .without_clearing_recipient_events(), + ); - let nodes_to_fail_payment: Vec<_> = vec![origin_node].into_iter().chain(path.iter().cloned()).collect(); + let nodes_to_fail_payment: Vec<_> = + vec![origin_node].into_iter().chain(path.iter().cloned()).collect(); fail_payment_along_path(nodes_to_fail_payment.as_slice()); expect_htlc_handling_failed_destinations!( @@ -2873,28 +3643,55 @@ pub fn send_probe_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expect } } -pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) { +pub fn pass_along_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, + our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret, +) { let mut events = origin_node.node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_route.len()); for (path_idx, expected_path) in expected_route.iter().enumerate() { - let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events); + let ev = + remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events); // Once we've gotten through all the HTLCs, the last one should result in a // PaymentClaimable (but each previous one should not!). let expect_payment = path_idx == expected_route.len() - 1; - pass_along_path(origin_node, expected_path, recv_value, our_payment_hash.clone(), Some(our_payment_secret), ev, expect_payment, None); + pass_along_path( + origin_node, + expected_path, + recv_value, + our_payment_hash.clone(), + Some(our_payment_secret), + ev, + expect_payment, + None, + ); } } -pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret, PaymentId) { - let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(expected_route.last().unwrap()); - let payment_id = send_along_route_with_secret(origin_node, route, &[expected_route], recv_value, our_payment_hash, our_payment_secret); +pub fn send_along_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], + recv_value: u64, +) -> (PaymentPreimage, PaymentHash, PaymentSecret, PaymentId) { + let (our_payment_preimage, our_payment_hash, our_payment_secret) = + get_payment_preimage_hash!(expected_route.last().unwrap()); + let payment_id = send_along_route_with_secret( + origin_node, + route, + &[expected_route], + recv_value, + our_payment_hash, + our_payment_secret, + ); (our_payment_preimage, our_payment_hash, our_payment_secret, payment_id) } pub fn do_claim_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { for path in args.expected_paths.iter() { - assert_eq!(path.last().unwrap().node.get_our_node_id(), args.expected_paths[0].last().unwrap().node.get_our_node_id()); + assert_eq!( + path.last().unwrap().node.get_our_node_id(), + args.expected_paths[0].last().unwrap().node.get_our_node_id() + ); } args.expected_paths[0].last().unwrap().node.claim_funds(args.payment_preimage); pass_claimed_payment_along_route(args) @@ -2924,9 +3721,14 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> { payment_preimage: PaymentPreimage, ) -> Self { Self { - origin_node, expected_paths, expected_extra_fees: vec![0; expected_paths.len()], - expected_min_htlc_overpay: vec![0; expected_paths.len()], skip_last: false, payment_preimage, - allow_1_msat_fee_overpay: false, custom_tlvs: vec![], + origin_node, + expected_paths, + expected_extra_fees: vec![0; expected_paths.len()], + expected_min_htlc_overpay: vec![0; expected_paths.len()], + skip_last: false, + payment_preimage, + allow_1_msat_fee_overpay: false, + custom_tlvs: vec![], } } pub fn skip_last(mut self, skip_last: bool) -> Self { @@ -2953,8 +3755,14 @@ impl<'a, 'b, 'c, 'd> ClaimAlongRouteArgs<'a, 'b, 'c, 'd> { pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { let ClaimAlongRouteArgs { - origin_node, expected_paths, expected_extra_fees, expected_min_htlc_overpay, skip_last, - payment_preimage: our_payment_preimage, allow_1_msat_fee_overpay, custom_tlvs, + origin_node, + expected_paths, + expected_extra_fees, + expected_min_htlc_overpay, + skip_last, + payment_preimage: our_payment_preimage, + allow_1_msat_fee_overpay, + custom_tlvs, } = args; let claim_event = expected_paths[0].last().unwrap().node.get_and_clear_pending_events(); assert_eq!(claim_event.len(), 1); @@ -2962,7 +3770,8 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { let mut fwd_amt_msat = 0; match claim_event[0] { Event::PaymentClaimed { - purpose: PaymentPurpose::SpontaneousPayment(preimage) + purpose: + PaymentPurpose::SpontaneousPayment(preimage) | PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(preimage), .. } | PaymentPurpose::Bolt12OfferPayment { payment_preimage: Some(preimage), .. } | PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(preimage), .. }, @@ -2972,14 +3781,15 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { .. } => { assert_eq!(preimage, our_payment_preimage); - assert_eq!(htlcs.len(), expected_paths.len()); // One per path. + assert_eq!(htlcs.len(), expected_paths.len()); // One per path. assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::(), amount_msat); assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs); check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs); fwd_amt_msat = amount_msat; }, Event::PaymentClaimed { - purpose: PaymentPurpose::Bolt11InvoicePayment { .. } + purpose: + PaymentPurpose::Bolt11InvoicePayment { .. } | PaymentPurpose::Bolt12OfferPayment { .. } | PaymentPurpose::Bolt12RefundPayment { .. }, payment_hash, @@ -2989,12 +3799,12 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { .. } => { assert_eq!(&payment_hash.0, &Sha256::hash(&our_payment_preimage.0)[..]); - assert_eq!(htlcs.len(), expected_paths.len()); // One per path. + assert_eq!(htlcs.len(), expected_paths.len()); // One per path. assert_eq!(htlcs.iter().map(|h| h.value_msat).sum::(), amount_msat); assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs); check_claimed_htlcs_match_route(origin_node, expected_paths, htlcs); fwd_amt_msat = amount_msat; - } + }, _ => panic!(), } @@ -3005,7 +3815,19 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { macro_rules! msgs_from_ev { ($ev: expr) => { match $ev { - &MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + &MessageSendEvent::UpdateHTLCs { + ref node_id, + ref channel_id, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert!(update_add_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); assert!(update_fail_htlcs.is_empty()); @@ -3016,9 +3838,12 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { }, _ => panic!("Unexpected event"), } - } + }; } - let mut per_path_msgs: Vec<((msgs::UpdateFulfillHTLC, Vec), PublicKey)> = Vec::with_capacity(expected_paths.len()); + let mut per_path_msgs: Vec<( + (msgs::UpdateFulfillHTLC, Vec), + PublicKey, + )> = Vec::with_capacity(expected_paths.len()); let mut events = expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_paths.len()); @@ -3028,7 +3853,11 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { for expected_path in expected_paths.iter() { // For MPP payments, we want the fulfill message from the payee to the penultimate hop in the // path. - let penultimate_hop_node_id = expected_path.iter().rev().skip(1).next() + let penultimate_hop_node_id = expected_path + .iter() + .rev() + .skip(1) + .next() .map(|n| n.node.get_our_node_id()) .unwrap_or(origin_node.node.get_our_node_id()); let ev = remove_first_msg_event_to_node(&penultimate_hop_node_id, &mut events); @@ -3036,68 +3865,96 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 { } } - for (i, (expected_route, (path_msgs, next_hop))) in expected_paths.iter().zip(per_path_msgs.drain(..)).enumerate() { + for (i, (expected_route, (path_msgs, next_hop))) in + expected_paths.iter().zip(per_path_msgs.drain(..)).enumerate() + { let mut next_msgs = Some(path_msgs); let mut expected_next_node = next_hop; macro_rules! last_update_fulfill_dance { - ($node: expr, $prev_node: expr) => { - { - $node.node.handle_update_fulfill_htlc($prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); - check_added_monitors!($node, 0); - assert!($node.node.get_and_clear_pending_msg_events().is_empty()); - commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); - } - } + ($node: expr, $prev_node: expr) => {{ + $node.node.handle_update_fulfill_htlc( + $prev_node.node.get_our_node_id(), + &next_msgs.as_ref().unwrap().0, + ); + check_added_monitors!($node, 0); + assert!($node.node.get_and_clear_pending_msg_events().is_empty()); + commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); + }}; } macro_rules! mid_update_fulfill_dance { - ($idx: expr, $node: expr, $prev_node: expr, $next_node: expr, $new_msgs: expr) => { - { - $node.node.handle_update_fulfill_htlc($prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); - let mut fee = { - let (base_fee, prop_fee) = { - let per_peer_state = $node.node.per_peer_state.read().unwrap(); - let peer_state = per_peer_state.get(&$prev_node.node.get_our_node_id()) - .unwrap().lock().unwrap(); - let channel = peer_state.channel_by_id.get(&next_msgs.as_ref().unwrap().0.channel_id).unwrap(); - if let Some(prev_config) = channel.context().prev_config() { - (prev_config.forwarding_fee_base_msat as u64, - prev_config.forwarding_fee_proportional_millionths as u64) - } else { - (channel.context().config().forwarding_fee_base_msat as u64, - channel.context().config().forwarding_fee_proportional_millionths as u64) - } - }; - ((fwd_amt_msat * prop_fee / 1_000_000) + base_fee) as u32 + ($idx: expr, $node: expr, $prev_node: expr, $next_node: expr, $new_msgs: expr) => {{ + $node.node.handle_update_fulfill_htlc( + $prev_node.node.get_our_node_id(), + &next_msgs.as_ref().unwrap().0, + ); + let mut fee = { + let (base_fee, prop_fee) = { + let per_peer_state = $node.node.per_peer_state.read().unwrap(); + let peer_state = per_peer_state + .get(&$prev_node.node.get_our_node_id()) + .unwrap() + .lock() + .unwrap(); + let channel = peer_state + .channel_by_id + .get(&next_msgs.as_ref().unwrap().0.channel_id) + .unwrap(); + if let Some(prev_config) = channel.context().prev_config() { + ( + prev_config.forwarding_fee_base_msat as u64, + prev_config.forwarding_fee_proportional_millionths as u64, + ) + } else { + ( + channel.context().config().forwarding_fee_base_msat as u64, + channel.context().config().forwarding_fee_proportional_millionths + as u64, + ) + } }; - - let mut expected_extra_fee = None; - if $idx == 1 { - fee += expected_extra_fees[i]; - fee += expected_min_htlc_overpay[i]; - expected_extra_fee = if expected_extra_fees[i] > 0 { Some(expected_extra_fees[i] as u64) } else { None }; - } - let mut events = $node.node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - let actual_fee = expect_payment_forwarded(events.pop().unwrap(), *$node, $next_node, $prev_node, - Some(fee as u64), expected_extra_fee, false, false, allow_1_msat_fee_overpay); - expected_total_fee_msat += actual_fee.unwrap(); - fwd_amt_msat += actual_fee.unwrap(); - check_added_monitors!($node, 1); - let new_next_msgs = if $new_msgs { - let events = $node.node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - let (res, nexthop) = msgs_from_ev!(&events[0]); - expected_next_node = nexthop; - Some(res) + ((fwd_amt_msat * prop_fee / 1_000_000) + base_fee) as u32 + }; + + let mut expected_extra_fee = None; + if $idx == 1 { + fee += expected_extra_fees[i]; + fee += expected_min_htlc_overpay[i]; + expected_extra_fee = if expected_extra_fees[i] > 0 { + Some(expected_extra_fees[i] as u64) } else { - assert!($node.node.get_and_clear_pending_msg_events().is_empty()); None }; - commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); - next_msgs = new_next_msgs; } - } + let mut events = $node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + let actual_fee = expect_payment_forwarded( + events.pop().unwrap(), + *$node, + $next_node, + $prev_node, + Some(fee as u64), + expected_extra_fee, + false, + false, + allow_1_msat_fee_overpay, + ); + expected_total_fee_msat += actual_fee.unwrap(); + fwd_amt_msat += actual_fee.unwrap(); + check_added_monitors!($node, 1); + let new_next_msgs = if $new_msgs { + let events = $node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let (res, nexthop) = msgs_from_ev!(&events[0]); + expected_next_node = nexthop; + Some(res) + } else { + assert!($node.node.get_and_clear_pending_msg_events().is_empty()); + None + }; + commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); + next_msgs = new_next_msgs; + }}; } let mut prev_node = expected_route.last().unwrap(); @@ -3148,17 +4005,28 @@ pub fn claim_payment_along_route(args: ClaimAlongRouteArgs) -> Option(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) -> Option { - claim_payment_along_route( - ClaimAlongRouteArgs::new(origin_node, &[expected_route], our_payment_preimage) - ) +pub fn claim_payment<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], + our_payment_preimage: PaymentPreimage, +) -> Option { + claim_payment_along_route(ClaimAlongRouteArgs::new( + origin_node, + &[expected_route], + our_payment_preimage, + )) } pub const TEST_FINAL_CLTV: u32 = 70; -pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret, PaymentId) { - let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(expected_route.last().unwrap().node.bolt11_invoice_features()).unwrap(); +pub fn route_payment<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, +) -> (PaymentPreimage, PaymentHash, PaymentSecret, PaymentId) { + let payment_params = PaymentParameters::from_node_id( + expected_route.last().unwrap().node.get_our_node_id(), + TEST_FINAL_CLTV, + ) + .with_bolt11_features(expected_route.last().unwrap().node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); let route = get_route(origin_node, &route_params).unwrap(); assert_eq!(route.paths.len(), 1); @@ -3171,33 +4039,69 @@ pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: (res.0, res.1, res.2, res.3) } -pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret, PaymentId) { +pub fn send_payment<'a, 'b, 'c>( + origin: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, +) -> (PaymentPreimage, PaymentHash, PaymentSecret, PaymentId) { let res = route_payment(&origin, expected_route, recv_value); claim_payment(&origin, expected_route, res.0); res } -pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_hash: PaymentHash) { +pub fn fail_payment_along_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, + our_payment_hash: PaymentHash, +) { for path in expected_paths.iter() { - assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id()); + assert_eq!( + path.last().unwrap().node.get_our_node_id(), + expected_paths[0].last().unwrap().node.get_our_node_id() + ); } expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash); - let expected_destinations: Vec = repeat(HTLCDestination::FailedPayment { payment_hash: our_payment_hash }).take(expected_paths.len()).collect(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(expected_paths[0].last().unwrap(), expected_destinations); + let expected_destinations: Vec = + repeat(HTLCDestination::FailedPayment { payment_hash: our_payment_hash }) + .take(expected_paths.len()) + .collect(); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + expected_paths[0].last().unwrap(), + expected_destinations + ); - pass_failed_payment_back(origin_node, expected_paths, skip_last, our_payment_hash, PaymentFailureReason::RecipientRejected); + pass_failed_payment_back( + origin_node, + expected_paths, + skip_last, + our_payment_hash, + PaymentFailureReason::RecipientRejected, + ); } -pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths_slice: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_hash: PaymentHash, expected_fail_reason: PaymentFailureReason) { +pub fn pass_failed_payment_back<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_paths_slice: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, + our_payment_hash: PaymentHash, expected_fail_reason: PaymentFailureReason, +) { let mut expected_paths: Vec<_> = expected_paths_slice.iter().collect(); check_added_monitors!(expected_paths[0].last().unwrap(), expected_paths.len()); - let mut per_path_msgs: Vec<((msgs::UpdateFailHTLC, Vec), PublicKey)> = Vec::with_capacity(expected_paths.len()); + let mut per_path_msgs: Vec<((msgs::UpdateFailHTLC, Vec), PublicKey)> = + Vec::with_capacity(expected_paths.len()); let events = expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_paths.len()); for ev in events.iter() { let (update_fail, commitment_signed, node_id) = match ev { - &MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + &MessageSendEvent::UpdateHTLCs { + ref node_id, + ref channel_id, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); assert_eq!(update_fail_htlcs.len(), 1); @@ -3211,9 +4115,16 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe per_path_msgs.push(((update_fail, commitment_signed), node_id)); } per_path_msgs.sort_unstable_by(|(_, node_id_a), (_, node_id_b)| node_id_a.cmp(node_id_b)); - expected_paths.sort_unstable_by(|path_a, path_b| path_a[path_a.len() - 2].node.get_our_node_id().cmp(&path_b[path_b.len() - 2].node.get_our_node_id())); + expected_paths.sort_unstable_by(|path_a, path_b| { + path_a[path_a.len() - 2] + .node + .get_our_node_id() + .cmp(&path_b[path_b.len() - 2].node.get_our_node_id()) + }); - for (i, (expected_route, (path_msgs, next_hop))) in expected_paths.iter().zip(per_path_msgs.drain(..)).enumerate() { + for (i, (expected_route, (path_msgs, next_hop))) in + expected_paths.iter().zip(per_path_msgs.drain(..)).enumerate() + { let mut next_msgs = Some(path_msgs); let mut expected_next_node = next_hop; let mut prev_node = expected_route.last().unwrap(); @@ -3222,17 +4133,43 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe assert_eq!(expected_next_node, node.node.get_our_node_id()); let update_next_node = !skip_last || idx != expected_route.len() - 1; if next_msgs.is_some() { - node.node.handle_update_fail_htlc(prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); - commitment_signed_dance!(node, prev_node, next_msgs.as_ref().unwrap().1, update_next_node); + node.node.handle_update_fail_htlc( + prev_node.node.get_our_node_id(), + &next_msgs.as_ref().unwrap().0, + ); + commitment_signed_dance!( + node, + prev_node, + next_msgs.as_ref().unwrap().1, + update_next_node + ); if !update_next_node { - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(node, vec![HTLCDestination::NextHopChannel { node_id: Some(prev_node.node.get_our_node_id()), channel_id: next_msgs.as_ref().unwrap().0.channel_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + node, + vec![HTLCDestination::NextHopChannel { + node_id: Some(prev_node.node.get_our_node_id()), + channel_id: next_msgs.as_ref().unwrap().0.channel_id + }] + ); } } let events = node.node.get_and_clear_pending_msg_events(); if update_next_node { assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + ref channel_id, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); assert_eq!(update_fail_htlcs.len(), 1); @@ -3256,15 +4193,28 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe if !skip_last { let prev_node = expected_route.first().unwrap(); - origin_node.node.handle_update_fail_htlc(prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); + origin_node.node.handle_update_fail_htlc( + prev_node.node.get_our_node_id(), + &next_msgs.as_ref().unwrap().0, + ); check_added_monitors!(origin_node, 0); assert!(origin_node.node.get_and_clear_pending_msg_events().is_empty()); commitment_signed_dance!(origin_node, prev_node, next_msgs.as_ref().unwrap().1, false); let events = origin_node.node.get_and_clear_pending_events(); - if i == expected_paths.len() - 1 { assert_eq!(events.len(), 2); } else { assert_eq!(events.len(), 1); } + if i == expected_paths.len() - 1 { + assert_eq!(events.len(), 2); + } else { + assert_eq!(events.len(), 1); + } let expected_payment_id = match events[0] { - Event::PaymentPathFailed { payment_hash, payment_failed_permanently, ref path, ref payment_id, .. } => { + Event::PaymentPathFailed { + payment_hash, + payment_failed_permanently, + ref path, + ref payment_id, + .. + } => { assert_eq!(payment_hash, our_payment_hash); assert!(payment_failed_permanently); for (idx, hop) in expected_route.iter().enumerate() { @@ -3277,10 +4227,14 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe if i == expected_paths.len() - 1 { match events[1] { Event::PaymentFailed { ref payment_hash, ref payment_id, ref reason } => { - assert_eq!(*payment_hash, Some(our_payment_hash), "unexpected second payment_hash"); + assert_eq!( + *payment_hash, + Some(our_payment_hash), + "unexpected second payment_hash" + ); assert_eq!(*payment_id, expected_payment_id); assert_eq!(reason.unwrap(), expected_fail_reason); - } + }, _ => panic!("Unexpected second event"), } } @@ -3294,7 +4248,10 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe check_added_monitors!(expected_paths[0].last().unwrap(), 0); } -pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], our_payment_hash: PaymentHash) { +pub fn fail_payment<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], + our_payment_hash: PaymentHash, +) { fail_payment_along_route(origin_node, &[&expected_path[..]], false, our_payment_hash); } @@ -3302,7 +4259,9 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec { create_chanmon_cfgs_with_keys(node_count, None) } -pub fn create_chanmon_cfgs_with_keys(node_count: usize, predefined_keys_ids: Option>) -> Vec { +pub fn create_chanmon_cfgs_with_keys( + node_count: usize, predefined_keys_ids: Option>, +) -> Vec { let mut chan_mon_cfgs = Vec::new(); for i in 0..node_count { let tx_broadcaster = test_utils::TestBroadcaster::new(Network::Testnet); @@ -3321,21 +4280,45 @@ pub fn create_chanmon_cfgs_with_keys(node_count: usize, predefined_keys_ids: Opt } } - chan_mon_cfgs.push(TestChanMonCfg { tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager, scorer }); + chan_mon_cfgs.push(TestChanMonCfg { + tx_broadcaster, + fee_estimator, + chain_source, + logger, + persister, + keys_manager, + scorer, + }); } chan_mon_cfgs } -pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec) -> Vec> { - create_node_cfgs_with_persisters(node_count, chanmon_cfgs, chanmon_cfgs.iter().map(|c| &c.persister).collect()) +pub fn create_node_cfgs<'a>( + node_count: usize, chanmon_cfgs: &'a Vec, +) -> Vec> { + create_node_cfgs_with_persisters( + node_count, + chanmon_cfgs, + chanmon_cfgs.iter().map(|c| &c.persister).collect(), + ) } -pub fn create_node_cfgs_with_persisters<'a>(node_count: usize, chanmon_cfgs: &'a Vec, persisters: Vec<&'a impl test_utils::SyncPersist>) -> Vec> { +pub fn create_node_cfgs_with_persisters<'a>( + node_count: usize, chanmon_cfgs: &'a Vec, + persisters: Vec<&'a impl test_utils::SyncPersist>, +) -> Vec> { let mut nodes = Vec::new(); for i in 0..node_count { - let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[i].chain_source), &chanmon_cfgs[i].tx_broadcaster, &chanmon_cfgs[i].logger, &chanmon_cfgs[i].fee_estimator, persisters[i], &chanmon_cfgs[i].keys_manager); + let chain_monitor = test_utils::TestChainMonitor::new( + Some(&chanmon_cfgs[i].chain_source), + &chanmon_cfgs[i].tx_broadcaster, + &chanmon_cfgs[i].logger, + &chanmon_cfgs[i].fee_estimator, + persisters[i], + &chanmon_cfgs[i].keys_manager, + ); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &chanmon_cfgs[i].logger)); let seed = [i as u8; 32]; nodes.push(NodeCfg { @@ -3343,8 +4326,15 @@ pub fn create_node_cfgs_with_persisters<'a>(node_count: usize, chanmon_cfgs: &'a logger: &chanmon_cfgs[i].logger, tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster, fee_estimator: &chanmon_cfgs[i].fee_estimator, - router: test_utils::TestRouter::new(network_graph.clone(), &chanmon_cfgs[i].logger, &chanmon_cfgs[i].scorer), - message_router: test_utils::TestMessageRouter::new(network_graph.clone(), &chanmon_cfgs[i].keys_manager), + router: test_utils::TestRouter::new( + network_graph.clone(), + &chanmon_cfgs[i].logger, + &chanmon_cfgs[i].scorer, + ), + message_router: test_utils::TestMessageRouter::new( + network_graph.clone(), + &chanmon_cfgs[i].keys_manager, + ), chain_monitor, keys_manager: &chanmon_cfgs[i].keys_manager, node_seed: seed, @@ -3374,24 +4364,66 @@ pub fn test_default_channel_config() -> UserConfig { default_config } -pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec>, node_config: &[Option]) -> Vec, &'b test_utils::TestBroadcaster, &'a test_utils::TestKeysInterface, &'a test_utils::TestKeysInterface, &'a test_utils::TestKeysInterface, &'b test_utils::TestFeeEstimator, &'a test_utils::TestRouter<'b>, &'a test_utils::TestMessageRouter<'b>, &'b test_utils::TestLogger>> { +pub fn create_node_chanmgrs<'a, 'b>( + node_count: usize, cfgs: &'a Vec>, node_config: &[Option], +) -> Vec< + ChannelManager< + &'a TestChainMonitor<'b>, + &'b test_utils::TestBroadcaster, + &'a test_utils::TestKeysInterface, + &'a test_utils::TestKeysInterface, + &'a test_utils::TestKeysInterface, + &'b test_utils::TestFeeEstimator, + &'a test_utils::TestRouter<'b>, + &'a test_utils::TestMessageRouter<'b>, + &'b test_utils::TestLogger, + >, +> { let mut chanmgrs = Vec::new(); for i in 0..node_count { let network = Network::Testnet; let genesis_block = bitcoin::constants::genesis_block(network); - let params = ChainParameters { - network, - best_block: BestBlock::from_network(network), - }; - let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, &cfgs[i].router, &cfgs[i].message_router, cfgs[i].logger, cfgs[i].keys_manager, - cfgs[i].keys_manager, cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { test_default_channel_config() }, params, genesis_block.header.time); + let params = ChainParameters { network, best_block: BestBlock::from_network(network) }; + let node = ChannelManager::new( + cfgs[i].fee_estimator, + &cfgs[i].chain_monitor, + cfgs[i].tx_broadcaster, + &cfgs[i].router, + &cfgs[i].message_router, + cfgs[i].logger, + cfgs[i].keys_manager, + cfgs[i].keys_manager, + cfgs[i].keys_manager, + if node_config[i].is_some() { + node_config[i].clone().unwrap() + } else { + test_default_channel_config() + }, + params, + genesis_block.header.time, + ); chanmgrs.push(node); } chanmgrs } -pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec>, chan_mgrs: &'a Vec, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'b test_utils::TestKeysInterface, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestRouter, &'c test_utils::TestMessageRouter, &'c test_utils::TestLogger>>) -> Vec> { +pub fn create_network<'a, 'b: 'a, 'c: 'b>( + node_count: usize, cfgs: &'b Vec>, + chan_mgrs: &'a Vec< + ChannelManager< + &'b TestChainMonitor<'c>, + &'c test_utils::TestBroadcaster, + &'b test_utils::TestKeysInterface, + &'b test_utils::TestKeysInterface, + &'b test_utils::TestKeysInterface, + &'c test_utils::TestFeeEstimator, + &'c test_utils::TestRouter, + &'c test_utils::TestMessageRouter, + &'c test_utils::TestLogger, + >, + >, +) -> Vec> { let mut nodes = Vec::new(); let chan_count = Rc::new(RefCell::new(0)); let payment_count = Rc::new(RefCell::new(0)); @@ -3401,39 +4433,63 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec(node: &Node<'a, 'b, 'c>) { let mut dummy_init_features = InitFeatures::empty(); dummy_init_features.set_static_remote_key_required(); - let init_dummy = msgs::Init { - features: dummy_init_features, - networks: None, - remote_network_address: None - }; + let init_dummy = + msgs::Init { features: dummy_init_features, networks: None, remote_network_address: None }; node.node.peer_connected(node_id_dummy, &init_dummy, true).unwrap(); node.onion_messenger.peer_connected(node_id_dummy, &init_dummy, true).unwrap(); @@ -3489,7 +4542,11 @@ pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 137; // Here we have a diff due t pub const ACCEPTED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 140; // Here we have a diff due to HTLC CLTV expiry being < 2^15 in test #[derive(PartialEq)] -pub enum HTLCType { NONE, TIMEOUT, SUCCESS } +pub enum HTLCType { + NONE, + TIMEOUT, + SUCCESS, +} /// Tests that the given node has broadcast transactions for the given Channel /// /// First checks that the latest holder commitment tx has been broadcast, unless an explicit @@ -3501,11 +4558,19 @@ pub enum HTLCType { NONE, TIMEOUT, SUCCESS } /// /// All broadcast transactions must be accounted for in one of the above three types of we'll /// also fail. -pub fn test_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction), commitment_tx: Option, has_htlc_tx: HTLCType) -> Vec { +pub fn test_txn_broadcast<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, + chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, ChannelId, Transaction), + commitment_tx: Option, has_htlc_tx: HTLCType, +) -> Vec { let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap(); let mut txn_seen = new_hash_set(); node_txn.retain(|tx| txn_seen.insert(tx.compute_txid())); - assert!(node_txn.len() >= if commitment_tx.is_some() { 0 } else { 1 } + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 }); + assert!( + node_txn.len() + >= if commitment_tx.is_some() { 0 } else { 1 } + + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 } + ); let mut res = Vec::with_capacity(2); node_txn.retain(|tx| { @@ -3515,7 +4580,9 @@ pub fn test_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, chan: &(msgs::Cha res.push(tx.clone()); } false - } else { true } + } else { + true + } }); if let Some(explicit_tx) = commitment_tx { res.push(explicit_tx.clone()); @@ -3534,7 +4601,9 @@ pub fn test_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, chan: &(msgs::Cha } res.push(tx.clone()); false - } else { true } + } else { + true + } }); assert!(res.len() == 2 || res.len() == 3); if res.len() == 3 { @@ -3548,16 +4617,22 @@ pub fn test_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, chan: &(msgs::Cha /// Tests that the given node has broadcast a claim transaction against the provided revoked /// HTLC transaction. -pub fn test_revoked_htlc_claim_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, revoked_tx: Transaction, commitment_revoked_tx: Transaction) { +pub fn test_revoked_htlc_claim_txn_broadcast<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, revoked_tx: Transaction, commitment_revoked_tx: Transaction, +) { let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap(); // We may issue multiple claiming transaction on revoked outputs due to block rescan // for revoked htlc outputs - if node_txn.len() != 1 && node_txn.len() != 2 && node_txn.len() != 3 { assert!(false); } + if node_txn.len() != 1 && node_txn.len() != 2 && node_txn.len() != 3 { + assert!(false); + } node_txn.retain(|tx| { if tx.input.len() == 1 && tx.input[0].previous_output.txid == revoked_tx.compute_txid() { check_spends!(tx, revoked_tx); false - } else { true } + } else { + true + } }); node_txn.retain(|tx| { check_spends!(tx, commitment_revoked_tx); @@ -3566,7 +4641,9 @@ pub fn test_revoked_htlc_claim_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c> assert!(node_txn.is_empty()); } -pub fn check_preimage_claim<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, prev_txn: &Vec) -> Vec { +pub fn check_preimage_claim<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, prev_txn: &Vec, +) -> Vec { let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap(); let mut txn_seen = new_hash_set(); node_txn.retain(|tx| txn_seen.insert(tx.compute_txid())); @@ -3594,7 +4671,9 @@ pub fn check_preimage_claim<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, prev_txn: &Vec< res } -pub fn handle_announce_close_broadcast_events<'a, 'b, 'c>(nodes: &Vec>, a: usize, b: usize, needs_err_handle: bool, expected_error: &str) { +pub fn handle_announce_close_broadcast_events<'a, 'b, 'c>( + nodes: &Vec>, a: usize, b: usize, needs_err_handle: bool, expected_error: &str, +) { let mut dummy_connected = false; if !is_any_peer_connected(&nodes[a]) { connect_dummy_node(&nodes[a]); @@ -3604,20 +4683,24 @@ pub fn handle_announce_close_broadcast_events<'a, 'b, 'c>(nodes: &Vec { - msg.clone() - }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => msg.clone(), _ => panic!("Unexpected event"), }; match events_1[0] { - MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => { + MessageSendEvent::HandleError { + node_id, + action: msgs::ErrorAction::SendErrorMessage { ref msg }, + } => { assert_eq!(node_id, nodes[b].node.get_our_node_id()); assert_eq!(msg.data, expected_error); if needs_err_handle { nodes[b].node.handle_error(nodes[a].node.get_our_node_id(), msg); } }, - MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::DisconnectPeer { ref msg } } => { + MessageSendEvent::HandleError { + node_id, + action: msgs::ErrorAction::DisconnectPeer { ref msg }, + } => { assert_eq!(node_id, nodes[b].node.get_our_node_id()); assert_eq!(msg.as_ref().unwrap().data, expected_error); if needs_err_handle { @@ -3637,18 +4720,22 @@ pub fn handle_announce_close_broadcast_events<'a, 'b, 'c>(nodes: &Vec { - msg.clone() - }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => msg.clone(), _ => panic!("Unexpected event"), }; if !needs_err_handle { match events_2[0] { - MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => { + MessageSendEvent::HandleError { + node_id, + action: msgs::ErrorAction::SendErrorMessage { ref msg }, + } => { assert_eq!(node_id, nodes[a].node.get_our_node_id()); assert_eq!(msg.data, expected_error); }, - MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::DisconnectPeer { ref msg } } => { + MessageSendEvent::HandleError { + node_id, + action: msgs::ErrorAction::DisconnectPeer { ref msg }, + } => { assert_eq!(node_id, nodes[a].node.get_our_node_id()); assert_eq!(msg.as_ref().unwrap().data, expected_error); }, @@ -3665,48 +4752,63 @@ pub fn handle_announce_close_broadcast_events<'a, 'b, 'c>(nodes: &Vec(nodes: &Vec>, a: usize, b: usize) { - handle_announce_close_broadcast_events(nodes, a, b, false, "Channel closed because commitment or closing transaction was confirmed on chain."); +pub fn get_announce_close_broadcast_events<'a, 'b, 'c>( + nodes: &Vec>, a: usize, b: usize, +) { + handle_announce_close_broadcast_events( + nodes, + a, + b, + false, + "Channel closed because commitment or closing transaction was confirmed on chain.", + ); } #[cfg(any(test, feature = "_externalize_tests"))] macro_rules! get_channel_value_stat { ($node: expr, $counterparty_node: expr, $channel_id: expr) => {{ let peer_state_lock = $node.node.per_peer_state.read().unwrap(); - let chan_lock = peer_state_lock.get(&$counterparty_node.node.get_our_node_id()).unwrap().lock().unwrap(); + let chan_lock = peer_state_lock + .get(&$counterparty_node.node.get_our_node_id()) + .unwrap() + .lock() + .unwrap(); let chan = chan_lock.channel_by_id.get(&$channel_id).and_then(Channel::as_funded).unwrap(); chan.get_value_stat() - }} + }}; } macro_rules! get_chan_reestablish_msgs { - ($src_node: expr, $dst_node: expr) => { - { - let mut announcements = $crate::prelude::new_hash_set(); - let mut res = Vec::with_capacity(1); - for msg in $src_node.node.get_and_clear_pending_msg_events() { - if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - res.push(msg.clone()); - } else if let MessageSendEvent::SendChannelAnnouncement { ref node_id, ref msg, .. } = msg { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - announcements.insert(msg.contents.short_channel_id); - } else { - panic!("Unexpected event") - } + ($src_node: expr, $dst_node: expr) => {{ + let mut announcements = $crate::prelude::new_hash_set(); + let mut res = Vec::with_capacity(1); + for msg in $src_node.node.get_and_clear_pending_msg_events() { + if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + res.push(msg.clone()); + } else if let MessageSendEvent::SendChannelAnnouncement { + ref node_id, ref msg, .. + } = msg + { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + announcements.insert(msg.contents.short_channel_id); + } else { + panic!("Unexpected event") } - assert!(announcements.is_empty()); - res } - } + assert!(announcements.is_empty()); + res + }}; } macro_rules! handle_chan_reestablish_msgs { - ($src_node: expr, $dst_node: expr) => { - { - let msg_events = $src_node.node.get_and_clear_pending_msg_events(); - let mut idx = 0; - let channel_ready = if let Some(&MessageSendEvent::SendChannelReady { ref node_id, ref msg }) = msg_events.get(0) { + ($src_node: expr, $dst_node: expr) => {{ + let msg_events = $src_node.node.get_and_clear_pending_msg_events(); + let mut idx = 0; + let channel_ready = + if let Some(&MessageSendEvent::SendChannelReady { ref node_id, ref msg }) = + msg_events.get(0) + { idx += 1; assert_eq!(*node_id, $dst_node.node.get_our_node_id()); Some(msg.clone()) @@ -3714,71 +4816,80 @@ macro_rules! handle_chan_reestablish_msgs { None }; - if let Some(&MessageSendEvent::SendAnnouncementSignatures { ref node_id, msg: _ }) = msg_events.get(idx) { - idx += 1; - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - } - - let mut had_channel_update = false; // ChannelUpdate may be now or later, but not both - if let Some(&MessageSendEvent::SendChannelUpdate { ref node_id, .. }) = msg_events.get(idx) { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - idx += 1; - had_channel_update = true; - } + if let Some(&MessageSendEvent::SendAnnouncementSignatures { ref node_id, msg: _ }) = + msg_events.get(idx) + { + idx += 1; + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + } - let mut revoke_and_ack = None; - let mut commitment_update = None; - let order = if let Some(ev) = msg_events.get(idx) { - match ev { - &MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - revoke_and_ack = Some(msg.clone()); - idx += 1; - RAACommitmentOrder::RevokeAndACKFirst - }, - &MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, ref updates } => { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - assert!(updates.commitment_signed.iter().all(|cs| cs.channel_id == *channel_id)); - commitment_update = Some(updates.clone()); - idx += 1; - RAACommitmentOrder::CommitmentFirst - }, - _ => RAACommitmentOrder::CommitmentFirst, - } - } else { - RAACommitmentOrder::CommitmentFirst - }; + let mut had_channel_update = false; // ChannelUpdate may be now or later, but not both + if let Some(&MessageSendEvent::SendChannelUpdate { ref node_id, .. }) = msg_events.get(idx) + { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + idx += 1; + had_channel_update = true; + } - if let Some(ev) = msg_events.get(idx) { - match ev { - &MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - assert!(revoke_and_ack.is_none()); - revoke_and_ack = Some(msg.clone()); - idx += 1; - }, - &MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, ref updates } => { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - assert!(commitment_update.is_none()); - assert!(updates.commitment_signed.iter().all(|cs| cs.channel_id == *channel_id)); - commitment_update = Some(updates.clone()); - idx += 1; - }, - _ => {}, - } + let mut revoke_and_ack = None; + let mut commitment_update = None; + let order = if let Some(ev) = msg_events.get(idx) { + match ev { + &MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + revoke_and_ack = Some(msg.clone()); + idx += 1; + RAACommitmentOrder::RevokeAndACKFirst + }, + &MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, ref updates } => { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + assert!(updates + .commitment_signed + .iter() + .all(|cs| cs.channel_id == *channel_id)); + commitment_update = Some(updates.clone()); + idx += 1; + RAACommitmentOrder::CommitmentFirst + }, + _ => RAACommitmentOrder::CommitmentFirst, } + } else { + RAACommitmentOrder::CommitmentFirst + }; - if let Some(&MessageSendEvent::SendChannelUpdate { ref node_id, .. }) = msg_events.get(idx) { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - idx += 1; - assert!(!had_channel_update); + if let Some(ev) = msg_events.get(idx) { + match ev { + &MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + assert!(revoke_and_ack.is_none()); + revoke_and_ack = Some(msg.clone()); + idx += 1; + }, + &MessageSendEvent::UpdateHTLCs { ref node_id, ref channel_id, ref updates } => { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + assert!(commitment_update.is_none()); + assert!(updates + .commitment_signed + .iter() + .all(|cs| cs.channel_id == *channel_id)); + commitment_update = Some(updates.clone()); + idx += 1; + }, + _ => {}, } + } - assert_eq!(msg_events.len(), idx); - - (channel_ready, revoke_and_ack, commitment_update, order) + if let Some(&MessageSendEvent::SendChannelUpdate { ref node_id, .. }) = msg_events.get(idx) + { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + idx += 1; + assert!(!had_channel_update); } - } + + assert_eq!(msg_events.len(), idx); + + (channel_ready, revoke_and_ack, commitment_update, order) + }}; } pub struct ReconnectArgs<'a, 'b, 'c, 'd> { @@ -3819,9 +4930,17 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> { /// for claims/fails they are separated out. pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) { let ReconnectArgs { - node_a, node_b, send_channel_ready, pending_htlc_adds, pending_htlc_claims, pending_htlc_fails, - pending_cell_htlc_claims, pending_cell_htlc_fails, pending_raa, - pending_responding_commitment_signed, pending_responding_commitment_signed_dup_monitor, + node_a, + node_b, + send_channel_ready, + pending_htlc_adds, + pending_htlc_claims, + pending_htlc_fails, + pending_cell_htlc_claims, + pending_cell_htlc_fails, + pending_raa, + pending_responding_commitment_signed, + pending_responding_commitment_signed_dup_monitor, } = args; connect_nodes(node_a, node_b); let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b); @@ -3879,10 +4998,18 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) { } // We don't yet support both needing updates, as that would require a different commitment dance: - assert!((pending_htlc_adds.0 == 0 && pending_htlc_claims.0 == 0 && pending_htlc_fails.0 == 0 && - pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0) || - (pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_htlc_fails.1 == 0 && - pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0)); + assert!( + (pending_htlc_adds.0 == 0 + && pending_htlc_claims.0 == 0 + && pending_htlc_fails.0 == 0 + && pending_cell_htlc_claims.0 == 0 + && pending_cell_htlc_fails.0 == 0) + || (pending_htlc_adds.1 == 0 + && pending_htlc_claims.1 == 0 + && pending_htlc_fails.1 == 0 + && pending_cell_htlc_claims.1 == 0 + && pending_cell_htlc_fails.1 == 0) + ); for chan_msgs in resp_1.drain(..) { if send_channel_ready.0 { @@ -3892,7 +5019,9 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) { assert_eq!(announcement_event.len(), 1); if let MessageSendEvent::SendChannelUpdate { .. } = announcement_event[0] { //TODO: Test announcement_sigs re-sending - } else { panic!("Unexpected event! {:?}", announcement_event[0]); } + } else { + panic!("Unexpected event! {:?}", announcement_event[0]); + } } } else { assert!(chan_msgs.0.is_none()); @@ -3905,35 +5034,63 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) { } else { assert!(chan_msgs.1.is_none()); } - if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 || - pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 || - pending_responding_commitment_signed.0 + if pending_htlc_adds.0 != 0 + || pending_htlc_claims.0 != 0 + || pending_htlc_fails.0 != 0 + || pending_cell_htlc_claims.0 != 0 + || pending_cell_htlc_fails.0 != 0 + || pending_responding_commitment_signed.0 { let commitment_update = chan_msgs.2.unwrap(); assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.0); - assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0); - assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.0 + pending_cell_htlc_fails.0); + assert_eq!( + commitment_update.update_fulfill_htlcs.len(), + pending_htlc_claims.0 + pending_cell_htlc_claims.0 + ); + assert_eq!( + commitment_update.update_fail_htlcs.len(), + pending_htlc_fails.0 + pending_cell_htlc_fails.0 + ); assert!(commitment_update.update_fail_malformed_htlcs.is_empty()); for update_add in commitment_update.update_add_htlcs { node_a.node.handle_update_add_htlc(node_b.node.get_our_node_id(), &update_add); } for update_fulfill in commitment_update.update_fulfill_htlcs { - node_a.node.handle_update_fulfill_htlc(node_b.node.get_our_node_id(), &update_fulfill); + node_a + .node + .handle_update_fulfill_htlc(node_b.node.get_our_node_id(), &update_fulfill); } for update_fail in commitment_update.update_fail_htlcs { node_a.node.handle_update_fail_htlc(node_b.node.get_our_node_id(), &update_fail); } if !pending_responding_commitment_signed.0 { - commitment_signed_dance!(node_a, node_b, commitment_update.commitment_signed, false); + commitment_signed_dance!( + node_a, + node_b, + commitment_update.commitment_signed, + false + ); } else { - node_a.node.handle_commitment_signed_batch_test(node_b.node.get_our_node_id(), &commitment_update.commitment_signed); + node_a.node.handle_commitment_signed_batch_test( + node_b.node.get_our_node_id(), + &commitment_update.commitment_signed, + ); check_added_monitors!(node_a, 1); - let as_revoke_and_ack = get_event_msg!(node_a, MessageSendEvent::SendRevokeAndACK, node_b.node.get_our_node_id()); + let as_revoke_and_ack = get_event_msg!( + node_a, + MessageSendEvent::SendRevokeAndACK, + node_b.node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes - node_b.node.handle_revoke_and_ack(node_a.node.get_our_node_id(), &as_revoke_and_ack); + node_b + .node + .handle_revoke_and_ack(node_a.node.get_our_node_id(), &as_revoke_and_ack); assert!(node_b.node.get_and_clear_pending_msg_events().is_empty()); - check_added_monitors!(node_b, if pending_responding_commitment_signed_dup_monitor.0 { 0 } else { 1 }); + check_added_monitors!( + node_b, + if pending_responding_commitment_signed_dup_monitor.0 { 0 } else { 1 } + ); } } else { assert!(chan_msgs.2.is_none()); @@ -3963,35 +5120,63 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) { } else { assert!(chan_msgs.1.is_none()); } - if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 || - pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 || - pending_responding_commitment_signed.1 + if pending_htlc_adds.1 != 0 + || pending_htlc_claims.1 != 0 + || pending_htlc_fails.1 != 0 + || pending_cell_htlc_claims.1 != 0 + || pending_cell_htlc_fails.1 != 0 + || pending_responding_commitment_signed.1 { let commitment_update = chan_msgs.2.unwrap(); assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.1); - assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.1 + pending_cell_htlc_claims.1); - assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.1 + pending_cell_htlc_fails.1); + assert_eq!( + commitment_update.update_fulfill_htlcs.len(), + pending_htlc_claims.1 + pending_cell_htlc_claims.1 + ); + assert_eq!( + commitment_update.update_fail_htlcs.len(), + pending_htlc_fails.1 + pending_cell_htlc_fails.1 + ); assert!(commitment_update.update_fail_malformed_htlcs.is_empty()); for update_add in commitment_update.update_add_htlcs { node_b.node.handle_update_add_htlc(node_a.node.get_our_node_id(), &update_add); } for update_fulfill in commitment_update.update_fulfill_htlcs { - node_b.node.handle_update_fulfill_htlc(node_a.node.get_our_node_id(), &update_fulfill); + node_b + .node + .handle_update_fulfill_htlc(node_a.node.get_our_node_id(), &update_fulfill); } for update_fail in commitment_update.update_fail_htlcs { node_b.node.handle_update_fail_htlc(node_a.node.get_our_node_id(), &update_fail); } if !pending_responding_commitment_signed.1 { - commitment_signed_dance!(node_b, node_a, commitment_update.commitment_signed, false); + commitment_signed_dance!( + node_b, + node_a, + commitment_update.commitment_signed, + false + ); } else { - node_b.node.handle_commitment_signed_batch_test(node_a.node.get_our_node_id(), &commitment_update.commitment_signed); + node_b.node.handle_commitment_signed_batch_test( + node_a.node.get_our_node_id(), + &commitment_update.commitment_signed, + ); check_added_monitors!(node_b, 1); - let bs_revoke_and_ack = get_event_msg!(node_b, MessageSendEvent::SendRevokeAndACK, node_a.node.get_our_node_id()); + let bs_revoke_and_ack = get_event_msg!( + node_b, + MessageSendEvent::SendRevokeAndACK, + node_a.node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes - node_a.node.handle_revoke_and_ack(node_b.node.get_our_node_id(), &bs_revoke_and_ack); + node_a + .node + .handle_revoke_and_ack(node_b.node.get_our_node_id(), &bs_revoke_and_ack); assert!(node_a.node.get_and_clear_pending_msg_events().is_empty()); - check_added_monitors!(node_a, if pending_responding_commitment_signed_dup_monitor.1 { 0 } else { 1 }); + check_added_monitors!( + node_a, + if pending_responding_commitment_signed_dup_monitor.1 { 0 } else { 1 } + ); } } else { assert!(chan_msgs.2.is_none()); @@ -4010,17 +5195,34 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>( let mut temp_chan_ids = Vec::new(); let mut funding_created_msgs = Vec::new(); - for (other_node, channel_value_satoshis, push_msat, user_channel_id, override_config) in params { + for (other_node, channel_value_satoshis, push_msat, user_channel_id, override_config) in params + { // Initialize channel opening. - let temp_chan_id = funding_node.node.create_channel( - other_node.node.get_our_node_id(), *channel_value_satoshis, *push_msat, *user_channel_id, - None, - override_config.clone(), - ).unwrap(); - let open_channel_msg = get_event_msg!(funding_node, MessageSendEvent::SendOpenChannel, other_node.node.get_our_node_id()); + let temp_chan_id = funding_node + .node + .create_channel( + other_node.node.get_our_node_id(), + *channel_value_satoshis, + *push_msat, + *user_channel_id, + None, + override_config.clone(), + ) + .unwrap(); + let open_channel_msg = get_event_msg!( + funding_node, + MessageSendEvent::SendOpenChannel, + other_node.node.get_our_node_id() + ); other_node.node.handle_open_channel(funding_node.node.get_our_node_id(), &open_channel_msg); - let accept_channel_msg = get_event_msg!(other_node, MessageSendEvent::SendAcceptChannel, funding_node.node.get_our_node_id()); - funding_node.node.handle_accept_channel(other_node.node.get_our_node_id(), &accept_channel_msg); + let accept_channel_msg = get_event_msg!( + other_node, + MessageSendEvent::SendAcceptChannel, + funding_node.node.get_our_node_id() + ); + funding_node + .node + .handle_accept_channel(other_node.node.get_our_node_id(), &accept_channel_msg); // Create the corresponding funding output. let events = funding_node.node.get_and_clear_pending_events(); @@ -4031,14 +5233,15 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>( ref counterparty_node_id, channel_value_satoshis: ref event_channel_value_satoshis, ref output_script, - user_channel_id: ref event_user_channel_id + user_channel_id: ref event_user_channel_id, } => { assert_eq!(temporary_channel_id, &temp_chan_id); assert_eq!(counterparty_node_id, &other_node.node.get_our_node_id()); assert_eq!(channel_value_satoshis, event_channel_value_satoshis); assert_eq!(user_channel_id, event_user_channel_id); tx_outs.push(TxOut { - value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(), + value: Amount::from_sat(*channel_value_satoshis), + script_pubkey: output_script.clone(), }); }, _ => panic!("Unexpected event"), @@ -4053,10 +5256,13 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>( input: Vec::new(), output: tx_outs, }; - assert!(funding_node.node.batch_funding_transaction_generated( - temp_chan_ids.iter().map(|(a, b)| (a, b)).collect::>().as_slice(), - tx.clone(), - ).is_ok()); + assert!(funding_node + .node + .batch_funding_transaction_generated( + temp_chan_ids.iter().map(|(a, b)| (a, b)).collect::>().as_slice(), + tx.clone(), + ) + .is_ok()); check_added_monitors!(funding_node, 0); let events = funding_node.node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), params.len()); @@ -4064,7 +5270,11 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>( let funding_created = events .iter() .find_map(|event| match event { - MessageSendEvent::SendFundingCreated { node_id, msg } if node_id == &other_node.node.get_our_node_id() => Some(msg.clone()), + MessageSendEvent::SendFundingCreated { node_id, msg } + if node_id == &other_node.node.get_our_node_id() => + { + Some(msg.clone()) + }, _ => None, }) .unwrap(); diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 4a0c08e020d..80a2db5e08d 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -12,58 +12,84 @@ //! claim outputs on-chain. use crate::chain; -use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; use crate::chain::chaininterface::LowerBoundedFeeEstimator; use crate::chain::channelmonitor; -use crate::chain::channelmonitor::{Balance, ChannelMonitorUpdateStep, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE}; +use crate::chain::channelmonitor::{ + Balance, ChannelMonitorUpdateStep, ANTI_REORG_DELAY, CLTV_CLAIM_BUFFER, + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE, LATENCY_GRACE_PERIOD_BLOCKS, +}; use crate::chain::transaction::OutPoint; -use crate::ln::onion_utils::LocalHTLCFailureReason; -use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider}; +use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; use crate::events::bump_transaction::WalletSource; -use crate::events::{Event, FundingInfo, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason}; +use crate::events::{ + ClosureReason, Event, FundingInfo, HTLCDestination, PathFailure, PaymentFailureReason, + PaymentPurpose, +}; +use crate::ln::chan_utils::{ + commitment_tx_base_weight, htlc_success_tx_weight, htlc_timeout_tx_weight, + HTLCOutputInCommitment, COMMITMENT_TX_WEIGHT_PER_HTLC, OFFERED_HTLC_SCRIPT_WEIGHT, +}; +use crate::ln::channel::{ + get_holder_selected_channel_reserve_satoshis, Channel, InboundV1Channel, OutboundV1Channel, + COINBASE_MATURITY, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, + MIN_AFFORDABLE_HTLC_COUNT, +}; +use crate::ln::channel::{ + ChannelError, DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, MIN_CHAN_DUST_LIMIT_SATOSHIS, +}; +use crate::ln::channelmanager::{ + self, PaymentId, RAACommitmentOrder, RecipientOnionFields, BREAKDOWN_TIMEOUT, + DISABLE_GOSSIP_TICKS, ENABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA, +}; +use crate::ln::msgs; +use crate::ln::msgs::{ + AcceptChannel, BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent, + RoutingMessageHandler, +}; +use crate::ln::onion_utils::AttributionData; +use crate::ln::onion_utils::LocalHTLCFailureReason; use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentPreimage, PaymentSecret, PaymentHash}; -use crate::ln::channel::{get_holder_selected_channel_reserve_satoshis, Channel, InboundV1Channel, OutboundV1Channel, COINBASE_MATURITY, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT}; -use crate::ln::channelmanager::{self, PaymentId, RAACommitmentOrder, RecipientOnionFields, BREAKDOWN_TIMEOUT, ENABLE_GOSSIP_TICKS, DISABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA}; -use crate::ln::channel::{DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, ChannelError, MIN_CHAN_DUST_LIMIT_SATOSHIS}; use crate::ln::{chan_utils, onion_utils}; -use crate::ln::chan_utils::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, OFFERED_HTLC_SCRIPT_WEIGHT, htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment}; use crate::routing::gossip::{NetworkGraph, NetworkUpdate}; -use crate::routing::router::{Path, PaymentParameters, Route, RouteHop, get_route, RouteParameters}; +use crate::routing::router::{ + get_route, Path, PaymentParameters, Route, RouteHop, RouteParameters, +}; +use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider}; use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; -use crate::ln::msgs; -use crate::ln::msgs::{AcceptChannel, BaseMessageHandler, ChannelMessageHandler, RoutingMessageHandler, ErrorAction, MessageSendEvent}; -use crate::util::test_channel_signer::TestChannelSigner; -use crate::util::test_utils::{self, TestLogger, WatchtowerPersister}; +use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; +use crate::util::config::{ + ChannelConfigOverrides, ChannelConfigUpdate, ChannelHandshakeConfigUpdate, MaxDustHTLCExposure, + UserConfig, +}; use crate::util::errors::APIError; -use crate::util::ser::{Writeable, ReadableArgs}; +use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::string::UntrustedString; -use crate::util::config::{ChannelConfigOverrides, ChannelHandshakeConfigUpdate, ChannelConfigUpdate, MaxDustHTLCExposure, UserConfig}; -use crate::ln::onion_utils::AttributionData; +use crate::util::test_channel_signer::TestChannelSigner; +use crate::util::test_utils::{self, TestLogger, WatchtowerPersister}; +use bitcoin::constants::ChainHash; use bitcoin::hash_types::BlockHash; use bitcoin::locktime::absolute::LockTime; -use bitcoin::script::{Builder, ScriptBuf}; -use bitcoin::opcodes; -use bitcoin::constants::ChainHash; use bitcoin::network::Network; -use bitcoin::{Amount, Sequence, Transaction, TxIn, TxOut, Witness}; -use bitcoin::OutPoint as BitcoinOutPoint; +use bitcoin::opcodes; +use bitcoin::script::{Builder, ScriptBuf}; use bitcoin::transaction::Version; +use bitcoin::OutPoint as BitcoinOutPoint; +use bitcoin::{Amount, Sequence, Transaction, TxIn, TxOut, Witness}; use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::{PublicKey,SecretKey}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use crate::io; use crate::prelude::*; +use crate::sync::{Arc, Mutex, RwLock}; use alloc::collections::BTreeSet; -use core::iter::repeat; use bitcoin::hashes::Hash; -use crate::sync::{Arc, Mutex, RwLock}; +use core::iter::repeat; use lightning_macros::xtest; -use crate::ln::functional_test_utils::*; use crate::ln::chan_utils::CommitmentTransaction; +use crate::ln::functional_test_utils::*; use super::channel::UNFUNDED_CHANNEL_AGE_LIMIT_TICKS; @@ -77,25 +103,51 @@ fn test_channel_resumption_fail_post_funding() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 0, 42, None, None).unwrap(); - let open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 0, 42, None, None) + .unwrap(); + let open_chan = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_chan); - let accept_chan = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_chan = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_chan); let (temp_chan_id, tx, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42); let new_chan_id = ChannelId::v1_from_funding_outpoint(funding_output); - nodes[0].node.funding_transaction_generated(temp_chan_id, nodes[1].node.get_our_node_id(), tx).unwrap(); + nodes[0] + .node + .funding_transaction_generated(temp_chan_id, nodes[1].node.get_our_node_id(), tx) + .unwrap(); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); - check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(new_chan_id, true, ClosureReason::DisconnectedPeer)]); + check_closed_events( + &nodes[0], + &[ExpectedCloseEvent::from_id_reason(new_chan_id, true, ClosureReason::DisconnectedPeer)], + ); // After ddf75afd16 we'd panic on reconnection if we exchanged funding info, so test that // explicitly here. - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); assert_eq!(nodes[0].node.get_and_clear_pending_msg_events(), Vec::new()); } @@ -113,51 +165,129 @@ pub fn test_insane_channel_opens() { // Instantiate channel parameters where we push the maximum msats given our // funding satoshis let channel_value_sat = 31337; // same as funding satoshis - let channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(channel_value_sat, &cfg); + let channel_reserve_satoshis = + get_holder_selected_channel_reserve_satoshis(channel_value_sat, &cfg); let push_msat = (channel_value_sat - channel_reserve_satoshis) * 1000; // Have node0 initiate a channel to node1 with aforementioned parameters - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_sat, push_msat, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_sat, + push_msat, + 42, + None, + None, + ) + .unwrap(); // Extract the channel open message from node0 to node1 - let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let open_channel_message = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); // Test helper that asserts we get the correct error string given a mutator // that supposedly makes the channel open message insane - let insane_open_helper = |expected_error_str: &str, message_mutator: fn(msgs::OpenChannel) -> msgs::OpenChannel| { - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &message_mutator(open_channel_message.clone())); - let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); - assert_eq!(msg_events.len(), 1); - let expected_regex = regex::Regex::new(expected_error_str).unwrap(); - if let MessageSendEvent::HandleError { ref action, .. } = msg_events[0] { - match action { - &ErrorAction::SendErrorMessage { .. } => { - nodes[1].logger.assert_log_regex("lightning::ln::channelmanager", expected_regex, 1); - }, - _ => panic!("unexpected event!"), + let insane_open_helper = + |expected_error_str: &str, message_mutator: fn(msgs::OpenChannel) -> msgs::OpenChannel| { + nodes[1].node.handle_open_channel( + nodes[0].node.get_our_node_id(), + &message_mutator(open_channel_message.clone()), + ); + let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 1); + let expected_regex = regex::Regex::new(expected_error_str).unwrap(); + if let MessageSendEvent::HandleError { ref action, .. } = msg_events[0] { + match action { + &ErrorAction::SendErrorMessage { .. } => { + nodes[1].logger.assert_log_regex( + "lightning::ln::channelmanager", + expected_regex, + 1, + ); + }, + _ => panic!("unexpected event!"), + } + } else { + assert!(false); } - } else { assert!(false); } - }; + }; use crate::ln::channelmanager::MAX_LOCAL_BREAKDOWN_TIMEOUT; // Test all mutations that would make the channel open message insane - insane_open_helper(format!("Per our config, funding must be at most {}. It was {}", TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1, TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2).as_str(), |mut msg| { msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2; msg }); - insane_open_helper(format!("Funding must be smaller than the total bitcoin supply. It was {}", TOTAL_BITCOIN_SUPPLY_SATOSHIS).as_str(), |mut msg| { msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS; msg }); + insane_open_helper( + format!( + "Per our config, funding must be at most {}. It was {}", + TOTAL_BITCOIN_SUPPLY_SATOSHIS + 1, + TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2 + ) + .as_str(), + |mut msg| { + msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS + 2; + msg + }, + ); + insane_open_helper( + format!( + "Funding must be smaller than the total bitcoin supply. It was {}", + TOTAL_BITCOIN_SUPPLY_SATOSHIS + ) + .as_str(), + |mut msg| { + msg.common_fields.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS; + msg + }, + ); - insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { msg.channel_reserve_satoshis = msg.common_fields.funding_satoshis + 1; msg }); + insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { + msg.channel_reserve_satoshis = msg.common_fields.funding_satoshis + 1; + msg + }); - insane_open_helper(r"push_msat \d+ was larger than channel amount minus reserve \(\d+\)", |mut msg| { msg.push_msat = (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000 + 1; msg }); + insane_open_helper( + r"push_msat \d+ was larger than channel amount minus reserve \(\d+\)", + |mut msg| { + msg.push_msat = + (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000 + 1; + msg + }, + ); - insane_open_helper("Peer never wants payout outputs?", |mut msg| { msg.common_fields.dust_limit_satoshis = msg.common_fields.funding_satoshis + 1 ; msg }); + insane_open_helper("Peer never wants payout outputs?", |mut msg| { + msg.common_fields.dust_limit_satoshis = msg.common_fields.funding_satoshis + 1; + msg + }); - insane_open_helper(r"Minimum htlc value \(\d+\) was larger than full channel value \(\d+\)", |mut msg| { msg.common_fields.htlc_minimum_msat = (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000; msg }); + insane_open_helper( + r"Minimum htlc value \(\d+\) was larger than full channel value \(\d+\)", + |mut msg| { + msg.common_fields.htlc_minimum_msat = + (msg.common_fields.funding_satoshis - msg.channel_reserve_satoshis) * 1000; + msg + }, + ); - insane_open_helper("They wanted our payments to be delayed by a needlessly long period", |mut msg| { msg.common_fields.to_self_delay = MAX_LOCAL_BREAKDOWN_TIMEOUT + 1; msg }); + insane_open_helper( + "They wanted our payments to be delayed by a needlessly long period", + |mut msg| { + msg.common_fields.to_self_delay = MAX_LOCAL_BREAKDOWN_TIMEOUT + 1; + msg + }, + ); - insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { msg.common_fields.max_accepted_htlcs = 0; msg }); + insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { + msg.common_fields.max_accepted_htlcs = 0; + msg + }); - insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { msg.common_fields.max_accepted_htlcs = 484; msg }); + insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { + msg.common_fields.max_accepted_htlcs = 484; + msg + }); } #[xtest(feature = "_externalize_tests")] @@ -173,11 +303,25 @@ pub fn test_funding_exceeds_no_wumbo_limit() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - match nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), MAX_FUNDING_SATOSHIS_NO_WUMBO + 1, 0, 42, None, None) { + match nodes[0].node.create_channel( + nodes[1].node.get_our_node_id(), + MAX_FUNDING_SATOSHIS_NO_WUMBO + 1, + 0, + 42, + None, + None, + ) { Err(APIError::APIMisuseError { err }) => { - assert_eq!(format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, MAX_FUNDING_SATOSHIS_NO_WUMBO + 1), err); + assert_eq!( + format!( + "funding_value must not exceed {}, it was {}", + MAX_FUNDING_SATOSHIS_NO_WUMBO, + MAX_FUNDING_SATOSHIS_NO_WUMBO + 1 + ), + err + ); }, - _ => panic!() + _ => panic!(), } } @@ -196,11 +340,27 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) { let mut push_amt = 100_000_000; let feerate_per_kw = 253; let channel_type_features = ChannelTypeFeatures::only_static_remote_key(); - push_amt -= feerate_per_kw as u64 * (commitment_tx_base_weight(&channel_type_features) + 4 * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 * 1000; + push_amt -= feerate_per_kw as u64 + * (commitment_tx_base_weight(&channel_type_features) + 4 * COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000 * 1000; push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000; - let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, if send_from_initiator { 0 } else { push_amt }, 42, None, None).unwrap(); - let mut open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let temp_channel_id = nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100_000, + if send_from_initiator { 0 } else { push_amt }, + 42, + None, + None, + ) + .unwrap(); + let mut open_channel_message = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); if !send_from_initiator { open_channel_message.channel_reserve_satoshis = 0; open_channel_message.common_fields.max_htlc_value_in_flight_msat = 100_000_000; @@ -208,7 +368,11 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) { nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_message); // Extract the channel accept message from node1 to node0 - let mut accept_channel_message = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let mut accept_channel_message = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); if send_from_initiator { accept_channel_message.channel_reserve_satoshis = 0; accept_channel_message.common_fields.max_htlc_value_in_flight_msat = 100_000_000; @@ -220,24 +384,35 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) { let mut sender_node_per_peer_lock; let mut sender_node_peer_state_lock; - let channel = get_channel_ref!(sender_node, counterparty_node, sender_node_per_peer_lock, sender_node_peer_state_lock, temp_channel_id); + let channel = get_channel_ref!( + sender_node, + counterparty_node, + sender_node_per_peer_lock, + sender_node_peer_state_lock, + temp_channel_id + ); assert!(channel.is_unfunded_v1()); channel.funding_mut().holder_selected_channel_reserve_satoshis = 0; channel.context_mut().holder_max_htlc_value_in_flight_msat = 100_000_000; } let funding_tx = sign_funding_transaction(&nodes[0], &nodes[1], 100_000, temp_channel_id); - let funding_msgs = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &funding_tx); + let funding_msgs = + create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &funding_tx); create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_msgs.0); // nodes[0] should now be able to send the full balance to nodes[1], violating nodes[1]'s // security model if it ever tries to send funds back to nodes[0] (but that's not our problem). if send_from_initiator { - send_payment(&nodes[0], &[&nodes[1]], 100_000_000 + send_payment( + &nodes[0], + &[&nodes[1]], + 100_000_000 // Note that for outbound channels we have to consider the commitment tx fee and the // "fee spike buffer", which is currently a multiple of the total commitment tx fee as // well as an additional HTLC. - - FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * commit_tx_fee_msat(feerate_per_kw, 2, &channel_type_features)); + - FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * commit_tx_fee_msat(feerate_per_kw, 2, &channel_type_features), + ); } else { send_payment(&nodes[1], &[&nodes[0]], push_amt); } @@ -258,7 +433,7 @@ pub fn test_async_inbound_update_fee() { create_announced_chan_between_nodes(&nodes, 0, 1); // balancing - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 8000000); // A B // update_fee -> @@ -287,19 +462,29 @@ pub fn test_async_inbound_update_fee() { let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_0.len(), 1); - let (update_msg, commitment_signed) = match events_0[0] { // (1) - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { - (update_fee.as_ref(), commitment_signed) - }, + let (update_msg, commitment_signed) = match events_0[0] { + // (1) + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, + .. + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msg.unwrap()); // ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]... - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 40000); - nodes[1].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 40000); + nodes[1] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); let payment_event = { @@ -312,14 +497,27 @@ pub fn test_async_inbound_update_fee() { // ...now when the messages get delivered everyone should be happy nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &payment_event.commitment_msg); // (2) - let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &payment_event.commitment_msg, + ); // (2) + let as_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // nodes[0] is awaiting nodes[1] revoke_and_ack so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); // deliver(1), generate (3): - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); - let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); + let bs_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // nodes[1] is awaiting nodes[0] revoke_and_ack so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[1], 1); @@ -341,13 +539,27 @@ pub fn test_async_inbound_update_fee() { assert!(as_update.update_fee.is_none()); // (5) check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_update.commitment_signed); // deliver (4) - let as_second_revoke = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_update.commitment_signed, + ); // deliver (4) + let as_second_revoke = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // only (6) so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_update.commitment_signed); // deliver (5) - let bs_second_revoke = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_update.commitment_signed, + ); // deliver (5) + let bs_second_revoke = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); check_added_monitors!(nodes[1], 1); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_second_revoke); @@ -356,7 +568,7 @@ pub fn test_async_inbound_update_fee() { let events_2 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_2.len(), 1); match events_2[0] { - Event::PendingHTLCsForwardable {..} => {}, // If we actually processed we'd receive the payment + Event::PendingHTLCsForwardable { .. } => {}, // If we actually processed we'd receive the payment _ => panic!("Unexpected event"), } @@ -375,7 +587,7 @@ pub fn test_update_fee_unordered_raa() { create_announced_chan_between_nodes(&nodes, 0, 1); // balancing - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 8000000); // First nodes[0] generates an update_fee { @@ -387,19 +599,29 @@ pub fn test_update_fee_unordered_raa() { let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_0.len(), 1); - let update_msg = match events_0[0] { // (1) - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, .. }, .. } => { - update_fee.as_ref() - }, + let update_msg = match events_0[0] { + // (1) + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, .. }, + .. + } => update_fee.as_ref(), _ => panic!("Unexpected event"), }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msg.unwrap()); // ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]... - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 40000); - nodes[1].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 40000); + nodes[1] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); let payment_event = { @@ -412,8 +634,15 @@ pub fn test_update_fee_unordered_raa() { // ...now when the messages get delivered everyone should be happy nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &payment_event.commitment_msg); // (2) - let as_revoke_msg = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &payment_event.commitment_msg, + ); // (2) + let as_revoke_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // nodes[0] is awaiting nodes[1] revoke_and_ack so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); @@ -462,17 +691,22 @@ pub fn test_multi_flight_update_fee() { let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_0.len(), 1); - let (update_msg_1, commitment_signed_1) = match events_0[0] { // (1) - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { - (update_fee.as_ref().unwrap(), commitment_signed) - }, + let (update_msg_1, commitment_signed_1) = match events_0[0] { + // (1) + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, + .. + } => (update_fee.as_ref().unwrap(), commitment_signed), _ => panic!("Unexpected event"), }; // Deliver first update_fee/commitment_signed pair, generating (1) and (2): nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msg_1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed_1); - let (bs_revoke_msg, bs_commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed_1); + let (bs_revoke_msg, bs_commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); // nodes[0] is awaiting a revoke from nodes[1] before it will create a new commitment @@ -507,11 +741,21 @@ pub fn test_multi_flight_update_fee() { assert!(as_second_update.update_fail_malformed_htlcs.is_empty()); // Check that the update_fee newly generated matches what we delivered: assert_eq!(as_second_update.update_fee.as_ref().unwrap().channel_id, update_msg_2.channel_id); - assert_eq!(as_second_update.update_fee.as_ref().unwrap().feerate_per_kw, update_msg_2.feerate_per_kw); + assert_eq!( + as_second_update.update_fee.as_ref().unwrap().feerate_per_kw, + update_msg_2.feerate_per_kw + ); // Deliver (2) commitment_signed - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_commitment_signed); - let as_revoke_msg = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_commitment_signed, + ); + let as_revoke_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); check_added_monitors!(nodes[0], 1); // No commitment_signed so get_event_msg's assert(len == 1) passes @@ -520,16 +764,27 @@ pub fn test_multi_flight_update_fee() { check_added_monitors!(nodes[1], 1); // Delever (4) - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_second_update.commitment_signed); - let (bs_second_revoke, bs_second_commitment) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_second_update.commitment_signed, + ); + let (bs_second_revoke, bs_second_commitment) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_second_revoke); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_commitment); - let as_second_revoke = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_second_commitment, + ); + let as_second_revoke = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); @@ -549,35 +804,69 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - if steps & 0b1000_0000 != 0{ + if steps & 0b1000_0000 != 0 { let block = create_dummy_block(nodes[0].best_block_hash(), 42, Vec::new()); connect_block(&nodes[0], &block); connect_block(&nodes[1], &block); } - if steps & 0x0f == 0 { return; } - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + if steps & 0x0f == 0 { + return; + } + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); - if steps & 0x0f == 1 { return; } + if steps & 0x0f == 1 { + return; + } nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); - if steps & 0x0f == 2 { return; } + if steps & 0x0f == 2 { + return; + } nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); - if steps & 0x0f == 3 { return; } - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + if steps & 0x0f == 3 { + return; + } + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let funding_created = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); let channel_id = ChannelId::v1_from_funding_txid( - funding_created.funding_txid.as_byte_array(), funding_created.funding_output_index + funding_created.funding_txid.as_byte_array(), + funding_created.funding_output_index, ); - if steps & 0x0f == 4 { return; } + if steps & 0x0f == 4 { + return; + } nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created); { let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); @@ -587,9 +876,15 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) { } expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); - if steps & 0x0f == 5 { return; } + if steps & 0x0f == 5 { + return; + } nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed); { let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); @@ -602,10 +897,14 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) { let events_4 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_4.len(), 0); - if steps & 0x0f == 6 { return; } + if steps & 0x0f == 6 { + return; + } create_chan_between_nodes_with_value_confirm_first(&nodes[0], &nodes[1], &tx, 2); - if steps & 0x0f == 7 { return; } + if steps & 0x0f == 7 { + return; + } confirm_transaction_at(&nodes[0], &tx, 2); connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH); create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]); @@ -652,23 +951,42 @@ pub fn test_update_fee_vanilla() { let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_0.len(), 1); let (update_msg, commitment_signed) = match events_0[0] { - MessageSendEvent::UpdateHTLCs { node_id:_, channel_id: _, updates: msgs::CommitmentUpdate { update_add_htlcs:_, update_fulfill_htlcs:_, update_fail_htlcs:_, update_fail_malformed_htlcs:_, ref update_fee, ref commitment_signed } } => { - (update_fee.as_ref(), commitment_signed) - }, + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + update_add_htlcs: _, + update_fulfill_htlcs: _, + update_fail_htlcs: _, + update_fail_malformed_htlcs: _, + ref update_fee, + ref commitment_signed, + }, + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msg.unwrap()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); - let (revoke_msg, commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); + let (revoke_msg, commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &revoke_msg); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); - let revoke_msg = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); + let revoke_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); @@ -685,11 +1003,18 @@ pub fn test_update_fee_that_funder_cannot_afford() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_value = 5000; let push_sats = 700; - let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, push_sats * 1000); + let chan = create_announced_chan_between_nodes_with_value( + &nodes, + 0, + 1, + channel_value, + push_sats * 1000, + ); let channel_id = chan.2; let secp_ctx = Secp256k1::new(); let default_config = UserConfig::default(); - let bs_channel_reserve_sats = get_holder_selected_channel_reserve_satoshis(channel_value, &default_config); + let bs_channel_reserve_sats = + get_holder_selected_channel_reserve_satoshis(channel_value, &default_config); let channel_type_features = ChannelTypeFeatures::only_static_remote_key(); @@ -697,8 +1022,12 @@ pub fn test_update_fee_that_funder_cannot_afford() { // CONCURRENT_INBOUND_HTLC_FEE_BUFFER HTLCs before actually running out of local balance, so we // calculate two different feerates here - the expected local limit as well as the expected // remote limit. - let feerate = ((channel_value - bs_channel_reserve_sats - push_sats) * 1000 / (commitment_tx_base_weight(&channel_type_features) + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC)) as u32; - let non_buffer_feerate = ((channel_value - bs_channel_reserve_sats - push_sats) * 1000 / commitment_tx_base_weight(&channel_type_features)) as u32; + let feerate = ((channel_value - bs_channel_reserve_sats - push_sats) * 1000 + / (commitment_tx_base_weight(&channel_type_features) + + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC)) + as u32; + let non_buffer_feerate = ((channel_value - bs_channel_reserve_sats - push_sats) * 1000 + / commitment_tx_base_weight(&channel_type_features)) as u32; { let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap(); *feerate_lock = feerate; @@ -707,7 +1036,9 @@ pub fn test_update_fee_that_funder_cannot_afford() { check_added_monitors!(nodes[0], 1); let update_msg = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), &update_msg.update_fee.unwrap()); + nodes[1] + .node + .handle_update_fee(nodes[0].node.get_our_node_id(), &update_msg.update_fee.unwrap()); commitment_signed_dance!(nodes[1], nodes[0], update_msg.commitment_signed, false); @@ -718,7 +1049,8 @@ pub fn test_update_fee_that_funder_cannot_afford() { //We made sure neither party's funds are below the dust limit and there are no HTLCs here assert_eq!(commitment_tx.output.len(), 2); let total_fee: u64 = commit_tx_fee_msat(feerate, 0, &channel_type_features) / 1000; - let mut actual_fee = commitment_tx.output.iter().fold(0, |acc, output| acc + output.value.to_sat()); + let mut actual_fee = + commitment_tx.output.iter().fold(0, |acc, output| acc + output.value.to_sat()); actual_fee = channel_value - actual_fee; assert_eq!(total_fee, actual_fee); } @@ -729,39 +1061,59 @@ pub fn test_update_fee_that_funder_cannot_afford() { *feerate_lock += 4; } nodes[0].node.timer_tick_occurred(); - nodes[0].logger.assert_log("lightning::ln::channel", format!("Cannot afford to send new feerate at {}", feerate + 4), 1); + nodes[0].logger.assert_log( + "lightning::ln::channel", + format!("Cannot afford to send new feerate at {}", feerate + 4), + 1, + ); check_added_monitors!(nodes[0], 0); const INITIAL_COMMITMENT_NUMBER: u64 = 281474976710654; let remote_point = { let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); - let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); + let chan_lock = + per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); + let remote_chan = + chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); let chan_signer = remote_chan.get_signer(); - chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap() + chan_signer + .as_ref() + .get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx) + .unwrap() }; let res = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); - let local_chan = local_chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); + let local_chan_lock = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let local_chan = + local_chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); let local_chan_signer = local_chan.get_signer(); let nondust_htlcs: Vec = vec![]; let commitment_tx = CommitmentTransaction::new( INITIAL_COMMITMENT_NUMBER - 1, &remote_point, push_sats, - channel_value - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000, + channel_value + - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) + / 1000, non_buffer_feerate + 4, nondust_htlcs, &local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(), &secp_ctx, ); - local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment( - &local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(), - Vec::new(), &secp_ctx, - ).unwrap() + local_chan_signer + .as_ecdsa() + .unwrap() + .sign_counterparty_commitment( + &local_chan.funding.channel_transaction_parameters, + &commitment_tx, + Vec::new(), + Vec::new(), + &secp_ctx, + ) + .unwrap() }; let commit_signed_msg = msgs::CommitmentSigned { @@ -773,10 +1125,7 @@ pub fn test_update_fee_that_funder_cannot_afford() { partial_signature_with_nonce: None, }; - let update_fee = msgs::UpdateFee { - channel_id: chan.2, - feerate_per_kw: non_buffer_feerate + 4, - }; + let update_fee = msgs::UpdateFee { channel_id: chan.2, feerate_per_kw: non_buffer_feerate + 4 }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), &update_fee); @@ -784,11 +1133,22 @@ pub fn test_update_fee_that_funder_cannot_afford() { //check to see if the funder, who sent the update_fee request, can afford the new fee (funder_balance >= fee+channel_reserve) //Should produce and error. nodes[1].node.handle_commitment_signed(nodes[0].node.get_our_node_id(), &commit_signed_msg); - nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Funding remote cannot afford proposed new fee", 3); + nodes[1].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Funding remote cannot afford proposed new fee", + 3, + ); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: String::from("Funding remote cannot afford proposed new fee") }, - [nodes[0].node.get_our_node_id()], channel_value); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { + err: String::from("Funding remote cannot afford proposed new fee") + }, + [nodes[0].node.get_our_node_id()], + channel_value + ); } #[xtest(feature = "_externalize_tests")] @@ -802,7 +1162,8 @@ pub fn test_update_fee_that_saturates_subs() { let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(default_config.clone()), Some(default_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(default_config.clone()), Some(default_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan_id = create_chan_between_nodes_with_value(&nodes[0], &nodes[1], 10_000, 8_500_000).3; @@ -821,16 +1182,20 @@ pub fn test_update_fee_that_saturates_subs() { let remote_point = { let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); - let remote_chan = chan_lock.channel_by_id.get(&chan_id).and_then(Channel::as_funded).unwrap(); + let chan_lock = + per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); + let remote_chan = + chan_lock.channel_by_id.get(&chan_id).and_then(Channel::as_funded).unwrap(); let chan_signer = remote_chan.get_signer(); chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER, &secp_ctx).unwrap() }; let res = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); - let local_chan = local_chan_lock.channel_by_id.get(&chan_id).and_then(Channel::as_funded).unwrap(); + let local_chan_lock = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let local_chan = + local_chan_lock.channel_by_id.get(&chan_id).and_then(Channel::as_funded).unwrap(); let local_chan_signer = local_chan.get_signer(); let nondust_htlcs: Vec = vec![]; let commitment_tx = CommitmentTransaction::new( @@ -845,10 +1210,17 @@ pub fn test_update_fee_that_saturates_subs() { &local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(), &secp_ctx, ); - local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment( - &local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(), - Vec::new(), &secp_ctx, - ).unwrap() + local_chan_signer + .as_ecdsa() + .unwrap() + .sign_counterparty_commitment( + &local_chan.funding.channel_transaction_parameters, + &commitment_tx, + Vec::new(), + Vec::new(), + &secp_ctx, + ) + .unwrap() }; let commit_signed_msg = msgs::CommitmentSigned { @@ -860,19 +1232,27 @@ pub fn test_update_fee_that_saturates_subs() { partial_signature_with_nonce: None, }; - let update_fee = msgs::UpdateFee { - channel_id: chan_id, - feerate_per_kw: FEERATE, - }; + let update_fee = msgs::UpdateFee { channel_id: chan_id, feerate_per_kw: FEERATE }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), &update_fee); nodes[1].node.handle_commitment_signed(nodes[0].node.get_our_node_id(), &commit_signed_msg); - nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Funding remote cannot afford proposed new fee", 3); + nodes[1].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Funding remote cannot afford proposed new fee", + 3, + ); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: String::from("Funding remote cannot afford proposed new fee") }, - [nodes[0].node.get_our_node_id()], 10_000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { + err: String::from("Funding remote cannot afford proposed new fee") + }, + [nodes[0].node.get_our_node_id()], + 10_000 + ); } #[xtest(feature = "_externalize_tests")] @@ -884,7 +1264,7 @@ pub fn test_update_fee_with_fundee_update_add_htlc() { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); // balancing - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 8000000); { let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap(); @@ -896,21 +1276,42 @@ pub fn test_update_fee_with_fundee_update_add_htlc() { let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_0.len(), 1); let (update_msg, commitment_signed) = match events_0[0] { - MessageSendEvent::UpdateHTLCs { node_id:_, channel_id: _, updates: msgs::CommitmentUpdate { update_add_htlcs:_, update_fulfill_htlcs:_, update_fail_htlcs:_, update_fail_malformed_htlcs:_, ref update_fee, ref commitment_signed } } => { - (update_fee.as_ref(), commitment_signed) - }, + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + update_add_htlcs: _, + update_fulfill_htlcs: _, + update_fail_htlcs: _, + update_fail_malformed_htlcs: _, + ref update_fee, + ref commitment_signed, + }, + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msg.unwrap()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); - let (revoke_msg, commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); + let (revoke_msg, commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); - let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 800000); + let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 800000); // nothing happens since node[1] is in AwaitingRemoteRevoke - nodes[1].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[1] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); { let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); assert_eq!(added_monitors.len(), 0); @@ -924,8 +1325,14 @@ pub fn test_update_fee_with_fundee_update_add_htlc() { assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); - let revoke_msg = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); + let revoke_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &revoke_msg); @@ -939,18 +1346,31 @@ pub fn test_update_fee_with_fundee_update_add_htlc() { assert_eq!(commitment_update.update_fail_malformed_htlcs.len(), 0); assert_eq!(commitment_update.update_fee.is_none(), true); - nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &commitment_update.update_add_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_update.commitment_signed); + nodes[0].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &commitment_update.update_add_htlcs[0], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &commitment_update.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let (revoke, commitment_signed) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (revoke, commitment_signed) = + get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &revoke); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commitment_signed); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commitment_signed); check_added_monitors!(nodes[1], 1); - let revoke = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let revoke = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &revoke); @@ -962,17 +1382,29 @@ pub fn test_update_fee_with_fundee_update_add_htlc() { let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentClaimable { .. } => { }, + Event::PaymentClaimable { .. } => {}, _ => panic!("Unexpected event"), }; - claim_payment(&nodes[1], &vec!(&nodes[0])[..], our_payment_preimage); + claim_payment(&nodes[1], &vec![&nodes[0]][..], our_payment_preimage); - send_payment(&nodes[1], &vec!(&nodes[0])[..], 800000); - send_payment(&nodes[0], &vec!(&nodes[1])[..], 800000); + send_payment(&nodes[1], &vec![&nodes[0]][..], 800000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 800000); close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -1011,16 +1443,29 @@ pub fn test_update_fee() { let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_0.len(), 1); let (update_msg, commitment_signed) = match events_0[0] { - MessageSendEvent::UpdateHTLCs { node_id:_, channel_id: _, updates: msgs::CommitmentUpdate { update_add_htlcs:_, update_fulfill_htlcs:_, update_fail_htlcs:_, update_fail_malformed_htlcs:_, ref update_fee, ref commitment_signed } } => { - (update_fee.as_ref(), commitment_signed) - }, + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + update_add_htlcs: _, + update_fulfill_htlcs: _, + update_fail_htlcs: _, + update_fail_malformed_htlcs: _, + ref update_fee, + ref commitment_signed, + }, + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msg.unwrap()); // Generate (2) and (3): - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); - let (revoke_msg, commitment_signed_0) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); + let (revoke_msg, commitment_signed_0) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); // Deliver (2): @@ -1038,23 +1483,45 @@ pub fn test_update_fee() { let events_0 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_0.len(), 1); let (update_msg, commitment_signed) = match events_0[0] { - MessageSendEvent::UpdateHTLCs { node_id:_, channel_id: _, updates: msgs::CommitmentUpdate { update_add_htlcs:_, update_fulfill_htlcs:_, update_fail_htlcs:_, update_fail_malformed_htlcs:_, ref update_fee, ref commitment_signed } } => { - (update_fee.as_ref(), commitment_signed) - }, + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + update_add_htlcs: _, + update_fulfill_htlcs: _, + update_fail_htlcs: _, + update_fail_malformed_htlcs: _, + ref update_fee, + ref commitment_signed, + }, + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_msg.unwrap()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); check_added_monitors!(nodes[1], 1); // ... creating (5) - let revoke_msg = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let revoke_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes // Handle (3), creating (6): - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed_0); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed_0); check_added_monitors!(nodes[0], 1); - let revoke_msg_0 = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let revoke_msg_0 = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes // Deliver (5): @@ -1073,9 +1540,16 @@ pub fn test_update_fee() { check_added_monitors!(nodes[1], 1); // Deliver (7) - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_update.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &commitment_update.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let revoke_msg = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let revoke_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &revoke_msg); @@ -1085,8 +1559,20 @@ pub fn test_update_fee() { assert_eq!(get_feerate!(nodes[0], nodes[1], channel_id), feerate + 30); assert_eq!(get_feerate!(nodes[1], nodes[0], channel_id), feerate + 30); close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -1104,30 +1590,31 @@ pub fn fake_network_test() { let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3); // Rebalance the network a bit by relaying one payment through all the channels... - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3]][..], 8000000); // Send some more payments - send_payment(&nodes[1], &vec!(&nodes[2], &nodes[3])[..], 1000000); - send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1], &nodes[0])[..], 1000000); - send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1])[..], 1000000); + send_payment(&nodes[1], &vec![&nodes[2], &nodes[3]][..], 1000000); + send_payment(&nodes[3], &vec![&nodes[2], &nodes[1], &nodes[0]][..], 1000000); + send_payment(&nodes[3], &vec![&nodes[2], &nodes[1]][..], 1000000); // Test failure packets - let payment_hash_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 1000000).1; - fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], payment_hash_1); + let payment_hash_1 = + route_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3]][..], 1000000).1; + fail_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3]][..], payment_hash_1); // Add a new channel that skips 3 let chan_4 = create_announced_chan_between_nodes(&nodes, 1, 3); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 1000000); - send_payment(&nodes[2], &vec!(&nodes[3])[..], 1000000); - send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000); - send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000); - send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000); - send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000); - send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[3]][..], 1000000); + send_payment(&nodes[2], &vec![&nodes[3]][..], 1000000); + send_payment(&nodes[1], &vec![&nodes[3]][..], 8000000); + send_payment(&nodes[1], &vec![&nodes[3]][..], 8000000); + send_payment(&nodes[1], &vec![&nodes[3]][..], 8000000); + send_payment(&nodes[1], &vec![&nodes[3]][..], 8000000); + send_payment(&nodes[1], &vec![&nodes[3]][..], 8000000); // Do some rebalance loop payments, simultaneously let mut hops = Vec::with_capacity(3); @@ -1158,15 +1645,25 @@ pub fn fake_network_test() { cltv_expiry_delta: TEST_FINAL_CLTV, maybe_announced_channel: true, }); - hops[1].fee_msat = chan_4.1.contents.fee_base_msat as u64 + chan_4.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000; - hops[0].fee_msat = chan_3.0.contents.fee_base_msat as u64 + chan_3.0.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000; - let payment_params = PaymentParameters::from_node_id( - nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV - ).with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + hops[1].fee_msat = chan_4.1.contents.fee_base_msat as u64 + + chan_4.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000; + hops[0].fee_msat = chan_3.0.contents.fee_base_msat as u64 + + chan_3.0.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000; + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1000000); - let payment_preimage_1 = send_along_route(&nodes[1], - Route { paths: vec![Path { hops, blinded_tail: None }], route_params: Some(route_params.clone()) }, - &vec!(&nodes[2], &nodes[3], &nodes[1])[..], 1000000).0; + let payment_preimage_1 = send_along_route( + &nodes[1], + Route { + paths: vec![Path { hops, blinded_tail: None }], + route_params: Some(route_params.clone()), + }, + &vec![&nodes[2], &nodes[3], &nodes[1]][..], + 1000000, + ) + .0; let mut hops = Vec::with_capacity(3); hops.push(RouteHop { @@ -1196,29 +1693,83 @@ pub fn fake_network_test() { cltv_expiry_delta: TEST_FINAL_CLTV, maybe_announced_channel: true, }); - hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000; - hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000; - let payment_hash_2 = send_along_route(&nodes[1], + hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000; + hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000; + let payment_hash_2 = send_along_route( + &nodes[1], Route { paths: vec![Path { hops, blinded_tail: None }], route_params: Some(route_params) }, - &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).1; + &vec![&nodes[3], &nodes[2], &nodes[1]][..], + 1000000, + ) + .1; // Claim the rebalances... - fail_payment(&nodes[1], &vec!(&nodes[3], &nodes[2], &nodes[1])[..], payment_hash_2); - claim_payment(&nodes[1], &vec!(&nodes[2], &nodes[3], &nodes[1])[..], payment_preimage_1); + fail_payment(&nodes[1], &vec![&nodes[3], &nodes[2], &nodes[1]][..], payment_hash_2); + claim_payment(&nodes[1], &vec![&nodes[2], &nodes[3], &nodes[1]][..], payment_preimage_1); // Close down the channels... close_channel(&nodes[0], &nodes[1], &chan_1.2, chan_1.3, true); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, false); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); close_channel(&nodes[2], &nodes[3], &chan_3.2, chan_3.3, true); - check_closed_event!(nodes[2], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[3].node.get_our_node_id()], 100000); - check_closed_event!(nodes[3], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[3].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[3], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[2].node.get_our_node_id()], + 100000 + ); close_channel(&nodes[1], &nodes[3], &chan_4.2, chan_4.3, false); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[3].node.get_our_node_id()], 100000); - check_closed_event!(nodes[3], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[3].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[3], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -1234,13 +1785,22 @@ pub fn holding_cell_htlc_counting() { let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); // Fetch a route in advance as we will be unable to once we're unable to send. - let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000); + let (route, payment_hash_1, _, payment_secret_1) = + get_route_and_payment_hash!(nodes[1], nodes[2], 100000); let mut payments = Vec::new(); for _ in 0..50 { - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000); - nodes[1].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[2], 100000); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); payments.push((payment_preimage, payment_hash)); } check_added_monitors!(nodes[1], 1); @@ -1254,17 +1814,34 @@ pub fn holding_cell_htlc_counting() { // the holding cell waiting on B's RAA to send. At this point we should not be able to add // another HTLC. { - unwrap_send_err!(nodes[1], nodes[1].node.send_payment_with_route(route, payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[1], + nodes[1].node.send_payment_with_route( + route, + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); } // This should also be true if we try to forward a payment. - let (route, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], 100000); + let (route, payment_hash_2, _, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[2], 100000); { - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); } @@ -1278,43 +1855,82 @@ pub fn holding_cell_htlc_counting() { // We have to forward pending HTLCs twice - once tries to forward the payment forward (and // fails), the second will process the resulting failure and fail the HTLC backward. expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); check_added_monitors!(nodes[1], 1); let bs_fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_fail_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &bs_fail_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], bs_fail_updates.commitment_signed, false, true); - expect_payment_failed_with_update!(nodes[0], payment_hash_2, false, chan_2.0.contents.short_channel_id, false); + expect_payment_failed_with_update!( + nodes[0], + payment_hash_2, + false, + chan_2.0.contents.short_channel_id, + false + ); // Now forward all the pending HTLCs and claim them back - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &initial_payment_event.msgs[0]); - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &initial_payment_event.commitment_msg); + nodes[2] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &initial_payment_event.msgs[0]); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &initial_payment_event.commitment_msg, + ); check_added_monitors!(nodes[2], 1); - let (bs_revoke_and_ack, bs_commitment_signed) = get_revoke_commit_msgs!(nodes[2], nodes[1].node.get_our_node_id()); + let (bs_revoke_and_ack, bs_commitment_signed) = + get_revoke_commit_msgs!(nodes[2], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[2].node.get_our_node_id(), &bs_revoke_and_ack); check_added_monitors!(nodes[1], 1); let as_updates = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &bs_commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &bs_commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let as_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[2].node.get_our_node_id() + ); for ref update in as_updates.update_add_htlcs.iter() { nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), update); } - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &as_updates.commitment_signed); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &as_updates.commitment_signed, + ); check_added_monitors!(nodes[2], 1); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[2], 1); - let (bs_revoke_and_ack, bs_commitment_signed) = get_revoke_commit_msgs!(nodes[2], nodes[1].node.get_our_node_id()); + let (bs_revoke_and_ack, bs_commitment_signed) = + get_revoke_commit_msgs!(nodes[2], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[2].node.get_our_node_id(), &bs_revoke_and_ack); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &bs_commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &bs_commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let as_final_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id()); + let as_final_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[2].node.get_our_node_id() + ); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &as_final_raa); check_added_monitors!(nodes[2], 1); @@ -1355,17 +1971,21 @@ pub fn duplicate_htlc_test() { create_announced_chan_between_nodes(&nodes, 3, 4); create_announced_chan_between_nodes(&nodes, 3, 5); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], 1000000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &vec![&nodes[3], &nodes[4]][..], 1000000); *nodes[0].network_payment_count.borrow_mut() -= 1; assert_eq!(route_payment(&nodes[1], &vec!(&nodes[3])[..], 1000000).0, payment_preimage); *nodes[0].network_payment_count.borrow_mut() -= 1; - assert_eq!(route_payment(&nodes[2], &vec!(&nodes[3], &nodes[5])[..], 1000000).0, payment_preimage); + assert_eq!( + route_payment(&nodes[2], &vec!(&nodes[3], &nodes[5])[..], 1000000).0, + payment_preimage + ); - claim_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], payment_preimage); - fail_payment(&nodes[2], &vec!(&nodes[3], &nodes[5])[..], payment_hash); - claim_payment(&nodes[1], &vec!(&nodes[3])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[3], &nodes[4]][..], payment_preimage); + fail_payment(&nodes[2], &vec![&nodes[3], &nodes[5]][..], payment_hash); + claim_payment(&nodes[1], &vec![&nodes[3]][..], payment_preimage); } #[xtest(feature = "_externalize_tests")] @@ -1385,13 +2005,22 @@ pub fn test_duplicate_htlc_different_direction_onchain() { let payment_value_msats = payment_value_sats * 1000; // balancing - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 8000000); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 900_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &vec![&nodes[1]][..], 900_000); let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], payment_value_msats); - let node_a_payment_secret = nodes[0].node.create_inbound_payment_for_hash(payment_hash, None, 7200, None).unwrap(); - send_along_route_with_secret(&nodes[1], route, &[&[&nodes[0]]], payment_value_msats, payment_hash, node_a_payment_secret); + let node_a_payment_secret = + nodes[0].node.create_inbound_payment_for_hash(payment_hash, None, 7200, None).unwrap(); + send_along_route_with_secret( + &nodes[1], + route, + &[&[&nodes[0]]], + payment_value_msats, + payment_hash, + node_a_payment_secret, + ); // Provide preimage to node 0 by claiming payment nodes[0].node.claim_funds(payment_preimage); @@ -1414,7 +2043,13 @@ pub fn test_duplicate_htlc_different_direction_onchain() { mine_transaction(&nodes[0], &remote_txn[0]); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[0], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires let claim_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); @@ -1424,31 +2059,59 @@ pub fn test_duplicate_htlc_different_direction_onchain() { check_spends!(claim_txn[1], remote_txn[0]); check_spends!(claim_txn[2], remote_txn[0]); let preimage_tx = &claim_txn[0]; - let timeout_tx = claim_txn.iter().skip(1).find(|t| t.input[0].previous_output != preimage_tx.input[0].previous_output).unwrap(); - let preimage_bump_tx = claim_txn.iter().skip(1).find(|t| t.input[0].previous_output == preimage_tx.input[0].previous_output).unwrap(); + let timeout_tx = claim_txn + .iter() + .skip(1) + .find(|t| t.input[0].previous_output != preimage_tx.input[0].previous_output) + .unwrap(); + let preimage_bump_tx = claim_txn + .iter() + .skip(1) + .find(|t| t.input[0].previous_output == preimage_tx.input[0].previous_output) + .unwrap(); assert_eq!(preimage_tx.input.len(), 1); assert_eq!(preimage_bump_tx.input.len(), 1); assert_eq!(preimage_tx.input.len(), 1); assert_eq!(preimage_tx.input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC 1 <--> 0, preimage tx - assert_eq!(remote_txn[0].output[preimage_tx.input[0].previous_output.vout as usize].value.to_sat(), payment_value_sats); + assert_eq!( + remote_txn[0].output[preimage_tx.input[0].previous_output.vout as usize].value.to_sat(), + payment_value_sats + ); assert_eq!(timeout_tx.input.len(), 1); assert_eq!(timeout_tx.input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); // HTLC 0 <--> 1, timeout tx check_spends!(timeout_tx, remote_txn[0]); - assert_eq!(remote_txn[0].output[timeout_tx.input[0].previous_output.vout as usize].value.to_sat(), 900); + assert_eq!( + remote_txn[0].output[timeout_tx.input[0].previous_output.vout as usize].value.to_sat(), + 900 + ); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 3); for e in events { match e { MessageSendEvent::BroadcastChannelUpdate { .. } => {}, - MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::DisconnectPeer { ref msg } } => { + MessageSendEvent::HandleError { + node_id, + action: msgs::ErrorAction::DisconnectPeer { ref msg }, + } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()); assert_eq!(msg.as_ref().unwrap().data, "Channel closed because commitment or closing transaction was confirmed on chain."); }, - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fail_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); @@ -1472,14 +2135,22 @@ pub fn test_basic_channel_reserve() { let channel_reserve = chan_stat.channel_reserve_msat; // The 2* and +1 are for the fee spike reserve. - let commit_tx_fee = 2 * commit_tx_fee_msat(get_feerate!(nodes[0], nodes[1], chan.2), 1 + 1, &get_channel_type_features!(nodes[0], nodes[1], chan.2)); + let commit_tx_fee = 2 * commit_tx_fee_msat( + get_feerate!(nodes[0], nodes[1], chan.2), + 1 + 1, + &get_channel_type_features!(nodes[0], nodes[1], chan.2), + ); let max_can_send = 5000000 - channel_reserve - commit_tx_fee; let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send); route.paths[0].hops.last_mut().unwrap().fee_msat += 1; - let err = nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)); - unwrap_send_err!(nodes[0], err, true, APIError::ChannelUnavailable { .. }, {} ); + let err = nodes[0].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ); + unwrap_send_err!(nodes[0], err, true, APIError::ChannelUnavailable { .. }, {}); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); send_payment(&nodes[0], &vec![&nodes[1]], max_can_send); @@ -1504,14 +2175,24 @@ pub fn test_fee_spike_violation_fails_htlc() { let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv); let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], - 3460001, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); - let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 3460001, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); + let onion_packet = + onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash) + .unwrap(); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, htlc_id: 0, amount_msat: htlc_msat, - payment_hash: payment_hash, + payment_hash, cltv_expiry: htlc_cltv, onion_routing_packet: onion_packet, skimmed_fee_msat: None, @@ -1530,21 +2211,32 @@ pub fn test_fee_spike_violation_fails_htlc() { let (local_secret, next_local_point) = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let chan_lock = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); let local_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); let chan_signer = local_chan.get_signer(); // Make the signer believe we validated another commitment, so we can release the secret chan_signer.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; - (chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(), - chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx).unwrap()) + ( + chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(), + chan_signer + .as_ref() + .get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx) + .unwrap(), + ) }; let remote_point = { let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); - let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); + let chan_lock = + per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); + let remote_chan = + chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); let chan_signer = remote_chan.get_signer(); - chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap() + chan_signer + .as_ref() + .get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx) + .unwrap() }; // Build the remote commitment transaction so we can sign it, and then later use the @@ -1563,8 +2255,10 @@ pub fn test_fee_spike_violation_fails_htlc() { let res = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); - let local_chan = local_chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); + let local_chan_lock = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let local_chan = + local_chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap(); let local_chan_signer = local_chan.get_signer(); let commitment_tx = CommitmentTransaction::new( commitment_number, @@ -1576,10 +2270,17 @@ pub fn test_fee_spike_violation_fails_htlc() { &local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(), &secp_ctx, ); - local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment( - &local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(), - Vec::new(), &secp_ctx, - ).unwrap() + local_chan_signer + .as_ecdsa() + .unwrap() + .sign_counterparty_commitment( + &local_chan.funding.channel_transaction_parameters, + &commitment_tx, + Vec::new(), + Vec::new(), + &secp_ctx, + ) + .unwrap() }; let commit_signed_msg = msgs::CommitmentSigned { @@ -1605,13 +2306,19 @@ pub fn test_fee_spike_violation_fails_htlc() { }; nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &raa_msg); expect_pending_htlcs_forwardable!(nodes[1]); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }] + ); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); // Make sure the HTLC failed in the way we expect. match events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fail_htlcs, .. }, .. } => { + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fail_htlcs, .. }, + .. + } => { assert_eq!(update_fail_htlcs.len(), 1); update_fail_htlcs[0].clone() }, @@ -1638,23 +2345,37 @@ pub fn test_chan_reserve_violation_outbound_htlc_inbound_chan() { let channel_type_features = ChannelTypeFeatures::only_static_remote_key(); let mut push_amt = 100_000_000; - push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, &channel_type_features); + push_amt -= commit_tx_fee_msat( + feerate_per_kw, + MIN_AFFORDABLE_HTLC_COUNT as u64, + &channel_type_features, + ); push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000; let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt); // Fetch a route in advance as we will be unable to once we're unable to send. - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 1_000_000); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 1_000_000); // Sending exactly enough to hit the reserve amount should be accepted for _ in 0..MIN_AFFORDABLE_HTLC_COUNT { route_payment(&nodes[1], &[&nodes[0]], 1_000_000); } // However one more HTLC should be significantly over the reserve amount and fail. - unwrap_send_err!(nodes[1], nodes[1].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[1], + nodes[1].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); } @@ -1672,7 +2393,11 @@ pub fn test_chan_reserve_violation_inbound_htlc_outbound_channel() { // channel reserve violation (so their balance is channel reserve (1000 sats) + commitment // transaction fee with 0 HTLCs (183 sats)). let mut push_amt = 100_000_000; - push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, &channel_type_features); + push_amt -= commit_tx_fee_msat( + feerate_per_kw, + MIN_AFFORDABLE_HTLC_COUNT as u64, + &channel_type_features, + ); push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000; let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt); @@ -1690,14 +2415,24 @@ pub fn test_chan_reserve_violation_inbound_htlc_outbound_channel() { let cur_height = nodes[1].node.best_block.read().unwrap().height + 1; let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv); let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], - 700_000, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); - let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 700_000, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); + let onion_packet = + onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash) + .unwrap(); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, htlc_id: MIN_AFFORDABLE_HTLC_COUNT as u64, amount_msat: htlc_msat, - payment_hash: payment_hash, + payment_hash, cltv_expiry: htlc_cltv, onion_routing_packet: onion_packet, skimmed_fee_msat: None, @@ -1732,12 +2467,17 @@ pub fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() { // channel reserve violation (so their balance is channel reserve (1000 sats) + commitment // transaction fee with 0 HTLCs (183 sats)). let mut push_amt = 100_000_000; - push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, &channel_type_features); + push_amt -= commit_tx_fee_msat( + feerate_per_kw, + MIN_AFFORDABLE_HTLC_COUNT as u64, + &channel_type_features, + ); push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000; create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, push_amt); let dust_amt = crate::ln::channel::MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000 - + feerate_per_kw as u64 * htlc_success_tx_weight(&channel_type_features) / 1000 * 1000 - 1; + + feerate_per_kw as u64 * htlc_success_tx_weight(&channel_type_features) / 1000 * 1000 + - 1; // In the previous code, routing this dust payment would cause nodes[0] to perceive a channel // reserve violation even though it's a dust HTLC and therefore shouldn't count towards the // commitment transaction fee. @@ -1752,9 +2492,18 @@ pub fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() { let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], dust_amt); route.paths[0].hops[0].fee_msat += 1; - unwrap_send_err!(nodes[1], nodes[1].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[1], + nodes[1].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); } #[xtest(feature = "_externalize_tests")] @@ -1772,22 +2521,36 @@ pub fn test_chan_init_feerate_unaffordability() { // Set the push_msat amount such that nodes[0] will not be able to afford to add even a single // HTLC. let mut push_amt = 100_000_000; - push_amt -= commit_tx_fee_msat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT as u64, &channel_type_features); + push_amt -= commit_tx_fee_msat( + feerate_per_kw, + MIN_AFFORDABLE_HTLC_COUNT as u64, + &channel_type_features, + ); assert_eq!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, push_amt + 1, 42, None, None).unwrap_err(), APIError::APIMisuseError { err: "Funding amount (356) can't even pay fee for initial commitment transaction fee of 357.".to_string() }); // During open, we don't have a "counterparty channel reserve" to check against, so that // requirement only comes into play on the open_channel handling side. push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, &default_config) * 1000; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, push_amt, 42, None, None).unwrap(); - let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, push_amt, 42, None, None) + .unwrap(); + let mut open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); open_channel_msg.push_msat += 1; nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); match msg_events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id: _, + } => { assert_eq!(msg.data, "Insufficient funding amount for initial reserve"); }, _ => panic!("Unexpected event"), @@ -1805,7 +2568,7 @@ pub fn test_chan_reserve_dust_inbound_htlcs_inbound_chan() { create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 98000000); let payment_amt = 46000; // Dust amount - // In the previous code, these first four payments would succeed. + // In the previous code, these first four payments would succeed. route_payment(&nodes[0], &[&nodes[1]], payment_amt); route_payment(&nodes[0], &[&nodes[1]], payment_amt); route_payment(&nodes[0], &[&nodes[1]], payment_amt); @@ -1840,15 +2603,27 @@ pub fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan.2); // Add a 2* and +1 for the fee spike reserve. - let commit_tx_fee_2_htlc = 2*commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features); - let recv_value_1 = (chan_stat.value_to_self_msat - chan_stat.channel_reserve_msat - total_routing_fee_msat - commit_tx_fee_2_htlc)/2; + let commit_tx_fee_2_htlc = 2 * commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features); + let recv_value_1 = (chan_stat.value_to_self_msat + - chan_stat.channel_reserve_msat + - total_routing_fee_msat + - commit_tx_fee_2_htlc) + / 2; let amt_msat_1 = recv_value_1 + total_routing_fee_msat; // Add a pending HTLC. - let (route_1, our_payment_hash_1, _, our_payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_1); + let (route_1, our_payment_hash_1, _, our_payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_1); let payment_event_1 = { - nodes[0].node.send_payment_with_route(route_1.clone(), our_payment_hash_1, - RecipientOnionFields::secret_only(our_payment_secret_1), PaymentId(our_payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route_1.clone(), + our_payment_hash_1, + RecipientOnionFields::secret_only(our_payment_secret_1), + PaymentId(our_payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1859,7 +2634,12 @@ pub fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { // Attempt to trigger a channel reserve violation --> payment failure. let commit_tx_fee_2_htlcs = commit_tx_fee_msat(feerate, 2, &channel_type_features); - let recv_value_2 = chan_stat.value_to_self_msat - amt_msat_1 - chan_stat.channel_reserve_msat - total_routing_fee_msat - commit_tx_fee_2_htlcs + 1; + let recv_value_2 = chan_stat.value_to_self_msat + - amt_msat_1 + - chan_stat.channel_reserve_msat + - total_routing_fee_msat + - commit_tx_fee_2_htlcs + + 1; let amt_msat_2 = recv_value_2 + total_routing_fee_msat; let mut route_2 = route_1.clone(); route_2.paths[0].hops.last_mut().unwrap().fee_msat = amt_msat_2; @@ -1871,8 +2651,22 @@ pub fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv); let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( - &route_2.paths[0], recv_value_2, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); - let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash_1).unwrap(); + &route_2.paths[0], + recv_value_2, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); + let onion_packet = onion_utils::construct_onion_packet( + onion_payloads, + onion_keys, + [0; 32], + &our_payment_hash_1, + ) + .unwrap(); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, htlc_id: 1, @@ -1886,13 +2680,24 @@ pub fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &msg); // Check that the payment failed and the channel is closed in response to the malicious UpdateAdd. - nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Remote HTLC add would put them under remote reserve value", 3); + nodes[1].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Remote HTLC add would put them under remote reserve value", + 3, + ); assert_eq!(nodes[1].node.list_channels().len(), 1); let err_msg = check_closed_broadcast!(nodes[1], true).unwrap(); assert_eq!(err_msg.data, "Remote HTLC add would put them under remote reserve value"); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "Remote HTLC add would put them under remote reserve value".to_string() }, - [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { + err: "Remote HTLC add would put them under remote reserve value".to_string() + }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -1909,15 +2714,19 @@ pub fn test_inbound_outbound_capacity_is_not_zero() { assert_eq!(channels1.len(), 1); let reserve = get_holder_selected_channel_reserve_satoshis(100_000, &default_config); - assert_eq!(channels0[0].inbound_capacity_msat, 95000000 - reserve*1000); - assert_eq!(channels1[0].outbound_capacity_msat, 95000000 - reserve*1000); + assert_eq!(channels0[0].inbound_capacity_msat, 95000000 - reserve * 1000); + assert_eq!(channels1[0].outbound_capacity_msat, 95000000 - reserve * 1000); - assert_eq!(channels0[0].outbound_capacity_msat, 100000 * 1000 - 95000000 - reserve*1000); - assert_eq!(channels1[0].inbound_capacity_msat, 100000 * 1000 - 95000000 - reserve*1000); + assert_eq!(channels0[0].outbound_capacity_msat, 100000 * 1000 - 95000000 - reserve * 1000); + assert_eq!(channels1[0].inbound_capacity_msat, 100000 * 1000 - 95000000 - reserve * 1000); } -fn commit_tx_fee_msat(feerate: u32, num_htlcs: u64, channel_type_features: &ChannelTypeFeatures) -> u64 { - (commitment_tx_base_weight(channel_type_features) + num_htlcs * COMMITMENT_TX_WEIGHT_PER_HTLC) * feerate as u64 / 1000 * 1000 +fn commit_tx_fee_msat( + feerate: u32, num_htlcs: u64, channel_type_features: &ChannelTypeFeatures, +) -> u64 { + (commitment_tx_base_weight(channel_type_features) + num_htlcs * COMMITMENT_TX_WEIGHT_PER_HTLC) + * feerate as u64 + / 1000 * 1000 } #[xtest(feature = "_externalize_tests")] @@ -1928,7 +2737,11 @@ pub fn test_channel_reserve_holding_cell_htlcs() { // It is now fixed, so we simply set the fee to the expected value here. let mut config = test_default_channel_config(); config.channel_config.forwarding_fee_base_msat = 239; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(config.clone()), Some(config.clone()), Some(config.clone())], + ); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 190000, 1001); let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 190000, 1001); @@ -1946,7 +2759,7 @@ pub fn test_channel_reserve_holding_cell_htlcs() { check_added_monitors!($node, 1); let payment_event = SendEvent::from_event(events.remove(0)); payment_event - }} + }}; } let feemsat = 239; // set above @@ -1958,15 +2771,28 @@ pub fn test_channel_reserve_holding_cell_htlcs() { // attempt to send amt_msat > their_max_htlc_value_in_flight_msat { - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap().with_max_channel_saturation_power_of_half(0); - let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, recv_value_0); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_max_channel_saturation_power_of_half(0); + let (mut route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, recv_value_0); route.paths[0].hops.last_mut().unwrap().fee_msat += 1; assert!(route.paths[0].hops.iter().rev().skip(1).all(|h| h.fee_msat == feemsat)); - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -1977,16 +2803,27 @@ pub fn test_channel_reserve_holding_cell_htlcs() { // 3 for the 3 HTLCs that will be sent, 2* and +1 for the fee spike reserve. // Also, ensure that each payment has enough to be over the dust limit to // ensure it'll be included in each commit tx fee calculation. - let commit_tx_fee_all_htlcs = 2*commit_tx_fee_msat(feerate, 3 + 1, &channel_type_features); - let ensure_htlc_amounts_above_dust_buffer = 3 * (stat01.counterparty_dust_limit_msat + 1000); - if stat01.value_to_self_msat < stat01.channel_reserve_msat + commit_tx_fee_all_htlcs + ensure_htlc_amounts_above_dust_buffer + amt_msat { + let commit_tx_fee_all_htlcs = + 2 * commit_tx_fee_msat(feerate, 3 + 1, &channel_type_features); + let ensure_htlc_amounts_above_dust_buffer = + 3 * (stat01.counterparty_dust_limit_msat + 1000); + if stat01.value_to_self_msat + < stat01.channel_reserve_msat + + commit_tx_fee_all_htlcs + + ensure_htlc_amounts_above_dust_buffer + + amt_msat + { break; } - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap().with_max_channel_saturation_power_of_half(0); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_max_channel_saturation_power_of_half(0); let route = get_route!(nodes[0], payment_params, recv_value_0).unwrap(); - let (payment_preimage, ..) = send_along_route(&nodes[0], route, &[&nodes[1], &nodes[2]], recv_value_0); + let (payment_preimage, ..) = + send_along_route(&nodes[0], route, &[&nodes[1], &nodes[2]], recv_value_0); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); let (stat01_, stat11_, stat12_, stat22_) = ( @@ -2000,7 +2837,10 @@ pub fn test_channel_reserve_holding_cell_htlcs() { assert_eq!(stat11_.value_to_self_msat, stat11.value_to_self_msat + amt_msat); assert_eq!(stat12_.value_to_self_msat, stat12.value_to_self_msat - (amt_msat - feemsat)); assert_eq!(stat22_.value_to_self_msat, stat22.value_to_self_msat + (amt_msat - feemsat)); - stat01 = stat01_; stat11 = stat11_; stat12 = stat12_; stat22 = stat22_; + stat01 = stat01_; + stat11 = stat11_; + stat12 = stat12_; + stat22 = stat22_; } // adding pending output. @@ -2014,14 +2854,26 @@ pub fn test_channel_reserve_holding_cell_htlcs() { // the amount of the first of these aforementioned 3 payments. The reason we split into 3 payments // is to test the behavior of the holding cell with respect to channel reserve and commit tx fee // policy. - let commit_tx_fee_2_htlcs = 2*commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features); - let recv_value_1 = (stat01.value_to_self_msat - stat01.channel_reserve_msat - total_fee_msat - commit_tx_fee_2_htlcs)/2; + let commit_tx_fee_2_htlcs = 2 * commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features); + let recv_value_1 = (stat01.value_to_self_msat + - stat01.channel_reserve_msat + - total_fee_msat + - commit_tx_fee_2_htlcs) + / 2; let amt_msat_1 = recv_value_1 + total_fee_msat; - let (route_1, our_payment_hash_1, our_payment_preimage_1, our_payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_1); + let (route_1, our_payment_hash_1, our_payment_preimage_1, our_payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_1); let payment_event_1 = { - nodes[0].node.send_payment_with_route(route_1.clone(), our_payment_hash_1, - RecipientOnionFields::secret_only(our_payment_secret_1), PaymentId(our_payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route_1.clone(), + our_payment_hash_1, + RecipientOnionFields::secret_only(our_payment_secret_1), + PaymentId(our_payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -2031,32 +2883,60 @@ pub fn test_channel_reserve_holding_cell_htlcs() { nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event_1.msgs[0]); // channel reserve test with htlc pending output > 0 - let recv_value_2 = stat01.value_to_self_msat - amt_msat_1 - stat01.channel_reserve_msat - total_fee_msat - commit_tx_fee_2_htlcs; + let recv_value_2 = stat01.value_to_self_msat + - amt_msat_1 + - stat01.channel_reserve_msat + - total_fee_msat + - commit_tx_fee_2_htlcs; { let mut route = route_1.clone(); route.paths[0].hops.last_mut().unwrap().fee_msat = recv_value_2 + 1; let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(nodes[2]); - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } // split the rest to test holding cell - let commit_tx_fee_3_htlcs = 2*commit_tx_fee_msat(feerate, 3 + 1, &channel_type_features); + let commit_tx_fee_3_htlcs = 2 * commit_tx_fee_msat(feerate, 3 + 1, &channel_type_features); let additional_htlc_cost_msat = commit_tx_fee_3_htlcs - commit_tx_fee_2_htlcs; - let recv_value_21 = recv_value_2/2 - additional_htlc_cost_msat/2; + let recv_value_21 = recv_value_2 / 2 - additional_htlc_cost_msat / 2; let recv_value_22 = recv_value_2 - recv_value_21 - total_fee_msat - additional_htlc_cost_msat; { let stat = get_channel_value_stat!(nodes[0], nodes[1], chan_1.2); - assert_eq!(stat.value_to_self_msat - (stat.pending_outbound_htlcs_amount_msat + recv_value_21 + recv_value_22 + total_fee_msat + total_fee_msat + commit_tx_fee_3_htlcs), stat.channel_reserve_msat); + assert_eq!( + stat.value_to_self_msat + - (stat.pending_outbound_htlcs_amount_msat + + recv_value_21 + recv_value_22 + + total_fee_msat + total_fee_msat + + commit_tx_fee_3_htlcs), + stat.channel_reserve_msat + ); } // now see if they go through on both sides - let (route_21, our_payment_hash_21, our_payment_preimage_21, our_payment_secret_21) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_21); + let (route_21, our_payment_hash_21, our_payment_preimage_21, our_payment_secret_21) = + get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_21); // but this will stuck in the holding cell - nodes[0].node.send_payment_with_route(route_21, our_payment_hash_21, - RecipientOnionFields::secret_only(our_payment_secret_21), PaymentId(our_payment_hash_21.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route_21, + our_payment_hash_21, + RecipientOnionFields::secret_only(our_payment_secret_21), + PaymentId(our_payment_hash_21.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 0); @@ -2066,23 +2946,44 @@ pub fn test_channel_reserve_holding_cell_htlcs() { let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22); route.paths[0].hops.last_mut().unwrap().fee_msat += 1; - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } - let (route_22, our_payment_hash_22, our_payment_preimage_22, our_payment_secret_22) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22); + let (route_22, our_payment_hash_22, our_payment_preimage_22, our_payment_secret_22) = + get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22); // this will also stuck in the holding cell - nodes[0].node.send_payment_with_route(route_22, our_payment_hash_22, - RecipientOnionFields::secret_only(our_payment_secret_22), PaymentId(our_payment_hash_22.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route_22, + our_payment_hash_22, + RecipientOnionFields::secret_only(our_payment_secret_22), + PaymentId(our_payment_hash_22.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); // flush the pending htlc - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &payment_event_1.commitment_msg); - let (as_revoke_and_ack, as_commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event_1.commitment_msg, + ); + let (as_revoke_and_ack, as_commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); // the pending htlc should be promoted to committed @@ -2090,8 +2991,15 @@ pub fn test_channel_reserve_holding_cell_htlcs() { check_added_monitors!(nodes[0], 1); let commitment_update_2 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &as_commitment_signed); - let bs_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &as_commitment_signed, + ); + let bs_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); @@ -2102,7 +3010,9 @@ pub fn test_channel_reserve_holding_cell_htlcs() { expect_pending_htlcs_forwardable!(nodes[1]); let ref payment_event_11 = expect_forward!(nodes[1]); - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event_11.msgs[0]); + nodes[2] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event_11.msgs[0]); commitment_signed_dance!(nodes[2], nodes[1], payment_event_11.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[2]); @@ -2110,8 +3020,14 @@ pub fn test_channel_reserve_holding_cell_htlcs() { // flush the htlcs in the holding cell assert_eq!(commitment_update_2.update_add_htlcs.len(), 2); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &commitment_update_2.update_add_htlcs[0]); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &commitment_update_2.update_add_htlcs[1]); + nodes[1].node.handle_update_add_htlc( + nodes[0].node.get_our_node_id(), + &commitment_update_2.update_add_htlcs[0], + ); + nodes[1].node.handle_update_add_htlc( + nodes[0].node.get_our_node_id(), + &commitment_update_2.update_add_htlcs[1], + ); commitment_signed_dance!(nodes[1], nodes[0], &commitment_update_2.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); @@ -2126,54 +3042,79 @@ pub fn test_channel_reserve_holding_cell_htlcs() { let events = nodes[2].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + .. + } => { assert_eq!(our_payment_hash_21, *payment_hash); assert_eq!(recv_value_21, amount_msat); assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap()); assert_eq!(via_channel_id, Some(chan_2.2)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(our_payment_secret_21, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), } match events[1] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + .. + } => { assert_eq!(our_payment_hash_22, *payment_hash); assert_eq!(recv_value_22, amount_msat); assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap()); assert_eq!(via_channel_id, Some(chan_2.2)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(our_payment_secret_22, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), } - claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_1); - claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_21); - claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), our_payment_preimage_22); + claim_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], our_payment_preimage_1); + claim_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], our_payment_preimage_21); + claim_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], our_payment_preimage_22); - let commit_tx_fee_0_htlcs = 2*commit_tx_fee_msat(feerate, 1, &channel_type_features); + let commit_tx_fee_0_htlcs = 2 * commit_tx_fee_msat(feerate, 1, &channel_type_features); let recv_value_3 = commit_tx_fee_2_htlcs - commit_tx_fee_0_htlcs - total_fee_msat; send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], recv_value_3); - let commit_tx_fee_1_htlc = 2*commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features); - let expected_value_to_self = stat01.value_to_self_msat - (recv_value_1 + total_fee_msat) - (recv_value_21 + total_fee_msat) - (recv_value_22 + total_fee_msat) - (recv_value_3 + total_fee_msat); + let commit_tx_fee_1_htlc = 2 * commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features); + let expected_value_to_self = stat01.value_to_self_msat + - (recv_value_1 + total_fee_msat) + - (recv_value_21 + total_fee_msat) + - (recv_value_22 + total_fee_msat) + - (recv_value_3 + total_fee_msat); let stat0 = get_channel_value_stat!(nodes[0], nodes[1], chan_1.2); assert_eq!(stat0.value_to_self_msat, expected_value_to_self); assert_eq!(stat0.value_to_self_msat, stat0.channel_reserve_msat + commit_tx_fee_1_htlc); let stat2 = get_channel_value_stat!(nodes[2], nodes[1], chan_2.2); - assert_eq!(stat2.value_to_self_msat, stat22.value_to_self_msat + recv_value_1 + recv_value_21 + recv_value_22 + recv_value_3); + assert_eq!( + stat2.value_to_self_msat, + stat22.value_to_self_msat + recv_value_1 + recv_value_21 + recv_value_22 + recv_value_3 + ); } #[xtest(feature = "_externalize_tests")] @@ -2208,15 +3149,25 @@ pub fn channel_reserve_in_flight_removes() { let b_chan_values = get_channel_value_stat!(nodes[1], nodes[0], chan_1.2); // Route the first two HTLCs. - let payment_value_1 = b_chan_values.channel_reserve_msat - b_chan_values.value_to_self_msat - 10000; - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], payment_value_1); + let payment_value_1 = + b_chan_values.channel_reserve_msat - b_chan_values.value_to_self_msat - 10000; + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], payment_value_1); let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1]], 20_000); // Start routing the third HTLC (this is just used to get everyone in the right state). - let (route, payment_hash_3, payment_preimage_3, payment_secret_3) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000); + let (route, payment_hash_3, payment_preimage_3, payment_secret_3) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100000); let send_1 = { - nodes[0].node.send_payment_with_route(route, payment_hash_3, - RecipientOnionFields::secret_only(payment_secret_3), PaymentId(payment_hash_3.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_3, + RecipientOnionFields::secret_only(payment_secret_3), + PaymentId(payment_hash_3.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); @@ -2237,17 +3188,34 @@ pub fn channel_reserve_in_flight_removes() { check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_removes.update_fulfill_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_removes.commitment_signed); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_removes.update_fulfill_htlcs[0], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_removes.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); expect_payment_sent(&nodes[0], payment_preimage_1, None, false, false); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_1.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &send_1.commitment_msg); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &send_1.commitment_msg, + ); check_added_monitors!(nodes[1], 1); // B is already AwaitingRAA, so cant generate a CS here - let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[1], 1); @@ -2257,19 +3225,36 @@ pub fn channel_reserve_in_flight_removes() { check_added_monitors!(nodes[0], 1); let as_cs = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_cs.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_cs.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // The second HTLCis removed, but as A is in AwaitingRAA it can't generate a CS here, so the // RAA that B generated above doesn't fully resolve the second HTLC from A's point of view. // However, the RAA A generates here *does* fully resolve the HTLC from B's point of view (as A // can no longer broadcast a commitment transaction with it and B has the preimage so can go // on-chain as necessary). - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_cs.update_fulfill_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_cs.commitment_signed); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_cs.update_fulfill_htlcs[0], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_cs.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); expect_payment_sent(&nodes[0], payment_preimage_2, None, false, false); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); @@ -2288,10 +3273,18 @@ pub fn channel_reserve_in_flight_removes() { // Now that B doesn't have the second RAA anymore, but A still does, send a payment from B back // to A to ensure that A doesn't count the almost-removed HTLC in update_add processing. - let (route, payment_hash_4, payment_preimage_4, payment_secret_4) = get_route_and_payment_hash!(nodes[1], nodes[0], 10000); + let (route, payment_hash_4, payment_preimage_4, payment_secret_4) = + get_route_and_payment_hash!(nodes[1], nodes[0], 10000); let send_2 = { - nodes[1].node.send_payment_with_route(route, payment_hash_4, - RecipientOnionFields::secret_only(payment_secret_4), PaymentId(payment_hash_4.0)).unwrap(); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash_4, + RecipientOnionFields::secret_only(payment_secret_4), + PaymentId(payment_hash_4.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); let mut events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -2299,15 +3292,29 @@ pub fn channel_reserve_in_flight_removes() { }; nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &send_2.msgs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &send_2.commitment_msg); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &send_2.commitment_msg, + ); check_added_monitors!(nodes[0], 1); - let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // Now just resolve all the outstanding messages/HTLCs for completeness... - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_cs.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_cs.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[1], 1); @@ -2317,9 +3324,16 @@ pub fn channel_reserve_in_flight_removes() { expect_payment_path_successful!(nodes[0]); let as_cs = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_cs.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_cs.commitment_signed, + ); check_added_monitors!(nodes[1], 1); - let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_raa); check_added_monitors!(nodes[0], 1); @@ -2364,11 +3378,12 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); // Start every node on the same block height to make reasoning about timeouts easier - connect_blocks(&nodes[0], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[0], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); // Force close the B<->C channel by timing out the HTLC let timeout_blocks = TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1; @@ -2389,19 +3404,25 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac connect_blocks(&nodes[0], timeout_blocks + upstream_timeout_blocks); // Check that nodes[1] fails the HTLC upstream - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 - }]); + }] + ); check_added_monitors!(nodes[1], 1); let htlc_updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); let msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. } = htlc_updates; nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().blamed_chan_closed(true)); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().blamed_chan_closed(true), + ); // Make sure we handle possible duplicate fails or extra messages after failing back match post_fail_back_action { @@ -2411,11 +3432,13 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac mine_transaction(&nodes[1], &node_1_txn[1]); // HTLC timeout connect_blocks(&nodes[1], ANTI_REORG_DELAY); // Expect handling another fail back event, but the HTLC is already gone - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 - }]); + }] + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); }, PostFailBackAction::ClaimOnChain => { @@ -2427,7 +3450,14 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac connect_blocks(&nodes[2], TEST_FINAL_CLTV - CLTV_CLAIM_BUFFER + 2); let node_2_txn = test_txn_broadcast(&nodes[2], &chan_2, None, HTLCType::SUCCESS); check_closed_broadcast!(nodes[2], true); - check_closed_event(&nodes[2], 1, ClosureReason::HTLCsTimedOut, false, &[node_b_id], 100_000); + check_closed_event( + &nodes[2], + 1, + ClosureReason::HTLCsTimedOut, + false, + &[node_b_id], + 100_000, + ); check_added_monitors!(nodes[2], 1); mine_transaction(&nodes[1], &node_2_txn[0]); // Commitment @@ -2437,10 +3467,13 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac }, PostFailBackAction::FailOffChain => { nodes[2].node.fail_htlc_backwards(&payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], - vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[2], 1); - let commitment_update = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id()); + let commitment_update = + get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id()); let update_fail = commitment_update.update_fail_htlcs[0].clone(); nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &update_fail); @@ -2452,10 +3485,13 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac nodes[2].node.claim_funds(payment_preimage); expect_payment_claimed!(nodes[2], payment_hash, 3_000_000); check_added_monitors!(nodes[2], 1); - let commitment_update = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id()); + let commitment_update = + get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id()); let update_fulfill = commitment_update.update_fulfill_htlcs[0].clone(); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &update_fulfill); + nodes[1] + .node + .handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &update_fulfill); let err_msg = get_err_msg(&nodes[1], &nodes[2].node.get_our_node_id()); assert_eq!(err_msg.channel_id, chan_2.2); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); @@ -2479,24 +3515,37 @@ pub fn channel_monitor_network_test() { let chan_4 = create_announced_chan_between_nodes(&nodes, 3, 4); // Make sure all nodes are at the same starting height - connect_blocks(&nodes[0], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); - connect_blocks(&nodes[3], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); - connect_blocks(&nodes[4], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[4].best_block_info().1); + connect_blocks(&nodes[0], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[3], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1); + connect_blocks(&nodes[4], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[4].best_block_info().1); // Rebalance the network a bit by relaying one payment through all the channels... - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3], &nodes[4]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3], &nodes[4]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3], &nodes[4]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2], &nodes[3], &nodes[4]][..], 8000000); // Simple case with no pending HTLCs: let error_message = "Channel force-closed"; - nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_1.2, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[0].node.get_our_node_id()], + 100000 + ); { let mut node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE); assert_eq!(node_txn.len(), 1); @@ -2512,20 +3561,37 @@ pub fn channel_monitor_network_test() { check_closed_broadcast!(nodes[0], true); assert_eq!(nodes[0].node.list_channels().len(), 0); assert_eq!(nodes[1].node.list_channels().len(), 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); // One pending HTLC is discarded by the force-close: - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[1], &[&nodes[2], &nodes[3]], 3_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[1], &[&nodes[2], &nodes[3]], 3_000_000); // Simple case of one pending HTLC to HTLC-Timeout (note that the HTLC-Timeout is not // broadcasted until we reach the timelock time). let error_message = "Channel force-closed"; - nodes[1].node.force_close_broadcasting_latest_txn(&chan_2.2, &nodes[2].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_2.2, + &nodes[2].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); { let mut node_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::NONE); - connect_blocks(&nodes[1], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + MIN_CLTV_EXPIRY_DELTA as u32 + 1); + connect_blocks( + &nodes[1], + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + MIN_CLTV_EXPIRY_DELTA as u32 + 1, + ); test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT); mine_transaction(&nodes[2], &node_txn[0]); check_added_monitors!(nodes[2], 1); @@ -2534,34 +3600,56 @@ pub fn channel_monitor_network_test() { check_closed_broadcast!(nodes[2], true); assert_eq!(nodes[1].node.list_channels().len(), 0); assert_eq!(nodes[2].node.list_channels().len(), 1); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); macro_rules! claim_funds { - ($node: expr, $prev_node: expr, $preimage: expr, $payment_hash: expr) => { - { - $node.node.claim_funds($preimage); - expect_payment_claimed!($node, $payment_hash, 3_000_000); - check_added_monitors!($node, 1); - - let events = $node.node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, .. } } => { - assert!(update_add_htlcs.is_empty()); - assert!(update_fail_htlcs.is_empty()); - assert_eq!(*node_id, $prev_node.node.get_our_node_id()); - }, - _ => panic!("Unexpected event"), - }; - } - } + ($node: expr, $prev_node: expr, $preimage: expr, $payment_hash: expr) => {{ + $node.node.claim_funds($preimage); + expect_payment_claimed!($node, $payment_hash, 3_000_000); + check_added_monitors!($node, 1); + + let events = $node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, .. }, + } => { + assert!(update_add_htlcs.is_empty()); + assert!(update_fail_htlcs.is_empty()); + assert_eq!(*node_id, $prev_node.node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + }; + }}; } // nodes[3] gets the preimage, but nodes[2] already disconnected, resulting in a nodes[2] // HTLC-Timeout and a nodes[3] claim against it (+ its own announces) let error_message = "Channel force-closed"; - nodes[2].node.force_close_broadcasting_latest_txn(&chan_3.2, &nodes[3].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[2] + .node + .force_close_broadcasting_latest_txn( + &chan_3.2, + &nodes[3].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors!(nodes[2], 1); check_closed_broadcast!(nodes[2], true); let node2_commitment_txid; @@ -2580,15 +3668,28 @@ pub fn channel_monitor_network_test() { check_closed_broadcast!(nodes[3], true); assert_eq!(nodes[2].node.list_channels().len(), 0); assert_eq!(nodes[3].node.list_channels().len(), 1); - check_closed_event!(nodes[2], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[3].node.get_our_node_id()], 100000); - check_closed_event!(nodes[3], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[3].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[3], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[2].node.get_our_node_id()], + 100000 + ); // Drop the ChannelMonitor for the previous channel to avoid it broadcasting transactions and // confusing us in the following tests. let chan_3_mon = nodes[3].chain_monitor.chain_monitor.remove_monitor(&chan_3.2); // One pending HTLC to time out: - let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[3], &[&nodes[4]], 3_000_000); + let (payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[3], &[&nodes[4]], 3_000_000); // CLTV expires at TEST_FINAL_CLTV + 1 (current height) + 1 (added in send_payment for // buffer space). @@ -2597,13 +3698,14 @@ pub fn channel_monitor_network_test() { let events = nodes[3].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); let close_chan_update_1 = match events[1] { - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - msg.clone() - }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => msg.clone(), _ => panic!("Unexpected event"), }; match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::DisconnectPeer { .. }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::DisconnectPeer { .. }, + node_id, + } => { assert_eq!(node_id, nodes[4].node.get_our_node_id()); }, _ => panic!("Unexpected event"), @@ -2616,7 +3718,9 @@ pub fn channel_monitor_network_test() { node_txn.retain(|tx| { if tx.input[0].previous_output.txid == node2_commitment_txid { false - } else { true } + } else { + true + } }); } @@ -2629,20 +3733,27 @@ pub fn channel_monitor_network_test() { let events = nodes[4].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); let close_chan_update_2 = match events[1] { - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - msg.clone() - }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => msg.clone(), _ => panic!("Unexpected event"), }; match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::DisconnectPeer { .. }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::DisconnectPeer { .. }, + node_id, + } => { assert_eq!(node_id, nodes[3].node.get_our_node_id()); }, _ => panic!("Unexpected event"), } check_added_monitors!(nodes[4], 1); test_txn_broadcast(&nodes[4], &chan_4, None, HTLCType::SUCCESS); - check_closed_event!(nodes[4], 1, ClosureReason::HTLCsTimedOut, [nodes[3].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[4], + 1, + ClosureReason::HTLCsTimedOut, + [nodes[3].node.get_our_node_id()], + 100000 + ); mine_transaction(&nodes[4], &node_txn[0]); check_preimage_claim(&nodes[4], &node_txn); @@ -2655,8 +3766,10 @@ pub fn channel_monitor_network_test() { assert_eq!(nodes[3].node.list_channels().len(), 0); assert_eq!(nodes[4].node.list_channels().len(), 0); - assert_eq!(nodes[3].chain_monitor.chain_monitor.watch_channel(chan_3.2, chan_3_mon), - Ok(ChannelMonitorUpdateStatus::Completed)); + assert_eq!( + nodes[3].chain_monitor.chain_monitor.watch_channel(chan_3.2, chan_3_mon), + Ok(ChannelMonitorUpdateStatus::Completed) + ); check_closed_event!(nodes[3], 1, ClosureReason::HTLCsTimedOut, [node_id_4], 100000); } @@ -2682,7 +3795,7 @@ pub fn test_justice_tx_htlc_timeout() { let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1); // A pending HTLC which will be revoked: - let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let payment_preimage_3 = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; // Get the will-be-revoked local txn from nodes[0] let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_5.2); assert_eq!(revoked_local_txn.len(), 2); // First commitment tx, then HTLC tx @@ -2690,10 +3803,16 @@ pub fn test_justice_tx_htlc_timeout() { assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.compute_txid()); assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to 0 are present assert_eq!(revoked_local_txn[1].input.len(), 1); - assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].compute_txid()); - assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC-Timeout - // Revoke the old state - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3); + assert_eq!( + revoked_local_txn[1].input[0].previous_output.txid, + revoked_local_txn[0].compute_txid() + ); + assert_eq!( + revoked_local_txn[1].input[0].witness.last().unwrap().len(), + OFFERED_HTLC_SCRIPT_WEIGHT + ); // HTLC-Timeout + // Revoke the old state + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage_3); { mine_transaction(&nodes[1], &revoked_local_txn[0]); @@ -2708,18 +3827,39 @@ pub fn test_justice_tx_htlc_timeout() { node_txn.clear(); } check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); test_txn_broadcast(&nodes[1], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::NONE); mine_transaction(&nodes[0], &revoked_local_txn[0]); connect_blocks(&nodes[0], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires - // Verify broadcast of revoked HTLC-timeout - let node_txn = test_txn_broadcast(&nodes[0], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT); + // Verify broadcast of revoked HTLC-timeout + let node_txn = test_txn_broadcast( + &nodes[0], + &chan_5, + Some(revoked_local_txn[0].clone()), + HTLCType::TIMEOUT, + ); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); // Broadcast revoked HTLC-timeout on node 1 mine_transaction(&nodes[1], &node_txn[1]); - test_revoked_htlc_claim_txn_broadcast(&nodes[1], node_txn[1].clone(), revoked_local_txn[0].clone()); + test_revoked_htlc_claim_txn_broadcast( + &nodes[1], + node_txn[1].clone(), + revoked_local_txn[0].clone(), + ); } get_announce_close_broadcast_events(&nodes, 0, 1); assert_eq!(nodes[0].node.list_channels().len(), 0); @@ -2748,15 +3888,15 @@ pub fn test_justice_tx_htlc_success() { let chan_6 = create_announced_chan_between_nodes(&nodes, 0, 1); // A pending HTLC which will be revoked: - let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let payment_preimage_4 = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; // Get the will-be-revoked local txn from B let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan_6.2); assert_eq!(revoked_local_txn.len(), 1); // Only commitment tx assert_eq!(revoked_local_txn[0].input.len(), 1); assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_6.3.compute_txid()); assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to A are present - // Revoke the old state - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_4); + // Revoke the old state + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage_4); { mine_transaction(&nodes[0], &revoked_local_txn[0]); { @@ -2771,12 +3911,33 @@ pub fn test_justice_tx_htlc_success() { test_txn_broadcast(&nodes[0], &chan_6, Some(revoked_local_txn[0].clone()), HTLCType::NONE); mine_transaction(&nodes[1], &revoked_local_txn[0]); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); - let node_txn = test_txn_broadcast(&nodes[1], &chan_6, Some(revoked_local_txn[0].clone()), HTLCType::SUCCESS); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); + let node_txn = test_txn_broadcast( + &nodes[1], + &chan_6, + Some(revoked_local_txn[0].clone()), + HTLCType::SUCCESS, + ); check_added_monitors!(nodes[1], 1); mine_transaction(&nodes[0], &node_txn[1]); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); - test_revoked_htlc_claim_txn_broadcast(&nodes[0], node_txn[1].clone(), revoked_local_txn[0].clone()); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); + test_revoked_htlc_claim_txn_broadcast( + &nodes[0], + node_txn[1].clone(), + revoked_local_txn[0].clone(), + ); } get_announce_close_broadcast_events(&nodes, 0, 1); assert_eq!(nodes[0].node.list_channels().len(), 0); @@ -2798,12 +3959,18 @@ pub fn revoked_output_claim() { // Only output is the full channel value back to nodes[0]: assert_eq!(revoked_local_txn[0].output.len(), 1); // Send a payment through, updating everyone's latest commitment txn - send_payment(&nodes[0], &vec!(&nodes[1])[..], 5000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 5000000); // Inform nodes[1] that nodes[0] broadcast a stale tx mine_transaction(&nodes[1], &revoked_local_txn[0]); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert_eq!(node_txn.len(), 1); // ChannelMonitor: justice tx against revoked to_local output @@ -2813,7 +3980,13 @@ pub fn revoked_output_claim() { mine_transaction(&nodes[0], &revoked_local_txn[0]); get_announce_close_broadcast_events(&nodes, 0, 1); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -2830,8 +4003,10 @@ fn do_test_forming_justice_tx_from_monitor_updates(broadcast_initial_commitment: let chanmon_cfgs = create_chanmon_cfgs(2); let destination_script0 = chanmon_cfgs[0].keys_manager.get_destination_script([0; 32]).unwrap(); let destination_script1 = chanmon_cfgs[1].keys_manager.get_destination_script([0; 32]).unwrap(); - let persisters = vec![WatchtowerPersister::new(destination_script0), - WatchtowerPersister::new(destination_script1)]; + let persisters = vec![ + WatchtowerPersister::new(destination_script0), + WatchtowerPersister::new(destination_script1), + ]; let node_cfgs = create_node_cfgs_with_persisters(2, &chanmon_cfgs, persisters.iter().collect()); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); @@ -2839,7 +4014,7 @@ fn do_test_forming_justice_tx_from_monitor_updates(broadcast_initial_commitment: if !broadcast_initial_commitment { // Send a payment to move the channel forward - send_payment(&nodes[0], &vec!(&nodes[1])[..], 5_000_000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 5_000_000); } // node[0] is gonna to revoke an old state thus node[1] should be able to claim the revoked output. @@ -2849,38 +4024,55 @@ fn do_test_forming_justice_tx_from_monitor_updates(broadcast_initial_commitment: let revoked_commitment_tx = &revoked_local_txn[0]; // Send another payment, now revoking the previous commitment tx - send_payment(&nodes[0], &vec!(&nodes[1])[..], 5_000_000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 5_000_000); - let justice_tx = persisters[1].justice_tx(channel_id, &revoked_commitment_tx.compute_txid()).unwrap(); + let justice_tx = + persisters[1].justice_tx(channel_id, &revoked_commitment_tx.compute_txid()).unwrap(); check_spends!(justice_tx, revoked_commitment_tx); mine_transactions(&nodes[1], &[revoked_commitment_tx, &justice_tx]); mine_transactions(&nodes[0], &[revoked_commitment_tx, &justice_tx]); check_added_monitors!(nodes[1], 1); - check_closed_event(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false, - &[nodes[0].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + &[nodes[0].node.get_our_node_id()], + 100_000, + ); get_announce_close_broadcast_events(&nodes, 1, 0); check_added_monitors!(nodes[0], 1); - check_closed_event(&nodes[0], 1, ClosureReason::CommitmentTxConfirmed, false, - &[nodes[1].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + &[nodes[1].node.get_our_node_id()], + 100_000, + ); // Check that the justice tx has sent the revoked output value to nodes[1] let monitor = get_monitor!(nodes[1], channel_id); - let total_claimable_balance = monitor.get_claimable_balances().iter().fold(0, |sum, balance| { - match balance { - channelmonitor::Balance::ClaimableAwaitingConfirmations { amount_satoshis, .. } => sum + amount_satoshis, + let total_claimable_balance = + monitor.get_claimable_balances().iter().fold(0, |sum, balance| match balance { + channelmonitor::Balance::ClaimableAwaitingConfirmations { amount_satoshis, .. } => { + sum + amount_satoshis + }, _ => panic!("Unexpected balance type"), - } - }); + }); // On the first commitment, node[1]'s balance was below dust so it didn't have an output - let node1_channel_balance = if broadcast_initial_commitment { 0 } else { revoked_commitment_tx.output[0].value.to_sat() }; + let node1_channel_balance = if broadcast_initial_commitment { + 0 + } else { + revoked_commitment_tx.output[0].value.to_sat() + }; let expected_claimable_balance = node1_channel_balance + justice_tx.output[0].value.to_sat(); assert_eq!(total_claimable_balance, expected_claimable_balance); } - #[xtest(feature = "_externalize_tests")] pub fn claim_htlc_outputs() { // Node revoked old state, htlcs haven't time out yet, claim them in shared justice tx @@ -2897,7 +4089,8 @@ pub fn claim_htlc_outputs() { send_payment(&nodes[0], &[&nodes[1]], 8_000_000); // node[0] is gonna to revoke an old state thus node[1] should be able to claim both offered/received HTLC outputs on top of commitment tx let payment_preimage_1 = route_payment(&nodes[0], &[&nodes[1]], 3_000_000).0; - let (_payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[1], &[&nodes[0]], 3_000_000); + let (_payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[1], &[&nodes[0]], 3_000_000); // Get the will-be-revoked local txn from node[0] let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2); @@ -2905,20 +4098,38 @@ pub fn claim_htlc_outputs() { assert_eq!(revoked_local_txn[0].input.len(), 1); assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.compute_txid()); assert_eq!(revoked_local_txn[1].input.len(), 1); - assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].compute_txid()); - assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC-Timeout + assert_eq!( + revoked_local_txn[1].input[0].previous_output.txid, + revoked_local_txn[0].compute_txid() + ); + assert_eq!( + revoked_local_txn[1].input[0].witness.last().unwrap().len(), + OFFERED_HTLC_SCRIPT_WEIGHT + ); // HTLC-Timeout check_spends!(revoked_local_txn[1], revoked_local_txn[0]); // Revoke the old state. - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage_1); { mine_transaction(&nodes[0], &revoked_local_txn[0]); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); mine_transaction(&nodes[1], &revoked_local_txn[0]); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); @@ -2928,10 +4139,14 @@ pub fn claim_htlc_outputs() { // The ChannelMonitor should claim the accepted HTLC output separately from the offered // HTLC and to_self outputs. let accepted_claim = node_txn.iter().filter(|tx| tx.input.len() == 1).next().unwrap(); - let offered_to_self_claim = node_txn.iter().filter(|tx| tx.input.len() == 2).next().unwrap(); + let offered_to_self_claim = + node_txn.iter().filter(|tx| tx.input.len() == 2).next().unwrap(); check_spends!(accepted_claim, revoked_local_txn[0]); check_spends!(offered_to_self_claim, revoked_local_txn[0]); - assert_eq!(accepted_claim.input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + accepted_claim.input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); let mut witness_lens = BTreeSet::new(); witness_lens.insert(offered_to_self_claim.input[0].witness.last().unwrap().len()); @@ -2967,8 +4182,11 @@ pub fn test_multiple_package_conflicts() { user_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_cfg.manually_accept_inbound_channels = true; - let node_chanmgrs = - create_node_chanmgrs(3, &node_cfgs, &[Some(user_cfg.clone()), Some(user_cfg.clone()), Some(user_cfg)]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(user_cfg.clone()), Some(user_cfg.clone()), Some(user_cfg)], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Since we're using anchor channels, make sure each node has a UTXO for paying fees. @@ -3151,15 +4369,18 @@ pub fn test_multiple_package_conflicts() { nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0], ); - nodes[0] - .node - .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &updates.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors(&nodes[0], 1); let (revoke_ack, commit_signed) = get_revoke_commit_msgs(&nodes[0], &nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &revoke_ack); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commit_signed); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commit_signed); check_added_monitors(&nodes[1], 4); let events = nodes[1].node.get_and_clear_pending_msg_events(); @@ -3235,17 +4456,20 @@ pub fn test_htlc_on_chain_success() { let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); // Ensure all nodes are at the same height - let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; + let node_max_height = + nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1); connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1); connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1); // Rebalance the network a bit by relaying one payment through all the channels... - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 8000000); - let (our_payment_preimage, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); - let (our_payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); + let (our_payment_preimage, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); + let (our_payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); // Broadcast legit commitment tx from C on B's chain // Broadcast HTLC Success transaction by C on received output from C's commitment tx on B's chain @@ -3266,20 +4490,39 @@ pub fn test_htlc_on_chain_success() { mine_transaction(&nodes[2], &commitment_tx[0]); check_closed_broadcast!(nodes[2], true); check_added_monitors!(nodes[2], 1); - check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelMonitor: 2 (2 * HTLC-Success tx) assert_eq!(node_txn.len(), 2); check_spends!(node_txn[0], commitment_tx[0]); check_spends!(node_txn[1], commitment_tx[0]); - assert_eq!(node_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); - assert_eq!(node_txn[1].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + node_txn[0].input[0].witness.clone().last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); + assert_eq!( + node_txn[1].input[0].witness.clone().last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); assert!(node_txn[0].output[0].script_pubkey.is_p2wsh()); // revokeable output assert!(node_txn[1].output[0].script_pubkey.is_p2wsh()); // revokeable output assert_eq!(node_txn[0].lock_time, LockTime::ZERO); assert_eq!(node_txn[1].lock_time, LockTime::ZERO); // Verify that B's ChannelManager is able to extract preimage from HTLC Success tx and pass it backward - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![commitment_tx[0].clone(), node_txn[0].clone(), node_txn[1].clone()])); + connect_block( + &nodes[1], + &create_dummy_block( + nodes[1].best_block_hash(), + 42, + vec![commitment_tx[0].clone(), node_txn[0].clone(), node_txn[1].clone()], + ), + ); connect_blocks(&nodes[1], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires { let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); @@ -3290,13 +4533,18 @@ pub fn test_htlc_on_chain_success() { let forwarded_events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(forwarded_events.len(), 3); match forwarded_events[0] { - Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {} + Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}, _ => panic!("Unexpected event"), } let chan_id = Some(chan_1.2); match forwarded_events[1] { - Event::PaymentForwarded { total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, - next_channel_id, outbound_amount_forwarded_msat, .. + Event::PaymentForwarded { + total_fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, + .. } => { assert_eq!(total_fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, chan_id); @@ -3304,11 +4552,16 @@ pub fn test_htlc_on_chain_success() { assert_eq!(next_channel_id, Some(chan_2.2)); assert_eq!(outbound_amount_forwarded_msat, Some(3000000)); }, - _ => panic!() + _ => panic!(), } match forwarded_events[2] { - Event::PaymentForwarded { total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, - next_channel_id, outbound_amount_forwarded_msat, .. + Event::PaymentForwarded { + total_fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, + .. } => { assert_eq!(total_fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, chan_id); @@ -3316,7 +4569,7 @@ pub fn test_htlc_on_chain_success() { assert_eq!(next_channel_id, Some(chan_2.2)); assert_eq!(outbound_amount_forwarded_msat, Some(3000000)); }, - _ => panic!() + _ => panic!(), } let mut events = nodes[1].node.get_and_clear_pending_msg_events(); { @@ -3328,16 +4581,32 @@ pub fn test_htlc_on_chain_success() { } assert_eq!(events.len(), 3); - let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); - let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events); + let nodes_2_event = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); + let nodes_0_event = + remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events); match nodes_2_event { - MessageSendEvent::HandleError { action: ErrorAction::DisconnectPeer { .. }, node_id: _ } => {}, + MessageSendEvent::HandleError { + action: ErrorAction::DisconnectPeer { .. }, + node_id: _, + } => {}, _ => panic!("Unexpected event"), } match nodes_0_event { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fail_htlcs, + ref update_fulfill_htlcs, + ref update_fail_malformed_htlcs, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fail_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); @@ -3354,7 +4623,7 @@ pub fn test_htlc_on_chain_success() { } macro_rules! check_tx_local_broadcast { - ($node: expr, $htlc_offered: expr, $commitment_tx: expr) => { { + ($node: expr, $htlc_offered: expr, $commitment_tx: expr) => {{ let mut node_txn = $node.tx_broadcaster.txn_broadcasted.lock().unwrap(); // HTLC timeout claims for non-anchor channels are only aggregated when claimed from the // remote commitment transaction. @@ -3363,20 +4632,32 @@ pub fn test_htlc_on_chain_success() { for tx in node_txn.iter() { check_spends!(tx, $commitment_tx); assert_ne!(tx.lock_time, LockTime::ZERO); - assert_eq!(tx.input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + tx.input[0].witness.last().unwrap().len(), + OFFERED_HTLC_SCRIPT_WEIGHT + ); assert!(tx.output[0].script_pubkey.is_p2wsh()); // revokeable output } - assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output); + assert_ne!( + node_txn[0].input[0].previous_output, + node_txn[1].input[0].previous_output + ); } else { assert_eq!(node_txn.len(), 1); check_spends!(node_txn[0], $commitment_tx); assert_ne!(node_txn[0].lock_time, LockTime::ZERO); - assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + node_txn[0].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); assert!(node_txn[0].output[0].script_pubkey.is_p2wpkh()); // direct payment - assert_ne!(node_txn[0].input[0].previous_output, node_txn[0].input[1].previous_output); + assert_ne!( + node_txn[0].input[0].previous_output, + node_txn[0].input[1].previous_output + ); } node_txn.clear(); - } } + }}; } // nodes[1] now broadcasts its own timeout-claim of the output that nodes[2] just claimed via success. check_tx_local_broadcast!(nodes[1], false, commitment_tx[0]); @@ -3388,24 +4669,29 @@ pub fn test_htlc_on_chain_success() { mine_transaction(&nodes[1], &node_a_commitment_tx[0]); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert!(node_txn.len() == 1 || node_txn.len() == 2); // HTLC-Success, RBF bump of above aggregated HTLC txn - let commitment_spend = - if node_txn.len() == 1 { + let commitment_spend = if node_txn.len() == 1 { + &node_txn[0] + } else { + // Certain `ConnectStyle`s will cause RBF bumps of the previous HTLC transaction to be broadcast. + // FullBlockViaListen + assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output); + if node_txn[0].input[0].previous_output.txid == node_a_commitment_tx[0].compute_txid() { + check_spends!(node_txn[1], commitment_tx[0]); &node_txn[0] } else { - // Certain `ConnectStyle`s will cause RBF bumps of the previous HTLC transaction to be broadcast. - // FullBlockViaListen - assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[0].previous_output); - if node_txn[0].input[0].previous_output.txid == node_a_commitment_tx[0].compute_txid() { - check_spends!(node_txn[1], commitment_tx[0]); - &node_txn[0] - } else { - check_spends!(node_txn[0], commitment_tx[0]); - &node_txn[1] - } - }; + check_spends!(node_txn[0], commitment_tx[0]); + &node_txn[1] + } + }; check_spends!(commitment_spend, node_a_commitment_tx[0]); assert_eq!(commitment_spend.input.len(), 2); @@ -3413,11 +4699,18 @@ pub fn test_htlc_on_chain_success() { assert_eq!(commitment_spend.input[1].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); assert_eq!(commitment_spend.lock_time.to_consensus_u32(), nodes[1].best_block_info().1); assert!(commitment_spend.output[0].script_pubkey.is_p2wpkh()); // direct payment - // We don't bother to check that B can claim the HTLC output on its commitment tx here as - // we already checked the same situation with A. + // We don't bother to check that B can claim the HTLC output on its commitment tx here as + // we already checked the same situation with A. // Verify that A's ChannelManager is able to extract preimage from preimage tx and generate PaymentSent - connect_block(&nodes[0], &create_dummy_block(nodes[0].best_block_hash(), 42, vec![node_a_commitment_tx[0].clone(), commitment_spend.clone()])); + connect_block( + &nodes[0], + &create_dummy_block( + nodes[0].best_block_hash(), + 42, + vec![node_a_commitment_tx[0].clone(), commitment_spend.clone()], + ), + ); connect_blocks(&nodes[0], TEST_FINAL_CLTV + MIN_CLTV_EXPIRY_DELTA as u32); // Confirm blocks until the HTLC expires check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); @@ -3465,23 +4758,38 @@ fn do_test_htlc_on_chain_timeout(connect_style: ConnectStyle) { let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); // Rebalance the network a bit by relaying one payment thorugh all the channels... - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 8000000); - let (_payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000); + let (_payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], 3000000); // Broadcast legit commitment tx from C on B's chain let commitment_tx = get_local_commitment_txn!(nodes[2], chan_2.2); check_spends!(commitment_tx[0], chan_2.3); nodes[2].node.fail_htlc_backwards(&payment_hash); check_added_monitors!(nodes[2], 0); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }] + ); check_added_monitors!(nodes[2], 1); let events = nodes[2].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(!update_fail_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); @@ -3493,28 +4801,48 @@ fn do_test_htlc_on_chain_timeout(connect_style: ConnectStyle) { mine_transaction(&nodes[2], &commitment_tx[0]); check_closed_broadcast!(nodes[2], true); check_added_monitors!(nodes[2], 1); - check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert_eq!(node_txn.len(), 0); // Broadcast timeout transaction by B on received output from C's commitment tx on B's chain // Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence mine_transaction(&nodes[1], &commitment_tx[0]); - check_closed_event(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false, - &[nodes[2].node.get_our_node_id()], 100000); - let htlc_expiry = get_monitor!(nodes[1], chan_2.2).get_claimable_balances().iter().filter_map(|bal| + check_closed_event( + &nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + &[nodes[2].node.get_our_node_id()], + 100000, + ); + let htlc_expiry = get_monitor!(nodes[1], chan_2.2) + .get_claimable_balances() + .iter() + .filter_map(|bal| { if let Balance::MaybeTimeoutClaimableHTLC { claimable_height, .. } = bal { Some(*claimable_height) } else { None } - ).next().unwrap(); + }) + .next() + .unwrap(); connect_blocks(&nodes[1], htlc_expiry - nodes[1].best_block_info().1); let timeout_tx = { let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); txn.iter().for_each(|tx| check_spends!(tx, commitment_tx[0])); - assert_eq!(txn[0].clone().input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + txn[0].clone().input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); txn.remove(0) }; @@ -3530,12 +4858,29 @@ fn do_test_htlc_on_chain_timeout(connect_style: ConnectStyle) { connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); check_added_monitors!(nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fail_htlcs, + ref update_fulfill_htlcs, + ref update_fail_malformed_htlcs, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(!update_fail_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); @@ -3554,11 +4899,20 @@ fn do_test_htlc_on_chain_timeout(connect_style: ConnectStyle) { check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // 1 timeout tx assert_eq!(node_txn.len(), 1); check_spends!(node_txn[0], commitment_tx[0]); - assert_eq!(node_txn[0].clone().input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1); + assert_eq!( + node_txn[0].clone().input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + 1 + ); } #[xtest(feature = "_externalize_tests")] @@ -3582,7 +4936,8 @@ pub fn test_simple_commitment_revoked_fail_backward() { create_announced_chan_between_nodes(&nodes, 0, 1); let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); - let (payment_preimage, _payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000); + let (payment_preimage, _payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000); // Get the will-be-revoked local txn from nodes[2] let revoked_local_txn = get_local_commitment_txn!(nodes[2], chan_2.2); // Revoke the old state @@ -3591,32 +4946,66 @@ pub fn test_simple_commitment_revoked_fail_backward() { let (_, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000); mine_transaction(&nodes[1], &revoked_local_txn[0]); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[2].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); check_added_monitors!(nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fail_htlcs, + ref update_fulfill_htlcs, + ref update_fail_malformed_htlcs, + ref commitment_signed, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert_eq!(update_fail_htlcs.len(), 1); assert!(update_fulfill_htlcs.is_empty()); assert!(update_fail_malformed_htlcs.is_empty()); assert_eq!(nodes[0].node.get_our_node_id(), *node_id); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false, true); - expect_payment_failed_with_update!(nodes[0], payment_hash, false, chan_2.0.contents.short_channel_id, true); + expect_payment_failed_with_update!( + nodes[0], + payment_hash, + false, + chan_2.0.contents.short_channel_id, + true + ); }, _ => panic!("Unexpected event"), } } -fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use_dust: bool, no_to_remote: bool) { +fn do_test_commitment_revoked_fail_backward_exhaustive( + deliver_bs_raa: bool, use_dust: bool, no_to_remote: bool, +) { // Test that if our counterparty broadcasts a revoked commitment transaction we fail all // pending HTLCs on that channel backwards even if the HTLCs aren't present in our latest // commitment transaction anymore. @@ -3641,7 +5030,11 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use create_announced_chan_between_nodes(&nodes, 0, 1); let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); - let (payment_preimage, _payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], if no_to_remote { 10_000 } else { 3_000_000 }); + let (payment_preimage, _payment_hash, ..) = route_payment( + &nodes[0], + &[&nodes[1], &nodes[2]], + if no_to_remote { 10_000 } else { 3_000_000 }, + ); // Get the will-be-revoked local txn from nodes[2] let revoked_local_txn = get_local_commitment_txn!(nodes[2], chan_2.2); assert_eq!(revoked_local_txn[0].output.len(), if no_to_remote { 1 } else { 2 }); @@ -3651,16 +5044,34 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use let value = if use_dust { // The dust limit applied to HTLC outputs considers the fee of the HTLC transaction as // well, so HTLCs at exactly the dust limit will not be included in commitment txn. - nodes[2].node.per_peer_state.read().unwrap().get(&nodes[1].node.get_our_node_id()) - .unwrap().lock().unwrap().channel_by_id.get(&chan_2.2).unwrap().context().holder_dust_limit_satoshis * 1000 - } else { 3000000 }; + nodes[2] + .node + .per_peer_state + .read() + .unwrap() + .get(&nodes[1].node.get_our_node_id()) + .unwrap() + .lock() + .unwrap() + .channel_by_id + .get(&chan_2.2) + .unwrap() + .context() + .holder_dust_limit_satoshis + * 1000 + } else { + 3000000 + }; let (_, first_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value); let (_, second_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value); let (_, third_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], value); nodes[2].node.fail_htlc_backwards(&first_payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: first_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash: first_payment_hash }] + ); check_added_monitors!(nodes[2], 1); let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -3668,12 +5079,25 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use assert!(updates.update_fail_malformed_htlcs.is_empty()); assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fee.is_none()); - nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); - let bs_raa = commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true, false, true); + nodes[1] + .node + .handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + let bs_raa = commitment_signed_dance!( + nodes[1], + nodes[2], + updates.commitment_signed, + false, + true, + false, + true + ); // Drop the last RAA from 3 -> 2 nodes[2].node.fail_htlc_backwards(&second_payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: second_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash: second_payment_hash }] + ); check_added_monitors!(nodes[2], 1); let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -3681,16 +5105,28 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use assert!(updates.update_fail_malformed_htlcs.is_empty()); assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fee.is_none()); - nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &updates.commitment_signed); + nodes[1] + .node + .handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); // Note that nodes[1] is in AwaitingRAA, so won't send a CS - let as_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[2].node.get_our_node_id() + ); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[2], 1); nodes[2].node.fail_htlc_backwards(&third_payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: third_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash: third_payment_hash }] + ); check_added_monitors!(nodes[2], 1); let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -3698,21 +5134,38 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use assert!(updates.update_fail_malformed_htlcs.is_empty()); assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fee.is_none()); - nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[1] + .node + .handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); // At this point first_payment_hash has dropped out of the latest two commitment // transactions that nodes[1] is tracking... - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); // Note that nodes[1] is (still) in AwaitingRAA, so won't send a CS - let as_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id()); + let as_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[2].node.get_our_node_id() + ); nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &as_raa); check_added_monitors!(nodes[2], 1); // Add a fourth HTLC, this one will get sequestered away in nodes[1]'s holding cell waiting // on nodes[2]'s RAA. - let (route, fourth_payment_hash, _, fourth_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[2], 1000000); - nodes[1].node.send_payment_with_route(route, fourth_payment_hash, - RecipientOnionFields::secret_only(fourth_payment_secret), PaymentId(fourth_payment_hash.0)).unwrap(); + let (route, fourth_payment_hash, _, fourth_payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[2], 1000000); + nodes[1] + .node + .send_payment_with_route( + route, + fourth_payment_hash, + RecipientOnionFields::secret_only(fourth_payment_secret), + PaymentId(fourth_payment_hash.0), + ) + .unwrap(); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); check_added_monitors!(nodes[1], 0); @@ -3725,11 +5178,11 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::HTLCHandlingFailed { .. } => { }, + Event::HTLCHandlingFailed { .. } => {}, _ => panic!("Unexpected event"), } match events[1] { - Event::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event"), }; // Deliberately don't process the pending fail-back so they all fail back at once after @@ -3765,9 +5218,21 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use assert_eq!(events.len(), if deliver_bs_raa { 4 } else { 3 }); if deliver_bs_raa { - let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); + let nodes_2_event = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); match nodes_2_event { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fail_htlcs, + ref update_fulfill_htlcs, + ref update_fail_malformed_htlcs, + .. + }, + } => { assert_eq!(nodes[2].node.get_our_node_id(), *node_id); assert_eq!(update_add_htlcs.len(), 1); assert!(update_fulfill_htlcs.is_empty()); @@ -3778,27 +5243,54 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use } } - let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); + let nodes_2_event = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); match nodes_2_event { - MessageSendEvent::HandleError { action: ErrorAction::DisconnectPeer { msg: Some(msgs::ErrorMessage { channel_id, ref data }) }, node_id: _ } => { + MessageSendEvent::HandleError { + action: + ErrorAction::DisconnectPeer { msg: Some(msgs::ErrorMessage { channel_id, ref data }) }, + node_id: _, + } => { assert_eq!(channel_id, chan_2.2); - assert_eq!(data.as_str(), "Channel closed because commitment or closing transaction was confirmed on chain."); + assert_eq!( + data.as_str(), + "Channel closed because commitment or closing transaction was confirmed on chain." + ); }, _ => panic!("Unexpected event"), } - let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events); + let nodes_0_event = + remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut events); match nodes_0_event { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fail_htlcs, + ref update_fulfill_htlcs, + ref update_fail_malformed_htlcs, + ref commitment_signed, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert_eq!(update_fail_htlcs.len(), 3); assert!(update_fulfill_htlcs.is_empty()); assert!(update_fail_malformed_htlcs.is_empty()); assert_eq!(nodes[0].node.get_our_node_id(), *node_id); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[1]); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[2]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[1]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[2]); commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false, true); @@ -3810,7 +5302,10 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use // If we delivered B's RAA we got an unknown preimage error, not something // that we should update our routing table for. if !deliver_bs_raa { - if let PathFailure::OnPath { network_update: Some(_) } = failure { } else { panic!("Unexpected path failure") } + if let PathFailure::OnPath { network_update: Some(_) } = failure { + } else { + panic!("Unexpected path failure") + } } }, _ => panic!("Unexpected event"), @@ -3822,7 +5317,11 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use _ => panic!("Unexpected event"), } match events[2] { - Event::PaymentPathFailed { ref payment_hash, failure: PathFailure::OnPath { network_update: Some(_) }, .. } => { + Event::PaymentPathFailed { + ref payment_hash, + failure: PathFailure::OnPath { network_update: Some(_) }, + .. + } => { assert!(failed_htlcs.insert(payment_hash.0)); }, _ => panic!("Unexpected event"), @@ -3834,7 +5333,11 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use _ => panic!("Unexpected event"), } match events[4] { - Event::PaymentPathFailed { ref payment_hash, failure: PathFailure::OnPath { network_update: Some(_) }, .. } => { + Event::PaymentPathFailed { + ref payment_hash, + failure: PathFailure::OnPath { network_update: Some(_) }, + .. + } => { assert!(failed_htlcs.insert(payment_hash.0)); }, _ => panic!("Unexpected event"), @@ -3886,9 +5389,17 @@ pub fn fail_backward_pending_htlc_upon_channel_failure() { // Alice -> Bob: Route a payment but without Bob sending revoke_and_ack. { - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 50_000); - nodes[0].node.send_payment_with_route(route, payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 50_000); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let payment_event = { @@ -3901,10 +5412,18 @@ pub fn fail_backward_pending_htlc_upon_channel_failure() { } // Alice -> Bob: Route another payment but now Alice waits for Bob's earlier revoke_and_ack. - let (route, failed_payment_hash, _, failed_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 50_000); + let (route, failed_payment_hash, _, failed_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 50_000); { - nodes[0].node.send_payment_with_route(route, failed_payment_hash, - RecipientOnionFields::secret_only(failed_payment_secret), PaymentId(failed_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + failed_payment_hash, + RecipientOnionFields::secret_only(failed_payment_secret), + PaymentId(failed_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -3912,16 +5431,28 @@ pub fn fail_backward_pending_htlc_upon_channel_failure() { // Alice <- Bob: Send a malformed update_add_htlc so Alice fails the channel. { - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 50_000); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 50_000); let secp_ctx = Secp256k1::new(); let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let current_height = nodes[1].node.best_block.read().unwrap().height + 1; let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads( - &route.paths[0], 50_000, &recipient_onion_fields, current_height, &None, None, None).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv); - let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + &route.paths[0], + 50_000, + &recipient_onion_fields, + current_height, + &None, + None, + None, + ) + .unwrap(); + let onion_keys = + onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv); + let onion_routing_packet = + onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash) + .unwrap(); // Send a 0-msat update_add_htlc to fail the channel. let update_add_htlc = msgs::UpdateAddHTLC { @@ -3978,11 +5509,24 @@ pub fn test_htlc_ignore_latest_remote_commitment() { let funding_tx = create_announced_chan_between_nodes(&nodes, 0, 1).3; let error_message = "Channel force-closed"; route_payment(&nodes[0], &[&nodes[1]], 10000000); - nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); assert_eq!(node_txn.len(), 2); @@ -3993,7 +5537,13 @@ pub fn test_htlc_ignore_latest_remote_commitment() { connect_block(&nodes[1], &block); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); // Duplicate the connect_block call since this may happen due to other listeners // registering new transactions @@ -4010,11 +5560,19 @@ pub fn test_force_close_fail_back() { create_announced_chan_between_nodes(&nodes, 0, 1); create_announced_chan_between_nodes(&nodes, 1, 2); - let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1000000); + let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], 1000000); let mut payment_event = { - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -4034,7 +5592,10 @@ pub fn test_force_close_fail_back() { check_added_monitors!(nodes[1], 1); nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors!(nodes[2], 1); let (_, _) = get_revoke_commit_msgs!(nodes[2], nodes[1].node.get_our_node_id()); @@ -4043,10 +5604,23 @@ pub fn test_force_close_fail_back() { // transaction and ensure nodes[1] doesn't fail-backwards (this was originally a bug!). let error_message = "Channel force-closed"; let channel_id = payment_event.commitment_msg[0].channel_id; - nodes[2].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[2] + .node + .force_close_broadcasting_latest_txn( + &channel_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[2], true); check_added_monitors!(nodes[2], 1); - check_closed_event!(nodes[2], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); let commitment_tx = { let mut node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap(); // Note that we don't bother broadcasting the HTLC-Success transaction here as we don't @@ -4061,19 +5635,30 @@ pub fn test_force_close_fail_back() { // Note no UpdateHTLCs event here from nodes[1] to nodes[0]! check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[2].node.get_our_node_id()], + 100000 + ); // Now check that if we add the preimage to ChannelMonitor it broadcasts our HTLC-Success.. { - get_monitor!(nodes[2], channel_id) - .provide_payment_preimage_unsafe_legacy( - &our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, - &LowerBoundedFeeEstimator::new(node_cfgs[2].fee_estimator), &node_cfgs[2].logger - ); + get_monitor!(nodes[2], channel_id).provide_payment_preimage_unsafe_legacy( + &our_payment_hash, + &our_payment_preimage, + &node_cfgs[2].tx_broadcaster, + &LowerBoundedFeeEstimator::new(node_cfgs[2].fee_estimator), + &node_cfgs[2].logger, + ); } mine_transaction(&nodes[2], &commitment_tx); let mut node_txn = nodes[2].tx_broadcaster.txn_broadcast(); - assert_eq!(node_txn.len(), if nodes[2].connect_style.borrow().updates_best_block_first() { 2 } else { 1 }); + assert_eq!( + node_txn.len(), + if nodes[2].connect_style.borrow().updates_best_block_first() { 2 } else { 1 } + ); let htlc_tx = node_txn.pop().unwrap(); assert_eq!(htlc_tx.input.len(), 1); assert_eq!(htlc_tx.input[0].previous_output.txid, commitment_tx.compute_txid()); @@ -4102,7 +5687,10 @@ pub fn test_dup_events_on_peer_disconnect() { expect_payment_claimed!(nodes[1], payment_hash, 1_000_000); check_added_monitors!(nodes[1], 1); let claim_msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &claim_msgs.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &claim_msgs.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); @@ -4125,18 +5713,41 @@ pub fn test_peer_disconnected_before_funding_broadcasted() { // Open a channel between `nodes[0]` and `nodes[1]`, for which the funding transaction is never // broadcasted, even though it's created by `nodes[0]`. - let expected_temporary_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let expected_temporary_channel_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None, None) + .unwrap(); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, _funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42); + let (temporary_channel_id, tx, _funding_output) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42); assert_eq!(temporary_channel_id, expected_temporary_channel_id); - assert!(nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).is_ok()); - - let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + assert!(nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone() + ) + .is_ok()); + + let funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); assert_eq!(funding_created_msg.temporary_channel_id, expected_temporary_channel_id); // Even though the funding transaction is created by `nodes[0]`, the `FundingCreated` msg is @@ -4158,10 +5769,22 @@ pub fn test_peer_disconnected_before_funding_broadcasted() { // Ensure that the channel is closed with `ClosureReason::DisconnectedPeer` and a // `DiscardFunding` event when the peers are disconnected and do not reconnect before the // funding transaction is broadcasted. - check_closed_event!(&nodes[0], 2, ClosureReason::DisconnectedPeer, true - , [nodes[1].node.get_our_node_id()], 1000000); - check_closed_event!(&nodes[1], 1, ClosureReason::DisconnectedPeer, false - , [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + &nodes[0], + 2, + ClosureReason::DisconnectedPeer, + true, + [nodes[1].node.get_our_node_id()], + 1000000 + ); + check_closed_event!( + &nodes[1], + 1, + ClosureReason::DisconnectedPeer, + false, + [nodes[0].node.get_our_node_id()], + 1000000 + ); } #[xtest(feature = "_externalize_tests")] @@ -4180,26 +5803,27 @@ pub fn test_simple_peer_disconnect() { reconnect_args.send_channel_ready = (true, true); reconnect_nodes(reconnect_args); - let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0; - let payment_hash_2 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1; - fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_2); - claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_1); + let payment_preimage_1 = route_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 1000000).0; + let payment_hash_2 = route_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 1000000).1; + fail_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], payment_hash_2); + claim_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], payment_preimage_1); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); - let (payment_preimage_3, payment_hash_3, ..) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000); - let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0; - let payment_hash_5 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1; - let payment_hash_6 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1; + let (payment_preimage_3, payment_hash_3, ..) = + route_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 1000000); + let payment_preimage_4 = route_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 1000000).0; + let payment_hash_5 = route_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 1000000).1; + let payment_hash_6 = route_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 1000000).1; nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage_3) - .skip_last(true) + .skip_last(true), ); fail_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], true, payment_hash_5); @@ -4237,8 +5861,8 @@ pub fn test_simple_peer_disconnect() { } check_added_monitors(&nodes[0], 1); - claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_4); - fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_6); + claim_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], payment_preimage_4); + fail_payment(&nodes[0], &vec![&nodes[1], &nodes[2]], payment_hash_6); } fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken_lnd: bool) { @@ -4250,7 +5874,8 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken let mut as_channel_ready = None; let channel_id = if messages_delivered == 0 { - let (channel_ready, chan_id, _) = create_chan_between_nodes_with_value_a(&nodes[0], &nodes[1], 100000, 10001); + let (channel_ready, chan_id, _) = + create_chan_between_nodes_with_value_a(&nodes[0], &nodes[1], 100000, 10001); as_channel_ready = Some(channel_ready); // nodes[1] doesn't receive the channel_ready message (it'll be re-sent on reconnect) // Note that we store it so that if we're running with `simulate_broken_lnd` we can deliver @@ -4260,11 +5885,19 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken create_announced_chan_between_nodes(&nodes, 0, 1).2 }; - let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1_000_000); + let (route, payment_hash_1, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1_000_000); let payment_event = { - nodes[0].node.send_payment_with_route(route, payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -4276,25 +5909,43 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken if messages_delivered < 2 { // Drop the payment_event messages, and let them get re-generated in reconnect_nodes! } else { - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); if messages_delivered >= 3 { - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + 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 (bs_revoke_and_ack, bs_commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_revoke_and_ack, bs_commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); if messages_delivered >= 4 { - nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_revoke_and_ack); + nodes[0] + .node + .handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_revoke_and_ack); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); if messages_delivered >= 5 { - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_commitment_signed); - let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_commitment_signed, + ); + let as_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); if messages_delivered >= 6 { - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_revoke_and_ack); + nodes[1].node.handle_revoke_and_ack( + nodes[0].node.get_our_node_id(), + &as_revoke_and_ack, + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); } @@ -4315,7 +5966,10 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken // in `reconnect_nodes` but we currently don't fail based on that. // // See-also - nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &as_channel_ready.as_ref().unwrap().0); + nodes[1].node.handle_channel_ready( + nodes[0].node.get_our_node_id(), + &as_channel_ready.as_ref().unwrap().0, + ); } // Even if the channel_ready messages get exchanged, as long as nothing further was // received on either side, both sides will need to resend them. @@ -4348,17 +6002,17 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken if messages_delivered == 0 { assert_eq!(events_1.len(), 2); match events_1[0] { - Event::ChannelReady { .. } => { }, + Event::ChannelReady { .. } => {}, _ => panic!("Unexpected event"), }; match events_1[1] { - Event::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event"), }; } else { assert_eq!(events_1.len(), 1); match events_1[0] { - Event::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event"), }; } @@ -4372,17 +6026,26 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken let events_2 = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events_2.len(), 1); match events_2[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { + Event::PaymentClaimable { + ref payment_hash, + ref purpose, + amount_msat, + receiver_node_id, + via_channel_id, + .. + } => { assert_eq!(payment_hash_1, *payment_hash); assert_eq!(amount_msat, 1_000_000); assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id()); assert_eq!(via_channel_id, Some(channel_id)); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_1, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -4408,7 +6071,9 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken }; if messages_delivered >= 1 { - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_fulfill_htlc); + nodes[0] + .node + .handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_fulfill_htlc); let events_4 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_4.len(), 1); @@ -4421,23 +6086,39 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken } if messages_delivered >= 2 { - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let (as_revoke_and_ack, as_commitment_signed) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (as_revoke_and_ack, as_commitment_signed) = + get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); if messages_delivered >= 3 { - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_revoke_and_ack); + nodes[1] + .node + .handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_revoke_and_ack); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); if messages_delivered >= 4 { - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_commitment_signed); - let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_commitment_signed, + ); + let bs_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[1], 1); if messages_delivered >= 5 { - nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_revoke_and_ack); + nodes[0].node.handle_revoke_and_ack( + nodes[1].node.get_our_node_id(), + &bs_revoke_and_ack, + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); } @@ -4535,7 +6216,11 @@ pub fn test_channel_ready_without_best_block_updated() { nodes[0].node.transactions_confirmed(&conf_block_header, &conf_txn[..], conf_height); // Ensure nodes[0] generates a channel_ready after the transactions_confirmed - let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let as_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(), &as_channel_ready); } @@ -4567,7 +6252,11 @@ pub fn test_channel_monitor_skipping_block_when_channel_manager_is_leading() { connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH); // Ensure nodes[0] generates a channel_ready after the transactions_confirmed - let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let as_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(), &as_channel_ready); } @@ -4602,7 +6291,11 @@ pub fn test_channel_monitor_skipping_block_when_channel_manager_is_lagging() { connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH); // Ensure nodes[0] generates a channel_ready after the transactions_confirmed - let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let as_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(), &as_channel_ready); } @@ -4616,12 +6309,21 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); // Now try to send a second payment which will fail to send - let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + let (route, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let events_1 = nodes[0].node.get_and_clear_pending_msg_events(); @@ -4638,7 +6340,19 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events_2.len(), 1); match events_2[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); assert!(update_add_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); @@ -4646,7 +6360,10 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { assert!(update_fail_malformed_htlcs.is_empty()); assert!(update_fee.is_none()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &update_fulfill_htlcs[0], + ); let events_3 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_3.len(), 1); match events_3[0] { @@ -4657,8 +6374,15 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { _ => panic!("Unexpected event"), } - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), commitment_signed); - let _ = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + commitment_signed, + ); + let _ = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); }, @@ -4668,14 +6392,32 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); assert_eq!(reestablish_1.len(), 1); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); assert_eq!(reestablish_2.len(), 1); @@ -4697,14 +6439,27 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { assert!(as_resp.2.as_ref().unwrap().update_fail_htlcs.is_empty()); assert!(as_resp.2.as_ref().unwrap().update_fail_malformed_htlcs.is_empty()); assert!(as_resp.2.as_ref().unwrap().update_fee.is_none()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_resp.2.as_ref().unwrap().update_add_htlcs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_resp.2.as_ref().unwrap().commitment_signed); - let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_update_add_htlc( + nodes[0].node.get_our_node_id(), + &as_resp.2.as_ref().unwrap().update_add_htlcs[0], + ); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_resp.2.as_ref().unwrap().commitment_signed, + ); + let bs_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), as_resp.1.as_ref().unwrap()); - let bs_second_commitment_signed = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_revoke_and_ack(nodes[0].node.get_our_node_id(), as_resp.1.as_ref().unwrap()); + let bs_second_commitment_signed = + get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(bs_second_commitment_signed.update_add_htlcs.is_empty()); assert!(bs_second_commitment_signed.update_fulfill_htlcs.is_empty()); assert!(bs_second_commitment_signed.update_fail_htlcs.is_empty()); @@ -4721,13 +6476,27 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { assert!(as_commitment_signed.update_fee.is_none()); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_commitment_signed.commitment_signed); - let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_second_commitment_signed.commitment_signed, + ); + let as_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_commitment_signed.commitment_signed); - let bs_second_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_commitment_signed.commitment_signed, + ); + let bs_second_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); // No commitment_signed so get_event_msg's assert(len == 1) passes check_added_monitors!(nodes[1], 1); @@ -4743,11 +6512,13 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() { Event::PaymentClaimable { ref payment_hash, ref purpose, .. } => { assert_eq!(payment_hash_2, *payment_hash); match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, payment_secret, .. + } => { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_2, *payment_secret); }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -4772,22 +6543,49 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) { create_announced_chan_between_nodes(&nodes, 0, 1); let our_payment_hash = if send_partial_mpp { - let (route, our_payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100000); + let (route, our_payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[1], 100000); // Use the utility function send_payment_along_path to send the payment with MPP data which // indicates there are more HTLCs coming. let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match. let payment_id = PaymentId([42; 32]); - let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id, &route).unwrap(); - nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, - RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, - &None, session_privs[0]).unwrap(); + let session_privs = nodes[0] + .node + .test_add_new_pending_payment( + our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + &route, + ) + .unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &route.paths[0], + &our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), + 200_000, + cur_height, + payment_id, + &None, + session_privs[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); // Now do the relevant commitment_signed/RAA dances along the path, noting that the final // hop should *not* yet generate any PaymentClaimable event(s). - pass_along_path(&nodes[0], &[&nodes[1]], 100000, our_payment_hash, Some(payment_secret), events.drain(..).next().unwrap(), false, None); + pass_along_path( + &nodes[0], + &[&nodes[1]], + 100000, + our_payment_hash, + Some(payment_secret), + events.drain(..).next().unwrap(), + false, + None, + ); our_payment_hash } else { route_payment(&nodes[0], &[&nodes[1]], 100000).1 @@ -4796,14 +6594,18 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) { let mut block = create_dummy_block(nodes[0].best_block_hash(), 42, Vec::new()); connect_block(&nodes[0], &block); connect_block(&nodes[1], &block); - let block_count = TEST_FINAL_CLTV + CHAN_CONFIRM_DEPTH + 2 - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS; + let block_count = + TEST_FINAL_CLTV + CHAN_CONFIRM_DEPTH + 2 - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS; for _ in CHAN_CONFIRM_DEPTH + 2..block_count { block.header.prev_blockhash = block.block_hash(); connect_block(&nodes[0], &block); connect_block(&nodes[1], &block); } - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }] + ); check_added_monitors!(nodes[1], 1); let htlc_timeout_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -4812,12 +6614,21 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) { assert!(htlc_timeout_updates.update_fail_malformed_htlcs.is_empty()); assert!(htlc_timeout_updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_timeout_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &htlc_timeout_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], htlc_timeout_updates.commitment_signed, false); // 100_000 msat as u64, followed by the height at which we failed back above let mut expected_failure_data = (100_000 as u64).to_be_bytes().to_vec(); expected_failure_data.extend_from_slice(&(block_count - 1).to_be_bytes()); - expect_payment_failed!(nodes[0], our_payment_hash, true, LocalHTLCFailureReason::IncorrectPaymentDetails, &expected_failure_data[..]); + expect_payment_failed!( + nodes[0], + our_payment_hash, + true, + LocalHTLCFailureReason::IncorrectPaymentDetails, + &expected_failure_data[..] + ); } #[xtest(feature = "_externalize_tests")] @@ -4836,26 +6647,45 @@ fn do_test_holding_cell_htlc_add_timeouts(forwarded_htlc: bool) { let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); // Make sure all nodes are at the same starting height - connect_blocks(&nodes[0], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[0], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); // Route a first payment to get the 1 -> 2 channel in awaiting_raa... - let (route, first_payment_hash, _, first_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000); - nodes[1].node.send_payment_with_route(route, first_payment_hash, - RecipientOnionFields::secret_only(first_payment_secret), PaymentId(first_payment_hash.0)).unwrap(); + let (route, first_payment_hash, _, first_payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[2], 100000); + nodes[1] + .node + .send_payment_with_route( + route, + first_payment_hash, + RecipientOnionFields::secret_only(first_payment_secret), + PaymentId(first_payment_hash.0), + ) + .unwrap(); assert_eq!(nodes[1].node.get_and_clear_pending_msg_events().len(), 1); check_added_monitors!(nodes[1], 1); // Now attempt to route a second payment, which should be placed in the holding cell let sending_node = if forwarded_htlc { &nodes[0] } else { &nodes[1] }; - let (route, second_payment_hash, _, second_payment_secret) = get_route_and_payment_hash!(sending_node, nodes[2], 100000); - sending_node.node.send_payment_with_route(route, second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), PaymentId(second_payment_hash.0)).unwrap(); + let (route, second_payment_hash, _, second_payment_secret) = + get_route_and_payment_hash!(sending_node, nodes[2], 100000); + sending_node + .node + .send_payment_with_route( + route, + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + PaymentId(second_payment_hash.0), + ) + .unwrap(); if forwarded_htlc { check_added_monitors!(nodes[0], 1); - let payment_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + let payment_event = + SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[1]); } @@ -4867,18 +6697,36 @@ fn do_test_holding_cell_htlc_add_timeouts(forwarded_htlc: bool) { connect_blocks(&nodes[1], 1); if forwarded_htlc { - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); check_added_monitors!(nodes[1], 1); let fail_commit = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(fail_commit.len(), 1); match fail_commit[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fail_htlcs, ref commitment_signed, .. }, .. } => { - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fail_htlcs, ref commitment_signed, .. }, + .. + } => { + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, true, true); }, _ => unreachable!(), } - expect_payment_failed_with_update!(nodes[0], second_payment_hash, false, chan_2.0.contents.short_channel_id, false); + expect_payment_failed_with_update!( + nodes[0], + second_payment_hash, + false, + chan_2.0.contents.short_channel_id, + false + ); } else { expect_payment_failed!(nodes[1], second_payment_hash, false); } @@ -4891,31 +6739,50 @@ pub fn test_holding_cell_htlc_add_timeouts() { } macro_rules! check_spendable_outputs { - ($node: expr, $keysinterface: expr) => { - { - let mut events = $node.chain_monitor.chain_monitor.get_and_clear_pending_events(); - let mut txn = Vec::new(); - let mut all_outputs = Vec::new(); - let secp_ctx = Secp256k1::new(); - for event in events.drain(..) { - match event { - Event::SpendableOutputs { mut outputs, channel_id: _ } => { - for outp in outputs.drain(..) { - txn.push($keysinterface.backing.spend_spendable_outputs(&[&outp], Vec::new(), Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), 253, None, &secp_ctx).unwrap()); - all_outputs.push(outp); - } - }, - _ => panic!("Unexpected event"), - }; - } - if all_outputs.len() > 1 { - if let Ok(tx) = $keysinterface.backing.spend_spendable_outputs(&all_outputs.iter().map(|a| a).collect::>(), Vec::new(), Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), 253, None, &secp_ctx) { - txn.push(tx); - } + ($node: expr, $keysinterface: expr) => {{ + let mut events = $node.chain_monitor.chain_monitor.get_and_clear_pending_events(); + let mut txn = Vec::new(); + let mut all_outputs = Vec::new(); + let secp_ctx = Secp256k1::new(); + for event in events.drain(..) { + match event { + Event::SpendableOutputs { mut outputs, channel_id: _ } => { + for outp in outputs.drain(..) { + txn.push( + $keysinterface + .backing + .spend_spendable_outputs( + &[&outp], + Vec::new(), + Builder::new() + .push_opcode(opcodes::all::OP_RETURN) + .into_script(), + 253, + None, + &secp_ctx, + ) + .unwrap(), + ); + all_outputs.push(outp); + } + }, + _ => panic!("Unexpected event"), + }; + } + if all_outputs.len() > 1 { + if let Ok(tx) = $keysinterface.backing.spend_spendable_outputs( + &all_outputs.iter().map(|a| a).collect::>(), + Vec::new(), + Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), + 253, + None, + &secp_ctx, + ) { + txn.push(tx); } - txn } - } + txn + }}; } #[xtest(feature = "_externalize_tests")] @@ -4928,10 +6795,23 @@ pub fn test_claim_sizeable_push_msat() { let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 98_000_000); let error_message = "Channel force-closed"; - nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan.2, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[0].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert_eq!(node_txn.len(), 1); check_spends!(node_txn[0], chan.3); @@ -4958,10 +6838,23 @@ pub fn test_claim_on_remote_sizeable_push_msat() { let error_message = "Channel force-closed"; let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 98_000_000); - nodes[0].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan.2, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(node_txn.len(), 1); @@ -4971,7 +6864,13 @@ pub fn test_claim_on_remote_sizeable_push_msat() { mine_transaction(&nodes[1], &node_txn[0]); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); let spend_txn = check_spendable_outputs!(nodes[1], node_cfgs[1].keys_manager); @@ -4990,16 +6889,22 @@ pub fn test_claim_on_remote_revoked_sizeable_push_msat() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 59000000); - let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let payment_preimage = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan.2); assert_eq!(revoked_local_txn[0].input.len(), 1); assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.compute_txid()); - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage); mine_transaction(&nodes[1], &revoked_local_txn[0]); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); mine_transaction(&nodes[1], &node_txn[0]); @@ -5051,7 +6956,13 @@ pub fn test_static_spendable_outputs_preimage_tx() { assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); mine_transaction(&nodes[1], &node_txn[0]); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); let spend_txn = check_spendable_outputs!(nodes[1], node_cfgs[1].keys_manager); @@ -5070,9 +6981,9 @@ pub fn test_static_spendable_outputs_timeout_tx() { let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); // Rebalance the network a bit by relaying one payment through all the channels ... - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 8000000); - let (_, our_payment_hash, ..) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3_000_000); + let (_, our_payment_hash, ..) = route_payment(&nodes[1], &vec![&nodes[0]][..], 3_000_000); let commitment_tx = get_local_commitment_txn!(nodes[0], chan_1.2); assert_eq!(commitment_tx[0].input.len(), 1); @@ -5091,11 +7002,17 @@ pub fn test_static_spendable_outputs_timeout_tx() { // Check B's monitor was able to send back output descriptor event for timeout tx on A's commitment tx let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(node_txn.len(), 1); // ChannelMonitor: timeout tx - check_spends!(node_txn[0], commitment_tx[0].clone()); + check_spends!(node_txn[0], commitment_tx[0].clone()); assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); mine_transaction(&nodes[1], &node_txn[0]); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); expect_payment_failed!(nodes[1], our_payment_hash, false); @@ -5115,21 +7032,30 @@ fn do_test_static_spendable_outputs_justice_tx_revoked_commitment_tx(split_tx: b // Create some initial channels let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); - let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let payment_preimage = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2); assert_eq!(revoked_local_txn[0].input.len(), 1); assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.compute_txid()); - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage); if split_tx { - connect_blocks(&nodes[1], TEST_FINAL_CLTV - COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE + 1); + connect_blocks( + &nodes[1], + TEST_FINAL_CLTV - COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE + 1, + ); } mine_transaction(&nodes[1], &revoked_local_txn[0]); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); // If the HTLC expires in more than COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE blocks, we'll // claim both the revoked and HTLC outputs in one transaction, otherwise we'll split them as we @@ -5170,24 +7096,33 @@ pub fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() { // Create some initial channels let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); - let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let payment_preimage = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; let revoked_local_txn = get_local_commitment_txn!(nodes[0], chan_1.2); assert_eq!(revoked_local_txn[0].input.len(), 1); assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.compute_txid()); - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage); // A will generate HTLC-Timeout from revoked commitment tx mine_transaction(&nodes[0], &revoked_local_txn[0]); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[0], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(revoked_htlc_txn.len(), 1); assert_eq!(revoked_htlc_txn[0].input.len(), 1); - assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), + OFFERED_HTLC_SCRIPT_WEIGHT + ); check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]); assert_ne!(revoked_htlc_txn[0].lock_time, LockTime::ZERO); // HTLC-Timeout @@ -5196,10 +7131,23 @@ pub fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() { // locktime. connect_blocks(&nodes[1], TEST_FINAL_CLTV); // B will generate justice tx from A's revoked commitment/HTLC tx - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()])); + connect_block( + &nodes[1], + &create_dummy_block( + nodes[1].best_block_hash(), + 42, + vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()], + ), + ); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); // There will be 2 justice transactions: // - One on the unpinnable, revoked to_self output on the commitment transaction and on @@ -5240,7 +7188,7 @@ pub fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { // Create some initial channels let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); - let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; + let payment_preimage = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan_1.2); assert_eq!(revoked_local_txn[0].input.len(), 1); assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.compute_txid()); @@ -5248,18 +7196,27 @@ pub fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { // The to-be-revoked commitment tx should have one HTLC and one to_remote output assert_eq!(revoked_local_txn[0].output.len(), 2); - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage); // B will generate HTLC-Success from revoked commitment tx mine_transaction(&nodes[1], &revoked_local_txn[0]); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert_eq!(revoked_htlc_txn.len(), 1); assert_eq!(revoked_htlc_txn[0].input.len(), 1); - assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); check_spends!(revoked_htlc_txn[0], revoked_local_txn[0]); // Check that the unspent (of two) outputs on revoked_local_txn[0] is a P2WPKH: @@ -5267,10 +7224,23 @@ pub fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { assert_eq!(revoked_local_txn[0].output[unspent_local_txn_output].script_pubkey.len(), 2 + 20); // P2WPKH // A will generate justice tx from B's revoked commitment/HTLC tx - connect_block(&nodes[0], &create_dummy_block(nodes[0].best_block_hash(), 42, vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()])); + connect_block( + &nodes[0], + &create_dummy_block( + nodes[0].best_block_hash(), + 42, + vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()], + ), + ); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); // There will be 2 justice transactions, one on the revoked HTLC output on the commitment // transaction, and one on the revoked to_self output on the HTLC-success transaction. @@ -5320,16 +7290,18 @@ pub fn test_onchain_to_onchain_claim() { let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); // Ensure all nodes are at the same height - let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; + let node_max_height = + nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1); connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1); connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1); // Rebalance the network a bit by relaying one payment through all the channels ... - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 8000000); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); let commitment_tx = get_local_commitment_txn!(nodes[2], chan_2.2); check_spends!(commitment_tx[0], chan_2.3); nodes[2].node.claim_funds(payment_preimage); @@ -5344,27 +7316,48 @@ pub fn test_onchain_to_onchain_claim() { mine_transaction(&nodes[2], &commitment_tx[0]); check_closed_broadcast!(nodes[2], true); check_added_monitors!(nodes[2], 1); - check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); let c_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelMonitor: 1 (HTLC-Success tx) assert_eq!(c_txn.len(), 1); check_spends!(c_txn[0], commitment_tx[0]); - assert_eq!(c_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + c_txn[0].input[0].witness.clone().last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); assert!(c_txn[0].output[0].script_pubkey.is_p2wsh()); // revokeable output assert_eq!(c_txn[0].lock_time, LockTime::ZERO); // Success tx // So we broadcast C's commitment tx and HTLC-Success on B's chain, we should successfully be able to extract preimage and update downstream monitor - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![commitment_tx[0].clone(), c_txn[0].clone()])); + connect_block( + &nodes[1], + &create_dummy_block( + nodes[1].best_block_hash(), + 42, + vec![commitment_tx[0].clone(), c_txn[0].clone()], + ), + ); check_added_monitors!(nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {} + Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}, _ => panic!("Unexpected event"), } match events[1] { - Event::PaymentForwarded { total_fee_earned_msat, prev_channel_id, claim_from_onchain_tx, - next_channel_id, outbound_amount_forwarded_msat, .. + Event::PaymentForwarded { + total_fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, + .. } => { assert_eq!(total_fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, Some(chan_1.2)); @@ -5377,16 +7370,32 @@ pub fn test_onchain_to_onchain_claim() { check_added_monitors!(nodes[1], 1); let mut msg_events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 3); - let nodes_2_event = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut msg_events); - let nodes_0_event = remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut msg_events); + let nodes_2_event = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut msg_events); + let nodes_0_event = + remove_first_msg_event_to_node(&nodes[0].node.get_our_node_id(), &mut msg_events); match nodes_2_event { - MessageSendEvent::HandleError { action: ErrorAction::DisconnectPeer { .. }, node_id: _ } => {}, + MessageSendEvent::HandleError { + action: ErrorAction::DisconnectPeer { .. }, + node_id: _, + } => {}, _ => panic!("Unexpected event"), } match nodes_0_event { - MessageSendEvent::UpdateHTLCs { ref node_id, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => { + MessageSendEvent::UpdateHTLCs { + ref node_id, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fail_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); @@ -5405,7 +7414,13 @@ pub fn test_onchain_to_onchain_claim() { // Broadcast A's commitment tx on B's chain to see if we are able to claim inbound HTLC with our HTLC-Success tx let commitment_tx = get_local_commitment_txn!(nodes[0], chan_1.2); mine_transaction(&nodes[1], &commitment_tx[0]); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelMonitor: HTLC-Success tx assert_eq!(b_txn.len(), 1); @@ -5430,8 +7445,17 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { // It is now fixed, so we simply set the fee to the expected value here. let mut config = test_default_channel_config(); config.channel_config.forwarding_fee_base_msat = 196; - let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, - &[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 5, + &node_cfgs, + &[ + Some(config.clone()), + Some(config.clone()), + Some(config.clone()), + Some(config.clone()), + Some(config.clone()), + ], + ); let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs); // Create the required channels and route one HTLC from A to D and another from A to E. @@ -5440,20 +7464,34 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { create_announced_chan_between_nodes(&nodes, 2, 3); create_announced_chan_between_nodes(&nodes, 2, 4); - let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; + let node_max_height = + nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; connect_blocks(&nodes[0], node_max_height * 2 - nodes[0].best_block_info().1); connect_blocks(&nodes[1], node_max_height * 2 - nodes[1].best_block_info().1); connect_blocks(&nodes[2], node_max_height * 2 - nodes[2].best_block_info().1); connect_blocks(&nodes[3], node_max_height * 2 - nodes[3].best_block_info().1); connect_blocks(&nodes[4], node_max_height * 2 - nodes[4].best_block_info().1); - let (our_payment_preimage, duplicate_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], 900_000); + let (our_payment_preimage, duplicate_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], 900_000); - let payment_secret = nodes[4].node.create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, None).unwrap(); - let payment_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[4].node.bolt11_invoice_features()).unwrap(); + let payment_secret = nodes[4] + .node + .create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, None) + .unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[4].node.bolt11_invoice_features()) + .unwrap(); let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[4], payment_params, 800_000); - send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[4]]], 800_000, duplicate_payment_hash, payment_secret); + send_along_route_with_secret( + &nodes[0], + route, + &[&[&nodes[1], &nodes[2], &nodes[4]]], + 800_000, + duplicate_payment_hash, + payment_secret, + ); // Now mine C's commitment transaction on node B and mine enough blocks to get the HTLC timeout // transaction (which we'll split in two so that we can resolve the HTLCs differently). @@ -5465,7 +7503,13 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { mine_transaction(&nodes[1], &commitment_txn[0]); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[2].node.get_our_node_id()], + 100000 + ); // Confirm blocks until both HTLCs expire and get a transaction which times out one HTLC. connect_blocks(&nodes[1], TEST_FINAL_CLTV + config.channel_config.cltv_expiry_delta as u32); @@ -5484,10 +7528,12 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { assert_eq!(tx.input[1].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1); // Split the HTLC claim transaction into two, one for each HTLC. - if commitment_txn[0].output[tx.input[1].previous_output.vout as usize].value.to_sat() < 850 { + if commitment_txn[0].output[tx.input[1].previous_output.vout as usize].value.to_sat() < 850 + { tx.input.remove(1); } - if commitment_txn[0].output[tx.input[0].previous_output.vout as usize].value.to_sat() < 850 { + if commitment_txn[0].output[tx.input[0].previous_output.vout as usize].value.to_sat() < 850 + { tx.input.remove(0); } assert_eq!(tx.input.len(), 1); @@ -5499,7 +7545,10 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { expect_payment_claimed!(nodes[4], duplicate_payment_hash, 800_000); check_added_monitors!(nodes[4], 1); let updates = get_htlc_update_msgs!(nodes[4], nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_fulfill_htlc(nodes[4].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[2].node.handle_update_fulfill_htlc( + nodes[4].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); let _cs_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); expect_payment_forwarded!(nodes[2], nodes[1], nodes[4], Some(196), false, false); check_added_monitors!(nodes[2], 1); @@ -5510,7 +7559,13 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { // preimage). mine_transaction(&nodes[2], &commitment_txn[0]); check_added_monitors!(nodes[2], 1); - check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); check_closed_broadcast(&nodes[2], 1, true); let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); @@ -5520,23 +7575,42 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { assert_eq!(htlc_success_txn[0].input.len(), 1); // Note that the witness script lengths are one longer than our constant as the CLTV value went // to two bytes rather than one. - assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1); + assert_eq!( + htlc_success_txn[0].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + 1 + ); assert_eq!(htlc_success_txn[1].input.len(), 1); - assert_eq!(htlc_success_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1); - assert_ne!(htlc_success_txn[0].input[0].previous_output, htlc_success_txn[1].input[0].previous_output); + assert_eq!( + htlc_success_txn[1].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + 1 + ); + assert_ne!( + htlc_success_txn[0].input[0].previous_output, + htlc_success_txn[1].input[0].previous_output + ); - let htlc_success_tx_to_confirm = - if htlc_success_txn[0].input[0].previous_output == htlc_timeout_tx.input[0].previous_output { - &htlc_success_txn[1] - } else { - &htlc_success_txn[0] - }; - assert_ne!(htlc_success_tx_to_confirm.input[0].previous_output, htlc_timeout_tx.input[0].previous_output); + let htlc_success_tx_to_confirm = if htlc_success_txn[0].input[0].previous_output + == htlc_timeout_tx.input[0].previous_output + { + &htlc_success_txn[1] + } else { + &htlc_success_txn[0] + }; + assert_ne!( + htlc_success_tx_to_confirm.input[0].previous_output, + htlc_timeout_tx.input[0].previous_output + ); // Mine the HTLC timeout transaction on node B. mine_transaction(&nodes[1], &htlc_timeout_tx); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(htlc_updates.update_add_htlcs.is_empty()); assert_eq!(htlc_updates.update_fail_htlcs.len(), 1); @@ -5545,10 +7619,19 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { assert!(htlc_updates.update_fail_malformed_htlcs.is_empty()); check_added_monitors!(nodes[1], 1); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &htlc_updates.update_fail_htlcs[0], + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); commitment_signed_dance!(nodes[0], nodes[1], &htlc_updates.commitment_signed, false, true); - expect_payment_failed_with_update!(nodes[0], duplicate_payment_hash, false, chan_2.0.contents.short_channel_id, true); + expect_payment_failed_with_update!( + nodes[0], + duplicate_payment_hash, + false, + chan_2.0.contents.short_channel_id, + true + ); // Finally, give node B the HTLC success transaction and ensure it extracts the preimage to // provide to node A. @@ -5562,7 +7645,10 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() { assert!(updates.update_fail_malformed_htlcs.is_empty()); check_added_monitors!(nodes[1], 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], &updates.commitment_signed, false); expect_payment_sent(&nodes[0], our_payment_preimage, None, true, true); } @@ -5590,7 +7676,13 @@ pub fn test_dynamic_spendable_outputs_local_htlc_success_tx() { mine_transaction(&nodes[1], &local_txn[0]); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let events = nodes[1].node.get_and_clear_pending_msg_events(); match events[0] { MessageSendEvent::UpdateHTLCs { .. } => {}, @@ -5639,53 +7731,123 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno // It is now fixed, so we simply set the fee to the expected value here. let mut config = test_default_channel_config(); config.channel_config.forwarding_fee_base_msat = 196; - let node_chanmgrs = create_node_chanmgrs(6, &node_cfgs, - &[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 6, + &node_cfgs, + &[ + Some(config.clone()), + Some(config.clone()), + Some(config.clone()), + Some(config.clone()), + Some(config.clone()), + Some(config.clone()), + ], + ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); let _chan_0_2 = create_announced_chan_between_nodes(&nodes, 0, 2); let _chan_1_2 = create_announced_chan_between_nodes(&nodes, 1, 2); let chan_2_3 = create_announced_chan_between_nodes(&nodes, 2, 3); let chan_3_4 = create_announced_chan_between_nodes(&nodes, 3, 4); - let chan_3_5 = create_announced_chan_between_nodes(&nodes, 3, 5); + let chan_3_5 = create_announced_chan_between_nodes(&nodes, 3, 5); // Rebalance and check output sanity... send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000); send_payment(&nodes[1], &[&nodes[2], &nodes[3], &nodes[5]], 500000); assert_eq!(get_local_commitment_txn!(nodes[3], chan_2_3.2)[0].output.len(), 2); - let ds_dust_limit = nodes[3].node.per_peer_state.read().unwrap().get(&nodes[2].node.get_our_node_id()) - .unwrap().lock().unwrap().channel_by_id.get(&chan_2_3.2).unwrap().context().holder_dust_limit_satoshis; + let ds_dust_limit = nodes[3] + .node + .per_peer_state + .read() + .unwrap() + .get(&nodes[2].node.get_our_node_id()) + .unwrap() + .lock() + .unwrap() + .channel_by_id + .get(&chan_2_3.2) + .unwrap() + .context() + .holder_dust_limit_satoshis; // 0th HTLC: - let (_, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee - // 1st HTLC: - let (_, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee - let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], ds_dust_limit*1000); + let (_, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit * 1000); // not added < dust limit + HTLC tx fee + // 1st HTLC: + let (_, payment_hash_2, ..) = + route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit * 1000); // not added < dust limit + HTLC tx fee + let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], ds_dust_limit * 1000); // 2nd HTLC: - send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_1, nodes[5].node.create_inbound_payment_for_hash(payment_hash_1, None, 7200, None).unwrap()); // not added < dust limit + HTLC tx fee - // 3rd HTLC: - send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_2, nodes[5].node.create_inbound_payment_for_hash(payment_hash_2, None, 7200, None).unwrap()); // not added < dust limit + HTLC tx fee - // 4th HTLC: - let (_, payment_hash_3, ..) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000); + send_along_route_with_secret( + &nodes[1], + route.clone(), + &[&[&nodes[2], &nodes[3], &nodes[5]]], + ds_dust_limit * 1000, + payment_hash_1, + nodes[5].node.create_inbound_payment_for_hash(payment_hash_1, None, 7200, None).unwrap(), + ); // not added < dust limit + HTLC tx fee + // 3rd HTLC: + send_along_route_with_secret( + &nodes[1], + route, + &[&[&nodes[2], &nodes[3], &nodes[5]]], + ds_dust_limit * 1000, + payment_hash_2, + nodes[5].node.create_inbound_payment_for_hash(payment_hash_2, None, 7200, None).unwrap(), + ); // not added < dust limit + HTLC tx fee + // 4th HTLC: + let (_, payment_hash_3, ..) = + route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000); // 5th HTLC: - let (_, payment_hash_4, ..) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000); + let (_, payment_hash_4, ..) = + route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000); let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], 1000000); // 6th HTLC: - send_along_route_with_secret(&nodes[1], route.clone(), &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_3, nodes[5].node.create_inbound_payment_for_hash(payment_hash_3, None, 7200, None).unwrap()); + send_along_route_with_secret( + &nodes[1], + route.clone(), + &[&[&nodes[2], &nodes[3], &nodes[5]]], + 1000000, + payment_hash_3, + nodes[5].node.create_inbound_payment_for_hash(payment_hash_3, None, 7200, None).unwrap(), + ); // 7th HTLC: - send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_4, nodes[5].node.create_inbound_payment_for_hash(payment_hash_4, None, 7200, None).unwrap()); + send_along_route_with_secret( + &nodes[1], + route, + &[&[&nodes[2], &nodes[3], &nodes[5]]], + 1000000, + payment_hash_4, + nodes[5].node.create_inbound_payment_for_hash(payment_hash_4, None, 7200, None).unwrap(), + ); // 8th HTLC: - let (_, payment_hash_5, ..) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000); + let (_, payment_hash_5, ..) = + route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000); // 9th HTLC: - let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], ds_dust_limit*1000); - send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], ds_dust_limit*1000, payment_hash_5, nodes[5].node.create_inbound_payment_for_hash(payment_hash_5, None, 7200, None).unwrap()); // not added < dust limit + HTLC tx fee + let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], ds_dust_limit * 1000); + send_along_route_with_secret( + &nodes[1], + route, + &[&[&nodes[2], &nodes[3], &nodes[5]]], + ds_dust_limit * 1000, + payment_hash_5, + nodes[5].node.create_inbound_payment_for_hash(payment_hash_5, None, 7200, None).unwrap(), + ); // not added < dust limit + HTLC tx fee // 10th HTLC: - let (_, payment_hash_6, ..) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee - // 11th HTLC: + let (_, payment_hash_6, ..) = + route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit * 1000); // not added < dust limit + HTLC tx fee + // 11th HTLC: let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[5], 1000000); - send_along_route_with_secret(&nodes[1], route, &[&[&nodes[2], &nodes[3], &nodes[5]]], 1000000, payment_hash_6, nodes[5].node.create_inbound_payment_for_hash(payment_hash_6, None, 7200, None).unwrap()); + send_along_route_with_secret( + &nodes[1], + route, + &[&[&nodes[2], &nodes[3], &nodes[5]]], + 1000000, + payment_hash_6, + nodes[5].node.create_inbound_payment_for_hash(payment_hash_6, None, 7200, None).unwrap(), + ); // Double-check that six of the new HTLC were added // We now have six HTLCs pending over the dust limit and six HTLCs under the dust limit (ie, @@ -5711,10 +7873,22 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno check_added_monitors!(nodes[4], 1); let four_removes = get_htlc_update_msgs!(nodes[4], nodes[3].node.get_our_node_id()); - nodes[3].node.handle_update_fail_htlc(nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[0]); - nodes[3].node.handle_update_fail_htlc(nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[1]); - nodes[3].node.handle_update_fail_htlc(nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[2]); - nodes[3].node.handle_update_fail_htlc(nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[3]); + nodes[3].node.handle_update_fail_htlc( + nodes[4].node.get_our_node_id(), + &four_removes.update_fail_htlcs[0], + ); + nodes[3].node.handle_update_fail_htlc( + nodes[4].node.get_our_node_id(), + &four_removes.update_fail_htlcs[1], + ); + nodes[3].node.handle_update_fail_htlc( + nodes[4].node.get_our_node_id(), + &four_removes.update_fail_htlcs[2], + ); + nodes[3].node.handle_update_fail_htlc( + nodes[4].node.get_our_node_id(), + &four_removes.update_fail_htlcs[3], + ); commitment_signed_dance!(nodes[3], nodes[4], four_removes.commitment_signed, false); // Fail 3rd below-dust and 7th above-dust HTLCs @@ -5730,34 +7904,84 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno check_added_monitors!(nodes[5], 1); let two_removes = get_htlc_update_msgs!(nodes[5], nodes[3].node.get_our_node_id()); - nodes[3].node.handle_update_fail_htlc(nodes[5].node.get_our_node_id(), &two_removes.update_fail_htlcs[0]); - nodes[3].node.handle_update_fail_htlc(nodes[5].node.get_our_node_id(), &two_removes.update_fail_htlcs[1]); + nodes[3].node.handle_update_fail_htlc( + nodes[5].node.get_our_node_id(), + &two_removes.update_fail_htlcs[0], + ); + nodes[3].node.handle_update_fail_htlc( + nodes[5].node.get_our_node_id(), + &two_removes.update_fail_htlcs[1], + ); commitment_signed_dance!(nodes[3], nodes[5], two_removes.commitment_signed, false); let ds_prev_commitment_tx = get_local_commitment_txn!(nodes[3], chan_2_3.2); // After 4 and 2 removes respectively above in nodes[4] and nodes[5], nodes[3] should receive 6 PaymentForwardedFailed events let failed_destinations_3 = vec![ - HTLCDestination::NextHopChannel { node_id: Some(nodes[4].node.get_our_node_id()), channel_id: chan_3_4.2 }, - HTLCDestination::NextHopChannel { node_id: Some(nodes[4].node.get_our_node_id()), channel_id: chan_3_4.2 }, - HTLCDestination::NextHopChannel { node_id: Some(nodes[4].node.get_our_node_id()), channel_id: chan_3_4.2 }, - HTLCDestination::NextHopChannel { node_id: Some(nodes[4].node.get_our_node_id()), channel_id: chan_3_4.2 }, - HTLCDestination::NextHopChannel { node_id: Some(nodes[5].node.get_our_node_id()), channel_id: chan_3_5.2 }, - HTLCDestination::NextHopChannel { node_id: Some(nodes[5].node.get_our_node_id()), channel_id: chan_3_5.2 }, + HTLCDestination::NextHopChannel { + node_id: Some(nodes[4].node.get_our_node_id()), + channel_id: chan_3_4.2, + }, + HTLCDestination::NextHopChannel { + node_id: Some(nodes[4].node.get_our_node_id()), + channel_id: chan_3_4.2, + }, + HTLCDestination::NextHopChannel { + node_id: Some(nodes[4].node.get_our_node_id()), + channel_id: chan_3_4.2, + }, + HTLCDestination::NextHopChannel { + node_id: Some(nodes[4].node.get_our_node_id()), + channel_id: chan_3_4.2, + }, + HTLCDestination::NextHopChannel { + node_id: Some(nodes[5].node.get_our_node_id()), + channel_id: chan_3_5.2, + }, + HTLCDestination::NextHopChannel { + node_id: Some(nodes[5].node.get_our_node_id()), + channel_id: chan_3_5.2, + }, ]; expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], failed_destinations_3); check_added_monitors!(nodes[3], 1); let six_removes = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[0]); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[1]); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[2]); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[3]); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[4]); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[5]); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &six_removes.update_fail_htlcs[0], + ); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &six_removes.update_fail_htlcs[1], + ); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &six_removes.update_fail_htlcs[2], + ); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &six_removes.update_fail_htlcs[3], + ); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &six_removes.update_fail_htlcs[4], + ); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &six_removes.update_fail_htlcs[5], + ); if deliver_last_raa { commitment_signed_dance!(nodes[2], nodes[3], six_removes.commitment_signed, false); } else { - let _cs_last_raa = commitment_signed_dance!(nodes[2], nodes[3], six_removes.commitment_signed, false, true, false, true); + let _cs_last_raa = commitment_signed_dance!( + nodes[2], + nodes[3], + six_removes.commitment_signed, + false, + true, + false, + true + ); } // D's latest commitment transaction now contains 1st + 2nd + 9th HTLCs (implicitly, they're @@ -5787,7 +8011,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno events.last().clone().unwrap() }; match close_event { - Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {} + Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}, _ => panic!("Unexpected event"), } @@ -5796,13 +8020,31 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno if deliver_last_raa { expect_pending_htlcs_forwardable_from_events!(nodes[2], events[1..2], true); - let expected_destinations: Vec = repeat(HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 }).take(3).collect(); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), expected_destinations); + let expected_destinations: Vec = repeat(HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_2_3.2, + }) + .take(3) + .collect(); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + expected_destinations + ); } else { let expected_destinations: Vec = if announce_latest { - repeat(HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 }).take(9).collect() + repeat(HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_2_3.2, + }) + .take(9) + .collect() } else { - repeat(HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 }).take(6).collect() + repeat(HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_2_3.2, + }) + .take(6) + .collect() }; expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], expected_destinations); @@ -5820,28 +8062,61 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno let target = if *node_id == nodes[0].node.get_our_node_id() { // If announce_latest, expect 0th, 1st, 4th, 8th, 10th HTLCs, else only 0th, 1st, 10th below-dust HTLCs for htlc in &updates.update_fail_htlcs { - assert!(htlc.htlc_id == 1 || htlc.htlc_id == 2 || htlc.htlc_id == 6 || if announce_latest { htlc.htlc_id == 3 || htlc.htlc_id == 5 } else { false }); + assert!( + htlc.htlc_id == 1 + || htlc.htlc_id == 2 || htlc.htlc_id == 6 + || if announce_latest { + htlc.htlc_id == 3 || htlc.htlc_id == 5 + } else { + false + } + ); } - assert_eq!(updates.update_fail_htlcs.len(), if announce_latest { 5 } else { 3 }); + assert_eq!( + updates.update_fail_htlcs.len(), + if announce_latest { 5 } else { 3 } + ); assert!(!a_done); a_done = true; &nodes[0] } else { // If announce_latest, expect 2nd, 3rd, 7th, 9th HTLCs, else only 2nd, 3rd, 9th below-dust HTLCs for htlc in &updates.update_fail_htlcs { - assert!(htlc.htlc_id == 1 || htlc.htlc_id == 2 || htlc.htlc_id == 5 || if announce_latest { htlc.htlc_id == 4 } else { false }); + assert!( + htlc.htlc_id == 1 + || htlc.htlc_id == 2 || htlc.htlc_id == 5 + || if announce_latest { htlc.htlc_id == 4 } else { false } + ); } assert_eq!(*node_id, nodes[1].node.get_our_node_id()); - assert_eq!(updates.update_fail_htlcs.len(), if announce_latest { 4 } else { 3 }); + assert_eq!( + updates.update_fail_htlcs.len(), + if announce_latest { 4 } else { 3 } + ); &nodes[1] }; - target.node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); - target.node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[1]); - target.node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[2]); + target.node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); + target.node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fail_htlcs[1], + ); + target.node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fail_htlcs[2], + ); if announce_latest { - target.node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[3]); + target.node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fail_htlcs[3], + ); if *node_id == nodes[0].node.get_our_node_id() { - target.node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[4]); + target.node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fail_htlcs[4], + ); } } commitment_signed_dance!(target, nodes[2], updates.commitment_signed, false, true); @@ -5855,7 +8130,13 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno let mut as_faileds = new_hash_set(); let mut as_updates = 0; for event in as_events.iter() { - if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref failure, .. } = event { + if let &Event::PaymentPathFailed { + ref payment_hash, + ref payment_failed_permanently, + ref failure, + .. + } = event + { assert!(as_faileds.insert(*payment_hash)); if *payment_hash != payment_hash_2 { assert_eq!(*payment_failed_permanently, deliver_last_raa); @@ -5866,7 +8147,9 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno as_updates += 1; } } else if let &Event::PaymentFailed { .. } = event { - } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } } assert!(as_faileds.contains(&payment_hash_1)); assert!(as_faileds.contains(&payment_hash_2)); @@ -5881,7 +8164,13 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno let mut bs_faileds = new_hash_set(); let mut bs_updates = 0; for event in bs_events.iter() { - if let &Event::PaymentPathFailed { ref payment_hash, ref payment_failed_permanently, ref failure, .. } = event { + if let &Event::PaymentPathFailed { + ref payment_hash, + ref payment_failed_permanently, + ref failure, + .. + } = event + { assert!(bs_faileds.insert(*payment_hash)); if *payment_hash != payment_hash_1 && *payment_hash != payment_hash_5 { assert_eq!(*payment_failed_permanently, deliver_last_raa); @@ -5892,7 +8181,9 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno bs_updates += 1; } } else if let &Event::PaymentFailed { .. } = event { - } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } } assert!(bs_faileds.contains(&payment_hash_1)); assert!(bs_faileds.contains(&payment_hash_2)); @@ -5905,8 +8196,26 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno // get a NetworkUpdate. A should have gotten 4 HTLCs which were failed-back due to // unknown-preimage-etc, B should have gotten 2. Thus, in the // announce_latest && deliver_last_raa case, we should have 5-4=1 and 4-2=2 NetworkUpdates. - assert_eq!(as_updates, if deliver_last_raa { 1 } else if !announce_latest { 3 } else { 5 }); - assert_eq!(bs_updates, if deliver_last_raa { 2 } else if !announce_latest { 3 } else { 4 }); + assert_eq!( + as_updates, + if deliver_last_raa { + 1 + } else if !announce_latest { + 3 + } else { + 5 + } + ); + assert_eq!( + bs_updates, + if deliver_last_raa { + 2 + } else if !announce_latest { + 3 + } else { + 4 + } + ); } #[xtest(feature = "_externalize_tests")] @@ -5936,7 +8245,7 @@ pub fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() { // Create some initial channels let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); - let (_, our_payment_hash, ..) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000); + let (_, our_payment_hash, ..) = route_payment(&nodes[0], &vec![&nodes[1]][..], 9000000); let local_txn = get_local_commitment_txn!(nodes[0], chan_1.2); assert_eq!(local_txn[0].input.len(), 1); check_spends!(local_txn[0], chan_1.3); @@ -5945,7 +8254,13 @@ pub fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() { mine_transaction(&nodes[0], &local_txn[0]); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[0], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires let htlc_timeout = { @@ -5970,8 +8285,10 @@ pub fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() { assert_eq!(spend_txn[1].input[0].sequence.0, BREAKDOWN_TIMEOUT as u32); assert_eq!(spend_txn[2].input.len(), 2); check_spends!(spend_txn[2], local_txn[0], htlc_timeout); - assert!(spend_txn[2].input[0].sequence.0 == BREAKDOWN_TIMEOUT as u32 || - spend_txn[2].input[1].sequence.0 == BREAKDOWN_TIMEOUT as u32); + assert!( + spend_txn[2].input[0].sequence.0 == BREAKDOWN_TIMEOUT as u32 + || spend_txn[2].input[1].sequence.0 == BREAKDOWN_TIMEOUT as u32 + ); } #[xtest(feature = "_externalize_tests")] @@ -5986,12 +8303,32 @@ pub fn test_key_derivation_params() { // We manually create the node configuration to backup the seed. let seed = [42; 32]; let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); - let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, &chanmon_cfgs[0].persister, &keys_manager); + let chain_monitor = test_utils::TestChainMonitor::new( + Some(&chanmon_cfgs[0].chain_source), + &chanmon_cfgs[0].tx_broadcaster, + &chanmon_cfgs[0].logger, + &chanmon_cfgs[0].fee_estimator, + &chanmon_cfgs[0].persister, + &keys_manager, + ); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &chanmon_cfgs[0].logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph.clone(), &chanmon_cfgs[0].logger, &scorer); + let router = + test_utils::TestRouter::new(network_graph.clone(), &chanmon_cfgs[0].logger, &scorer); let message_router = test_utils::TestMessageRouter::new(network_graph.clone(), &keys_manager); - let node = NodeCfg { chain_source: &chanmon_cfgs[0].chain_source, logger: &chanmon_cfgs[0].logger, tx_broadcaster: &chanmon_cfgs[0].tx_broadcaster, fee_estimator: &chanmon_cfgs[0].fee_estimator, router, message_router, chain_monitor, keys_manager: &keys_manager, network_graph, node_seed: seed, override_init_features: alloc::rc::Rc::new(core::cell::RefCell::new(None)) }; + let node = NodeCfg { + chain_source: &chanmon_cfgs[0].chain_source, + logger: &chanmon_cfgs[0].logger, + tx_broadcaster: &chanmon_cfgs[0].tx_broadcaster, + fee_estimator: &chanmon_cfgs[0].fee_estimator, + router, + message_router, + chain_monitor, + keys_manager: &keys_manager, + network_graph, + node_seed: seed, + override_init_features: alloc::rc::Rc::new(core::cell::RefCell::new(None)), + }; let mut node_cfgs = create_node_cfgs(3, &chanmon_cfgs); node_cfgs.remove(0); node_cfgs.insert(0, node); @@ -6007,24 +8344,32 @@ pub fn test_key_derivation_params() { assert_ne!(chan_0.3.output[0].script_pubkey, chan_1.3.output[0].script_pubkey); // Ensure all nodes are at the same height - let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; + let node_max_height = + nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1); connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1); connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1); - let (_, our_payment_hash, ..) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000); + let (_, our_payment_hash, ..) = route_payment(&nodes[0], &vec![&nodes[1]][..], 9000000); let local_txn_0 = get_local_commitment_txn!(nodes[0], chan_0.2); let local_txn_1 = get_local_commitment_txn!(nodes[0], chan_1.2); assert_eq!(local_txn_1[0].input.len(), 1); check_spends!(local_txn_1[0], chan_1.3); // We check funding pubkey are unique - let (from_0_funding_key_0, from_0_funding_key_1) = (PublicKey::from_slice(&local_txn_0[0].input[0].witness.to_vec()[3][2..35]), PublicKey::from_slice(&local_txn_0[0].input[0].witness.to_vec()[3][36..69])); - let (from_1_funding_key_0, from_1_funding_key_1) = (PublicKey::from_slice(&local_txn_1[0].input[0].witness.to_vec()[3][2..35]), PublicKey::from_slice(&local_txn_1[0].input[0].witness.to_vec()[3][36..69])); + let (from_0_funding_key_0, from_0_funding_key_1) = ( + PublicKey::from_slice(&local_txn_0[0].input[0].witness.to_vec()[3][2..35]), + PublicKey::from_slice(&local_txn_0[0].input[0].witness.to_vec()[3][36..69]), + ); + let (from_1_funding_key_0, from_1_funding_key_1) = ( + PublicKey::from_slice(&local_txn_1[0].input[0].witness.to_vec()[3][2..35]), + PublicKey::from_slice(&local_txn_1[0].input[0].witness.to_vec()[3][36..69]), + ); if from_0_funding_key_0 == from_1_funding_key_0 - || from_0_funding_key_0 == from_1_funding_key_1 - || from_0_funding_key_1 == from_1_funding_key_0 - || from_0_funding_key_1 == from_1_funding_key_1 { + || from_0_funding_key_0 == from_1_funding_key_1 + || from_0_funding_key_1 == from_1_funding_key_0 + || from_0_funding_key_1 == from_1_funding_key_1 + { panic!("Funding pubkeys aren't unique"); } @@ -6033,7 +8378,13 @@ pub fn test_key_derivation_params() { connect_blocks(&nodes[0], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); let htlc_timeout = { let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); @@ -6058,8 +8409,10 @@ pub fn test_key_derivation_params() { assert_eq!(spend_txn[1].input[0].sequence.0, BREAKDOWN_TIMEOUT as u32); assert_eq!(spend_txn[2].input.len(), 2); check_spends!(spend_txn[2], local_txn_1[0], htlc_timeout); - assert!(spend_txn[2].input[0].sequence.0 == BREAKDOWN_TIMEOUT as u32 || - spend_txn[2].input[1].sequence.0 == BREAKDOWN_TIMEOUT as u32); + assert!( + spend_txn[2].input[0].sequence.0 == BREAKDOWN_TIMEOUT as u32 + || spend_txn[2].input[1].sequence.0 == BREAKDOWN_TIMEOUT as u32 + ); } #[xtest(feature = "_externalize_tests")] @@ -6071,11 +8424,17 @@ pub fn test_static_output_closing_tx() { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 8000000); let closing_tx = close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true).2; mine_transaction(&nodes[0], &closing_tx); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); let spend_txn = check_spendable_outputs!(nodes[0], node_cfgs[0].keys_manager); @@ -6083,7 +8442,13 @@ pub fn test_static_output_closing_tx() { check_spends!(spend_txn[0], closing_tx); mine_transaction(&nodes[1], &closing_tx); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); let spend_txn = check_spendable_outputs!(nodes[1], node_cfgs[1].keys_manager); @@ -6098,7 +8463,8 @@ fn do_htlc_claim_local_commitment_only(use_dust: bool) { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], if use_dust { 50000 } else { 3_000_000 }); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], if use_dust { 50000 } else { 3_000_000 }); // Claim the payment, but don't deliver A's commitment_signed, resulting in the HTLC only being // present in B's local commitment transaction, but none of A's commitment transactions. @@ -6107,10 +8473,16 @@ fn do_htlc_claim_local_commitment_only(use_dust: bool) { expect_payment_claimed!(nodes[1], payment_hash, if use_dust { 50000 } else { 3_000_000 }); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_updates.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_updates.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_updates.commitment_signed, + ); check_added_monitors!(nodes[0], 1); let as_updates = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_updates.0); @@ -6122,10 +8494,21 @@ fn do_htlc_claim_local_commitment_only(use_dust: bool) { connect_block(&nodes[1], &block); block.header.prev_blockhash = block.block_hash(); } - test_txn_broadcast(&nodes[1], &chan, None, if use_dust { HTLCType::NONE } else { HTLCType::SUCCESS }); + test_txn_broadcast( + &nodes[1], + &chan, + None, + if use_dust { HTLCType::NONE } else { HTLCType::SUCCESS }, + ); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::HTLCsTimedOut, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HTLCsTimedOut, + [nodes[0].node.get_our_node_id()], + 100000 + ); } fn do_htlc_claim_current_remote_commitment_only(use_dust: bool) { @@ -6135,9 +8518,17 @@ fn do_htlc_claim_current_remote_commitment_only(use_dust: bool) { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], if use_dust { 50000 } else { 3000000 }); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], if use_dust { 50000 } else { 3000000 }); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let _as_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -6149,14 +8540,22 @@ fn do_htlc_claim_current_remote_commitment_only(use_dust: bool) { let starting_block = nodes[1].best_block_info(); let mut block = create_dummy_block(starting_block.0, 42, Vec::new()); - for _ in starting_block.1 + 1..TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + starting_block.1 + 2 { + for _ in + starting_block.1 + 1..TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + starting_block.1 + 2 + { connect_block(&nodes[0], &block); block.header.prev_blockhash = block.block_hash(); } test_txn_broadcast(&nodes[0], &chan, None, HTLCType::NONE); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HTLCsTimedOut, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HTLCsTimedOut, + [nodes[1].node.get_our_node_id()], + 100000 + ); } fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no_close: bool) { @@ -6173,19 +8572,33 @@ fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no let htlc_value = if use_dust { 50000 } else { 3000000 }; let (_, our_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], htlc_value); nodes[1].node.fail_htlc_backwards(&our_payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }] + ); check_added_monitors!(nodes[1], 1); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_updates.commitment_signed); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_updates.commitment_signed, + ); check_added_monitors!(nodes[0], 1); let as_updates = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_updates.0); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_updates.1); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_updates.1); check_added_monitors!(nodes[1], 1); - let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_revoke_and_ack = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); if check_revoke_no_close { nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_revoke_and_ack); @@ -6194,7 +8607,9 @@ fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no let starting_block = nodes[1].best_block_info(); let mut block = create_dummy_block(starting_block.0, 42, Vec::new()); - for _ in starting_block.1 + 1..TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + CHAN_CONFIRM_DEPTH + 2 { + for _ in + starting_block.1 + 1..TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + CHAN_CONFIRM_DEPTH + 2 + { connect_block(&nodes[0], &block); block.header.prev_blockhash = block.block_hash(); } @@ -6202,7 +8617,13 @@ fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no test_txn_broadcast(&nodes[0], &chan, None, HTLCType::NONE); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HTLCsTimedOut, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HTLCsTimedOut, + [nodes[1].node.get_our_node_id()], + 100000 + ); } else { expect_payment_failed!(nodes[0], our_payment_hash, true); } @@ -6238,7 +8659,8 @@ pub fn htlc_claim_single_commitment_only_b() { #[xtest(feature = "_externalize_tests")] #[should_panic] -pub fn bolt2_open_channel_sending_node_checks_part1() { //This test needs to be on its own as we are catching a panic +pub fn bolt2_open_channel_sending_node_checks_part1() { + //This test needs to be on its own as we are catching a panic let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); @@ -6249,16 +8671,42 @@ pub fn bolt2_open_channel_sending_node_checks_part1() { //This test needs to be } // BOLT #2 spec: Sending node must ensure temporary_channel_id is unique from any other channel ID with the same peer. - let channel_value_satoshis=10000; - let push_msat=10001; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).unwrap(); - let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &node0_to_1_send_open_channel); - get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); - - // Create a second channel with the same random values. This used to panic due to a colliding + let channel_value_satoshis = 10000; + let push_msat = 10001; + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_satoshis, + push_msat, + 42, + None, + None, + ) + .unwrap(); + let node0_to_1_send_open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); + nodes[1] + .node + .handle_open_channel(nodes[0].node.get_our_node_id(), &node0_to_1_send_open_channel); + get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + + // Create a second channel with the same random values. This used to panic due to a colliding // channel_id, but now panics due to a colliding outbound SCID alias. - assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).is_err()); + assert!(nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_satoshis, + push_msat, + 42, + None, + None + ) + .is_err()); } #[xtest(feature = "_externalize_tests")] @@ -6269,41 +8717,93 @@ pub fn bolt2_open_channel_sending_node_checks_part2() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // BOLT #2 spec: Sending node must set funding_satoshis to less than 2^24 satoshis - let channel_value_satoshis=2^24; - let push_msat=10001; - assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).is_err()); + let channel_value_satoshis = 2 ^ 24; + let push_msat = 10001; + assert!(nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_satoshis, + push_msat, + 42, + None, + None + ) + .is_err()); // BOLT #2 spec: Sending node must set push_msat to equal or less than 1000 * funding_satoshis - let channel_value_satoshis=10000; + let channel_value_satoshis = 10000; // Test when push_msat is equal to 1000 * funding_satoshis. - let push_msat=1000*channel_value_satoshis+1; - assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).is_err()); + let push_msat = 1000 * channel_value_satoshis + 1; + assert!(nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_satoshis, + push_msat, + 42, + None, + None + ) + .is_err()); // BOLT #2 spec: Sending node must set set channel_reserve_satoshis greater than or equal to dust_limit_satoshis - let channel_value_satoshis=10000; - let push_msat=10001; - assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).is_ok()); //Create a valid channel - let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - assert!(node0_to_1_send_open_channel.channel_reserve_satoshis>=node0_to_1_send_open_channel.common_fields.dust_limit_satoshis); + let channel_value_satoshis = 10000; + let push_msat = 10001; + assert!(nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_satoshis, + push_msat, + 42, + None, + None + ) + .is_ok()); //Create a valid channel + let node0_to_1_send_open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); + assert!( + node0_to_1_send_open_channel.channel_reserve_satoshis + >= node0_to_1_send_open_channel.common_fields.dust_limit_satoshis + ); // BOLT #2 spec: Sending node must set undefined bits in channel_flags to 0 // Only the least-significant bit of channel_flags is currently defined resulting in channel_flags only having one of two possible states 0 or 1 - assert!(node0_to_1_send_open_channel.common_fields.channel_flags<=1); + assert!(node0_to_1_send_open_channel.common_fields.channel_flags <= 1); // BOLT #2 spec: Sending node should set to_self_delay sufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehaviour by the receiver. - assert!(BREAKDOWN_TIMEOUT>0); - assert!(node0_to_1_send_open_channel.common_fields.to_self_delay==BREAKDOWN_TIMEOUT); + assert!(BREAKDOWN_TIMEOUT > 0); + assert!(node0_to_1_send_open_channel.common_fields.to_self_delay == BREAKDOWN_TIMEOUT); // BOLT #2 spec: Sending node must ensure the chain_hash value identifies the chain it wishes to open the channel within. let chain_hash = ChainHash::using_genesis_block(Network::Testnet); assert_eq!(node0_to_1_send_open_channel.common_fields.chain_hash, chain_hash); // BOLT #2 spec: Sending node must set funding_pubkey, revocation_basepoint, htlc_basepoint, payment_basepoint, and delayed_payment_basepoint to valid DER-encoded, compressed, secp256k1 pubkeys. - assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.funding_pubkey.serialize()).is_ok()); - assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.revocation_basepoint.serialize()).is_ok()); - assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.htlc_basepoint.serialize()).is_ok()); - assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.payment_basepoint.serialize()).is_ok()); - assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.common_fields.delayed_payment_basepoint.serialize()).is_ok()); + assert!(PublicKey::from_slice( + &node0_to_1_send_open_channel.common_fields.funding_pubkey.serialize() + ) + .is_ok()); + assert!(PublicKey::from_slice( + &node0_to_1_send_open_channel.common_fields.revocation_basepoint.serialize() + ) + .is_ok()); + assert!(PublicKey::from_slice( + &node0_to_1_send_open_channel.common_fields.htlc_basepoint.serialize() + ) + .is_ok()); + assert!(PublicKey::from_slice( + &node0_to_1_send_open_channel.common_fields.payment_basepoint.serialize() + ) + .is_ok()); + assert!(PublicKey::from_slice( + &node0_to_1_send_open_channel.common_fields.delayed_payment_basepoint.serialize() + ) + .is_ok()); } #[xtest(feature = "_externalize_tests")] @@ -6313,22 +8813,42 @@ pub fn bolt2_open_channel_sane_dust_limit() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let channel_value_satoshis=1000000; - let push_msat=10001; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None, None).unwrap(); - let mut node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let channel_value_satoshis = 1000000; + let push_msat = 10001; + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + channel_value_satoshis, + push_msat, + 42, + None, + None, + ) + .unwrap(); + let mut node0_to_1_send_open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); node0_to_1_send_open_channel.common_fields.dust_limit_satoshis = 547; node0_to_1_send_open_channel.channel_reserve_satoshis = 100001; - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &node0_to_1_send_open_channel); + nodes[1] + .node + .handle_open_channel(nodes[0].node.get_our_node_id(), &node0_to_1_send_open_channel); let events = nodes[1].node.get_and_clear_pending_msg_events(); let err_msg = match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => { - msg.clone() - }, + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id: _, + } => msg.clone(), _ => panic!("Unexpected event"), }; - assert_eq!(err_msg.data, "dust_limit_satoshis (547) is greater than the implementation limit (546)"); + assert_eq!( + err_msg.data, + "dust_limit_satoshis (547) is greater than the implementation limit (546)" + ); } // Test that if we fail to send an HTLC that is being freed from the holding cell, and the HTLC @@ -6355,9 +8875,10 @@ pub fn test_fail_holding_cell_htlc_upon_free() { let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let (update_msg, commitment_signed) = match events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { - (update_fee.as_ref(), commitment_signed) - }, + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, + .. + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; @@ -6369,17 +8890,28 @@ pub fn test_fail_holding_cell_htlc_upon_free() { let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan.2); // 2* and +1 HTLCs on the commit tx fee calculation for the fee spike reserve. - let max_can_send = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send); + let max_can_send = + 5000000 - channel_reserve - 2 * commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send); // Send a payment which passes reserve checks but gets stuck in the holding cell. - nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2); assert_eq!(chan_stat.holding_cell_outbound_amount_msat, max_can_send); // Flush the pending fee update. - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); let (as_revoke_and_ack, _) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &as_revoke_and_ack); @@ -6390,13 +8922,24 @@ pub fn test_fail_holding_cell_htlc_upon_free() { // us to surface its failure to the user. chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2); assert_eq!(chan_stat.holding_cell_outbound_amount_msat, 0); - nodes[0].logger.assert_log("lightning::ln::channel", format!("Freeing holding cell with 1 HTLC updates in channel {}", chan.2), 1); + nodes[0].logger.assert_log( + "lightning::ln::channel", + format!("Freeing holding cell with 1 HTLC updates in channel {}", chan.2), + 1, + ); // Check that the payment failed to be sent out. let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match &events[0] { - &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, failure: PathFailure::OnPath { network_update: None }, ref short_channel_id, .. } => { + &Event::PaymentPathFailed { + ref payment_id, + ref payment_hash, + ref payment_failed_permanently, + failure: PathFailure::OnPath { network_update: None }, + ref short_channel_id, + .. + } => { assert_eq!(PaymentId(our_payment_hash.0), *payment_id.as_ref().unwrap()); assert_eq!(our_payment_hash.clone(), *payment_hash); assert_eq!(*payment_failed_permanently, false); @@ -6435,9 +8978,10 @@ pub fn test_free_and_fail_holding_cell_htlcs() { let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let (update_msg, commitment_signed) = match events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { - (update_fee.as_ref(), commitment_signed) - }, + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, + .. + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; @@ -6450,27 +8994,51 @@ pub fn test_free_and_fail_holding_cell_htlcs() { // 2* and +1 HTLCs on the commit tx fee calculation for the fee spike reserve. let amt_1 = 20000; - let amt_2 = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features) - amt_1; - let (route_1, payment_hash_1, payment_preimage_1, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], amt_1); - let (route_2, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], amt_2); + let amt_2 = 5000000 + - channel_reserve + - 2 * commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features) + - amt_1; + let (route_1, payment_hash_1, payment_preimage_1, payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], amt_1); + let (route_2, payment_hash_2, _, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], amt_2); // Send 2 payments which pass reserve checks but get stuck in the holding cell. - nodes[0].node.send_payment_with_route(route_1, payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route_1, + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2); assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1); let payment_id_2 = PaymentId(nodes[0].keys_manager.get_secure_random_bytes()); - nodes[0].node.send_payment_with_route(route_2.clone(), payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), payment_id_2).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route_2.clone(), + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + payment_id_2, + ) + .unwrap(); chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2); assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1 + amt_2); // Flush the pending fee update. - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); - let (revoke_and_ack, commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), commitment_signed); + let (revoke_and_ack, commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &revoke_and_ack); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); check_added_monitors!(nodes[0], 2); // Upon receipt of the RAA, there will be an attempt to resend the holding cell HTLCs, @@ -6478,13 +9046,24 @@ pub fn test_free_and_fail_holding_cell_htlcs() { // to surface its failure to the user. The first payment should succeed. chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2); assert_eq!(chan_stat.holding_cell_outbound_amount_msat, 0); - nodes[0].logger.assert_log("lightning::ln::channel", format!("Freeing holding cell with 2 HTLC updates in channel {}", chan.2), 1); + nodes[0].logger.assert_log( + "lightning::ln::channel", + format!("Freeing holding cell with 2 HTLC updates in channel {}", chan.2), + 1, + ); // Check that the second payment failed to be sent out. let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match &events[0] { - &Event::PaymentPathFailed { ref payment_id, ref payment_hash, ref payment_failed_permanently, failure: PathFailure::OnPath { network_update: None }, ref short_channel_id, .. } => { + &Event::PaymentPathFailed { + ref payment_id, + ref payment_hash, + ref payment_failed_permanently, + failure: PathFailure::OnPath { network_update: None }, + ref short_channel_id, + .. + } => { assert_eq!(payment_id_2, *payment_id.as_ref().unwrap()); assert_eq!(payment_hash_2.clone(), *payment_hash); assert_eq!(*payment_failed_permanently, false); @@ -6531,7 +9110,10 @@ pub fn test_free_and_fail_holding_cell_htlcs() { expect_payment_claimed!(nodes[1], payment_hash_1, amt_1); let update_msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_msgs.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &update_msgs.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], update_msgs.commitment_signed, false, true); expect_payment_sent!(nodes[0], payment_preimage_1); } @@ -6548,7 +9130,11 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() { let mut config = test_default_channel_config(); config.channel_config.forwarding_fee_base_msat = 0; config.channel_config.forwarding_fee_proportional_millionths = 0; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(config.clone()), Some(config.clone()), Some(config.clone())], + ); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000); let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000); @@ -6565,9 +9151,10 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() { let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let (update_msg, commitment_signed) = match events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { - (update_fee.as_ref(), commitment_signed) - }, + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, + .. + } => (update_fee.as_ref(), commitment_signed), _ => panic!("Unexpected event"), }; @@ -6579,11 +9166,20 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() { let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan_0_1.2); // Send a payment which passes reserve checks but gets stuck in the holding cell. - let max_can_send = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], max_can_send); + let max_can_send = + 5000000 - channel_reserve - 2 * commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], max_can_send); let payment_event = { - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -6600,11 +9196,16 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() { assert_eq!(chan_stat.holding_cell_outbound_amount_msat, max_can_send); // Flush the pending fee update. - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), commitment_signed); - let (raa, commitment_signed) = get_revoke_commit_msgs!(nodes[2], nodes[1].node.get_our_node_id()); + nodes[2] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), commitment_signed); + let (raa, commitment_signed) = + get_revoke_commit_msgs!(nodes[2], nodes[1].node.get_our_node_id()); check_added_monitors!(nodes[2], 1); nodes[1].node.handle_revoke_and_ack(nodes[2].node.get_our_node_id(), &raa); - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &commitment_signed); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &commitment_signed); check_added_monitors!(nodes[1], 2); // A final RAA message is generated to finalize the fee update. @@ -6612,9 +9213,7 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() { assert_eq!(events.len(), 1); let raa_msg = match &events[0] { - &MessageSendEvent::SendRevokeAndACK { ref msg, .. } => { - msg.clone() - }, + &MessageSendEvent::SendRevokeAndACK { ref msg, .. } => msg.clone(), _ => panic!("Unexpected event"), }; @@ -6650,13 +9249,18 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() { // Pass the failure messages back to nodes[0]. nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &fail_msg); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &commitment_signed); // Complete the HTLC failure+removal process. - let (raa, commitment_signed) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (raa, commitment_signed) = + get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); check_added_monitors!(nodes[0], 1); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &raa); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commitment_signed); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &commitment_signed); check_added_monitors!(nodes[1], 2); let final_raa_event = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(final_raa_event.len(), 1); @@ -6665,7 +9269,13 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() { _ => panic!("Unexpected event"), }; nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &raa); - expect_payment_failed_with_update!(nodes[0], our_payment_hash, false, chan_1_2.0.contents.short_channel_id, false); + expect_payment_failed_with_update!( + nodes[0], + our_payment_hash, + false, + chan_1_2.0.contents.short_channel_id, + false + ); check_added_monitors!(nodes[0], 1); } @@ -6680,8 +9290,10 @@ pub fn test_payment_route_reaching_same_channel_twice() { let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 0) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); - let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000); + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); + let (mut route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000); // Extend the path by itself, essentially simulating route going through same channel twice let cloned_hops = route.paths[0].hops.clone(); @@ -6707,12 +9319,22 @@ pub fn test_update_add_htlc_bolt2_sender_value_below_minimum_msat() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000); - let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000); + let (mut route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100000); route.paths[0].hops[0].fee_msat = 100; - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -6725,7 +9347,8 @@ pub fn test_update_add_htlc_bolt2_sender_zero_value_msat() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000); - let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000); + let (mut route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100000); route.paths[0].hops[0].fee_msat = 0; unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)), @@ -6733,7 +9356,11 @@ pub fn test_update_add_htlc_bolt2_sender_zero_value_msat() { assert_eq!(err, "Cannot send 0-msat HTLC")); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - nodes[0].logger.assert_log_contains("lightning::ln::channelmanager", "Cannot send 0-msat HTLC", 2); + nodes[0].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Cannot send 0-msat HTLC", + 2, + ); } #[xtest(feature = "_externalize_tests")] @@ -6745,19 +9372,40 @@ pub fn test_update_add_htlc_bolt2_receiver_zero_value_msat() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); updates.update_add_htlcs[0].amount_msat = 0; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); - nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Remote side tried to send a 0-msat HTLC", 3); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Remote side tried to send a 0-msat HTLC", + 3, + ); check_closed_broadcast!(nodes[1], true).unwrap(); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "Remote side tried to send a 0-msat HTLC".to_string() }, - [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { + err: "Remote side tried to send a 0-msat HTLC".to_string() + }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -6771,8 +9419,10 @@ pub fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() { let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 0) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); - let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000); + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); + let (mut route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000); route.paths[0].hops.last_mut().unwrap().cltv_expiry_delta = 500000001; unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) @@ -6790,37 +9440,74 @@ pub fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increme let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0); - let max_accepted_htlcs = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id()) - .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().context().counterparty_max_accepted_htlcs as u64; + let max_accepted_htlcs = nodes[1] + .node + .per_peer_state + .read() + .unwrap() + .get(&nodes[0].node.get_our_node_id()) + .unwrap() + .lock() + .unwrap() + .channel_by_id + .get(&chan.2) + .unwrap() + .context() + .counterparty_max_accepted_htlcs as u64; // Fetch a route in advance as we will be unable to once we're unable to send. - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100000); for i in 0..max_accepted_htlcs { - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100000); let payment_event = { - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.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); - if let MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate{ update_add_htlcs: ref htlcs, .. }, } = events[0] { + if let MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: msgs::CommitmentUpdate { update_add_htlcs: ref htlcs, .. }, + } = events[0] + { assert_eq!(htlcs[0].htlc_id, i); } else { assert!(false); } 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_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[1]); expect_payment_claimable!(nodes[1], our_payment_hash, our_payment_secret, 100000); } - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -6834,17 +9521,28 @@ pub fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_value_in_flight() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_value = 100000; let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, 0); - let max_in_flight = get_channel_value_stat!(nodes[0], nodes[1], chan.2).counterparty_max_htlc_value_in_flight_msat; + let max_in_flight = get_channel_value_stat!(nodes[0], nodes[1], chan.2) + .counterparty_max_htlc_value_in_flight_msat; - send_payment(&nodes[0], &vec!(&nodes[1])[..], max_in_flight); + send_payment(&nodes[0], &vec![&nodes[1]][..], max_in_flight); - let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], max_in_flight); + let (mut route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], max_in_flight); // Manually create a route over our max in flight (which our router normally automatically // limits us to. - route.paths[0].hops[0].fee_msat = max_in_flight + 1; - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + route.paths[0].hops[0].fee_msat = max_in_flight + 1; + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); send_payment(&nodes[0], &[&nodes[1]], max_in_flight); @@ -6862,23 +9560,40 @@ pub fn test_update_add_htlc_bolt2_receiver_check_amount_received_more_than_min() let htlc_minimum_msat: u64; { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let chan_lock = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); let channel = chan_lock.channel_by_id.get(&chan.2).unwrap(); htlc_minimum_msat = channel.context().get_holder_htlc_minimum_msat(); } - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], htlc_minimum_msat); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], htlc_minimum_msat); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - updates.update_add_htlcs[0].amount_msat = htlc_minimum_msat-1; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + updates.update_add_htlcs[0].amount_msat = htlc_minimum_msat - 1; + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); assert!(nodes[1].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[1], true).unwrap(); assert!(regex::Regex::new(r"Remote side tried to send less than our minimum HTLC value\. Lower limit: \(\d+\)\. Actual: \(\d+\)").unwrap().is_match(err_msg.data.as_str())); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -6898,9 +9613,17 @@ pub fn test_update_add_htlc_bolt2_receiver_sender_can_afford_amount_sent() { let commit_tx_fee_outbound = 2 * commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features); let max_can_send = 5000000 - channel_reserve - commit_tx_fee_outbound; - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -6908,13 +9631,21 @@ pub fn test_update_add_htlc_bolt2_receiver_sender_can_afford_amount_sent() { // at this time channel-initiatee receivers are not required to enforce that senders // respect the fee_spike_reserve. updates.update_add_htlcs[0].amount_msat = max_can_send + commit_tx_fee_outbound + 1; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); assert!(nodes[1].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[1], true).unwrap(); assert_eq!(err_msg.data, "Remote HTLC add would put them under remote reserve value"); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -6933,11 +9664,25 @@ pub fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() { route.paths[0].hops[0].fee_msat = send_amt; let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let cur_height = nodes[0].node.best_block.read().unwrap().height + 1; - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::signing_only(), + &route.paths[0], + &session_priv, + ); let recipient_onion_fields = RecipientOnionFields::secret_only(our_payment_secret); let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], send_amt, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); - let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash).unwrap(); + &route.paths[0], + send_amt, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); + let onion_packet = + onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash) + .unwrap(); let mut msg = msgs::UpdateAddHTLC { channel_id: chan.2, @@ -6959,9 +9704,17 @@ pub fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() { assert!(nodes[1].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[1], true).unwrap(); - assert!(regex::Regex::new(r"Remote tried to push more than our max accepted HTLCs \(\d+\)").unwrap().is_match(err_msg.data.as_str())); + assert!(regex::Regex::new(r"Remote tried to push more than our max accepted HTLCs \(\d+\)") + .unwrap() + .is_match(err_msg.data.as_str())); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -6973,19 +9726,39 @@ pub fn test_update_add_htlc_bolt2_receiver_check_max_in_flight_msat() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - updates.update_add_htlcs[0].amount_msat = get_channel_value_stat!(nodes[1], nodes[0], chan.2).counterparty_max_htlc_value_in_flight_msat + 1; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + updates.update_add_htlcs[0].amount_msat = get_channel_value_stat!(nodes[1], nodes[0], chan.2) + .counterparty_max_htlc_value_in_flight_msat + + 1; + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); assert!(nodes[1].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[1], true).unwrap(); - assert!(regex::Regex::new("Remote HTLC add would put them over our max HTLC value").unwrap().is_match(err_msg.data.as_str())); + assert!(regex::Regex::new("Remote HTLC add would put them over our max HTLC value") + .unwrap() + .is_match(err_msg.data.as_str())); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[0].node.get_our_node_id()], + 1000000 + ); } #[xtest(feature = "_externalize_tests")] @@ -6997,19 +9770,35 @@ pub fn test_update_add_htlc_bolt2_receiver_check_cltv_expiry() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); updates.update_add_htlcs[0].cltv_expiry = 500000000; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); assert!(nodes[1].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[1], true).unwrap(); - assert_eq!(err_msg.data,"Remote provided CLTV expiry in seconds instead of block height"); + assert_eq!(err_msg.data, "Remote provided CLTV expiry in seconds instead of block height"); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7023,24 +9812,52 @@ pub fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); //Disconnect and Reconnect nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); assert_eq!(reestablish_1.len(), 1); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); assert_eq!(reestablish_2.len(), 1); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); @@ -7049,20 +9866,35 @@ pub fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() { handle_chan_reestablish_msgs!(nodes[1], nodes[0]); //Resend HTLC - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); assert_eq!(updates.commitment_signed.len(), 1); assert_eq!(updates.commitment_signed[0].htlc_signatures.len(), 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); let _bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); assert!(nodes[1].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[1], true).unwrap(); - assert!(regex::Regex::new(r"Remote skipped HTLC ID \(skipped ID: \d+\)").unwrap().is_match(err_msg.data.as_str())); + assert!(regex::Regex::new(r"Remote skipped HTLC ID \(skipped ID: \d+\)") + .unwrap() + .is_match(err_msg.data.as_str())); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7074,15 +9906,25 @@ pub fn test_update_fulfill_htlc_bolt2_update_fulfill_htlc_before_commitment() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); - let update_msg = msgs::UpdateFulfillHTLC{ + let update_msg = msgs::UpdateFulfillHTLC { channel_id: chan.2, htlc_id: 0, payment_preimage: our_payment_preimage, @@ -7092,9 +9934,19 @@ pub fn test_update_fulfill_htlc_bolt2_update_fulfill_htlc_before_commitment() { assert!(nodes[0].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[0], true).unwrap(); - assert!(regex::Regex::new(r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed").unwrap().is_match(err_msg.data.as_str())); + assert!(regex::Regex::new( + r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed" + ) + .unwrap() + .is_match(err_msg.data.as_str())); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7107,27 +9959,47 @@ pub fn test_update_fulfill_htlc_bolt2_update_fail_htlc_before_commitment() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); - let update_msg = msgs::UpdateFailHTLC{ + let update_msg = msgs::UpdateFailHTLC { channel_id: chan.2, htlc_id: 0, reason: Vec::new(), - attribution_data: Some(AttributionData::new()) + attribution_data: Some(AttributionData::new()), }; nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_msg); assert!(nodes[0].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[0], true).unwrap(); - assert!(regex::Regex::new(r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed").unwrap().is_match(err_msg.data.as_str())); + assert!(regex::Regex::new( + r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed" + ) + .unwrap() + .is_match(err_msg.data.as_str())); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7140,13 +10012,23 @@ pub fn test_update_fulfill_htlc_bolt2_update_fail_malformed_htlc_before_commitme let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); - let update_msg = msgs::UpdateFailMalformedHTLC{ + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + let update_msg = msgs::UpdateFailMalformedHTLC { channel_id: chan.2, htlc_id: 0, sha256_of_onion: [1; 32], @@ -7157,9 +10039,19 @@ pub fn test_update_fulfill_htlc_bolt2_update_fail_malformed_htlc_before_commitme assert!(nodes[0].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[0], true).unwrap(); - assert!(regex::Regex::new(r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed").unwrap().is_match(err_msg.data.as_str())); + assert!(regex::Regex::new( + r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed" + ) + .unwrap() + .is_match(err_msg.data.as_str())); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7172,7 +10064,8 @@ pub fn test_update_fulfill_htlc_bolt2_incorrect_htlc_id() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); - let (our_payment_preimage, our_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 100_000); + let (our_payment_preimage, our_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 100_000); nodes[1].node.claim_funds(our_payment_preimage); check_added_monitors!(nodes[1], 1); @@ -7182,7 +10075,19 @@ pub fn test_update_fulfill_htlc_bolt2_incorrect_htlc_id() { assert_eq!(events.len(), 1); let mut update_fulfill_msg: msgs::UpdateFulfillHTLC = { match events[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, .. } } => { + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); assert!(update_fail_htlcs.is_empty()); @@ -7202,7 +10107,13 @@ pub fn test_update_fulfill_htlc_bolt2_incorrect_htlc_id() { let err_msg = check_closed_broadcast!(nodes[0], true).unwrap(); assert_eq!(err_msg.data, "Remote tried to fulfill/fail an HTLC we couldn't find"); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7215,7 +10126,8 @@ pub fn test_update_fulfill_htlc_bolt2_wrong_preimage() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); - let (our_payment_preimage, our_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 100_000); + let (our_payment_preimage, our_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 100_000); nodes[1].node.claim_funds(our_payment_preimage); check_added_monitors!(nodes[1], 1); @@ -7225,7 +10137,19 @@ pub fn test_update_fulfill_htlc_bolt2_wrong_preimage() { assert_eq!(events.len(), 1); let mut update_fulfill_msg: msgs::UpdateFulfillHTLC = { match events[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, .. } } => { + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert_eq!(update_fulfill_htlcs.len(), 1); assert!(update_fail_htlcs.is_empty()); @@ -7243,9 +10167,17 @@ pub fn test_update_fulfill_htlc_bolt2_wrong_preimage() { assert!(nodes[0].node.list_channels().is_empty()); let err_msg = check_closed_broadcast!(nodes[0], true).unwrap(); - assert!(regex::Regex::new(r"Remote tried to fulfill HTLC \(\d+\) with an incorrect preimage").unwrap().is_match(err_msg.data.as_str())); + assert!(regex::Regex::new(r"Remote tried to fulfill HTLC \(\d+\) with an incorrect preimage") + .unwrap() + .is_match(err_msg.data.as_str())); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7258,26 +10190,51 @@ pub fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_me let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); updates.update_add_htlcs[0].onion_routing_packet.version = 1; //Produce a malformed HTLC message - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false, true); expect_pending_htlcs_forwardable!(nodes[1]); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::InvalidOnion]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::InvalidOnion] + ); check_added_monitors(&nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); let mut update_msg: msgs::UpdateFailMalformedHTLC = { match events[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, .. } } => { + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); assert!(update_fail_htlcs.is_empty()); @@ -7295,7 +10252,13 @@ pub fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_me let err_msg = check_closed_broadcast!(nodes[0], true).unwrap(); assert_eq!(err_msg.data, "Got update_fail_malformed_htlc with BADONION not set"); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: err_msg.data }, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: err_msg.data }, + [nodes[1].node.get_our_node_id()], + 1000000 + ); } #[xtest(feature = "_externalize_tests")] @@ -7310,12 +10273,20 @@ pub fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000); let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1000000, 1000000); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100000); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], 100000); //First hop let mut payment_event = { - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.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); @@ -7337,14 +10308,29 @@ pub fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_ check_added_monitors!(nodes[2], 0); commitment_signed_dance!(nodes[2], nodes[1], payment_event.commitment_msg, false, true); expect_pending_htlcs_forwardable!(nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::InvalidOnion]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::InvalidOnion] + ); check_added_monitors(&nodes[2], 1); let events_3 = nodes[2].node.get_and_clear_pending_msg_events(); assert_eq!(events_3.len(), 1); - let update_msg : (msgs::UpdateFailMalformedHTLC, Vec) = { + let update_msg: (msgs::UpdateFailMalformedHTLC, Vec) = { match events_3[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); assert!(update_fail_htlcs.is_empty()); @@ -7360,13 +10346,31 @@ pub fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_ check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[2], update_msg.1, false, true); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); let events_4 = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events_4.len(), 1); //Confirm that handlinge the update_malformed_htlc message produces an update_fail_htlc message to be forwarded back along the route match events_4[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, .. } } => { + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + .. + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); assert_eq!(update_fail_htlcs.len(), 1); @@ -7388,12 +10392,20 @@ pub fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() { create_announced_chan_between_nodes(&nodes, 0, 1); let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); - let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100_000); + let (route, our_payment_hash, _, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], 100_000); // First hop let mut payment_event = { - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); SendEvent::from_node(&nodes[0]) }; @@ -7411,7 +10423,10 @@ pub fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() { check_added_monitors!(nodes[2], 0); commitment_signed_dance!(nodes[2], nodes[1], payment_event.commitment_msg, false, true); expect_pending_htlcs_forwardable!(nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), &[HTLCDestination::InvalidOnion]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::InvalidOnion] + ); check_added_monitors(&nodes[2], 1); let events_3 = nodes[2].node.get_and_clear_pending_msg_events(); @@ -7422,22 +10437,31 @@ pub fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() { // Set the NODE bit (BADONION and PERM already set in invalid_onion_version error) update_msg.failure_code |= 0x2000; - nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), &update_msg); + nodes[1] + .node + .handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), &update_msg); commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true); }, _ => panic!("Unexpected event"), } - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], vec![HTLCDestination::NextHopChannel { - node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); let events_4 = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events_4.len(), 1); check_added_monitors!(nodes[1], 1); match events_4[0] { MessageSendEvent::UpdateHTLCs { ref updates, .. } => { - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false, true); }, _ => panic!("Unexpected event"), @@ -7449,11 +10473,18 @@ pub fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() { // Expect a PaymentPathFailed event with a ChannelFailure network update for the channel between // the node originating the error to its next hop. match events_5[0] { - Event::PaymentPathFailed { error_code, failure: PathFailure::OnPath { network_update: Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }) }, .. + Event::PaymentPathFailed { + error_code, + failure: + PathFailure::OnPath { + network_update: + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }), + }, + .. } => { assert_eq!(short_channel_id, chan_2.0.contents.short_channel_id); assert!(is_permanent); - assert_eq!(error_code, Some(0x8000|0x4000|0x2000|4)); + assert_eq!(error_code, Some(0x8000 | 0x4000 | 0x2000 | 4)); }, _ => panic!("Unexpected event"), } @@ -7477,14 +10508,26 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan =create_announced_chan_between_nodes(&nodes, 0, 1); + let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let bs_dust_limit = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id()) - .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().context().holder_dust_limit_satoshis; + let bs_dust_limit = nodes[1] + .node + .per_peer_state + .read() + .unwrap() + .get(&nodes[0].node.get_our_node_id()) + .unwrap() + .lock() + .unwrap() + .channel_by_id + .get(&chan.2) + .unwrap() + .context() + .holder_dust_limit_satoshis; // We route 2 dust-HTLCs between A and B - let (_, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000); - let (_, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000); + let (_, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit * 1000); + let (_, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit * 1000); route_payment(&nodes[0], &[&nodes[1]], 1000000); // Cache one local commitment tx as previous @@ -7493,12 +10536,20 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) { // Fail one HTLC to prune it in the will-be-latest-local commitment tx nodes[1].node.fail_htlc_backwards(&payment_hash_2); check_added_monitors!(nodes[1], 0); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_2 }] + ); check_added_monitors!(nodes[1], 1); let remove = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &remove.update_fail_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &remove.commitment_signed); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &remove.update_fail_htlcs[0]); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &remove.commitment_signed, + ); check_added_monitors!(nodes[0], 1); // Cache one local commitment tx as lastest @@ -7528,7 +10579,13 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) { check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); @@ -7546,7 +10603,7 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) { assert_eq!(payment_hash, payment_hash_2); } }, - Event::PaymentFailed { .. } => {} + Event::PaymentFailed { .. } => {}, _ => panic!("Unexpected event"), } } @@ -7572,10 +10629,23 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let bs_dust_limit = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id()) - .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().context().holder_dust_limit_satoshis; - - let (_payment_preimage_1, dust_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000); + let bs_dust_limit = nodes[1] + .node + .per_peer_state + .read() + .unwrap() + .get(&nodes[0].node.get_our_node_id()) + .unwrap() + .lock() + .unwrap() + .channel_by_id + .get(&chan.2) + .unwrap() + .context() + .holder_dust_limit_satoshis; + + let (_payment_preimage_1, dust_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit * 1000); let (_payment_preimage_2, non_dust_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1000000); let as_commitment_tx = get_local_commitment_txn!(nodes[0], chan.2); @@ -7584,14 +10654,20 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) { // We revoked bs_commitment_tx if revoked { let (payment_preimage_3, ..) = route_payment(&nodes[0], &[&nodes[1]], 1000000); - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage_3); } let mut timeout_tx = Vec::new(); if local { // We fail dust-HTLC 1 by broadcast of local commitment tx mine_transaction(&nodes[0], &as_commitment_tx[0]); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); expect_payment_failed!(nodes[0], dust_hash, false); @@ -7600,7 +10676,10 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) { check_added_monitors!(nodes[0], 1); assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); timeout_tx.push(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].clone()); - assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + timeout_tx[0].input[0].witness.last().unwrap().len(), + OFFERED_HTLC_SCRIPT_WEIGHT + ); // We fail non-dust-HTLC 2 by broadcast of local HTLC-timeout tx on local commitment tx assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); mine_transaction(&nodes[0], &timeout_tx[0]); @@ -7611,19 +10690,34 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) { mine_transaction(&nodes[0], &bs_commitment_tx[0]); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); connect_blocks(&nodes[0], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires - timeout_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().drain(..) - .filter(|tx| tx.input[0].previous_output.txid == bs_commitment_tx[0].compute_txid()).collect(); + timeout_tx = nodes[0] + .tx_broadcaster + .txn_broadcasted + .lock() + .unwrap() + .drain(..) + .filter(|tx| tx.input[0].previous_output.txid == bs_commitment_tx[0].compute_txid()) + .collect(); check_spends!(timeout_tx[0], bs_commitment_tx[0]); // For both a revoked or non-revoked commitment transaction, after ANTI_REORG_DELAY the // dust HTLC should have been failed. expect_payment_failed!(nodes[0], dust_hash, false); if !revoked { - assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + timeout_tx[0].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); } else { assert_eq!(timeout_tx[0].lock_time.to_consensus_u32(), 11); } @@ -7658,59 +10752,143 @@ pub fn test_user_configurable_csv_delay() { let logger = TestLogger::new(); // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in OutboundV1Channel::new() - if let Err(error) = OutboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), - &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[1].node.init_features(), 1000000, 1000000, 0, - &low_our_to_self_config, 0, 42, None, &logger) - { + if let Err(error) = OutboundV1Channel::new( + &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), + &nodes[0].keys_manager, + &nodes[0].keys_manager, + nodes[1].node.get_our_node_id(), + &nodes[1].node.init_features(), + 1000000, + 1000000, + 0, + &low_our_to_self_config, + 0, + 42, + None, + &logger, + ) { match error { - APIError::APIMisuseError { err } => { assert!(regex::Regex::new(r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks").unwrap().is_match(err.as_str())); }, + APIError::APIMisuseError { err } => { + assert!(regex::Regex::new( + r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks" + ) + .unwrap() + .is_match(err.as_str())); + }, _ => panic!("Unexpected event"), } - } else { assert!(false) } + } else { + assert!(false) + } // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in InboundV1Channel::new() - nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None, None).unwrap(); - let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None, None) + .unwrap(); + let mut open_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendOpenChannel, + nodes[0].node.get_our_node_id() + ); open_channel.common_fields.to_self_delay = 200; - if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), - &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0, - &low_our_to_self_config, 0, &nodes[0].logger, /*is_0conf=*/false) - { + if let Err(error) = InboundV1Channel::new( + &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), + &nodes[0].keys_manager, + &nodes[0].keys_manager, + nodes[1].node.get_our_node_id(), + &nodes[0].node.channel_type_features(), + &nodes[1].node.init_features(), + &open_channel, + 0, + &low_our_to_self_config, + 0, + &nodes[0].logger, + /*is_0conf=*/ false, + ) { match error { ChannelError::Close((err, _)) => { - let regex = regex::Regex::new(r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks").unwrap(); + let regex = regex::Regex::new( + r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks", + ) + .unwrap(); assert!(regex.is_match(err.as_str())); }, _ => panic!("Unexpected event"), } - } else { assert!(false); } + } else { + assert!(false); + } // We test msg.to_self_delay <= config.their_to_self_delay is enforced in Chanel::accept_channel() - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1000000, 1000000, 42, None, None).unwrap(); - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id())); - let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 1000000, 1000000, 42, None, None) + .unwrap(); + nodes[1].node.handle_open_channel( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ), + ); + let mut accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); accept_channel.common_fields.to_self_delay = 200; nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); let reason_msg; - if let MessageSendEvent::HandleError { ref action, .. } = nodes[0].node.get_and_clear_pending_msg_events()[0] { + if let MessageSendEvent::HandleError { ref action, .. } = + nodes[0].node.get_and_clear_pending_msg_events()[0] + { match action { &ErrorAction::SendErrorMessage { ref msg } => { assert!(regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap().is_match(msg.data.as_str())); reason_msg = msg.data.clone(); }, - _ => { panic!(); } + _ => { + panic!(); + }, } - } else { panic!(); } - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: reason_msg }, [nodes[1].node.get_our_node_id()], 1000000); + } else { + panic!(); + } + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: reason_msg }, + [nodes[1].node.get_our_node_id()], + 1000000 + ); // We test msg.to_self_delay <= config.their_to_self_delay is enforced in InboundV1Channel::new() - nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None, None).unwrap(); - let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None, None) + .unwrap(); + let mut open_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendOpenChannel, + nodes[0].node.get_our_node_id() + ); open_channel.common_fields.to_self_delay = 200; - if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), - &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0, - &high_their_to_self_config, 0, &nodes[0].logger, /*is_0conf=*/false) - { + if let Err(error) = InboundV1Channel::new( + &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator::new(253)), + &nodes[0].keys_manager, + &nodes[0].keys_manager, + nodes[1].node.get_our_node_id(), + &nodes[0].node.channel_type_features(), + &nodes[1].node.init_features(), + &open_channel, + 0, + &high_their_to_self_config, + 0, + &nodes[0].logger, + /*is_0conf=*/ false, + ) { match error { ChannelError::Close((err, _)) => { let regex = regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap(); @@ -7718,7 +10896,9 @@ pub fn test_user_configurable_csv_delay() { }, _ => panic!("Unexpected event"), } - } else { assert!(false); } + } else { + assert!(false); + } } #[xtest(feature = "_externalize_tests")] @@ -7737,15 +10917,36 @@ pub fn test_check_htlc_underpaying() { let scorer = test_utils::TestScorer::new(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 10_000); - let route = get_route(&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), - None, nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &nodes[0].node.get_our_node_id(), + &route_params, + &nodes[0].network_graph.read_only(), + None, + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]); - let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, None).unwrap(); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let our_payment_secret = nodes[1] + .node + .create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, None) + .unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -7757,7 +10958,10 @@ pub fn test_check_htlc_underpaying() { // Note that we first have to wait a random delay before processing the receipt of the HTLC, // and then will wait a second random delay before failing the HTLC back: expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }] + ); // Node 3 is expecting payment of 100_000 but received 10_000, // it should fail htlc like we didn't know the preimage. @@ -7766,7 +10970,19 @@ pub fn test_check_htlc_underpaying() { let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let (update_fail_htlc, commitment_signed) = match events[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); assert_eq!(update_fail_htlcs.len(), 1); @@ -7784,7 +11000,13 @@ pub fn test_check_htlc_underpaying() { // 10_000 msat as u64, followed by a height of CHAN_CONFIRM_DEPTH as u32 let mut expected_failure_data = (10_000 as u64).to_be_bytes().to_vec(); expected_failure_data.extend_from_slice(&CHAN_CONFIRM_DEPTH.to_be_bytes()); - expect_payment_failed!(nodes[0], our_payment_hash, true, LocalHTLCFailureReason::IncorrectPaymentDetails, &expected_failure_data[..]); + expect_payment_failed!( + nodes[0], + our_payment_hash, + true, + LocalHTLCFailureReason::IncorrectPaymentDetails, + &expected_failure_data[..] + ); } #[xtest(feature = "_externalize_tests")] @@ -7817,9 +11039,12 @@ pub fn test_announce_disable_channels() { for e in msg_events { match e { MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - assert_eq!(msg.contents.channel_flags & (1<<1), 1<<1); // The "channel disabled" bit should be set - // Check that each channel gets updated exactly once - if chans_disabled.insert(msg.contents.short_channel_id, msg.contents.timestamp).is_some() { + assert_eq!(msg.contents.channel_flags & (1 << 1), 1 << 1); // The "channel disabled" bit should be set + // Check that each channel gets updated exactly once + if chans_disabled + .insert(msg.contents.short_channel_id, msg.contents.timestamp) + .is_some() + { panic!("Generated ChannelUpdate for wrong chan!"); } }, @@ -7827,14 +11052,32 @@ pub fn test_announce_disable_channels() { } } // Reconnect peers - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); assert_eq!(reestablish_1.len(), 3); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); assert_eq!(reestablish_2.len(), 3); @@ -7864,7 +11107,7 @@ pub fn test_announce_disable_channels() { for e in msg_events { match e { MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - assert_eq!(msg.contents.channel_flags & (1<<1), 0); // The "channel disabled" bit should be off + assert_eq!(msg.contents.channel_flags & (1 << 1), 0); // The "channel disabled" bit should be off match chans_disabled.remove(&msg.contents.short_channel_id) { // Each update should have a higher timestamp than the previous one, replacing // the old one. @@ -7891,11 +11134,13 @@ pub fn test_bump_penalty_txn_on_revoked_commitment() { let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000); - let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0; - let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[0].node.bolt11_invoice_features()).unwrap(); - let (route,_, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], payment_params, 3000000); - send_along_route(&nodes[1], route, &vec!(&nodes[0])[..], 3000000); + let payment_preimage = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; + let payment_params = + PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[0].node.bolt11_invoice_features()) + .unwrap(); + let (route, _, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], payment_params, 3000000); + send_along_route(&nodes[1], route, &vec![&nodes[0]][..], 3000000); let revoked_txn = get_local_commitment_txn!(nodes[0], chan.2); // Revoked commitment txn with 4 outputs : to_local, to_remote, 1 outgoing HTLC, 1 incoming HTLC @@ -7907,7 +11152,7 @@ pub fn test_bump_penalty_txn_on_revoked_commitment() { let header_114 = connect_blocks(&nodes[1], 14); // Actually revoke tx by claiming a HTLC - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage); connect_block(&nodes[1], &create_dummy_block(header_114, 42, vec![revoked_txn[0].clone()])); check_added_monitors!(nodes[1], 1); @@ -7927,8 +11172,15 @@ pub fn test_bump_penalty_txn_on_revoked_commitment() { assert!(tx.input.len() == 1 || tx.input.len() == 2); assert_eq!(tx.output.len(), 1); check_spends!(tx, revoked_txn[0]); - let total_input: u64 = tx.input.iter().map(|i| revoked_txn[0].output[i.previous_output.vout as usize].value.to_sat()).sum(); - let fee_rate: u64 = (total_input - tx.output[0].value.to_sat()) * 1000 / tx.weight().to_wu(); + let total_input: u64 = tx + .input + .iter() + .map(|i| { + revoked_txn[0].output[i.previous_output.vout as usize].value.to_sat() + }) + .sum(); + let fee_rate: u64 = + (total_input - tx.output[0].value.to_sat()) * 1000 / tx.weight().to_wu(); assert_ne!(fee_rate, 0); for input in &tx.input { $fee_rates.insert(input.previous_output, fee_rate); @@ -7939,7 +11191,7 @@ pub fn test_bump_penalty_txn_on_revoked_commitment() { assert_eq!($penalty_txids.len(), 3); node_txn.clear(); } - } + }; } // One or more justice tx should have been broadcast, check it. @@ -7987,18 +11239,39 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000); // Lock HTLC in both directions (using a slightly lower CLTV delay to provide timely RBF bumps) - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 50).with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 50) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); let scorer = test_utils::TestScorer::new(); let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 3_000_000); - let route = get_route(&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), None, - nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &nodes[0].node.get_our_node_id(), + &route_params, + &nodes[0].network_graph.read_only(), + None, + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0; let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), 50) - .with_bolt11_features(nodes[0].node.bolt11_invoice_features()).unwrap(); + .with_bolt11_features(nodes[0].node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 3_000_000); - let route = get_route(&nodes[1].node.get_our_node_id(), &route_params, &nodes[1].network_graph.read_only(), None, - nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &nodes[1].node.get_our_node_id(), + &route_params, + &nodes[1].network_graph.read_only(), + None, + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let failed_payment_hash = send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000).1; let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2); @@ -8006,13 +11279,22 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.compute_txid()); // Revoke local commitment tx - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage); // B will generate both revoked HTLC-timeout/HTLC-preimage txn from revoked commitment tx - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![revoked_local_txn[0].clone()])); + connect_block( + &nodes[1], + &create_dummy_block(nodes[1].best_block_hash(), 42, vec![revoked_local_txn[0].clone()]), + ); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); connect_blocks(&nodes[1], 50); // Confirm blocks until the HTLC expires (note CLTV was explicitly 50 above) let revoked_htlc_txn = { @@ -8035,12 +11317,19 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { let hash_128 = connect_blocks(&nodes[0], 40); let block_11 = create_dummy_block(hash_128, 42, vec![revoked_local_txn[0].clone()]); connect_block(&nodes[0], &block_11); - let block_129 = create_dummy_block(block_11.block_hash(), 42, vec![revoked_htlc_txn[0].clone(), revoked_htlc_txn[1].clone()]); + let block_129 = create_dummy_block( + block_11.block_hash(), + 42, + vec![revoked_htlc_txn[0].clone(), revoked_htlc_txn[1].clone()], + ); connect_block(&nodes[0], &block_129); let events = nodes[0].node.get_and_clear_pending_events(); - expect_pending_htlcs_forwardable_conditions(events[0..2].to_vec(), &[HTLCDestination::FailedPayment { payment_hash: failed_payment_hash }]); + expect_pending_htlcs_forwardable_conditions( + events[0..2].to_vec(), + &[HTLCDestination::FailedPayment { payment_hash: failed_payment_hash }], + ); match events.last().unwrap() { - Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {} + Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}, _ => panic!("Unexpected event"), } let first; @@ -8070,8 +11359,14 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { assert_ne!(node_txn[0].input[0].previous_output, node_txn[1].input[1].previous_output); assert_ne!(node_txn[1].input[0].previous_output, node_txn[1].input[1].previous_output); - assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output); - assert_eq!(node_txn[1].input[1].previous_output, revoked_htlc_txn[0].input[0].previous_output); + assert_eq!( + node_txn[1].input[0].previous_output, + revoked_htlc_txn[1].input[0].previous_output + ); + assert_eq!( + node_txn[1].input[1].previous_output, + revoked_htlc_txn[0].input[0].previous_output + ); // node_txn[3] spends the revoked outputs from the revoked_htlc_txn (which only have one // output, checked above). @@ -8081,7 +11376,8 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { first = node_txn[2].compute_txid(); // Store both feerates for later comparison - let fee_1 = revoked_htlc_txn[0].output[0].value + revoked_htlc_txn[1].output[0].value - node_txn[2].output[0].value; + let fee_1 = revoked_htlc_txn[0].output[0].value + revoked_htlc_txn[1].output[0].value + - node_txn[2].output[0].value; feerate_1 = fee_1 * 1000 / node_txn[2].weight().to_wu(); penalty_txn = vec![node_txn[0].clone()]; node_txn.clear(); @@ -8105,7 +11401,8 @@ pub fn test_bump_penalty_txn_on_revoked_htlcs() { check_spends!(node_txn[0], revoked_htlc_txn[0], revoked_htlc_txn[1]); // Verify bumped tx is different and 25% bump heuristic assert_ne!(first, node_txn[0].compute_txid()); - let fee_2 = revoked_htlc_txn[0].output[0].value + revoked_htlc_txn[1].output[0].value - node_txn[0].output[0].value; + let fee_2 = revoked_htlc_txn[0].output[0].value + revoked_htlc_txn[1].output[0].value + - node_txn[0].output[0].value; let feerate_2 = fee_2 * 1000 / node_txn[0].weight().to_wu(); assert!(feerate_2 * 100 > feerate_1 * 125); let txn = vec![node_txn[0].clone()]; @@ -8150,8 +11447,9 @@ pub fn test_bump_penalty_txn_on_remote_commitment() { let htlc_value_b_msats = 583_000; let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], htlc_value_a_msats); - route_payment(&nodes[1], &vec!(&nodes[0])[..], htlc_value_b_msats); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], htlc_value_a_msats); + route_payment(&nodes[1], &vec![&nodes[0]][..], htlc_value_b_msats); // Remote commitment txn with 4 outputs : to_local, to_remote, 1 outgoing HTLC, 1 incoming HTLC let remote_txn = get_local_commitment_txn!(nodes[0], chan.2); @@ -8165,7 +11463,7 @@ pub fn test_bump_penalty_txn_on_remote_commitment() { mine_transaction(&nodes[1], &remote_txn[0]); check_added_monitors!(nodes[1], 2); connect_blocks(&nodes[1], TEST_FINAL_CLTV); // Confirm blocks until the HTLC expires - // depending on the block connection style, node 1 may have broadcast either 3 or 10 txs + // depending on the block connection style, node 1 may have broadcast either 3 or 10 txs remote_txn }; @@ -8190,14 +11488,16 @@ pub fn test_bump_penalty_txn_on_remote_commitment() { preimage = node_txn[0].compute_txid(); let index = node_txn[0].input[0].previous_output.vout; - let fee = remote_txn[0].output[index as usize].value.to_sat() - node_txn[0].output[0].value.to_sat(); + let fee = remote_txn[0].output[index as usize].value.to_sat() + - node_txn[0].output[0].value.to_sat(); feerate_preimage = fee * 1000 / node_txn[0].weight().to_wu(); - let (preimage_bump_tx, timeout_tx) = if node_txn[2].input[0].previous_output == node_txn[0].input[0].previous_output { - (node_txn[2].clone(), node_txn[1].clone()) - } else { - (node_txn[1].clone(), node_txn[2].clone()) - }; + let (preimage_bump_tx, timeout_tx) = + if node_txn[2].input[0].previous_output == node_txn[0].input[0].previous_output { + (node_txn[2].clone(), node_txn[1].clone()) + } else { + (node_txn[1].clone(), node_txn[2].clone()) + }; preimage_bump = preimage_bump_tx; check_spends!(preimage_bump, remote_txn[0]); @@ -8205,7 +11505,8 @@ pub fn test_bump_penalty_txn_on_remote_commitment() { timeout = timeout_tx.compute_txid(); let index = timeout_tx.input[0].previous_output.vout; - let fee = remote_txn[0].output[index as usize].value.to_sat() - timeout_tx.output[0].value.to_sat(); + let fee = remote_txn[0].output[index as usize].value.to_sat() + - timeout_tx.output[0].value.to_sat(); feerate_timeout = fee * 1000 / timeout_tx.weight().to_wu(); node_txn.clear(); @@ -8224,13 +11525,15 @@ pub fn test_bump_penalty_txn_on_remote_commitment() { check_spends!(preimage_bump, remote_txn[0]); let index = preimage_bump.input[0].previous_output.vout; - let fee = remote_txn[0].output[index as usize].value.to_sat() - preimage_bump.output[0].value.to_sat(); + let fee = remote_txn[0].output[index as usize].value.to_sat() + - preimage_bump.output[0].value.to_sat(); let new_feerate = fee * 1000 / preimage_bump.weight().to_wu(); assert!(new_feerate * 100 > feerate_timeout * 125); assert_ne!(timeout, preimage_bump.compute_txid()); let index = node_txn[0].input[0].previous_output.vout; - let fee = remote_txn[0].output[index as usize].value.to_sat() - node_txn[0].output[0].value.to_sat(); + let fee = remote_txn[0].output[index as usize].value.to_sat() + - node_txn[0].output[0].value.to_sat(); let new_feerate = fee * 1000 / node_txn[0].weight().to_wu(); assert!(new_feerate * 100 > feerate_preimage * 125); assert_ne!(preimage, node_txn[0].compute_txid()); @@ -8262,37 +11565,54 @@ pub fn test_counterparty_raa_skip_no_crash() { let next_per_commitment_point; { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let mut guard = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); - let keys = guard.channel_by_id.get(&channel_id).and_then(Channel::as_funded).unwrap() - .get_signer(); + let mut guard = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let keys = + guard.channel_by_id.get(&channel_id).and_then(Channel::as_funded).unwrap().get_signer(); const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; // Make signer believe we got a counterparty signature, so that it allows the revocation keys.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; - per_commitment_secret = keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(); + per_commitment_secret = + keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(); // Must revoke without gaps keys.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1).unwrap(); keys.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1; - next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(), - &SecretKey::from_slice(&keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2).unwrap()).unwrap()); + next_per_commitment_point = PublicKey::from_secret_key( + &Secp256k1::new(), + &SecretKey::from_slice( + &keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2).unwrap(), + ) + .unwrap(), + ); } - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), + nodes[1].node.handle_revoke_and_ack( + nodes[0].node.get_our_node_id(), &msgs::RevokeAndACK { channel_id, per_commitment_secret, next_per_commitment_point, #[cfg(taproot)] next_local_nonce: None, - }); - assert_eq!(check_closed_broadcast!(nodes[1], true).unwrap().data, "Received an unexpected revoke_and_ack"); + }, + ); + assert_eq!( + check_closed_broadcast!(nodes[1], true).unwrap().data, + "Received an unexpected revoke_and_ack" + ); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "Received an unexpected revoke_and_ack".to_string() } - , [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: "Received an unexpected revoke_and_ack".to_string() }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -8307,25 +11627,34 @@ pub fn test_bump_txn_sanitize_tracking_maps() { let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000); // Lock HTLC in both directions - let (payment_preimage_1, ..) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000); - let (_, payment_hash_2, ..) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 9_000_000); + let (payment_preimage_1, ..) = route_payment(&nodes[0], &vec![&nodes[1]][..], 9_000_000); + let (_, payment_hash_2, ..) = route_payment(&nodes[1], &vec![&nodes[0]][..], 9_000_000); let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2); assert_eq!(revoked_local_txn[0].input.len(), 1); assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.compute_txid()); // Revoke local commitment tx - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage_1); // Broadcast set of revoked txn on A connect_blocks(&nodes[0], TEST_FINAL_CLTV + 2 - CHAN_CONFIRM_DEPTH); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[0], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[0], + vec![HTLCDestination::FailedPayment { payment_hash: payment_hash_2 }] + ); assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0); mine_transaction(&nodes[0], &revoked_local_txn[0]); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 1000000 + ); let penalty_txn = { let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 2); //ChannelMonitor: justice txn * 2 @@ -8358,7 +11687,8 @@ pub fn test_channel_conf_timeout() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let _funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 100_000); + let _funding_tx = + create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 100_000); // The outbound node should wait forever for confirmation: // This matches `channel::FUNDING_CONF_DEADLINE_BLOCKS` and BOLT 2's suggested timeout, thus is @@ -8373,13 +11703,25 @@ pub fn test_channel_conf_timeout() { connect_blocks(&nodes[1], 1); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::FundingTimedOut, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::FundingTimedOut, + [nodes[0].node.get_our_node_id()], + 1000000 + ); let close_ev = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(close_ev.len(), 1); match close_ev[0] { - MessageSendEvent::HandleError { action: ErrorAction::DisconnectPeer { ref msg }, ref node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::DisconnectPeer { ref msg }, + ref node_id, + } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - assert_eq!(msg.as_ref().unwrap().data, "Channel closed because funding transaction failed to confirm within 2016 blocks"); + assert_eq!( + msg.as_ref().unwrap().data, + "Channel closed because funding transaction failed to confirm within 2016 blocks" + ); }, _ => panic!("Unexpected event"), } @@ -8396,10 +11738,24 @@ pub fn test_override_channel_config() { let mut override_config = UserConfig::default(); override_config.channel_handshake_config.our_to_self_delay = 200; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 16_000_000, 12_000_000, 42, None, Some(override_config)).unwrap(); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 16_000_000, + 12_000_000, + 42, + None, + Some(override_config), + ) + .unwrap(); // Assert the channel created by node0 is using the override config. - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let res = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert_eq!(res.common_fields.channel_flags, 0); assert_eq!(res.common_fields.to_self_delay, 200); } @@ -8413,12 +11769,30 @@ pub fn test_override_0msat_htlc_minimum() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(zero_config.clone())]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 16_000_000, 12_000_000, 42, None, Some(zero_config)).unwrap(); - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 16_000_000, + 12_000_000, + 42, + None, + Some(zero_config), + ) + .unwrap(); + let res = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert_eq!(res.common_fields.htlc_minimum_msat, 1); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &res); - let res = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let res = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); assert_eq!(res.common_fields.htlc_minimum_msat, 1); } @@ -8432,20 +11806,37 @@ pub fn test_channel_update_has_correct_htlc_maximum_msat() { let mut config_30_percent = UserConfig::default(); config_30_percent.channel_handshake_config.announce_for_forwarding = true; - config_30_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 30; + config_30_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 30; let mut config_50_percent = UserConfig::default(); config_50_percent.channel_handshake_config.announce_for_forwarding = true; - config_50_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 50; + config_50_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 50; let mut config_95_percent = UserConfig::default(); config_95_percent.channel_handshake_config.announce_for_forwarding = true; - config_95_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 95; + config_95_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 95; let mut config_100_percent = UserConfig::default(); config_100_percent.channel_handshake_config.announce_for_forwarding = true; - config_100_percent.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; + config_100_percent + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 100; let chanmon_cfgs = create_chanmon_cfgs(4); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[Some(config_30_percent), Some(config_50_percent), Some(config_95_percent), Some(config_100_percent)]); + let node_chanmgrs = create_node_chanmgrs( + 4, + &node_cfgs, + &[ + Some(config_30_percent), + Some(config_50_percent), + Some(config_95_percent), + Some(config_100_percent), + ], + ); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); let channel_value_satoshis = 100000; @@ -8454,8 +11845,10 @@ pub fn test_channel_update_has_correct_htlc_maximum_msat() { let channel_value_50_percent_msat = (channel_value_msat as f64 * 0.5) as u64; let channel_value_90_percent_msat = (channel_value_msat as f64 * 0.9) as u64; - let (node_0_chan_update, node_1_chan_update, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value_satoshis, 10001); - let (node_2_chan_update, node_3_chan_update, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, channel_value_satoshis, 10001); + let (node_0_chan_update, node_1_chan_update, _, _) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value_satoshis, 10001); + let (node_2_chan_update, node_3_chan_update, _, _) = + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, channel_value_satoshis, 10001); // Assert that `node[0]`'s `ChannelUpdate` is capped at 50 percent of the `channel_value`, as // that's the value of `node[1]`'s `holder_max_htlc_value_in_flight_msat`. @@ -8482,11 +11875,26 @@ pub fn test_manually_accept_inbound_channel_request() { let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf.clone())]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf.clone())]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(manually_accept_conf)).unwrap(); - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100000, + 10001, + 42, + None, + Some(manually_accept_conf), + ) + .unwrap(); + let res = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &res); @@ -8515,8 +11923,16 @@ pub fn test_manually_accept_inbound_channel_request() { let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 23, Some(config_overrides)).unwrap(); - } + nodes[1] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 23, + Some(config_overrides), + ) + .unwrap(); + }, _ => panic!("Unexpected event"), } @@ -8532,22 +11948,38 @@ pub fn test_manually_accept_inbound_channel_request() { assert_eq!(msg.common_fields.max_accepted_htlcs, 3); accept_channel = msg; - } + }, _ => panic!("Unexpected event"), } // Continue channel opening process until channel update messages are sent. nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, funding_outpoint) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); - nodes[0].node.unsafe_manual_funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), funding_outpoint).unwrap(); + let (temporary_channel_id, tx, funding_outpoint) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); + nodes[0] + .node + .unsafe_manual_funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + funding_outpoint, + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let funding_created = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed); check_added_monitors!(nodes[0], 1); let events = &nodes[0].node.get_and_clear_pending_events(); @@ -8569,16 +12001,28 @@ pub fn test_manually_accept_inbound_channel_request() { mine_transaction(&nodes[0], &tx); mine_transaction(&nodes[1], &tx); - let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id()); + let as_channel_ready = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelReady, + nodes[0].node.get_our_node_id() + ); nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &as_channel_ready); - let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let as_channel_ready = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ); nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &as_channel_ready); 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()); // Assert that the overriden base fee surfaces in the channel update. - let channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); + let channel_update = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[0].node.get_our_node_id() + ); assert_eq!(channel_update.contents.fee_base_msat, 555); get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); @@ -8590,11 +12034,26 @@ pub fn test_manually_reject_inbound_channel_request() { manually_accept_conf.manually_accept_inbound_channels = true; let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf.clone())]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf.clone())]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(manually_accept_conf)).unwrap(); - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100000, + 10001, + 42, + None, + Some(manually_accept_conf), + ) + .unwrap(); + let res = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &res); @@ -8605,8 +12064,15 @@ pub fn test_manually_reject_inbound_channel_request() { let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.force_close_broadcasting_latest_txn(&temporary_channel_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); - } + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); + }, _ => panic!("Unexpected event"), } @@ -8616,7 +12082,7 @@ pub fn test_manually_reject_inbound_channel_request() { match close_msg_ev[0] { MessageSendEvent::HandleError { ref node_id, .. } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - } + }, _ => panic!("Unexpected event"), } @@ -8630,11 +12096,26 @@ pub fn test_can_not_accept_inbound_channel_twice() { manually_accept_conf.manually_accept_inbound_channels = true; let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf.clone())]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf.clone())]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(manually_accept_conf)).unwrap(); - let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100000, + 10001, + 42, + None, + Some(manually_accept_conf), + ) + .unwrap(); + let res = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &res); @@ -8645,8 +12126,21 @@ pub fn test_can_not_accept_inbound_channel_twice() { let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).unwrap(); - let api_res = nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None); + nodes[1] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) + .unwrap(); + let api_res = nodes[1].node.accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ); match api_res { Err(APIError::APIMisuseError { err }) => { assert_eq!(err, "No such channel awaiting to be accepted."); @@ -8654,7 +12148,7 @@ pub fn test_can_not_accept_inbound_channel_twice() { Ok(_) => panic!("Channel shouldn't be possible to be accepted twice"), Err(e) => panic!("Unexpected Error {:?}", e), } - } + }, _ => panic!("Unexpected event"), } @@ -8665,7 +12159,7 @@ pub fn test_can_not_accept_inbound_channel_twice() { match accept_msg_ev[0] { MessageSendEvent::SendAcceptChannel { ref node_id, .. } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - } + }, _ => panic!("Unexpected event"), } } @@ -8678,7 +12172,12 @@ pub fn test_can_not_accept_unknown_inbound_channel() { let nodes = create_network(2, &node_cfg, &node_chanmgr); let unknown_channel_id = ChannelId::new_zero(); - let api_res = nodes[0].node.accept_inbound_channel(&unknown_channel_id, &nodes[1].node.get_our_node_id(), 0, None); + let api_res = nodes[0].node.accept_inbound_channel( + &unknown_channel_id, + &nodes[1].node.get_our_node_id(), + 0, + None, + ); match api_res { Err(APIError::APIMisuseError { err }) => { assert_eq!(err, "No such channel awaiting to be accepted."); @@ -8708,7 +12207,8 @@ pub fn test_onion_value_mpp_set_calculation() { let total_msat = 100_000; let expected_paths: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]]; - let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], total_msat); + let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[3], total_msat); let sample_path = route.paths.pop().unwrap(); let mut path_1 = sample_path.clone(); @@ -8729,39 +12229,80 @@ pub fn test_onion_value_mpp_set_calculation() { // Send payment let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); - let onion_session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), payment_id, &route).unwrap(); - nodes[0].node.test_send_payment_internal(&route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); + let onion_session_privs = nodes[0] + .node + .test_add_new_pending_payment( + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + payment_id, + &route, + ) + .unwrap(); + nodes[0] + .node + .test_send_payment_internal( + &route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + None, + payment_id, + Some(total_msat), + onion_session_privs, + ) + .unwrap(); check_added_monitors!(nodes[0], expected_paths.len()); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_paths.len()); // First path - let ev = remove_first_msg_event_to_node(&expected_paths[0][0].node.get_our_node_id(), &mut events); + let ev = + remove_first_msg_event_to_node(&expected_paths[0][0].node.get_our_node_id(), &mut events); let mut payment_event = SendEvent::from_event(ev); let mut prev_node = &nodes[0]; for (idx, &node) in expected_paths[0].iter().enumerate() { assert_eq!(node.node.get_our_node_id(), payment_event.node_id); - if idx == 0 { // routing node + if idx == 0 { + // routing node let session_priv = [3; 32]; let height = nodes[0].best_block_info().1; let session_priv = SecretKey::from_slice(&session_priv).unwrap(); - let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); + let mut onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); let recipient_onion_fields = RecipientOnionFields::secret_only(our_payment_secret); - let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], 100_000, - &recipient_onion_fields, height + 1, &None, None, None).unwrap(); + let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads( + &route.paths[0], + 100_000, + &recipient_onion_fields, + height + 1, + &None, + None, + None, + ) + .unwrap(); // Edit amt_to_forward to simulate the sender having set // the final amount and the routing node taking less fee if let msgs::OutboundOnionPayload::Receive { - ref mut sender_intended_htlc_amt_msat, .. - } = onion_payloads[1] { + ref mut sender_intended_htlc_amt_msat, + .. + } = onion_payloads[1] + { *sender_intended_htlc_amt_msat = 99_000; - } else { panic!() } - let new_onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash).unwrap(); + } else { + panic!() + } + let new_onion_packet = onion_utils::construct_onion_packet( + onion_payloads, + onion_keys, + [0; 32], + &our_payment_hash, + ) + .unwrap(); payment_event.msgs[0].onion_routing_packet = new_onion_packet; } @@ -8785,16 +12326,27 @@ pub fn test_onion_value_mpp_set_calculation() { } // Second path - let ev = remove_first_msg_event_to_node(&expected_paths[1][0].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], expected_paths[1], 101_000, our_payment_hash.clone(), Some(our_payment_secret), ev, true, None); - - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], expected_paths, our_payment_preimage) + let ev = + remove_first_msg_event_to_node(&expected_paths[1][0].node.get_our_node_id(), &mut events); + pass_along_path( + &nodes[0], + expected_paths[1], + 101_000, + our_payment_hash.clone(), + Some(our_payment_secret), + ev, + true, + None, ); + + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + expected_paths, + our_payment_preimage, + )); } fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) { - let routing_node_count = msat_amounts.len(); let node_count = routing_node_count + 2; @@ -8812,18 +12364,26 @@ fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) { let mut dst_chan_ids = Vec::with_capacity(routing_node_count); for i in 0..routing_node_count { let routing_node = 2 + i; - let src_chan_id = create_announced_chan_between_nodes(&nodes, src_idx, routing_node).0.contents.short_channel_id; + let src_chan_id = create_announced_chan_between_nodes(&nodes, src_idx, routing_node) + .0 + .contents + .short_channel_id; src_chan_ids.push(src_chan_id); - let dst_chan_id = create_announced_chan_between_nodes(&nodes, routing_node, dst_idx).0.contents.short_channel_id; + let dst_chan_id = create_announced_chan_between_nodes(&nodes, routing_node, dst_idx) + .0 + .contents + .short_channel_id; dst_chan_ids.push(dst_chan_id); let path = vec![&nodes[routing_node], &nodes[dst_idx]]; expected_paths.push(path); } - let expected_paths: Vec<&[&Node]> = expected_paths.iter().map(|route| route.as_slice()).collect(); + let expected_paths: Vec<&[&Node]> = + expected_paths.iter().map(|route| route.as_slice()).collect(); // Create a route for each amount let example_amount = 100000; - let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(&nodes[src_idx], nodes[dst_idx], example_amount); + let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(&nodes[src_idx], nodes[dst_idx], example_amount); let sample_path = route.paths.pop().unwrap(); for i in 0..routing_node_count { let routing_node = 2 + i; @@ -8838,27 +12398,57 @@ fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) { // Send payment with manually set total_msat let payment_id = PaymentId(nodes[src_idx].keys_manager.backing.get_secure_random_bytes()); - let onion_session_privs = nodes[src_idx].node.test_add_new_pending_payment(our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), payment_id, &route).unwrap(); - nodes[src_idx].node.test_send_payment_internal(&route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); + let onion_session_privs = nodes[src_idx] + .node + .test_add_new_pending_payment( + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + payment_id, + &route, + ) + .unwrap(); + nodes[src_idx] + .node + .test_send_payment_internal( + &route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + None, + payment_id, + Some(total_msat), + onion_session_privs, + ) + .unwrap(); check_added_monitors!(nodes[src_idx], expected_paths.len()); let mut events = nodes[src_idx].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_paths.len()); let mut amount_received = 0; for (path_idx, expected_path) in expected_paths.iter().enumerate() { - let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events); + let ev = + remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events); let current_path_amount = msat_amounts[path_idx]; amount_received += current_path_amount; - let became_claimable_now = amount_received >= total_msat && amount_received - current_path_amount < total_msat; - pass_along_path(&nodes[src_idx], expected_path, amount_received, our_payment_hash.clone(), Some(our_payment_secret), ev, became_claimable_now, None); + let became_claimable_now = + amount_received >= total_msat && amount_received - current_path_amount < total_msat; + pass_along_path( + &nodes[src_idx], + expected_path, + amount_received, + our_payment_hash.clone(), + Some(our_payment_secret), + ev, + became_claimable_now, + None, + ); } - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[src_idx], &expected_paths, our_payment_preimage) - ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[src_idx], + &expected_paths, + our_payment_preimage, + )); } #[xtest(feature = "_externalize_tests")] @@ -8880,7 +12470,8 @@ pub fn test_simple_mpp() { let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3).0.contents.short_channel_id; let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3).0.contents.short_channel_id; - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); let path = route.paths[0].clone(); route.paths.push(path); route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -8889,10 +12480,19 @@ pub fn test_simple_mpp() { route.paths[1].hops[0].pubkey = nodes[2].node.get_our_node_id(); route.paths[1].hops[0].short_channel_id = chan_2_id; route.paths[1].hops[1].short_channel_id = chan_4_id; - send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, payment_secret); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) + send_along_route_with_secret( + &nodes[0], + route, + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + 200_000, + payment_hash, + payment_secret, ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + payment_preimage, + )); } #[xtest(feature = "_externalize_tests")] @@ -8906,14 +12506,24 @@ pub fn test_preimage_storage() { create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; { - let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 7200, None).unwrap(); + let (payment_hash, payment_secret) = + nodes[1].node.create_inbound_payment(Some(100_000), 7200, None).unwrap(); let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); let mut payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); } // Note that after leaving the above scope we have no knowledge of any arguments or return @@ -8922,13 +12532,11 @@ pub fn test_preimage_storage() { let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentClaimable { ref purpose, .. } => { - match &purpose { - PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => { - claim_payment(&nodes[0], &[&nodes[1]], payment_preimage.unwrap()); - }, - _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment") - } + Event::PaymentClaimable { ref purpose, .. } => match &purpose { + PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => { + claim_payment(&nodes[0], &[&nodes[1]], payment_preimage.unwrap()); + }, + _ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"), }, _ => panic!("Unexpected event"), } @@ -8946,7 +12554,8 @@ pub fn test_bad_secret_hash() { let random_payment_hash = PaymentHash([42; 32]); let random_payment_secret = PaymentSecret([43; 32]); - let (our_payment_hash, our_payment_secret) = nodes[1].node.create_inbound_payment(Some(100_000), 2, None).unwrap(); + let (our_payment_hash, our_payment_secret) = + nodes[1].node.create_inbound_payment(Some(100_000), 2, None).unwrap(); let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); // All the below cases should end up being handled exactly identically, so we macro the @@ -8956,25 +12565,37 @@ pub fn test_bad_secret_hash() { check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); let payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); // We have to forward pending HTLCs once to process the receipt of the HTLC and then // again to process the pending backwards-failure of the HTLC expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment{ payment_hash: $payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: $payment_hash }] + ); check_added_monitors!(nodes[1], 1); // We should fail the payment back let mut events = nodes[1].node.get_and_clear_pending_msg_events(); match events.pop().unwrap() { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. } } => { - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. }, + } => { + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false); }, _ => panic!("Unexpected event"), } - } + }; } let expected_error_code = LocalHTLCFailureReason::IncorrectPaymentDetails; @@ -8982,22 +12603,61 @@ pub fn test_bad_secret_hash() { let expected_error_data = [0, 0, 0, 0, 0, 1, 0x86, 0xa0, 0, 0, 0, CHAN_CONFIRM_DEPTH as u8]; // Send a payment with the right payment hash but the wrong payment secret - nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, - RecipientOnionFields::secret_only(random_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + our_payment_hash, + RecipientOnionFields::secret_only(random_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); handle_unknown_invalid_payment_data!(our_payment_hash); - expect_payment_failed!(nodes[0], our_payment_hash, true, expected_error_code, expected_error_data); + expect_payment_failed!( + nodes[0], + our_payment_hash, + true, + expected_error_code, + expected_error_data + ); // Send a payment with a random payment hash, but the right payment secret - nodes[0].node.send_payment_with_route(route.clone(), random_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(random_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + random_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(random_payment_hash.0), + ) + .unwrap(); handle_unknown_invalid_payment_data!(random_payment_hash); - expect_payment_failed!(nodes[0], random_payment_hash, true, expected_error_code, expected_error_data); + expect_payment_failed!( + nodes[0], + random_payment_hash, + true, + expected_error_code, + expected_error_data + ); // Send a payment with a random payment hash and random payment secret - nodes[0].node.send_payment_with_route(route, random_payment_hash, - RecipientOnionFields::secret_only(random_payment_secret), PaymentId(random_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + random_payment_hash, + RecipientOnionFields::secret_only(random_payment_secret), + PaymentId(random_payment_hash.0), + ) + .unwrap(); handle_unknown_invalid_payment_data!(random_payment_hash); - expect_payment_failed!(nodes[0], random_payment_hash, true, expected_error_code, expected_error_data); + expect_payment_failed!( + nodes[0], + random_payment_hash, + true, + expected_error_code, + expected_error_data + ); } #[xtest(feature = "_externalize_tests")] @@ -9020,7 +12680,7 @@ pub fn test_update_err_monitor_lockdown() { let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); // Rebalance the network to generate htlc in the two directions - send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 10_000_000); // Route a HTLC from node 0 to node 1 (but don't settle) let (preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 9_000_000); @@ -9032,13 +12692,28 @@ pub fn test_update_err_monitor_lockdown() { let watchtower = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(chan_1.2).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( - &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; + let new_monitor = + <(BlockHash, channelmonitor::ChannelMonitor)>::read( + &mut io::Cursor::new(&monitor.encode()), + (nodes[0].keys_manager, nodes[0].keys_manager), + ) + .unwrap() + .1; assert!(new_monitor == *monitor); new_monitor }; - let watchtower = test_utils::TestChainMonitor::new(Some(&chain_source), &chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister, &node_cfgs[0].keys_manager); - assert_eq!(watchtower.watch_channel(chan_1.2, new_monitor), Ok(ChannelMonitorUpdateStatus::Completed)); + let watchtower = test_utils::TestChainMonitor::new( + Some(&chain_source), + &chanmon_cfgs[0].tx_broadcaster, + &logger, + &chanmon_cfgs[0].fee_estimator, + &persister, + &node_cfgs[0].keys_manager, + ); + assert_eq!( + watchtower.watch_channel(chan_1.2, new_monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); watchtower }; let block = create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()); @@ -9054,16 +12729,37 @@ pub fn test_update_err_monitor_lockdown() { let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - if let Some(channel) = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1.2).as_funded_mut() { + if let Some(channel) = get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_1.2 + ) + .as_funded_mut() + { assert_eq!(updates.commitment_signed.len(), 1); - if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed[0], &node_cfgs[0].logger) { - assert_eq!(watchtower.chain_monitor.update_channel(chan_1.2, &update), ChannelMonitorUpdateStatus::InProgress); - assert_eq!(nodes[0].chain_monitor.update_channel(chan_1.2, &update), ChannelMonitorUpdateStatus::Completed); - } else { assert!(false); } + if let Ok(Some(update)) = + channel.commitment_signed(&updates.commitment_signed[0], &node_cfgs[0].logger) + { + assert_eq!( + watchtower.chain_monitor.update_channel(chan_1.2, &update), + ChannelMonitorUpdateStatus::InProgress + ); + assert_eq!( + nodes[0].chain_monitor.update_channel(chan_1.2, &update), + ChannelMonitorUpdateStatus::Completed + ); + } else { + assert!(false); + } } else { assert!(false); } @@ -9090,35 +12786,55 @@ pub fn test_concurrent_monitor_claim() { let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); // Rebalance the network to generate htlc in the two directions - send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 10_000_000); // Route a HTLC from node 0 to node 1 (but don't settle) - route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0; + route_payment(&nodes[0], &vec![&nodes[1]][..], 9_000_000).0; // Copy ChainMonitor to simulate watchtower Alice and update block height her ChannelMonitor timeout HTLC onchain let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", "Alice")); let persister = test_utils::TestPersister::new(); - let alice_broadcaster = test_utils::TestBroadcaster::with_blocks( - Arc::new(Mutex::new(nodes[0].blocks.lock().unwrap().clone())), - ); + let alice_broadcaster = test_utils::TestBroadcaster::with_blocks(Arc::new(Mutex::new( + nodes[0].blocks.lock().unwrap().clone(), + ))); let watchtower_alice = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(chan_1.2).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( - &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; + let new_monitor = + <(BlockHash, channelmonitor::ChannelMonitor)>::read( + &mut io::Cursor::new(&monitor.encode()), + (nodes[0].keys_manager, nodes[0].keys_manager), + ) + .unwrap() + .1; assert!(new_monitor == *monitor); new_monitor }; - let watchtower = test_utils::TestChainMonitor::new(Some(&chain_source), &alice_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister, &node_cfgs[0].keys_manager); - assert_eq!(watchtower.watch_channel(chan_1.2, new_monitor), Ok(ChannelMonitorUpdateStatus::Completed)); + let watchtower = test_utils::TestChainMonitor::new( + Some(&chain_source), + &alice_broadcaster, + &logger, + &chanmon_cfgs[0].fee_estimator, + &persister, + &node_cfgs[0].keys_manager, + ); + assert_eq!( + watchtower.watch_channel(chan_1.2, new_monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); watchtower }; let block = create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()); // Make Alice aware of enough blocks that it doesn't think we're violating transaction lock time // requirements here. - const HTLC_TIMEOUT_BROADCAST: u32 = CHAN_CONFIRM_DEPTH + 1 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS; - alice_broadcaster.blocks.lock().unwrap().resize((HTLC_TIMEOUT_BROADCAST) as usize, (block.clone(), HTLC_TIMEOUT_BROADCAST)); + const HTLC_TIMEOUT_BROADCAST: u32 = + CHAN_CONFIRM_DEPTH + 1 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS; + alice_broadcaster + .blocks + .lock() + .unwrap() + .resize((HTLC_TIMEOUT_BROADCAST) as usize, (block.clone(), HTLC_TIMEOUT_BROADCAST)); watchtower_alice.chain_monitor.block_connected(&block, HTLC_TIMEOUT_BROADCAST); // Watchtower Alice should have broadcast a commitment/HTLC-timeout @@ -9133,41 +12849,91 @@ pub fn test_concurrent_monitor_claim() { let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", "Bob")); let persister = test_utils::TestPersister::new(); - let bob_broadcaster = test_utils::TestBroadcaster::with_blocks(Arc::clone(&alice_broadcaster.blocks)); + let bob_broadcaster = + test_utils::TestBroadcaster::with_blocks(Arc::clone(&alice_broadcaster.blocks)); let watchtower_bob = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(chan_1.2).unwrap(); - let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( - &mut io::Cursor::new(&monitor.encode()), (nodes[0].keys_manager, nodes[0].keys_manager)).unwrap().1; + let new_monitor = + <(BlockHash, channelmonitor::ChannelMonitor)>::read( + &mut io::Cursor::new(&monitor.encode()), + (nodes[0].keys_manager, nodes[0].keys_manager), + ) + .unwrap() + .1; assert!(new_monitor == *monitor); new_monitor }; - let watchtower = test_utils::TestChainMonitor::new(Some(&chain_source), &bob_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister, &node_cfgs[0].keys_manager); - assert_eq!(watchtower.watch_channel(chan_1.2, new_monitor), Ok(ChannelMonitorUpdateStatus::Completed)); + let watchtower = test_utils::TestChainMonitor::new( + Some(&chain_source), + &bob_broadcaster, + &logger, + &chanmon_cfgs[0].fee_estimator, + &persister, + &node_cfgs[0].keys_manager, + ); + assert_eq!( + watchtower.watch_channel(chan_1.2, new_monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); watchtower }; - watchtower_bob.chain_monitor.block_connected(&create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()), HTLC_TIMEOUT_BROADCAST - 1); + watchtower_bob.chain_monitor.block_connected( + &create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()), + HTLC_TIMEOUT_BROADCAST - 1, + ); // Route another payment to generate another update with still previous HTLC pending - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 3000000); - nodes[1].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 3000000); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert_eq!(updates.update_add_htlcs.len(), 1); - nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[0] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &updates.update_add_htlcs[0]); { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - if let Some(channel) = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1.2).as_funded_mut() { + if let Some(channel) = get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_1.2 + ) + .as_funded_mut() + { assert_eq!(updates.commitment_signed.len(), 1); - if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed[0], &node_cfgs[0].logger) { + if let Ok(Some(update)) = + channel.commitment_signed(&updates.commitment_signed[0], &node_cfgs[0].logger) + { // Watchtower Alice should already have seen the block and reject the update - assert_eq!(watchtower_alice.chain_monitor.update_channel(chan_1.2, &update), ChannelMonitorUpdateStatus::InProgress); - assert_eq!(watchtower_bob.chain_monitor.update_channel(chan_1.2, &update), ChannelMonitorUpdateStatus::Completed); - assert_eq!(nodes[0].chain_monitor.update_channel(chan_1.2, &update), ChannelMonitorUpdateStatus::Completed); - } else { assert!(false); } + assert_eq!( + watchtower_alice.chain_monitor.update_channel(chan_1.2, &update), + ChannelMonitorUpdateStatus::InProgress + ); + assert_eq!( + watchtower_bob.chain_monitor.update_channel(chan_1.2, &update), + ChannelMonitorUpdateStatus::Completed + ); + assert_eq!( + nodes[0].chain_monitor.update_channel(chan_1.2, &update), + ChannelMonitorUpdateStatus::Completed + ); + } else { + assert!(false); + } } else { assert!(false); } @@ -9176,7 +12942,10 @@ pub fn test_concurrent_monitor_claim() { check_added_monitors!(nodes[0], 1); //// Provide one more block to watchtower Bob, expect broadcast of commitment and HTLC-Timeout - watchtower_bob.chain_monitor.block_connected(&create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()), HTLC_TIMEOUT_BROADCAST); + watchtower_bob.chain_monitor.block_connected( + &create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()), + HTLC_TIMEOUT_BROADCAST, + ); // Watchtower Bob should have broadcast a commitment/HTLC-timeout let bob_state_y; @@ -9190,9 +12959,18 @@ pub fn test_concurrent_monitor_claim() { let height = HTLC_TIMEOUT_BROADCAST + 1; connect_blocks(&nodes[0], height - nodes[0].best_block_info().1); check_closed_broadcast(&nodes[0], 1, true); - check_closed_event!(&nodes[0], 1, ClosureReason::HTLCsTimedOut, false, - [nodes[1].node.get_our_node_id()], 100000); - watchtower_alice.chain_monitor.block_connected(&create_dummy_block(BlockHash::all_zeros(), 42, vec![bob_state_y.clone()]), height); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::HTLCsTimedOut, + false, + [nodes[1].node.get_our_node_id()], + 100000 + ); + watchtower_alice.chain_monitor.block_connected( + &create_dummy_block(BlockHash::all_zeros(), 42, vec![bob_state_y.clone()]), + height, + ); check_added_monitors(&nodes[0], 1); { let htlc_txn = alice_broadcaster.txn_broadcast(); @@ -9220,24 +12998,59 @@ pub fn test_pre_lockin_no_chan_closed_update() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // Create an initial channel - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let mut open_chan_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_chan_msg); - let accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_chan_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_chan_msg); // Move the first channel through the funding flow... - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); - let channel_id = ChannelId::v1_from_funding_outpoint(crate::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }); - nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id, data: "Hi".to_owned() }); + let funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); + let channel_id = ChannelId::v1_from_funding_outpoint(crate::chain::transaction::OutPoint { + txid: funding_created_msg.funding_txid, + index: funding_created_msg.funding_output_index, + }); + nodes[0].node.handle_error( + nodes[1].node.get_our_node_id(), + &msgs::ErrorMessage { channel_id, data: "Hi".to_owned() }, + ); assert!(nodes[0].chain_monitor.added_monitors.lock().unwrap().is_empty()); - check_closed_event!(nodes[0], 2, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString("Hi".to_string()) }, true, - [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 2, + ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString("Hi".to_string()) }, + true, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[xtest(feature = "_externalize_tests")] @@ -9257,8 +13070,8 @@ pub fn test_htlc_no_detection() { // Create some initial channels let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); - send_payment(&nodes[0], &vec!(&nodes[1])[..], 1_000_000); - let (_, our_payment_hash, ..) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 2_000_000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 1_000_000); + let (_, our_payment_hash, ..) = route_payment(&nodes[0], &vec![&nodes[1]][..], 2_000_000); let local_txn = get_local_commitment_txn!(nodes[0], chan_1.2); assert_eq!(local_txn[0].input.len(), 1); assert_eq!(local_txn[0].output.len(), 3); @@ -9269,10 +13082,20 @@ pub fn test_htlc_no_detection() { connect_block(&nodes[0], &block); // We deliberately connect the local tx twice as this should provoke a failure calling // this test before #653 fix. - chain::Listen::block_connected(&nodes[0].chain_monitor.chain_monitor, &block, nodes[0].best_block_info().1 + 1); + chain::Listen::block_connected( + &nodes[0].chain_monitor.chain_monitor, + &block, + nodes[0].best_block_info().1 + 1, + ); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[0], TEST_FINAL_CLTV); let htlc_timeout = { @@ -9284,12 +13107,17 @@ pub fn test_htlc_no_detection() { node_txn[0].clone() }; - connect_block(&nodes[0], &create_dummy_block(nodes[0].best_block_hash(), 42, vec![htlc_timeout.clone()])); + connect_block( + &nodes[0], + &create_dummy_block(nodes[0].best_block_hash(), 42, vec![htlc_timeout.clone()]), + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); expect_payment_failed!(nodes[0], our_payment_hash, false); } -fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain_before_fulfill: bool) { +fn do_test_onchain_htlc_settlement_after_close( + broadcast_alice: bool, go_onchain_before_fulfill: bool, +) { // If we route an HTLC, then learn the HTLC's preimage after the upstream channel has been // force-closed, we must claim that HTLC on-chain. (Given an HTLC forwarded from Alice --> Bob --> // Carol, Alice would be the upstream node, and Carol the downstream.) @@ -9314,7 +13142,8 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain // Steps (1) and (2): // Send an HTLC Alice --> Bob --> Carol, but Carol doesn't settle the HTLC back. - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000); // Check that Alice's commitment transaction now contains an output for this HTLC. let alice_txn = get_local_commitment_txn!(nodes[0], chan_ab.2); @@ -9336,20 +13165,42 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain counterparty_node = 0; } let error_message = "Channel force-closed"; - nodes[force_closing_node].node.force_close_broadcasting_latest_txn(&chan_ab.2, &nodes[counterparty_node].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[force_closing_node] + .node + .force_close_broadcasting_latest_txn( + &chan_ab.2, + &nodes[counterparty_node].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[force_closing_node], true); check_added_monitors!(nodes[force_closing_node], 1); - check_closed_event!(nodes[force_closing_node], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[counterparty_node].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[force_closing_node], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[counterparty_node].node.get_our_node_id()], + 100000 + ); if go_onchain_before_fulfill { let txn_to_broadcast = match broadcast_alice { true => alice_txn.clone(), - false => get_local_commitment_txn!(nodes[1], chan_ab.2) + false => get_local_commitment_txn!(nodes[1], chan_ab.2), }; - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![txn_to_broadcast[0].clone()])); + connect_block( + &nodes[1], + &create_dummy_block(nodes[1].best_block_hash(), 42, vec![txn_to_broadcast[0].clone()]), + ); if broadcast_alice { check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); } } @@ -9367,9 +13218,19 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain assert!(carol_updates.update_fee.is_none()); assert_eq!(carol_updates.update_fulfill_htlcs.len(), 1); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &carol_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &carol_updates.update_fulfill_htlcs[0], + ); let went_onchain = go_onchain_before_fulfill || force_closing_node == 1; - expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], if went_onchain { None } else { Some(1000) }, went_onchain, false); + expect_payment_forwarded!( + nodes[1], + nodes[0], + nodes[2], + if went_onchain { None } else { Some(1000) }, + went_onchain, + false + ); // If Alice broadcasted but Bob doesn't know yet, here he prepares to tell her about the preimage. if !go_onchain_before_fulfill && broadcast_alice { let events = nodes[1].node.get_and_clear_pending_msg_events(); @@ -9381,7 +13242,10 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain _ => panic!("Unexpected event"), }; } - nodes[1].node.handle_commitment_signed_batch_test(nodes[2].node.get_our_node_id(), &carol_updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[2].node.get_our_node_id(), + &carol_updates.commitment_signed, + ); // One monitor update for the preimage to update the Bob<->Alice channel, one monitor update // Carol<->Bob's updated commitment transaction info. check_added_monitors!(nodes[1], 2); @@ -9405,7 +13269,10 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain nodes[2].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bob_revocation); check_added_monitors!(nodes[2], 1); - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bob_updates.commitment_signed); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bob_updates.commitment_signed, + ); check_added_monitors!(nodes[2], 1); let events = nodes[2].node.get_and_clear_pending_msg_events(); @@ -9423,14 +13290,25 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain // If this test requires the force-closed channel to not be on-chain until after the fulfill, // here's where we put said channel's commitment tx on-chain. let mut txn_to_broadcast = alice_txn.clone(); - if !broadcast_alice { txn_to_broadcast = get_local_commitment_txn!(nodes[1], chan_ab.2); } + if !broadcast_alice { + txn_to_broadcast = get_local_commitment_txn!(nodes[1], chan_ab.2); + } if !go_onchain_before_fulfill { - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![txn_to_broadcast[0].clone()])); + connect_block( + &nodes[1], + &create_dummy_block(nodes[1].best_block_hash(), 42, vec![txn_to_broadcast[0].clone()]), + ); // If Bob was the one to force-close, he will have already passed these checks earlier. if broadcast_alice { check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); } let mut bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); if broadcast_alice { @@ -9459,7 +13337,10 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain check_spends!(bob_txn[0], txn_to_broadcast[0]); assert_eq!(bob_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); } else { - assert_eq!(bob_txn.len(), if nodes[1].connect_style.borrow().updates_best_block_first() { 3 } else { 2 }); + assert_eq!( + bob_txn.len(), + if nodes[1].connect_style.borrow().updates_best_block_first() { 3 } else { 2 } + ); let htlc_tx = bob_txn.pop().unwrap(); check_spends!(htlc_tx, txn_to_broadcast[0]); assert_eq!(htlc_tx.input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT + 1); @@ -9484,16 +13365,31 @@ pub fn test_duplicate_temporary_channel_id_from_different_peers() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Create an first channel channel - nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let mut open_chan_msg_chan_1_0 = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .create_channel(nodes[0].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let mut open_chan_msg_chan_1_0 = get_event_msg!( + nodes[1], + MessageSendEvent::SendOpenChannel, + nodes[0].node.get_our_node_id() + ); // Create an second channel - nodes[2].node.create_channel(nodes[0].node.get_our_node_id(), 100000, 10001, 43, None, None).unwrap(); - let mut open_chan_msg_chan_2_0 = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id()); + nodes[2] + .node + .create_channel(nodes[0].node.get_our_node_id(), 100000, 10001, 43, None, None) + .unwrap(); + let mut open_chan_msg_chan_2_0 = get_event_msg!( + nodes[2], + MessageSendEvent::SendOpenChannel, + nodes[0].node.get_our_node_id() + ); // Modify the `OpenChannel` from `nodes[2]` to `nodes[0]` to ensure that it uses the same // `temporary_channel_id` as the `OpenChannel` from nodes[1] to nodes[0]. - open_chan_msg_chan_2_0.common_fields.temporary_channel_id = open_chan_msg_chan_1_0.common_fields.temporary_channel_id; + open_chan_msg_chan_2_0.common_fields.temporary_channel_id = + open_chan_msg_chan_1_0.common_fields.temporary_channel_id; // Assert that `nodes[0]` can accept both `OpenChannel` requests, even though they use the same // `temporary_channel_id` as they are from different peers. @@ -9504,7 +13400,10 @@ pub fn test_duplicate_temporary_channel_id_from_different_peers() { match &events[0] { MessageSendEvent::SendAcceptChannel { node_id, msg } => { assert_eq!(node_id, &nodes[1].node.get_our_node_id()); - assert_eq!(msg.common_fields.temporary_channel_id, open_chan_msg_chan_1_0.common_fields.temporary_channel_id); + assert_eq!( + msg.common_fields.temporary_channel_id, + open_chan_msg_chan_1_0.common_fields.temporary_channel_id + ); }, _ => panic!("Unexpected event"), } @@ -9517,7 +13416,10 @@ pub fn test_duplicate_temporary_channel_id_from_different_peers() { match &events[0] { MessageSendEvent::SendAcceptChannel { node_id, msg } => { assert_eq!(node_id, &nodes[2].node.get_our_node_id()); - assert_eq!(msg.common_fields.temporary_channel_id, open_chan_msg_chan_1_0.common_fields.temporary_channel_id); + assert_eq!( + msg.common_fields.temporary_channel_id, + open_chan_msg_chan_1_0.common_fields.temporary_channel_id + ); }, _ => panic!("Unexpected event"), } @@ -9549,24 +13451,49 @@ pub fn test_peer_funding_sidechannel() { let cs_funding_events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(cs_funding_events.len(), 1); match cs_funding_events[0] { - Event::FundingGenerationReady { .. } => {} + Event::FundingGenerationReady { .. } => {}, _ => panic!("Unexpected event {:?}", cs_funding_events), } - nodes[1].node.funding_transaction_generated_unchecked(temp_chan_id_ca, nodes[0].node.get_our_node_id(), tx.clone(), funding_output.index).unwrap(); - let funding_created_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingCreated, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .funding_transaction_generated_unchecked( + temp_chan_id_ca, + nodes[0].node.get_our_node_id(), + tx.clone(), + funding_output.index, + ) + .unwrap(); + let funding_created_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingCreated, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_created(nodes[1].node.get_our_node_id(), &funding_created_msg); get_event_msg!(nodes[0], MessageSendEvent::SendFundingSigned, nodes[1].node.get_our_node_id()); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); check_added_monitors!(nodes[0], 1); - let res = nodes[0].node.funding_transaction_generated(temp_chan_id_ab, nodes[1].node.get_our_node_id(), tx.clone()); + let res = nodes[0].node.funding_transaction_generated( + temp_chan_id_ab, + nodes[1].node.get_our_node_id(), + tx.clone(), + ); let err_msg = format!("{:?}", res.unwrap_err()); assert!(err_msg.contains("An existing channel using ID")); assert!(err_msg.contains("is open with peer")); let channel_id = ChannelId::v1_from_funding_outpoint(funding_output); - let reason = ClosureReason::ProcessingError { err: format!("An existing channel using ID {} is open with peer {}", channel_id, nodes[1].node.get_our_node_id()), }; - check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(temp_chan_id_ab, true, reason)]); + let reason = ClosureReason::ProcessingError { + err: format!( + "An existing channel using ID {} is open with peer {}", + channel_id, + nodes[1].node.get_our_node_id() + ), + }; + check_closed_events( + &nodes[0], + &[ExpectedCloseEvent::from_id_reason(temp_chan_id_ab, true, reason)], + ); get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id()); } @@ -9594,11 +13521,22 @@ pub fn test_duplicate_conflicting_funding_from_second_peer() { let dummy_monitor = get_monitor!(nodes[2], dummy_chan_id).clone(); nodes[0].chain_monitor.chain_monitor.watch_channel(real_chan_id, dummy_monitor).unwrap(); - nodes[0].node.funding_transaction_generated(temp_chan_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + nodes[0] + .node + .funding_transaction_generated(temp_chan_id, nodes[1].node.get_our_node_id(), tx.clone()) + .unwrap(); - let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let mut funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); @@ -9607,8 +13545,12 @@ pub fn test_duplicate_conflicting_funding_from_second_peer() { // watch_channel call which failed), but zero monitor updates. check_added_monitors!(nodes[0], 1); get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id()); - let err_reason = ClosureReason::ProcessingError { err: "Channel ID was a duplicate".to_owned() }; - check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(temp_chan_id, true, err_reason)]); + let err_reason = + ClosureReason::ProcessingError { err: "Channel ID was a duplicate".to_owned() }; + check_closed_events( + &nodes[0], + &[ExpectedCloseEvent::from_id_reason(temp_chan_id, true, err_reason)], + ); } #[xtest(feature = "_externalize_tests")] @@ -9624,25 +13566,49 @@ pub fn test_duplicate_funding_err_in_funding() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let (_, _, _, real_channel_id, funding_tx) = create_chan_between_nodes(&nodes[0], &nodes[1]); - let real_chan_funding_txo = chain::transaction::OutPoint { txid: funding_tx.compute_txid(), index: 0 }; + let real_chan_funding_txo = + chain::transaction::OutPoint { txid: funding_tx.compute_txid(), index: 0 }; assert_eq!(ChannelId::v1_from_funding_outpoint(real_chan_funding_txo), real_channel_id); - nodes[2].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let mut open_chan_msg = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[2] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let mut open_chan_msg = get_event_msg!( + nodes[2], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); let node_c_temp_chan_id = open_chan_msg.common_fields.temporary_channel_id; open_chan_msg.common_fields.temporary_channel_id = real_channel_id; nodes[1].node.handle_open_channel(nodes[2].node.get_our_node_id(), &open_chan_msg); - let mut accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[2].node.get_our_node_id()); + let mut accept_chan_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[2].node.get_our_node_id() + ); accept_chan_msg.common_fields.temporary_channel_id = node_c_temp_chan_id; nodes[2].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_chan_msg); // Now that we have a second channel with the same funding txo, send a bogus funding message // and let nodes[1] remove the inbound channel. - let (_, funding_tx, _) = create_funding_transaction(&nodes[2], &nodes[1].node.get_our_node_id(), 100_000, 42); + let (_, funding_tx, _) = + create_funding_transaction(&nodes[2], &nodes[1].node.get_our_node_id(), 100_000, 42); - nodes[2].node.funding_transaction_generated(node_c_temp_chan_id, nodes[1].node.get_our_node_id(), funding_tx).unwrap(); - - let mut funding_created_msg = get_event_msg!(nodes[2], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + nodes[2] + .node + .funding_transaction_generated( + node_c_temp_chan_id, + nodes[1].node.get_our_node_id(), + funding_tx, + ) + .unwrap(); + + let mut funding_created_msg = get_event_msg!( + nodes[2], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); funding_created_msg.temporary_channel_id = real_channel_id; // Make the signature invalid by changing the funding output funding_created_msg.funding_output_index += 10; @@ -9669,10 +13635,24 @@ pub fn test_duplicate_chan_id() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // Create an initial channel - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let mut open_chan_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_chan_msg); - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); // Try to create a second channel with the same temporary_channel_id as the first and check // that it is rejected. @@ -9681,7 +13661,10 @@ pub fn test_duplicate_chan_id() { let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { // Technically, at this point, nodes[1] would be justified in thinking both the // first (valid) and second (invalid) channels are closed, given they both have // the same non-temporary channel_id. However, currently we do not, so we just @@ -9694,14 +13677,27 @@ pub fn test_duplicate_chan_id() { } // Move the first channel through the funding flow... - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let mut funding_created_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); let channel_id = ChannelId::v1_from_funding_txid( - funding_created_msg.funding_txid.as_byte_array(), funding_created_msg.funding_output_index + funding_created_msg.funding_txid.as_byte_array(), + funding_created_msg.funding_output_index, ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msg); @@ -9713,9 +13709,16 @@ pub fn test_duplicate_chan_id() { } expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); - let funding_outpoint = crate::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }; + let funding_outpoint = crate::chain::transaction::OutPoint { + txid: funding_created_msg.funding_txid, + index: funding_created_msg.funding_output_index, + }; let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint); // Now we have the first channel past funding_created (ie it has a txid-based channel_id, not a @@ -9730,7 +13733,10 @@ pub fn test_duplicate_chan_id() { let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { // Technically, at this point, nodes[1] would be justified in thinking both // channels are closed, but currently we do not, so we just move forward with it. assert_eq!(msg.channel_id, open_chan_msg.common_fields.temporary_channel_id); @@ -9741,26 +13747,47 @@ pub fn test_duplicate_chan_id() { } // Now try to create a second channel which has a duplicate funding output. - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let open_chan_2_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let open_chan_2_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_chan_2_msg); - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); // Get and check the FundingGenerationReady event let funding_created = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let mut a_peer_state = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let mut a_peer_state = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); // Once we call `get_funding_created` the channel has a duplicate channel_id as // another channel in the ChannelManager - an invalid state. Thus, we'd panic later when we // try to create another channel. Instead, we drop the channel entirely here (leaving the // channelmanager in a possibly nonsense state instead). - let mut channel = a_peer_state.channel_by_id.remove(&open_chan_2_msg.common_fields.temporary_channel_id).unwrap(); + let mut channel = a_peer_state + .channel_by_id + .remove(&open_chan_2_msg.common_fields.temporary_channel_id) + .unwrap(); if let Some(mut chan) = channel.as_unfunded_outbound_v1_mut() { let logger = test_utils::TestLogger::new(); - chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap() + chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger) + .map_err(|_| ()) + .unwrap() } else { panic!("Unexpected Channel phase") - }.unwrap() + } + .unwrap() }; check_added_monitors!(nodes[0], 0); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created); @@ -9768,18 +13795,26 @@ pub fn test_duplicate_chan_id() { // without trying to persist the `ChannelMonitor`. check_added_monitors!(nodes[1], 0); - check_closed_events(&nodes[1], &[ - ExpectedCloseEvent::from_id_reason(funding_created.temporary_channel_id, false, ClosureReason::ProcessingError { - err: "Already had channel with the new channel_id".to_owned() - }) - ]); + check_closed_events( + &nodes[1], + &[ExpectedCloseEvent::from_id_reason( + funding_created.temporary_channel_id, + false, + ClosureReason::ProcessingError { + err: "Already had channel with the new channel_id".to_owned(), + }, + )], + ); // ...still, nodes[1] will reject the duplicate channel. { let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { // Technically, at this point, nodes[1] would be justified in thinking both // channels are closed, but currently we do not, so we just move forward with it. assert_eq!(msg.channel_id, channel_id); @@ -9805,8 +13840,10 @@ pub fn test_duplicate_chan_id() { assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx); - let (channel_ready, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); - let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); + let (channel_ready, _) = + create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); + let (announcement, as_update, bs_update) = + create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update); send_payment(&nodes[0], &[&nodes[1]], 8000000); @@ -9834,26 +13871,51 @@ pub fn test_error_chans_closed() { assert_eq!(nodes[2].node.list_usable_channels().len(), 1); // Closing a channel from a different peer has no effect - nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id: chan_3.2, data: "ERR".to_owned() }); + nodes[0].node.handle_error( + nodes[1].node.get_our_node_id(), + &msgs::ErrorMessage { channel_id: chan_3.2, data: "ERR".to_owned() }, + ); assert_eq!(nodes[0].node.list_usable_channels().len(), 3); // Closing one channel doesn't impact others - nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id: chan_2.2, data: "ERR".to_owned() }); + nodes[0].node.handle_error( + nodes[1].node.get_our_node_id(), + &msgs::ErrorMessage { channel_id: chan_2.2, data: "ERR".to_owned() }, + ); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], false); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString("ERR".to_string()) }, - [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString("ERR".to_string()) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0).len(), 1); assert_eq!(nodes[0].node.list_usable_channels().len(), 2); - assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_1.2 || nodes[0].node.list_usable_channels()[1].channel_id == chan_1.2); - assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2 || nodes[0].node.list_usable_channels()[1].channel_id == chan_3.2); + assert!( + nodes[0].node.list_usable_channels()[0].channel_id == chan_1.2 + || nodes[0].node.list_usable_channels()[1].channel_id == chan_1.2 + ); + assert!( + nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2 + || nodes[0].node.list_usable_channels()[1].channel_id == chan_3.2 + ); // A null channel ID should close all channels let _chan_4 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); - nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id: ChannelId::new_zero(), data: "ERR".to_owned() }); + nodes[0].node.handle_error( + nodes[1].node.get_our_node_id(), + &msgs::ErrorMessage { channel_id: ChannelId::new_zero(), data: "ERR".to_owned() }, + ); check_added_monitors!(nodes[0], 2); - check_closed_event!(nodes[0], 2, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString("ERR".to_string()) }, - [nodes[1].node.get_our_node_id(); 2], 100000); + check_closed_event!( + nodes[0], + 2, + ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString("ERR".to_string()) }, + [nodes[1].node.get_our_node_id(); 2], + 100000 + ); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); match events[0] { @@ -9895,29 +13957,70 @@ pub fn test_invalid_funding_tx() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 10_000, 42, None, None).unwrap(); - nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id())); - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 10_000, 42, None, None) + .unwrap(); + nodes[1].node.handle_open_channel( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ), + ); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); - let (temporary_channel_id, mut tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); + let (temporary_channel_id, mut tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); // Create a witness program which can be spent by a 4-empty-stack-elements witness and which is // 136 bytes long. This matches our "accepted HTLC preimage spend" matching, previously causing // a panic as we'd try to extract a 32 byte preimage from a witness element without checking // its length. - let mut wit_program: Vec = channelmonitor::deliberately_bogus_accepted_htlc_witness_program(); + let mut wit_program: Vec = + channelmonitor::deliberately_bogus_accepted_htlc_witness_program(); let wit_program_script: ScriptBuf = wit_program.into(); for output in tx.output.iter_mut() { // Make the confirmed funding transaction have a bogus script_pubkey output.script_pubkey = ScriptBuf::new_p2wsh(&wit_program_script.wscript_hash()); } - nodes[0].node.funding_transaction_generated_unchecked(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone(), 0).unwrap(); - nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id())); + nodes[0] + .node + .funding_transaction_generated_unchecked( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + 0, + ) + .unwrap(); + nodes[1].node.handle_funding_created( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_funding_signed( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[0], 1); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); @@ -9930,37 +14033,51 @@ pub fn test_invalid_funding_tx() { let expected_err = "funding tx had wrong script/value or output index"; confirm_transaction_at(&nodes[1], &tx, 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: expected_err.to_string() }, - [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { err: expected_err.to_string() }, + [nodes[0].node.get_our_node_id()], + 100000 + ); check_added_monitors!(nodes[1], 1); let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events_2.len(), 1); if let MessageSendEvent::HandleError { node_id, action } = &events_2[0] { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); if let msgs::ErrorAction::DisconnectPeer { msg } = action { - assert_eq!(msg.as_ref().unwrap().data, "Channel closed because of an exception: ".to_owned() + expected_err); - } else { panic!(); } - } else { panic!(); } + assert_eq!( + msg.as_ref().unwrap().data, + "Channel closed because of an exception: ".to_owned() + expected_err + ); + } else { + panic!(); + } + } else { + panic!(); + } assert_eq!(nodes[1].node.list_channels().len(), 0); // Now confirm a spend of the (bogus) funding transaction. As long as the witness is 5 elements // long the ChannelMonitor will try to read 32 bytes from the second-to-last element, panicing // as its not 32 bytes long. let mut spend_tx = Transaction { - version: Version::TWO, lock_time: LockTime::ZERO, - input: tx.output.iter().enumerate().map(|(idx, _)| TxIn { - previous_output: BitcoinOutPoint { - txid: tx.compute_txid(), - vout: idx as u32, - }, - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, - witness: Witness::from_slice(&channelmonitor::deliberately_bogus_accepted_htlc_witness()) - }).collect(), - output: vec![TxOut { - value: Amount::from_sat(1000), - script_pubkey: ScriptBuf::new(), - }] + version: Version::TWO, + lock_time: LockTime::ZERO, + input: tx + .output + .iter() + .enumerate() + .map(|(idx, _)| TxIn { + previous_output: BitcoinOutPoint { txid: tx.compute_txid(), vout: idx as u32 }, + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, + witness: Witness::from_slice( + &channelmonitor::deliberately_bogus_accepted_htlc_witness(), + ), + }) + .collect(), + output: vec![TxOut { value: Amount::from_sat(1000), script_pubkey: ScriptBuf::new() }], }; check_spends!(spend_tx, tx); mine_transaction(&nodes[1], &spend_tx); @@ -9980,26 +14097,57 @@ pub fn test_coinbase_funding_tx() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); // Create the coinbase funding transaction. - let (temporary_channel_id, tx, _) = create_coinbase_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + let (temporary_channel_id, tx, _) = create_coinbase_funding_transaction( + &nodes[0], + &nodes[1].node.get_our_node_id(), + 100000, + 42, + ); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let funding_created = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed); check_added_monitors!(nodes[0], 1); @@ -10016,7 +14164,14 @@ pub fn test_coinbase_funding_tx() { // Now connect one more block which results in 100 confirmations of the coinbase transaction. connect_blocks(&nodes[0], 1); // There should now be a `channel_ready` which can be handled. - let _ = &nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &get_event_msg!(&nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id())); + let _ = &nodes[1].node.handle_channel_ready( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + &nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ), + ); confirm_transaction_at(&nodes[1], &tx, 1); connect_blocks(&nodes[1], COINBASE_MATURITY - 2); @@ -10057,10 +14212,23 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t nodes[1].node.peer_disconnected(nodes[2].node.get_our_node_id()); nodes[2].node.peer_disconnected(nodes[1].node.get_our_node_id()); let error_message = "Channel force-closed"; - nodes[1].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &channel_id, + &nodes[2].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[2].node.get_our_node_id()], 100000); - check_added_monitors!(nodes[1], 1); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_added_monitors!(nodes[1], 1); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(node_txn.len(), 1); @@ -10069,7 +14237,10 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t connect_blocks(&nodes[1], TEST_FINAL_CLTV - LATENCY_GRACE_PERIOD_BLOCKS); } nodes[1].chain_monitor.chain_monitor.transactions_confirmed( - &nodes[1].get_block_header(conf_height), &[(0, &node_txn[0])], conf_height); + &nodes[1].get_block_header(conf_height), + &[(0, &node_txn[0])], + conf_height, + ); if test_height_before_timelock { // If we confirmed the close transaction, but timelocks have not yet expired, we should not // generate any events or broadcast any transactions @@ -10090,8 +14261,17 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t // should immediately fail-backwards the HTLC to the previous hop, without waiting for an // additional block built on top of the current chain. nodes[1].chain_monitor.chain_monitor.transactions_confirmed( - &nodes[1].get_block_header(conf_height + 1), &[(0, htlc_tx)], conf_height + 1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: channel_id }]); + &nodes[1].get_block_header(conf_height + 1), + &[(0, htlc_tx)], + conf_height + 1, + ); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id + }] + ); check_added_monitors!(nodes[1], 1); let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -10100,21 +14280,35 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, true, true); - expect_payment_failed_with_update!(nodes[0], payment_hash, false, chan_announce.contents.short_channel_id, true); + expect_payment_failed_with_update!( + nodes[0], + payment_hash, + false, + chan_announce.contents.short_channel_id, + true + ); // We should also generate a SpendableOutputs event with the to_self output (once the // timelock is up). - connect_blocks(&nodes[1], (BREAKDOWN_TIMEOUT as u32) - TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS - 1); + connect_blocks( + &nodes[1], + (BREAKDOWN_TIMEOUT as u32) - TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS - 1, + ); let descriptor_spend_txn = check_spendable_outputs!(nodes[1], node_cfgs[1].keys_manager); assert_eq!(descriptor_spend_txn.len(), 1); // When the HTLC times out on the A<->B edge, the B<->C channel will fail the HTLC back to // avoid the A<->B channel closing (even though it already has). This will generate a // spurious HTLCHandlingFailed event. - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], - vec![HTLCDestination::NextHopChannel { node_id: Some(node_c_id), channel_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { node_id: Some(node_c_id), channel_id }] + ); } } @@ -10132,20 +14326,32 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) { let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); let route = get_route!(nodes[0], payment_params, 10_000).unwrap(); - let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[1]); + let (our_payment_preimage, our_payment_hash, our_payment_secret) = + get_payment_preimage_hash!(&nodes[1]); { - nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.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); let mut payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); } expect_pending_htlcs_forwardable!(nodes[1]); @@ -10153,13 +14359,22 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) { { // Note that we use a different PaymentId here to allow us to duplicativly pay - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_secret.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_secret.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); let mut payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); // At this point, nodes[1] would notice it has too much value for the payment. It will // assume the second is a privacy attack (no longer particularly relevant @@ -10178,34 +14393,66 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) { HTLCDestination::FailedPayment { payment_hash: our_payment_hash }, HTLCDestination::FailedPayment { payment_hash: our_payment_hash }, ]; - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], expected_destinations); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + expected_destinations + ); nodes[1].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[1], 1); let fail_updates_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert_eq!(fail_updates_1.update_fail_htlcs.len(), 2); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[1]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &fail_updates_1.update_fail_htlcs[0], + ); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &fail_updates_1.update_fail_htlcs[1], + ); commitment_signed_dance!(nodes[0], nodes[1], fail_updates_1.commitment_signed, false); let failure_events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(failure_events.len(), 4); - if let Event::PaymentPathFailed { .. } = failure_events[0] {} else { panic!(); } - if let Event::PaymentFailed { .. } = failure_events[1] {} else { panic!(); } - if let Event::PaymentPathFailed { .. } = failure_events[2] {} else { panic!(); } - if let Event::PaymentFailed { .. } = failure_events[3] {} else { panic!(); } + if let Event::PaymentPathFailed { .. } = failure_events[0] { + } else { + panic!(); + } + if let Event::PaymentFailed { .. } = failure_events[1] { + } else { + panic!(); + } + if let Event::PaymentPathFailed { .. } = failure_events[2] { + } else { + panic!(); + } + if let Event::PaymentFailed { .. } = failure_events[3] { + } else { + panic!(); + } } else { // Let the second HTLC fail and claim the first - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }] + ); nodes[1].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[1], 1); let fail_updates_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &fail_updates_1.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], fail_updates_1.commitment_signed, false); - expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, PaymentFailedConditions::new()); + expect_payment_failed_conditions( + &nodes[0], + our_payment_hash, + true, + PaymentFailedConditions::new(), + ); claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage); } @@ -10239,19 +14486,25 @@ pub fn test_inconsistent_mpp_params() { create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0); create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0); - let chan_2_3 =create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0); + let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0); - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()) + .unwrap(); let mut route = get_route!(nodes[0], payment_params, 15_000_000).unwrap(); assert_eq!(route.paths.len(), 2); route.paths.sort_by(|path_a, _| { // Sort the path so that the path through nodes[1] comes first if path_a.hops[0].pubkey == nodes[1].node.get_our_node_id() { - core::cmp::Ordering::Less } else { core::cmp::Ordering::Greater } + core::cmp::Ordering::Less + } else { + core::cmp::Ordering::Greater + } }); - let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[3]); + let (our_payment_preimage, our_payment_hash, our_payment_secret) = + get_payment_preimage_hash!(&nodes[3]); let cur_height = nodes[0].best_block_info().1; let payment_id = PaymentId([42; 32]); @@ -10261,23 +14514,60 @@ pub fn test_inconsistent_mpp_params() { // ultimately have, just not right away. let mut dup_route = route.clone(); dup_route.paths.push(route.paths[1].clone()); - nodes[0].node.test_add_new_pending_payment(our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), payment_id, &dup_route).unwrap() + nodes[0] + .node + .test_add_new_pending_payment( + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + payment_id, + &dup_route, + ) + .unwrap() }; - nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), 15_000_000, cur_height, payment_id, - &None, session_privs[0]).unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &route.paths[0], + &our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + 15_000_000, + cur_height, + payment_id, + &None, + session_privs[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); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 15_000_000, our_payment_hash, Some(our_payment_secret), events.pop().unwrap(), false, None); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + 15_000_000, + our_payment_hash, + Some(our_payment_secret), + events.pop().unwrap(), + false, + None, + ); } assert!(nodes[3].node.get_and_clear_pending_events().is_empty()); - nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), 14_000_000, cur_height, payment_id, &None, session_privs[1]).unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &route.paths[1], + &our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + 14_000_000, + cur_height, + payment_id, + &None, + session_privs[1], + ) + .unwrap(); check_added_monitors!(nodes[0], 1); { @@ -10285,7 +14575,9 @@ pub fn test_inconsistent_mpp_params() { assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[2].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[2] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[2], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[2]); @@ -10295,7 +14587,9 @@ pub fn test_inconsistent_mpp_params() { assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[3].node.handle_update_add_htlc(nodes[2].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[3] + .node + .handle_update_add_htlc(nodes[2].node.get_our_node_id(), &payment_event.msgs[0]); check_added_monitors!(nodes[3], 0); commitment_signed_dance!(nodes[3], nodes[2], payment_event.commitment_msg, true, true); @@ -10305,36 +14599,77 @@ pub fn test_inconsistent_mpp_params() { } expect_pending_htlcs_forwardable_ignore!(nodes[3]); nodes[3].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[3], vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[3], + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }] + ); nodes[3].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[3], 1); let fail_updates_1 = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &fail_updates_1.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[2], nodes[3], fail_updates_1.commitment_signed, false); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_2_3.2 + }] + ); check_added_monitors!(nodes[2], 1); let fail_updates_2 = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &fail_updates_2.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &fail_updates_2.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[2], fail_updates_2.commitment_signed, false); - expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, PaymentFailedConditions::new().mpp_parts_remain()); + expect_payment_failed_conditions( + &nodes[0], + our_payment_hash, + true, + PaymentFailedConditions::new().mpp_parts_remain(), + ); - nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), 15_000_000, cur_height, payment_id, - &None, session_privs[2]).unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &route.paths[1], + &our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + 15_000_000, + cur_height, + payment_id, + &None, + session_privs[2], + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, our_payment_hash, Some(our_payment_secret), events.pop().unwrap(), true, None); - - do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], our_payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + 15_000_000, + our_payment_hash, + Some(our_payment_secret), + events.pop().unwrap(), + true, + None, ); + + do_claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + our_payment_preimage, + )); expect_payment_sent(&nodes[0], our_payment_preimage, Some(None), true, true); } @@ -10354,15 +14689,26 @@ pub fn test_double_partial_claim() { create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0); create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0); - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 15_000_000); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[3], 15_000_000); assert_eq!(route.paths.len(), 2); route.paths.sort_by(|path_a, _| { // Sort the path so that the path through nodes[1] comes first if path_a.hops[0].pubkey == nodes[1].node.get_our_node_id() { - core::cmp::Ordering::Less } else { core::cmp::Ordering::Greater } + core::cmp::Ordering::Less + } else { + core::cmp::Ordering::Greater + } }); - send_along_route_with_secret(&nodes[0], route.clone(), &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 15_000_000, payment_hash, payment_secret); + send_along_route_with_secret( + &nodes[0], + route.clone(), + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + 15_000_000, + payment_hash, + payment_secret, + ); // nodes[3] has now received a PaymentClaimable event...which it will take some (exorbitant) // amount of time to respond to. @@ -10376,17 +14722,39 @@ pub fn test_double_partial_claim() { ]; expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], failed_destinations); - pass_failed_payment_back(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_hash, PaymentFailureReason::RecipientRejected); + pass_failed_payment_back( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_hash, + PaymentFailureReason::RecipientRejected, + ); // nodes[1] now retries one of the two paths... - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); let node_1_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 15_000_000, payment_hash, Some(payment_secret), node_1_msgs, false, None); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + 15_000_000, + payment_hash, + Some(payment_secret), + node_1_msgs, + false, + None, + ); // At this point nodes[3] has received one half of the payment, and the user goes to handle // that PaymentClaimable event they got hours ago and never handled...we should refuse to claim. @@ -10406,7 +14774,10 @@ enum ExposureEvent { AtUpdateFeeOutbound, } -fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_event: ExposureEvent, on_holder_tx: bool, multiplier_dust_limit: bool, apply_excess_fee: bool) { +fn do_test_max_dust_htlc_exposure( + dust_outbound_balance: bool, exposure_breach_event: ExposureEvent, on_holder_tx: bool, + multiplier_dust_limit: bool, apply_excess_fee: bool, +) { // Test that we properly reject dust HTLC violating our `max_dust_htlc_exposure_msat` // policy. // @@ -10425,19 +14796,25 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e // We hard-code the feerate values here but they're re-calculated furter down and asserted. // If the values ever change below these constants should simply be updated. const AT_FEE_OUTBOUND_HTLCS: u64 = 20; - let nondust_htlc_count_in_limit = - if exposure_breach_event == ExposureEvent::AtUpdateFeeOutbound { + let nondust_htlc_count_in_limit = if exposure_breach_event == ExposureEvent::AtUpdateFeeOutbound + { AT_FEE_OUTBOUND_HTLCS - } else { 0 }; + } else { + 0 + }; let initial_feerate = if apply_excess_fee { 253 * 2 } else { 253 }; let expected_dust_buffer_feerate = initial_feerate + 2530; - let mut commitment_tx_cost_msat = commit_tx_fee_msat(initial_feerate - 253, nondust_htlc_count_in_limit, &ChannelTypeFeatures::empty()); - commitment_tx_cost_msat += - if on_holder_tx { - htlc_success_tx_weight(&ChannelTypeFeatures::empty()) - } else { - htlc_timeout_tx_weight(&ChannelTypeFeatures::empty()) - } * (initial_feerate as u64 - 253) * nondust_htlc_count_in_limit; + let mut commitment_tx_cost_msat = commit_tx_fee_msat( + initial_feerate - 253, + nondust_htlc_count_in_limit, + &ChannelTypeFeatures::empty(), + ); + commitment_tx_cost_msat += if on_holder_tx { + htlc_success_tx_weight(&ChannelTypeFeatures::empty()) + } else { + htlc_timeout_tx_weight(&ChannelTypeFeatures::empty()) + } * (initial_feerate as u64 - 253) + * nondust_htlc_count_in_limit; { let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap(); *feerate_lock = initial_feerate; @@ -10447,30 +14824,50 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e // to get roughly the same initial value as the default setting when this test was // originally written. MaxDustHTLCExposure::FeeRateMultiplier((5_000_000 + commitment_tx_cost_msat) / 253) - } else { MaxDustHTLCExposure::FixedLimitMsat(5_000_000 + commitment_tx_cost_msat) }; + } else { + MaxDustHTLCExposure::FixedLimitMsat(5_000_000 + commitment_tx_cost_msat) + }; let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None, None).unwrap(); - let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None, None) + .unwrap(); + let mut open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); open_channel.common_fields.max_htlc_value_in_flight_msat = 50_000_000; open_channel.common_fields.max_accepted_htlcs = 60; if on_holder_tx { open_channel.common_fields.dust_limit_satoshis = 546; } nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); - let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let mut accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); let channel_type_features = ChannelTypeFeatures::only_static_remote_key(); - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42); if on_holder_tx { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - let channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, temporary_channel_id); + let channel = get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + temporary_channel_id + ); if let Some(mut chan) = channel.as_unfunded_outbound_v1_mut() { chan.context.holder_dust_limit_satoshis = 546; } else { @@ -10478,17 +14875,40 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e } } - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); - nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id())); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); + nodes[1].node.handle_funding_created( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_funding_signed( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[0], 1); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); - let (channel_ready, channel_id) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); - let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); + let (channel_ready, channel_id) = + create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); + let (announcement, as_update, bs_update) = + create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update); { @@ -10502,26 +14922,42 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e let (dust_buffer_feerate, max_dust_htlc_exposure_msat) = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let chan_lock = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); let chan = chan_lock.channel_by_id.get(&channel_id).unwrap(); - (chan.context().get_dust_buffer_feerate(None) as u64, - chan.context().get_max_dust_htlc_exposure_msat(253)) + ( + chan.context().get_dust_buffer_feerate(None) as u64, + chan.context().get_max_dust_htlc_exposure_msat(253), + ) }; assert_eq!(dust_buffer_feerate, expected_dust_buffer_feerate as u64); - let dust_outbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + open_channel.common_fields.dust_limit_satoshis - 1) * 1000; - let dust_outbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat; + let dust_outbound_htlc_on_holder_tx_msat: u64 = + (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + + open_channel.common_fields.dust_limit_satoshis + - 1) * 1000; + let dust_outbound_htlc_on_holder_tx: u64 = + max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat; // Substract 3 sats for multiplier and 2 sats for fixed limit to make sure we are 50% below the dust limit. // This is to make sure we fully use the dust limit. If we don't, we could end up with `dust_ibd_htlc_on_holder_tx` being 1 // while `max_dust_htlc_exposure_msat` is not equal to `dust_outbound_htlc_on_holder_tx_msat`. - let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + open_channel.common_fields.dust_limit_satoshis - if multiplier_dust_limit { 3 } else { 2 }) * 1000; - let dust_inbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat; + let dust_inbound_htlc_on_holder_tx_msat: u64 = + (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + + open_channel.common_fields.dust_limit_satoshis + - if multiplier_dust_limit { 3 } else { 2 }) + * 1000; + let dust_inbound_htlc_on_holder_tx: u64 = + max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat; // This test was written with a fixed dust value here, which we retain, but assert that it is, // indeed, dust on both transactions. let dust_htlc_on_counterparty_tx: u64 = 4; let dust_htlc_on_counterparty_tx_msat: u64 = 1_250_000; - let calcd_dust_htlc_on_counterparty_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + open_channel.common_fields.dust_limit_satoshis - if multiplier_dust_limit { 3 } else { 2 }) * 1000; + let calcd_dust_htlc_on_counterparty_tx_msat: u64 = + (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + + open_channel.common_fields.dust_limit_satoshis + - if multiplier_dust_limit { 3 } else { 2 }) + * 1000; assert!(dust_htlc_on_counterparty_tx_msat < dust_inbound_htlc_on_holder_tx_msat); assert!(dust_htlc_on_counterparty_tx_msat < calcd_dust_htlc_on_counterparty_tx_msat); @@ -10558,35 +14994,79 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e } if exposure_breach_event == ExposureEvent::AtHTLCForward { - route.paths[0].hops.last_mut().unwrap().fee_msat = - if on_holder_tx { dust_outbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 1 }; + route.paths[0].hops.last_mut().unwrap().fee_msat = if on_holder_tx { + dust_outbound_htlc_on_holder_tx_msat + } else { + dust_htlc_on_counterparty_tx_msat + 1 + }; // With default dust exposure: 5000 sats if on_holder_tx { - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); } else { - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); } } else if exposure_breach_event == ExposureEvent::AtHTLCReception { - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], if on_holder_tx { dust_inbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 4 }); - nodes[1].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!( + nodes[1], + nodes[0], + if on_holder_tx { + dust_inbound_htlc_on_holder_tx_msat + } else { + dust_htlc_on_counterparty_tx_msat + 4 + } + ); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); let mut events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.remove(0)); - nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[0] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[0], nodes[1], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[0]); - expect_htlc_handling_failed_destinations!(nodes[0].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[0].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }] + ); // With default dust exposure: 5000 sats if on_holder_tx { // Outbound dust balance: 6399 sats - let dust_inbound_overflow = dust_inbound_htlc_on_holder_tx_msat * (dust_inbound_htlc_on_holder_tx + 1); - let dust_outbound_overflow = dust_outbound_htlc_on_holder_tx_msat * dust_outbound_htlc_on_holder_tx + dust_inbound_htlc_on_holder_tx_msat; + let dust_inbound_overflow = + dust_inbound_htlc_on_holder_tx_msat * (dust_inbound_htlc_on_holder_tx + 1); + let dust_outbound_overflow = dust_outbound_htlc_on_holder_tx_msat + * dust_outbound_htlc_on_holder_tx + + dust_inbound_htlc_on_holder_tx_msat; nodes[0].logger.assert_log("lightning::ln::channel", format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", if dust_outbound_balance { dust_outbound_overflow } else { dust_inbound_overflow }, max_dust_htlc_exposure_msat), 1); } else { // Outbound dust balance: 5200 sats @@ -10601,9 +15081,17 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e // we need to add a lot of HTLCs that will become dust at the new feerate // to cross the threshold. for _ in 0..AT_FEE_OUTBOUND_HTLCS { - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(1_000), None); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[1], Some(1_000), None); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); } { let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap(); @@ -10611,7 +15099,11 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e } nodes[0].node.timer_tick_occurred(); check_added_monitors!(nodes[0], 1); - nodes[0].logger.assert_log_contains("lightning::ln::channel", "Cannot afford to send new feerate at 2530 without infringing max dust htlc exposure", 1); + nodes[0].logger.assert_log_contains( + "lightning::ln::channel", + "Cannot afford to send new feerate at 2530 without infringing max dust htlc exposure", + 1, + ); } let _ = nodes[0].node.get_and_clear_pending_msg_events(); @@ -10619,24 +15111,98 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e added_monitors.clear(); } -fn do_test_max_dust_htlc_exposure_by_threshold_type(multiplier_dust_limit: bool, apply_excess_fee: bool) { - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit, apply_excess_fee); +fn do_test_max_dust_htlc_exposure_by_threshold_type( + multiplier_dust_limit: bool, apply_excess_fee: bool, +) { + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtHTLCForward, + true, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCForward, + true, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCReception, + true, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCReception, + false, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtHTLCForward, + false, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtHTLCReception, + false, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtHTLCReception, + true, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCForward, + false, + multiplier_dust_limit, + apply_excess_fee, + ); if !multiplier_dust_limit && !apply_excess_fee { // Because non-dust HTLC transaction fees are included in the dust exposure, trying to // increase the fee to hit a higher dust exposure with a // `MaxDustHTLCExposure::FeeRateMultiplier` is no longer super practical, so we skip these // in the `multiplier_dust_limit` case. - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit, apply_excess_fee); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit, apply_excess_fee); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtUpdateFeeOutbound, + true, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtUpdateFeeOutbound, + false, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtUpdateFeeOutbound, + false, + multiplier_dust_limit, + apply_excess_fee, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtUpdateFeeOutbound, + true, + multiplier_dust_limit, + apply_excess_fee, + ); } } @@ -10667,8 +15233,7 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { let mut config = test_default_channel_config(); // Set the dust limit to the default value - config.channel_config.max_dust_htlc_exposure = - MaxDustHTLCExposure::FeeRateMultiplier(10_000); + config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(10_000); // Make sure the HTLC limits don't get in the way let chan_ty = ChannelTypeFeatures::only_static_remote_key(); config.channel_handshake_limits.min_max_accepted_htlcs = chan_utils::max_htlcs(&chan_ty); @@ -10676,11 +15241,16 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { config.channel_handshake_config.our_htlc_minimum_msat = 1; config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config)]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(config.clone()), Some(config.clone()), Some(config)], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Leave enough on the funder side to let it pay the mining fees for a commit tx with tons of htlcs - let chan_id_1 = create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 1_000_000, 750_000_000).2; + let chan_id_1 = + create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 1_000_000, 750_000_000).2; // First get the channel one HTLC_VALUE HTLC away from the dust limit by sending dust HTLCs // repeatedly until we run out of space. @@ -10690,18 +15260,27 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { while nodes[0].node.list_channels()[0].next_outbound_htlc_minimum_msat == 0 { route_payment(&nodes[0], &[&nodes[1]], HTLC_VALUE); } - assert_ne!(nodes[0].node.list_channels()[0].next_outbound_htlc_limit_msat, 0, - "We don't want to run out of ability to send because of some non-dust limit"); - assert!(nodes[0].node.list_channels()[0].pending_outbound_htlcs.len() < 10, - "We should be able to fill our dust limit without too many HTLCs"); + assert_ne!( + nodes[0].node.list_channels()[0].next_outbound_htlc_limit_msat, + 0, + "We don't want to run out of ability to send because of some non-dust limit" + ); + assert!( + nodes[0].node.list_channels()[0].pending_outbound_htlcs.len() < 10, + "We should be able to fill our dust limit without too many HTLCs" + ); let dust_limit = nodes[0].node.list_channels()[0].next_outbound_htlc_minimum_msat; claim_payment(&nodes[0], &[&nodes[1]], payment_preimage); - assert_ne!(nodes[0].node.list_channels()[0].next_outbound_htlc_minimum_msat, 0, - "Make sure we are able to send once we clear one HTLC"); + assert_ne!( + nodes[0].node.list_channels()[0].next_outbound_htlc_minimum_msat, + 0, + "Make sure we are able to send once we clear one HTLC" + ); // Skip the router complaint when node 0 will attempt to pay node 1 - let (route_0_1, payment_hash_0_1, _, payment_secret_0_1) = get_route_and_payment_hash!(nodes[0], nodes[1], dust_limit * 2); + let (route_0_1, payment_hash_0_1, _, payment_secret_0_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], dust_limit * 2); assert_eq!(nodes[0].node.list_channels().len(), 1); assert_eq!(nodes[1].node.list_channels().len(), 1); @@ -10713,8 +15292,10 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { let commitment_tx_per_htlc_cost = htlc_success_tx_weight(&ChannelTypeFeatures::empty()) * EXCESS_FEERATE as u64; let max_htlcs_remaining = dust_limit * 2 / commitment_tx_per_htlc_cost; - assert!(max_htlcs_remaining < chan_utils::max_htlcs(&chan_ty).into(), - "We should be able to fill our dust limit without too many HTLCs"); + assert!( + max_htlcs_remaining < chan_utils::max_htlcs(&chan_ty).into(), + "We should be able to fill our dust limit without too many HTLCs" + ); for i in 0..max_htlcs_remaining + 1 { assert_ne!(i, max_htlcs_remaining); if nodes[0].node.list_channels()[0].next_outbound_htlc_limit_msat <= dust_limit { @@ -10732,9 +15313,17 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { assert_eq!(nodes[1].node.list_channels()[0].pending_outbound_htlcs.len(), 0); // Send an additional non-dust htlc from 1 to 0, and check the complaint - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], dust_limit * 2); - nodes[1].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], dust_limit * 2); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); let mut events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -10742,7 +15331,10 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[0], nodes[1], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[0]); - expect_htlc_handling_failed_destinations!(nodes[0].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[0].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }] + ); nodes[0].logger.assert_log("lightning::ln::channel", format!("Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx", 2535000, 2530000), 1); @@ -10755,7 +15347,9 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[1].node.handle_update_fail_htlc(nodes[0].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[1] + .node + .handle_update_fail_htlc(nodes[0].node.get_our_node_id(), &updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false); expect_payment_failed!(nodes[1], payment_hash, false); @@ -10765,9 +15359,18 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { assert_eq!(nodes[1].node.list_channels()[0].pending_outbound_htlcs.len(), 0); // Send an additional non-dust htlc from 0 to 1 using the pre-calculated route above, and check the immediate complaint - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route_0_1, payment_hash_0_1, - RecipientOnionFields::secret_only(payment_secret_0_1), PaymentId(payment_hash_0_1.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route_0_1, + payment_hash_0_1, + RecipientOnionFields::secret_only(payment_secret_0_1), + PaymentId(payment_hash_0_1.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); nodes[0].logger.assert_log("lightning::ln::outbound_payment", format!("Failed to send along path due to error: Channel unavailable: Cannot send more than our next-HTLC maximum - {} msat", 2325000), 1); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -10799,9 +15402,16 @@ pub fn test_nondust_htlc_excess_fees_are_dust() { ); let fail = get_htlc_update_msgs(&nodes[0], &nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_fail_htlc(nodes[0].node.get_our_node_id(), &fail.update_fail_htlcs[0]); + nodes[2] + .node + .handle_update_fail_htlc(nodes[0].node.get_our_node_id(), &fail.update_fail_htlcs[0]); commitment_signed_dance!(nodes[2], nodes[0], fail.commitment_signed, false); - expect_payment_failed_conditions(&nodes[2], payment_hash, false, PaymentFailedConditions::new()); + expect_payment_failed_conditions( + &nodes[2], + payment_hash, + false, + PaymentFailedConditions::new(), + ); } fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) { @@ -10842,9 +15452,12 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) // Set `expected_dust_exposure_msat` to match the calculation in `FundedChannel::can_accept_incoming_htlc` // only_static_remote_key: 500_492 + 22 * (724 + 172) / 1000 * 1000 + 22 * 663 / 1000 * 1000 = 533_492 // anchors_zero_htlc_fee: 500_492 + 22 * (1_124 + 172) / 1000 * 1000 = 528_492 - let mut expected_dust_exposure_msat = BASE_DUST_EXPOSURE_MSAT + EXCESS_FEERATE * (commitment_tx_base_weight(&features) + COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 * 1000; + let mut expected_dust_exposure_msat = BASE_DUST_EXPOSURE_MSAT + + EXCESS_FEERATE * (commitment_tx_base_weight(&features) + COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000 * 1000; if features == ChannelTypeFeatures::only_static_remote_key() { - expected_dust_exposure_msat += EXCESS_FEERATE * htlc_timeout_tx_weight(&features) / 1000 * 1000; + expected_dust_exposure_msat += + EXCESS_FEERATE * htlc_timeout_tx_weight(&features) / 1000 * 1000; assert_eq!(expected_dust_exposure_msat, 533_492); } else { assert_eq!(expected_dust_exposure_msat, 528_492); @@ -10859,23 +15472,27 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) // Set node 1's max dust htlc exposure to 1msat below `expected_dust_exposure_msat` let mut fixed_limit_config = default_config.clone(); - fixed_limit_config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FixedLimitMsat(expected_dust_exposure_msat - 1); + fixed_limit_config.channel_config.max_dust_htlc_exposure = + MaxDustHTLCExposure::FixedLimitMsat(expected_dust_exposure_msat - 1); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(default_config), Some(fixed_limit_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(default_config), Some(fixed_limit_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan_id = create_chan_between_nodes_with_value(&nodes[0], &nodes[1], 100_000, 50_000_000).3; let node_1_dust_buffer_feerate = { let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); + let chan_lock = + per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); let chan = chan_lock.channel_by_id.get(&chan_id).unwrap(); chan.context().get_dust_buffer_feerate(None) as u64 }; // Skip the router complaint when node 1 will attempt to pay node 0 - let (route_1_0, payment_hash_1_0, _, payment_secret_1_0) = get_route_and_payment_hash!(nodes[1], nodes[0], NON_DUST_HTLC_MSAT); + let (route_1_0, payment_hash_1_0, _, payment_secret_1_0) = + get_route_and_payment_hash!(nodes[1], nodes[0], NON_DUST_HTLC_MSAT); // Bring node 1's dust htlc exposure up to `BASE_DUST_EXPOSURE_MSAT` for _ in 0..DUST_HTLC_COUNT { @@ -10891,9 +15508,17 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) assert_eq!(nodes[1].node.list_channels()[0].pending_inbound_htlcs.len(), DUST_HTLC_COUNT); // Send an additional non-dust htlc from 0 to 1, and check the complaint - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], NON_DUST_HTLC_MSAT); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], NON_DUST_HTLC_MSAT); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.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); @@ -10901,7 +15526,10 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }] + ); nodes[1].logger.assert_log("lightning::ln::channel", format!("Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx", expected_dust_exposure_msat, expected_dust_exposure_msat - 1), 1); @@ -10914,7 +15542,9 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) assert_eq!(updates.update_fail_htlcs.len(), 1); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false); expect_payment_failed!(nodes[0], payment_hash, false); @@ -10927,10 +15557,19 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) assert_eq!(nodes[1].node.list_channels()[0].pending_inbound_htlcs.len(), DUST_HTLC_COUNT); // Set node 1's max dust htlc exposure equal to the `expected_dust_exposure_msat` - nodes[1].node.update_partial_channel_config(&nodes[0].node.get_our_node_id(), &[chan_id], &ChannelConfigUpdate { - max_dust_htlc_exposure_msat: Some(MaxDustHTLCExposure::FixedLimitMsat(expected_dust_exposure_msat)), - ..ChannelConfigUpdate::default() - }).unwrap(); + nodes[1] + .node + .update_partial_channel_config( + &nodes[0].node.get_our_node_id(), + &[chan_id], + &ChannelConfigUpdate { + max_dust_htlc_exposure_msat: Some(MaxDustHTLCExposure::FixedLimitMsat( + expected_dust_exposure_msat, + )), + ..ChannelConfigUpdate::default() + }, + ) + .unwrap(); // Check a successful payment send_payment(&nodes[0], &[&nodes[1]], NON_DUST_HTLC_MSAT); @@ -10946,24 +15585,47 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) // The `expected_dust_exposure_msat` for the outbound htlc changes in the non-anchor case, as the htlc success and timeout transactions have different weights // only_static_remote_key: 500_492 + 22 * (724 + 172) / 1000 * 1000 + 22 * 703 / 1000 * 1000 = 534_492 if features == ChannelTypeFeatures::only_static_remote_key() { - expected_dust_exposure_msat = BASE_DUST_EXPOSURE_MSAT + EXCESS_FEERATE * (commitment_tx_base_weight(&features) + COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 * 1000 + EXCESS_FEERATE * htlc_success_tx_weight(&features) / 1000 * 1000; + expected_dust_exposure_msat = BASE_DUST_EXPOSURE_MSAT + + EXCESS_FEERATE + * (commitment_tx_base_weight(&features) + COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000 * 1000 + + EXCESS_FEERATE * htlc_success_tx_weight(&features) / 1000 * 1000; assert_eq!(expected_dust_exposure_msat, 534_492); } else { assert_eq!(expected_dust_exposure_msat, 528_492); } // Set node 1's max dust htlc exposure to 1msat below `expected_dust_exposure_msat` - nodes[1].node.update_partial_channel_config(&nodes[0].node.get_our_node_id(), &[chan_id], &ChannelConfigUpdate { - max_dust_htlc_exposure_msat: Some(MaxDustHTLCExposure::FixedLimitMsat(expected_dust_exposure_msat - 1)), - ..ChannelConfigUpdate::default() - }).unwrap(); + nodes[1] + .node + .update_partial_channel_config( + &nodes[0].node.get_our_node_id(), + &[chan_id], + &ChannelConfigUpdate { + max_dust_htlc_exposure_msat: Some(MaxDustHTLCExposure::FixedLimitMsat( + expected_dust_exposure_msat - 1, + )), + ..ChannelConfigUpdate::default() + }, + ) + .unwrap(); // Send an additional non-dust htlc from 1 to 0 using the pre-calculated route above, and check the immediate complaint - unwrap_send_err!(nodes[1], nodes[1].node.send_payment_with_route(route_1_0, payment_hash_1_0, - RecipientOnionFields::secret_only(payment_secret_1_0), PaymentId(payment_hash_1_0.0) - ), true, APIError::ChannelUnavailable { .. }, {}); + unwrap_send_err!( + nodes[1], + nodes[1].node.send_payment_with_route( + route_1_0, + payment_hash_1_0, + RecipientOnionFields::secret_only(payment_secret_1_0), + PaymentId(payment_hash_1_0.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); let dust_limit = if features == ChannelTypeFeatures::only_static_remote_key() { - MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000 + htlc_success_tx_weight(&features) * node_1_dust_buffer_feerate / 1000 * 1000 + MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000 + + htlc_success_tx_weight(&features) * node_1_dust_buffer_feerate / 1000 * 1000 } else { MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000 }; @@ -10980,10 +15642,19 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) assert_eq!(nodes[1].node.list_channels()[0].pending_inbound_htlcs.len(), DUST_HTLC_COUNT); // Set node 1's max dust htlc exposure equal to `expected_dust_exposure_msat` - nodes[1].node.update_partial_channel_config(&nodes[0].node.get_our_node_id(), &[chan_id], &ChannelConfigUpdate { - max_dust_htlc_exposure_msat: Some(MaxDustHTLCExposure::FixedLimitMsat(expected_dust_exposure_msat)), - ..ChannelConfigUpdate::default() - }).unwrap(); + nodes[1] + .node + .update_partial_channel_config( + &nodes[0].node.get_our_node_id(), + &[chan_id], + &ChannelConfigUpdate { + max_dust_htlc_exposure_msat: Some(MaxDustHTLCExposure::FixedLimitMsat( + expected_dust_exposure_msat, + )), + ..ChannelConfigUpdate::default() + }, + ) + .unwrap(); // Check a successful payment send_payment(&nodes[1], &[&nodes[0]], NON_DUST_HTLC_MSAT); @@ -11000,7 +15671,9 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) #[test] fn test_nondust_htlc_fees_dust_exposure_delta() { do_test_nondust_htlc_fees_dust_exposure_delta(ChannelTypeFeatures::only_static_remote_key()); - do_test_nondust_htlc_fees_dust_exposure_delta(ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()); + do_test_nondust_htlc_fees_dust_exposure_delta( + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + ); } #[xtest(feature = "_externalize_tests")] @@ -11010,37 +15683,73 @@ pub fn test_non_final_funding_tx() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let temp_channel_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let open_channel_message = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_message); - let accept_channel_message = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel_message = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel_message); let best_height = nodes[0].node.best_block.read().unwrap().height; let chan_id = *nodes[0].network_chan_count.borrow(); let events = nodes[0].node.get_and_clear_pending_events(); - let input = TxIn { previous_output: BitcoinOutPoint::null(), script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence(1), witness: Witness::from_slice(&[&[1]]) }; + let input = TxIn { + previous_output: BitcoinOutPoint::null(), + script_sig: bitcoin::ScriptBuf::new(), + sequence: Sequence(1), + witness: Witness::from_slice(&[&[1]]), + }; assert_eq!(events.len(), 1); let mut tx = match events[0] { Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => { // Timelock the transaction _beyond_ the best client height + 1. - Transaction { version: Version(chan_id as i32), lock_time: LockTime::from_height(best_height + 2).unwrap(), input: vec![input], output: vec![TxOut { - value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(), - }]} + Transaction { + version: Version(chan_id as i32), + lock_time: LockTime::from_height(best_height + 2).unwrap(), + input: vec![input], + output: vec![TxOut { + value: Amount::from_sat(*channel_value_satoshis), + script_pubkey: output_script.clone(), + }], + } }, _ => panic!("Unexpected event"), }; // Transaction should fail as it's evaluated as non-final for propagation. - match nodes[0].node.funding_transaction_generated(temp_channel_id, nodes[1].node.get_our_node_id(), tx.clone()) { + match nodes[0].node.funding_transaction_generated( + temp_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) { Err(APIError::APIMisuseError { err }) => { assert_eq!(format!("Funding transaction absolute timelock is non-final"), err); }, - _ => panic!() + _ => panic!(), } let err = "Error in transaction funding: Misuse error: Funding transaction absolute timelock is non-final".to_owned(); - check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(temp_channel_id, false, ClosureReason::ProcessingError { err })]); - assert_eq!(get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id()).data, "Failed to fund channel"); + check_closed_events( + &nodes[0], + &[ExpectedCloseEvent::from_id_reason( + temp_channel_id, + false, + ClosureReason::ProcessingError { err }, + )], + ); + assert_eq!( + get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id()).data, + "Failed to fund channel" + ); } #[xtest(feature = "_externalize_tests")] @@ -11050,30 +15759,55 @@ pub fn test_non_final_funding_tx_within_headroom() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let temp_channel_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let open_channel_message = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_message); - let accept_channel_message = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel_message = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel_message); let best_height = nodes[0].node.best_block.read().unwrap().height; let chan_id = *nodes[0].network_chan_count.borrow(); let events = nodes[0].node.get_and_clear_pending_events(); - let input = TxIn { previous_output: BitcoinOutPoint::null(), script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence(1), witness: Witness::from_slice(&[[1]]) }; + let input = TxIn { + previous_output: BitcoinOutPoint::null(), + script_sig: bitcoin::ScriptBuf::new(), + sequence: Sequence(1), + witness: Witness::from_slice(&[[1]]), + }; assert_eq!(events.len(), 1); let mut tx = match events[0] { Event::FundingGenerationReady { ref channel_value_satoshis, ref output_script, .. } => { // Timelock the transaction within a +1 headroom from the best block. - Transaction { version: Version(chan_id as i32), lock_time: LockTime::from_consensus(best_height + 1), input: vec![input], output: vec![TxOut { - value: Amount::from_sat(*channel_value_satoshis), script_pubkey: output_script.clone(), - }]} + Transaction { + version: Version(chan_id as i32), + lock_time: LockTime::from_consensus(best_height + 1), + input: vec![input], + output: vec![TxOut { + value: Amount::from_sat(*channel_value_satoshis), + script_pubkey: output_script.clone(), + }], + } }, _ => panic!("Unexpected event"), }; // Transaction should be accepted if it's in a +1 headroom from best block. - assert!(nodes[0].node.funding_transaction_generated(temp_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).is_ok()); + assert!(nodes[0] + .node + .funding_transaction_generated(temp_channel_id, nodes[1].node.get_our_node_id(), tx.clone()) + .is_ok()); get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); } @@ -11106,8 +15840,13 @@ pub fn accept_busted_but_better_fee() { let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_fee.as_ref().unwrap()); + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, + .. + } => { + nodes[1] + .node + .handle_update_fee(nodes[0].node.get_our_node_id(), update_fee.as_ref().unwrap()); commitment_signed_dance!(nodes[1], nodes[0], commitment_signed, false); }, _ => panic!("Unexpected event"), @@ -11125,8 +15864,13 @@ pub fn accept_busted_but_better_fee() { let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => { - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_fee.as_ref().unwrap()); + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, + .. + } => { + nodes[1] + .node + .handle_update_fee(nodes[0].node.get_our_node_id(), update_fee.as_ref().unwrap()); commitment_signed_dance!(nodes[1], nodes[0], commitment_signed, false); }, _ => panic!("Unexpected event"), @@ -11144,11 +15888,23 @@ pub fn accept_busted_but_better_fee() { let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, .. }, .. } => { - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), update_fee.as_ref().unwrap()); - check_closed_event!(nodes[1], 1, ClosureReason::PeerFeerateTooLow { - peer_feerate_sat_per_kw: 1000, required_feerate_sat_per_kw: 5000, - }, [nodes[0].node.get_our_node_id()], 100000); + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { ref update_fee, .. }, + .. + } => { + nodes[1] + .node + .handle_update_fee(nodes[0].node.get_our_node_id(), update_fee.as_ref().unwrap()); + check_closed_event!( + nodes[1], + 1, + ClosureReason::PeerFeerateTooLow { + peer_feerate_sat_per_kw: 1000, + required_feerate_sat_per_kw: 5000, + }, + [nodes[0].node.get_our_node_id()], + 100000 + ); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); }, @@ -11162,24 +15918,44 @@ fn do_payment_with_custom_min_final_cltv_expiry(valid_delta: bool, use_user_hash let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let min_final_cltv_expiry_delta = 120; - let final_cltv_expiry_delta = if valid_delta { min_final_cltv_expiry_delta + 2 } else { - min_final_cltv_expiry_delta - 2 }; + let final_cltv_expiry_delta = + if valid_delta { min_final_cltv_expiry_delta + 2 } else { min_final_cltv_expiry_delta - 2 }; let recv_value = 100_000; create_chan_between_nodes(&nodes[0], &nodes[1]); - let payment_parameters = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), final_cltv_expiry_delta as u32); + let payment_parameters = PaymentParameters::from_node_id( + nodes[1].node.get_our_node_id(), + final_cltv_expiry_delta as u32, + ); let (payment_hash, payment_preimage, payment_secret) = if use_user_hash { - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], - Some(recv_value), Some(min_final_cltv_expiry_delta)); + let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!( + nodes[1], + Some(recv_value), + Some(min_final_cltv_expiry_delta) + ); (payment_hash, payment_preimage, payment_secret) } else { - let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(recv_value), 7200, Some(min_final_cltv_expiry_delta)).unwrap(); - (payment_hash, nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap(), payment_secret) + let (payment_hash, payment_secret) = nodes[1] + .node + .create_inbound_payment(Some(recv_value), 7200, Some(min_final_cltv_expiry_delta)) + .unwrap(); + ( + payment_hash, + nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap(), + payment_secret, + ) }; let route = get_route!(nodes[0], payment_parameters, recv_value).unwrap(); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.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); @@ -11189,17 +15965,29 @@ fn do_payment_with_custom_min_final_cltv_expiry(valid_delta: bool, use_user_hash expect_pending_htlcs_forwardable!(nodes[1]); if valid_delta { - expect_payment_claimable!(nodes[1], payment_hash, payment_secret, recv_value, if use_user_hash { - None } else { Some(payment_preimage) }, nodes[1].node.get_our_node_id()); + expect_payment_claimable!( + nodes[1], + payment_hash, + payment_secret, + recv_value, + if use_user_hash { None } else { Some(payment_preimage) }, + nodes[1].node.get_our_node_id() + ); - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage); } else { - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[1], 1); let fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &fail_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &fail_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], fail_updates.commitment_signed, false, true); expect_payment_failed!(nodes[0], payment_hash, true); @@ -11225,17 +16013,18 @@ pub fn test_disconnects_peer_awaiting_response_ticks() { // Asserts a disconnect event is queued to the user. let check_disconnect_event = |node: &Node, should_disconnect: bool| { - let disconnect_event = node.node.get_and_clear_pending_msg_events().iter().find_map(|event| - if let MessageSendEvent::HandleError { action, .. } = event { - if let msgs::ErrorAction::DisconnectPeerWithWarning { .. } = action { - Some(()) + let disconnect_event = + node.node.get_and_clear_pending_msg_events().iter().find_map(|event| { + if let MessageSendEvent::HandleError { action, .. } = event { + if let msgs::ErrorAction::DisconnectPeerWithWarning { .. } = action { + Some(()) + } else { + None + } } else { None } - } else { - None - } - ); + }); assert_eq!(disconnect_event.is_some(), should_disconnect); }; @@ -11267,21 +16056,35 @@ pub fn test_disconnects_peer_awaiting_response_ticks() { nodes[0].node.timer_tick_occurred(); check_added_monitors!(&nodes[0], 1); let alice_fee_update = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), alice_fee_update.update_fee.as_ref().unwrap()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &alice_fee_update.commitment_signed); + nodes[1].node.handle_update_fee( + nodes[0].node.get_our_node_id(), + alice_fee_update.update_fee.as_ref().unwrap(), + ); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &alice_fee_update.commitment_signed, + ); check_added_monitors!(&nodes[1], 1); // This will prompt Bob (nodes[1]) to respond with his `CommitmentSigned` and `RevokeAndACK`. - let (bob_revoke_and_ack, bob_commitment_signed) = get_revoke_commit_msgs!(&nodes[1], nodes[0].node.get_our_node_id()); + let (bob_revoke_and_ack, bob_commitment_signed) = + get_revoke_commit_msgs!(&nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bob_revoke_and_ack); check_added_monitors!(&nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bob_commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bob_commitment_signed, + ); check_added_monitors(&nodes[0], 1); // Alice then needs to send her final `RevokeAndACK` to complete the commitment dance. We // pretend Bob hasn't received the message and check whether he'll disconnect Alice after // reaching `DISCONNECT_PEER_AWAITING_RESPONSE_TICKS`. - let alice_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let alice_revoke_and_ack = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); check_disconnect(&nodes[1]); // Now, we'll reconnect them to test awaiting a `ChannelReestablish` message. @@ -11291,11 +16094,15 @@ pub fn test_disconnects_peer_awaiting_response_ticks() { nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); let bob_init = msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, }; nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &bob_init, true).unwrap(); let alice_init = msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, }; nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &alice_init, true).unwrap(); @@ -11303,21 +16110,32 @@ pub fn test_disconnects_peer_awaiting_response_ticks() { // received Bob's yet, so she should disconnect him after reaching // `DISCONNECT_PEER_AWAITING_RESPONSE_TICKS`. let alice_channel_reestablish = get_event_msg!( - nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id() + nodes[0], + MessageSendEvent::SendChannelReestablish, + nodes[1].node.get_our_node_id() ); - nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &alice_channel_reestablish); + nodes[1] + .node + .handle_channel_reestablish(nodes[0].node.get_our_node_id(), &alice_channel_reestablish); check_disconnect(&nodes[0]); // Bob now sends his `ChannelReestablish` to Alice to resume the channel and consider it "live". - let bob_channel_reestablish = nodes[1].node.get_and_clear_pending_msg_events().iter().find_map(|event| - if let MessageSendEvent::SendChannelReestablish { node_id, msg } = event { - assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - Some(msg.clone()) - } else { - None - } - ).unwrap(); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bob_channel_reestablish); + let bob_channel_reestablish = nodes[1] + .node + .get_and_clear_pending_msg_events() + .iter() + .find_map(|event| { + if let MessageSendEvent::SendChannelReestablish { node_id, msg } = event { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + Some(msg.clone()) + } else { + None + } + }) + .unwrap(); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bob_channel_reestablish); // Sanity check that Alice won't disconnect Bob since she's no longer waiting for any messages. for _ in 0..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS { @@ -11350,10 +16168,21 @@ pub fn test_remove_expired_outbound_unfunded_channels() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let temp_channel_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let open_channel_message = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_message); - let accept_channel_message = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel_message = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel_message); let events = nodes[0].node.get_and_clear_pending_events(); @@ -11366,7 +16195,8 @@ pub fn test_remove_expired_outbound_unfunded_channels() { // Asserts the outbound channel has been removed from a nodes[0]'s peer state map. let check_outbound_channel_existence = |should_exist: bool| { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let chan_lock = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); assert_eq!(chan_lock.channel_by_id.contains_key(&temp_channel_id), should_exist); }; @@ -11386,12 +16216,25 @@ pub fn test_remove_expired_outbound_unfunded_channels() { let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); match msg_events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => { - assert_eq!(msg.data, "Force-closing pending channel due to timeout awaiting establishment handshake"); + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id: _, + } => { + assert_eq!( + msg.data, + "Force-closing pending channel due to timeout awaiting establishment handshake" + ); }, _ => panic!("Unexpected event"), } - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, false, &[nodes[1].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); } #[xtest(feature = "_externalize_tests")] @@ -11401,10 +16244,21 @@ pub fn test_remove_expired_inbound_unfunded_channels() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let temp_channel_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let open_channel_message = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let temp_channel_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let open_channel_message = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_message); - let accept_channel_message = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel_message = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel_message); let events = nodes[0].node.get_and_clear_pending_events(); @@ -11417,7 +16271,8 @@ pub fn test_remove_expired_inbound_unfunded_channels() { // Asserts the inbound channel has been removed from a nodes[1]'s peer state map. let check_inbound_channel_existence = |should_exist: bool| { let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); - let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); + let chan_lock = + per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap(); assert_eq!(chan_lock.channel_by_id.contains_key(&temp_channel_id), should_exist); }; @@ -11437,12 +16292,25 @@ pub fn test_remove_expired_inbound_unfunded_channels() { let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); match msg_events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => { - assert_eq!(msg.data, "Force-closing pending channel due to timeout awaiting establishment handshake"); + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id: _, + } => { + assert_eq!( + msg.data, + "Force-closing pending channel due to timeout awaiting establishment handshake" + ); }, _ => panic!("Unexpected event"), } - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); } #[xtest(feature = "_externalize_tests")] @@ -11456,8 +16324,15 @@ pub fn test_channel_close_when_not_timely_accepted() { // Simulate peer-disconnects mid-handshake // The channel is initiated from the node 0 side, // but the nodes disconnect before node 1 could send accept channel - let create_chan_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let create_chan_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); @@ -11476,7 +16351,13 @@ pub fn test_channel_close_when_not_timely_accepted() { // Since we disconnected from peer and did not connect back within time, // we should have forced-closed the channel by now. - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); assert_eq!(nodes[0].node.list_channels().len(), 0); { @@ -11499,8 +16380,15 @@ pub fn test_rebroadcast_open_channel_when_reconnect_mid_handshake() { // Simulate peer-disconnects mid-handshake // The channel is initiated from the node 0 side, // but the nodes disconnect before node 1 could send accept channel - let create_chan_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let create_chan_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert_eq!(open_channel_msg.common_fields.temporary_channel_id, create_chan_id); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); @@ -11513,12 +16401,30 @@ pub fn test_rebroadcast_open_channel_when_reconnect_mid_handshake() { assert_eq!(nodes[1].node.list_channels().len(), 0); // The peers now reconnect - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); // Make sure the SendOpenChannel message is added to node_0 pending message events let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -11550,8 +16456,10 @@ fn do_test_multi_post_event_actions(do_reload: bool) { send_payment(&nodes[0], &[&nodes[1]], 1_000_000); send_payment(&nodes[0], &[&nodes[2]], 1_000_000); - let (our_payment_preimage, our_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); - let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[2]], 1_000_000); + let (our_payment_preimage, our_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[0], &[&nodes[2]], 1_000_000); nodes[1].node.claim_funds(our_payment_preimage); check_added_monitors!(nodes[1], 1); @@ -11562,29 +16470,56 @@ fn do_test_multi_post_event_actions(do_reload: bool) { expect_payment_claimed!(nodes[2], payment_hash_2, 1_000_000); for dest in &[1, 2] { - let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[*dest], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[*dest].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); - commitment_signed_dance!(nodes[0], nodes[*dest], htlc_fulfill_updates.commitment_signed, false); + let htlc_fulfill_updates = + get_htlc_update_msgs!(nodes[*dest], nodes[0].node.get_our_node_id()); + nodes[0].node.handle_update_fulfill_htlc( + nodes[*dest].node.get_our_node_id(), + &htlc_fulfill_updates.update_fulfill_htlcs[0], + ); + commitment_signed_dance!( + nodes[0], + nodes[*dest], + htlc_fulfill_updates.commitment_signed, + false + ); check_added_monitors(&nodes[0], 0); } let (route, payment_hash_3, _, payment_secret_3) = get_route_and_payment_hash!(nodes[1], nodes[0], 100_000); let payment_id = PaymentId(payment_hash_3.0); - nodes[1].node.send_payment_with_route(route, payment_hash_3, - RecipientOnionFields::secret_only(payment_secret_3), payment_id).unwrap(); + nodes[1] + .node + .send_payment_with_route( + route, + payment_hash_3, + RecipientOnionFields::secret_only(payment_secret_3), + payment_id, + ) + .unwrap(); check_added_monitors(&nodes[1], 1); let send_event = SendEvent::from_node(&nodes[1]); nodes[0].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &send_event.msgs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &send_event.commitment_msg); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &send_event.commitment_msg, + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); if do_reload { let nodes_0_serialized = nodes[0].node.encode(); let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); let chan_1_monitor_serialized = get_monitor!(nodes[0], chan_id_2).encode(); - reload_node!(nodes[0], test_default_channel_config(), &nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], persister, chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + test_default_channel_config(), + &nodes_0_serialized, + &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], + persister, + chain_monitor, + nodes_0_deserialized + ); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); nodes[2].node.peer_disconnected(nodes[0].node.get_our_node_id()); @@ -11597,12 +16532,22 @@ fn do_test_multi_post_event_actions(do_reload: bool) { assert_eq!(events.len(), 4); if let Event::PaymentSent { payment_preimage, .. } = events[0] { assert!(payment_preimage == our_payment_preimage || payment_preimage == payment_preimage_2); - } else { panic!(); } + } else { + panic!(); + } if let Event::PaymentSent { payment_preimage, .. } = events[1] { assert!(payment_preimage == our_payment_preimage || payment_preimage == payment_preimage_2); - } else { panic!(); } - if let Event::PaymentPathSuccessful { .. } = events[2] {} else { panic!(); } - if let Event::PaymentPathSuccessful { .. } = events[3] {} else { panic!(); } + } else { + panic!(); + } + if let Event::PaymentPathSuccessful { .. } = events[2] { + } else { + panic!(); + } + if let Event::PaymentPathSuccessful { .. } = events[3] { + } else { + panic!(); + } // After the events are processed, the ChannelMonitorUpdates will be released and, upon their // completion, we'll respond to nodes[1] with an RAA + CS. @@ -11624,17 +16569,21 @@ pub fn test_batch_channel_open() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Initiate channel opening and create the batch channel funding transaction. - let (tx, funding_created_msgs) = create_batch_channel_funding(&nodes[0], &[ - (&nodes[1], 100_000, 0, 42, None), - (&nodes[2], 200_000, 0, 43, None), - ]); + let (tx, funding_created_msgs) = create_batch_channel_funding( + &nodes[0], + &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], + ); // Go through the funding_created and funding_signed flow with node 1. nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msgs[0]); check_added_monitors(&nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); @@ -11646,7 +16595,11 @@ pub fn test_batch_channel_open() { check_added_monitors(&nodes[2], 1); expect_channel_pending_event(&nodes[2], &nodes[0].node.get_our_node_id()); - let funding_signed_msg = get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[2], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[0].node.handle_funding_signed(nodes[2].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); @@ -11657,9 +16610,9 @@ pub fn test_batch_channel_open() { assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); // Complete the persistence of the monitor. - nodes[0].chain_monitor.complete_sole_pending_chan_update( - &ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 1 }) - ); + nodes[0].chain_monitor.complete_sole_pending_chan_update(&ChannelId::v1_from_funding_outpoint( + OutPoint { txid: tx.compute_txid(), index: 1 }, + )); let events = nodes[0].node.get_and_clear_pending_events(); // The transaction should only have been broadcast now. @@ -11694,17 +16647,21 @@ pub fn test_close_in_funding_batch() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Initiate channel opening and create the batch channel funding transaction. - let (tx, funding_created_msgs) = create_batch_channel_funding(&nodes[0], &[ - (&nodes[1], 100_000, 0, 42, None), - (&nodes[2], 200_000, 0, 43, None), - ]); + let (tx, funding_created_msgs) = create_batch_channel_funding( + &nodes[0], + &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], + ); // Go through the funding_created and funding_signed flow with node 1. nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msgs[0]); check_added_monitors(&nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); @@ -11717,7 +16674,14 @@ pub fn test_close_in_funding_batch() { let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); let error_message = "Channel force-closed"; - nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &channel_id_1, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); // The monitor should become closed. check_added_monitors(&nodes[0], 1); @@ -11726,7 +16690,10 @@ pub fn test_close_in_funding_batch() { let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap(); assert_eq!(monitor_updates_1.len(), 1); assert_eq!(monitor_updates_1[0].updates.len(), 1); - assert!(matches!(monitor_updates_1[0].updates[0], ChannelMonitorUpdateStep::ChannelForceClosed { .. })); + assert!(matches!( + monitor_updates_1[0].updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); } let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -11745,22 +16712,25 @@ pub fn test_close_in_funding_batch() { } // All channels in the batch should close immediately. - check_closed_events(&nodes[0], &[ - ExpectedCloseEvent { - channel_id: Some(channel_id_1), - discard_funding: true, - channel_funding_txo: Some(funding_txo_1), - user_channel_id: Some(42), - ..Default::default() - }, - ExpectedCloseEvent { - channel_id: Some(channel_id_2), - discard_funding: true, - channel_funding_txo: Some(funding_txo_2), - user_channel_id: Some(43), - ..Default::default() - }, - ]); + check_closed_events( + &nodes[0], + &[ + ExpectedCloseEvent { + channel_id: Some(channel_id_1), + discard_funding: true, + channel_funding_txo: Some(funding_txo_1), + user_channel_id: Some(42), + ..Default::default() + }, + ExpectedCloseEvent { + channel_id: Some(channel_id_2), + discard_funding: true, + channel_funding_txo: Some(funding_txo_2), + user_channel_id: Some(43), + ..Default::default() + }, + ], + ); // Ensure the channels don't exist anymore. assert!(nodes[0].node.list_channels().is_empty()); @@ -11774,17 +16744,21 @@ pub fn test_batch_funding_close_after_funding_signed() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Initiate channel opening and create the batch channel funding transaction. - let (tx, funding_created_msgs) = create_batch_channel_funding(&nodes[0], &[ - (&nodes[1], 100_000, 0, 42, None), - (&nodes[2], 200_000, 0, 43, None), - ]); + let (tx, funding_created_msgs) = create_batch_channel_funding( + &nodes[0], + &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], + ); // Go through the funding_created and funding_signed flow with node 1. nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msgs[0]); check_added_monitors(&nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); @@ -11793,7 +16767,11 @@ pub fn test_batch_funding_close_after_funding_signed() { check_added_monitors(&nodes[2], 1); expect_channel_pending_event(&nodes[2], &nodes[0].node.get_our_node_id()); - let funding_signed_msg = get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[2], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[0].node.handle_funding_signed(nodes[2].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); @@ -11807,18 +16785,31 @@ pub fn test_batch_funding_close_after_funding_signed() { let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); let error_message = "Channel force-closed"; - nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &channel_id_1, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors(&nodes[0], 2); { let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap(); let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap(); assert_eq!(monitor_updates_1.len(), 1); assert_eq!(monitor_updates_1[0].updates.len(), 1); - assert!(matches!(monitor_updates_1[0].updates[0], ChannelMonitorUpdateStep::ChannelForceClosed { .. })); + assert!(matches!( + monitor_updates_1[0].updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); let monitor_updates_2 = monitor_updates.get(&channel_id_2).unwrap(); assert_eq!(monitor_updates_2.len(), 1); assert_eq!(monitor_updates_2[0].updates.len(), 1); - assert!(matches!(monitor_updates_2[0].updates[0], ChannelMonitorUpdateStep::ChannelForceClosed { .. })); + assert!(matches!( + monitor_updates_2[0].updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); } let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); match msg_events[0] { @@ -11836,22 +16827,25 @@ pub fn test_batch_funding_close_after_funding_signed() { } // All channels in the batch should close immediately. - check_closed_events(&nodes[0], &[ - ExpectedCloseEvent { - channel_id: Some(channel_id_1), - discard_funding: true, - channel_funding_txo: Some(funding_txo_1), - user_channel_id: Some(42), - ..Default::default() - }, - ExpectedCloseEvent { - channel_id: Some(channel_id_2), - discard_funding: true, - channel_funding_txo: Some(funding_txo_2), - user_channel_id: Some(43), - ..Default::default() - }, - ]); + check_closed_events( + &nodes[0], + &[ + ExpectedCloseEvent { + channel_id: Some(channel_id_1), + discard_funding: true, + channel_funding_txo: Some(funding_txo_1), + user_channel_id: Some(42), + ..Default::default() + }, + ExpectedCloseEvent { + channel_id: Some(channel_id_2), + discard_funding: true, + channel_funding_txo: Some(funding_txo_2), + user_channel_id: Some(43), + ..Default::default() + }, + ], + ); // Ensure the channels don't exist anymore. assert!(nodes[0].node.list_channels().is_empty()); @@ -11864,30 +16858,51 @@ fn do_test_funding_and_commitment_tx_confirm_same_block(confirm_remote_commitmen let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let mut min_depth_1_block_cfg = test_default_channel_config(); min_depth_1_block_cfg.channel_handshake_config.minimum_depth = 1; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(min_depth_1_block_cfg.clone()), Some(min_depth_1_block_cfg)]); + let node_chanmgrs = create_node_chanmgrs( + 2, + &node_cfgs, + &[Some(min_depth_1_block_cfg.clone()), Some(min_depth_1_block_cfg)], + ); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0); - let chan_id = ChannelId::v1_from_funding_outpoint(chain::transaction::OutPoint { txid: funding_tx.compute_txid(), index: 0 }); + let chan_id = ChannelId::v1_from_funding_outpoint(chain::transaction::OutPoint { + txid: funding_tx.compute_txid(), + index: 0, + }); assert_eq!(nodes[0].node.list_channels().len(), 1); assert_eq!(nodes[1].node.list_channels().len(), 1); - let (closing_node, other_node) = if confirm_remote_commitment { - (&nodes[1], &nodes[0]) - } else { - (&nodes[0], &nodes[1]) - }; + let (closing_node, other_node) = + if confirm_remote_commitment { (&nodes[1], &nodes[0]) } else { (&nodes[0], &nodes[1]) }; let error_message = "Channel force-closed"; - closing_node.node.force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id(), error_message.to_string()).unwrap(); + closing_node + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &other_node.node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); let mut msg_events = closing_node.node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); match msg_events.pop().unwrap() { - MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { .. }, .. } => {}, + MessageSendEvent::HandleError { + action: msgs::ErrorAction::SendErrorMessage { .. }, + .. + } => {}, _ => panic!("Unexpected event"), } check_added_monitors(closing_node, 1); - check_closed_event(closing_node, 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[other_node.node.get_our_node_id()], 1_000_000); + check_closed_event( + closing_node, + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[other_node.node.get_our_node_id()], + 1_000_000, + ); let commitment_tx = { let mut txn = closing_node.tx_broadcaster.txn_broadcast(); @@ -11902,7 +16917,14 @@ fn do_test_funding_and_commitment_tx_confirm_same_block(confirm_remote_commitmen check_closed_broadcast(other_node, 1, true); check_added_monitors(other_node, 1); - check_closed_event(other_node, 1, ClosureReason::CommitmentTxConfirmed, false, &[closing_node.node.get_our_node_id()], 1_000_000); + check_closed_event( + other_node, + 1, + ClosureReason::CommitmentTxConfirmed, + false, + &[closing_node.node.get_our_node_id()], + 1_000_000, + ); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[1].node.list_channels().is_empty()); @@ -11929,22 +16951,36 @@ pub fn test_accept_inbound_channel_errors_queued() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config0), Some(config1)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel_msg); let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - match nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 23, None) { + match nodes[1].node.accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 23, + None, + ) { Err(APIError::ChannelUnavailable { err: _ }) => (), _ => panic!(), } - } + }, _ => panic!("Unexpected event"), } - assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, - open_channel_msg.common_fields.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, + open_channel_msg.common_fields.temporary_channel_id + ); } #[xtest(feature = "_externalize_tests")] @@ -11956,23 +16992,50 @@ pub fn test_manual_funding_abandon() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).is_ok()); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + assert!(nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .is_ok()); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, _tx, funding_outpoint) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); - nodes[0].node.unsafe_manual_funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), funding_outpoint).unwrap(); + let (temporary_channel_id, _tx, funding_outpoint) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); + nodes[0] + .node + .unsafe_manual_funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + funding_outpoint, + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let funding_created = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); let err = msgs::ErrorMessage { channel_id: funding_signed.channel_id, data: "".to_string() }; nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &err); @@ -11984,7 +17047,7 @@ pub fn test_manual_funding_abandon() { assert_eq!(*channel_id, err.channel_id); assert_eq!(*outpoint, funding_outpoint); true - } + }, _ => false, })); } @@ -11998,23 +17061,50 @@ pub fn test_funding_signed_event() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).is_ok()); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + assert!(nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None) + .is_ok()); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, funding_outpoint) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); - nodes[0].node.unsafe_manual_funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), funding_outpoint).unwrap(); + let (temporary_channel_id, tx, funding_outpoint) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42); + nodes[0] + .node + .unsafe_manual_funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + funding_outpoint, + ) + .unwrap(); check_added_monitors!(nodes[0], 0); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let funding_created = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed); check_added_monitors!(nodes[0], 1); let events = &nodes[0].node.get_and_clear_pending_events(); @@ -12036,9 +17126,17 @@ pub fn test_funding_signed_event() { mine_transaction(&nodes[0], &tx); mine_transaction(&nodes[1], &tx); - let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id()); + let as_channel_ready = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelReady, + nodes[0].node.get_our_node_id() + ); nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &as_channel_ready); - let as_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let as_channel_ready = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ); nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &as_channel_ready); expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id()); 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/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs index a8eec347f1f..32db6ba880c 100644 --- a/lightning/src/ln/invoice_utils.rs +++ b/lightning/src/ln/invoice_utils.rs @@ -1,28 +1,33 @@ //! 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::chain; use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use crate::sign::{Recipient, NodeSigner, SignerProvider, 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::{ + Bolt11InvoiceParameters, ChannelManager, PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA, + MIN_FINAL_CLTV_EXPIRY_DELTA, +}; use crate::ln::inbound_payment::{create, create_from_hash}; +use crate::onion_message::messenger::MessageRouter; use crate::routing::gossip::RoutingFees; use crate::routing::router::{RouteHint, RouteHintHop, Router}; -use crate::onion_message::messenger::MessageRouter; +use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; +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. @@ -62,11 +67,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, @@ -76,8 +85,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, ) } @@ -117,11 +135,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, @@ -129,40 +151,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(); @@ -172,8 +206,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))?; @@ -184,15 +217,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) @@ -200,26 +236,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)), } } @@ -231,16 +272,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 @@ -264,10 +309,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, @@ -328,7 +370,17 @@ fn rotate_through_iterators>(mut vecs: Vec) -> impl /// confirmations during routing. /// /// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA -pub fn create_invoice_from_channelmanager( +pub fn create_invoice_from_channelmanager< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, +>( channelmanager: &ChannelManager, amt_msat: Option, description: String, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, ) -> Result> @@ -371,7 +423,17 @@ where /// 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( +pub fn create_invoice_from_channelmanager_with_description_hash< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, +>( channelmanager: &ChannelManager, amt_msat: Option, description_hash: Sha256, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, @@ -405,7 +467,17 @@ where /// 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( +pub fn create_invoice_from_channelmanager_with_description_hash_and_payment_hash< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, +>( channelmanager: &ChannelManager, amt_msat: Option, description_hash: Sha256, invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, min_final_cltv_expiry_delta: Option, @@ -437,7 +509,17 @@ where /// 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( +pub fn create_invoice_from_channelmanager_with_payment_hash< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + MR: Deref, + L: Deref, +>( channelmanager: &ChannelManager, amt_msat: Option, description: String, invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, min_final_cltv_expiry_delta: Option, @@ -484,9 +566,7 @@ where /// * 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, @@ -509,13 +589,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; } @@ -529,15 +612,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; } @@ -559,12 +648,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, @@ -584,10 +677,10 @@ where &channel.channel_id, channel.short_channel_id, channel.inbound_capacity_msat); } - } + }, btree_map::Entry::Vacant(entry) => { entry.insert(channel); - } + }, } } @@ -617,32 +710,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 @@ -656,13 +761,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; @@ -670,25 +775,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); @@ -696,7 +807,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 } } @@ -705,22 +819,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() { @@ -749,7 +868,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); @@ -758,9 +876,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), @@ -772,32 +889,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); @@ -821,8 +958,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] @@ -858,9 +1001,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, @@ -870,7 +1013,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] @@ -881,9 +1029,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, @@ -894,7 +1041,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()); } @@ -934,12 +1084,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. @@ -951,20 +1103,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()); @@ -981,7 +1150,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()); } @@ -992,8 +1165,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()); @@ -1009,9 +1184,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()); @@ -1095,31 +1273,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()); @@ -1137,7 +1354,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); @@ -1205,13 +1423,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, @@ -1225,7 +1441,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] @@ -1261,10 +1481,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 { @@ -1272,16 +1490,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 { @@ -1289,22 +1521,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(); @@ -1313,14 +1564,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 @@ -1337,12 +1598,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); } @@ -1361,24 +1632,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] @@ -1389,25 +1685,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] @@ -1418,22 +1730,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] @@ -1447,8 +1778,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()); @@ -1457,14 +1790,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]; @@ -1474,9 +1808,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()); @@ -1486,9 +1823,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, ); } @@ -1503,32 +1840,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()); @@ -1542,9 +1919,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, ); } @@ -1559,7 +1936,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); @@ -1573,9 +1951,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, ); } @@ -1593,9 +1971,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. @@ -1605,9 +1985,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, ); } @@ -1622,10 +2002,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()); @@ -1634,9 +2018,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, ); } @@ -1663,9 +2047,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. @@ -1677,9 +2061,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 @@ -1692,9 +2076,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. @@ -1706,9 +2090,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, ); } @@ -1724,7 +2108,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. @@ -1796,30 +2181,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(); @@ -1837,10 +2236,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] @@ -1851,7 +2254,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), @@ -1861,7 +2264,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!(), } } @@ -1890,7 +2295,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"]; @@ -1904,24 +2313,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/lightning/src/ln/max_payment_path_len_tests.rs b/lightning/src/ln/max_payment_path_len_tests.rs index 95a1fbaaa10..71661f8f138 100644 --- a/lightning/src/ln/max_payment_path_len_tests.rs +++ b/lightning/src/ln/max_payment_path_len_tests.rs @@ -10,14 +10,14 @@ //! Tests for calculating the maximum length of a path based on the payment metadata, custom TLVs, //! and/or blinded paths present. -use bitcoin::secp256k1::{Secp256k1, PublicKey}; +use crate::blinded_path::payment::{ + BlindedPayInfo, BlindedPaymentPath, Bolt12RefundContext, PaymentConstraints, PaymentContext, + UnauthenticatedReceiveTlvs, +}; use crate::blinded_path::BlindedHop; -use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath, Bolt12RefundContext, PaymentConstraints, PaymentContext, UnauthenticatedReceiveTlvs}; use crate::events::Event; -use crate::types::payment::PaymentSecret; use crate::ln::blinded_payment_tests::get_blinded_route_parameters; use crate::ln::channelmanager::PaymentId; -use crate::types::features::BlindedHopFeatures; use crate::ln::functional_test_utils::*; use crate::ln::msgs; use crate::ln::msgs::{BaseMessageHandler, OnionMessageHandler}; @@ -26,11 +26,16 @@ use crate::ln::onion_utils::MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY; use crate::ln::outbound_payment::{RecipientOnionFields, Retry, RetryableSendFailure}; use crate::offers::nonce::Nonce; use crate::prelude::*; -use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA}; +use crate::routing::router::{ + PaymentParameters, RouteParameters, RouteParametersConfig, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, +}; use crate::sign::NodeSigner; +use crate::types::features::BlindedHopFeatures; +use crate::types::payment::PaymentSecret; use crate::util::errors::APIError; use crate::util::ser::Writeable; use crate::util::test_utils; +use bitcoin::secp256k1::{PublicKey, Secp256k1}; // 3+32 (payload length and HMAC) + 2+8 (amt_to_forward) + // 2+4 (outgoing_cltv_value) + 2+8 (short_channel_id) @@ -56,14 +61,16 @@ fn large_payment_metadata() { // without exceeding the max onion packet size. let final_payload_len_without_metadata = msgs::OutboundOnionPayload::Receive { payment_data: Some(msgs::FinalOnionHopData { - payment_secret: PaymentSecret([0; 32]), total_msat: MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY + payment_secret: PaymentSecret([0; 32]), + total_msat: MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, }), payment_metadata: None, keysend_preimage: None, custom_tlvs: &Vec::new(), sender_intended_htlc_amt_msat: MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, cltv_expiry_height: nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, - }.serialized_length(); + } + .serialized_length(); let max_metadata_len = 1300 - 1 // metadata type - crate::util::ser::BigSize(1200).serialized_length() // metadata length @@ -73,38 +80,70 @@ fn large_payment_metadata() { let mut payment_metadata = vec![42; max_metadata_len]; // Check that the maximum-size metadata is sendable. - let (mut route_0_1, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], &nodes[1], amt_msat); + let (mut route_0_1, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[0], &nodes[1], amt_msat); let mut recipient_onion_max_md_size = RecipientOnionFields { payment_secret: Some(payment_secret), payment_metadata: Some(payment_metadata.clone()), custom_tlvs: Vec::new(), }; - nodes[0].node.send_payment(payment_hash, recipient_onion_max_md_size.clone(), PaymentId(payment_hash.0), route_0_1.route_params.clone().unwrap(), Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + recipient_onion_max_md_size.clone(), + PaymentId(payment_hash.0), + route_0_1.route_params.clone().unwrap(), + 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); let path = &[&nodes[1]]; - let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap()) - .with_payment_secret(payment_secret) - .with_payment_metadata(payment_metadata.clone()); + let args = + PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap()) + .with_payment_secret(payment_secret) + .with_payment_metadata(payment_metadata.clone()); do_pass_along_path(args); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage) - ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1]]], + payment_preimage, + )); // Check that the payment parameter for max path length will prevent us from routing past our // next-hop peer given the payment_metadata size. - let (mut route_0_2, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(&nodes[0], &nodes[2], amt_msat); + let (mut route_0_2, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(&nodes[0], &nodes[2], amt_msat); let mut route_params_0_2 = route_0_2.route_params.clone().unwrap(); route_params_0_2.payment_params.max_path_length = 1; nodes[0].router.expect_find_route_query(route_params_0_2); - let err = nodes[0].node.send_payment(payment_hash_2, recipient_onion_max_md_size.clone(), PaymentId(payment_hash_2.0), route_0_2.route_params.clone().unwrap(), Retry::Attempts(0)).unwrap_err(); + let err = nodes[0] + .node + .send_payment( + payment_hash_2, + recipient_onion_max_md_size.clone(), + PaymentId(payment_hash_2.0), + route_0_2.route_params.clone().unwrap(), + Retry::Attempts(0), + ) + .unwrap_err(); assert_eq!(err, RetryableSendFailure::RouteNotFound); // If our payment_metadata contains 1 additional byte, we'll fail prior to pathfinding. let mut recipient_onion_too_large_md = recipient_onion_max_md_size.clone(); recipient_onion_too_large_md.payment_metadata.as_mut().map(|mut md| md.push(42)); - let err = nodes[0].node.send_payment(payment_hash, recipient_onion_too_large_md.clone(), PaymentId(payment_hash.0), route_0_1.route_params.clone().unwrap(), Retry::Attempts(0)).unwrap_err(); + let err = nodes[0] + .node + .send_payment( + payment_hash, + recipient_onion_too_large_md.clone(), + PaymentId(payment_hash.0), + route_0_1.route_params.clone().unwrap(), + Retry::Attempts(0), + ) + .unwrap_err(); assert_eq!(err, RetryableSendFailure::OnionPacketSizeExceeded); // Confirm that we'll fail to construct an onion packet given this payment_metadata that's too @@ -112,7 +151,19 @@ fn large_payment_metadata() { let secp_ctx = Secp256k1::signing_only(); route_0_1.paths[0].hops[0].fee_msat = MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY; route_0_1.paths[0].hops[0].cltv_expiry_delta = DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA; - let err = onion_utils::create_payment_onion(&secp_ctx, &route_0_1.paths[0], &test_utils::privkey(42), MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, &recipient_onion_too_large_md, nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, &payment_hash, &None, None, [0; 32]).unwrap_err(); + let err = onion_utils::create_payment_onion( + &secp_ctx, + &route_0_1.paths[0], + &test_utils::privkey(42), + MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, + &recipient_onion_too_large_md, + nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, + &payment_hash, + &None, + None, + [0; 32], + ) + .unwrap_err(); match err { APIError::InvalidRoute { err } => { assert_eq!(err, "Route size too large considering onion data"); @@ -130,18 +181,30 @@ fn large_payment_metadata() { let mut route_params_0_2 = route_0_2.route_params.clone().unwrap(); route_params_0_2.payment_params.max_path_length = 2; nodes[0].router.expect_find_route_query(route_params_0_2); - nodes[0].node.send_payment(payment_hash_2, recipient_onion_allows_2_hops.clone(), PaymentId(payment_hash_2.0), route_0_2.route_params.unwrap(), Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash_2, + recipient_onion_allows_2_hops.clone(), + PaymentId(payment_hash_2.0), + route_0_2.route_params.unwrap(), + 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); let path = &[&nodes[1], &nodes[2]]; - let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash_2, events.pop().unwrap()) - .with_payment_secret(payment_secret_2) - .with_payment_metadata(recipient_onion_allows_2_hops.payment_metadata.unwrap()); + let args = + PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash_2, events.pop().unwrap()) + .with_payment_secret(payment_secret_2) + .with_payment_metadata(recipient_onion_allows_2_hops.payment_metadata.unwrap()); do_pass_along_path(args); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage_2) - ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + payment_preimage_2, + )); } #[test] @@ -154,16 +217,18 @@ fn one_hop_blinded_path_with_custom_tlv() { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); - let chan_upd_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; + let chan_upd_1_2 = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents; // Start with all nodes at the same height - connect_blocks(&nodes[0], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[0], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); // Construct the route parameters for sending to nodes[2]'s 1-hop blinded path. let amt_msat = 100_000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); let payee_tlvs = UnauthenticatedReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -177,9 +242,15 @@ fn one_hop_blinded_path_with_custom_tlv() { let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key); let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPaymentPath::new( - &[], nodes[2].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16, - &chanmon_cfgs[2].keys_manager, &secp_ctx - ).unwrap(); + &[], + nodes[2].node.get_our_node_id(), + payee_tlvs, + u64::MAX, + TEST_FINAL_CLTV as u16, + &chanmon_cfgs[2].keys_manager, + &secp_ctx, + ) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::blinded(vec![blinded_path.clone()]), amt_msat, @@ -195,8 +266,9 @@ fn one_hop_blinded_path_with_custom_tlv() { intro_node_blinding_point: Some(blinded_path.blinding_point()), keysend_preimage: None, invoice_request: None, - custom_tlvs: &Vec::new() - }.serialized_length(); + custom_tlvs: &Vec::new(), + } + .serialized_length(); let max_custom_tlv_len = 1300 - crate::util::ser::BigSize(CUSTOM_TLV_TYPE).serialized_length() // custom TLV type - crate::util::ser::BigSize(1200).serialized_length() // custom TLV length @@ -208,49 +280,89 @@ fn one_hop_blinded_path_with_custom_tlv() { let recipient_onion_max_custom_tlv_size = RecipientOnionFields::spontaneous_empty() .with_custom_tlvs(vec![(CUSTOM_TLV_TYPE, vec![42; max_custom_tlv_len])]) .unwrap(); - nodes[1].node.send_payment(payment_hash, recipient_onion_max_custom_tlv_size.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap(); + nodes[1] + .node + .send_payment( + payment_hash, + recipient_onion_max_custom_tlv_size.clone(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[1], 1); let mut events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let path = &[&nodes[2]]; - let args = PassAlongPathArgs::new(&nodes[1], path, amt_msat, payment_hash, events.pop().unwrap()) - .with_payment_secret(payment_secret) - .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()); + let args = + PassAlongPathArgs::new(&nodes[1], path, amt_msat, payment_hash, events.pop().unwrap()) + .with_payment_secret(payment_secret) + .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()); do_pass_along_path(args); claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2]]], payment_preimage) - .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()) + .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()), ); // If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding. let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone(); recipient_onion_too_large_custom_tlv.custom_tlvs[0].1.push(42); - let err = nodes[1].node.send_payment(payment_hash, recipient_onion_too_large_custom_tlv, PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap_err(); + let err = nodes[1] + .node + .send_payment( + payment_hash, + recipient_onion_too_large_custom_tlv, + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0), + ) + .unwrap_err(); assert_eq!(err, RetryableSendFailure::OnionPacketSizeExceeded); // With the maximum-size custom TLV, our max path length is limited to 1, so attempting to route // nodes[0] -> nodes[2] will fail. - let err = nodes[0].node.send_payment(payment_hash, recipient_onion_max_custom_tlv_size.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap_err(); + let err = nodes[0] + .node + .send_payment( + payment_hash, + recipient_onion_max_custom_tlv_size.clone(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0), + ) + .unwrap_err(); assert_eq!(err, RetryableSendFailure::RouteNotFound); // If we remove enough custom TLV bytes to allow for 1 intermediate unblinded hop, we're now able // to send nodes[0] -> nodes[2]. let mut recipient_onion_allows_2_hops = recipient_onion_max_custom_tlv_size.clone(); - recipient_onion_allows_2_hops.custom_tlvs[0].1.resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0); - nodes[0].node.send_payment(payment_hash, recipient_onion_allows_2_hops.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap(); + recipient_onion_allows_2_hops.custom_tlvs[0] + .1 + .resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0); + nodes[0] + .node + .send_payment( + payment_hash, + recipient_onion_allows_2_hops.clone(), + PaymentId(payment_hash.0), + route_params.clone(), + 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); let path = &[&nodes[1], &nodes[2]]; - let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap()) - .with_payment_secret(payment_secret) - .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone()); + let args = + PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap()) + .with_payment_secret(payment_secret) + .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone()); do_pass_along_path(args); claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) - .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs) + .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs), ); } @@ -264,10 +376,12 @@ fn blinded_path_with_custom_tlv() { let nodes = create_network(4, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); create_announced_chan_between_nodes(&nodes, 1, 2); - let chan_upd_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; + let chan_upd_2_3 = + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents; // Ensure all nodes are at the same height - let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; + let node_max_height = + nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32; connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1); connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1); connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1); @@ -275,25 +389,35 @@ fn blinded_path_with_custom_tlv() { // Construct the route parameters for sending to nodes[3]'s blinded path. let amt_msat = 100_000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); - let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000, - nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_2_3], - &chanmon_cfgs[3].keys_manager); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); + let route_params = get_blinded_route_parameters( + amt_msat, + payment_secret, + 1, + 1_0000_0000, + nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_2_3], + &chanmon_cfgs[3].keys_manager, + ); // Calculate the maximum custom TLV value size where a valid onion packet is still possible. const CUSTOM_TLV_TYPE: u64 = 65537; let mut route = get_route(&nodes[1], &route_params).unwrap(); let reserved_packet_bytes_without_custom_tlv: usize = onion_utils::build_onion_payloads( - &route.paths[0], MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, + &route.paths[0], + MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, &RecipientOnionFields::spontaneous_empty(), - nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, &None, - None, None + nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, + &None, + None, + None, ) - .unwrap() - .0 - .iter() - .map(|payload| payload.serialized_length() + PAYLOAD_HMAC_LEN) - .sum(); + .unwrap() + .0 + .iter() + .map(|payload| payload.serialized_length() + PAYLOAD_HMAC_LEN) + .sum(); let max_custom_tlv_len = 1300 - crate::util::ser::BigSize(CUSTOM_TLV_TYPE).serialized_length() // custom TLV type - crate::util::ser::BigSize(1200).serialized_length() // custom TLV length @@ -304,32 +428,63 @@ fn blinded_path_with_custom_tlv() { let recipient_onion_max_custom_tlv_size = RecipientOnionFields::spontaneous_empty() .with_custom_tlvs(vec![(CUSTOM_TLV_TYPE, vec![42; max_custom_tlv_len])]) .unwrap(); - nodes[1].node.send_payment(payment_hash, recipient_onion_max_custom_tlv_size.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap(); + nodes[1] + .node + .send_payment( + payment_hash, + recipient_onion_max_custom_tlv_size.clone(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[1], 1); let mut events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let path = &[&nodes[2], &nodes[3]]; - let args = PassAlongPathArgs::new(&nodes[1], path, amt_msat, payment_hash, events.pop().unwrap()) - .with_payment_secret(payment_secret) - .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()); + let args = + PassAlongPathArgs::new(&nodes[1], path, amt_msat, payment_hash, events.pop().unwrap()) + .with_payment_secret(payment_secret) + .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()); do_pass_along_path(args); claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[1], &[&[&nodes[2], &nodes[3]]], payment_preimage) - .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()) + .with_custom_tlvs(recipient_onion_max_custom_tlv_size.custom_tlvs.clone()), ); // If 1 byte is added to the custom TLV value, we'll fail to send prior to pathfinding. let mut recipient_onion_too_large_custom_tlv = recipient_onion_max_custom_tlv_size.clone(); recipient_onion_too_large_custom_tlv.custom_tlvs[0].1.push(42); - let err = nodes[1].node.send_payment(payment_hash, recipient_onion_too_large_custom_tlv.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap_err(); + let err = nodes[1] + .node + .send_payment( + payment_hash, + recipient_onion_too_large_custom_tlv.clone(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0), + ) + .unwrap_err(); assert_eq!(err, RetryableSendFailure::OnionPacketSizeExceeded); // Confirm that we can't construct an onion packet given this too-large custom TLV. let secp_ctx = Secp256k1::signing_only(); route.paths[0].hops[0].fee_msat = MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY; route.paths[0].hops[0].cltv_expiry_delta = DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA; - let err = onion_utils::create_payment_onion(&secp_ctx, &route.paths[0], &test_utils::privkey(42), MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, &recipient_onion_too_large_custom_tlv, nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, &payment_hash, &None, None, [0; 32]).unwrap_err(); + let err = onion_utils::create_payment_onion( + &secp_ctx, + &route.paths[0], + &test_utils::privkey(42), + MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY, + &recipient_onion_too_large_custom_tlv, + nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, + &payment_hash, + &None, + None, + [0; 32], + ) + .unwrap_err(); match err { APIError::InvalidRoute { err } => { assert_eq!(err, "Route size too large considering onion data"); @@ -339,26 +494,51 @@ fn blinded_path_with_custom_tlv() { // With the maximum-size custom TLV, we can't have any intermediate unblinded hops, so attempting // to route nodes[0] -> nodes[3] will fail. - let err = nodes[0].node.send_payment(payment_hash, recipient_onion_max_custom_tlv_size.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap_err(); + let err = nodes[0] + .node + .send_payment( + payment_hash, + recipient_onion_max_custom_tlv_size.clone(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0), + ) + .unwrap_err(); assert_eq!(err, RetryableSendFailure::RouteNotFound); // If we remove enough custom TLV bytes to allow for 1 intermediate unblinded hop, we're now able // to send nodes[0] -> nodes[3]. let mut recipient_onion_allows_2_hops = recipient_onion_max_custom_tlv_size.clone(); - recipient_onion_allows_2_hops.custom_tlvs[0].1.resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0); - nodes[0].node.send_payment(payment_hash, recipient_onion_allows_2_hops.clone(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap(); + recipient_onion_allows_2_hops.custom_tlvs[0] + .1 + .resize(max_custom_tlv_len - INTERMED_PAYLOAD_LEN_ESTIMATE, 0); + nodes[0] + .node + .send_payment( + payment_hash, + recipient_onion_allows_2_hops.clone(), + PaymentId(payment_hash.0), + route_params.clone(), + 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); let path = &[&nodes[1], &nodes[2], &nodes[3]]; - let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap()) - .with_payment_secret(payment_secret) - .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone()); + let args = + PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, events.pop().unwrap()) + .with_payment_secret(payment_secret) + .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs.clone()); do_pass_along_path(args); claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], payment_preimage) - .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs) + ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2], &nodes[3]]], + payment_preimage, + ) + .with_custom_tlvs(recipient_onion_allows_2_hops.custom_tlvs), ); } @@ -372,40 +552,60 @@ fn bolt12_invoice_too_large_blinded_paths() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); - nodes[1].router.expect_blinded_payment_paths(vec![ - BlindedPaymentPath::from_raw( - PublicKey::from_slice(&[2; 33]).unwrap(), PublicKey::from_slice(&[2; 33]).unwrap(), - vec![ - BlindedHop { - blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(), - encrypted_payload: vec![42; 1300], - }, - BlindedHop { - blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(), - encrypted_payload: vec![42; 1300], - }, - ], - BlindedPayInfo { - fee_base_msat: 42, - fee_proportional_millionths: 42, - cltv_expiry_delta: 42, - htlc_minimum_msat: 42, - htlc_maximum_msat: 42_000_000, - features: BlindedHopFeatures::empty(), - } - ) - ]); + nodes[1].router.expect_blinded_payment_paths(vec![BlindedPaymentPath::from_raw( + PublicKey::from_slice(&[2; 33]).unwrap(), + PublicKey::from_slice(&[2; 33]).unwrap(), + vec![ + BlindedHop { + blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(), + encrypted_payload: vec![42; 1300], + }, + BlindedHop { + blinded_node_id: PublicKey::from_slice(&[2; 33]).unwrap(), + encrypted_payload: vec![42; 1300], + }, + ], + BlindedPayInfo { + fee_base_msat: 42, + fee_proportional_millionths: 42, + cltv_expiry_delta: 42, + htlc_minimum_msat: 42, + htlc_maximum_msat: 42_000_000, + features: BlindedHopFeatures::empty(), + }, + )]); let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap(); let payment_id = PaymentId([1; 32]); - nodes[0].node.pay_for_offer(&offer, None, Some(5000), None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); - let invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .pay_for_offer( + &offer, + None, + Some(5000), + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) + .unwrap(); + let invreq_om = nodes[0] + .onion_messenger + .next_onion_message_for_peer(nodes[1].node.get_our_node_id()) + .unwrap(); nodes[1].onion_messenger.handle_onion_message(nodes[0].node.get_our_node_id(), &invreq_om); - let invoice_om = nodes[1].onion_messenger.next_onion_message_for_peer(nodes[0].node.get_our_node_id()).unwrap(); + let invoice_om = nodes[1] + .onion_messenger + .next_onion_message_for_peer(nodes[0].node.get_our_node_id()) + .unwrap(); nodes[0].onion_messenger.handle_onion_message(nodes[1].node.get_our_node_id(), &invoice_om); // TODO: assert on the invoice error once we support replying to invoice OMs with failure info - nodes[0].logger.assert_log_contains("lightning::ln::channelmanager", "Failed paying invoice: OnionPacketSizeExceeded", 1); + nodes[0].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Failed paying invoice: OnionPacketSizeExceeded", + 1, + ); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index aa2d8c668ba..863868e3d71 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -13,15 +13,15 @@ #[macro_use] pub mod functional_test_utils; -pub mod onion_payment; -pub mod channelmanager; +pub mod chan_utils; pub mod channel_keys; pub mod channel_state; +pub mod channelmanager; +mod features; pub mod inbound_payment; pub mod msgs; +pub mod onion_payment; pub mod peer_handler; -pub mod chan_utils; -mod features; pub mod script; pub mod types; @@ -57,58 +57,58 @@ pub use onion_utils::process_onion_failure; #[cfg(fuzzing)] pub use onion_utils::AttributionData; -#[cfg(test)] -#[allow(unused_mut)] -pub mod bolt11_payment_tests; -#[cfg(test)] -#[allow(unused_mut)] -mod blinded_payment_tests; #[cfg(all(test, async_payments))] #[allow(unused_mut)] mod async_payments_tests; -#[cfg(any(test, feature = "_externalize_tests"))] +#[cfg(test)] #[allow(unused_mut)] -pub mod functional_tests; -#[cfg(all(test, splicing))] +mod async_signer_tests; +#[cfg(test)] #[allow(unused_mut)] -mod splicing_tests; +mod blinded_payment_tests; #[cfg(test)] #[allow(unused_mut)] -mod max_payment_path_len_tests; +pub mod bolt11_payment_tests; #[cfg(test)] #[allow(unused_mut)] -mod payment_tests; +mod chanmon_update_fail_tests; #[cfg(test)] #[allow(unused_mut)] -mod priv_short_conf_tests; +mod dual_funding_tests; +#[cfg(any(test, feature = "_externalize_tests"))] +#[allow(unused_mut)] +pub mod functional_tests; #[cfg(test)] #[allow(unused_mut)] -mod chanmon_update_fail_tests; +mod max_payment_path_len_tests; #[cfg(test)] #[allow(unused_mut)] -mod reorg_tests; +mod monitor_tests; #[cfg(test)] #[allow(unused_mut)] -mod reload_tests; +mod offers_tests; #[cfg(test)] #[allow(unused_mut)] mod onion_route_tests; #[cfg(test)] #[allow(unused_mut)] -mod monitor_tests; +mod payment_tests; #[cfg(test)] #[allow(unused_mut)] -mod shutdown_tests; +mod priv_short_conf_tests; #[cfg(test)] mod quiescence_tests; #[cfg(test)] #[allow(unused_mut)] -mod async_signer_tests; +mod reload_tests; #[cfg(test)] #[allow(unused_mut)] -mod offers_tests; +mod reorg_tests; #[cfg(test)] #[allow(unused_mut)] -mod dual_funding_tests; +mod shutdown_tests; +#[cfg(all(test, splicing))] +#[allow(unused_mut)] +mod splicing_tests; pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN; diff --git a/lightning/src/ln/monitor_tests.rs b/lightning/src/ln/monitor_tests.rs index e70e2cfa99b..a189117f562 100644 --- a/lightning/src/ln/monitor_tests.rs +++ b/lightning/src/ln/monitor_tests.rs @@ -9,29 +9,36 @@ //! Further functional tests which test blockchain reorganizations. -use crate::sign::{ecdsa::EcdsaChannelSigner, OutputSpender, SignerProvider, SpendableOutputDescriptor}; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, ARCHIVAL_DELAY_BLOCKS,LATENCY_GRACE_PERIOD_BLOCKS, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE, Balance, BalanceSource, ChannelMonitorUpdateStep}; +use crate::chain::chaininterface::{ + compute_feerate_sat_per_1000_weight, ConfirmationTarget, LowerBoundedFeeEstimator, +}; +use crate::chain::channelmonitor::{ + Balance, BalanceSource, ChannelMonitorUpdateStep, ANTI_REORG_DELAY, ARCHIVAL_DELAY_BLOCKS, + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE, LATENCY_GRACE_PERIOD_BLOCKS, +}; use crate::chain::transaction::OutPoint; -use crate::chain::chaininterface::{ConfirmationTarget, LowerBoundedFeeEstimator, compute_feerate_sat_per_1000_weight}; +use crate::crypto::utils::sign; use crate::events::bump_transaction::{BumpTransactionEvent, WalletSource}; -use crate::events::{Event, ClosureReason, HTLCDestination}; -use crate::ln::channel; -use crate::ln::types::ChannelId; +use crate::events::{ClosureReason, Event, HTLCDestination}; use crate::ln::chan_utils; -use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, PaymentId, RecipientOnionFields}; +use crate::ln::channel; +use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, BREAKDOWN_TIMEOUT}; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent}; -use crate::crypto::utils::sign; -use crate::util::ser::Writeable; +use crate::ln::types::ChannelId; +use crate::sign::{ + ecdsa::EcdsaChannelSigner, OutputSpender, SignerProvider, SpendableOutputDescriptor, +}; use crate::util::scid_utils::block_from_scid; +use crate::util::ser::Writeable; -use bitcoin::{Amount, PublicKey, ScriptBuf, Transaction, TxIn, TxOut, Witness}; +use bitcoin::hex::FromHex; use bitcoin::locktime::absolute::LockTime; -use bitcoin::script::Builder; use bitcoin::opcodes; -use bitcoin::hex::FromHex; +use bitcoin::script::Builder; use bitcoin::secp256k1::{Secp256k1, SecretKey}; -use bitcoin::sighash::{SighashCache, EcdsaSighashType}; +use bitcoin::sighash::{EcdsaSighashType, SighashCache}; use bitcoin::transaction::Version; +use bitcoin::{Amount, PublicKey, ScriptBuf, Transaction, TxIn, TxOut, Witness}; use crate::prelude::*; @@ -62,15 +69,25 @@ fn chanmon_fail_from_stale_commitment() { create_announced_chan_between_nodes(&nodes, 0, 1); let (update_a, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2); - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let bs_txn = get_local_commitment_txn!(nodes[1], chan_id_2); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); @@ -82,33 +99,72 @@ fn chanmon_fail_from_stale_commitment() { mine_transaction(&nodes[1], &bs_txn[0]); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[2].node.get_our_node_id()], + 100000 + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] + ); check_added_monitors!(nodes[1], 1); let fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &fail_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &fail_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], fail_updates.commitment_signed, true, true); - expect_payment_failed_with_update!(nodes[0], payment_hash, false, update_a.contents.short_channel_id, true); + expect_payment_failed_with_update!( + nodes[0], + payment_hash, + false, + update_a.contents.short_channel_id, + true + ); } -fn test_spendable_output<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, spendable_tx: &Transaction, has_anchors_htlc_event: bool) -> Vec { +fn test_spendable_output<'a, 'b, 'c, 'd>( + node: &'a Node<'b, 'c, 'd>, spendable_tx: &Transaction, has_anchors_htlc_event: bool, +) -> Vec { let mut spendable = node.chain_monitor.chain_monitor.get_and_clear_pending_events(); assert_eq!(spendable.len(), if has_anchors_htlc_event { 2 } else { 1 }); if has_anchors_htlc_event { - if let Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { .. }) = spendable.pop().unwrap() {} - else { panic!(); } + if let Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { .. }) = + spendable.pop().unwrap() + { + } else { + panic!(); + } } if let Event::SpendableOutputs { outputs, .. } = spendable.pop().unwrap() { assert_eq!(outputs.len(), 1); - let spend_tx = node.keys_manager.backing.spend_spendable_outputs(&[&outputs[0]], Vec::new(), - Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), 253, None, &Secp256k1::new()).unwrap(); + let spend_tx = node + .keys_manager + .backing + .spend_spendable_outputs( + &[&outputs[0]], + Vec::new(), + Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), + 253, + None, + &Secp256k1::new(), + ) + .unwrap(); check_spends!(spend_tx, spendable_tx); outputs - } else { panic!(); } + } else { + panic!(); + } } #[test] @@ -137,7 +193,13 @@ fn revoked_output_htlc_resolution_timing() { // Confirm the revoked commitment transaction, closing the channel. mine_transaction(&nodes[1], &revoked_local_txn[0]); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); check_closed_broadcast!(nodes[1], true); // Two justice transactions will be broadcast, one on the unpinnable, revoked to_self output, @@ -171,7 +233,8 @@ fn archive_fully_resolved_monitors() { let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let mut user_config = test_default_channel_config(); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = @@ -179,10 +242,23 @@ fn archive_fully_resolved_monitors() { let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 10_000_000); - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), "".to_owned()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + "".to_owned(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 1_000_000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); let commitment_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(commitment_tx.len(), 1); @@ -204,7 +280,10 @@ fn archive_fully_resolved_monitors() { let spendable_event = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events(); assert_eq!(spendable_event.len(), 1); - if let Event::SpendableOutputs { .. } = spendable_event[0] {} else { panic!(); } + if let Event::SpendableOutputs { .. } = spendable_event[0] { + } else { + panic!(); + } // Until the `Balance` set of both monitors goes empty, calling // `archive_fully_resolved_channel_monitors` will do nothing (though we don't bother to observe @@ -282,23 +361,23 @@ fn archive_fully_resolved_monitors() { for node in nodes { node.chain_source.remove_watched_txn_and_outputs( OutPoint { txid: funding_tx.compute_txid(), index: 0 }, - funding_tx.output[0].script_pubkey.clone() + funding_tx.output[0].script_pubkey.clone(), ); node.chain_source.remove_watched_txn_and_outputs( OutPoint { txid: commitment_tx[0].compute_txid(), index: 0 }, - commitment_tx[0].output[0].script_pubkey.clone() + commitment_tx[0].output[0].script_pubkey.clone(), ); node.chain_source.remove_watched_txn_and_outputs( OutPoint { txid: commitment_tx[0].compute_txid(), index: 1 }, - commitment_tx[0].output[1].script_pubkey.clone() + commitment_tx[0].output[1].script_pubkey.clone(), ); node.chain_source.remove_watched_txn_and_outputs( OutPoint { txid: commitment_tx[0].compute_txid(), index: 2 }, - commitment_tx[0].output[2].script_pubkey.clone() + commitment_tx[0].output[2].script_pubkey.clone(), ); node.chain_source.remove_watched_txn_and_outputs( OutPoint { txid: htlc_claim_tx[0].compute_txid(), index: 0 }, - htlc_claim_tx[0].output[0].script_pubkey.clone() + htlc_claim_tx[0].output[0].script_pubkey.clone(), ); } } @@ -315,7 +394,8 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) { user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = @@ -326,9 +406,11 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) { let chan_feerate = get_feerate!(nodes[0], nodes[1], chan_id) as u64; let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan_id); - let commitment_tx_fee = chan_feerate * chan_utils::commitment_tx_base_weight(&channel_type_features) / 1000; + let commitment_tx_fee = + chan_feerate * chan_utils::commitment_tx_base_weight(&channel_type_features) / 1000; let anchor_outputs_value = if anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 }; - assert_eq!(vec![Balance::ClaimableOnChannelClose { + assert_eq!( + vec![Balance::ClaimableOnChannelClose { amount_satoshis: 1_000_000 - 1_000 - commitment_tx_fee - anchor_outputs_value, transaction_fee_satoshis: commitment_tx_fee, outbound_payment_htlc_rounded_msat: 0, @@ -336,29 +418,48 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) { inbound_claiming_htlc_rounded_msat: 0, inbound_htlc_rounded_msat: 0, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); - assert_eq!(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 1_000, transaction_fee_satoshis: 0, + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); + assert_eq!( + vec![Balance::ClaimableOnChannelClose { + amount_satoshis: 1_000, + transaction_fee_satoshis: 0, outbound_payment_htlc_rounded_msat: 0, outbound_forwarded_htlc_rounded_msat: 0, inbound_claiming_htlc_rounded_msat: 0, inbound_htlc_rounded_msat: 0, }], - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); let shutdown_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); @@ -374,49 +475,73 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) { assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + assert_eq!( + vec![Balance::ClaimableAwaitingConfirmations { amount_satoshis: 1_000_000 - 1_000 - commitment_tx_fee - anchor_outputs_value, confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, source: BalanceSource::CoopClose, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); + assert_eq!( + vec![Balance::ClaimableAwaitingConfirmations { amount_satoshis: 1000, confirmation_height: nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1, source: BalanceSource::CoopClose, }], - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 2); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2); assert!(get_monitor!(nodes[0], chan_id) - .get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_a).is_empty()); + .get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_a) + .is_empty()); assert!(get_monitor!(nodes[1], chan_id) - .get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_b).is_empty()); + .get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_b) + .is_empty()); connect_blocks(&nodes[0], 1); connect_blocks(&nodes[1], 1); - assert_eq!(Vec::::new(), - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); - assert_eq!(Vec::::new(), - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + assert_eq!( + Vec::::new(), + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); + assert_eq!( + Vec::::new(), + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); let spendable_outputs_a = test_spendable_output(&nodes[0], &shutdown_tx[0], false); assert_eq!( - get_monitor!(nodes[0], chan_id).get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_a), + get_monitor!(nodes[0], chan_id) + .get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_a), spendable_outputs_a ); let spendable_outputs_b = test_spendable_output(&nodes[1], &shutdown_tx[0], false); assert_eq!( - get_monitor!(nodes[1], chan_id).get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_b), + get_monitor!(nodes[1], chan_id) + .get_spendable_outputs(&shutdown_tx[0], shutdown_tx_conf_height_b), spendable_outputs_b ); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 1000000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 1000000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 1000000 + ); } #[test] @@ -459,7 +584,8 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -478,8 +604,14 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { ], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, coinbase_tx.output[1].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); + nodes[1].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, + coinbase_tx.output[1].value, + ); } let (_, _, chan_id, funding_tx) = @@ -491,9 +623,11 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 3_000_100); // This HTLC is allowed to time out, letting A claim it. However, in order to test claimable // balances more fully we also give B the preimage for this HTLC. - let (timeout_payment_preimage, timeout_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 4_000_200); + let (timeout_payment_preimage, timeout_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 4_000_200); // This HTLC will be dust, and not be claimable at all: - let (dust_payment_preimage, dust_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 3_000); + let (dust_payment_preimage, dust_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 3_000); let htlc_cltv_timeout = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 1; // Note ChannelManager adds one to CLTV timeouts for safety @@ -538,27 +672,59 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { // Before B receives the payment preimage, it only suggests the push_msat value of 1_000 sats // as claimable. A lists both its to-self balance and the (possibly-claimable) HTLCs. - let commitment_tx_fee = chan_feerate as u64 * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate as u64 + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; let anchor_outputs_value = if anchors { 2 * channel::ANCHOR_OUTPUT_VALUE_SATOSHI } else { 0 }; - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 1_000_000 - 3_000 - 4_000 - 1_000 - 3 - commitment_tx_fee - anchor_outputs_value - 1 /* msat amount that is burned to fees */, - transaction_fee_satoshis: commitment_tx_fee, - outbound_payment_htlc_rounded_msat: 3300, - outbound_forwarded_htlc_rounded_msat: 0, - inbound_claiming_htlc_rounded_msat: 0, - inbound_htlc_rounded_msat: 0, - }, sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 1_000, - transaction_fee_satoshis: 0, - outbound_payment_htlc_rounded_msat: 0, - outbound_forwarded_htlc_rounded_msat: 0, - inbound_claiming_htlc_rounded_msat: 0, - inbound_htlc_rounded_msat: 3300, - }, received_htlc_balance.clone(), received_htlc_timeout_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { + amount_satoshis: 1_000_000 + - 3_000 - 4_000 - 1_000 + - 3 - commitment_tx_fee + - anchor_outputs_value + - 1, /* msat amount that is burned to fees */ + transaction_fee_satoshis: commitment_tx_fee, + outbound_payment_htlc_rounded_msat: 3300, + outbound_forwarded_htlc_rounded_msat: 0, + inbound_claiming_htlc_rounded_msat: 0, + inbound_htlc_rounded_msat: 0, + }, + sent_htlc_balance.clone(), + sent_htlc_timeout_balance.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { + amount_satoshis: 1_000, + transaction_fee_satoshis: 0, + outbound_payment_htlc_rounded_msat: 0, + outbound_forwarded_htlc_rounded_msat: 0, + inbound_claiming_htlc_rounded_msat: 0, + inbound_htlc_rounded_msat: 3300, + }, + received_htlc_balance.clone(), + received_htlc_timeout_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); nodes[1].node.claim_funds(payment_preimage); check_added_monitors!(nodes[1], 1); @@ -577,25 +743,37 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { if prev_commitment_tx { // To build a previous commitment transaction, deliver one round of commitment messages. - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &b_htlc_msgs.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &b_htlc_msgs.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &b_htlc_msgs.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &b_htlc_msgs.commitment_signed, + ); check_added_monitors!(nodes[0], 1); let (as_raa, as_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_raa); let _htlc_updates = get_htlc_update_msgs!(&nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_cs); - let _bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let _bs_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); check_added_monitors!(nodes[1], 1); } // Once B has received the payment preimage, it includes the value of the HTLC in its // "claimable if you were to close the channel" balance. - let commitment_tx_fee = chan_feerate as u64 * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + - if prev_commitment_tx { 1 } else { 2 } * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; - let mut a_expected_balances = vec![Balance::ClaimableOnChannelClose { + let commitment_tx_fee = chan_feerate as u64 + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + if prev_commitment_tx { 1 } else { 2 } * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; + let mut a_expected_balances = vec![ + Balance::ClaimableOnChannelClose { amount_satoshis: 1_000_000 - // Channel funding value in satoshis 4_000 - // The to-be-failed HTLC value in satoshis 3_000 - // The claimed HTLC value in satoshis @@ -605,27 +783,48 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { anchor_outputs_value - // The anchor outputs value in satoshis 1, // The rounded up msat part of the one HTLC transaction_fee_satoshis: commitment_tx_fee, - outbound_payment_htlc_rounded_msat: 3000 + if prev_commitment_tx { - 200 /* 1 to-be-failed HTLC */ } else { 300 /* 2 HTLCs */ }, + outbound_payment_htlc_rounded_msat: 3000 + + if prev_commitment_tx { + 200 /* 1 to-be-failed HTLC */ + } else { + 300 /* 2 HTLCs */ + }, outbound_forwarded_htlc_rounded_msat: 0, inbound_claiming_htlc_rounded_msat: 0, inbound_htlc_rounded_msat: 0, - }, sent_htlc_timeout_balance.clone()]; + }, + sent_htlc_timeout_balance.clone(), + ]; if !prev_commitment_tx { a_expected_balances.push(sent_htlc_balance.clone()); } - assert_eq!(sorted_vec(a_expected_balances), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); - assert_eq!(vec![Balance::ClaimableOnChannelClose { + assert_eq!( + sorted_vec(a_expected_balances), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); + assert_eq!( + vec![Balance::ClaimableOnChannelClose { amount_satoshis: 1_000 + 3_000 + 4_000, transaction_fee_satoshis: 0, outbound_payment_htlc_rounded_msat: 0, outbound_forwarded_htlc_rounded_msat: 0, - inbound_claiming_htlc_rounded_msat: 3000 + if prev_commitment_tx { - 200 /* 1 HTLC */ } else { 300 /* 2 HTLCs */ }, + inbound_claiming_htlc_rounded_msat: 3000 + + if prev_commitment_tx { + 200 /* 1 HTLC */ + } else { + 300 /* 2 HTLCs */ + }, inbound_htlc_rounded_msat: 0, }], - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); // Broadcast the closing transaction (which has both pending HTLCs in it) and get B's // broadcasted HTLC claim transaction with preimage. @@ -639,13 +838,17 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { match events.pop().unwrap() { Event::BumpTransaction(bump_event) => { let mut first_htlc_event = bump_event.clone(); - if let BumpTransactionEvent::HTLCResolution { ref mut htlc_descriptors, .. } = &mut first_htlc_event { + if let BumpTransactionEvent::HTLCResolution { ref mut htlc_descriptors, .. } = + &mut first_htlc_event + { htlc_descriptors.remove(1); } else { panic!("Unexpected event"); } let mut second_htlc_event = bump_event; - if let BumpTransactionEvent::HTLCResolution { ref mut htlc_descriptors, .. } = &mut second_htlc_event { + if let BumpTransactionEvent::HTLCResolution { ref mut htlc_descriptors, .. } = + &mut second_htlc_event + { htlc_descriptors.remove(0); } else { panic!("Unexpected event"); @@ -664,17 +867,39 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { check_spends!(b_broadcast_txn[1], remote_txn[0], coinbase_tx); assert_eq!(b_broadcast_txn[0].input.len(), if anchors { 2 } else { 1 }); assert_eq!(b_broadcast_txn[1].input.len(), if anchors { 2 } else { 1 }); - assert_eq!(remote_txn[0].output[b_broadcast_txn[0].input[0].previous_output.vout as usize].value.to_sat(), 3_000); - assert_eq!(remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize].value.to_sat(), 4_000); + assert_eq!( + remote_txn[0].output[b_broadcast_txn[0].input[0].previous_output.vout as usize] + .value + .to_sat(), + 3_000 + ); + assert_eq!( + remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize] + .value + .to_sat(), + 4_000 + ); assert!(nodes[0].node.list_channels().is_empty()); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 1000000 + ); assert!(nodes[1].node.list_channels().is_empty()); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); @@ -684,10 +909,14 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { // other Balance variants, as close has already happened. assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - let commitment_tx_fee = chan_feerate as u64 * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - // Channel funding value in satoshis + let commitment_tx_fee = chan_feerate as u64 + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 - // Channel funding value in satoshis 4_000 - // The to-be-failed HTLC value in satoshis 3_000 - // The claimed HTLC value in satoshis 1_000 - // The push_msat value in satoshis @@ -695,21 +924,44 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { commitment_tx_fee - // The commitment transaction fee with two HTLC outputs anchor_outputs_value - // The anchor outputs value in satoshis 1, // The rounded up msat parts of HTLCs - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - source: BalanceSource::CounterpartyForceClosed, - }, sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + source: BalanceSource::CounterpartyForceClosed, + }, + sent_htlc_balance.clone(), + sent_htlc_timeout_balance.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // The main non-HTLC balance is just awaiting confirmations, but the claimable height is the // CSV delay, not ANTI_REORG_DELAY. - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000, - confirmation_height: node_b_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, - // Both HTLC balances are "contentious" as our counterparty could claim them if we wait too - // long. - received_htlc_claiming_balance.clone(), received_htlc_timeout_claiming_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000, + confirmation_height: node_b_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + // Both HTLC balances are "contentious" as our counterparty could claim them if we wait too + // long. + received_htlc_claiming_balance.clone(), + received_htlc_timeout_claiming_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); expect_payment_failed!(nodes[0], dust_payment_hash, false); @@ -717,14 +969,36 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { // After ANTI_REORG_DELAY, A will consider its balance fully spendable and generate a // `SpendableOutputs` event. However, B still has to wait for the CSV delay. - assert_eq!(sorted_vec(vec![sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000, - confirmation_height: node_b_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, received_htlc_claiming_balance.clone(), received_htlc_timeout_claiming_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000, + confirmation_height: node_b_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + received_htlc_claiming_balance.clone(), + received_htlc_timeout_claiming_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); test_spendable_output(&nodes[0], &remote_txn[0], false); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); @@ -737,11 +1011,22 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { } else { expect_payment_sent(&nodes[0], payment_preimage, None, true, false); } - assert_eq!(sorted_vec(vec![sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); - assert_eq!(vec![sent_htlc_timeout_balance.clone()], - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + assert_eq!( + vec![sent_htlc_timeout_balance.clone()], + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); // When the HTLC timeout output is spendable in the next block, A should broadcast it connect_blocks(&nodes[0], htlc_cltv_timeout - nodes[0].best_block_info().1); @@ -750,10 +1035,21 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { assert_eq!(a_broadcast_txn.len(), 1); check_spends!(a_broadcast_txn[0], remote_txn[0]); assert_eq!(a_broadcast_txn[0].input.len(), 2); - assert_ne!(a_broadcast_txn[0].input[0].previous_output.vout, a_broadcast_txn[0].input[1].previous_output.vout); + assert_ne!( + a_broadcast_txn[0].input[0].previous_output.vout, + a_broadcast_txn[0].input[1].previous_output.vout + ); // a_broadcast_txn [0] and [1] should spend the HTLC outputs of the commitment tx - assert!(a_broadcast_txn[0].input.iter().any(|input| remote_txn[0].output[input.previous_output.vout as usize].value.to_sat() == 3_000)); - assert!(a_broadcast_txn[0].input.iter().any(|input| remote_txn[0].output[input.previous_output.vout as usize].value.to_sat() == 4_000)); + assert!(a_broadcast_txn[0].input.iter().any(|input| remote_txn[0].output + [input.previous_output.vout as usize] + .value + .to_sat() + == 3_000)); + assert!(a_broadcast_txn[0].input.iter().any(|input| remote_txn[0].output + [input.previous_output.vout as usize] + .value + .to_sat() + == 4_000)); // Confirm node B's claim for node A to remove that claim from the aggregated claim transaction. mine_transaction(&nodes[0], &b_broadcast_txn[0]); @@ -764,17 +1060,21 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { // "MaybeClaimable", but instead move it to "AwaitingConfirmations". mine_transaction(&nodes[0], &a_htlc_timeout_tx); assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + assert_eq!( + vec![Balance::ClaimableAwaitingConfirmations { amount_satoshis: 4_000, confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, source: BalanceSource::Htlc, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); // After ANTI_REORG_DELAY, A will generate a SpendableOutputs event and drop the claimable // balance entry. connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); - assert_eq!(Vec::::new(), - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + assert_eq!( + Vec::::new(), + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); expect_payment_failed!(nodes[0], timeout_payment_hash, false); test_spendable_output(&nodes[0], &a_htlc_timeout_tx, false); @@ -785,46 +1085,77 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { let node_b_htlc_claimable = nodes[1].best_block_info().1 + BREAKDOWN_TIMEOUT as u32; mine_transaction(&nodes[1], &b_broadcast_txn[0]); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000, - confirmation_height: node_b_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 3_000, - confirmation_height: node_b_htlc_claimable, - source: BalanceSource::Htlc, - }, received_htlc_timeout_claiming_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000, + confirmation_height: node_b_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 3_000, + confirmation_height: node_b_htlc_claimable, + source: BalanceSource::Htlc, + }, + received_htlc_timeout_claiming_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // After reaching the commitment output CSV, we'll get a SpendableOutputs event for it and have // only the HTLCs claimable on node B. connect_blocks(&nodes[1], node_b_commitment_claimable - nodes[1].best_block_info().1); test_spendable_output(&nodes[1], &remote_txn[0], anchors); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 3_000, - confirmation_height: node_b_htlc_claimable, - source: BalanceSource::Htlc, - }, received_htlc_timeout_claiming_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 3_000, + confirmation_height: node_b_htlc_claimable, + source: BalanceSource::Htlc, + }, + received_htlc_timeout_claiming_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // After reaching the claimed HTLC output CSV, we'll get a SpendableOutptus event for it and // have only one HTLC output left spendable. connect_blocks(&nodes[1], node_b_htlc_claimable - nodes[1].best_block_info().1); test_spendable_output(&nodes[1], &b_broadcast_txn[0], anchors); - assert_eq!(vec![received_htlc_timeout_claiming_balance.clone()], - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + assert_eq!( + vec![received_htlc_timeout_claiming_balance.clone()], + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); // Finally, mine the HTLC timeout transaction that A broadcasted (even though B should be able // to claim this HTLC with the preimage it knows!). It will remain listed as a claimable HTLC // until ANTI_REORG_DELAY confirmations on the spend. mine_transaction(&nodes[1], &a_htlc_timeout_tx); - assert_eq!(vec![received_htlc_timeout_claiming_balance.clone()], - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + assert_eq!( + vec![received_htlc_timeout_claiming_balance.clone()], + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); - assert_eq!(Vec::::new(), - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + assert_eq!( + Vec::::new(), + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new @@ -833,7 +1164,13 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { connect_blocks(node, 6); connect_blocks(node, 6); assert!(node.chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - assert!(node.chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(node + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); } } @@ -862,7 +1199,8 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -881,34 +1219,61 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { ], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, coinbase_tx.output[1].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); + nodes[1].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, + coinbase_tx.output[1].value, + ); } // Create a single channel with two pending HTLCs from nodes[0] to nodes[1], one which nodes[1] // knows the preimage for, one which it does not. - let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + let (_, _, chan_id, funding_tx) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 10_000_000); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 10_000_000); let htlc_cltv_timeout = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 1; // Note ChannelManager adds one to CLTV timeouts for safety - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); expect_payment_claimable!(nodes[1], payment_hash, payment_secret, 10_000_000); - let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 20_000_000); - nodes[0].node.send_payment_with_route(route_2, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[1], 20_000_000); + nodes[0] + .node + .send_payment_with_route( + route_2, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); @@ -925,10 +1290,23 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { // claimable balances. let error_message = "Channel force-closed"; let node_a_commitment_claimable = nodes[0].best_block_info().1 + BREAKDOWN_TIMEOUT as u32; - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 1000000 + ); let commitment_tx = { let mut txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); assert_eq!(txn.len(), 1); @@ -956,21 +1334,44 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { outbound_payment: true, }; - let commitment_tx_fee = chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; let anchor_outputs_value = if anchors { 2 * channel::ANCHOR_OUTPUT_VALUE_SATOSHI } else { 0 }; - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 10_000 - 20_000 - commitment_tx_fee - anchor_outputs_value, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, htlc_balance_known_preimage.clone(), htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 10_000 - 20_000 - commitment_tx_fee + - anchor_outputs_value, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + htlc_balance_known_preimage.clone(), + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // Get nodes[1]'s HTLC claim tx for the second HTLC mine_transaction(&nodes[1], &commitment_tx); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); let bs_htlc_claim_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(bs_htlc_claim_txn.len(), 1); check_spends!(bs_htlc_claim_txn[0], commitment_tx); @@ -978,12 +1379,27 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { // Connect blocks until the HTLCs expire, allowing us to (validly) broadcast the HTLC-Timeout // transaction. connect_blocks(&nodes[0], TEST_FINAL_CLTV); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 10_000 - 20_000 - commitment_tx_fee - anchor_outputs_value, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, htlc_balance_known_preimage.clone(), htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 10_000 - 20_000 - commitment_tx_fee + - anchor_outputs_value, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + htlc_balance_known_preimage.clone(), + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); if anchors { handle_bump_htlc_event(&nodes[0], 1); } @@ -994,26 +1410,53 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { check_spends!(timeout_htlc_txn[0], commitment_tx, coinbase_tx); // One input from the commitment transaction for each HTLC, and one input to provide fees. assert_eq!(timeout_htlc_txn[0].input.len(), 3); - assert_eq!(timeout_htlc_txn[0].input[0].witness.last().unwrap().len(), chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS); - assert_eq!(timeout_htlc_txn[0].input[1].witness.last().unwrap().len(), chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS); + assert_eq!( + timeout_htlc_txn[0].input[0].witness.last().unwrap().len(), + chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS + ); + assert_eq!( + timeout_htlc_txn[0].input[1].witness.last().unwrap().len(), + chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS + ); } else { assert_eq!(timeout_htlc_txn.len(), 2); check_spends!(timeout_htlc_txn[0], commitment_tx); check_spends!(timeout_htlc_txn[1], commitment_tx); - assert_eq!(timeout_htlc_txn[0].input[0].witness.last().unwrap().len(), chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT); - assert_eq!(timeout_htlc_txn[1].input[0].witness.last().unwrap().len(), chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + timeout_htlc_txn[0].input[0].witness.last().unwrap().len(), + chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT + ); + assert_eq!( + timeout_htlc_txn[1].input[0].witness.last().unwrap().len(), + chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT + ); } // Now confirm nodes[1]'s HTLC claim, giving nodes[0] the preimage. Note that the "maybe // claimable" balance remains until we see ANTI_REORG_DELAY blocks. mine_transaction(&nodes[0], &bs_htlc_claim_txn[0]); expect_payment_sent(&nodes[0], payment_preimage_2, None, true, false); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 10_000 - 20_000 - commitment_tx_fee - anchor_outputs_value, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, htlc_balance_known_preimage.clone(), htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 10_000 - 20_000 - commitment_tx_fee + - anchor_outputs_value, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + htlc_balance_known_preimage.clone(), + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); if anchors { // The HTLC timeout claim corresponding to the counterparty preimage claim is removed from the @@ -1024,7 +1467,10 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { check_spends!(timeout_htlc_txn[0], commitment_tx, coinbase_tx); // One input from the commitment transaction for the HTLC, and one input to provide fees. assert_eq!(timeout_htlc_txn[0].input.len(), 2); - assert_eq!(timeout_htlc_txn[0].input[0].witness.last().unwrap().len(), chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS); + assert_eq!( + timeout_htlc_txn[0].input[0].witness.last().unwrap().len(), + chan_utils::OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS + ); } // Now confirm nodes[0]'s HTLC-Timeout transaction, which changes the claimable balance to an @@ -1034,16 +1480,31 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { // Note that prior to the fix in the commit which introduced this test, this (and the next // balance) check failed. With this check removed, the code panicked in the `connect_blocks` // call, as described, two hunks down. - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 10_000 - 20_000 - commitment_tx_fee - anchor_outputs_value, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: node_a_htlc_claimable, - source: BalanceSource::Htlc, - }, htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 10_000 - 20_000 - commitment_tx_fee + - anchor_outputs_value, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: node_a_htlc_claimable, + source: BalanceSource::Htlc, + }, + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // Finally make the HTLC transactions have ANTI_REORG_DELAY blocks. This call previously // panicked as described in the test introduction. This will remove the "maybe claimable" @@ -1051,39 +1512,63 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); expect_payment_failed!(nodes[0], payment_hash, false); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 10_000 - 20_000 - commitment_tx_fee - anchor_outputs_value, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: node_a_htlc_claimable, - source: BalanceSource::Htlc, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 10_000 - 20_000 - commitment_tx_fee + - anchor_outputs_value, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: node_a_htlc_claimable, + source: BalanceSource::Htlc, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // Connect blocks until the commitment transaction's CSV expires, providing us the relevant // `SpendableOutputs` event and removing the claimable balance entry. connect_blocks(&nodes[0], node_a_commitment_claimable - nodes[0].best_block_info().1 - 1); assert!(get_monitor!(nodes[0], chan_id) - .get_spendable_outputs(&commitment_tx, commitment_tx_conf_height_a).is_empty()); + .get_spendable_outputs(&commitment_tx, commitment_tx_conf_height_a) + .is_empty()); connect_blocks(&nodes[0], 1); - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + assert_eq!( + vec![Balance::ClaimableAwaitingConfirmations { amount_satoshis: 10_000, confirmation_height: node_a_htlc_claimable, source: BalanceSource::Htlc, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); let to_self_spendable_output = test_spendable_output(&nodes[0], &commitment_tx, false); assert_eq!( - get_monitor!(nodes[0], chan_id).get_spendable_outputs(&commitment_tx, commitment_tx_conf_height_a), + get_monitor!(nodes[0], chan_id) + .get_spendable_outputs(&commitment_tx, commitment_tx_conf_height_a), to_self_spendable_output ); // Connect blocks until the HTLC-Timeout's CSV expires, providing us the relevant // `SpendableOutputs` event and removing the claimable balance entry. connect_blocks(&nodes[0], node_a_htlc_claimable - nodes[0].best_block_info().1); - assert!(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); test_spendable_output(&nodes[0], &timeout_htlc_txn[0], false); // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're @@ -1092,7 +1577,13 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { connect_blocks(&nodes[0], 6); connect_blocks(&nodes[0], 6); assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - assert!(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -1110,7 +1601,8 @@ fn test_no_preimage_inbound_htlc_balances() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000); + let (_, _, chan_id, funding_tx) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000); // Send two HTLCs, one from A to B, and one from B to A. let to_b_failed_payment_hash = route_payment(&nodes[0], &[&nodes[1]], 10_000_000).1; @@ -1146,27 +1638,55 @@ fn test_no_preimage_inbound_htlc_balances() { // Both A and B will have an HTLC that's claimable on timeout and one that's claimable if they // receive the preimage. These will remain the same through the channel closure and until the // HTLC output is spent. - let commitment_tx_fee = chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 1_000_000 - 500_000 - 10_000 - commitment_tx_fee, - transaction_fee_satoshis: commitment_tx_fee, - outbound_payment_htlc_rounded_msat: 0, - outbound_forwarded_htlc_rounded_msat: 0, - inbound_claiming_htlc_rounded_msat: 0, - inbound_htlc_rounded_msat: 0, - }, a_received_htlc_balance.clone(), a_sent_htlc_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + let commitment_tx_fee = chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { + amount_satoshis: 1_000_000 - 500_000 - 10_000 - commitment_tx_fee, + transaction_fee_satoshis: commitment_tx_fee, + outbound_payment_htlc_rounded_msat: 0, + outbound_forwarded_htlc_rounded_msat: 0, + inbound_claiming_htlc_rounded_msat: 0, + inbound_htlc_rounded_msat: 0, + }, + a_received_htlc_balance.clone(), + a_sent_htlc_balance.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 500_000 - 20_000, - transaction_fee_satoshis: 0, - outbound_payment_htlc_rounded_msat: 0, - outbound_forwarded_htlc_rounded_msat: 0, - inbound_claiming_htlc_rounded_msat: 0, - inbound_htlc_rounded_msat: 0, - }, b_received_htlc_balance.clone(), b_sent_htlc_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { + amount_satoshis: 500_000 - 20_000, + transaction_fee_satoshis: 0, + outbound_payment_htlc_rounded_msat: 0, + outbound_forwarded_htlc_rounded_msat: 0, + inbound_claiming_htlc_rounded_msat: 0, + inbound_htlc_rounded_msat: 0, + }, + b_received_htlc_balance.clone(), + b_sent_htlc_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // Get nodes[0]'s commitment transaction and HTLC-Timeout transaction let as_txn = get_local_commitment_txn!(nodes[0], chan_id); @@ -1177,35 +1697,77 @@ fn test_no_preimage_inbound_htlc_balances() { // Now close the channel by confirming A's commitment transaction on both nodes, checking the // claimable balances remain the same except for the non-HTLC balance changing variant. let node_a_commitment_claimable = nodes[0].best_block_info().1 + BREAKDOWN_TIMEOUT as u32; - let as_pre_spend_claims = sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, + let as_pre_spend_claims = sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 + - chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, confirmation_height: node_a_commitment_claimable, source: BalanceSource::HolderForceClosed, - }, a_received_htlc_balance.clone(), a_sent_htlc_balance.clone()]); + }, + a_received_htlc_balance.clone(), + a_sent_htlc_balance.clone(), + ]); mine_transaction(&nodes[0], &as_txn[0]); nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 1000000 + ); - assert_eq!(as_pre_spend_claims, - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + as_pre_spend_claims, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[1], &as_txn[0]); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); let node_b_commitment_claimable = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; - let mut bs_pre_spend_claims = sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { + let mut bs_pre_spend_claims = sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { amount_satoshis: 500_000 - 20_000, confirmation_height: node_b_commitment_claimable, source: BalanceSource::CounterpartyForceClosed, - }, b_received_htlc_balance.clone(), b_sent_htlc_balance.clone()]); - assert_eq!(bs_pre_spend_claims, - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + }, + b_received_htlc_balance.clone(), + b_sent_htlc_balance.clone(), + ]); + assert_eq!( + bs_pre_spend_claims, + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // We'll broadcast the HTLC-Timeout transaction one block prior to the htlc's expiration (as it // is confirmable in the next block), but will still include the same claimable balances as no @@ -1213,68 +1775,148 @@ fn test_no_preimage_inbound_htlc_balances() { // won't do anything as the channel is already closed. connect_blocks(&nodes[0], TEST_FINAL_CLTV); - let as_htlc_timeout_claim = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); + let as_htlc_timeout_claim = + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(as_htlc_timeout_claim.len(), 1); check_spends!(as_htlc_timeout_claim[0], as_txn[0]); - expect_pending_htlcs_forwardable_conditions!(nodes[0], - [HTLCDestination::FailedPayment { payment_hash: to_a_failed_payment_hash }]); + expect_pending_htlcs_forwardable_conditions!( + nodes[0], + [HTLCDestination::FailedPayment { payment_hash: to_a_failed_payment_hash }] + ); - assert_eq!(as_pre_spend_claims, - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + as_pre_spend_claims, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], 1); - assert_eq!(as_pre_spend_claims, - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + as_pre_spend_claims, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // For node B, we'll get the non-HTLC funds claimable after ANTI_REORG_DELAY confirmations connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); test_spendable_output(&nodes[1], &as_txn[0], false); - bs_pre_spend_claims.retain(|e| if let Balance::ClaimableAwaitingConfirmations { .. } = e { false } else { true }); + bs_pre_spend_claims.retain(|e| { + if let Balance::ClaimableAwaitingConfirmations { .. } = e { + false + } else { + true + } + }); // The next few blocks for B look the same as for A, though for the opposite HTLC nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); connect_blocks(&nodes[1], TEST_FINAL_CLTV - (ANTI_REORG_DELAY - 1)); - expect_pending_htlcs_forwardable_conditions!(nodes[1], - [HTLCDestination::FailedPayment { payment_hash: to_b_failed_payment_hash }]); - let bs_htlc_timeout_claim = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); + expect_pending_htlcs_forwardable_conditions!( + nodes[1], + [HTLCDestination::FailedPayment { payment_hash: to_b_failed_payment_hash }] + ); + let bs_htlc_timeout_claim = + nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(bs_htlc_timeout_claim.len(), 1); check_spends!(bs_htlc_timeout_claim[0], as_txn[0]); - assert_eq!(bs_pre_spend_claims, - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + bs_pre_spend_claims, + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[1], 1); - assert_eq!(bs_pre_spend_claims, - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + bs_pre_spend_claims, + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // Now confirm the two HTLC timeout transactions for A, checking that the inbound HTLC resolves // after ANTI_REORG_DELAY confirmations and the other takes BREAKDOWN_TIMEOUT confirmations. mine_transaction(&nodes[0], &as_htlc_timeout_claim[0]); let as_timeout_claimable_height = nodes[0].best_block_info().1 + (BREAKDOWN_TIMEOUT as u32) - 1; - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, a_received_htlc_balance.clone(), Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: as_timeout_claimable_height, - source: BalanceSource::Htlc, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 - chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + a_received_htlc_balance.clone(), + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: as_timeout_claimable_height, + source: BalanceSource::Htlc, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[0], &bs_htlc_timeout_claim[0]); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, a_received_htlc_balance.clone(), Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: as_timeout_claimable_height, - source: BalanceSource::Htlc, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 - chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + a_received_htlc_balance.clone(), + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: as_timeout_claimable_height, + source: BalanceSource::Htlc, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // Once as_htlc_timeout_claim[0] reaches ANTI_REORG_DELAY confirmations, we should get a // payment failure event. @@ -1282,59 +1924,114 @@ fn test_no_preimage_inbound_htlc_balances() { expect_payment_failed!(nodes[0], to_b_failed_payment_hash, false); connect_blocks(&nodes[0], 1); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - confirmation_height: node_a_commitment_claimable, - source: BalanceSource::HolderForceClosed, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: core::cmp::max(as_timeout_claimable_height, htlc_cltv_timeout), - source: BalanceSource::Htlc, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 - chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, + confirmation_height: node_a_commitment_claimable, + source: BalanceSource::HolderForceClosed, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: core::cmp::max(as_timeout_claimable_height, htlc_cltv_timeout), + source: BalanceSource::Htlc, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], node_a_commitment_claimable - nodes[0].best_block_info().1); - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + assert_eq!( + vec![Balance::ClaimableAwaitingConfirmations { amount_satoshis: 10_000, confirmation_height: core::cmp::max(as_timeout_claimable_height, htlc_cltv_timeout), source: BalanceSource::Htlc, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); test_spendable_output(&nodes[0], &as_txn[0], false); connect_blocks(&nodes[0], as_timeout_claimable_height - nodes[0].best_block_info().1); - assert!(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); test_spendable_output(&nodes[0], &as_htlc_timeout_claim[0], false); // The process for B should be completely identical as well, noting that the non-HTLC-balance // was already claimed. mine_transaction(&nodes[1], &bs_htlc_timeout_claim[0]); let bs_timeout_claimable_height = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; - assert_eq!(sorted_vec(vec![b_received_htlc_balance.clone(), Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 20_000, - confirmation_height: bs_timeout_claimable_height, - source: BalanceSource::Htlc, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + b_received_htlc_balance.clone(), + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 20_000, + confirmation_height: bs_timeout_claimable_height, + source: BalanceSource::Htlc, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[1], &as_htlc_timeout_claim[0]); - assert_eq!(sorted_vec(vec![b_received_htlc_balance.clone(), Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 20_000, - confirmation_height: bs_timeout_claimable_height, - source: BalanceSource::Htlc, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + b_received_htlc_balance.clone(), + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 20_000, + confirmation_height: bs_timeout_claimable_height, + source: BalanceSource::Htlc, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2); expect_payment_failed!(nodes[1], to_a_failed_payment_hash, false); - assert_eq!(vec![b_received_htlc_balance.clone()], - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + assert_eq!( + vec![b_received_htlc_balance.clone()], + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); test_spendable_output(&nodes[1], &bs_htlc_timeout_claim[0], false); connect_blocks(&nodes[1], 1); - assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new @@ -1342,7 +2039,13 @@ fn test_no_preimage_inbound_htlc_balances() { connect_blocks(&nodes[1], 6); connect_blocks(&nodes[1], 6); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); } fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_spend_first: bool) { @@ -1359,7 +2062,8 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = @@ -1380,7 +2084,8 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ // are all currently claimed in separate transactions, which helps us test as we can claim // HTLCs individually. - let (claimed_payment_preimage, claimed_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 3_000_100); + let (claimed_payment_preimage, claimed_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 3_000_100); let timeout_payment_hash = route_payment(&nodes[1], &[&nodes[0]], 4_000_200).1; let dust_payment_hash = route_payment(&nodes[1], &[&nodes[0]], 3_000).1; @@ -1414,23 +2119,32 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ assert_eq!(events.len(), 6); let mut failed_payments: HashSet<_> = [timeout_payment_hash, dust_payment_hash, live_payment_hash, missing_htlc_payment_hash] - .iter().map(|a| *a).collect(); - events.retain(|ev| { - match ev { - Event::HTLCHandlingFailed { failed_next_destination: HTLCDestination::NextHopChannel { node_id, channel_id }, .. } => { - assert_eq!(*channel_id, chan_id); - assert_eq!(*node_id, Some(nodes[1].node.get_our_node_id())); - false - }, - Event::HTLCHandlingFailed { failed_next_destination: HTLCDestination::FailedPayment { payment_hash }, .. } => { - assert!(failed_payments.remove(payment_hash)); - false - }, - _ => true, - } + .iter() + .map(|a| *a) + .collect(); + events.retain(|ev| match ev { + Event::HTLCHandlingFailed { + failed_next_destination: HTLCDestination::NextHopChannel { node_id, channel_id }, + .. + } => { + assert_eq!(*channel_id, chan_id); + assert_eq!(*node_id, Some(nodes[1].node.get_our_node_id())); + false + }, + Event::HTLCHandlingFailed { + failed_next_destination: HTLCDestination::FailedPayment { payment_hash }, + .. + } => { + assert!(failed_payments.remove(payment_hash)); + false + }, + _ => true, }); assert!(failed_payments.is_empty()); - if let Event::PendingHTLCsForwardable { .. } = events[0] {} else { panic!(); } + if let Event::PendingHTLCsForwardable { .. } = events[0] { + } else { + panic!(); + } match &events[1] { Event::ChannelClosed { reason: ClosureReason::HTLCsTimedOut, .. } => {}, _ => panic!(), @@ -1439,49 +2153,78 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ connect_blocks(&nodes[1], htlc_cltv_timeout + 1 - 10); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::HTLCsTimedOut, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HTLCsTimedOut, + [nodes[0].node.get_our_node_id()], + 1000000 + ); // Prior to channel closure, B considers the preimage HTLC as its own, and otherwise only // lists the two on-chain timeout-able HTLCs as claimable balances. assert_eq!( sorted_vec(vec![ Balance::ClaimableOnChannelClose { - amount_satoshis: 100_000 - 5_000 - 4_000 - 3 - 2_000 + 3_000 - 1 /* rounded up msat parts of HTLCs */, + amount_satoshis: 100_000 - 5_000 - 4_000 - 3 - 2_000 + 3_000 - 1, /* rounded up msat parts of HTLCs */ transaction_fee_satoshis: 0, outbound_payment_htlc_rounded_msat: 3200, outbound_forwarded_htlc_rounded_msat: 0, inbound_claiming_htlc_rounded_msat: 100, inbound_htlc_rounded_msat: 0, - }, Balance::MaybeTimeoutClaimableHTLC { + }, + Balance::MaybeTimeoutClaimableHTLC { amount_satoshis: 2_000, claimable_height: missing_htlc_cltv_timeout, payment_hash: missing_htlc_payment_hash, outbound_payment: true, - }, Balance::MaybeTimeoutClaimableHTLC { + }, + Balance::MaybeTimeoutClaimableHTLC { amount_satoshis: 4_000, claimable_height: htlc_cltv_timeout, payment_hash: timeout_payment_hash, outbound_payment: true, - }, Balance::MaybeTimeoutClaimableHTLC { + }, + Balance::MaybeTimeoutClaimableHTLC { amount_satoshis: 5_000, claimable_height: live_htlc_cltv_timeout, payment_hash: live_payment_hash, outbound_payment: true, }, ]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ), ); mine_transaction(&nodes[1], &as_revoked_txn[0]); - let mut claim_txn: Vec<_> = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().drain(..).filter(|tx| tx.input.iter().any(|inp| inp.previous_output.txid == as_revoked_txn[0].compute_txid())).collect(); + let mut claim_txn: Vec<_> = nodes[1] + .tx_broadcaster + .txn_broadcasted + .lock() + .unwrap() + .drain(..) + .filter(|tx| { + tx.input.iter().any(|inp| inp.previous_output.txid == as_revoked_txn[0].compute_txid()) + }) + .collect(); // Currently, the revoked commitment is claimed in two batches based on pinnability. assert_eq!(claim_txn.len(), 2); - claim_txn.sort_unstable_by_key(|tx| tx.output.iter().map(|output| output.value.to_sat()).sum::()); + claim_txn.sort_unstable_by_key(|tx| { + tx.output.iter().map(|output| output.value.to_sat()).sum::() + }); // The following constants were determined experimentally let anchor_outputs_value = if anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 }; - let commitment_tx_fee = chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 3 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 3 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; let pinnable_weight = if anchors { 1398 } else { 1389 }; let unpinnable_weight = 483; @@ -1489,27 +2232,36 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ // somewhat so it may not always be exact. fuzzy_assert_eq(claim_txn[0].weight().to_wu(), pinnable_weight); fuzzy_assert_eq(claim_txn[1].weight().to_wu(), unpinnable_weight); - let pinnable_fee = claim_txn[0].input.iter().map(|txin| { - assert_eq!(txin.previous_output.txid, as_revoked_txn[0].compute_txid()); - as_revoked_txn[0].output[txin.previous_output.vout as usize].value.to_sat() - }).sum::() - claim_txn[0].output.iter().map(|txout| txout.value.to_sat()).sum::(); - let unpinnable_fee = claim_txn[1].input.iter().map(|txin| { - assert_eq!(txin.previous_output.txid, as_revoked_txn[0].compute_txid()); - as_revoked_txn[0].output[txin.previous_output.vout as usize].value.to_sat() - }).sum::() - claim_txn[1].output.iter().map(|txout| txout.value.to_sat()).sum::(); + let pinnable_fee = claim_txn[0] + .input + .iter() + .map(|txin| { + assert_eq!(txin.previous_output.txid, as_revoked_txn[0].compute_txid()); + as_revoked_txn[0].output[txin.previous_output.vout as usize].value.to_sat() + }) + .sum::() + - claim_txn[0].output.iter().map(|txout| txout.value.to_sat()).sum::(); + let unpinnable_fee = claim_txn[1] + .input + .iter() + .map(|txin| { + assert_eq!(txin.previous_output.txid, as_revoked_txn[0].compute_txid()); + as_revoked_txn[0].output[txin.previous_output.vout as usize].value.to_sat() + }) + .sum::() + - claim_txn[1].output.iter().map(|txout| txout.value.to_sat()).sum::(); // The expected balances for the next three checks. let to_remote_balance = Balance::ClaimableAwaitingConfirmations { // to_remote output in A's revoked commitment - amount_satoshis: 100_000 - 5_000 - 4_000 - 3 - 1 /* rounded up msat parts of HTLCs */, + amount_satoshis: 100_000 - 5_000 - 4_000 - 3 - 1, /* rounded up msat parts of HTLCs */ confirmation_height: nodes[1].best_block_info().1 + 5, source: BalanceSource::CounterpartyForceClosed, }; - let htlc_unclaimed_balance = |amount: u64| Balance::CounterpartyRevokedOutputClaimable { - amount_satoshis: amount, - }; + let htlc_unclaimed_balance = + |amount: u64| Balance::CounterpartyRevokedOutputClaimable { amount_satoshis: amount }; let to_self_unclaimed_balance = Balance::CounterpartyRevokedOutputClaimable { - amount_satoshis: 1_000_000 - 100_000 - 3_000 - commitment_tx_fee - anchor_outputs_value - 1 /* rounded up msat parts of HTLCs */, + amount_satoshis: 1_000_000 - 100_000 - 3_000 - commitment_tx_fee - anchor_outputs_value - 1, /* rounded up msat parts of HTLCs */ }; let to_self_claimed_avail_height; let largest_htlc_claimed_avail_height; @@ -1524,7 +2276,14 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ htlc_unclaimed_balance(4_000), htlc_unclaimed_balance(5_000), ]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ), ); if confirm_htlc_spend_first { @@ -1544,7 +2303,12 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ source: BalanceSource::CounterpartyForceClosed, }; let unpinnable_claimed_balance = Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 100_000 - 3_000 - commitment_tx_fee - anchor_outputs_value - unpinnable_fee - 1 /* rounded up msat parts of HTLCs */, + amount_satoshis: 1_000_000 + - 100_000 - 3_000 + - commitment_tx_fee + - anchor_outputs_value + - unpinnable_fee + - 1, /* rounded up msat parts of HTLCs */ confirmation_height: to_self_claimed_avail_height, source: BalanceSource::CounterpartyForceClosed, }; @@ -1556,7 +2320,14 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ pinnable_claimed_balance.clone(), to_self_unclaimed_balance.clone(), ]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ), ); } else { assert_eq!( @@ -1567,7 +2338,14 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ htlc_unclaimed_balance(4_000), htlc_unclaimed_balance(5_000), ]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ), ); } @@ -1582,26 +2360,49 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ pinnable_claimed_balance.clone(), unpinnable_claimed_balance.clone(), ]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ), ); connect_blocks(&nodes[1], 3); test_spendable_output(&nodes[1], &as_revoked_txn[0], false); let mut payment_failed_events = nodes[1].node.get_and_clear_pending_events(); - expect_payment_failed_conditions_event(payment_failed_events[..2].to_vec(), - missing_htlc_payment_hash, false, PaymentFailedConditions::new()); - expect_payment_failed_conditions_event(payment_failed_events[2..].to_vec(), - dust_payment_hash, false, PaymentFailedConditions::new()); + expect_payment_failed_conditions_event( + payment_failed_events[..2].to_vec(), + missing_htlc_payment_hash, + false, + PaymentFailedConditions::new(), + ); + expect_payment_failed_conditions_event( + payment_failed_events[2..].to_vec(), + dust_payment_hash, + false, + PaymentFailedConditions::new(), + ); connect_blocks(&nodes[1], 1); if confirm_htlc_spend_first { test_spendable_output(&nodes[1], &claim_txn[0], false); let mut payment_failed_events = nodes[1].node.get_and_clear_pending_events(); - expect_payment_failed_conditions_event(payment_failed_events[..2].to_vec(), - live_payment_hash, false, PaymentFailedConditions::new()); - expect_payment_failed_conditions_event(payment_failed_events[2..].to_vec(), - timeout_payment_hash, false, PaymentFailedConditions::new()); + expect_payment_failed_conditions_event( + payment_failed_events[..2].to_vec(), + live_payment_hash, + false, + PaymentFailedConditions::new(), + ); + expect_payment_failed_conditions_event( + payment_failed_events[2..].to_vec(), + timeout_payment_hash, + false, + PaymentFailedConditions::new(), + ); } else { test_spendable_output(&nodes[1], &claim_txn[1], false); } @@ -1611,12 +2412,23 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ } else { test_spendable_output(&nodes[1], &claim_txn[0], false); let mut payment_failed_events = nodes[1].node.get_and_clear_pending_events(); - expect_payment_failed_conditions_event(payment_failed_events[..2].to_vec(), - live_payment_hash, false, PaymentFailedConditions::new()); - expect_payment_failed_conditions_event(payment_failed_events[2..].to_vec(), - timeout_payment_hash, false, PaymentFailedConditions::new()); + expect_payment_failed_conditions_event( + payment_failed_events[..2].to_vec(), + live_payment_hash, + false, + PaymentFailedConditions::new(), + ); + expect_payment_failed_conditions_event( + payment_failed_events[2..].to_vec(), + timeout_payment_hash, + false, + PaymentFailedConditions::new(), + ); } - assert_eq!(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances(), Vec::new()); + assert_eq!( + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances(), + Vec::new() + ); // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new @@ -1624,7 +2436,13 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ connect_blocks(&nodes[1], 6); connect_blocks(&nodes[1], 6); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -1645,7 +2463,8 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -1664,8 +2483,14 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { ], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, coinbase_tx.output[1].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); + nodes[1].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, + coinbase_tx.output[1].value, + ); } // Create some initial channels @@ -1698,7 +2523,13 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { mine_transaction(&nodes[1], &revoked_local_txn[0]); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); if anchors { handle_bump_htlc_event(&nodes[1], 1); } @@ -1707,8 +2538,10 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { assert_eq!(txn.len(), 1); assert_eq!(txn[0].input.len(), if anchors { 2 } else { 1 }); assert_eq!(txn[0].input[0].previous_output.vout, if anchors { 3 } else { 1 }); - assert_eq!(txn[0].input[0].witness.last().unwrap().len(), - if anchors { ACCEPTED_HTLC_SCRIPT_WEIGHT_ANCHORS } else { ACCEPTED_HTLC_SCRIPT_WEIGHT }); + assert_eq!( + txn[0].input[0].witness.last().unwrap().len(), + if anchors { ACCEPTED_HTLC_SCRIPT_WEIGHT_ANCHORS } else { ACCEPTED_HTLC_SCRIPT_WEIGHT } + ); check_spends!(txn[0], revoked_local_txn[0], coinbase_tx); txn.pop().unwrap() }; @@ -1728,7 +2561,10 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { } }; check_spends!(revoked_htlc_timeout, revoked_local_txn[0], coinbase_tx); - assert_ne!(revoked_htlc_success.input[0].previous_output, revoked_htlc_timeout.input[0].previous_output); + assert_ne!( + revoked_htlc_success.input[0].previous_output, + revoked_htlc_timeout.input[0].previous_output + ); assert_eq!(revoked_htlc_success.lock_time, LockTime::ZERO); assert_ne!(revoked_htlc_timeout.lock_time, LockTime::ZERO); @@ -1736,13 +2572,21 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { // `COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE` blocks, making us consider all the HTLCs // pinnable claims, which the remainder of the test assumes. connect_blocks(&nodes[0], TEST_FINAL_CLTV - COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(&nodes[0], - [HTLCDestination::FailedPayment { payment_hash: failed_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + &nodes[0], + [HTLCDestination::FailedPayment { payment_hash: failed_payment_hash }] + ); // A will generate justice tx from B's revoked commitment/HTLC tx mine_transaction(&nodes[0], &revoked_local_txn[0]); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 1000000 + ); let to_remote_conf_height = nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1; let revoked_to_self_claim = { @@ -1754,33 +2598,63 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { assert_eq!(as_commitment_claim_txn[1].input.len(), 2); check_spends!(as_commitment_claim_txn[0], revoked_local_txn[0]); check_spends!(as_commitment_claim_txn[1], revoked_local_txn[0]); - assert_ne!(as_commitment_claim_txn[0].input[0].previous_output, as_commitment_claim_txn[1].input[0].previous_output); - assert_ne!(as_commitment_claim_txn[0].input[0].previous_output, as_commitment_claim_txn[1].input[1].previous_output); - assert_ne!(as_commitment_claim_txn[1].input[0].previous_output, as_commitment_claim_txn[1].input[1].previous_output); + assert_ne!( + as_commitment_claim_txn[0].input[0].previous_output, + as_commitment_claim_txn[1].input[0].previous_output + ); + assert_ne!( + as_commitment_claim_txn[0].input[0].previous_output, + as_commitment_claim_txn[1].input[1].previous_output + ); + assert_ne!( + as_commitment_claim_txn[1].input[0].previous_output, + as_commitment_claim_txn[1].input[1].previous_output + ); as_commitment_claim_txn.remove(0) }; // The next two checks have the same balance set for A - even though we confirm a revoked HTLC // transaction our balance tracking doesn't use the on-chain value so the // `CounterpartyRevokedOutputClaimable` entry doesn't change. - let commitment_tx_fee = chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; let anchor_outputs_value = if anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 }; - let as_balances = sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { + let as_balances = sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { // to_remote output in B's revoked commitment - amount_satoshis: 1_000_000 - 12_000 - 3_000 - commitment_tx_fee - anchor_outputs_value - 1 /* The rounded up msat part of the one HTLC */, + amount_satoshis: 1_000_000 + - 12_000 - 3_000 - commitment_tx_fee + - anchor_outputs_value + - 1, /* The rounded up msat part of the one HTLC */ confirmation_height: to_remote_conf_height, source: BalanceSource::CounterpartyForceClosed, - }, Balance::CounterpartyRevokedOutputClaimable { + }, + Balance::CounterpartyRevokedOutputClaimable { // to_self output in B's revoked commitment amount_satoshis: 11_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 1 + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 1 amount_satoshis: 3_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 amount_satoshis: 1_000, - }]); - assert_eq!(as_balances, - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + }, + ]); + assert_eq!( + as_balances, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[0], &revoked_htlc_success); let as_htlc_claim_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); @@ -1792,64 +2666,126 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { assert_eq!(as_htlc_claim_tx[1].input.len(), 1); check_spends!(as_htlc_claim_tx[1], revoked_local_txn[0]); - assert_eq!(as_balances, - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + as_balances, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); assert_eq!(as_htlc_claim_tx[0].output.len(), 1); - let as_revoked_htlc_success_claim_fee = chan_feerate * as_htlc_claim_tx[0].weight().to_wu() / 1000; + let as_revoked_htlc_success_claim_fee = + chan_feerate * as_htlc_claim_tx[0].weight().to_wu() / 1000; if anchors { // With anchors, B can pay for revoked_htlc_success's fee with additional inputs, rather // than with the HTLC itself. - fuzzy_assert_eq(as_htlc_claim_tx[0].output[0].value.to_sat(), - 3_000 - as_revoked_htlc_success_claim_fee); + fuzzy_assert_eq( + as_htlc_claim_tx[0].output[0].value.to_sat(), + 3_000 - as_revoked_htlc_success_claim_fee, + ); } else { - fuzzy_assert_eq(as_htlc_claim_tx[0].output[0].value.to_sat(), - 3_000 - revoked_htlc_success_fee - as_revoked_htlc_success_claim_fee); + fuzzy_assert_eq( + as_htlc_claim_tx[0].output[0].value.to_sat(), + 3_000 - revoked_htlc_success_fee - as_revoked_htlc_success_claim_fee, + ); } mine_transaction(&nodes[0], &as_htlc_claim_tx[0]); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - // to_remote output in B's revoked commitment - amount_satoshis: 1_000_000 - 12_000 - 3_000 - commitment_tx_fee - anchor_outputs_value - 1 /* rounded up msat parts of HTLCs */, - confirmation_height: to_remote_conf_height, - source: BalanceSource::CounterpartyForceClosed, - }, Balance::CounterpartyRevokedOutputClaimable { - // to_self output in B's revoked commitment - amount_satoshis: 11_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 - amount_satoshis: 1_000, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: as_htlc_claim_tx[0].output[0].value.to_sat(), - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - source: BalanceSource::CounterpartyForceClosed, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + // to_remote output in B's revoked commitment + amount_satoshis: 1_000_000 + - 12_000 - 3_000 - commitment_tx_fee + - anchor_outputs_value + - 1, /* rounded up msat parts of HTLCs */ + confirmation_height: to_remote_conf_height, + source: BalanceSource::CounterpartyForceClosed, + }, + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in B's revoked commitment + amount_satoshis: 11_000, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 + amount_satoshis: 1_000, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: as_htlc_claim_tx[0].output[0].value.to_sat(), + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + source: BalanceSource::CounterpartyForceClosed, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 3); test_spendable_output(&nodes[0], &revoked_local_txn[0], false); - assert_eq!(sorted_vec(vec![Balance::CounterpartyRevokedOutputClaimable { - // to_self output to B - amount_satoshis: 11_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 - amount_satoshis: 1_000, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: as_htlc_claim_tx[0].output[0].value.to_sat(), - confirmation_height: nodes[0].best_block_info().1 + 2, - source: BalanceSource::CounterpartyForceClosed, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::CounterpartyRevokedOutputClaimable { + // to_self output to B + amount_satoshis: 11_000, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 + amount_satoshis: 1_000, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: as_htlc_claim_tx[0].output[0].value.to_sat(), + confirmation_height: nodes[0].best_block_info().1 + 2, + source: BalanceSource::CounterpartyForceClosed, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], 2); test_spendable_output(&nodes[0], &as_htlc_claim_tx[0], false); - assert_eq!(sorted_vec(vec![Balance::CounterpartyRevokedOutputClaimable { - // to_self output in B's revoked commitment - amount_satoshis: 11_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 - amount_satoshis: 1_000, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in B's revoked commitment + amount_satoshis: 11_000, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 + amount_satoshis: 1_000, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); - connect_blocks(&nodes[0], revoked_htlc_timeout.lock_time.to_consensus_u32() - nodes[0].best_block_info().1); + connect_blocks( + &nodes[0], + revoked_htlc_timeout.lock_time.to_consensus_u32() - nodes[0].best_block_info().1, + ); // As time goes on A may split its revocation claim transaction into multiple. let as_fewer_input_rbf = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); for tx in as_fewer_input_rbf.iter() { @@ -1877,44 +2813,84 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { // previous iteration of the revoked balance handling this would result in us "forgetting" that // the revoked HTLC output still needed to be claimed. connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); - assert_eq!(sorted_vec(vec![Balance::CounterpartyRevokedOutputClaimable { - // to_self output in B's revoked commitment - amount_satoshis: 11_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 - amount_satoshis: 1_000, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in B's revoked commitment + amount_satoshis: 11_000, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 + amount_satoshis: 1_000, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[0], &revoked_htlc_timeout_claim); - assert_eq!(sorted_vec(vec![Balance::CounterpartyRevokedOutputClaimable { - // to_self output in B's revoked commitment - amount_satoshis: 11_000, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: revoked_htlc_timeout_claim.output[0].value.to_sat(), - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - source: BalanceSource::CounterpartyForceClosed, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in B's revoked commitment + amount_satoshis: 11_000, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: revoked_htlc_timeout_claim.output[0].value.to_sat(), + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + source: BalanceSource::CounterpartyForceClosed, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[0], &revoked_to_self_claim); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - // to_self output in B's revoked commitment - amount_satoshis: revoked_to_self_claim.output[0].value.to_sat(), - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - source: BalanceSource::CounterpartyForceClosed, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: revoked_htlc_timeout_claim.output[0].value.to_sat(), - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 2, - source: BalanceSource::CounterpartyForceClosed, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + // to_self output in B's revoked commitment + amount_satoshis: revoked_to_self_claim.output[0].value.to_sat(), + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + source: BalanceSource::CounterpartyForceClosed, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: revoked_htlc_timeout_claim.output[0].value.to_sat(), + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 2, + source: BalanceSource::CounterpartyForceClosed, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 2); test_spendable_output(&nodes[0], &revoked_htlc_timeout_claim, false); connect_blocks(&nodes[0], 1); test_spendable_output(&nodes[0], &revoked_to_self_claim, false); - assert_eq!(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances(), Vec::new()); + assert_eq!( + nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances(), + Vec::new() + ); // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new @@ -1922,7 +2898,13 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { connect_blocks(&nodes[0], 6); connect_blocks(&nodes[0], 6); assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - assert!(nodes[0].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -1946,7 +2928,8 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -1958,7 +2941,10 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), }], }; - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 100_000_000); @@ -1969,7 +2955,8 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { // transaction, and one which we will not, allowing B to claim the HTLC output in an aggregated // revocation-claim transaction. - let (claimed_payment_preimage, claimed_payment_hash, ..) = route_payment(&nodes[1], &[&nodes[0]], 3_000_100); + let (claimed_payment_preimage, claimed_payment_hash, ..) = + route_payment(&nodes[1], &[&nodes[0]], 3_000_100); let revoked_payment_hash = route_payment(&nodes[1], &[&nodes[0]], 4_000_000).1; let htlc_cltv_timeout = nodes[1].best_block_info().1 + TEST_FINAL_CLTV + 1; // Note ChannelManager adds one to CLTV timeouts for safety @@ -1977,8 +2964,11 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { // Cheat by giving A's ChannelMonitor the preimage to the to-be-claimed HTLC so that we have an // HTLC-claim transaction on the to-be-revoked state. get_monitor!(nodes[0], chan_id).provide_payment_preimage_unsafe_legacy( - &claimed_payment_hash, &claimed_payment_preimage, &node_cfgs[0].tx_broadcaster, - &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger + &claimed_payment_hash, + &claimed_payment_preimage, + &node_cfgs[0].tx_broadcaster, + &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), + &nodes[0].logger, ); // Now get the latest commitment transaction from A and then update the fee to revoke it @@ -2001,7 +2991,9 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { check_added_monitors!(nodes[0], 1); let fee_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), &fee_update.update_fee.unwrap()); + nodes[1] + .node + .handle_update_fee(nodes[0].node.get_our_node_id(), &fee_update.update_fee.unwrap()); commitment_signed_dance!(nodes[1], nodes[0], fee_update.commitment_signed, false); nodes[0].node.claim_funds(claimed_payment_preimage); @@ -2009,29 +3001,48 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { check_added_monitors!(nodes[0], 1); let _a_htlc_msgs = get_htlc_update_msgs!(&nodes[0], nodes[1].node.get_our_node_id()); - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 100_000 - 4_000 - 3_000 - 1 /* rounded up msat parts of HTLCs */, - transaction_fee_satoshis: 0, - outbound_payment_htlc_rounded_msat: 100, - outbound_forwarded_htlc_rounded_msat: 0, - inbound_claiming_htlc_rounded_msat: 0, - inbound_htlc_rounded_msat: 0, - }, Balance::MaybeTimeoutClaimableHTLC { - amount_satoshis: 4_000, - claimable_height: htlc_cltv_timeout, - payment_hash: revoked_payment_hash, - outbound_payment: true, - }, Balance::MaybeTimeoutClaimableHTLC { - amount_satoshis: 3_000, - claimable_height: htlc_cltv_timeout, - payment_hash: claimed_payment_hash, - outbound_payment: true, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { + amount_satoshis: 100_000 - 4_000 - 3_000 - 1, /* rounded up msat parts of HTLCs */ + transaction_fee_satoshis: 0, + outbound_payment_htlc_rounded_msat: 100, + outbound_forwarded_htlc_rounded_msat: 0, + inbound_claiming_htlc_rounded_msat: 0, + inbound_htlc_rounded_msat: 0, + }, + Balance::MaybeTimeoutClaimableHTLC { + amount_satoshis: 4_000, + claimable_height: htlc_cltv_timeout, + payment_hash: revoked_payment_hash, + outbound_payment: true, + }, + Balance::MaybeTimeoutClaimableHTLC { + amount_satoshis: 3_000, + claimable_height: htlc_cltv_timeout, + payment_hash: claimed_payment_hash, + outbound_payment: true, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[1], &as_revoked_txn[0]); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); check_added_monitors!(nodes[1], 1); let mut claim_txn = nodes[1].tx_broadcaster.txn_broadcast(); @@ -2046,26 +3057,43 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { assert_ne!(claim_txn[0].input[0].previous_output, claim_txn[1].input[1].previous_output); assert_ne!(claim_txn[1].input[0].previous_output, claim_txn[1].input[1].previous_output); - let to_remote_maturity = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; - let commitment_tx_fee = chan_feerate * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; let anchor_outputs_value = if anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 }; - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - // to_remote output in A's revoked commitment - amount_satoshis: 100_000 - 4_000 - 3_000 - 1 /* rounded up msat parts of HTLCs */, - confirmation_height: to_remote_maturity, - source: BalanceSource::CounterpartyForceClosed, - }, Balance::CounterpartyRevokedOutputClaimable { - // to_self output in A's revoked commitment - amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 1 - amount_satoshis: 4_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 - amount_satoshis: 3_000, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + // to_remote output in A's revoked commitment + amount_satoshis: 100_000 - 4_000 - 3_000 - 1, /* rounded up msat parts of HTLCs */ + confirmation_height: to_remote_maturity, + source: BalanceSource::CounterpartyForceClosed, + }, + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in A's revoked commitment + amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 1 + amount_satoshis: 4_000, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 + amount_satoshis: 3_000, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); // Confirm A's HTLC-Success transaction which presumably raced B's claim, causing B to create a // new claim. @@ -2073,7 +3101,14 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { mine_transaction(&nodes[0], &as_revoked_txn[0]); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event!(&nodes[0], 1, ClosureReason::CommitmentTxConfirmed, false, [nodes[1].node.get_our_node_id()], 1_000_000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); handle_bump_htlc_event(&nodes[0], 1); } let htlc_success_claim = if anchors { @@ -2105,65 +3140,124 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { check_spends!(claim_txn_2[1], as_revoked_txn[0]); } - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - // to_remote output in A's revoked commitment - amount_satoshis: 100_000 - 4_000 - 3_000 - 1 /* rounded up msat parts of HTLCs */, - confirmation_height: to_remote_maturity, - source: BalanceSource::CounterpartyForceClosed, - }, Balance::CounterpartyRevokedOutputClaimable { - // to_self output in A's revoked commitment - amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 1 - amount_satoshis: 4_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 - // The amount here is a bit of a misnomer, really its been reduced by the HTLC - // transaction fee, but the claimable amount is always a bit of an overshoot for HTLCs - // anyway, so its not a big change. - amount_satoshis: 3_000, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + // to_remote output in A's revoked commitment + amount_satoshis: 100_000 - 4_000 - 3_000 - 1, /* rounded up msat parts of HTLCs */ + confirmation_height: to_remote_maturity, + source: BalanceSource::CounterpartyForceClosed, + }, + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in A's revoked commitment + amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 1 + amount_satoshis: 4_000, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 + // The amount here is a bit of a misnomer, really its been reduced by the HTLC + // transaction fee, but the claimable amount is always a bit of an overshoot for HTLCs + // anyway, so its not a big change. + amount_satoshis: 3_000, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[1], 5); test_spendable_output(&nodes[1], &as_revoked_txn[0], false); - assert_eq!(sorted_vec(vec![Balance::CounterpartyRevokedOutputClaimable { - // to_self output in A's revoked commitment - amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 1 - amount_satoshis: 4_000, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 2 - // The amount here is a bit of a misnomer, really its been reduced by the HTLC - // transaction fee, but the claimable amount is always a bit of an overshoot for HTLCs - // anyway, so its not a big change. - amount_satoshis: 3_000, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in A's revoked commitment + amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 1 + amount_satoshis: 4_000, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 2 + // The amount here is a bit of a misnomer, really its been reduced by the HTLC + // transaction fee, but the claimable amount is always a bit of an overshoot for HTLCs + // anyway, so its not a big change. + amount_satoshis: 3_000, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transaction(&nodes[1], &claim_txn_2[0]); let htlc_2_claim_maturity = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; - assert_eq!(sorted_vec(vec![Balance::CounterpartyRevokedOutputClaimable { - // to_self output in A's revoked commitment - amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 1 - amount_satoshis: 4_000, - }, Balance::ClaimableAwaitingConfirmations { // HTLC 2 - amount_satoshis: claim_txn_2[0].output[0].value.to_sat(), - confirmation_height: htlc_2_claim_maturity, - source: BalanceSource::CounterpartyForceClosed, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in A's revoked commitment + amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 1 + amount_satoshis: 4_000, + }, + Balance::ClaimableAwaitingConfirmations { + // HTLC 2 + amount_satoshis: claim_txn_2[0].output[0].value.to_sat(), + confirmation_height: htlc_2_claim_maturity, + source: BalanceSource::CounterpartyForceClosed, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[1], 5); test_spendable_output(&nodes[1], &claim_txn_2[0], false); - assert_eq!(sorted_vec(vec![Balance::CounterpartyRevokedOutputClaimable { - // to_self output in A's revoked commitment - amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, - }, Balance::CounterpartyRevokedOutputClaimable { // HTLC 1 - amount_satoshis: 4_000, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::CounterpartyRevokedOutputClaimable { + // to_self output in A's revoked commitment + amount_satoshis: 1_000_000 - 100_000 - commitment_tx_fee - anchor_outputs_value, + }, + Balance::CounterpartyRevokedOutputClaimable { + // HTLC 1 + amount_satoshis: 4_000, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + ) + ); mine_transactions(&nodes[1], &[&claim_txn[0], &claim_txn_2[1]]); let rest_claim_maturity = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; @@ -2181,26 +3275,43 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { source: BalanceSource::CounterpartyForceClosed, }, ], - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()); + nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances() + ); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); // We shouldn't fail the payment until we spend the output connect_blocks(&nodes[1], 5); expect_payment_failed!(nodes[1], revoked_payment_hash, false); - let spendable_output_events = nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events(); + let spendable_output_events = + nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events(); assert_eq!(spendable_output_events.len(), 2); for event in spendable_output_events { if let Event::SpendableOutputs { outputs, channel_id: _ } = event { assert_eq!(outputs.len(), 1); - let spend_tx = nodes[1].keys_manager.backing.spend_spendable_outputs( - &[&outputs[0]], Vec::new(), ScriptBuf::new_op_return(&[]), 253, None, &Secp256k1::new(), - ).unwrap(); + let spend_tx = nodes[1] + .keys_manager + .backing + .spend_spendable_outputs( + &[&outputs[0]], + Vec::new(), + ScriptBuf::new_op_return(&[]), + 253, + None, + &Secp256k1::new(), + ) + .unwrap(); check_spends!(spend_tx, &claim_txn[0], &claim_txn_2[1]); } else { panic!("unexpected event"); } } - assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); // Ensure that even if we connect more blocks, potentially replaying the entire chain if we're // using `ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks`, we don't get new @@ -2208,7 +3319,13 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { connect_blocks(&nodes[1], 6); connect_blocks(&nodes[1], 6); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_id) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -2236,7 +3353,11 @@ fn do_test_claimable_balance_correct_while_payment_pending(outbound_payment: boo user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(user_config.clone()), Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(user_config.clone()), Some(user_config.clone()), Some(user_config)], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -2255,18 +3376,28 @@ fn do_test_claimable_balance_correct_while_payment_pending(outbound_payment: boo ], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, coinbase_tx.output[1].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); + nodes[1].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 1 }, + coinbase_tx.output[1].value, + ); } // Create a channel from A -> B - let (_, _, chan_ab_id, funding_tx_ab) = - create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000 /* channel_value (sat) */, 0 /* push_msat */); + let (_, _, chan_ab_id, funding_tx_ab) = create_announced_chan_between_nodes_with_value( + &nodes, 0, 1, 1_000_000, /* channel_value (sat) */ + 0, /* push_msat */ + ); let funding_outpoint_ab = OutPoint { txid: funding_tx_ab.compute_txid(), index: 0 }; assert_eq!(ChannelId::v1_from_funding_outpoint(funding_outpoint_ab), chan_ab_id); // Create a channel from B -> C - let (_, _, chan_bc_id, funding_tx_bc) = - create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000 /* channel_value (sat) */, 0 /* push_msat */); + let (_, _, chan_bc_id, funding_tx_bc) = create_announced_chan_between_nodes_with_value( + &nodes, 1, 2, 1_000_000, /* channel_value (sat) */ + 0, /* push_msat */ + ); let funding_outpoint_bc = OutPoint { txid: funding_tx_bc.compute_txid(), index: 0 }; assert_eq!(ChannelId::v1_from_funding_outpoint(funding_outpoint_bc), chan_bc_id); @@ -2279,8 +3410,10 @@ fn do_test_claimable_balance_correct_while_payment_pending(outbound_payment: boo let channel_type_features_bc = get_channel_type_features!(nodes[1], nodes[2], chan_bc_id); (chan_bc_feerate, channel_type_features_bc) }; - let commitment_tx_fee = chan_feerate as u64 * - (chan_utils::commitment_tx_base_weight(&channel_type_features) + chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate as u64 + * (chan_utils::commitment_tx_base_weight(&channel_type_features) + + chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; // This HTLC will be forwarded by B from A -> C let _ = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 4_000_000); @@ -2288,18 +3421,42 @@ fn do_test_claimable_balance_correct_while_payment_pending(outbound_payment: boo if outbound_payment { assert_eq!( - 1_000_000 - commitment_tx_fee - anchor_outputs_value - 4_001 /* Note HTLC timeout amount of 4001 sats is excluded for outbound payment */, - nodes[0].chain_monitor.chain_monitor.get_monitor(chan_ab_id).unwrap().get_claimable_balances().iter().map( - |x| x.claimable_amount_satoshis()).sum()); + 1_000_000 - commitment_tx_fee - anchor_outputs_value - 4_001, /* Note HTLC timeout amount of 4001 sats is excluded for outbound payment */ + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(chan_ab_id) + .unwrap() + .get_claimable_balances() + .iter() + .map(|x| x.claimable_amount_satoshis()) + .sum() + ); } else { assert_eq!( 0u64, - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_ab_id).unwrap().get_claimable_balances().iter().map( - |x| x.claimable_amount_satoshis()).sum()); + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_ab_id) + .unwrap() + .get_claimable_balances() + .iter() + .map(|x| x.claimable_amount_satoshis()) + .sum() + ); assert_eq!( - 1_000_000 - commitment_tx_fee - anchor_outputs_value /* Note HTLC timeout amount of 4000 sats is included */, - nodes[1].chain_monitor.chain_monitor.get_monitor(chan_bc_id).unwrap().get_claimable_balances().iter().map( - |x| x.claimable_amount_satoshis()).sum()); + 1_000_000 - commitment_tx_fee - anchor_outputs_value, /* Note HTLC timeout amount of 4000 sats is included */ + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(chan_bc_id) + .unwrap() + .get_claimable_balances() + .iter() + .map(|x| x.claimable_amount_satoshis()) + .sum() + ); } } @@ -2313,8 +3470,12 @@ fn test_claimable_balance_correct_while_payment_pending() { fn do_test_restored_packages_retry(check_old_monitor_retries_after_upgrade: bool) { // Tests that we'll retry packages that were previously timelocked after we've restored them. - let node0_key_id = <[u8; 32]>::from_hex("0000000000000000000000004D49E5DA0000000000000000000000000000002A").unwrap(); - let node1_key_id = <[u8; 32]>::from_hex("0000000000000000000000004D49E5DAD000D6201F116BAFD379F1D61DF161B9").unwrap(); + let node0_key_id = + <[u8; 32]>::from_hex("0000000000000000000000004D49E5DA0000000000000000000000000000002A") + .unwrap(); + let node1_key_id = + <[u8; 32]>::from_hex("0000000000000000000000004D49E5DAD000D6201F116BAFD379F1D61DF161B9") + .unwrap(); let predefined_keys_ids = Some(vec![node0_key_id, node1_key_id]); let chanmon_cfgs = create_chanmon_cfgs_with_keys(2, predefined_keys_ids); @@ -2329,14 +3490,28 @@ fn do_test_restored_packages_retry(check_old_monitor_retries_after_upgrade: bool // Open a channel, lock in an HTLC, and immediately broadcast the commitment transaction. This // ensures that the HTLC timeout package is held until we reach its expiration height. - let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 50_000_000); + let (_, _, chan_id, funding_tx) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 50_000_000); route_payment(&nodes[0], &[&nodes[1]], 10_000_000); let error_message = "Channel force-closed"; - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); check_closed_broadcast(&nodes[0], 1, true); - check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, - [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + [nodes[1].node.get_our_node_id()], + 100000 + ); let commitment_tx = { let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); @@ -2368,7 +3543,14 @@ fn do_test_restored_packages_retry(check_old_monitor_retries_after_upgrade: bool let serialized_monitor = >::from_hex( "0101fffffffffffffffff9550f22c95100160014d5a9aa98b89acc215fc3d23d6fec0ad59ca3665f00002200204c5f18e5e95b184f34d02ba6de8a2a4e36ae3d4ec87299ad81f3284dc7195c6302d7dde8e10a5a22c9bd0d7ef5494d85683ac050253b917615d4f97af633f0a8e2035f5e9d58b4328566223c107d86cf853e6b9fae1d26ff6d969be0178d1423c4ea0016001467822698d782e8421ebdf96d010de99382b7ec2300160014caf6d80fe2bab80473b021f57588a9c384bf23170000000000000000000000004d49e5da0000000000000000000000000000002a0270b20ad0f2c2bb30a55590fc77778495bc1b38c96476901145dda57491237f0f74c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e00000022002034c0cc0ad0dd5fe61dcf7ef58f995e3d34f8dbd24aa2a6fae68fefe102bf025c21391732ce658e1fe167300bb689a81e7db5399b9ee4095e217b0e997e8dd3d17a0000000000000000004a002103adde8029d3ee281a32e9db929b39f503ff9d7e93cd308eb157955344dc6def84022103205087e2dc1f6b9937e887dfa712c5bdfa950b01dbda3ebac4c85efdde48ee6a04020090004752210307a78def56cba9fc4db22a25928181de538ee59ba1a475ae113af7790acd0db32103c21e841cbc0b48197d060c71e116c185fa0ac281b7d0aa5924f535154437ca3b52ae00000000000186a0ffffffffffff0291e7c0a3232fb8650a6b4089568a81062b48a768780e5a74bb4a4a74e33aec2c029d5760248ec86c4a76d9df8308555785a06a65472fb995f5b392d520bbd000650090c1c94b11625690c9d84c5daa67b6ad19fcc7f9f23e194384140b08fcab9e8e810000ffffffffffff000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000002167c86cc0e598a6b541f7c9bf9ef17222e4a76f636e2d22185aeadd2b02d029c0000000000000000391732ce658e1fe167300bb689a81e7db5399b9ee4095e217b0e997e8dd3d17a00000000000000010000000000009896800000005166687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f29250500000000a0009d00202d704fbfe342a9ff6eaca14d80a24aaed0e680bbbdd36157b6f2798c61d906910120f9fe5e552aa0fc45020f0505efde432a4e373e5d393863973a6899f8c26d33d102080000000000989680044d4c00210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c2302090007000000000241000408000001000000000006020000080800000000009896800a04000000460000000000000000000000000000000166687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925fffffffffffe01e3002004f8eda5676356f539169a8e9a1e86c7f125283328d6f4bded1b939b52a6a7e30108000000000000c299022103a1f98e85886df54add6908b4fc1ff515e44aedefe9eb9c02879c89994298fa79042103a650bf03971df0176c7b412247390ef717853e8bd487b204dccc2fe2078bb75206210390bbbcebe9f70ba5dfd98866a79f72f75e0a6ea550ef73b202dd87cd6477350a08210284152d57908488e666e872716a286eb670b3d06cbeebf3f2e4ad350e01ec5e5b0a2102295e2de39eb3dcc2882f8cc266df7882a8b6d2c32aa08799f49b693aad3be28e0c04000000fd0e00fd0202002045cfd42d0989e55b953f516ac7fd152bd90ec4438a2fc636f97ddd32a0c8fe0d01080000000000009b5e0221035f5e9d58b4328566223c107d86cf853e6b9fae1d26ff6d969be0178d1423c4ea04210230fde9c031f487db95ff55b7c0acbe0c7c26a8d82615e9184416bd350101616706210225afb4e88eac8b47b67adeaf085f5eb5d37d936f56138f0848de3d104edf113208210208e4687a95c172b86b920c3bc5dbd5f023094ec2cb0abdb74f9b624f45740df90a2102d7dde8e10a5a22c9bd0d7ef5494d85683ac050253b917615d4f97af633f0a8e20c04000000fd0efd011d3b00010102080000000000989680040400000051062066687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925080400000000417e2650c201383711eed2a7cb8652c3e77ee6a395e81849c5c222217ed68b333c0ca9f1e900662ae68a7359efa7ef9d90613f2a62f7c3ff90f8c25e2cc974c9d3a0009d00202d704fbfe342a9ff6eaca14d80a24aaed0e680bbbdd36157b6f2798c61d906910120f9fe5e552aa0fc45020f0505efde432a4e373e5d393863973a6899f8c26d33d102080000000000989680044d4c00210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c2302090007000000000241000408000001000000000006020000080800000000009896800a0400000046fffffffffffefffffffffffe000000000000000000000000000000000000000000000000f1600ef6ea657b8d411d553516ae35cedfe86b0cd48d1f91b32772facbae757d0000000b0000000000000002fd01da002045cfd42d0989e55b953f516ac7fd152bd90ec4438a2fc636f97ddd32a0c8fe0d01fd01840200000000010174c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e00000000000f55f9800310270000000000002200208309b406e3b96e76cde414fbb8f5159f5b25b24075656c6382cec797854d53495e9b0000000000002200204c5f18e5e95b184f34d02ba6de8a2a4e36ae3d4ec87299ad81f3284dc7195c6350c300000000000016001425df8ec4a074f80579fed67d4707d5ec8ed7e8d304004730440220671c9badf26bd3a1ebd2d17020c6be20587d7822530daacc52c28839875eaec602204b575a21729ed27311f6d79fdf6fe8702b0a798f7d842e39ede1b56f249a613401473044022016a0da36f70cbf5d889586af88f238982889dc161462c56557125c7acfcb69e9022036ae10c6cc8cbc3b27d9e9ef6babb556086585bc819f252208bd175286699fdd014752210307a78def56cba9fc4db22a25928181de538ee59ba1a475ae113af7790acd0db32103c21e841cbc0b48197d060c71e116c185fa0ac281b7d0aa5924f535154437ca3b52ae50c9222002040000000b0320f1600ef6ea657b8d411d553516ae35cedfe86b0cd48d1f91b32772facbae757d0406030400020090fd02a1002045cfd42d0989e55b953f516ac7fd152bd90ec4438a2fc636f97ddd32a0c8fe0d01fd01840200000000010174c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e00000000000f55f9800310270000000000002200208309b406e3b96e76cde414fbb8f5159f5b25b24075656c6382cec797854d53495e9b0000000000002200204c5f18e5e95b184f34d02ba6de8a2a4e36ae3d4ec87299ad81f3284dc7195c6350c300000000000016001425df8ec4a074f80579fed67d4707d5ec8ed7e8d304004730440220671c9badf26bd3a1ebd2d17020c6be20587d7822530daacc52c28839875eaec602204b575a21729ed27311f6d79fdf6fe8702b0a798f7d842e39ede1b56f249a613401473044022016a0da36f70cbf5d889586af88f238982889dc161462c56557125c7acfcb69e9022036ae10c6cc8cbc3b27d9e9ef6babb556086585bc819f252208bd175286699fdd014752210307a78def56cba9fc4db22a25928181de538ee59ba1a475ae113af7790acd0db32103c21e841cbc0b48197d060c71e116c185fa0ac281b7d0aa5924f535154437ca3b52ae50c9222002040000000b0320f1600ef6ea657b8d411d553516ae35cedfe86b0cd48d1f91b32772facbae757d04cd01cb00c901c7002245cfd42d0989e55b953f516ac7fd152bd90ec4438a2fc636f97ddd32a0c8fe0d0001022102d7dde8e10a5a22c9bd0d7ef5494d85683ac050253b917615d4f97af633f0a8e204020090062b5e9b0000000000002200204c5f18e5e95b184f34d02ba6de8a2a4e36ae3d4ec87299ad81f3284dc7195c630821035f5e9d58b4328566223c107d86cf853e6b9fae1d26ff6d969be0178d1423c4ea0a200000000000000000000000004d49e5da0000000000000000000000000000002a0c0800000000000186a0000000000000000274c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e0000000000000001000000000022002034c0cc0ad0dd5fe61dcf7ef58f995e3d34f8dbd24aa2a6fae68fefe102bf025c45cfd42d0989e55b953f516ac7fd152bd90ec4438a2fc636f97ddd32a0c8fe0d000000000000000100000000002200208309b406e3b96e76cde414fbb8f5159f5b25b24075656c6382cec797854d5349010100160014d5a9aa98b89acc215fc3d23d6fec0ad59ca3665ffd027100fd01e6fd01e300080000fffffffffffe02080000000000009b5e0408000000000000c3500604000000fd08b0af002102d7dde8e10a5a22c9bd0d7ef5494d85683ac050253b917615d4f97af633f0a8e20221035f5e9d58b4328566223c107d86cf853e6b9fae1d26ff6d969be0178d1423c4ea04210230fde9c031f487db95ff55b7c0acbe0c7c26a8d82615e9184416bd350101616706210225afb4e88eac8b47b67adeaf085f5eb5d37d936f56138f0848de3d104edf113208210208e4687a95c172b86b920c3bc5dbd5f023094ec2cb0abdb74f9b624f45740df90acdcc00a8020000000174c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e00000000000f55f9800310270000000000002200208309b406e3b96e76cde414fbb8f5159f5b25b24075656c6382cec797854d53495e9b0000000000002200204c5f18e5e95b184f34d02ba6de8a2a4e36ae3d4ec87299ad81f3284dc7195c6350c300000000000016001425df8ec4a074f80579fed67d4707d5ec8ed7e8d350c92220022045cfd42d0989e55b953f516ac7fd152bd90ec4438a2fc636f97ddd32a0c8fe0d0c3c3b00010102080000000000989680040400000051062066687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f29250804000000000240671c9badf26bd3a1ebd2d17020c6be20587d7822530daacc52c28839875eaec64b575a21729ed27311f6d79fdf6fe8702b0a798f7d842e39ede1b56f249a613404010006407e2650c201383711eed2a7cb8652c3e77ee6a395e81849c5c222217ed68b333c0ca9f1e900662ae68a7359efa7ef9d90613f2a62f7c3ff90f8c25e2cc974c9d3010000000000000001010000000000000000090b2a953d93a124c600ecb1a0ccfed420169cdd37f538ad94a3e4e6318c93c14adf59cdfbb40bdd40950c9f8dd547d29d75a173e1376a7850743394c46dea2dfd01cefd01ca00fd017ffd017c00080000ffffffffffff0208000000000000c2990408000000000000c3500604000000fd08b0af002102295e2de39eb3dcc2882f8cc266df7882a8b6d2c32aa08799f49b693aad3be28e022103a1f98e85886df54add6908b4fc1ff515e44aedefe9eb9c02879c89994298fa79042103a650bf03971df0176c7b412247390ef717853e8bd487b204dccc2fe2078bb75206210390bbbcebe9f70ba5dfd98866a79f72f75e0a6ea550ef73b202dd87cd6477350a08210284152d57908488e666e872716a286eb670b3d06cbeebf3f2e4ad350e01ec5e5b0aa2a1007d020000000174c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e00000000000f55f9800299c2000000000000220020740e108cfbc93967b6ab242a351ebee7de51814cf78d366adefd78b10281f17e50c300000000000016001425df8ec4a074f80579fed67d4707d5ec8ed7e8d351c92220022004f8eda5676356f539169a8e9a1e86c7f125283328d6f4bded1b939b52a6a7e30c00024045cb2485594bb1ec08e7bb6af4f89c912bd53f006d7876ea956773e04a4aad4a40e2b8d4fc612102f0b54061b3c1239fb78783053e8e6f9d92b1b99f81ae9ec2040100060000fd019600b0af002103c21e841cbc0b48197d060c71e116c185fa0ac281b7d0aa5924f535154437ca3b02210270b20ad0f2c2bb30a55590fc77778495bc1b38c96476901145dda57491237f0f042103b4e59df102747edc3a3e2283b42b88a8c8218ffd0dcfb52f2524b371d64cadaa062103d902b7b8b3434076d2b210e912c76645048b71e28995aad227a465a65ccd817608210301e9a52f923c157941de4a7692e601f758660969dcf5abdb67817efe84cce2ef0202009004010106b7b600b0af00210307a78def56cba9fc4db22a25928181de538ee59ba1a475ae113af7790acd0db30221034d0f817cb19b4a3bd144b615459bd06cbab3b4bdc96d73e18549a992cee80e8104210380542b59a9679890cba529fe155a9508ef57dac7416d035b23666e3fb98c3814062103adde8029d3ee281a32e9db929b39f503ff9d7e93cd308eb157955344dc6def84082103205087e2dc1f6b9937e887dfa712c5bdfa950b01dbda3ebac4c85efdde48ee6a02020090082274c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e000000000287010108d30df34e3a1e00ecdd03a2c843db062479a81752c4dfd0cc4baef0f81e7bc7ef8820990daf8d8e8d30a3b4b08af12c9f5cd71e45c7238103e0c80ca13850862e4fd2c56b69b7195312518de1bfe9aed63c80bb7760d70b2a870d542d815895fd12423d11e2adb0cdf55d776dac8f487c9b3b7ea12f1b150eb15889cf41333ade465692bf1cdc360b9c2a19bf8c1ca4fed7639d8bc953d36c10d8c6c9a8c0a57608788979bcf145e61b308006896e21d03e92084f93bd78740c20639134a7a8fd019afd019600b0af002103c21e841cbc0b48197d060c71e116c185fa0ac281b7d0aa5924f535154437ca3b02210270b20ad0f2c2bb30a55590fc77778495bc1b38c96476901145dda57491237f0f042103b4e59df102747edc3a3e2283b42b88a8c8218ffd0dcfb52f2524b371d64cadaa062103d902b7b8b3434076d2b210e912c76645048b71e28995aad227a465a65ccd817608210301e9a52f923c157941de4a7692e601f758660969dcf5abdb67817efe84cce2ef0202009004010106b7b600b0af00210307a78def56cba9fc4db22a25928181de538ee59ba1a475ae113af7790acd0db30221034d0f817cb19b4a3bd144b615459bd06cbab3b4bdc96d73e18549a992cee80e8104210380542b59a9679890cba529fe155a9508ef57dac7416d035b23666e3fb98c3814062103adde8029d3ee281a32e9db929b39f503ff9d7e93cd308eb157955344dc6def84082103205087e2dc1f6b9937e887dfa712c5bdfa950b01dbda3ebac4c85efdde48ee6a02020090082274c52ab4f11296d62b66a6dba9513b04a3e7fb5a09a30cee22fce7294ab55b7e000000000000000186a00000000000000000000000004d49e5da0000000000000000000000000000002a00000000000000000000000000000000000000000000000001000000510000000000000001000000000000000145cfd42d0989e55b953f516ac7fd152bd90ec4438a2fc636f97ddd32a0c8fe0d00000000041000080000000000989680020400000051160004000000510208000000000000000004040000000b0000000000000000000101300300050007010109210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c230d000f020000", ).unwrap(); - reload_node!(nodes[0], &nodes[0].node.encode(), &[&serialized_monitor], persister, new_chain_monitor, node_deserialized); + reload_node!( + nodes[0], + &nodes[0].node.encode(), + &[&serialized_monitor], + persister, + new_chain_monitor, + node_deserialized + ); } // Connecting more blocks should result in the HTLC transactions being rebroadcast. @@ -2404,9 +3586,8 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let (_, _, _, chan_id, funding_tx) = create_chan_between_nodes_with_value( - &nodes[0], &nodes[1], 1_000_000, 500_000_000 - ); + let (_, _, _, chan_id, funding_tx) = + create_chan_between_nodes_with_value(&nodes[0], &nodes[1], 1_000_000, 500_000_000); const HTLC_AMT_MSAT: u64 = 1_000_000; const HTLC_AMT_SAT: u64 = HTLC_AMT_MSAT / 1000; route_payment(&nodes[0], &[&nodes[1]], HTLC_AMT_MSAT); @@ -2414,24 +3595,41 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { let htlc_expiry = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 1; let commitment_txn = get_local_commitment_txn!(&nodes[0], chan_id); - assert_eq!(commitment_txn.len(), if anchors { 1 /* commitment tx only */} else { 2 /* commitment and htlc timeout tx */ }); + assert_eq!( + commitment_txn.len(), + if anchors { + 1 /* commitment tx only */ + } else { + 2 /* commitment and htlc timeout tx */ + } + ); check_spends!(&commitment_txn[0], &funding_tx); mine_transaction(&nodes[0], &commitment_txn[0]); check_closed_broadcast!(&nodes[0], true); - check_closed_event!(&nodes[0], 1, ClosureReason::CommitmentTxConfirmed, - false, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + [nodes[1].node.get_our_node_id()], + 1000000 + ); check_added_monitors(&nodes[0], 1); let coinbase_tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: vec![TxIn { ..Default::default() }], - output: vec![TxOut { // UTXO to attach fees to `htlc_tx` on anchors + output: vec![TxOut { + // UTXO to attach fees to `htlc_tx` on anchors value: Amount::ONE_BTC, script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), }], }; - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); // Set up a helper closure we'll use throughout our test. We should only expect retries without // bumps if fees have not increased after a block has been connected (assuming the height timer @@ -2452,11 +3650,11 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { assert_eq!(txn.len(), 1); let htlc_tx = txn.pop().unwrap(); check_spends!(&htlc_tx, &commitment_txn[0], &coinbase_tx); - let htlc_tx_fee = HTLC_AMT_SAT + coinbase_tx.output[0].value.to_sat() - - htlc_tx.output.iter().map(|output| output.value.to_sat()).sum::(); + let htlc_tx_fee = HTLC_AMT_SAT + coinbase_tx.output[0].value.to_sat() + - htlc_tx.output.iter().map(|output| output.value.to_sat()).sum::(); let htlc_tx_weight = htlc_tx.weight().to_wu(); (htlc_tx, compute_feerate_sat_per_1000_weight(htlc_tx_fee, htlc_tx_weight)) - } + }, _ => panic!("Unexpected event"), } } else { @@ -2533,12 +3731,12 @@ fn do_test_yield_anchors_events(have_htlcs: bool) { anchors_config.channel_handshake_config.announce_for_forwarding = true; anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; anchors_config.manually_accept_inbound_channels = true; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value( - &nodes, 0, 1, 1_000_000, 500_000_000 - ); + let (_, _, chan_id, funding_tx) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000); let mut payment_preimage_1 = None; let mut payment_hash_1 = None; let mut payment_preimage_2 = None; @@ -2558,9 +3756,19 @@ fn do_test_yield_anchors_events(have_htlcs: bool) { // Note that if we use the wrong target, we will immediately broadcast the commitment // transaction as no bump is required. if have_htlcs { - nodes[0].fee_estimator.target_override.lock().unwrap().insert(ConfirmationTarget::UrgentOnChainSweep, 500); + nodes[0] + .fee_estimator + .target_override + .lock() + .unwrap() + .insert(ConfirmationTarget::UrgentOnChainSweep, 500); } else { - nodes[0].fee_estimator.target_override.lock().unwrap().insert(ConfirmationTarget::OutputSpendingFee, 500); + nodes[0] + .fee_estimator + .target_override + .lock() + .unwrap() + .insert(ConfirmationTarget::OutputSpendingFee, 500); } connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); @@ -2568,7 +3776,14 @@ fn do_test_yield_anchors_events(have_htlcs: bool) { connect_blocks(&nodes[1], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); if !have_htlcs { - nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), "".to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[0].node.get_our_node_id(), + "".to_string(), + ) + .unwrap(); } { let txn = nodes[1].tx_broadcaster.txn_broadcast(); @@ -2578,15 +3793,28 @@ fn do_test_yield_anchors_events(have_htlcs: bool) { if have_htlcs { get_monitor!(nodes[0], chan_id).provide_payment_preimage_unsafe_legacy( - &payment_hash_2.unwrap(), &payment_preimage_2.unwrap(), &node_cfgs[0].tx_broadcaster, - &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger + &payment_hash_2.unwrap(), + &payment_preimage_2.unwrap(), + &node_cfgs[0].tx_broadcaster, + &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), + &nodes[0].logger, ); get_monitor!(nodes[1], chan_id).provide_payment_preimage_unsafe_legacy( - &payment_hash_1.unwrap(), &payment_preimage_1.unwrap(), &node_cfgs[1].tx_broadcaster, - &LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger + &payment_hash_1.unwrap(), + &payment_preimage_1.unwrap(), + &node_cfgs[1].tx_broadcaster, + &LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), + &nodes[1].logger, ); } else { - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), "".to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + "".to_string(), + ) + .unwrap(); } check_closed_broadcast(&nodes[0], 1, true); @@ -2615,12 +3843,16 @@ fn do_test_yield_anchors_events(have_htlcs: bool) { version: Version::TWO, lock_time: LockTime::ZERO, input: vec![TxIn { ..Default::default() }], - output: vec![TxOut { // UTXO to attach fees to `anchor_tx` + output: vec![TxOut { + // UTXO to attach fees to `anchor_tx` value: Amount::ONE_BTC, script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), }], }; - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); nodes[0].bump_tx_handler.handle_event(&event); let mut txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); assert_eq!(txn.len(), 2); @@ -2653,7 +3885,10 @@ fn do_test_yield_anchors_events(have_htlcs: bool) { let mut txn = nodes[1].tx_broadcaster.unique_txn_broadcast(); // Both HTLC claims are pinnable at this point, // and will be broadcast in a single transaction. - assert_eq!(txn.len(), if nodes[1].connect_style.borrow().updates_best_block_first() { 2 } else { 1 }); + assert_eq!( + txn.len(), + if nodes[1].connect_style.borrow().updates_best_block_first() { 2 } else { 1 } + ); if nodes[1].connect_style.borrow().updates_best_block_first() { let new_commitment_tx = txn.remove(0); check_spends!(new_commitment_tx, funding_tx); @@ -2670,8 +3905,12 @@ fn do_test_yield_anchors_events(have_htlcs: bool) { // best block is updated before the confirmed transactions are notified. if nodes[0].connect_style.borrow().updates_best_block_first() { assert_eq!(holder_events.len(), 3); - if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = holder_events.remove(0) {} - else { panic!("unexpected event"); } + if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = + holder_events.remove(0) + { + } else { + panic!("unexpected event"); + } } else { assert_eq!(holder_events.len(), 2); } @@ -2731,13 +3970,19 @@ fn test_anchors_aggregated_revoked_htlc_tx() { anchors_config.channel_handshake_config.announce_for_forwarding = true; anchors_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; anchors_config.manually_accept_inbound_channels = true; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config.clone()), Some(anchors_config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 2, + &node_cfgs, + &[Some(anchors_config.clone()), Some(anchors_config.clone())], + ); let bob_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan_a = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 20_000_000); - let chan_b = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 20_000_000); + let chan_a = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 20_000_000); + let chan_b = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 20_000_000); // Serialize Bob with the initial state of both channels, which we'll use later. let bob_serialized = nodes[1].node.encode(); @@ -2767,15 +4012,23 @@ fn test_anchors_aggregated_revoked_htlc_tx() { // Restart Bob with the revoked state and provide the HTLC preimages he claimed. reload_node!( - nodes[1], anchors_config, bob_serialized, &[&bob_serialized_monitor_a, &bob_serialized_monitor_b], - bob_persister, bob_chain_monitor, bob_deserialized + nodes[1], + anchors_config, + bob_serialized, + &[&bob_serialized_monitor_a, &bob_serialized_monitor_b], + bob_persister, + bob_chain_monitor, + bob_deserialized ); for chan_id in [chan_a.2, chan_b.2].iter() { let monitor = get_monitor!(nodes[1], *chan_id); for payment in [payment_a, payment_b, payment_c, payment_d].iter() { monitor.provide_payment_preimage_unsafe_legacy( - &payment.1, &payment.0, &node_cfgs[1].tx_broadcaster, - &LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger + &payment.1, + &payment.0, + &node_cfgs[1].tx_broadcaster, + &LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), + &nodes[1].logger, ); } } @@ -2786,7 +4039,13 @@ fn test_anchors_aggregated_revoked_htlc_tx() { *nodes[1].fee_estimator.sat_per_kw.lock().unwrap() *= 2; nodes[1].node.timer_tick_occurred(); check_added_monitors(&nodes[1], 2); - check_closed_event!(&nodes[1], 2, ClosureReason::OutdatedChannelManager, [nodes[0].node.get_our_node_id(); 2], 1000000); + check_closed_event!( + &nodes[1], + 2, + ClosureReason::OutdatedChannelManager, + [nodes[0].node.get_our_node_id(); 2], + 1000000 + ); // Bob should now receive two events to bump his revoked commitment transaction fees. assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); @@ -2800,12 +4059,15 @@ fn test_anchors_aggregated_revoked_htlc_tx() { version: Version::TWO, lock_time: LockTime::ZERO, input: vec![TxIn { ..Default::default() }], - output: vec![TxOut { // UTXO to attach fees to `anchor_tx` + output: vec![TxOut { + // UTXO to attach fees to `anchor_tx` value: utxo_value, script_pubkey: nodes[1].wallet_source.get_change_script().unwrap(), }], }; - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, utxo_value); + nodes[1] + .wallet_source + .add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, utxo_value); match event { Event::BumpTransaction(event) => nodes[1].bump_tx_handler.handle_event(&event), _ => panic!("Unexpected event"), @@ -2823,14 +4085,28 @@ fn test_anchors_aggregated_revoked_htlc_tx() { revoked_commitment_txs.push(commitment_tx.clone()); anchor_txs.push(anchor_tx.clone()); - }; + } for node in &nodes { - mine_transactions(node, &[&revoked_commitment_txs[0], &anchor_txs[0], &revoked_commitment_txs[1], &anchor_txs[1]]); + mine_transactions( + node, + &[ + &revoked_commitment_txs[0], + &anchor_txs[0], + &revoked_commitment_txs[1], + &anchor_txs[1], + ], + ); } check_added_monitors!(&nodes[0], 2); check_closed_broadcast(&nodes[0], 2, true); - check_closed_event!(&nodes[0], 2, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id(); 2], 1000000); + check_closed_event!( + &nodes[0], + 2, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id(); 2], + 1000000 + ); // Alice should detect the confirmed revoked commitments, and attempt to claim all of the // revoked outputs in aggregated transactions per channel, grouped into pinnable and unpinnable @@ -2839,12 +4115,20 @@ fn test_anchors_aggregated_revoked_htlc_tx() { let txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(txn.len(), 4); - let revoked_claims_a: Vec<_> = txn.clone().into_iter().filter(|tx| { - tx.input[0].previous_output.txid == revoked_commitment_txs[0].compute_txid() - }).collect(); - let revoked_claims_b: Vec<_> = txn.clone().into_iter().filter(|tx| { - tx.input[0].previous_output.txid == revoked_commitment_txs[1].compute_txid() - }).collect(); + let revoked_claims_a: Vec<_> = txn + .clone() + .into_iter() + .filter(|tx| { + tx.input[0].previous_output.txid == revoked_commitment_txs[0].compute_txid() + }) + .collect(); + let revoked_claims_b: Vec<_> = txn + .clone() + .into_iter() + .filter(|tx| { + tx.input[0].previous_output.txid == revoked_commitment_txs[1].compute_txid() + }) + .collect(); assert_eq!(revoked_claims_a.len(), 2); assert_eq!(revoked_claims_a.iter().map(|tx| tx.input.len()).sum::(), 3); @@ -2867,13 +4151,22 @@ fn test_anchors_aggregated_revoked_htlc_tx() { // Certain block `ConnectStyle`s cause an extra `ChannelClose` event to be emitted since the // best block is updated before the confirmed transactions are notified. match *nodes[1].connect_style.borrow() { - ConnectStyle::BestBlockFirst|ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::BestBlockFirstSkippingBlocks => { + ConnectStyle::BestBlockFirst + | ConnectStyle::BestBlockFirstReorgsOnlyTip + | ConnectStyle::BestBlockFirstSkippingBlocks => { assert_eq!(events.len(), 4); - if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = events.remove(0) {} - else { panic!("unexpected event"); } - if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = events.remove(1) {} - else { panic!("unexpected event"); } - + if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = + events.remove(0) + { + } else { + panic!("unexpected event"); + } + if let Event::BumpTransaction(BumpTransactionEvent::ChannelClose { .. }) = + events.remove(1) + { + } else { + panic!("unexpected event"); + } }, _ => assert_eq!(events.len(), 2), }; @@ -2885,7 +4178,8 @@ fn test_anchors_aggregated_revoked_htlc_tx() { version: Version::TWO, lock_time: LockTime::ZERO, input: vec![TxIn { ..Default::default() }], - output: vec![TxOut { // UTXO to attach fees to `htlc_tx` + output: vec![TxOut { + // UTXO to attach fees to `htlc_tx` value: Amount::ONE_BTC, script_pubkey: fee_utxo_script.clone(), }], @@ -2893,12 +4187,14 @@ fn test_anchors_aggregated_revoked_htlc_tx() { let mut htlc_tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, - input: vec![TxIn { // Fee input + input: vec![TxIn { + // Fee input previous_output: bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, ..Default::default() }], - output: vec![TxOut { // Fee input change - value: coinbase_tx.output[0].value / 2 , + output: vec![TxOut { + // Fee input change + value: coinbase_tx.output[0].value / 2, script_pubkey: ScriptBuf::new_op_return(&[]), }], }; @@ -2906,7 +4202,12 @@ fn test_anchors_aggregated_revoked_htlc_tx() { for event in events { // We don't use the `BumpTransactionEventHandler` here because it does not support // creating one transaction from multiple `HTLCResolution` events. - if let Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { mut htlc_descriptors, tx_lock_time, .. }) = event { + if let Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { + mut htlc_descriptors, + tx_lock_time, + .. + }) = event + { assert_eq!(htlc_descriptors.len(), 2); for htlc_descriptor in &htlc_descriptors { assert!(!htlc_descriptor.htlc.offered); @@ -2921,16 +4222,28 @@ fn test_anchors_aggregated_revoked_htlc_tx() { } for (idx, htlc_descriptor) in descriptors.into_iter().enumerate() { let htlc_input_idx = idx + 1; - let signer = nodes[1].keys_manager.derive_channel_signer(htlc_descriptor.channel_derivation_parameters.keys_id); - let our_sig = signer.sign_holder_htlc_transaction(&htlc_tx, htlc_input_idx, &htlc_descriptor, &secp).unwrap(); + let signer = nodes[1] + .keys_manager + .derive_channel_signer(htlc_descriptor.channel_derivation_parameters.keys_id); + let our_sig = signer + .sign_holder_htlc_transaction(&htlc_tx, htlc_input_idx, &htlc_descriptor, &secp) + .unwrap(); let witness_script = htlc_descriptor.witness_script(&secp); - htlc_tx.input[htlc_input_idx].witness = htlc_descriptor.tx_input_witness(&our_sig, &witness_script); + htlc_tx.input[htlc_input_idx].witness = + htlc_descriptor.tx_input_witness(&our_sig, &witness_script); } let fee_utxo_sig = { let witness_script = ScriptBuf::new_p2pkh(&public_key.pubkey_hash()); - let sighash = hash_to_message!(&SighashCache::new(&htlc_tx).p2wsh_signature_hash( - 0, &witness_script, coinbase_tx.output[0].value, EcdsaSighashType::All - ).unwrap()[..]); + let sighash = hash_to_message!( + &SighashCache::new(&htlc_tx) + .p2wsh_signature_hash( + 0, + &witness_script, + coinbase_tx.output[0].value, + EcdsaSighashType::All + ) + .unwrap()[..] + ); let sig = sign(&secp, &sighash, &secret_key); let mut sig = sig.serialize_der().to_vec(); sig.push(EcdsaSighashType::All as u8); @@ -2952,11 +4265,14 @@ fn test_anchors_aggregated_revoked_htlc_tx() { // Each channel has 1 adjusted claim of the HTLC revocations. assert_eq!(txn.len(), 2); - let revoked_htlc_claims = txn.iter().filter(|tx| - tx.input.len() == 2 && - tx.output.len() == 1 && - tx.input[0].previous_output.txid == htlc_tx.compute_txid() - ).collect::>(); + let revoked_htlc_claims = txn + .iter() + .filter(|tx| { + tx.input.len() == 2 + && tx.output.len() == 1 + && tx.input[0].previous_output.txid == htlc_tx.compute_txid() + }) + .collect::>(); assert_eq!(revoked_htlc_claims.len(), 2); for revoked_htlc_claim in revoked_htlc_claims { check_spends!(revoked_htlc_claim, htlc_tx); @@ -2972,7 +4288,6 @@ fn test_anchors_aggregated_revoked_htlc_tx() { mine_transactions(node, &revoked_claim_transactions.values().collect::>()); } - // Connect one block to make sure the HTLC events are not yielded while ANTI_REORG_DELAY has not // been reached. connect_blocks(&nodes[0], 1); @@ -2986,7 +4301,8 @@ fn test_anchors_aggregated_revoked_htlc_tx() { connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); - let spendable_output_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events(); + let spendable_output_events = + nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events(); // The spendable outputs for each channel consist of: // - 1 aggregated claim of the HTLC revocations. // - 1 static to_remote output. @@ -2995,14 +4311,28 @@ fn test_anchors_aggregated_revoked_htlc_tx() { if let Event::SpendableOutputs { outputs, channel_id } = event { assert_eq!(outputs.len(), 1); assert!(vec![chan_b.2, chan_a.2].contains(&channel_id.unwrap())); - let spend_tx = nodes[0].keys_manager.backing.spend_spendable_outputs( - &[&outputs[0]], Vec::new(), ScriptBuf::new_op_return(&[]), 253, None, &Secp256k1::new(), - ).unwrap(); + let spend_tx = nodes[0] + .keys_manager + .backing + .spend_spendable_outputs( + &[&outputs[0]], + Vec::new(), + ScriptBuf::new_op_return(&[]), + 253, + None, + &Secp256k1::new(), + ) + .unwrap(); if let SpendableOutputDescriptor::StaticPaymentOutput(_) = &outputs[0] { check_spends!(spend_tx, &revoked_commitment_txs[0], &revoked_commitment_txs[1]); } else { - check_spends!(spend_tx, revoked_claim_transactions.get(&spend_tx.input[0].previous_output.txid).unwrap()); + check_spends!( + spend_tx, + revoked_claim_transactions + .get(&spend_tx.input[0].previous_output.txid) + .unwrap() + ); } } else { panic!("unexpected event"); @@ -3022,7 +4352,9 @@ fn test_anchors_aggregated_revoked_htlc_tx() { assert_eq!(nodes[1].chain_monitor.chain_monitor.get_claimable_balances(&[]).len(), 6); } -fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_commitment_before_reload: bool) { +fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload( + confirm_commitment_before_reload: bool, +) { // Tests that we'll fix a ChannelMonitor's `counterparty_payment_script` for an anchor outputs // channel upon deserialization. let chanmon_cfgs = create_chanmon_cfgs(2); @@ -3032,11 +4364,16 @@ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_c let mut user_config = test_default_channel_config(); user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 2, + &node_cfgs, + &[Some(user_config.clone()), Some(user_config.clone())], + ); let node_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 50_000_000); + let (_, _, chan_id, funding_tx) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 50_000_000); // Set the monitor's `counterparty_payment_script` to a dummy P2WPKH script. let secp = Secp256k1::new(); @@ -3049,11 +4386,24 @@ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_c // Confirm the counterparty's commitment and reload the monitor (either before or after) such // that we arrive at the correct `counterparty_payment_script` after the reload. let error_message = "Channel force-closed"; - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); check_closed_broadcast(&nodes[0], 1, true); - check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, - [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + [nodes[1].node.get_our_node_id()], + 100000 + ); let commitment_tx = { let mut txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); @@ -3068,20 +4418,44 @@ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_c // We should expect our round trip serialization check to fail as we're writing the monitor // with the incorrect P2WPKH script but reading it with the correct P2WSH script. *nodes[1].chain_monitor.expect_monitor_round_trip_fail.lock().unwrap() = Some(chan_id); - let commitment_tx_conf_height = block_from_scid(mine_transaction(&nodes[1], &commitment_tx)); + let commitment_tx_conf_height = + block_from_scid(mine_transaction(&nodes[1], &commitment_tx)); let serialized_monitor = get_monitor!(nodes[1], chan_id).encode(); - reload_node!(nodes[1], user_config, &nodes[1].node.encode(), &[&serialized_monitor], persister, chain_monitor, node_deserialized); + reload_node!( + nodes[1], + user_config, + &nodes[1].node.encode(), + &[&serialized_monitor], + persister, + chain_monitor, + node_deserialized + ); commitment_tx_conf_height } else { let serialized_monitor = get_monitor!(nodes[1], chan_id).encode(); - reload_node!(nodes[1], user_config, &nodes[1].node.encode(), &[&serialized_monitor], persister, chain_monitor, node_deserialized); - let commitment_tx_conf_height = block_from_scid(mine_transaction(&nodes[1], &commitment_tx)); + reload_node!( + nodes[1], + user_config, + &nodes[1].node.encode(), + &[&serialized_monitor], + persister, + chain_monitor, + node_deserialized + ); + let commitment_tx_conf_height = + block_from_scid(mine_transaction(&nodes[1], &commitment_tx)); check_added_monitors(&nodes[1], 1); check_closed_broadcast(&nodes[1], 1, true); commitment_tx_conf_height }; - check_closed_event!(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false, - [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + [nodes[0].node.get_our_node_id()], + 100000 + ); assert!(get_monitor!(nodes[1], chan_id).get_counterparty_payment_script().is_p2wsh()); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); @@ -3091,12 +4465,21 @@ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_c // If we saw the commitment before our `counterparty_payment_script` was fixed, we'll never // get the spendable output event for the `to_remote` output, so we'll need to get it // manually via `get_spendable_outputs`. - let outputs = get_monitor!(nodes[1], chan_id).get_spendable_outputs(&commitment_tx, commitment_tx_conf_height); + let outputs = get_monitor!(nodes[1], chan_id) + .get_spendable_outputs(&commitment_tx, commitment_tx_conf_height); assert_eq!(outputs.len(), 1); - let spend_tx = nodes[1].keys_manager.backing.spend_spendable_outputs( - &[&outputs[0]], Vec::new(), Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), - 253, None, &secp - ).unwrap(); + let spend_tx = nodes[1] + .keys_manager + .backing + .spend_spendable_outputs( + &[&outputs[0]], + Vec::new(), + Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), + 253, + None, + &secp, + ) + .unwrap(); check_spends!(spend_tx, &commitment_tx); } else { test_spendable_output(&nodes[1], &commitment_tx, false); @@ -3110,7 +4493,9 @@ fn test_anchors_monitor_fixes_counterparty_payment_script_on_reload() { } #[cfg(not(ldk_test_vectors))] -fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterparty_commitment: bool) { +fn do_test_monitor_claims_with_random_signatures( + anchors: bool, confirm_counterparty_commitment: bool, +) { // Tests that our monitor claims will always use fresh random signatures (ensuring a unique // wtxid) to prevent certain classes of transaction replacement at the bitcoin P2P layer. let chanmon_cfgs = create_chanmon_cfgs(2); @@ -3120,26 +4505,29 @@ fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterp user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; user_config.manually_accept_inbound_channels = true; } - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config.clone()), Some(user_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: vec![TxIn { ..Default::default() }], - output: vec![ - TxOut { - value: Amount::ONE_BTC, - script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), - }, - ], + output: vec![TxOut { + value: Amount::ONE_BTC, + script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), + }], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.compute_txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); } // Open a channel and route a payment. We'll let it timeout to claim it. - let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + let (_, _, chan_id, funding_tx) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); route_payment(&nodes[0], &[&nodes[1]], 1_000_000); let (closing_node, other_node) = if confirm_counterparty_commitment { @@ -3149,7 +4537,9 @@ fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterp }; get_monitor!(closing_node, chan_id).broadcast_latest_holder_commitment_txn( - &closing_node.tx_broadcaster, &closing_node.fee_estimator, &closing_node.logger + &closing_node.tx_broadcaster, + &closing_node.fee_estimator, + &closing_node.logger, ); // The commitment transaction comes first. @@ -3163,16 +4553,30 @@ fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterp mine_transaction(closing_node, &commitment_tx); check_added_monitors!(closing_node, 1); check_closed_broadcast!(closing_node, true); - check_closed_event!(closing_node, 1, ClosureReason::CommitmentTxConfirmed, [other_node.node.get_our_node_id()], 1_000_000); + check_closed_event!( + closing_node, + 1, + ClosureReason::CommitmentTxConfirmed, + [other_node.node.get_our_node_id()], + 1_000_000 + ); mine_transaction(other_node, &commitment_tx); check_added_monitors!(other_node, 1); check_closed_broadcast!(other_node, true); - check_closed_event!(other_node, 1, ClosureReason::CommitmentTxConfirmed, [closing_node.node.get_our_node_id()], 1_000_000); + check_closed_event!( + other_node, + 1, + ClosureReason::CommitmentTxConfirmed, + [closing_node.node.get_our_node_id()], + 1_000_000 + ); // If we update the best block to the new height before providing the confirmed transactions, // we'll see another broadcast of the commitment transaction. - if !confirm_counterparty_commitment && nodes[0].connect_style.borrow().updates_best_block_first() { + if !confirm_counterparty_commitment + && nodes[0].connect_style.borrow().updates_best_block_first() + { let _ = nodes[0].tx_broadcaster.txn_broadcast(); } @@ -3235,9 +4639,11 @@ fn test_event_replay_causing_monitor_replay() { let payment_preimage = route_payment(&nodes[0], &[&nodes[1]], 1_000_000).0; - do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage) - ); + do_claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1]]], + payment_preimage, + )); // At this point the `PaymentSent` event has not been processed but the full commitment signed // dance has completed. @@ -3246,14 +4652,33 @@ fn test_event_replay_causing_monitor_replay() { // Now process the `PaymentSent` to get the final RAA `ChannelMonitorUpdate`, checking that it // resulted in a `ChannelManager` persistence request. nodes[0].node.get_and_clear_needs_persistence(); - expect_payment_sent(&nodes[0], payment_preimage, None, true, true /* expected post-event monitor update*/); + expect_payment_sent( + &nodes[0], + payment_preimage, + None, + true, + true, /* expected post-event monitor update*/ + ); assert!(nodes[0].node.get_and_clear_needs_persistence()); let serialized_monitor = get_monitor!(nodes[0], chan.2).encode(); - reload_node!(nodes[0], &serialized_channel_manager, &[&serialized_monitor], persister, new_chain_monitor, node_deserialized); + reload_node!( + nodes[0], + &serialized_channel_manager, + &[&serialized_monitor], + persister, + new_chain_monitor, + node_deserialized + ); // Expect the `PaymentSent` to get replayed, this time without the duplicate monitor update - expect_payment_sent(&nodes[0], payment_preimage, None, false, false /* expected post-event monitor update*/); + expect_payment_sent( + &nodes[0], + payment_preimage, + None, + false, + false, /* expected post-event monitor update*/ + ); } #[test] @@ -3268,10 +4693,19 @@ fn test_update_replay_panics() { let monitor = get_monitor!(nodes[1], chan.2).clone(); // Create some updates to apply - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); - let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); - nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id(), "".to_owned()).unwrap(); - let reason = ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }; + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan.2, + &nodes[0].node.get_our_node_id(), + "".to_owned(), + ) + .unwrap(); + let reason = ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }; check_closed_event(&nodes[1], 1, reason, false, &[nodes[0].node.get_our_node_id()], 100_000); check_closed_broadcast(&nodes[1], 1, true); check_added_monitors(&nodes[1], 1); @@ -3284,12 +4718,26 @@ fn test_update_replay_panics() { check_added_monitors(&nodes[1], 1); expect_payment_claimed!(nodes[1], payment_hash_2, 1_000_000); - let mut updates = nodes[1].chain_monitor.monitor_updates.lock().unwrap().get_mut(&chan.2).unwrap().split_off(0); + let mut updates = nodes[1] + .chain_monitor + .monitor_updates + .lock() + .unwrap() + .get_mut(&chan.2) + .unwrap() + .split_off(0); // Update `monitor` until there's just one normal updates, an FC update, and a post-FC claim // update pending for update in updates.drain(..updates.len() - 4) { - monitor.update_monitor(&update, &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger).unwrap(); + monitor + .update_monitor( + &update, + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ) + .unwrap(); } assert_eq!(updates.len(), 4); assert!(matches!(updates[1].updates[0], ChannelMonitorUpdateStep::ChannelForceClosed { .. })); @@ -3299,29 +4747,75 @@ fn test_update_replay_panics() { // Ensure applying the force-close update skipping the last normal update fails let poisoned_monitor = monitor.clone(); std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - let _ = poisoned_monitor.update_monitor(&updates[1], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger); + let _ = poisoned_monitor.update_monitor( + &updates[1], + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ); // We should panic, rather than returning an error here. - })).unwrap_err(); + })) + .unwrap_err(); // Then apply the last normal and force-close update and make sure applying the preimage // updates out-of-order fails. - monitor.update_monitor(&updates[0], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger).unwrap(); - monitor.update_monitor(&updates[1], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger).unwrap(); + monitor + .update_monitor( + &updates[0], + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ) + .unwrap(); + monitor + .update_monitor( + &updates[1], + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ) + .unwrap(); let poisoned_monitor = monitor.clone(); std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - let _ = poisoned_monitor.update_monitor(&updates[3], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger); + let _ = poisoned_monitor.update_monitor( + &updates[3], + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ); // We should panic, rather than returning an error here. - })).unwrap_err(); + })) + .unwrap_err(); // Make sure re-applying the force-close update fails let poisoned_monitor = monitor.clone(); std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - let _ = poisoned_monitor.update_monitor(&updates[1], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger); + let _ = poisoned_monitor.update_monitor( + &updates[1], + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ); // We should panic, rather than returning an error here. - })).unwrap_err(); + })) + .unwrap_err(); // ...and finally ensure that applying all the updates succeeds. - monitor.update_monitor(&updates[2], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger).unwrap(); - monitor.update_monitor(&updates[3], &nodes[1].tx_broadcaster, &nodes[1].fee_estimator, &nodes[1].logger).unwrap(); + monitor + .update_monitor( + &updates[2], + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ) + .unwrap(); + monitor + .update_monitor( + &updates[3], + &nodes[1].tx_broadcaster, + &nodes[1].fee_estimator, + &nodes[1].logger, + ) + .unwrap(); } diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index c27db4a55b4..8e570b520e8 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,23 +1100,25 @@ 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() - } - 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.", + )), } } } @@ -1123,13 +1126,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 +1147,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 +1216,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 +1469,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 +1778,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 +1827,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 +1862,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 +1942,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 +1956,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 +1982,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 +2020,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 +2118,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 +2149,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 +2235,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 +2258,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 +2302,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 +2338,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 +2346,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 +2381,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 +2407,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 +2431,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 +2812,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 +3080,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 +3092,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 +3105,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 +3133,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 +3176,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 +3189,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 +3204,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 +3232,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 +3277,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 +3287,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 +3303,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 +3312,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 +3335,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 +3385,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 +3451,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 +3473,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 +3488,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 +3507,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 +3548,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 +3593,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 +3603,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 +3625,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 +3640,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 +3659,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 +3675,7 @@ impl LengthReadable for Ping { let byteslen = Readable::read(r)?; r.read_exact(&mut vec![0u8; byteslen as usize][..])?; byteslen - } + }, }) } } @@ -3577,7 +3694,7 @@ impl LengthReadable for Pong { let byteslen = Readable::read(r)?; r.read_exact(&mut vec![0u8; byteslen as usize][..])?; byteslen - } + }, }) } } @@ -3717,7 +3834,7 @@ impl LengthReadable for ErrorMessage { Ok(s) => s, Err(_) => return Err(DecodeError::InvalidValue), } - } + }, }) } } @@ -3744,7 +3861,7 @@ impl LengthReadable for WarningMessage { Ok(s) => s, Err(_) => return Err(DecodeError::InvalidValue), } - } + }, }) } } @@ -3786,7 +3903,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 +3990,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 +4066,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 +4077,7 @@ impl LengthReadable for ReplyChannelRange { first_blocknum, number_of_blocks, sync_complete, - short_channel_ids + short_channel_ids, }) } } @@ -3992,55 +4108,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 +4186,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 +4203,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 +4296,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 +4332,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 +4352,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 +4373,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 +4392,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 +4433,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 +4472,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 +4515,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 +4532,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 +4555,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 +4578,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 +4620,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 +4655,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 +4678,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 +4728,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 +4752,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 +4773,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 +4822,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 +4858,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 +4897,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 +4917,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 +4933,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 +4976,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 +4994,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 +5004,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 +5064,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 +5091,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 +5111,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 +5128,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 +5146,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 +5182,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 +5233,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 +5250,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 +5264,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 +5305,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 +5349,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 +5379,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 +5417,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 +5480,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 +5495,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 +5512,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 +5568,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 +5581,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 +5590,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 +5648,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 +5674,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 +5689,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 +5726,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 +5756,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 +5764,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 +5774,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 +5783,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 +5797,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 +5833,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 +5855,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 +5868,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 +5903,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 +5939,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 +5949,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 +5979,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 +5999,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 +6039,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 +6099,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 +6120,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 +6139,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 +6153,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 +6170,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 +6187,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 +6197,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 +6229,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 +6250,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 +6276,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 +6292,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 +6311,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 +6324,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/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index 78cd40e9e34..d637d88060e 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -40,30 +40,39 @@ //! Nodes without channels are disconnected and connected as needed to ensure that deterministic //! blinded paths are used. -use bitcoin::network::Network; -use bitcoin::secp256k1::{PublicKey, Secp256k1}; -use core::time::Duration; -use crate::blinded_path::IntroductionNode; use crate::blinded_path::message::BlindedMessagePath; -use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext}; use crate::blinded_path::message::OffersContext; -use crate::events::{ClosureReason, Event, HTLCDestination, PaidBolt12Invoice, PaymentFailureReason, PaymentPurpose}; -use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry, self}; -use crate::types::features::Bolt12InvoiceFeatures; +use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext}; +use crate::blinded_path::IntroductionNode; +use crate::events::{ + ClosureReason, Event, HTLCDestination, PaidBolt12Invoice, PaymentFailureReason, PaymentPurpose, +}; +use crate::ln::channelmanager::{ + self, Bolt12PaymentError, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry, + MAX_SHORT_LIVED_RELATIVE_EXPIRY, +}; use crate::ln::functional_test_utils::*; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement}; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, + OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, + UnsignedNodeAnnouncement, +}; use crate::ln::outbound_payment::IDEMPOTENCY_TIMEOUT_TICKS; use crate::offers::invoice::Bolt12Invoice; use crate::offers::invoice_error::InvoiceError; use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields}; use crate::offers::nonce::Nonce; use crate::offers::parse::Bolt12SemanticError; -use crate::onion_message::messenger::{Destination, PeeledOnion, MessageSendInstructions}; +use crate::onion_message::messenger::{Destination, MessageSendInstructions, PeeledOnion}; use crate::onion_message::offers::OffersMessage; use crate::routing::gossip::{NodeAlias, NodeId}; use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig}; use crate::sign::{NodeSigner, Recipient}; +use crate::types::features::Bolt12InvoiceFeatures; use crate::util::ser::Writeable; +use bitcoin::network::Network; +use bitcoin::secp256k1::{PublicKey, Secp256k1}; +use core::time::Duration; use crate::prelude::*; @@ -76,7 +85,7 @@ macro_rules! expect_recent_payment { Some(_) => panic!("Unexpected recent payment state"), None => panic!("No recent payments"), } - } + }; } fn connect_peers<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>) { @@ -112,8 +121,8 @@ fn disconnect_peers<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, peers: &[&Node<'a, 'b fn announce_node_address<'a, 'b, 'c>( node: &Node<'a, 'b, 'c>, peers: &[&Node<'a, 'b, 'c>], address: SocketAddress, ) { - let features = node.onion_messenger.provided_node_features() - | node.gossip_sync.provided_node_features(); + let features = + node.onion_messenger.provided_node_features() | node.gossip_sync.provided_node_features(); let rgb = [0u8; 3]; let announcement = UnsignedNodeAnnouncement { features, @@ -125,14 +134,12 @@ fn announce_node_address<'a, 'b, 'c>( excess_address_data: Vec::new(), excess_data: Vec::new(), }; - let signature = node.keys_manager.sign_gossip_message( - UnsignedGossipMessage::NodeAnnouncement(&announcement) - ).unwrap(); + let signature = node + .keys_manager + .sign_gossip_message(UnsignedGossipMessage::NodeAnnouncement(&announcement)) + .unwrap(); - let msg = NodeAnnouncement { - signature, - contents: announcement - }; + let msg = NodeAnnouncement { signature, contents: announcement }; let node_pubkey = node.node.get_our_node_id(); node.gossip_sync.handle_node_announcement(None, &msg).unwrap(); @@ -141,14 +148,16 @@ fn announce_node_address<'a, 'b, 'c>( } } -fn resolve_introduction_node<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, path: &BlindedMessagePath) -> PublicKey { +fn resolve_introduction_node<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, path: &BlindedMessagePath, +) -> PublicKey { path.public_introduction_node_id(&node.network_graph.read_only()) .and_then(|node_id| node_id.as_pubkey().ok()) .unwrap() } fn route_bolt12_payment<'a, 'b, 'c>( - node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], invoice: &Bolt12Invoice + node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], invoice: &Bolt12Invoice, ) { // Monitor added when handling the invoice onion message. check_added_monitors(node, 1); @@ -167,7 +176,8 @@ fn route_bolt12_payment<'a, 'b, 'c>( } fn claim_bolt12_payment<'a, 'b, 'c>( - node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], expected_payment_context: PaymentContext, invoice: &Bolt12Invoice + node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], expected_payment_context: PaymentContext, + invoice: &Bolt12Invoice, ) { let recipient = &path[path.len() - 1]; let payment_purpose = match get_event!(recipient, Event::PaymentClaimable) { @@ -197,7 +207,9 @@ fn claim_bolt12_payment<'a, 'b, 'c>( fn extract_offer_nonce<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> Nonce { match node.onion_messenger.peel_onion_message(message) { Ok(PeeledOnion::Offers(_, Some(OffersContext::InvoiceRequest { nonce }), _)) => nonce, - Ok(PeeledOnion::Offers(_, context, _)) => panic!("Unexpected onion message context: {:?}", context), + Ok(PeeledOnion::Offers(_, context, _)) => { + panic!("Unexpected onion message context: {:?}", context) + }, Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"), Ok(_) => panic!("Unexpected onion message"), Err(e) => panic!("Failed to process onion message {:?}", e), @@ -205,11 +217,13 @@ fn extract_offer_nonce<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessa } pub(super) fn extract_invoice_request<'a, 'b, 'c>( - node: &Node<'a, 'b, 'c>, message: &OnionMessage + node: &Node<'a, 'b, 'c>, message: &OnionMessage, ) -> (InvoiceRequest, BlindedMessagePath) { match node.onion_messenger.peel_onion_message(message) { Ok(PeeledOnion::Offers(message, _, reply_path)) => match message { - OffersMessage::InvoiceRequest(invoice_request) => (invoice_request, reply_path.unwrap()), + OffersMessage::InvoiceRequest(invoice_request) => { + (invoice_request, reply_path.unwrap()) + }, OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice), #[cfg(async_payments)] OffersMessage::StaticInvoice(invoice) => panic!("Unexpected static invoice: {:?}", invoice), @@ -221,10 +235,14 @@ pub(super) fn extract_invoice_request<'a, 'b, 'c>( } } -fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> (Bolt12Invoice, BlindedMessagePath) { +fn extract_invoice<'a, 'b, 'c>( + node: &Node<'a, 'b, 'c>, message: &OnionMessage, +) -> (Bolt12Invoice, BlindedMessagePath) { match node.onion_messenger.peel_onion_message(message) { Ok(PeeledOnion::Offers(message, _, reply_path)) => match message { - OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request), + OffersMessage::InvoiceRequest(invoice_request) => { + panic!("Unexpected invoice_request: {:?}", invoice_request) + }, OffersMessage::Invoice(invoice) => (invoice, reply_path.unwrap()), #[cfg(async_payments)] OffersMessage::StaticInvoice(invoice) => panic!("Unexpected static invoice: {:?}", invoice), @@ -237,11 +255,13 @@ fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) } fn extract_invoice_error<'a, 'b, 'c>( - node: &Node<'a, 'b, 'c>, message: &OnionMessage + node: &Node<'a, 'b, 'c>, message: &OnionMessage, ) -> InvoiceError { match node.onion_messenger.peel_onion_message(message) { Ok(PeeledOnion::Offers(message, _, _)) => match message { - OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request), + OffersMessage::InvoiceRequest(invoice_request) => { + panic!("Unexpected invoice_request: {:?}", invoice_request) + }, OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice), #[cfg(async_payments)] OffersMessage::StaticInvoice(invoice) => panic!("Unexpected invoice: {:?}", invoice), @@ -269,7 +289,9 @@ fn prefers_non_tor_nodes_in_blinded_paths() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -294,10 +316,8 @@ fn prefers_non_tor_nodes_in_blinded_paths() { let tor = SocketAddress::OnionV2([255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 38, 7]); announce_node_address(charlie, &[alice, bob, david, &nodes[4], &nodes[5]], tor.clone()); - let offer = bob.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + bob.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -310,10 +330,8 @@ fn prefers_non_tor_nodes_in_blinded_paths() { announce_node_address(&nodes[4], &[alice, bob, charlie, david, &nodes[5]], tor.clone()); announce_node_address(&nodes[5], &[alice, bob, charlie, david, &nodes[4]], tor.clone()); - let offer = bob.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + bob.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -338,7 +356,9 @@ fn prefers_more_connected_nodes_in_blinded_paths() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -361,10 +381,8 @@ fn prefers_more_connected_nodes_in_blinded_paths() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]); - let offer = bob.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + bob.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -388,9 +406,7 @@ fn creates_short_lived_offer() { let bob = &nodes[1]; let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY; - let offer = alice.node - .create_offer_builder(Some(absolute_expiry)).unwrap() - .build().unwrap(); + let offer = alice.node.create_offer_builder(Some(absolute_expiry)).unwrap().build().unwrap(); assert_eq!(offer.absolute_expiry(), Some(absolute_expiry)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -413,21 +429,17 @@ fn creates_long_lived_offer() { let alice = &nodes[0]; let alice_id = alice.node.get_our_node_id(); - let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY + let absolute_expiry = alice.node.duration_since_epoch() + + MAX_SHORT_LIVED_RELATIVE_EXPIRY + Duration::from_secs(1); - let offer = alice.node - .create_offer_builder(Some(absolute_expiry)) - .unwrap() - .build().unwrap(); + let offer = alice.node.create_offer_builder(Some(absolute_expiry)).unwrap().build().unwrap(); assert_eq!(offer.absolute_expiry(), Some(absolute_expiry)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); } - let offer = alice.node - .create_offer_builder(None).unwrap() - .build().unwrap(); + let offer = alice.node.create_offer_builder(None).unwrap().build().unwrap(); assert_eq!(offer.absolute_expiry(), None); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -451,10 +463,18 @@ fn creates_short_lived_refund() { let absolute_expiry = bob.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY; let payment_id = PaymentId([1; 32]); - let refund = bob.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = bob + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_eq!(refund.absolute_expiry(), Some(absolute_expiry)); assert!(!refund.paths().is_empty()); for path in refund.paths() { @@ -477,13 +497,21 @@ fn creates_long_lived_refund() { let bob = &nodes[1]; let bob_id = bob.node.get_our_node_id(); - let absolute_expiry = bob.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY - + Duration::from_secs(1); + let absolute_expiry = + bob.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY + Duration::from_secs(1); let payment_id = PaymentId([1; 32]); - let refund = bob.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = bob + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_eq!(refund.absolute_expiry(), Some(absolute_expiry)); assert!(!refund.paths().is_empty()); for path in refund.paths() { @@ -508,7 +536,9 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -529,11 +559,8 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None) - .unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -541,7 +568,17 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { } let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -585,12 +622,10 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { // Both Bob and Charlie have an equal number of channels and need to be connected // to Alice when she's handling the message. Therefore, either Bob or Charlie could // serve as the introduction node for the reply path back to Alice. - assert!( - matches!( - reply_path.introduction_node(), - &IntroductionNode::NodeId(node_id) if node_id == bob_id || node_id == charlie_id, - ) - ); + assert!(matches!( + reply_path.introduction_node(), + &IntroductionNode::NodeId(node_id) if node_id == bob_id || node_id == charlie_id, + )); route_bolt12_payment(david, &[charlie, bob, alice], &invoice); expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id); @@ -616,7 +651,9 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -639,10 +676,18 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = david.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = david + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_eq!(refund.amount_msats(), 10_000_000); assert_eq!(refund.absolute_expiry(), Some(absolute_expiry)); assert_ne!(refund.payer_signing_pubkey(), david_id); @@ -674,7 +719,6 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() { } assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(bob_id)); - route_bolt12_payment(david, &[charlie, bob, alice], &invoice); expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id); @@ -699,10 +743,8 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { let bob = &nodes[1]; let bob_id = bob.node.get_our_node_id(); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -710,7 +752,17 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { } let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) + .unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -768,10 +820,18 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = bob.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = bob + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_eq!(refund.amount_msats(), 10_000_000); assert_eq!(refund.absolute_expiry(), Some(absolute_expiry)); assert_ne!(refund.payer_signing_pubkey(), bob_id); @@ -822,16 +882,29 @@ fn pays_for_offer_without_blinded_paths() { let bob = &nodes[1]; let bob_id = bob.node.get_our_node_id(); - let offer = alice.node - .create_offer_builder(None).unwrap() + let offer = alice + .node + .create_offer_builder(None) + .unwrap() .clear_paths() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); assert_eq!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(offer.paths().is_empty()); let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) + .unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -877,11 +950,19 @@ fn pays_for_refund_without_blinded_paths() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = bob.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = bob + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() .clear_paths() - .build().unwrap(); + .build() + .unwrap(); assert_eq!(refund.payer_signing_pubkey(), bob_id); assert!(refund.paths().is_empty()); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -919,7 +1000,9 @@ fn send_invoice_requests_with_distinct_reply_path() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 7, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None, None] + 7, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None, None], ); let nodes = create_network(7, &node_cfgs, &node_chanmgrs); @@ -946,11 +1029,8 @@ fn send_invoice_requests_with_distinct_reply_path() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5], &nodes[6]]); disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None) - .unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -958,7 +1038,17 @@ fn send_invoice_requests_with_distinct_reply_path() { } let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); connect_peers(david, bob); @@ -983,7 +1073,10 @@ fn send_invoice_requests_with_distinct_reply_path() { alice.onion_messenger.handle_onion_message(bob_id, &onion_message); let (_, reply_path) = extract_invoice_request(alice, &onion_message); - assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(nodes[6].node.get_our_node_id())); + assert_eq!( + reply_path.introduction_node(), + &IntroductionNode::NodeId(nodes[6].node.get_our_node_id()) + ); } /// This test checks that when multiple potential introduction nodes are available for the payee, @@ -1003,7 +1096,9 @@ fn send_invoice_for_refund_with_distinct_reply_path() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 7, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None, None] + 7, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None, None], ); let nodes = create_network(7, &node_cfgs, &node_chanmgrs); @@ -1032,10 +1127,18 @@ fn send_invoice_for_refund_with_distinct_reply_path() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = alice.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = alice + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_ne!(refund.payer_signing_pubkey(), alice_id); for path in refund.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); @@ -1063,7 +1166,10 @@ fn send_invoice_for_refund_with_distinct_reply_path() { let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); let (_, reply_path) = extract_invoice(alice, &onion_message); - assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(nodes[6].node.get_our_node_id())); + assert_eq!( + reply_path.introduction_node(), + &IntroductionNode::NodeId(nodes[6].node.get_our_node_id()) + ); } /// Verifies that the invoice request message can be retried if it fails to reach the @@ -1082,17 +1188,25 @@ fn creates_and_pays_for_offer_with_retry() { let bob = &nodes[1]; let bob_id = bob.node.get_our_node_id(); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); } let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) + .unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let _lost_onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -1158,13 +1272,21 @@ fn pays_bolt12_invoice_asynchronously() { let bob = &nodes[1]; let bob_id = bob.node.get_our_node_id(); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) + .unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -1243,10 +1365,8 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { let bob = &nodes[1]; let bob_id = bob.node.get_our_node_id(); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -1254,7 +1374,17 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { } let payment_id = PaymentId([1; 32]); - bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + bob.node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) + .unwrap(); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); @@ -1311,10 +1441,18 @@ fn creates_refund_with_blinded_path_using_unannounced_introduction_node() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = bob.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = bob + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_ne!(refund.payer_signing_pubkey(), bob_id); assert!(!refund.paths().is_empty()); for path in refund.paths() { @@ -1352,7 +1490,9 @@ fn fails_authentication_when_handling_invoice_request() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -1373,11 +1513,8 @@ fn fails_authentication_when_handling_invoice_request() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None) - .unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_eq!(offer.metadata(), None); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); @@ -1385,24 +1522,39 @@ fn fails_authentication_when_handling_invoice_request() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); } - let invalid_path = alice.node + let invalid_path = alice + .node .create_offer_builder(None) .unwrap() - .build().unwrap() - .paths().first().unwrap() + .build() + .unwrap() + .paths() + .first() + .unwrap() .clone(); assert_eq!(invalid_path.introduction_node(), &IntroductionNode::NodeId(bob_id)); // Send the invoice request directly to Alice instead of using a blinded path. let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); connect_peers(david, alice); match &mut david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 { - MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => - *destination = Destination::Node(alice_id), + MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => { + *destination = Destination::Node(alice_id) + }, _ => panic!(), } @@ -1421,13 +1573,24 @@ fn fails_authentication_when_handling_invoice_request() { // Send the invoice request to Alice using an invalid blinded path. let payment_id = PaymentId([2; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); match &mut david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 { - MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => - *destination = Destination::BlindedPath(invalid_path), + MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => { + *destination = Destination::BlindedPath(invalid_path) + }, _ => panic!(), } @@ -1464,7 +1627,9 @@ fn fails_authentication_when_handling_invoice_for_offer() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -1485,11 +1650,8 @@ fn fails_authentication_when_handling_invoice_for_offer() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None) - .unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -1498,7 +1660,17 @@ fn fails_authentication_when_handling_invoice_for_offer() { // Initiate an invoice request, but abandon tracking it. let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); david.node.abandon_payment(payment_id); get_event!(david, Event::PaymentFailed); @@ -1515,7 +1687,17 @@ fn fails_authentication_when_handling_invoice_for_offer() { }; let payment_id = PaymentId([2; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -1525,8 +1707,9 @@ fn fails_authentication_when_handling_invoice_for_offer() { let mut pending_offers_messages = david.node.pending_offers_messages.lock().unwrap(); let mut pending_invoice_request = pending_offers_messages.first_mut().unwrap(); match &mut pending_invoice_request.1 { - MessageSendInstructions::WithSpecifiedReplyPath { reply_path, .. } => - *reply_path = invalid_reply_path, + MessageSendInstructions::WithSpecifiedReplyPath { reply_path, .. } => { + *reply_path = invalid_reply_path + }, _ => panic!(), } } @@ -1572,7 +1755,9 @@ fn fails_authentication_when_handling_invoice_for_refund() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -1594,10 +1779,18 @@ fn fails_authentication_when_handling_invoice_for_refund() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = david.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = david + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_ne!(refund.payer_signing_pubkey(), david_id); assert!(!refund.paths().is_empty()); for path in refund.paths() { @@ -1610,8 +1803,9 @@ fn fails_authentication_when_handling_invoice_for_refund() { connect_peers(david, alice); match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 { - MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => - *destination = Destination::Node(david_id), + MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => { + *destination = Destination::Node(david_id) + }, _ => panic!(), } @@ -1628,10 +1822,18 @@ fn fails_authentication_when_handling_invoice_for_refund() { // Send the invoice to David using an invalid blinded path. let invalid_path = refund.paths().first().unwrap().clone(); let payment_id = PaymentId([2; 32]); - let refund = david.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = david + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); assert_ne!(refund.payer_signing_pubkey(), david_id); assert!(!refund.paths().is_empty()); for path in refund.paths() { @@ -1641,8 +1843,9 @@ fn fails_authentication_when_handling_invoice_for_refund() { let expected_invoice = alice.node.request_refund_payment(&refund).unwrap(); match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 { - MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => - *destination = Destination::BlindedPath(invalid_path), + MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } => { + *destination = Destination::BlindedPath(invalid_path) + }, _ => panic!(), } @@ -1692,14 +1895,25 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() { args.send_channel_ready = (true, true); reconnect_nodes(args); - let offer = alice.node - .create_offer_builder(Some(absolute_expiry)).unwrap() + let offer = alice + .node + .create_offer_builder(Some(absolute_expiry)) + .unwrap() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); let payment_id = PaymentId([1; 32]); - match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match david.node.pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths), } @@ -1710,11 +1924,18 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() { args.send_channel_ready = (true, true); reconnect_nodes(args); - assert!( - david.node.pay_for_offer( - &offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default() - ).is_ok() - ); + assert!(david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default() + ) + .is_ok()); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); } @@ -1736,7 +1957,9 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -1756,7 +1979,11 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() { let absolute_expiry = david.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY; let payment_id = PaymentId([1; 32]); match david.node.create_refund_builder( - 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default() + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths), @@ -1766,10 +1993,18 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() { args.send_channel_ready = (true, true); reconnect_nodes(args); - let refund = david.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = david + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); match alice.node.request_refund_payment(&refund) { Ok(_) => panic!("Expected error"), @@ -1796,14 +2031,25 @@ fn fails_creating_invoice_request_for_unsupported_chain() { let alice = &nodes[0]; let bob = &nodes[1]; - let offer = alice.node - .create_offer_builder(None).unwrap() + let offer = alice + .node + .create_offer_builder(None) + .unwrap() .clear_chains() .chain(Network::Signet) - .build().unwrap(); + .build() + .unwrap(); let payment_id = PaymentId([1; 32]); - match bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match bob.node.pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain), } @@ -1824,11 +2070,19 @@ fn fails_sending_invoice_with_unsupported_chain_for_refund() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = bob.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = bob + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() .chain(Network::Signet) - .build().unwrap(); + .build() + .unwrap(); match alice.node.request_refund_payment(&refund) { Ok(_) => panic!("Expected error"), @@ -1855,14 +2109,20 @@ fn fails_creating_invoice_request_without_blinded_reply_path() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); disconnect_peers(david, &[bob, charlie, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); let payment_id = PaymentId([1; 32]); - match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match david.node.pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths), } @@ -1889,20 +2149,33 @@ fn fails_creating_invoice_request_with_duplicate_payment_id() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); let payment_id = PaymentId([1; 32]); - assert!( - david.node.pay_for_offer( - &offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default() - ).is_ok() - ); + assert!(david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default() + ) + .is_ok()); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); - match david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) { + match david.node.pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId), } @@ -1921,15 +2194,24 @@ fn fails_creating_refund_with_duplicate_payment_id() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - assert!( - nodes[0].node.create_refund_builder( - 10_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default() - ).is_ok() - ); + assert!(nodes[0] + .node + .create_refund_builder( + 10_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default() + ) + .is_ok()); expect_recent_payment!(nodes[0], RecentPaymentDetails::AwaitingInvoice, payment_id); match nodes[0].node.create_refund_builder( - 10_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default() + 10_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId), @@ -1954,7 +2236,9 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -1975,13 +2259,21 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); connect_peers(david, bob); @@ -2029,7 +2321,9 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_refund() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -2048,10 +2342,18 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_refund() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = david.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = david + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); match alice.node.request_refund_payment(&refund) { Ok(_) => panic!("Expected error"), @@ -2074,7 +2376,9 @@ fn fails_paying_invoice_more_than_once() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -2097,10 +2401,18 @@ fn fails_paying_invoice_more_than_once() { let absolute_expiry = Duration::from_secs(u64::MAX); let payment_id = PaymentId([1; 32]); - let refund = david.node - .create_refund_builder(10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + let refund = david + .node + .create_refund_builder( + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); // Alice sends the first invoice @@ -2163,7 +2475,9 @@ fn fails_paying_invoice_with_unknown_required_features() { *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 6, + &node_cfgs, + &[None, Some(accept_forward_cfg), None, None, None, None], ); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); @@ -2184,13 +2498,21 @@ fn fails_paying_invoice_with_unknown_required_features() { disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]); disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]); - let offer = alice.node - .create_offer_builder(None).unwrap() - .amount_msats(10_000_000) - .build().unwrap(); + let offer = + alice.node.create_offer_builder(None).unwrap().amount_msats(10_000_000).build().unwrap(); let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()) + david + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) .unwrap(); connect_peers(david, bob); @@ -2221,10 +2543,13 @@ fn fails_paying_invoice_with_unknown_required_features() { let created_at = alice.node.duration_since_epoch(); let invoice = invoice_request - .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).unwrap() - .respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at).unwrap() + .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx) + .unwrap() + .respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at) + .unwrap() .features_unchecked(Bolt12InvoiceFeatures::unknown()) - .build_and_sign(&secp_ctx).unwrap(); + .build_and_sign(&secp_ctx) + .unwrap(); // Enqueue an onion message containing the new invoice. let instructions = MessageSendInstructions::WithoutReplyPath { @@ -2267,10 +2592,27 @@ fn rejects_keysend_to_non_static_invoice_path() { let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap(); let amt_msat = 5000; let payment_id = PaymentId([1; 32]); - nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), RouteParametersConfig::default()).unwrap(); - let invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .pay_for_offer( + &offer, + None, + Some(amt_msat), + None, + payment_id, + Retry::Attempts(1), + RouteParametersConfig::default(), + ) + .unwrap(); + let invreq_om = nodes[0] + .onion_messenger + .next_onion_message_for_peer(nodes[1].node.get_our_node_id()) + .unwrap(); nodes[1].onion_messenger.handle_onion_message(nodes[0].node.get_our_node_id(), &invreq_om); - let invoice_om = nodes[1].onion_messenger.next_onion_message_for_peer(nodes[0].node.get_our_node_id()).unwrap(); + let invoice_om = nodes[1] + .onion_messenger + .next_onion_message_for_peer(nodes[0].node.get_our_node_id()) + .unwrap(); let invoice = extract_invoice(&nodes[0], &invoice_om).0; nodes[0].onion_messenger.handle_onion_message(nodes[1].node.get_our_node_id(), &invoice_om); @@ -2279,7 +2621,7 @@ fn rejects_keysend_to_non_static_invoice_path() { let payment_preimage = match get_event!(nodes[1], Event::PaymentClaimable) { Event::PaymentClaimable { purpose, .. } => purpose.preimage().unwrap(), - _ => panic!() + _ => panic!(), }; claim_payment(&nodes[0], &[&nodes[1]], payment_preimage); @@ -2296,10 +2638,16 @@ fn rejects_keysend_to_non_static_invoice_path() { let pay_params = PaymentParameters::from_bolt12_invoice(&invoice); let route_params = RouteParameters::from_payment_params_and_value(pay_params, amt_msat); let keysend_payment_id = PaymentId([2; 32]); - let payment_hash = nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), keysend_payment_id, - route_params, Retry::Attempts(0) - ).unwrap(); + let payment_hash = nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + keysend_payment_id, + route_params, + 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); @@ -2311,7 +2659,9 @@ fn rejects_keysend_to_non_static_invoice_path() { .expect_failure(HTLCDestination::FailedPayment { payment_hash }); do_pass_along_path(args); let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false); expect_payment_failed_conditions(&nodes[0], payment_hash, true, PaymentFailedConditions::new()); } @@ -2336,23 +2686,39 @@ fn no_double_pay_with_stale_channelmanager() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let alice_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan_id_0 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000).2; - let chan_id_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000).2; + let chan_id_0 = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000).2; + let chan_id_1 = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000).2; let alice_id = nodes[0].node.get_our_node_id(); let bob_id = nodes[1].node.get_our_node_id(); let amt_msat = nodes[0].node.list_usable_channels()[0].next_outbound_htlc_limit_msat + 1; // Force MPP - let offer = nodes[1].node - .create_offer_builder(None).unwrap() + let offer = nodes[1] + .node + .create_offer_builder(None) + .unwrap() .clear_paths() .amount_msats(amt_msat) - .build().unwrap(); + .build() + .unwrap(); assert_eq!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(offer.paths().is_empty()); let payment_id = PaymentId([1; 32]); - nodes[0].node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap(); + nodes[0] + .node + .pay_for_offer( + &offer, + None, + None, + None, + payment_id, + Retry::Attempts(0), + RouteParametersConfig::default(), + ) + .unwrap(); expect_recent_payment!(nodes[0], RecentPaymentDetails::AwaitingInvoice, payment_id); let invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); @@ -2390,9 +2756,22 @@ fn no_double_pay_with_stale_channelmanager() { // duplicate payment attempt. let monitor_0 = get_monitor!(nodes[0], chan_id_0).encode(); let monitor_1 = get_monitor!(nodes[0], chan_id_1).encode(); - reload_node!(nodes[0], &alice_chan_manager_serialized, &[&monitor_0, &monitor_1], persister, chain_monitor, alice_deserialized); + reload_node!( + nodes[0], + &alice_chan_manager_serialized, + &[&monitor_0, &monitor_1], + persister, + chain_monitor, + alice_deserialized + ); // The stale manager results in closing the channels. - check_closed_event!(nodes[0], 2, ClosureReason::OutdatedChannelManager, [bob_id, bob_id], 10_000_000); + check_closed_event!( + nodes[0], + 2, + ClosureReason::OutdatedChannelManager, + [bob_id, bob_id], + 10_000_000 + ); check_added_monitors!(nodes[0], 2); // Alice receives a duplicate invoice, but the payment should be transitioned to Retryable by now. diff --git a/lightning/src/ln/onion_payment.rs b/lightning/src/ln/onion_payment.rs index 09d453d0020..50eb6d2dc76 100644 --- a/lightning/src/ln/onion_payment.rs +++ b/lightning/src/ln/onion_payment.rs @@ -3,21 +3,24 @@ //! Primarily features [`peel_payment_onion`], which allows the decoding of an onion statelessly //! and can be used to predict whether we'd accept a payment. -use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; +use bitcoin::hashes::Hash; use bitcoin::secp256k1::ecdh::SharedSecret; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; use crate::blinded_path; use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay}; use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS}; -use crate::types::payment::PaymentHash; -use crate::ln::channelmanager::{BlindedFailure, BlindedForward, CLTV_FAR_FAR_AWAY, HTLCFailureMsg, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting}; -use crate::types::features::BlindedHopFeatures; +use crate::ln::channelmanager::{ + BlindedFailure, BlindedForward, HTLCFailureMsg, PendingHTLCInfo, PendingHTLCRouting, + CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::msgs; use crate::ln::onion_utils; -use crate::ln::onion_utils::{HTLCFailReason, ONION_DATA_LEN, LocalHTLCFailureReason}; +use crate::ln::onion_utils::{HTLCFailReason, LocalHTLCFailureReason, ONION_DATA_LEN}; use crate::sign::{NodeSigner, Recipient}; +use crate::types::features::BlindedHopFeatures; +use crate::types::payment::PaymentHash; use crate::util::logger::Logger; #[allow(unused_imports)] @@ -37,7 +40,7 @@ pub struct InboundHTLCErr { } /// Writes payment data for invalid or unknown payment error code. -pub (super) fn invalid_payment_err_data(amt_msat: u64, current_height: u32) -> Vec{ +pub(super) fn invalid_payment_err_data(amt_msat: u64, current_height: u32) -> Vec { let mut err_data = Vec::with_capacity(12); err_data.extend_from_slice(&amt_msat.to_be_bytes()); err_data.extend_from_slice(¤t_height.to_be_bytes()); @@ -45,27 +48,27 @@ pub (super) fn invalid_payment_err_data(amt_msat: u64, current_height: u32) -> V } fn check_blinded_payment_constraints( - amt_msat: u64, cltv_expiry: u32, constraints: &PaymentConstraints + amt_msat: u64, cltv_expiry: u32, constraints: &PaymentConstraints, ) -> Result<(), ()> { - if amt_msat < constraints.htlc_minimum_msat || - cltv_expiry > constraints.max_cltv_expiry - { return Err(()) } + if amt_msat < constraints.htlc_minimum_msat || cltv_expiry > constraints.max_cltv_expiry { + return Err(()); + } Ok(()) } fn check_blinded_forward( inbound_amt_msat: u64, inbound_cltv_expiry: u32, payment_relay: &PaymentRelay, - payment_constraints: &PaymentConstraints, features: &BlindedHopFeatures + payment_constraints: &PaymentConstraints, features: &BlindedHopFeatures, ) -> Result<(u64, u32), ()> { - let amt_to_forward = blinded_path::payment::amt_to_forward_msat( - inbound_amt_msat, payment_relay - ).ok_or(())?; - let outgoing_cltv_value = inbound_cltv_expiry.checked_sub( - payment_relay.cltv_expiry_delta as u32 - ).ok_or(())?; + let amt_to_forward = + blinded_path::payment::amt_to_forward_msat(inbound_amt_msat, payment_relay).ok_or(())?; + let outgoing_cltv_value = + inbound_cltv_expiry.checked_sub(payment_relay.cltv_expiry_delta as u32).ok_or(())?; check_blinded_payment_constraints(inbound_amt_msat, outgoing_cltv_value, payment_constraints)?; - if features.requires_unknown_bits_from(&BlindedHopFeatures::empty()) { return Err(()) } + if features.requires_unknown_bits_from(&BlindedHopFeatures::empty()) { + return Err(()); + } Ok((amt_to_forward, outgoing_cltv_value)) } @@ -73,7 +76,7 @@ enum RoutingInfo { Direct { short_channel_id: u64, new_packet_bytes: [u8; ONION_DATA_LEN], - next_hop_hmac: [u8; 32] + next_hop_hmac: [u8; 32], }, Trampoline { next_trampoline: PublicKey, @@ -81,31 +84,62 @@ enum RoutingInfo { new_packet_bytes: Vec, next_hop_hmac: [u8; 32], shared_secret: SharedSecret, - current_path_key: Option - } + current_path_key: Option, + }, } pub(super) fn create_fwd_pending_htlc_info( msg: &msgs::UpdateAddHTLC, hop_data: onion_utils::Hop, shared_secret: [u8; 32], - next_packet_pubkey_opt: Option> + next_packet_pubkey_opt: Option>, ) -> Result { debug_assert!(next_packet_pubkey_opt.is_some()); let ( - routing_info, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point, - next_blinding_override + routing_info, + amt_to_forward, + outgoing_cltv_value, + intro_node_blinding_point, + next_blinding_override, ) = match hop_data { - onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload { - short_channel_id, amt_to_forward, outgoing_cltv_value - }, new_packet_bytes, next_hop_hmac, .. } => - (RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, None, None), - onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload { - short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features, - next_blinding_override, - }, new_packet_bytes, next_hop_hmac, .. } => { + onion_utils::Hop::Forward { + next_hop_data: + msgs::InboundOnionForwardPayload { + short_channel_id, + amt_to_forward, + outgoing_cltv_value, + }, + new_packet_bytes, + next_hop_hmac, + .. + } => ( + RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, + amt_to_forward, + outgoing_cltv_value, + None, + None, + ), + onion_utils::Hop::BlindedForward { + next_hop_data: + msgs::InboundOnionBlindedForwardPayload { + short_channel_id, + payment_relay, + payment_constraints, + intro_node_blinding_point, + features, + next_blinding_override, + }, + new_packet_bytes, + next_hop_hmac, + .. + } => { let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward( - msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features - ).map_err(|()| { + msg.amount_msat, + msg.cltv_expiry, + &payment_relay, + &payment_constraints, + &features, + ) + .map_err(|()| { // We should be returning malformed here if `msg.blinding_point` is set, but this is // unreachable right now since we checked it in `decode_update_add_htlc_onion`. InboundHTLCErr { @@ -114,40 +148,64 @@ pub(super) fn create_fwd_pending_htlc_info( err_data: vec![0; 32], } })?; - (RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point, - next_blinding_override) + ( + RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, + amt_to_forward, + outgoing_cltv_value, + intro_node_blinding_point, + next_blinding_override, + ) }, - onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } => + onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } => { return Err(InboundHTLCErr { msg: "Final Node OnionHopData provided for us as an intermediary node", reason: LocalHTLCFailureReason::InvalidOnionPayload, err_data: Vec::new(), - }), - onion_utils::Hop::TrampolineReceive { .. } | onion_utils::Hop::TrampolineBlindedReceive { .. } => + }) + }, + onion_utils::Hop::TrampolineReceive { .. } + | onion_utils::Hop::TrampolineBlindedReceive { .. } => { return Err(InboundHTLCErr { msg: "Final Node OnionHopData provided for us as an intermediary node", reason: LocalHTLCFailureReason::InvalidOnionPayload, err_data: Vec::new(), - }), - onion_utils::Hop::TrampolineForward { next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => { - ( - RoutingInfo::Trampoline { - next_trampoline: next_trampoline_hop_data.next_trampoline, - new_packet_bytes: new_trampoline_packet_bytes, - next_hop_hmac: next_trampoline_hop_hmac, - shared_secret: trampoline_shared_secret, - current_path_key: None - }, - next_trampoline_hop_data.amt_to_forward, - next_trampoline_hop_data.outgoing_cltv_value, - None, - None - ) + }) }, - onion_utils::Hop::TrampolineBlindedForward { outer_hop_data, next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => { + onion_utils::Hop::TrampolineForward { + next_trampoline_hop_data, + next_trampoline_hop_hmac, + new_trampoline_packet_bytes, + trampoline_shared_secret, + .. + } => ( + RoutingInfo::Trampoline { + next_trampoline: next_trampoline_hop_data.next_trampoline, + new_packet_bytes: new_trampoline_packet_bytes, + next_hop_hmac: next_trampoline_hop_hmac, + shared_secret: trampoline_shared_secret, + current_path_key: None, + }, + next_trampoline_hop_data.amt_to_forward, + next_trampoline_hop_data.outgoing_cltv_value, + None, + None, + ), + onion_utils::Hop::TrampolineBlindedForward { + outer_hop_data, + next_trampoline_hop_data, + next_trampoline_hop_hmac, + new_trampoline_packet_bytes, + trampoline_shared_secret, + .. + } => { let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward( - msg.amount_msat, msg.cltv_expiry, &next_trampoline_hop_data.payment_relay, &next_trampoline_hop_data.payment_constraints, &next_trampoline_hop_data.features - ).map_err(|()| { + msg.amount_msat, + msg.cltv_expiry, + &next_trampoline_hop_data.payment_relay, + &next_trampoline_hop_data.payment_constraints, + &next_trampoline_hop_data.features, + ) + .map_err(|()| { // We should be returning malformed here if `msg.blinding_point` is set, but this is // unreachable right now since we checked it in `decode_update_add_htlc_onion`. InboundHTLCErr { @@ -162,12 +220,12 @@ pub(super) fn create_fwd_pending_htlc_info( new_packet_bytes: new_trampoline_packet_bytes, next_hop_hmac: next_trampoline_hop_hmac, shared_secret: trampoline_shared_secret, - current_path_key: outer_hop_data.current_path_key + current_path_key: outer_hop_data.current_path_key, }, amt_to_forward, outgoing_cltv_value, next_trampoline_hop_data.intro_node_blinding_point, - next_trampoline_hop_data.next_blinding_override + next_trampoline_hop_data.next_blinding_override, ) }, }; @@ -176,7 +234,8 @@ pub(super) fn create_fwd_pending_htlc_info( RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac } => { let outgoing_packet = msgs::OnionPacket { version: 0, - public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)), + public_key: next_packet_pubkey_opt + .unwrap_or(Err(secp256k1::Error::InvalidPublicKey)), hop_data: new_packet_bytes, hmac: next_hop_hmac, }; @@ -184,17 +243,24 @@ pub(super) fn create_fwd_pending_htlc_info( onion_packet: outgoing_packet, short_channel_id, incoming_cltv_expiry: Some(msg.cltv_expiry), - blinded: intro_node_blinding_point.or(msg.blinding_point) - .map(|bp| BlindedForward { + blinded: intro_node_blinding_point.or(msg.blinding_point).map(|bp| { + BlindedForward { inbound_blinding_point: bp, next_blinding_override, failure: intro_node_blinding_point .map(|_| BlindedFailure::FromIntroductionNode) .unwrap_or(BlindedFailure::FromBlindedNode), - }), + } + }), } - } - RoutingInfo::Trampoline { next_trampoline, new_packet_bytes, next_hop_hmac, shared_secret, current_path_key } => { + }, + RoutingInfo::Trampoline { + next_trampoline, + new_packet_bytes, + next_hop_hmac, + shared_secret, + current_path_key, + } => { let next_trampoline_packet_pubkey = match next_packet_pubkey_opt { Some(Ok(pubkey)) => pubkey, _ => return Err(InboundHTLCErr { @@ -214,16 +280,15 @@ pub(super) fn create_fwd_pending_htlc_info( onion_packet: outgoing_packet, node_id: next_trampoline, incoming_cltv_expiry: msg.cltv_expiry, - blinded: intro_node_blinding_point.or(current_path_key) - .map(|bp| BlindedForward { - inbound_blinding_point: bp, - next_blinding_override, - failure: intro_node_blinding_point - .map(|_| BlindedFailure::FromIntroductionNode) - .unwrap_or(BlindedFailure::FromBlindedNode), - }) + blinded: intro_node_blinding_point.or(current_path_key).map(|bp| BlindedForward { + inbound_blinding_point: bp, + next_blinding_override, + failure: intro_node_blinding_point + .map(|_| BlindedFailure::FromIntroductionNode) + .unwrap_or(BlindedFailure::FromBlindedNode), + }), } - } + }, }; Ok(PendingHTLCInfo { @@ -238,70 +303,151 @@ pub(super) fn create_fwd_pending_htlc_info( } pub(super) fn create_recv_pending_htlc_info( - hop_data: onion_utils::Hop, shared_secret: [u8; 32], payment_hash: PaymentHash, - amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool, - counterparty_skimmed_fee_msat: Option, current_height: u32 + hop_data: onion_utils::Hop, shared_secret: [u8; 32], payment_hash: PaymentHash, amt_msat: u64, + cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool, + counterparty_skimmed_fee_msat: Option, current_height: u32, ) -> Result { let ( - payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, onion_cltv_expiry, - payment_metadata, payment_context, requires_blinded_error, has_recipient_created_payment_secret, - invoice_request + payment_data, + keysend_preimage, + custom_tlvs, + onion_amt_msat, + onion_cltv_expiry, + payment_metadata, + payment_context, + requires_blinded_error, + has_recipient_created_payment_secret, + invoice_request, ) = match hop_data { - onion_utils::Hop::Receive { hop_data: msgs::InboundOnionReceivePayload { - payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat, - cltv_expiry_height, payment_metadata, .. - }, .. } => - (payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat, - cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None), - onion_utils::Hop::BlindedReceive { hop_data: msgs::InboundOnionBlindedReceivePayload { - sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret, - intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage, - custom_tlvs, invoice_request - }, .. } => { + onion_utils::Hop::Receive { + hop_data: + msgs::InboundOnionReceivePayload { + payment_data, + keysend_preimage, + custom_tlvs, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + payment_metadata, + .. + }, + .. + } => ( + payment_data, + keysend_preimage, + custom_tlvs, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + payment_metadata, + None, + false, + keysend_preimage.is_none(), + None, + ), + onion_utils::Hop::BlindedReceive { + hop_data: + msgs::InboundOnionBlindedReceivePayload { + sender_intended_htlc_amt_msat, + total_msat, + cltv_expiry_height, + payment_secret, + intro_node_blinding_point, + payment_constraints, + payment_context, + keysend_preimage, + custom_tlvs, + invoice_request, + }, + .. + } => { check_blinded_payment_constraints( - sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints + sender_intended_htlc_amt_msat, + cltv_expiry, + &payment_constraints, ) - .map_err(|()| { - InboundHTLCErr { - reason: LocalHTLCFailureReason::InvalidOnionBlinding, - err_data: vec![0; 32], - msg: "Amount or cltv_expiry violated blinded payment constraints", - } - })?; + .map_err(|()| InboundHTLCErr { + reason: LocalHTLCFailureReason::InvalidOnionBlinding, + err_data: vec![0; 32], + msg: "Amount or cltv_expiry violated blinded payment constraints", + })?; let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat }; - (Some(payment_data), keysend_preimage, custom_tlvs, - sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context), - intro_node_blinding_point.is_none(), true, invoice_request) - } + ( + Some(payment_data), + keysend_preimage, + custom_tlvs, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + None, + Some(payment_context), + intro_node_blinding_point.is_none(), + true, + invoice_request, + ) + }, onion_utils::Hop::TrampolineReceive { - trampoline_hop_data: msgs::InboundOnionReceivePayload { - payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat, - cltv_expiry_height, payment_metadata, .. - }, .. - } => - (payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat, - cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None), + trampoline_hop_data: + msgs::InboundOnionReceivePayload { + payment_data, + keysend_preimage, + custom_tlvs, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + payment_metadata, + .. + }, + .. + } => ( + payment_data, + keysend_preimage, + custom_tlvs, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + payment_metadata, + None, + false, + keysend_preimage.is_none(), + None, + ), onion_utils::Hop::TrampolineBlindedReceive { - trampoline_hop_data: msgs::InboundOnionBlindedReceivePayload { - sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret, - intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage, - custom_tlvs, invoice_request - }, .. + trampoline_hop_data: + msgs::InboundOnionBlindedReceivePayload { + sender_intended_htlc_amt_msat, + total_msat, + cltv_expiry_height, + payment_secret, + intro_node_blinding_point, + payment_constraints, + payment_context, + keysend_preimage, + custom_tlvs, + invoice_request, + }, + .. } => { check_blinded_payment_constraints( - sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints, + sender_intended_htlc_amt_msat, + cltv_expiry, + &payment_constraints, ) - .map_err(|()| { - InboundHTLCErr { + .map_err(|()| { + InboundHTLCErr { reason: LocalHTLCFailureReason::InvalidOnionBlinding, err_data: vec![0; 32], msg: "Amount or cltv_expiry violated blinded payment constraints within Trampoline onion", } - })?; + })?; let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat }; - (Some(payment_data), keysend_preimage, custom_tlvs, - sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context), - intro_node_blinding_point.is_none(), true, invoice_request) + ( + Some(payment_data), + keysend_preimage, + custom_tlvs, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + None, + Some(payment_context), + intro_node_blinding_point.is_none(), + true, + invoice_request, + ) }, onion_utils::Hop::Forward { .. } => { return Err(InboundHTLCErr { @@ -317,7 +463,8 @@ pub(super) fn create_recv_pending_htlc_info( msg: "Got blinded non final data with an HMAC of 0", }) }, - onion_utils::Hop::TrampolineForward { .. } | onion_utils::Hop::TrampolineBlindedForward { .. } => { + onion_utils::Hop::TrampolineForward { .. } + | onion_utils::Hop::TrampolineBlindedForward { .. } => { return Err(InboundHTLCErr { reason: LocalHTLCFailureReason::InvalidOnionPayload, err_data: Vec::new(), @@ -330,8 +477,8 @@ pub(super) fn create_recv_pending_htlc_info( return Err(InboundHTLCErr { msg: "Upstream node set CLTV to less than the CLTV set by the sender", reason: LocalHTLCFailureReason::FinalIncorrectCLTVExpiry, - err_data: cltv_expiry.to_be_bytes().to_vec() - }) + err_data: cltv_expiry.to_be_bytes().to_vec(), + }); } // final_expiry_too_soon // We have to have some headroom to broadcast on chain if we have the preimage, so make sure @@ -347,9 +494,9 @@ pub(super) fn create_recv_pending_htlc_info( msg: "The final CLTV expiry is too soon to handle", }); } - if (!allow_underpay && onion_amt_msat > amt_msat) || - (allow_underpay && onion_amt_msat > - amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0))) + if (!allow_underpay && onion_amt_msat > amt_msat) + || (allow_underpay + && onion_amt_msat > amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0))) { return Err(InboundHTLCErr { reason: LocalHTLCFailureReason::FinalIncorrectHTLCAmount, @@ -429,51 +576,67 @@ where L::Target: Logger, { let (hop, next_packet_details_opt) = - decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx - ).map_err(|(msg, failure_reason)| { - let (reason, err_data) = match msg { - HTLCFailureMsg::Malformed(_) => (failure_reason, Vec::new()), - HTLCFailureMsg::Relay(r) => (LocalHTLCFailureReason::InvalidOnionPayload, r.reason), - }; - let msg = "Failed to decode update add htlc onion"; - InboundHTLCErr { msg, reason, err_data } - })?; + decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx).map_err( + |(msg, failure_reason)| { + let (reason, err_data) = match msg { + HTLCFailureMsg::Malformed(_) => (failure_reason, Vec::new()), + HTLCFailureMsg::Relay(r) => { + (LocalHTLCFailureReason::InvalidOnionPayload, r.reason) + }, + }; + let msg = "Failed to decode update add htlc onion"; + InboundHTLCErr { msg, reason, err_data } + }, + )?; Ok(match hop { - onion_utils::Hop::Forward { shared_secret, .. } | - onion_utils::Hop::BlindedForward { shared_secret, .. } => { + onion_utils::Hop::Forward { shared_secret, .. } + | onion_utils::Hop::BlindedForward { shared_secret, .. } => { let NextPacketDetails { - next_packet_pubkey, outgoing_amt_msat: _, outgoing_connector: _, outgoing_cltv_value + next_packet_pubkey, + outgoing_amt_msat: _, + outgoing_connector: _, + outgoing_cltv_value, } = match next_packet_details_opt { Some(next_packet_details) => next_packet_details, // Forward should always include the next hop details - None => return Err(InboundHTLCErr { - msg: "Failed to decode update add htlc onion", - reason: LocalHTLCFailureReason::InvalidOnionPayload, - err_data: Vec::new(), - }), + None => { + return Err(InboundHTLCErr { + msg: "Failed to decode update add htlc onion", + reason: LocalHTLCFailureReason::InvalidOnionPayload, + err_data: Vec::new(), + }) + }, }; - if let Err((err_msg, reason)) = check_incoming_htlc_cltv( - cur_height, outgoing_cltv_value, msg.cltv_expiry, - ) { - return Err(InboundHTLCErr { - msg: err_msg, - reason, - err_data: Vec::new(), - }); + if let Err((err_msg, reason)) = + check_incoming_htlc_cltv(cur_height, outgoing_cltv_value, msg.cltv_expiry) + { + return Err(InboundHTLCErr { msg: err_msg, reason, err_data: Vec::new() }); } // TODO: If this is potentially a phantom payment we should decode the phantom payment // onion here and check it. - create_fwd_pending_htlc_info(msg, hop, shared_secret.secret_bytes(), Some(next_packet_pubkey))? + create_fwd_pending_htlc_info( + msg, + hop, + shared_secret.secret_bytes(), + Some(next_packet_pubkey), + )? }, _ => { let shared_secret = hop.shared_secret().secret_bytes(); create_recv_pending_htlc_info( - hop, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry, - None, allow_skimmed_fees, msg.skimmed_fee_msat, cur_height, + hop, + shared_secret, + msg.payment_hash, + msg.amount_msat, + msg.cltv_expiry, + None, + allow_skimmed_fees, + msg.skimmed_fee_msat, + cur_height, )? - } + }, }) } @@ -492,7 +655,11 @@ pub(super) struct NextPacketDetails { pub(super) outgoing_cltv_value: u32, } -pub(super) fn decode_incoming_update_add_htlc_onion( +pub(super) fn decode_incoming_update_add_htlc_onion< + NS: Deref, + L: Deref, + T: secp256k1::Verification, +>( msg: &msgs::UpdateAddHTLC, node_signer: NS, logger: L, secp_ctx: &Secp256k1, ) -> Result<(onion_utils::Hop, Option), (HTLCFailureMsg, LocalHTLCFailureReason)> where @@ -501,21 +668,29 @@ where { let encode_malformed_error = |message: &str, failure_reason: LocalHTLCFailureReason| { log_info!(logger, "Failed to accept/forward incoming HTLC: {}", message); - let (sha256_of_onion, failure_reason) = if msg.blinding_point.is_some() || failure_reason == LocalHTLCFailureReason::InvalidOnionBlinding { + let (sha256_of_onion, failure_reason) = if msg.blinding_point.is_some() + || failure_reason == LocalHTLCFailureReason::InvalidOnionBlinding + { ([0; 32], LocalHTLCFailureReason::InvalidOnionBlinding) } else { (Sha256::hash(&msg.onion_routing_packet.hop_data).to_byte_array(), failure_reason) }; - return Err((HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - sha256_of_onion, - failure_code: failure_reason.failure_code(), - }), failure_reason)); + return Err(( + HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + sha256_of_onion, + failure_code: failure_reason.failure_code(), + }), + failure_reason, + )); }; if let Err(_) = msg.onion_routing_packet.public_key { - return encode_malformed_error("invalid ephemeral pubkey", LocalHTLCFailureReason::InvalidOnionKey); + return encode_malformed_error( + "invalid ephemeral pubkey", + LocalHTLCFailureReason::InvalidOnionKey, + ); } if msg.onion_routing_packet.version != 0 { @@ -525,82 +700,156 @@ where //receiving node would have to brute force to figure out which version was put in the //packet by the node that send us the message, in the case of hashing the hop_data, the //node knows the HMAC matched, so they already know what is there... - return encode_malformed_error("Unknown onion packet version", LocalHTLCFailureReason::InvalidOnionVersion) + return encode_malformed_error( + "Unknown onion packet version", + LocalHTLCFailureReason::InvalidOnionVersion, + ); } - let encode_relay_error = |message: &str, reason: LocalHTLCFailureReason, shared_secret: [u8; 32], trampoline_shared_secret: Option<[u8; 32]>, data: &[u8]| { + let encode_relay_error = |message: &str, + reason: LocalHTLCFailureReason, + shared_secret: [u8; 32], + trampoline_shared_secret: Option<[u8; 32]>, + data: &[u8]| { if msg.blinding_point.is_some() { - return encode_malformed_error(message, LocalHTLCFailureReason::InvalidOnionBlinding) + return encode_malformed_error(message, LocalHTLCFailureReason::InvalidOnionBlinding); } log_info!(logger, "Failed to accept/forward incoming HTLC: {}", message); let failure = HTLCFailReason::reason(reason, data.to_vec()) .get_encrypted_failure_packet(&shared_secret, &trampoline_shared_secret); - return Err((HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - reason: failure.data, - attribution_data: failure.attribution_data, - }), reason)); + return Err(( + HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + reason: failure.data, + attribution_data: failure.attribution_data, + }), + reason, + )); }; let next_hop = match onion_utils::decode_next_payment_hop( - Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac, - msg.payment_hash, msg.blinding_point, node_signer + Recipient::Node, + &msg.onion_routing_packet.public_key.unwrap(), + &msg.onion_routing_packet.hop_data[..], + msg.onion_routing_packet.hmac, + msg.payment_hash, + msg.blinding_point, + node_signer, ) { Ok(res) => res, Err(onion_utils::OnionDecodeErr::Malformed { err_msg, reason }) => { return encode_malformed_error(err_msg, reason); }, - Err(onion_utils::OnionDecodeErr::Relay { err_msg, reason, shared_secret, trampoline_shared_secret }) => { - return encode_relay_error(err_msg, reason, shared_secret.secret_bytes(), trampoline_shared_secret.map(|tss| tss.secret_bytes()), &[0; 0]); + Err(onion_utils::OnionDecodeErr::Relay { + err_msg, + reason, + shared_secret, + trampoline_shared_secret, + }) => { + return encode_relay_error( + err_msg, + reason, + shared_secret.secret_bytes(), + trampoline_shared_secret.map(|tss| tss.secret_bytes()), + &[0; 0], + ); }, }; let next_packet_details = match next_hop { - onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload { short_channel_id, amt_to_forward, outgoing_cltv_value }, shared_secret, .. } => { - let next_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx, - msg.onion_routing_packet.public_key.unwrap(), &shared_secret.secret_bytes()); + onion_utils::Hop::Forward { + next_hop_data: + msgs::InboundOnionForwardPayload { + short_channel_id, + amt_to_forward, + outgoing_cltv_value, + }, + shared_secret, + .. + } => { + let next_packet_pubkey = onion_utils::next_hop_pubkey( + secp_ctx, + msg.onion_routing_packet.public_key.unwrap(), + &shared_secret.secret_bytes(), + ); Some(NextPacketDetails { - next_packet_pubkey, outgoing_connector: HopConnector::ShortChannelId(short_channel_id), - outgoing_amt_msat: amt_to_forward, outgoing_cltv_value + next_packet_pubkey, + outgoing_connector: HopConnector::ShortChannelId(short_channel_id), + outgoing_amt_msat: amt_to_forward, + outgoing_cltv_value, }) - } - onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload { short_channel_id, ref payment_relay, ref payment_constraints, ref features, .. }, shared_secret, .. } => { - let (amt_to_forward, outgoing_cltv_value) = match check_blinded_forward( - msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features - ) { - Ok((amt, cltv)) => (amt, cltv), - Err(()) => { - return encode_relay_error("Underflow calculating outbound amount or cltv value for blinded forward", + }, + onion_utils::Hop::BlindedForward { + next_hop_data: + msgs::InboundOnionBlindedForwardPayload { + short_channel_id, + ref payment_relay, + ref payment_constraints, + ref features, + .. + }, + shared_secret, + .. + } => { + let (amt_to_forward, outgoing_cltv_value) = + match check_blinded_forward( + msg.amount_msat, + msg.cltv_expiry, + &payment_relay, + &payment_constraints, + &features, + ) { + Ok((amt, cltv)) => (amt, cltv), + Err(()) => { + return encode_relay_error("Underflow calculating outbound amount or cltv value for blinded forward", LocalHTLCFailureReason::InvalidOnionBlinding, shared_secret.secret_bytes(), None, &[0; 32]); - } - }; - let next_packet_pubkey = onion_utils::next_hop_pubkey(&secp_ctx, - msg.onion_routing_packet.public_key.unwrap(), &shared_secret.secret_bytes()); + }, + }; + let next_packet_pubkey = onion_utils::next_hop_pubkey( + &secp_ctx, + msg.onion_routing_packet.public_key.unwrap(), + &shared_secret.secret_bytes(), + ); Some(NextPacketDetails { - next_packet_pubkey, outgoing_connector: HopConnector::ShortChannelId(short_channel_id), outgoing_amt_msat: amt_to_forward, - outgoing_cltv_value + next_packet_pubkey, + outgoing_connector: HopConnector::ShortChannelId(short_channel_id), + outgoing_amt_msat: amt_to_forward, + outgoing_cltv_value, }) - } - onion_utils::Hop::TrampolineForward { next_trampoline_hop_data: msgs::InboundTrampolineForwardPayload { amt_to_forward, outgoing_cltv_value, next_trampoline }, trampoline_shared_secret, incoming_trampoline_public_key, .. } => { - let next_trampoline_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx, - incoming_trampoline_public_key, &trampoline_shared_secret.secret_bytes()); + }, + onion_utils::Hop::TrampolineForward { + next_trampoline_hop_data: + msgs::InboundTrampolineForwardPayload { + amt_to_forward, + outgoing_cltv_value, + next_trampoline, + }, + trampoline_shared_secret, + incoming_trampoline_public_key, + .. + } => { + let next_trampoline_packet_pubkey = onion_utils::next_hop_pubkey( + secp_ctx, + incoming_trampoline_public_key, + &trampoline_shared_secret.secret_bytes(), + ); Some(NextPacketDetails { next_packet_pubkey: next_trampoline_packet_pubkey, outgoing_connector: HopConnector::Trampoline(next_trampoline), outgoing_amt_msat: amt_to_forward, outgoing_cltv_value, }) - } - _ => None + }, + _ => None, }; Ok((next_hop, next_packet_details)) } pub(super) fn check_incoming_htlc_cltv( - cur_height: u32, outgoing_cltv_value: u32, cltv_expiry: u32 + cur_height: u32, outgoing_cltv_value: u32, cltv_expiry: u32, ) -> Result<(), (&'static str, LocalHTLCFailureReason)> { if (cltv_expiry as u64) < (outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 { return Err(("Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta", @@ -613,7 +862,10 @@ pub(super) fn check_incoming_htlc_cltv( return Err(("CLTV expiry is too close", LocalHTLCFailureReason::CLTVExpiryTooSoon)); } if cltv_expiry > cur_height + CLTV_FAR_FAR_AWAY as u32 { - return Err(("CLTV expiry is too far in the future", LocalHTLCFailureReason::CLTVExpiryTooFar)); + return Err(( + "CLTV expiry is too far in the future", + LocalHTLCFailureReason::CLTVExpiryTooFar, + )); } // If the HTLC expires ~now, don't bother trying to forward it to our // counterparty. They should fail it anyway, but we don't want to bother with @@ -624,7 +876,10 @@ pub(super) fn check_incoming_htlc_cltv( // but there is no need to do that, and since we're a bit conservative with our // risk threshold it just results in failing to forward payments. if (outgoing_cltv_value) as u64 <= (cur_height + LATENCY_GRACE_PERIOD_BLOCKS) as u64 { - return Err(("Outgoing CLTV value is too soon", LocalHTLCFailureReason::OutgoingCLTVTooSoon)); + return Err(( + "Outgoing CLTV value is too soon", + LocalHTLCFailureReason::OutgoingCLTVTooSoon, + )); } Ok(()) @@ -632,18 +887,18 @@ pub(super) fn check_incoming_htlc_cltv( #[cfg(test)] mod tests { - use bitcoin::hashes::Hash; - use bitcoin::hashes::sha256::Hash as Sha256; - use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; - use crate::ln::types::ChannelId; - use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret}; use crate::ln::channelmanager::{RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA}; use crate::ln::functional_test_utils::TEST_FINAL_CLTV; - use crate::types::features::{ChannelFeatures, NodeFeatures}; use crate::ln::msgs; use crate::ln::onion_utils::create_payment_onion; + use crate::ln::types::ChannelId; use crate::routing::router::{Path, RouteHop}; + use crate::types::features::{ChannelFeatures, NodeFeatures}; + use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::test_utils; + use bitcoin::hashes::sha256::Hash as Sha256; + use bitcoin::hashes::Hash; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; #[test] fn fail_construct_onion_on_too_big_payloads() { @@ -659,22 +914,40 @@ mod tests { let charlie_pk = PublicKey::from_secret_key(&secp_ctx, &charlie.get_node_secret_key()); let ( - session_priv, total_amt_msat, cur_height, mut recipient_onion, keysend_preimage, payment_hash, - prng_seed, hops, .. + session_priv, + total_amt_msat, + cur_height, + mut recipient_onion, + keysend_preimage, + payment_hash, + prng_seed, + hops, + .., ) = payment_onion_args(bob_pk, charlie_pk); // Ensure the onion will not fit all the payloads by adding a large custom TLV. recipient_onion.custom_tlvs.push((13377331, vec![0; 1156])); - let path = Path { hops, blinded_tail: None, }; + let path = Path { hops, blinded_tail: None }; let onion_keys = super::onion_utils::construct_onion_keys(&secp_ctx, &path, &session_priv); let (onion_payloads, ..) = super::onion_utils::build_onion_payloads( - &path, total_amt_msat, &recipient_onion, cur_height + 1, &Some(keysend_preimage), None, None - ).unwrap(); + &path, + total_amt_msat, + &recipient_onion, + cur_height + 1, + &Some(keysend_preimage), + None, + None, + ) + .unwrap(); assert!(super::onion_utils::construct_onion_packet( - onion_payloads, onion_keys, prng_seed, &payment_hash - ).is_err()); + onion_payloads, + onion_keys, + prng_seed, + &payment_hash + ) + .is_err()); } #[test] @@ -687,42 +960,63 @@ mod tests { let charlie = crate::sign::KeysManager::new(&[3; 32], 42, 42); let charlie_pk = PublicKey::from_secret_key(&secp_ctx, &charlie.get_node_secret_key()); - let (session_priv, total_amt_msat, cur_height, recipient_onion, preimage, payment_hash, - prng_seed, hops, recipient_amount, pay_secret) = payment_onion_args(bob_pk, charlie_pk); + let ( + session_priv, + total_amt_msat, + cur_height, + recipient_onion, + preimage, + payment_hash, + prng_seed, + hops, + recipient_amount, + pay_secret, + ) = payment_onion_args(bob_pk, charlie_pk); - let path = Path { - hops: hops, - blinded_tail: None, - }; + let path = Path { hops, blinded_tail: None }; let (onion, amount_msat, cltv_expiry) = create_payment_onion( - &secp_ctx, &path, &session_priv, total_amt_msat, &recipient_onion, - cur_height, &payment_hash, &Some(preimage), None, prng_seed - ).unwrap(); + &secp_ctx, + &path, + &session_priv, + total_amt_msat, + &recipient_onion, + cur_height, + &payment_hash, + &Some(preimage), + None, + prng_seed, + ) + .unwrap(); let msg = make_update_add_msg(amount_msat, cltv_expiry, payment_hash, onion); let logger = test_utils::TestLogger::with_id("bob".to_string()); let peeled = peel_payment_onion(&msg, &bob, &logger, &secp_ctx, cur_height, false) - .map_err(|e| e.msg).unwrap(); + .map_err(|e| e.msg) + .unwrap(); let next_onion = match peeled.routing { - PendingHTLCRouting::Forward { onion_packet, .. } => { - onion_packet - }, + PendingHTLCRouting::Forward { onion_packet, .. } => onion_packet, _ => panic!("expected a forwarded onion"), }; let msg2 = make_update_add_msg(amount_msat, cltv_expiry, payment_hash, next_onion); let peeled2 = peel_payment_onion(&msg2, &charlie, &logger, &secp_ctx, cur_height, false) - .map_err(|e| e.msg).unwrap(); + .map_err(|e| e.msg) + .unwrap(); match peeled2.routing { - PendingHTLCRouting::ReceiveKeysend { payment_preimage, payment_data, incoming_cltv_expiry, .. } => { + PendingHTLCRouting::ReceiveKeysend { + payment_preimage, + payment_data, + incoming_cltv_expiry, + .. + } => { assert_eq!(payment_preimage, preimage); assert_eq!(peeled2.outgoing_amt_msat, recipient_amount); assert_eq!(incoming_cltv_expiry, peeled2.outgoing_cltv_value); - let msgs::FinalOnionHopData{total_msat, payment_secret} = payment_data.unwrap(); + let msgs::FinalOnionHopData { total_msat, payment_secret } = payment_data.unwrap(); assert_eq!(total_msat, total_amt_msat); assert_eq!(payment_secret, pay_secret); }, @@ -732,7 +1026,7 @@ mod tests { fn make_update_add_msg( amount_msat: u64, cltv_expiry: u32, payment_hash: PaymentHash, - onion_routing_packet: msgs::OnionPacket + onion_routing_packet: msgs::OnionPacket, ) -> msgs::UpdateAddHTLC { msgs::UpdateAddHTLC { channel_id: ChannelId::from_bytes([0; 32]), @@ -746,9 +1040,19 @@ mod tests { } } - fn payment_onion_args(hop_pk: PublicKey, recipient_pk: PublicKey) -> ( - SecretKey, u64, u32, RecipientOnionFields, PaymentPreimage, PaymentHash, [u8; 32], - Vec, u64, PaymentSecret, + fn payment_onion_args( + hop_pk: PublicKey, recipient_pk: PublicKey, + ) -> ( + SecretKey, + u64, + u32, + RecipientOnionFields, + PaymentPreimage, + PaymentHash, + [u8; 32], + Vec, + u64, + PaymentSecret, ) { let session_priv_bytes = [42; 32]; let session_priv = SecretKey::from_slice(&session_priv_bytes).unwrap(); @@ -783,11 +1087,20 @@ mod tests { node_features: NodeFeatures::empty(), channel_features: ChannelFeatures::empty(), maybe_announced_channel: false, - } + }, ]; - (session_priv, total_amt_msat, cur_height, recipient_onion, preimage, payment_hash, - prng_seed, hops, recipient_amount, pay_secret) + ( + session_priv, + total_amt_msat, + cur_height, + recipient_onion, + preimage, + payment_hash, + prng_seed, + hops, + recipient_amount, + pay_secret, + ) } - } diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs index 5e17afe62d6..bb5e5d2a7c2 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -12,51 +12,79 @@ //! returned errors decode to the correct thing. use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS}; -use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::events::{Event, HTLCDestination, PathFailure, PaymentFailureReason}; -use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS; -use crate::ln::channelmanager::{HTLCForwardInfo, FailureCode, CLTV_FAR_FAR_AWAY, DISABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA, PendingAddHTLCInfo, PendingHTLCInfo, PendingHTLCRouting, PaymentId, RecipientOnionFields}; -use crate::ln::onion_utils::{self, LocalHTLCFailureReason}; -use crate::routing::gossip::{NetworkUpdate, RoutingFees}; -use crate::routing::router::{get_route, PaymentParameters, Route, RouteParameters, RouteHint, RouteHintHop, Path, TrampolineHop, BlindedTail, RouteHop}; -use crate::types::features::{InitFeatures, Bolt11InvoiceFeatures}; +use crate::ln::channelmanager::{ + FailureCode, HTLCForwardInfo, PaymentId, PendingAddHTLCInfo, PendingHTLCInfo, + PendingHTLCRouting, RecipientOnionFields, CLTV_FAR_FAR_AWAY, DISABLE_GOSSIP_TICKS, + MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::functional_test_utils::test_default_channel_config; use crate::ln::msgs; use crate::ln::msgs::{ - BaseMessageHandler, ChannelMessageHandler, ChannelUpdate, FinalOnionHopData, - OutboundOnionPayload, OutboundTrampolinePayload, MessageSendEvent, + BaseMessageHandler, ChannelMessageHandler, ChannelUpdate, FinalOnionHopData, MessageSendEvent, + OutboundOnionPayload, OutboundTrampolinePayload, }; +use crate::ln::onion_utils::{self, LocalHTLCFailureReason}; use crate::ln::wire::Encode; +use crate::routing::gossip::{NetworkUpdate, RoutingFees}; +use crate::routing::router::{ + get_route, BlindedTail, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, + RouteParameters, TrampolineHop, +}; +use crate::sign::{EntropySource, NodeSigner, Recipient}; +use crate::types::features::{Bolt11InvoiceFeatures, InitFeatures}; +use crate::types::payment::{PaymentHash, PaymentSecret}; +use crate::util::config::{ChannelConfig, MaxDustHTLCExposure, UserConfig}; +use crate::util::errors::APIError; use crate::util::ser::{BigSize, Writeable, Writer}; use crate::util::test_utils; -use crate::util::config::{UserConfig, ChannelConfig, MaxDustHTLCExposure}; -use crate::util::errors::APIError; use bitcoin::constants::ChainHash; -use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::secp256k1; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; +use crate::blinded_path::BlindedHop; use crate::io; +use crate::ln::functional_test_utils::*; +use crate::ln::onion_utils::{construct_trampoline_onion_keys, construct_trampoline_onion_packet}; use crate::prelude::*; use bitcoin::hex::{DisplayHex, FromHex}; use types::features::{ChannelFeatures, Features, NodeFeatures}; -use crate::blinded_path::BlindedHop; -use crate::ln::functional_test_utils::*; -use crate::ln::onion_utils::{construct_trampoline_onion_keys, construct_trampoline_onion_packet}; use super::msgs::OnionErrorPacket; use super::onion_utils::AttributionData; -fn run_onion_failure_test(_name: &str, test_case: u8, nodes: &Vec, route: &Route, payment_hash: &PaymentHash, payment_secret: &PaymentSecret, callback_msg: F1, callback_node: F2, expected_retryable: bool, expected_error_code: Option, expected_channel_update: Option, expected_short_channel_id: Option, expected_htlc_destination: Option) - where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC), - F2: FnMut(), +fn run_onion_failure_test( + _name: &str, test_case: u8, nodes: &Vec, route: &Route, payment_hash: &PaymentHash, + payment_secret: &PaymentSecret, callback_msg: F1, callback_node: F2, expected_retryable: bool, + expected_error_code: Option, + expected_channel_update: Option, expected_short_channel_id: Option, + expected_htlc_destination: Option, +) where + F1: for<'a> FnMut(&'a mut msgs::UpdateAddHTLC), + F2: FnMut(), { - run_onion_failure_test_with_fail_intercept(_name, test_case, nodes, route, payment_hash, payment_secret, callback_msg, |_|{}, callback_node, expected_retryable, expected_error_code, expected_channel_update, expected_short_channel_id, expected_htlc_destination); + run_onion_failure_test_with_fail_intercept( + _name, + test_case, + nodes, + route, + payment_hash, + payment_secret, + callback_msg, + |_| {}, + callback_node, + expected_retryable, + expected_error_code, + expected_channel_update, + expected_short_channel_id, + expected_htlc_destination, + ); } // test_case @@ -66,16 +94,17 @@ fn run_onion_failure_test(_name: &str, test_case: u8, nodes: &Vec, // 3: final node fails backward (but tamper onion payloads from node0) // 100: trigger error in the intermediate node and tamper returning fail_htlc // 200: trigger error in the final node and tamper returning fail_htlc -fn run_onion_failure_test_with_fail_intercept( +fn run_onion_failure_test_with_fail_intercept( _name: &str, test_case: u8, nodes: &Vec, route: &Route, payment_hash: &PaymentHash, payment_secret: &PaymentSecret, mut callback_msg: F1, mut callback_fail: F2, - mut callback_node: F3, expected_retryable: bool, expected_error_reason: Option, + mut callback_node: F3, expected_retryable: bool, + expected_error_reason: Option, expected_channel_update: Option, expected_short_channel_id: Option, expected_htlc_destination: Option, -) - where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC), - F2: for <'a> FnMut(&'a mut msgs::UpdateFailHTLC), - F3: FnMut(), +) where + F1: for<'a> FnMut(&'a mut msgs::UpdateAddHTLC), + F2: for<'a> FnMut(&'a mut msgs::UpdateFailHTLC), + F3: FnMut(), { macro_rules! expect_event { ($node: expr, $event_type: path) => {{ @@ -85,20 +114,27 @@ fn run_onion_failure_test_with_fail_intercept( $event_type { .. } => {}, _ => panic!("Unexpected event"), } - }} + }}; } macro_rules! expect_htlc_forward { ($node: expr) => {{ expect_event!($node, Event::PendingHTLCsForwardable); $node.node.process_pending_htlc_forwards(); - }} + }}; } // 0 ~~> 2 send payment let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); - nodes[0].node.send_payment_with_route(route.clone(), *payment_hash, - RecipientOnionFields::secret_only(*payment_secret), payment_id).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + *payment_hash, + RecipientOnionFields::secret_only(*payment_secret), + payment_id, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); // temper update_add (0 => 1) @@ -112,15 +148,24 @@ fn run_onion_failure_test_with_fail_intercept( commitment_signed_dance!(nodes[1], nodes[0], &update_0.commitment_signed, false, true); let update_1_0 = match test_case { - 0|100 => { // intermediate node failure; fail backward to 0 + 0 | 100 => { + // intermediate node failure; fail backward to 0 expect_pending_htlcs_forwardable!(nodes[1]); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[expected_htlc_destination.clone().unwrap()]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[expected_htlc_destination.clone().unwrap()] + ); check_added_monitors(&nodes[1], 1); let update_1_0 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - assert!(update_1_0.update_fail_htlcs.len()+update_1_0.update_fail_malformed_htlcs.len()==1 && (update_1_0.update_fail_htlcs.len()==1 || update_1_0.update_fail_malformed_htlcs.len()==1)); + assert!( + update_1_0.update_fail_htlcs.len() + update_1_0.update_fail_malformed_htlcs.len() + == 1 && (update_1_0.update_fail_htlcs.len() == 1 + || update_1_0.update_fail_malformed_htlcs.len() == 1) + ); update_1_0 }, - 1|2|3|200 => { // final node failure; forwarding to 2 + 1 | 2 | 3 | 200 => { + // final node failure; forwarding to 2 assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); // forwarding on 1 if test_case != 200 { @@ -145,10 +190,16 @@ fn run_onion_failure_test_with_fail_intercept( expect_htlc_forward!(&nodes[2]); expect_event!(&nodes[2], Event::PaymentClaimable); callback_node(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }] + ); } else if test_case == 1 || test_case == 3 { expect_htlc_forward!(&nodes[2]); - expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), vec![expected_htlc_destination.clone().unwrap()]); + expect_htlc_handling_failed_destinations!( + nodes[2].node.get_and_clear_pending_events(), + vec![expected_htlc_destination.clone().unwrap()] + ); } check_added_monitors!(&nodes[2], 1); @@ -180,14 +231,24 @@ fn run_onion_failure_test_with_fail_intercept( } nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &fail_msg); } else { - nodes[0].node.handle_update_fail_malformed_htlc(nodes[1].node.get_our_node_id(), &update_1_0.update_fail_malformed_htlcs[0]); + nodes[0].node.handle_update_fail_malformed_htlc( + nodes[1].node.get_our_node_id(), + &update_1_0.update_fail_malformed_htlcs[0], + ); }; commitment_signed_dance!(nodes[0], nodes[1], update_1_0.commitment_signed, false, true); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); - if let &Event::PaymentPathFailed { ref payment_failed_permanently, ref short_channel_id, ref error_code, failure: PathFailure::OnPath { ref network_update }, .. } = &events[0] { + if let &Event::PaymentPathFailed { + ref payment_failed_permanently, + ref short_channel_id, + ref error_code, + failure: PathFailure::OnPath { ref network_update }, + .. + } = &events[0] + { assert_eq!(*payment_failed_permanently, !expected_retryable); assert_eq!(error_code.is_none(), expected_error_reason.is_none()); if let Some(expected_reason) = expected_error_reason { @@ -197,7 +258,11 @@ fn run_onion_failure_test_with_fail_intercept( match network_update { Some(update) => match update { &NetworkUpdate::ChannelFailure { ref short_channel_id, ref is_permanent } => { - if let NetworkUpdate::ChannelFailure { short_channel_id: ref expected_short_channel_id, is_permanent: ref expected_is_permanent } = expected_channel_update.unwrap() { + if let NetworkUpdate::ChannelFailure { + short_channel_id: ref expected_short_channel_id, + is_permanent: ref expected_is_permanent, + } = expected_channel_update.unwrap() + { assert!(*short_channel_id == *expected_short_channel_id); assert!(*is_permanent == *expected_is_permanent); } else { @@ -205,14 +270,18 @@ fn run_onion_failure_test_with_fail_intercept( } }, &NetworkUpdate::NodeFailure { ref node_id, ref is_permanent } => { - if let NetworkUpdate::NodeFailure { node_id: ref expected_node_id, is_permanent: ref expected_is_permanent } = expected_channel_update.unwrap() { + if let NetworkUpdate::NodeFailure { + node_id: ref expected_node_id, + is_permanent: ref expected_is_permanent, + } = expected_channel_update.unwrap() + { assert!(*node_id == *expected_node_id); assert!(*is_permanent == *expected_is_permanent); } else { panic!("Unexpected message event"); } }, - } + }, None => panic!("Expected channel update"), } } else { @@ -230,15 +299,22 @@ fn run_onion_failure_test_with_fail_intercept( panic!("Unexpected event"); } match events[1] { - Event::PaymentFailed { payment_hash: ev_payment_hash, payment_id: ev_payment_id, reason: ref ev_reason } => { + Event::PaymentFailed { + payment_hash: ev_payment_hash, + payment_id: ev_payment_id, + reason: ref ev_reason, + } => { assert_eq!(Some(*payment_hash), ev_payment_hash); assert_eq!(payment_id, ev_payment_id); - assert_eq!(if expected_retryable { - PaymentFailureReason::RetriesExhausted - } else { - PaymentFailureReason::RecipientRejected - }, ev_reason.unwrap()); - } + assert_eq!( + if expected_retryable { + PaymentFailureReason::RetriesExhausted + } else { + PaymentFailureReason::RecipientRejected + }, + ev_reason.unwrap() + ); + }, _ => panic!("Unexpected second event"), } } @@ -246,8 +322,8 @@ fn run_onion_failure_test_with_fail_intercept( impl msgs::ChannelUpdate { fn dummy(short_channel_id: u64) -> msgs::ChannelUpdate { use bitcoin::hash_types::BlockHash; - use bitcoin::secp256k1::ffi::Signature as FFISignature; use bitcoin::secp256k1::ecdsa::Signature; + use bitcoin::secp256k1::ffi::Signature as FFISignature; msgs::ChannelUpdate { signature: Signature::from(unsafe { FFISignature::new() }), contents: msgs::UnsignedChannelUpdate { @@ -262,13 +338,13 @@ impl msgs::ChannelUpdate { fee_base_msat: 0, fee_proportional_millionths: 0, excess_data: vec![], - } + }, } } } struct BogusOnionHopData { - data: Vec + data: Vec, } impl BogusOnionHopData { fn new(orig: msgs::OutboundOnionPayload) -> Self { @@ -294,16 +370,37 @@ fn test_fee_failures() { let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config)]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(config.clone()), Some(config.clone()), Some(config)], + ); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let channels = [create_announced_chan_between_nodes(&nodes, 0, 1), create_announced_chan_between_nodes(&nodes, 1, 2)]; + let channels = [ + create_announced_chan_between_nodes(&nodes, 0, 1), + create_announced_chan_between_nodes(&nodes, 1, 2), + ]; // positive case - let (route, payment_hash_success, payment_preimage_success, payment_secret_success) = get_route_and_payment_hash!(nodes[0], nodes[2], 40_000); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash_success, - RecipientOnionFields::secret_only(payment_secret_success), PaymentId(payment_hash_success.0)).unwrap(); + let (route, payment_hash_success, payment_preimage_success, payment_secret_success) = + get_route_and_payment_hash!(nodes[0], nodes[2], 40_000); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash_success, + RecipientOnionFields::secret_only(payment_secret_success), + PaymentId(payment_hash_success.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 40_000, payment_hash_success, payment_secret_success); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + 40_000, + payment_hash_success, + payment_secret_success, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_success); // If the hop gives fee_insufficient but enough fees were provided, then the previous hop @@ -311,10 +408,26 @@ fn test_fee_failures() { // because we ignore channel update contents, we will still blame the 2nd channel. let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("fee_insufficient", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, || {}, true, Some(LocalHTLCFailureReason::FeeInsufficient), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false}), Some(short_channel_id), - Some(HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: channels[1].2 })); + run_onion_failure_test( + "fee_insufficient", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + || {}, + true, + Some(LocalHTLCFailureReason::FeeInsufficient), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: channels[1].2, + }), + ); // In an earlier version, we spuriously failed to forward payments if the expected feerate // changed between the channel open and the payment. @@ -323,11 +436,25 @@ fn test_fee_failures() { *feerate_lock *= 2; } - let (payment_preimage_success, payment_hash_success, payment_secret_success) = get_payment_preimage_hash!(nodes[2]); - nodes[0].node.send_payment_with_route(route, payment_hash_success, - RecipientOnionFields::secret_only(payment_secret_success), PaymentId(payment_hash_success.0)).unwrap(); + let (payment_preimage_success, payment_hash_success, payment_secret_success) = + get_payment_preimage_hash!(nodes[2]); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_success, + RecipientOnionFields::secret_only(payment_secret_success), + PaymentId(payment_hash_success.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 40_000, payment_hash_success, payment_secret_success); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + 40_000, + payment_hash_success, + payment_secret_success, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_success); } @@ -350,143 +477,425 @@ fn test_onion_failure() { let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config), Some(node_2_cfg)]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(config.clone()), Some(config), Some(node_2_cfg)], + ); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let channels = [create_announced_chan_between_nodes(&nodes, 0, 1), create_announced_chan_between_nodes(&nodes, 1, 2)]; + let channels = [ + create_announced_chan_between_nodes(&nodes, 0, 1), + create_announced_chan_between_nodes(&nodes, 1, 2), + ]; for node in nodes.iter() { *node.keys_manager.override_random_bytes.lock().unwrap() = Some([3; 32]); } - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 40000); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], 40000); // positive case - send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 40000); + send_payment(&nodes[0], &vec![&nodes[1], &nodes[2]][..], 40000); - let next_hop_failure = HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: channels[1].2 }; + let next_hop_failure = HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: channels[1].2, + }; // intermediate node failure let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("invalid_realm", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let cur_height = nodes[0].best_block_info().1 + 1; - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); - let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); - let mut new_payloads = Vec::new(); - for payload in onion_payloads.drain(..) { - new_payloads.push(BogusOnionHopData::new(payload)); - } - // break the first (non-final) hop payload by swapping the realm (0) byte for a byte - // describing a length-1 TLV payload, which is obviously bogus. - new_payloads[0].data[0] = 1; - msg.onion_routing_packet = onion_utils::construct_onion_packet_with_writable_hopdata(new_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); - }, ||{}, true, Some(LocalHTLCFailureReason::InvalidOnionPayload), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(short_channel_id), Some(HTLCDestination::InvalidOnion)); + run_onion_failure_test( + "invalid_realm", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let cur_height = nodes[0].best_block_info().1 + 1; + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); + let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 40000, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); + let mut new_payloads = Vec::new(); + for payload in onion_payloads.drain(..) { + new_payloads.push(BogusOnionHopData::new(payload)); + } + // break the first (non-final) hop payload by swapping the realm (0) byte for a byte + // describing a length-1 TLV payload, which is obviously bogus. + new_payloads[0].data[0] = 1; + msg.onion_routing_packet = onion_utils::construct_onion_packet_with_writable_hopdata( + new_payloads, + onion_keys, + [0; 32], + &payment_hash, + ) + .unwrap(); + }, + || {}, + true, + Some(LocalHTLCFailureReason::InvalidOnionPayload), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + Some(HTLCDestination::InvalidOnion), + ); // final node failure let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("invalid_realm", 3, &nodes, &route, &payment_hash, &payment_secret, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let cur_height = nodes[0].best_block_info().1 + 1; - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); - let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); - let mut new_payloads = Vec::new(); - for payload in onion_payloads.drain(..) { - new_payloads.push(BogusOnionHopData::new(payload)); - } - // break the last-hop payload by swapping the realm (0) byte for a byte describing a - // length-1 TLV payload, which is obviously bogus. - new_payloads[1].data[0] = 1; - msg.onion_routing_packet = onion_utils::construct_onion_packet_with_writable_hopdata(new_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); - }, ||{}, false, Some(LocalHTLCFailureReason::InvalidOnionPayload), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(short_channel_id), Some(HTLCDestination::InvalidOnion)); + run_onion_failure_test( + "invalid_realm", + 3, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let cur_height = nodes[0].best_block_info().1 + 1; + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); + let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 40000, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); + let mut new_payloads = Vec::new(); + for payload in onion_payloads.drain(..) { + new_payloads.push(BogusOnionHopData::new(payload)); + } + // break the last-hop payload by swapping the realm (0) byte for a byte describing a + // length-1 TLV payload, which is obviously bogus. + new_payloads[1].data[0] = 1; + msg.onion_routing_packet = onion_utils::construct_onion_packet_with_writable_hopdata( + new_payloads, + onion_keys, + [0; 32], + &payment_hash, + ) + .unwrap(); + }, + || {}, + false, + Some(LocalHTLCFailureReason::InvalidOnionPayload), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + Some(HTLCDestination::InvalidOnion), + ); // the following three with run_onion_failure_test_with_fail_intercept() test only the origin node // receiving simulated fail messages // intermediate node failure - run_onion_failure_test_with_fail_intercept("temporary_node_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - // trigger error - msg.amount_msat -= 1; - }, |msg| { - // and tamper returning error message - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), LocalHTLCFailureReason::TemporaryNodeFailure, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{}, true, Some(LocalHTLCFailureReason::TemporaryNodeFailure), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: false}), Some(route.paths[0].hops[0].short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test_with_fail_intercept( + "temporary_node_failure", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + // trigger error + msg.amount_msat -= 1; + }, + |msg| { + // and tamper returning error message + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[0].shared_secret.as_ref(), + LocalHTLCFailureReason::TemporaryNodeFailure, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || {}, + true, + Some(LocalHTLCFailureReason::TemporaryNodeFailure), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: false, + }), + Some(route.paths[0].hops[0].short_channel_id), + Some(next_hop_failure.clone()), + ); // final node failure - run_onion_failure_test_with_fail_intercept("temporary_node_failure", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { - // and tamper returning error message - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), LocalHTLCFailureReason::TemporaryNodeFailure, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, true, Some(LocalHTLCFailureReason::TemporaryNodeFailure), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: false}), Some(route.paths[0].hops[1].short_channel_id), None); + run_onion_failure_test_with_fail_intercept( + "temporary_node_failure", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { + // and tamper returning error message + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[1].shared_secret.as_ref(), + LocalHTLCFailureReason::TemporaryNodeFailure, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + true, + Some(LocalHTLCFailureReason::TemporaryNodeFailure), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: false, + }), + Some(route.paths[0].hops[1].short_channel_id), + None, + ); let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]); // intermediate node failure - run_onion_failure_test_with_fail_intercept("permanent_node_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), LocalHTLCFailureReason::PermanentNodeFailure, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{}, true, Some(LocalHTLCFailureReason::PermanentNodeFailure), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test_with_fail_intercept( + "permanent_node_failure", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[0].shared_secret.as_ref(), + LocalHTLCFailureReason::PermanentNodeFailure, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || {}, + true, + Some(LocalHTLCFailureReason::PermanentNodeFailure), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[0].short_channel_id), + Some(next_hop_failure.clone()), + ); // final node failure - run_onion_failure_test_with_fail_intercept("permanent_node_failure", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), LocalHTLCFailureReason::PermanentNodeFailure, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, false, Some(LocalHTLCFailureReason::PermanentNodeFailure), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: true}), Some(route.paths[0].hops[1].short_channel_id), None); + run_onion_failure_test_with_fail_intercept( + "permanent_node_failure", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[1].shared_secret.as_ref(), + LocalHTLCFailureReason::PermanentNodeFailure, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + false, + Some(LocalHTLCFailureReason::PermanentNodeFailure), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[1].short_channel_id), + None, + ); let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]); // intermediate node failure - run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), LocalHTLCFailureReason::RequiredNodeFeature, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, true, Some(LocalHTLCFailureReason::RequiredNodeFeature), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test_with_fail_intercept( + "required_node_feature_missing", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[0].shared_secret.as_ref(), + LocalHTLCFailureReason::RequiredNodeFeature, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + true, + Some(LocalHTLCFailureReason::RequiredNodeFeature), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[0].short_channel_id), + Some(next_hop_failure.clone()), + ); // final node failure - run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), LocalHTLCFailureReason::RequiredNodeFeature, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, false, Some(LocalHTLCFailureReason::RequiredNodeFeature), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: true}), Some(route.paths[0].hops[1].short_channel_id), None); + run_onion_failure_test_with_fail_intercept( + "required_node_feature_missing", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[1].shared_secret.as_ref(), + LocalHTLCFailureReason::RequiredNodeFeature, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + false, + Some(LocalHTLCFailureReason::RequiredNodeFeature), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[1].short_channel_id), + None, + ); let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]); // Our immediate peer sent UpdateFailMalformedHTLC because it couldn't understand the onion in // the UpdateAddHTLC that we sent. let short_channel_id = channels[0].0.contents.short_channel_id; - run_onion_failure_test("invalid_onion_version", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { msg.onion_routing_packet.version = 1; }, ||{}, true, - Some(LocalHTLCFailureReason::InvalidOnionVersion), None, Some(short_channel_id), Some(HTLCDestination::InvalidOnion)); + run_onion_failure_test( + "invalid_onion_version", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.onion_routing_packet.version = 1; + }, + || {}, + true, + Some(LocalHTLCFailureReason::InvalidOnionVersion), + None, + Some(short_channel_id), + Some(HTLCDestination::InvalidOnion), + ); - run_onion_failure_test("invalid_onion_hmac", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { msg.onion_routing_packet.hmac = [3; 32]; }, ||{}, true, - Some(LocalHTLCFailureReason::InvalidOnionHMAC), None, Some(short_channel_id), Some(HTLCDestination::InvalidOnion)); + run_onion_failure_test( + "invalid_onion_hmac", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.onion_routing_packet.hmac = [3; 32]; + }, + || {}, + true, + Some(LocalHTLCFailureReason::InvalidOnionHMAC), + None, + Some(short_channel_id), + Some(HTLCDestination::InvalidOnion), + ); - run_onion_failure_test("invalid_onion_key", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { msg.onion_routing_packet.public_key = Err(secp256k1::Error::InvalidPublicKey);}, ||{}, true, - Some(LocalHTLCFailureReason::InvalidOnionKey), None, Some(short_channel_id), Some(HTLCDestination::InvalidOnion)); + run_onion_failure_test( + "invalid_onion_key", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.onion_routing_packet.public_key = Err(secp256k1::Error::InvalidPublicKey); + }, + || {}, + true, + Some(LocalHTLCFailureReason::InvalidOnionKey), + None, + Some(short_channel_id), + Some(HTLCDestination::InvalidOnion), + ); let short_channel_id = channels[1].0.contents.short_channel_id; let chan_update = ChannelUpdate::dummy(short_channel_id); @@ -495,72 +904,201 @@ fn test_onion_failure() { err_data.extend_from_slice(&(chan_update.serialized_length() as u16 + 2).to_be_bytes()); err_data.extend_from_slice(&ChannelUpdate::TYPE.to_be_bytes()); err_data.extend_from_slice(&chan_update.encode()); - run_onion_failure_test_with_fail_intercept("temporary_channel_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), LocalHTLCFailureReason::TemporaryChannelFailure, &err_data, 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{}, true, Some(LocalHTLCFailureReason::TemporaryChannelFailure), - Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), - Some(short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test_with_fail_intercept( + "temporary_channel_failure", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[0].shared_secret.as_ref(), + LocalHTLCFailureReason::TemporaryChannelFailure, + &err_data, + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || {}, + true, + Some(LocalHTLCFailureReason::TemporaryChannelFailure), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); // Check we can still handle onion failures that include channel updates without a type prefix let err_data_without_type = chan_update.encode_with_len(); - run_onion_failure_test_with_fail_intercept("temporary_channel_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), LocalHTLCFailureReason::TemporaryChannelFailure, &err_data_without_type, 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{}, true, Some(LocalHTLCFailureReason::TemporaryChannelFailure), - Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), - Some(short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test_with_fail_intercept( + "temporary_channel_failure", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[0].shared_secret.as_ref(), + LocalHTLCFailureReason::TemporaryChannelFailure, + &err_data_without_type, + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || {}, + true, + Some(LocalHTLCFailureReason::TemporaryChannelFailure), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test_with_fail_intercept("permanent_channel_failure", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), LocalHTLCFailureReason::PermanentChannelFailure, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - // short_channel_id from the processing node - }, ||{}, true, Some(LocalHTLCFailureReason::PermanentChannelFailure), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test_with_fail_intercept( + "permanent_channel_failure", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[0].shared_secret.as_ref(), + LocalHTLCFailureReason::PermanentChannelFailure, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + // short_channel_id from the processing node + }, + || {}, + true, + Some(LocalHTLCFailureReason::PermanentChannelFailure), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test_with_fail_intercept("required_channel_feature_missing", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[0].shared_secret.as_ref(), LocalHTLCFailureReason::RequiredChannelFeature, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - // short_channel_id from the processing node - }, ||{}, true, Some(LocalHTLCFailureReason::RequiredChannelFeature), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test_with_fail_intercept( + "required_channel_feature_missing", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[0].shared_secret.as_ref(), + LocalHTLCFailureReason::RequiredChannelFeature, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + // short_channel_id from the processing node + }, + || {}, + true, + Some(LocalHTLCFailureReason::RequiredChannelFeature), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); let mut bogus_route = route.clone(); bogus_route.paths[0].hops[1].short_channel_id -= 1; let short_channel_id = bogus_route.paths[0].hops[1].short_channel_id; - run_onion_failure_test("unknown_next_peer", 100, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(LocalHTLCFailureReason::UnknownNextPeer), - Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent:true}), Some(short_channel_id), Some(HTLCDestination::UnknownNextHop { requested_forward_scid: short_channel_id })); + run_onion_failure_test( + "unknown_next_peer", + 100, + &nodes, + &bogus_route, + &payment_hash, + &payment_secret, + |_| {}, + || {}, + true, + Some(LocalHTLCFailureReason::UnknownNextPeer), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + Some(HTLCDestination::UnknownNextHop { requested_forward_scid: short_channel_id }), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - let amt_to_forward = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[2].node.get_our_node_id()) - .unwrap().lock().unwrap().channel_by_id.get(&channels[1].2).unwrap() - .context().get_counterparty_htlc_minimum_msat() - 1; + let amt_to_forward = nodes[1] + .node + .per_peer_state + .read() + .unwrap() + .get(&nodes[2].node.get_our_node_id()) + .unwrap() + .lock() + .unwrap() + .channel_by_id + .get(&channels[1].2) + .unwrap() + .context() + .get_counterparty_htlc_minimum_msat() + - 1; let mut bogus_route = route.clone(); let route_len = bogus_route.paths[0].hops.len(); - bogus_route.paths[0].hops[route_len-1].fee_msat = amt_to_forward; - run_onion_failure_test("amount_below_minimum", 100, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(LocalHTLCFailureReason::AmountBelowMinimum), + bogus_route.paths[0].hops[route_len - 1].fee_msat = amt_to_forward; + run_onion_failure_test( + "amount_below_minimum", + 100, + &nodes, + &bogus_route, + &payment_hash, + &payment_secret, + |_| {}, + || {}, + true, + Some(LocalHTLCFailureReason::AmountBelowMinimum), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), - Some(short_channel_id), Some(next_hop_failure.clone())); + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); // Clear pending payments so that the following positive test has the correct payment hash. for node in nodes.iter() { @@ -568,122 +1106,318 @@ fn test_onion_failure() { } // Test a positive test-case with one extra msat, meeting the minimum. - bogus_route.paths[0].hops[route_len-1].fee_msat = amt_to_forward + 1; - let preimage = send_along_route(&nodes[0], bogus_route, &[&nodes[1], &nodes[2]], amt_to_forward+1).0; + bogus_route.paths[0].hops[route_len - 1].fee_msat = amt_to_forward + 1; + let preimage = + send_along_route(&nodes[0], bogus_route, &[&nodes[1], &nodes[2]], amt_to_forward + 1).0; claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], preimage); // We ignore channel update contents in onion errors, so will blame the 2nd channel even though // the first node is the one that messed up. let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("fee_insufficient", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, || {}, true, Some(LocalHTLCFailureReason::FeeInsufficient), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false}), Some(short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test( + "fee_insufficient", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + || {}, + true, + Some(LocalHTLCFailureReason::FeeInsufficient), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("incorrect_cltv_expiry", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - // need to violate: cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value - msg.cltv_expiry -= 1; - }, || {}, true, Some(LocalHTLCFailureReason::IncorrectCLTVExpiry), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false}), Some(short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test( + "incorrect_cltv_expiry", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + // need to violate: cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value + msg.cltv_expiry -= 1; + }, + || {}, + true, + Some(LocalHTLCFailureReason::IncorrectCLTVExpiry), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("expiry_too_soon", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1; - connect_blocks(&nodes[0], height - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], height - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], height - nodes[2].best_block_info().1); - }, ||{}, true, Some(LocalHTLCFailureReason::CLTVExpiryTooSoon), - Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), - Some(short_channel_id), Some(next_hop_failure.clone())); - - run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, false, Some(LocalHTLCFailureReason::IncorrectPaymentDetails), None, None, None); + run_onion_failure_test( + "expiry_too_soon", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1; + connect_blocks(&nodes[0], height - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], height - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], height - nodes[2].best_block_info().1); + }, + || {}, + true, + Some(LocalHTLCFailureReason::CLTVExpiryTooSoon), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); + + run_onion_failure_test( + "unknown_payment_hash", + 2, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + false, + Some(LocalHTLCFailureReason::IncorrectPaymentDetails), + None, + None, + None, + ); let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]); - run_onion_failure_test("final_expiry_too_soon", 1, &nodes, &route, &payment_hash, &payment_secret, |msg| { - let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1; - connect_blocks(&nodes[0], height - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], height - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], height - nodes[2].best_block_info().1); - }, || {}, false, Some(LocalHTLCFailureReason::IncorrectPaymentDetails), None, None, Some(HTLCDestination::FailedPayment { payment_hash })); - - run_onion_failure_test("final_incorrect_cltv_expiry", 1, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - nodes[1].node.process_pending_update_add_htlcs(); - for (_, pending_forwards) in nodes[1].node.forward_htlcs.lock().unwrap().iter_mut() { - for f in pending_forwards.iter_mut() { - match f { - &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => - forward_info.outgoing_cltv_value -= 1, - _ => {}, + run_onion_failure_test( + "final_expiry_too_soon", + 1, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1; + connect_blocks(&nodes[0], height - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], height - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], height - nodes[2].best_block_info().1); + }, + || {}, + false, + Some(LocalHTLCFailureReason::IncorrectPaymentDetails), + None, + None, + Some(HTLCDestination::FailedPayment { payment_hash }), + ); + + run_onion_failure_test( + "final_incorrect_cltv_expiry", + 1, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + nodes[1].node.process_pending_update_add_htlcs(); + for (_, pending_forwards) in nodes[1].node.forward_htlcs.lock().unwrap().iter_mut() { + for f in pending_forwards.iter_mut() { + match f { + &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { + ref mut forward_info, + .. + }) => forward_info.outgoing_cltv_value -= 1, + _ => {}, + } } } - } - }, true, Some(LocalHTLCFailureReason::FinalIncorrectCLTVExpiry), None, Some(channels[1].0.contents.short_channel_id), Some(HTLCDestination::FailedPayment { payment_hash })); - - run_onion_failure_test("final_incorrect_htlc_amount", 1, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - nodes[1].node.process_pending_update_add_htlcs(); - // violate amt_to_forward > msg.amount_msat - for (_, pending_forwards) in nodes[1].node.forward_htlcs.lock().unwrap().iter_mut() { - for f in pending_forwards.iter_mut() { - match f { - &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => - forward_info.outgoing_amt_msat -= 1, - _ => {}, + }, + true, + Some(LocalHTLCFailureReason::FinalIncorrectCLTVExpiry), + None, + Some(channels[1].0.contents.short_channel_id), + Some(HTLCDestination::FailedPayment { payment_hash }), + ); + + run_onion_failure_test( + "final_incorrect_htlc_amount", + 1, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + nodes[1].node.process_pending_update_add_htlcs(); + // violate amt_to_forward > msg.amount_msat + for (_, pending_forwards) in nodes[1].node.forward_htlcs.lock().unwrap().iter_mut() { + for f in pending_forwards.iter_mut() { + match f { + &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { + ref mut forward_info, + .. + }) => forward_info.outgoing_amt_msat -= 1, + _ => {}, + } } } - } - }, true, Some(LocalHTLCFailureReason::FinalIncorrectHTLCAmount), None, Some(channels[1].0.contents.short_channel_id), Some(HTLCDestination::FailedPayment { payment_hash })); + }, + true, + Some(LocalHTLCFailureReason::FinalIncorrectHTLCAmount), + None, + Some(channels[1].0.contents.short_channel_id), + Some(HTLCDestination::FailedPayment { payment_hash }), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("channel_disabled", 100, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - // disconnect event to the channel between nodes[1] ~ nodes[2] - nodes[1].node.peer_disconnected(nodes[2].node.get_our_node_id()); - nodes[2].node.peer_disconnected(nodes[1].node.get_our_node_id()); - }, true, Some(LocalHTLCFailureReason::TemporaryChannelFailure), - Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), - Some(short_channel_id), Some(next_hop_failure.clone())); - run_onion_failure_test("channel_disabled", 100, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - // disconnect event to the channel between nodes[1] ~ nodes[2] - for _ in 0..DISABLE_GOSSIP_TICKS + 1 { - nodes[1].node.timer_tick_occurred(); - nodes[2].node.timer_tick_occurred(); - } - nodes[1].node.get_and_clear_pending_msg_events(); - nodes[2].node.get_and_clear_pending_msg_events(); - }, true, Some(LocalHTLCFailureReason::ChannelDisabled), - Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), - Some(short_channel_id), Some(next_hop_failure.clone())); + run_onion_failure_test( + "channel_disabled", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + // disconnect event to the channel between nodes[1] ~ nodes[2] + nodes[1].node.peer_disconnected(nodes[2].node.get_our_node_id()); + nodes[2].node.peer_disconnected(nodes[1].node.get_our_node_id()); + }, + true, + Some(LocalHTLCFailureReason::TemporaryChannelFailure), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); + run_onion_failure_test( + "channel_disabled", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + // disconnect event to the channel between nodes[1] ~ nodes[2] + for _ in 0..DISABLE_GOSSIP_TICKS + 1 { + nodes[1].node.timer_tick_occurred(); + nodes[2].node.timer_tick_occurred(); + } + nodes[1].node.get_and_clear_pending_msg_events(); + nodes[2].node.get_and_clear_pending_msg_events(); + }, + true, + Some(LocalHTLCFailureReason::ChannelDisabled), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }), + Some(short_channel_id), + Some(next_hop_failure.clone()), + ); reconnect_nodes(ReconnectArgs::new(&nodes[1], &nodes[2])); - run_onion_failure_test("expiry_too_far", 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let mut route = route.clone(); - let height = nodes[2].best_block_info().1; - route.paths[0].hops[1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.paths[0].hops[0].cltv_expiry_delta + 1; - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); - let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, &recipient_onion_fields, height, &None, None, None).unwrap(); - let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); - msg.cltv_expiry = htlc_cltv; - msg.onion_routing_packet = onion_packet; - }, ||{}, true, Some(LocalHTLCFailureReason::CLTVExpiryTooFar), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id), Some(next_hop_failure.clone())); - - run_onion_failure_test_with_fail_intercept("mpp_timeout", 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { - // Tamper returning error message - let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); - let failure = onion_utils::build_failure_packet(onion_keys[1].shared_secret.as_ref(), LocalHTLCFailureReason::MPPTimeout, &[0;0], 0); - msg.reason = failure.data; - msg.attribution_data = failure.attribution_data; - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, true, Some(LocalHTLCFailureReason::MPPTimeout), None, None, None); - - run_onion_failure_test_with_fail_intercept("bogus err packet with valid hmac", 200, &nodes, - &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { + run_onion_failure_test( + "expiry_too_far", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); + let mut route = route.clone(); + let height = nodes[2].best_block_info().1; + route.paths[0].hops[1].cltv_expiry_delta += + CLTV_FAR_FAR_AWAY + route.paths[0].hops[0].cltv_expiry_delta + 1; + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); + let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 40000, + &recipient_onion_fields, + height, + &None, + None, + None, + ) + .unwrap(); + let onion_packet = onion_utils::construct_onion_packet( + onion_payloads, + onion_keys, + [0; 32], + &payment_hash, + ) + .unwrap(); + msg.cltv_expiry = htlc_cltv; + msg.onion_routing_packet = onion_packet; + }, + || {}, + true, + Some(LocalHTLCFailureReason::CLTVExpiryTooFar), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[0].short_channel_id), + Some(next_hop_failure.clone()), + ); + + run_onion_failure_test_with_fail_intercept( + "mpp_timeout", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { + // Tamper returning error message + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); + let failure = onion_utils::build_failure_packet( + onion_keys[1].shared_secret.as_ref(), + LocalHTLCFailureReason::MPPTimeout, + &[0; 0], + 0, + ); + msg.reason = failure.data; + msg.attribution_data = failure.attribution_data; + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + true, + Some(LocalHTLCFailureReason::MPPTimeout), + None, + None, + None, + ); + + run_onion_failure_test_with_fail_intercept( + "bogus err packet with valid hmac", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { + let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); let mut decoded_err_packet = msgs::DecodedOnionErrorPacket { failuremsg: vec![0], pad: vec![0; 255], @@ -697,31 +1431,69 @@ fn test_onion_failure() { data: decoded_err_packet.encode(), attribution_data: Some(AttributionData::new()), }; - onion_error.attribution_data.as_mut().unwrap().add_hmacs(&onion_keys[1].shared_secret.as_ref(), &onion_error.data); + onion_error + .attribution_data + .as_mut() + .unwrap() + .add_hmacs(&onion_keys[1].shared_secret.as_ref(), &onion_error.data); onion_utils::test_crypt_failure_packet( - &onion_keys[1].shared_secret.as_ref(), &mut onion_error); + &onion_keys[1].shared_secret.as_ref(), + &mut onion_error, + ); msg.reason = onion_error.data; msg.attribution_data = onion_error.attribution_data; - }, || nodes[2].node.fail_htlc_backwards(&payment_hash), false, None, - Some(NetworkUpdate::NodeFailure { node_id: route.paths[0].hops[1].pubkey, is_permanent: true }), - Some(channels[1].0.contents.short_channel_id), None); + }, + || nodes[2].node.fail_htlc_backwards(&payment_hash), + false, + None, + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: true, + }), + Some(channels[1].0.contents.short_channel_id), + None, + ); - run_onion_failure_test_with_fail_intercept("bogus err packet that is too short for an hmac", 200, &nodes, - &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { + run_onion_failure_test_with_fail_intercept( + "bogus err packet that is too short for an hmac", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { msg.reason = vec![1, 2, 3]; - }, || nodes[2].node.fail_htlc_backwards(&payment_hash), false, None, - None, None, None); + }, + || nodes[2].node.fail_htlc_backwards(&payment_hash), + false, + None, + None, + None, + None, + ); - run_onion_failure_test_with_fail_intercept("0-length channel update in intermediate node UPDATE onion failure", - 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { + run_onion_failure_test_with_fail_intercept( + "0-length channel update in intermediate node UPDATE onion failure", + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { msg.amount_msat -= 1; - }, |msg| { + }, + |msg| { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); let mut decoded_err_packet = msgs::DecodedOnionErrorPacket { failuremsg: vec![ 0x10, 0x7, // UPDATE|7 - 0x0, 0x0 // 0-len channel update + 0x0, 0x0, // 0-len channel update ], pad: vec![0; 255 - 4 /* 4-byte error message */], hmac: [0; 32], @@ -730,29 +1502,51 @@ fn test_onion_failure() { let mut hmac = HmacEngine::::new(&um); hmac.input(&decoded_err_packet.encode()[32..]); decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array(); - let mut onion_error = OnionErrorPacket{ + let mut onion_error = OnionErrorPacket { data: decoded_err_packet.encode(), attribution_data: Some(AttributionData::new()), }; - onion_error.attribution_data.as_mut().unwrap().add_hmacs(&onion_keys[0].shared_secret.as_ref(), &onion_error.data); + onion_error + .attribution_data + .as_mut() + .unwrap() + .add_hmacs(&onion_keys[0].shared_secret.as_ref(), &onion_error.data); onion_utils::test_crypt_failure_packet( - &onion_keys[0].shared_secret.as_ref(), &mut onion_error); + &onion_keys[0].shared_secret.as_ref(), + &mut onion_error, + ); msg.reason = onion_error.data; msg.attribution_data = onion_error.attribution_data; - }, || {}, true, Some(LocalHTLCFailureReason::TemporaryChannelFailure), + }, + || {}, + true, + Some(LocalHTLCFailureReason::TemporaryChannelFailure), Some(NetworkUpdate::ChannelFailure { short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: false, }), - Some(channels[1].0.contents.short_channel_id), Some(next_hop_failure.clone())); - run_onion_failure_test_with_fail_intercept("0-length channel update in final node UPDATE onion failure", - 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { + Some(channels[1].0.contents.short_channel_id), + Some(next_hop_failure.clone()), + ); + run_onion_failure_test_with_fail_intercept( + "0-length channel update in final node UPDATE onion failure", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); let mut decoded_err_packet = msgs::DecodedOnionErrorPacket { failuremsg: vec![ 0x10, 0x7, // UPDATE|7 - 0x0, 0x0 // 0-len channel update + 0x0, 0x0, // 0-len channel update ], pad: vec![0; 255 - 4 /* 4-byte error message */], hmac: [0; 32], @@ -761,21 +1555,32 @@ fn test_onion_failure() { let mut hmac = HmacEngine::::new(&um); hmac.input(&decoded_err_packet.encode()[32..]); decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array(); - let mut onion_error = OnionErrorPacket{ + let mut onion_error = OnionErrorPacket { data: decoded_err_packet.encode(), attribution_data: Some(AttributionData::new()), }; - onion_error.attribution_data.as_mut().unwrap().add_hmacs(&onion_keys[1].shared_secret.as_ref(), &onion_error.data); + onion_error + .attribution_data + .as_mut() + .unwrap() + .add_hmacs(&onion_keys[1].shared_secret.as_ref(), &onion_error.data); onion_utils::test_crypt_failure_packet( - &onion_keys[1].shared_secret.as_ref(), &mut onion_error); + &onion_keys[1].shared_secret.as_ref(), + &mut onion_error, + ); msg.reason = onion_error.data; msg.attribution_data = onion_error.attribution_data; - }, || nodes[2].node.fail_htlc_backwards(&payment_hash), true, Some(LocalHTLCFailureReason::TemporaryChannelFailure), + }, + || nodes[2].node.fail_htlc_backwards(&payment_hash), + true, + Some(LocalHTLCFailureReason::TemporaryChannelFailure), Some(NetworkUpdate::ChannelFailure { short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: false, }), - Some(channels[1].0.contents.short_channel_id), None); + Some(channels[1].0.contents.short_channel_id), + None, + ); } #[test] @@ -786,10 +1591,19 @@ fn test_overshoot_final_cltv() { let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); create_announced_chan_between_nodes(&nodes, 1, 2); - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 40000); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], 40000); let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); - nodes[0].node.send_payment_with_route(route, payment_hash, RecipientOnionFields::secret_only(payment_secret), payment_id).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -801,8 +1615,9 @@ fn test_overshoot_final_cltv() { for (_, pending_forwards) in nodes[1].node.forward_htlcs.lock().unwrap().iter_mut() { for f in pending_forwards.iter_mut() { match f { - &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => - forward_info.outgoing_cltv_value += 1, + &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { + ref mut forward_info, .. + }) => forward_info.outgoing_cltv_value += 1, _ => {}, } } @@ -827,7 +1642,8 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { config.channel_handshake_config.announce_for_forwarding = announce_for_forwarding; config.channel_handshake_limits.force_announced_channel_preference = false; config.accept_forwards_to_priv_channels = !announce_for_forwarding; - config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); + config.channel_config.max_dust_htlc_exposure = + MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let persister; @@ -836,18 +1652,12 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { let channel_manager_1_deserialized; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let other_channel = create_chan_between_nodes( - &nodes[0], &nodes[1], - ); + let other_channel = create_chan_between_nodes(&nodes[0], &nodes[1]); let channel_to_update = if announce_for_forwarding { - let channel = create_announced_chan_between_nodes( - &nodes, 1, 2, - ); + let channel = create_announced_chan_between_nodes(&nodes, 1, 2); (channel.2, channel.0.contents.short_channel_id) } else { - let channel = create_unannounced_chan_between_nodes_with_value( - &nodes, 1, 2, 100000, 10001, - ); + let channel = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001); (channel.0.channel_id, channel.0.short_channel_id_alias.unwrap()) }; let channel_to_update_counterparty = &nodes[2].node.get_our_node_id(); @@ -870,13 +1680,22 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { htlc_maximum_msat: None, htlc_minimum_msat: None, }])]; - let payment_params = PaymentParameters::from_node_id(*channel_to_update_counterparty, TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap() - .with_route_hints(hop_hints).unwrap(); + let payment_params = + PaymentParameters::from_node_id(*channel_to_update_counterparty, TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_route_hints(hop_hints) + .unwrap(); get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, PAYMENT_AMT) }; - send_along_route_with_secret(&nodes[0], route.clone(), &[&[&nodes[1], &nodes[2]]], PAYMENT_AMT, - payment_hash, payment_secret); + send_along_route_with_secret( + &nodes[0], + route.clone(), + &[&[&nodes[1], &nodes[2]]], + PAYMENT_AMT, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); // Closure to force expiry of a channel's previous config. @@ -887,11 +1706,15 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { }; // Closure to update and retrieve the latest ChannelUpdate. - let update_and_get_channel_update = |config: &ChannelConfig, expect_new_update: bool, - prev_update: Option<&msgs::ChannelUpdate>, should_expire_prev_config: bool| -> Option { - nodes[1].node.update_channel_config( - channel_to_update_counterparty, &[channel_to_update.0], config, - ).unwrap(); + let update_and_get_channel_update = |config: &ChannelConfig, + expect_new_update: bool, + prev_update: Option<&msgs::ChannelUpdate>, + should_expire_prev_config: bool| + -> Option { + nodes[1] + .node + .update_channel_config(channel_to_update_counterparty, &[channel_to_update.0], config) + .unwrap(); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expect_new_update as usize); if !expect_new_update { @@ -923,11 +1746,25 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { // second hop. let expect_onion_failure = |name: &str, error_reason: LocalHTLCFailureReason| { let short_channel_id = channel_to_update.1; - let network_update = NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }; + let network_update = + NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: false }; run_onion_failure_test( - name, 100, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {}, true, - Some(error_reason), Some(network_update), Some(short_channel_id), - Some(HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: channel_to_update.0 }), + name, + 100, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || {}, + true, + Some(error_reason), + Some(network_update), + Some(short_channel_id), + Some(HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: channel_to_update.0, + }), ); }; @@ -935,22 +1772,35 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { let mut invalid_config = default_config.clone(); invalid_config.cltv_expiry_delta = 0; match nodes[1].node.update_channel_config( - channel_to_update_counterparty, &[channel_to_update.0], &invalid_config, + channel_to_update_counterparty, + &[channel_to_update.0], + &invalid_config, ) { - Err(APIError::APIMisuseError{ .. }) => {}, + Err(APIError::APIMisuseError { .. }) => {}, _ => panic!("unexpected result applying invalid cltv_expiry_delta"), } // Increase the base fee which should trigger a new ChannelUpdate. - let mut config = nodes[1].node.list_usable_channels().iter() - .find(|channel| channel.channel_id == channel_to_update.0).unwrap() - .config.unwrap(); + let mut config = nodes[1] + .node + .list_usable_channels() + .iter() + .find(|channel| channel.channel_id == channel_to_update.0) + .unwrap() + .config + .unwrap(); config.forwarding_fee_base_msat = u32::max_value(); let msg = update_and_get_channel_update(&config.clone(), true, None, false).unwrap(); // The old policy should still be in effect until a new block is connected. - send_along_route_with_secret(&nodes[0], route.clone(), &[&[&nodes[1], &nodes[2]]], PAYMENT_AMT, - payment_hash, payment_secret); + send_along_route_with_secret( + &nodes[0], + route.clone(), + &[&[&nodes[1], &nodes[2]]], + PAYMENT_AMT, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); // Connect a block, which should expire the previous config, leading to a failure when @@ -983,11 +1833,23 @@ fn do_test_onion_failure_stale_channel_update(announce_for_forwarding: bool) { let config_after_restart = { let chan_1_monitor_serialized = get_monitor!(nodes[1], other_channel.3).encode(); let chan_2_monitor_serialized = get_monitor!(nodes[1], channel_to_update.0).encode(); - reload_node!(nodes[1], nodes[1].node.get_current_default_configuration().clone(), &nodes[1].node.encode(), - &[&chan_1_monitor_serialized, &chan_2_monitor_serialized], persister, chain_monitor, channel_manager_1_deserialized); - nodes[1].node.list_channels().iter() - .find(|channel| channel.channel_id == channel_to_update.0).unwrap() - .config.unwrap() + reload_node!( + nodes[1], + nodes[1].node.get_current_default_configuration().clone(), + &nodes[1].node.encode(), + &[&chan_1_monitor_serialized, &chan_2_monitor_serialized], + persister, + chain_monitor, + channel_manager_1_deserialized + ); + nodes[1] + .node + .list_channels() + .iter() + .find(|channel| channel.channel_id == channel_to_update.0) + .unwrap() + .config + .unwrap() }; assert_eq!(config, config_after_restart); } @@ -1018,9 +1880,12 @@ fn test_always_create_tlv_format_onion_payloads() { create_announced_chan_between_nodes(&nodes, 0, 1); create_announced_chan_between_nodes(&nodes, 1, 2); - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(Bolt11InvoiceFeatures::empty()).unwrap(); - let (route, _payment_hash, _payment_preimage, _payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 40000); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(Bolt11InvoiceFeatures::empty()) + .unwrap(); + let (route, _payment_hash, _payment_preimage, _payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 40000); let hops = &route.paths[0].hops; // Asserts that the first hop to `node[1]` signals no support for variable length onions. @@ -1031,21 +1896,33 @@ fn test_always_create_tlv_format_onion_payloads() { let cur_height = nodes[0].best_block_info().1 + 1; let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, &recipient_onion_fields, cur_height, &None, None, None).unwrap(); + &route.paths[0], + 40000, + &recipient_onion_fields, + cur_height, + &None, + None, + None, + ) + .unwrap(); match onion_payloads[0] { - msgs::OutboundOnionPayload::Forward {..} => {}, - _ => { panic!( + msgs::OutboundOnionPayload::Forward { .. } => {}, + _ => { + panic!( "Should have generated a `msgs::OnionHopDataFormat::NonFinalNode` payload for `hops[0]`, despite that the features signals no support for variable length onions" - )} + ) + }, } match onion_payloads[1] { - msgs::OutboundOnionPayload::Receive {..} => {}, - _ => {panic!( + msgs::OutboundOnionPayload::Receive { .. } => {}, + _ => { + panic!( "Should have generated a `msgs::OnionHopDataFormat::FinalNode` payload for `hops[1]`, despite that the features signals no support for variable length onions" - )} + ) + }, } } @@ -1055,14 +1932,17 @@ fn test_trampoline_onion_payload_serialization() { let trampoline_payload = OutboundTrampolinePayload::Forward { amt_to_forward: 100000000, outgoing_cltv_value: 800000, - outgoing_node_id: PublicKey::from_slice(&>::from_hex("02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145").unwrap()).unwrap(), + outgoing_node_id: PublicKey::from_slice( + &>::from_hex( + "02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145", + ) + .unwrap(), + ) + .unwrap(), }; - let slice_to_hex = |slice: &[u8]| { - slice.iter() - .map(|b| format!("{:02x}", b).to_string()) - .collect::() - }; + let slice_to_hex = + |slice: &[u8]| slice.iter().map(|b| format!("{:02x}", b).to_string()).collect::(); let carol_payload_hex = slice_to_hex(&trampoline_payload.encode()); assert_eq!(carol_payload_hex, "2e020405f5e10004030c35000e2102edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145"); @@ -1081,7 +1961,13 @@ fn test_trampoline_onion_payload_assembly_values() { hops: vec![ // Bob RouteHop { - pubkey: PublicKey::from_slice(&>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c", + ) + .unwrap(), + ) + .unwrap(), node_features: NodeFeatures::empty(), short_channel_id: 0, channel_features: ChannelFeatures::empty(), @@ -1089,10 +1975,15 @@ fn test_trampoline_onion_payload_assembly_values() { cltv_expiry_delta: 24, maybe_announced_channel: false, }, - // Carol RouteHop { - pubkey: PublicKey::from_slice(&>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007", + ) + .unwrap(), + ) + .unwrap(), node_features: NodeFeatures::empty(), short_channel_id: (572330 << 40) + (42 << 16) + 2821, channel_features: ChannelFeatures::empty(), @@ -1105,43 +1996,90 @@ fn test_trampoline_onion_payload_assembly_values() { trampoline_hops: vec![ // Carol's pubkey TrampolineHop { - pubkey: PublicKey::from_slice(&>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007", + ) + .unwrap(), + ) + .unwrap(), node_features: Features::empty(), fee_msat: 2_500, cltv_expiry_delta: 24, }, // Dave's pubkey (the intro node needs to be duplicated) TrampolineHop { - pubkey: PublicKey::from_slice(&>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991", + ) + .unwrap(), + ) + .unwrap(), node_features: Features::empty(), fee_msat: 150_500, cltv_expiry_delta: 36, - } + }, ], hops: vec![ // Dave's blinded node id BlindedHop { - blinded_node_id: PublicKey::from_slice(&>::from_hex("0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be").unwrap()).unwrap(), + blinded_node_id: PublicKey::from_slice( + &>::from_hex( + "0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be", + ) + .unwrap(), + ) + .unwrap(), encrypted_payload: vec![], }, // Eve's blinded node id BlindedHop { - blinded_node_id: PublicKey::from_slice(&>::from_hex("020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22").unwrap()).unwrap(), + blinded_node_id: PublicKey::from_slice( + &>::from_hex( + "020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22", + ) + .unwrap(), + ) + .unwrap(), encrypted_payload: vec![], - } + }, ], - blinding_point: PublicKey::from_slice(&>::from_hex("02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e").unwrap()).unwrap(), + blinding_point: PublicKey::from_slice( + &>::from_hex( + "02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e", + ) + .unwrap(), + ) + .unwrap(), excess_final_cltv_expiry_delta: 0, - final_value_msat: amt_msat + final_value_msat: amt_msat, }), }; assert_eq!(path.fee_msat(), 156_000); assert_eq!(path.final_value_msat(), amt_msat); assert_eq!(path.final_cltv_expiry_delta(), None); - let payment_secret = PaymentSecret(SecretKey::from_slice(&>::from_hex("7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da").unwrap()).unwrap().secret_bytes()); + let payment_secret = PaymentSecret( + SecretKey::from_slice( + &>::from_hex( + "7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da", + ) + .unwrap(), + ) + .unwrap() + .secret_bytes(), + ); let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); - let (trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils::build_trampoline_onion_payloads(&path.blinded_tail.as_ref().unwrap(), amt_msat, &recipient_onion_fields, cur_height, &None).unwrap(); + let (trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = + onion_utils::build_trampoline_onion_payloads( + &path.blinded_tail.as_ref().unwrap(), + amt_msat, + &recipient_onion_fields, + cur_height, + &None, + ) + .unwrap(); assert_eq!(trampoline_payloads.len(), 3); assert_eq!(outer_total_msat, 150_153_000); assert_eq!(outer_starting_htlc_offset, 800_060); @@ -1149,7 +2087,13 @@ fn test_trampoline_onion_payload_assembly_values() { let trampoline_carol_payload = &trampoline_payloads[0]; let trampoline_dave_payload = &trampoline_payloads[1]; let trampoline_eve_payload = &trampoline_payloads[2]; - if let OutboundTrampolinePayload::BlindedReceive { sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, .. } = trampoline_eve_payload { + if let OutboundTrampolinePayload::BlindedReceive { + sender_intended_htlc_amt_msat, + total_msat, + cltv_expiry_height, + .. + } = trampoline_eve_payload + { assert_eq!(sender_intended_htlc_amt_msat, &150_000_000); assert_eq!(total_msat, &150_000_000); assert_eq!(cltv_expiry_height, &800_000); @@ -1157,11 +2101,14 @@ fn test_trampoline_onion_payload_assembly_values() { panic!("Eve Trampoline payload must be BlindedReceive"); } - if let OutboundTrampolinePayload::BlindedForward { .. } = trampoline_dave_payload {} else { + if let OutboundTrampolinePayload::BlindedForward { .. } = trampoline_dave_payload { + } else { panic!("Dave Trampoline payload must be BlindedForward"); } - if let OutboundTrampolinePayload::Forward { amt_to_forward, outgoing_cltv_value, .. } = trampoline_carol_payload { + if let OutboundTrampolinePayload::Forward { amt_to_forward, outgoing_cltv_value, .. } = + trampoline_carol_payload + { assert_eq!(amt_to_forward, &150_150_500); assert_eq!(outgoing_cltv_value, &800_036); } else { @@ -1170,33 +2117,56 @@ fn test_trampoline_onion_payload_assembly_values() { // all dummy values let secp_ctx = Secp256k1::new(); - let session_priv = SecretKey::from_slice(&>::from_hex("a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99").unwrap()).unwrap(); + let session_priv = SecretKey::from_slice( + &>::from_hex("a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99") + .unwrap(), + ) + .unwrap(); let prng_seed = onion_utils::gen_pad_from_shared_secret(&session_priv.secret_bytes()); let payment_hash = PaymentHash(session_priv.secret_bytes()); - let onion_keys = construct_trampoline_onion_keys(&secp_ctx, &path.blinded_tail.as_ref().unwrap(), &session_priv); + let onion_keys = construct_trampoline_onion_keys( + &secp_ctx, + &path.blinded_tail.as_ref().unwrap(), + &session_priv, + ); let trampoline_packet = construct_trampoline_onion_packet( trampoline_payloads, onion_keys, prng_seed, &payment_hash, None, - ).unwrap(); + ) + .unwrap(); - let (outer_payloads, total_msat, total_htlc_offset) = onion_utils::build_onion_payloads(&path, outer_total_msat, &recipient_onion_fields, outer_starting_htlc_offset, &None, None, Some(trampoline_packet)).unwrap(); + let (outer_payloads, total_msat, total_htlc_offset) = onion_utils::build_onion_payloads( + &path, + outer_total_msat, + &recipient_onion_fields, + outer_starting_htlc_offset, + &None, + None, + Some(trampoline_packet), + ) + .unwrap(); assert_eq!(outer_payloads.len(), 2); assert_eq!(total_msat, 150_156_000); assert_eq!(total_htlc_offset, 800_084); let outer_bob_payload = &outer_payloads[0]; let outer_carol_payload = &outer_payloads[1]; - if let OutboundOnionPayload::TrampolineEntrypoint { amt_to_forward, outgoing_cltv_value, .. } = outer_carol_payload { + if let OutboundOnionPayload::TrampolineEntrypoint { + amt_to_forward, outgoing_cltv_value, .. + } = outer_carol_payload + { assert_eq!(amt_to_forward, &150_153_000); assert_eq!(outgoing_cltv_value, &800_060); } else { panic!("Carol payload must be TrampolineEntrypoint"); } - if let OutboundOnionPayload::Forward { amt_to_forward, outgoing_cltv_value, .. } = outer_bob_payload { + if let OutboundOnionPayload::Forward { amt_to_forward, outgoing_cltv_value, .. } = + outer_bob_payload + { assert_eq!(amt_to_forward, &150_153_000); assert_eq!(outgoing_cltv_value, &800_084); } else { @@ -1214,7 +2184,8 @@ fn test_trampoline_onion_payload_assembly_values() { &None, None, prng_seed, - ).unwrap(); + ) + .unwrap(); assert_eq!(total_msat_combined, total_msat); assert_eq!(total_htlc_offset_combined, total_htlc_offset); } @@ -1226,7 +2197,13 @@ fn test_trampoline_onion_payload_construction_vectors() { let trampoline_payload_carol = OutboundTrampolinePayload::Forward { amt_to_forward: 150_150_500, outgoing_cltv_value: 800_036, - outgoing_node_id: PublicKey::from_slice(&>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()).unwrap(), + outgoing_node_id: PublicKey::from_slice( + &>::from_hex( + "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991", + ) + .unwrap(), + ) + .unwrap(), }; let carol_payload = trampoline_payload_carol.encode().to_lower_hex_string(); assert_eq!(carol_payload, "2e020408f31d6404030c35240e21032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991"); @@ -1250,10 +2227,19 @@ fn test_trampoline_onion_payload_construction_vectors() { let eve_payload = trampoline_payload_eve.encode().to_lower_hex_string(); assert_eq!(eve_payload, "e4020408f0d18004030c35000ad1bcd747394fbd4d99588da075a623316e15a576df5bc785cccc7cd6ec7b398acce6faf520175f9ec920f2ef261cdb83dc28cc3a0eeb970107b3306489bf771ef5b1213bca811d345285405861d08a655b6c237fa247a8b4491beee20c878a60e9816492026d8feb9dafa84585b253978db6a0aa2945df5ef445c61e801fb82f43d5f00716baf9fc9b3de50bc22950a36bda8fc27bfb1242e5860c7e687438d4133e058770361a19b6c271a2a07788d34dccc27e39b9829b061a4d960eac4a2c2b0f4de506c24f9af3868c0aff6dda27281c120408f0d180"); - let trampoline_payloads = vec![trampoline_payload_carol, trampoline_payload_dave, trampoline_payload_eve]; - - let trampoline_session_key = SecretKey::from_slice(&>::from_hex("a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99").unwrap()).unwrap(); - let associated_data_slice = SecretKey::from_slice(&>::from_hex("e89bc505e84aaca09613833fc58c9069078fb43bfbea0488f34eec9db99b5f82").unwrap()).unwrap(); + let trampoline_payloads = + vec![trampoline_payload_carol, trampoline_payload_dave, trampoline_payload_eve]; + + let trampoline_session_key = SecretKey::from_slice( + &>::from_hex("a64feb81abd58e473df290e9e1c07dc3e56114495cadf33191f44ba5448ebe99") + .unwrap(), + ) + .unwrap(); + let associated_data_slice = SecretKey::from_slice( + &>::from_hex("e89bc505e84aaca09613833fc58c9069078fb43bfbea0488f34eec9db99b5f82") + .unwrap(), + ) + .unwrap(); let associated_data = PaymentHash(associated_data_slice.secret_bytes()); let trampoline_hops = Path { @@ -1262,39 +2248,80 @@ fn test_trampoline_onion_payload_construction_vectors() { trampoline_hops: vec![ // Carol's pubkey TrampolineHop { - pubkey: PublicKey::from_slice(&>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007", + ) + .unwrap(), + ) + .unwrap(), node_features: Features::empty(), fee_msat: 0, cltv_expiry_delta: 0, }, // Dave's pubkey (the intro node needs to be duplicated) TrampolineHop { - pubkey: PublicKey::from_slice(&>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991", + ) + .unwrap(), + ) + .unwrap(), node_features: Features::empty(), fee_msat: 0, cltv_expiry_delta: 0, - } + }, ], hops: vec![ // Dave's blinded node id BlindedHop { - blinded_node_id: PublicKey::from_slice(&>::from_hex("0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be").unwrap()).unwrap(), + blinded_node_id: PublicKey::from_slice( + &>::from_hex( + "0295d40514096a8be54859e7dfe947b376eaafea8afe5cb4eb2c13ff857ed0b4be", + ) + .unwrap(), + ) + .unwrap(), encrypted_payload: vec![], }, // Eve's blinded node id BlindedHop { - blinded_node_id: PublicKey::from_slice(&>::from_hex("020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22").unwrap()).unwrap(), + blinded_node_id: PublicKey::from_slice( + &>::from_hex( + "020e2dbadcc2005e859819ddebbe88a834ae8a6d2b049233c07335f15cd1dc5f22", + ) + .unwrap(), + ) + .unwrap(), encrypted_payload: vec![], - } + }, ], - blinding_point: PublicKey::from_slice(&>::from_hex("02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e").unwrap()).unwrap(), + blinding_point: PublicKey::from_slice( + &>::from_hex( + "02988face71e92c345a068f740191fd8e53be14f0bb957ef730d3c5f76087b960e", + ) + .unwrap(), + ) + .unwrap(), excess_final_cltv_expiry_delta: 0, - final_value_msat: 0 + final_value_msat: 0, }), }; - let trampoline_onion_keys = construct_trampoline_onion_keys(&Secp256k1::new(), &trampoline_hops.blinded_tail.unwrap(), &trampoline_session_key); - let trampoline_onion_packet = construct_trampoline_onion_packet(trampoline_payloads, trampoline_onion_keys, [0u8; 32], &associated_data, None).unwrap(); + let trampoline_onion_keys = construct_trampoline_onion_keys( + &Secp256k1::new(), + &trampoline_hops.blinded_tail.unwrap(), + &trampoline_session_key, + ); + let trampoline_onion_packet = construct_trampoline_onion_packet( + trampoline_payloads, + trampoline_onion_keys, + [0u8; 32], + &associated_data, + None, + ) + .unwrap(); let trampoline_onion_packet_hex = trampoline_onion_packet.encode().to_lower_hex_string(); assert_eq!(trampoline_onion_packet_hex, "0002bc59a9abc893d75a8d4f56a6572f9a3507323a8de22abe0496ea8d37da166a8b4bba0e560f1a9deb602bfd98fe9167141d0b61d669df90c0149096d505b85d3d02806e6c12caeb308b878b6bc7f1b15839c038a6443cd3bec3a94c2293165375555f6d7720862b525930f41fddcc02260d197abd93fb58e60835fd97d9dc14e7979c12f59df08517b02e3e4d50e1817de4271df66d522c4e9675df71c635c4176a8381bc22b342ff4e9031cede87f74cc039fca74aa0a3786bc1db2e158a9a520ecb99667ef9a6bbfaf5f0e06f81c27ca48134ba2103229145937c5dc7b8ecc5201d6aeb592e78faa3c05d3a035df77628f0be9b1af3ef7d386dd5cc87b20778f47ebd40dbfcf12b9071c5d7112ab84c3e0c5c14867e684d09a18bc93ac47d73b7343e3403ef6e3b70366835988920e7d772c3719d3596e53c29c4017cb6938421a557ce81b4bb26701c25bf622d4c69f1359dc85857a375c5c74987a4d3152f66987001c68a50c4bf9e0b1dab4ad1a64b0535319bbf6c4fbe4f9c50cb65f5ef887bfb91b0a57c0f86ba3d91cbeea1607fb0c12c6c75d03bbb0d3a3019c40597027f5eebca23083e50ec79d41b1152131853525bf3fc13fb0be62c2e3ce733f59671eee5c4064863fb92ae74be9ca68b9c716f9519fd268478ee27d91d466b0de51404de3226b74217d28250ead9d2c95411e0230570f547d4cc7c1d589791623131aa73965dccc5aa17ec12b442215ce5d346df664d799190df5dd04a13"); @@ -1305,24 +2332,38 @@ fn test_trampoline_onion_payload_construction_vectors() { amt_to_forward: 150153000, outgoing_cltv_value: 800060, }, - // Carol OutboundOnionPayload::TrampolineEntrypoint { amt_to_forward: 150153000, outgoing_cltv_value: 800060, trampoline_packet: trampoline_onion_packet, - multipath_trampoline_data: Some(FinalOnionHopData{ - payment_secret: PaymentSecret(SecretKey::from_slice(&>::from_hex("7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da").unwrap()).unwrap().secret_bytes()), - total_msat: 150153000 + multipath_trampoline_data: Some(FinalOnionHopData { + payment_secret: PaymentSecret( + SecretKey::from_slice( + &>::from_hex( + "7494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da", + ) + .unwrap(), + ) + .unwrap() + .secret_bytes(), + ), + total_msat: 150153000, }), - } + }, ]; let outer_hops = Path { hops: vec![ // Bob RouteHop { - pubkey: PublicKey::from_slice(&>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c", + ) + .unwrap(), + ) + .unwrap(), node_features: NodeFeatures::empty(), short_channel_id: 0, channel_features: ChannelFeatures::empty(), @@ -1330,10 +2371,15 @@ fn test_trampoline_onion_payload_construction_vectors() { cltv_expiry_delta: 0, maybe_announced_channel: false, }, - // Carol RouteHop { - pubkey: PublicKey::from_slice(&>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()).unwrap(), + pubkey: PublicKey::from_slice( + &>::from_hex( + "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007", + ) + .unwrap(), + ) + .unwrap(), node_features: NodeFeatures::empty(), short_channel_id: 0, channel_features: ChannelFeatures::empty(), @@ -1351,16 +2397,27 @@ fn test_trampoline_onion_payload_construction_vectors() { let carol_payload = outer_payloads[1].encode().to_lower_hex_string(); assert_eq!(carol_payload, "fd0255020408f3272804030c353c08247494b65bc092b48a75465e43e29be807eb2cc535ce8aaba31012b8ff1ceac5da08f3272814fd02200002bc59a9abc893d75a8d4f56a6572f9a3507323a8de22abe0496ea8d37da166a8b4bba0e560f1a9deb602bfd98fe9167141d0b61d669df90c0149096d505b85d3d02806e6c12caeb308b878b6bc7f1b15839c038a6443cd3bec3a94c2293165375555f6d7720862b525930f41fddcc02260d197abd93fb58e60835fd97d9dc14e7979c12f59df08517b02e3e4d50e1817de4271df66d522c4e9675df71c635c4176a8381bc22b342ff4e9031cede87f74cc039fca74aa0a3786bc1db2e158a9a520ecb99667ef9a6bbfaf5f0e06f81c27ca48134ba2103229145937c5dc7b8ecc5201d6aeb592e78faa3c05d3a035df77628f0be9b1af3ef7d386dd5cc87b20778f47ebd40dbfcf12b9071c5d7112ab84c3e0c5c14867e684d09a18bc93ac47d73b7343e3403ef6e3b70366835988920e7d772c3719d3596e53c29c4017cb6938421a557ce81b4bb26701c25bf622d4c69f1359dc85857a375c5c74987a4d3152f66987001c68a50c4bf9e0b1dab4ad1a64b0535319bbf6c4fbe4f9c50cb65f5ef887bfb91b0a57c0f86ba3d91cbeea1607fb0c12c6c75d03bbb0d3a3019c40597027f5eebca23083e50ec79d41b1152131853525bf3fc13fb0be62c2e3ce733f59671eee5c4064863fb92ae74be9ca68b9c716f9519fd268478ee27d91d466b0de51404de3226b74217d28250ead9d2c95411e0230570f547d4cc7c1d589791623131aa73965dccc5aa17ec12b442215ce5d346df664d799190df5dd04a13"); - let outer_session_key = SecretKey::from_slice(&>::from_hex("4f777e8dac16e6dfe333066d9efb014f7a51d11762ff76eca4d3a95ada99ba3e").unwrap()).unwrap(); - let outer_onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &outer_hops, &outer_session_key); - let outer_onion_prng_seed = onion_utils::gen_pad_from_shared_secret(&outer_session_key.secret_bytes()); - let outer_onion_packet = onion_utils::construct_onion_packet(outer_payloads, outer_onion_keys, outer_onion_prng_seed, &associated_data).unwrap(); + let outer_session_key = SecretKey::from_slice( + &>::from_hex("4f777e8dac16e6dfe333066d9efb014f7a51d11762ff76eca4d3a95ada99ba3e") + .unwrap(), + ) + .unwrap(); + let outer_onion_keys = + onion_utils::construct_onion_keys(&Secp256k1::new(), &outer_hops, &outer_session_key); + let outer_onion_prng_seed = + onion_utils::gen_pad_from_shared_secret(&outer_session_key.secret_bytes()); + let outer_onion_packet = onion_utils::construct_onion_packet( + outer_payloads, + outer_onion_keys, + outer_onion_prng_seed, + &associated_data, + ) + .unwrap(); let outer_onion_packet_hex = outer_onion_packet.encode().to_lower_hex_string(); assert_eq!(outer_onion_packet_hex, "00025fd60556c134ae97e4baedba220a644037754ee67c54fd05e93bf40c17cbb73362fb9dee96001ff229945595b6edb59437a6bc143406d3f90f749892a84d8d430c6890437d26d5bfc599d565316ef51347521075bbab87c59c57bcf20af7e63d7192b46cf171e4f73cb11f9f603915389105d91ad630224bea95d735e3988add1e24b5bf28f1d7128db64284d90a839ba340d088c74b1fb1bd21136b1809428ec5399c8649e9bdf92d2dcfc694deae5046fa5b2bdf646847aaad73f5e95275763091c90e71031cae1f9a770fdea559642c9c02f424a2a28163dd0957e3874bd28a97bec67d18c0321b0e68bc804aa8345b17cb626e2348ca06c8312a167c989521056b0f25c55559d446507d6c491d50605cb79fa87929ce64b0a9860926eeaec2c431d926a1cadb9a1186e4061cb01671a122fc1f57602cbef06d6c194ec4b715c2e3dd4120baca3172cd81900b49fef857fb6d6afd24c983b608108b0a5ac0c1c6c52011f23b8778059ffadd1bb7cd06e2525417365f485a7fd1d4a9ba3818ede7cdc9e71afee8532252d08e2531ca52538655b7e8d912f7ec6d37bbcce8d7ec690709dbf9321e92c565b78e7fe2c22edf23e0902153d1ca15a112ad32fb19695ec65ce11ddf670da7915f05ad4b86c154fb908cb567315d1124f303f75fa075ebde8ef7bb12e27737ad9e4924439097338ea6d7a6fc3721b88c9b830a34e8d55f4c582b74a3895cc848fe57f4fe29f115dabeb6b3175be15d94408ed6771109cfaf57067ae658201082eae7605d26b1449af4425ae8e8f58cdda5c6265f1fd7a386fc6cea3074e4f25b909b96175883676f7610a00fdf34df9eb6c7b9a4ae89b839c69fd1f285e38cdceb634d782cc6d81179759bc9fd47d7fd060470d0b048287764c6837963274e708314f017ac7dc26d0554d59bfcfd3136225798f65f0b0fea337c6b256ebbb63a90b994c0ab93fd8b1d6bd4c74aebe535d6110014cd3d525394027dfe8faa98b4e9b2bee7949eb1961f1b026791092f84deea63afab66603dbe9b6365a102a1fef2f6b9744bc1bb091a8da9130d34d4d39f25dbad191649cfb67e10246364b7ce0c6ec072f9690cabb459d9fda0c849e17535de4357e9907270c75953fca3c845bb613926ecf73205219c7057a4b6bb244c184362bb4e2f24279dc4e60b94a5b1ec11c34081a628428ba5646c995b9558821053ba9c84a05afbf00dabd60223723096516d2f5668f3ec7e11612b01eb7a3a0506189a2272b88e89807943adb34291a17f6cb5516ffd6f945a1c42a524b21f096d66f350b1dad4db455741ae3d0e023309fbda5ef55fb0dc74f3297041448b2be76c525141963934c6afc53d263fb7836626df502d7c2ee9e79cbbd87afd84bbb8dfbf45248af3cd61ad5fac827e7683ca4f91dfad507a8eb9c17b2c9ac5ec051fe645a4a6cb37136f6f19b611e0ea8da7960af2d779507e55f57305bc74b7568928c5dd5132990fe54c22117df91c257d8c7b61935a018a28c1c3b17bab8e4294fa699161ec21123c9fc4e71079df31f300c2822e1246561e04765d3aab333eafd026c7431ac7616debb0e022746f4538e1c6348b600c988eeb2d051fc60c468dca260a84c79ab3ab8342dc345a764672848ea234e17332bc124799daf7c5fcb2e2358514a7461357e1c19c802c5ee32deccf1776885dd825bedd5f781d459984370a6b7ae885d4483a76ddb19b30f47ed47cd56aa5a079a89793dbcad461c59f2e002067ac98dd5a534e525c9c46c2af730741bf1f8629357ec0bfc0bc9ecb31af96777e507648ff4260dc3673716e098d9111dfd245f1d7c55a6de340deb8bd7a053e5d62d760f184dc70ca8fa255b9023b9b9aedfb6e419a5b5951ba0f83b603793830ee68d442d7b88ee1bbf6bbd1bcd6f68cc1af"); } fn do_test_fail_htlc_backwards_with_reason(failure_code: FailureCode) { - let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); @@ -1369,9 +2426,17 @@ fn do_test_fail_htlc_backwards_with_reason(failure_code: FailureCode) { create_announced_chan_between_nodes(&nodes, 0, 1); let payment_amount = 100_000; - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_amount); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], payment_amount); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1383,13 +2448,28 @@ fn do_test_fail_htlc_backwards_with_reason(failure_code: FailureCode) { expect_payment_claimable!(nodes[1], payment_hash, payment_secret, payment_amount); nodes[1].node.fail_htlc_backwards_with_reason(&payment_hash, failure_code); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let (update_fail_htlc, commitment_signed) = match events[0] { - MessageSendEvent::UpdateHTLCs { node_id: _, channel_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + MessageSendEvent::UpdateHTLCs { + node_id: _, + channel_id: _, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { assert!(update_add_htlcs.is_empty()); assert!(update_fulfill_htlcs.is_empty()); assert_eq!(update_fail_htlcs.len(), 1); @@ -1411,17 +2491,20 @@ fn do_test_fail_htlc_backwards_with_reason(failure_code: FailureCode) { htlc_msat_height_data.extend_from_slice(&CHAN_CONFIRM_DEPTH.to_be_bytes()); htlc_msat_height_data }, - FailureCode::InvalidOnionPayload(data) => { - match data { - Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(), - None => Vec::new(), - } - } + FailureCode::InvalidOnionPayload(data) => match data { + Some((typ, offset)) => [BigSize(typ).encode(), offset.encode()].concat(), + None => Vec::new(), + }, }; let failure_code = failure_code.into(); - expect_payment_failed!(nodes[0], payment_hash, failure_code.is_permanent(), failure_code, failure_data); - + expect_payment_failed!( + nodes[0], + payment_hash, + failure_code.is_permanent(), + failure_code, + failure_data + ); } #[test] @@ -1438,41 +2521,49 @@ macro_rules! get_phantom_route { let phantom_pubkey = $nodes[1].keys_manager.get_node_id(Recipient::PhantomNode).unwrap(); let phantom_route_hint = $nodes[1].node.get_phantom_route_hints(); let payment_params = PaymentParameters::from_node_id(phantom_pubkey, TEST_FINAL_CLTV) - .with_bolt11_features($nodes[1].node.bolt11_invoice_features()).unwrap() + .with_bolt11_features($nodes[1].node.bolt11_invoice_features()) + .unwrap() .with_route_hints(vec![RouteHint(vec![ - RouteHintHop { - src_node_id: $nodes[0].node.get_our_node_id(), - short_channel_id: $channel.0.contents.short_channel_id, - fees: RoutingFees { - base_msat: $channel.0.contents.fee_base_msat, - proportional_millionths: $channel.0.contents.fee_proportional_millionths, - }, - cltv_expiry_delta: $channel.0.contents.cltv_expiry_delta, - htlc_minimum_msat: None, - htlc_maximum_msat: None, + RouteHintHop { + src_node_id: $nodes[0].node.get_our_node_id(), + short_channel_id: $channel.0.contents.short_channel_id, + fees: RoutingFees { + base_msat: $channel.0.contents.fee_base_msat, + proportional_millionths: $channel.0.contents.fee_proportional_millionths, }, - RouteHintHop { - src_node_id: phantom_route_hint.real_node_pubkey, - short_channel_id: phantom_route_hint.phantom_scid, - fees: RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }, - cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - } - ])]).unwrap(); + cltv_expiry_delta: $channel.0.contents.cltv_expiry_delta, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + RouteHintHop { + src_node_id: phantom_route_hint.real_node_pubkey, + short_channel_id: phantom_route_hint.phantom_scid, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, + cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + ])]) + .unwrap(); let scorer = test_utils::TestScorer::new(); let network_graph = $nodes[0].network_graph.read_only(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, $amt); - (get_route( - &$nodes[0].node.get_our_node_id(), &route_params, &network_graph, - Some(&$nodes[0].node.list_usable_channels().iter().collect::>()), - $nodes[0].logger, &scorer, &Default::default(), &[0u8; 32] - ).unwrap(), phantom_route_hint.phantom_scid) - } -}} + ( + get_route( + &$nodes[0].node.get_our_node_id(), + &route_params, + &network_graph, + Some(&$nodes[0].node.list_usable_channels().iter().collect::>()), + $nodes[0].logger, + &scorer, + &Default::default(), + &[0u8; 32], + ) + .unwrap(), + phantom_route_hint.phantom_scid, + ) + }}; +} #[test] fn test_phantom_onion_hmac_failure() { @@ -1485,12 +2576,20 @@ fn test_phantom_onion_hmac_failure() { // Get the route. let recv_value_msat = 10_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); let (route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel); // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1506,10 +2605,12 @@ fn test_phantom_onion_hmac_failure() { let mut pending_forward = forward_htlcs.get_mut(&phantom_scid).unwrap(); match pending_forward[0] { HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - forward_info: PendingHTLCInfo { - routing: PendingHTLCRouting::Forward { ref mut onion_packet, .. }, - .. - }, .. + forward_info: + PendingHTLCInfo { + routing: PendingHTLCRouting::Forward { ref mut onion_packet, .. }, + .. + }, + .. }) => { onion_packet.hmac[onion_packet.hmac.len() - 1] ^= 1; Sha256::hash(&onion_packet.hop_data).to_byte_array().to_vec() @@ -1518,7 +2619,10 @@ fn test_phantom_onion_hmac_failure() { } }; nodes[1].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); nodes[1].node.process_pending_htlc_forwards(); let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(&nodes[1], 1); @@ -1546,14 +2650,22 @@ fn test_phantom_invalid_onion_payload() { // Get the route. let recv_value_msat = 10_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); let (route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel); // We'll use the session priv later when constructing an invalid onion packet. let session_priv = [3; 32]; *nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some(session_priv); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1568,25 +2680,44 @@ fn test_phantom_invalid_onion_payload() { for f in pending_forwards.iter_mut() { match f { &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - forward_info: PendingHTLCInfo { - routing: PendingHTLCRouting::Forward { ref mut onion_packet, .. }, - .. - }, .. + forward_info: + PendingHTLCInfo { + routing: PendingHTLCRouting::Forward { ref mut onion_packet, .. }, + .. + }, + .. }) => { // Construct the onion payloads for the entire route and an invalid amount. let height = nodes[0].best_block_info().1; let session_priv = SecretKey::from_slice(&session_priv).unwrap(); - let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv); + let mut onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ); let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads( - &route.paths[0], msgs::MAX_VALUE_MSAT + 1, - &recipient_onion_fields, height + 1, &None, None, None).unwrap(); + &route.paths[0], + msgs::MAX_VALUE_MSAT + 1, + &recipient_onion_fields, + height + 1, + &None, + None, + None, + ) + .unwrap(); // We only want to construct the onion packet for the last hop, not the entire route, so // remove the first hop's payload and its keys. onion_keys.remove(0); onion_payloads.remove(0); - let new_onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + let new_onion_packet = onion_utils::construct_onion_packet( + onion_payloads, + onion_keys, + [0; 32], + &payment_hash, + ) + .unwrap(); onion_packet.hop_data = new_onion_packet.hop_data; onion_packet.hmac = new_onion_packet.hmac; }, @@ -1595,7 +2726,10 @@ fn test_phantom_invalid_onion_payload() { } } nodes[1].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); nodes[1].node.process_pending_htlc_forwards(); let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(&nodes[1], 1); @@ -1624,12 +2758,20 @@ fn test_phantom_final_incorrect_cltv_expiry() { // Get the route. let recv_value_msat = 10_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); let (route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel); // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1644,7 +2786,8 @@ fn test_phantom_final_incorrect_cltv_expiry() { for f in pending_forwards.iter_mut() { match f { &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - forward_info: PendingHTLCInfo { ref mut outgoing_cltv_value, .. }, .. + forward_info: PendingHTLCInfo { ref mut outgoing_cltv_value, .. }, + .. }) => { *outgoing_cltv_value -= 1; }, @@ -1653,7 +2796,10 @@ fn test_phantom_final_incorrect_cltv_expiry() { } } nodes[1].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); nodes[1].node.process_pending_htlc_forwards(); let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(&nodes[1], 1); @@ -1682,15 +2828,23 @@ fn test_phantom_failure_too_low_cltv() { // Get the route. let recv_value_msat = 10_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel); // Modify the route to have a too-low cltv. route.paths[0].hops[1].cltv_expiry_delta = 5; // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1700,7 +2854,10 @@ fn test_phantom_failure_too_low_cltv() { expect_pending_htlcs_forwardable_ignore!(nodes[1]); nodes[1].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); nodes[1].node.process_pending_htlc_forwards(); let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(&nodes[1], 1); @@ -1711,9 +2868,7 @@ fn test_phantom_failure_too_low_cltv() { // Ensure the payment fails with the expected error. let mut error_data = recv_value_msat.to_be_bytes().to_vec(); - error_data.extend_from_slice( - &nodes[0].node.best_block.read().unwrap().height.to_be_bytes(), - ); + error_data.extend_from_slice(&nodes[0].node.best_block.read().unwrap().height.to_be_bytes()); let mut fail_conditions = PaymentFailedConditions::new() .blamed_scid(phantom_scid) .expected_htlc_error_data(LocalHTLCFailureReason::IncorrectPaymentDetails, &error_data); @@ -1733,12 +2888,20 @@ fn test_phantom_failure_modified_cltv() { // Get the route. let recv_value_msat = 10_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel); // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1784,12 +2947,20 @@ fn test_phantom_failure_expires_too_soon() { // Get the route. let recv_value_msat = 10_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_value_msat)); let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel); // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1830,12 +3001,20 @@ fn test_phantom_failure_too_low_recv_amt() { // Get the route with a too-low amount. let recv_amt_msat = 10_000; let bad_recv_amt_msat = recv_amt_msat - 10; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_amt_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_amt_msat)); let (mut route, phantom_scid) = get_phantom_route!(nodes, bad_recv_amt_msat, channel); // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1847,7 +3026,10 @@ fn test_phantom_failure_too_low_recv_amt() { nodes[1].node.process_pending_htlc_forwards(); expect_pending_htlcs_forwardable_ignore!(nodes[1]); nodes[1].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }] + ); nodes[1].node.process_pending_htlc_forwards(); let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(&nodes[1], 1); @@ -1877,9 +3059,11 @@ fn do_test_phantom_dust_exposure_failure(multiplier_dust_limit: bool) { let mut receiver_config = UserConfig::default(); // Default test fee estimator rate is 253, so to set the max dust exposure to the dust limit, // we need to set the multiplier to 2. - receiver_config.channel_config.max_dust_htlc_exposure = - if multiplier_dust_limit { MaxDustHTLCExposure::FeeRateMultiplier(2) } - else { MaxDustHTLCExposure::FixedLimitMsat(max_dust_exposure) }; + receiver_config.channel_config.max_dust_htlc_exposure = if multiplier_dust_limit { + MaxDustHTLCExposure::FeeRateMultiplier(2) + } else { + MaxDustHTLCExposure::FixedLimitMsat(max_dust_exposure) + }; receiver_config.channel_handshake_config.announce_for_forwarding = true; let chanmon_cfgs = create_chanmon_cfgs(2); @@ -1890,12 +3074,20 @@ fn do_test_phantom_dust_exposure_failure(multiplier_dust_limit: bool) { let channel = create_announced_chan_between_nodes(&nodes, 0, 1); // Get the route with an amount exceeding the dust exposure threshold of nodes[1]. - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(max_dust_exposure + 1)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(max_dust_exposure + 1)); let (mut route, phantom_scid) = get_phantom_route!(nodes, max_dust_exposure + 1, channel); // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1935,12 +3127,20 @@ fn test_phantom_failure_reject_payment() { // Get the route with a too-low amount. let recv_amt_msat = 10_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[1], Some(recv_amt_msat)); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[1], Some(recv_amt_msat)); let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_amt_msat, channel); // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); let mut update_add = update_0.update_add_htlcs[0].clone(); @@ -1952,9 +3152,19 @@ fn test_phantom_failure_reject_payment() { nodes[1].node.process_pending_htlc_forwards(); expect_pending_htlcs_forwardable_ignore!(nodes[1]); nodes[1].node.process_pending_htlc_forwards(); - expect_payment_claimable!(nodes[1], payment_hash, payment_secret, recv_amt_msat, None, route.paths[0].hops.last().unwrap().pubkey); + expect_payment_claimable!( + nodes[1], + payment_hash, + payment_secret, + recv_amt_msat, + None, + route.paths[0].hops.last().unwrap().pubkey + ); nodes[1].node.fail_htlc_backwards(&payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); nodes[1].node.process_pending_htlc_forwards(); let update_1 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 8cab698a59a..3029752fadb 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -9,8 +9,8 @@ //! Utilities to send payments and manage outbound payment information. -use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; use bitcoin::secp256k1::{self, Secp256k1, SecretKey}; use lightning_invoice::Bolt11Invoice; @@ -22,17 +22,20 @@ use crate::ln::onion_utils; use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason}; use crate::offers::invoice::Bolt12Invoice; use crate::offers::invoice_request::InvoiceRequest; -use crate::offers::static_invoice::StaticInvoice; use crate::offers::nonce::Nonce; -use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, RouteParametersConfig, Router}; +use crate::offers::static_invoice::StaticInvoice; +use crate::routing::router::{ + BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, + RouteParametersConfig, Router, +}; use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::types::features::Bolt12InvoiceFeatures; use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::errors::APIError; use crate::util::logger::Logger; +use crate::util::ser::ReadableArgs; #[cfg(feature = "std")] use crate::util::time::Instant; -use crate::util::ser::ReadableArgs; #[cfg(async_payments)] use crate::offers::invoice::{DerivedSigningPubkey, InvoiceBuilder}; @@ -70,7 +73,7 @@ pub(crate) enum PendingOutboundPayment { expiration: StaleExpiration, retry_strategy: Retry, route_params_config: RouteParametersConfig, - retryable_invoice_request: Option + retryable_invoice_request: Option, }, // This state will never be persisted to disk because we transition from `AwaitingInvoice` to // `Retryable` atomically within the `ChannelManager::total_consistency_lock`. Useful to avoid @@ -171,10 +174,11 @@ impl PendingOutboundPayment { fn is_auto_retryable_now(&self) -> bool { match self { PendingOutboundPayment::Retryable { - retry_strategy: Some(strategy), attempts, payment_params: Some(_), .. - } => { - strategy.is_retryable_now(&attempts) - }, + retry_strategy: Some(strategy), + attempts, + payment_params: Some(_), + .. + } => strategy.is_retryable_now(&attempts), _ => false, } } @@ -184,9 +188,9 @@ impl PendingOutboundPayment { // We're handling retries manually, we can always retry. true }, - PendingOutboundPayment::Retryable { retry_strategy: Some(strategy), attempts, .. } => { - strategy.is_retryable_now(&attempts) - }, + PendingOutboundPayment::Retryable { + retry_strategy: Some(strategy), attempts, .. + } => strategy.is_retryable_now(&attempts), _ => false, } } @@ -240,7 +244,9 @@ impl PendingOutboundPayment { PendingOutboundPayment::AwaitingOffer { .. } => None, PendingOutboundPayment::AwaitingInvoice { .. } => None, PendingOutboundPayment::InvoiceReceived { payment_hash, .. } => Some(*payment_hash), - PendingOutboundPayment::StaticInvoiceReceived { payment_hash, .. } => Some(*payment_hash), + PendingOutboundPayment::StaticInvoiceReceived { payment_hash, .. } => { + Some(*payment_hash) + }, PendingOutboundPayment::Retryable { payment_hash, .. } => Some(*payment_hash), PendingOutboundPayment::Fulfilled { payment_hash, .. } => *payment_hash, PendingOutboundPayment::Abandoned { payment_hash, .. } => Some(*payment_hash), @@ -249,19 +255,30 @@ impl PendingOutboundPayment { fn mark_fulfilled(&mut self) { let mut session_privs = new_hash_set(); - core::mem::swap(&mut session_privs, match self { - PendingOutboundPayment::Legacy { session_privs } | - PendingOutboundPayment::Retryable { session_privs, .. } | - PendingOutboundPayment::Fulfilled { session_privs, .. } | - PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs, - PendingOutboundPayment::AwaitingOffer { .. } | - PendingOutboundPayment::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } | - PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); return; }, - }); + core::mem::swap( + &mut session_privs, + match self { + PendingOutboundPayment::Legacy { session_privs } + | PendingOutboundPayment::Retryable { session_privs, .. } + | PendingOutboundPayment::Fulfilled { session_privs, .. } + | PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs, + PendingOutboundPayment::AwaitingOffer { .. } + | PendingOutboundPayment::AwaitingInvoice { .. } + | PendingOutboundPayment::InvoiceReceived { .. } + | PendingOutboundPayment::StaticInvoiceReceived { .. } => { + debug_assert!(false); + return; + }, + }, + ); let payment_hash = self.payment_hash(); let total_msat = self.total_msat(); - *self = PendingOutboundPayment::Fulfilled { session_privs, payment_hash, timer_ticks_without_htlcs: 0, total_msat }; + *self = PendingOutboundPayment::Fulfilled { + session_privs, + payment_hash, + timer_ticks_without_htlcs: 0, + total_msat, + }; } fn mark_abandoned(&mut self, reason: PaymentFailureReason) { @@ -275,10 +292,9 @@ impl PendingOutboundPayment { }; let total_msat = self.total_msat(); match self { - Self::Retryable { payment_hash, .. } | - Self::InvoiceReceived { payment_hash, .. } | - Self::StaticInvoiceReceived { payment_hash, .. } => - { + Self::Retryable { payment_hash, .. } + | Self::InvoiceReceived { payment_hash, .. } + | Self::StaticInvoiceReceived { payment_hash, .. } => { *self = Self::Abandoned { session_privs, payment_hash: *payment_hash, @@ -286,29 +302,33 @@ impl PendingOutboundPayment { total_msat, }; }, - _ => {} + _ => {}, } } /// panics if path is None and !self.is_fulfilled fn remove(&mut self, session_priv: &[u8; 32], path: Option<&Path>) -> bool { let remove_res = match self { - PendingOutboundPayment::Legacy { session_privs } | - PendingOutboundPayment::Retryable { session_privs, .. } | - PendingOutboundPayment::Fulfilled { session_privs, .. } | - PendingOutboundPayment::Abandoned { session_privs, .. } => { - session_privs.remove(session_priv) - }, - PendingOutboundPayment::AwaitingOffer { .. } | - PendingOutboundPayment::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } | - PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); false }, + PendingOutboundPayment::Legacy { session_privs } + | PendingOutboundPayment::Retryable { session_privs, .. } + | PendingOutboundPayment::Fulfilled { session_privs, .. } + | PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs.remove(session_priv), + PendingOutboundPayment::AwaitingOffer { .. } + | PendingOutboundPayment::AwaitingInvoice { .. } + | PendingOutboundPayment::InvoiceReceived { .. } + | PendingOutboundPayment::StaticInvoiceReceived { .. } => { + debug_assert!(false); + false + }, }; if remove_res { if let PendingOutboundPayment::Retryable { - ref mut pending_amt_msat, ref mut pending_fee_msat, - ref mut remaining_max_total_routing_fee_msat, .. - } = self { + ref mut pending_amt_msat, + ref mut pending_fee_msat, + ref mut remaining_max_total_routing_fee_msat, + .. + } = self + { let path = path.expect("Removing a failed payment should always come with a path"); *pending_amt_msat -= path.final_value_msat(); let path_fee_msat = path.fee_msat(); @@ -316,8 +336,11 @@ impl PendingOutboundPayment { *fee_msat -= path_fee_msat; } - if let Some(max_total_routing_fee_msat) = remaining_max_total_routing_fee_msat.as_mut() { - *max_total_routing_fee_msat = max_total_routing_fee_msat.saturating_add(path_fee_msat); + if let Some(max_total_routing_fee_msat) = + remaining_max_total_routing_fee_msat.as_mut() + { + *max_total_routing_fee_msat = + max_total_routing_fee_msat.saturating_add(path_fee_msat); } } } @@ -326,31 +349,38 @@ impl PendingOutboundPayment { pub(super) fn insert(&mut self, session_priv: [u8; 32], path: &Path) -> bool { let insert_res = match self { - PendingOutboundPayment::Legacy { session_privs } | - PendingOutboundPayment::Retryable { session_privs, .. } => { - session_privs.insert(session_priv) - }, - PendingOutboundPayment::AwaitingOffer { .. } | - PendingOutboundPayment::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } | - PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); false }, + PendingOutboundPayment::Legacy { session_privs } + | PendingOutboundPayment::Retryable { session_privs, .. } => session_privs.insert(session_priv), + PendingOutboundPayment::AwaitingOffer { .. } + | PendingOutboundPayment::AwaitingInvoice { .. } + | PendingOutboundPayment::InvoiceReceived { .. } + | PendingOutboundPayment::StaticInvoiceReceived { .. } => { + debug_assert!(false); + false + }, PendingOutboundPayment::Fulfilled { .. } => false, PendingOutboundPayment::Abandoned { .. } => false, }; if insert_res { if let PendingOutboundPayment::Retryable { - ref mut pending_amt_msat, ref mut pending_fee_msat, - ref mut remaining_max_total_routing_fee_msat, .. - } = self { - *pending_amt_msat += path.final_value_msat(); - let path_fee_msat = path.fee_msat(); - if let Some(fee_msat) = pending_fee_msat.as_mut() { - *fee_msat += path_fee_msat; - } + ref mut pending_amt_msat, + ref mut pending_fee_msat, + ref mut remaining_max_total_routing_fee_msat, + .. + } = self + { + *pending_amt_msat += path.final_value_msat(); + let path_fee_msat = path.fee_msat(); + if let Some(fee_msat) = pending_fee_msat.as_mut() { + *fee_msat += path_fee_msat; + } - if let Some(max_total_routing_fee_msat) = remaining_max_total_routing_fee_msat.as_mut() { - *max_total_routing_fee_msat = max_total_routing_fee_msat.saturating_sub(path_fee_msat); - } + if let Some(max_total_routing_fee_msat) = + remaining_max_total_routing_fee_msat.as_mut() + { + *max_total_routing_fee_msat = + max_total_routing_fee_msat.saturating_sub(path_fee_msat); + } } } insert_res @@ -358,12 +388,10 @@ impl PendingOutboundPayment { pub(super) fn remaining_parts(&self) -> usize { match self { - PendingOutboundPayment::Legacy { session_privs } | - PendingOutboundPayment::Retryable { session_privs, .. } | - PendingOutboundPayment::Fulfilled { session_privs, .. } | - PendingOutboundPayment::Abandoned { session_privs, .. } => { - session_privs.len() - }, + PendingOutboundPayment::Legacy { session_privs } + | PendingOutboundPayment::Retryable { session_privs, .. } + | PendingOutboundPayment::Fulfilled { session_privs, .. } + | PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs.len(), PendingOutboundPayment::AwaitingInvoice { .. } => 0, PendingOutboundPayment::AwaitingOffer { .. } => 0, PendingOutboundPayment::InvoiceReceived { .. } => 0, @@ -409,8 +437,9 @@ impl Retry { max_retry_count > count }, #[cfg(feature = "std")] - (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => - *max_duration >= Instant::now().duration_since(*first_attempted_at), + (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => { + *max_duration >= Instant::now().duration_since(*first_attempted_at) + }, } } } @@ -419,7 +448,7 @@ impl Retry { pub(super) fn has_expired(route_params: &RouteParameters) -> bool { if let Some(expiry_time) = route_params.payment_params.expiry_time { if let Ok(elapsed) = std::time::SystemTime::UNIX_EPOCH.elapsed() { - return elapsed > core::time::Duration::from_secs(expiry_time) + return elapsed > core::time::Duration::from_secs(expiry_time); } } false @@ -489,7 +518,10 @@ pub enum RetryableSendFailure { /// the BOLT 12 invoice paid to via [`ChannelManager::send_payment_for_bolt12_invoice`] was /// expired. #[cfg_attr(feature = "std", doc = "")] - #[cfg_attr(feature = "std", doc = "Note that this error is *not* caused by [`Retry::Timeout`].")] + #[cfg_attr( + feature = "std", + doc = "Note that this error is *not* caused by [`Retry::Timeout`]." + )] /// /// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time /// [`ChannelManager::send_payment_for_bolt12_invoice`]: crate::ln::channelmanager::ChannelManager::send_payment_for_bolt12_invoice @@ -691,7 +723,11 @@ impl RecipientOnionFields { /// set of onion fields for today's BOLT11 invoices - most nodes require a [`PaymentSecret`] /// but do not require or provide any further data. pub fn secret_only(payment_secret: PaymentSecret) -> Self { - Self { payment_secret: Some(payment_secret), payment_metadata: None, custom_tlvs: Vec::new() } + Self { + payment_secret: Some(payment_secret), + payment_metadata: None, + custom_tlvs: Vec::new(), + } } /// Creates a new [`RecipientOnionFields`] with no fields. This generally does not create @@ -719,9 +755,15 @@ impl RecipientOnionFields { custom_tlvs.sort_unstable_by_key(|(typ, _)| *typ); let mut prev_type = None; for (typ, _) in custom_tlvs.iter() { - if *typ < 1 << 16 { return Err(()); } - if *typ == 5482373484 { return Err(()); } // keysend - if *typ == 77_777 { return Err(()); } // invoice requests for async payments + if *typ < 1 << 16 { + return Err(()); + } + if *typ == 5482373484 { + return Err(()); + } // keysend + if *typ == 77_777 { + return Err(()); + } // invoice requests for async payments match prev_type { Some(prev) if prev >= *typ => return Err(()), _ => {}, @@ -770,15 +812,21 @@ impl RecipientOnionFields { /// Here we implement this, first checking compatibility then mutating two objects and then /// dropping any remaining non-matching fields from both. pub(super) fn check_merge(&mut self, further_htlc_fields: &mut Self) -> Result<(), ()> { - if self.payment_secret != further_htlc_fields.payment_secret { return Err(()); } - if self.payment_metadata != further_htlc_fields.payment_metadata { return Err(()); } + if self.payment_secret != further_htlc_fields.payment_secret { + return Err(()); + } + if self.payment_metadata != further_htlc_fields.payment_metadata { + return Err(()); + } let tlvs = &mut self.custom_tlvs; let further_tlvs = &mut further_htlc_fields.custom_tlvs; let even_tlvs = tlvs.iter().filter(|(typ, _)| *typ % 2 == 0); let further_even_tlvs = further_tlvs.iter().filter(|(typ, _)| *typ % 2 == 0); - if even_tlvs.ne(further_even_tlvs) { return Err(()) } + if even_tlvs.ne(further_even_tlvs) { + return Err(()); + } tlvs.retain(|tlv| further_tlvs.iter().any(|further_tlv| tlv == further_tlv)); further_tlvs.retain(|further_tlv| tlvs.iter().any(|tlv| tlv == further_tlv)); @@ -807,7 +855,9 @@ pub(super) struct OutboundPayments { } impl OutboundPayments { - pub(super) fn new(pending_outbound_payments: HashMap) -> Self { + pub(super) fn new( + pending_outbound_payments: HashMap, + ) -> Self { let has_invoice_requests = pending_outbound_payments.values().any(|payment| { matches!( payment, @@ -825,11 +875,12 @@ impl OutboundPayments { } pub(super) fn send_payment( - &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, - retry_strategy: Retry, route_params: RouteParameters, router: &R, + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + payment_id: PaymentId, retry_strategy: Retry, route_params: RouteParameters, router: &R, first_hops: Vec, compute_inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, - pending_events: &Mutex)>>, send_payment_along_path: SP, + pending_events: &Mutex)>>, + send_payment_along_path: SP, ) -> Result<(), RetryableSendFailure> where R::Target: Router, @@ -839,17 +890,32 @@ impl OutboundPayments { IH: Fn() -> InFlightHtlcs, SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - self.send_payment_for_non_bolt12_invoice(payment_id, payment_hash, recipient_onion, None, retry_strategy, - route_params, router, first_hops, &compute_inflight_htlcs, entropy_source, node_signer, - best_block_height, logger, pending_events, &send_payment_along_path) + self.send_payment_for_non_bolt12_invoice( + payment_id, + payment_hash, + recipient_onion, + None, + retry_strategy, + route_params, + router, + first_hops, + &compute_inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + &send_payment_along_path, + ) } pub(super) fn send_spontaneous_payment( &self, payment_preimage: Option, recipient_onion: RecipientOnionFields, payment_id: PaymentId, retry_strategy: Retry, route_params: RouteParameters, router: &R, - first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, - node_signer: &NS, best_block_height: u32, logger: &L, - pending_events: &Mutex)>>, send_payment_along_path: SP + first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, + best_block_height: u32, logger: &L, + pending_events: &Mutex)>>, + send_payment_along_path: SP, ) -> Result where R::Target: Router, @@ -862,21 +928,33 @@ impl OutboundPayments { let preimage = payment_preimage .unwrap_or_else(|| PaymentPreimage(entropy_source.get_secure_random_bytes())); let payment_hash = PaymentHash(Sha256::hash(&preimage.0).to_byte_array()); - self.send_payment_for_non_bolt12_invoice(payment_id, payment_hash, recipient_onion, Some(preimage), - retry_strategy, route_params, router, first_hops, inflight_htlcs, entropy_source, - node_signer, best_block_height, logger, pending_events, send_payment_along_path) - .map(|()| payment_hash) + self.send_payment_for_non_bolt12_invoice( + payment_id, + payment_hash, + recipient_onion, + Some(preimage), + retry_strategy, + route_params, + router, + first_hops, + inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + send_payment_along_path, + ) + .map(|()| payment_hash) } pub(super) fn pay_for_bolt11_invoice( - &self, invoice: &Bolt11Invoice, payment_id: PaymentId, - amount_msats: Option, - route_params_config: RouteParametersConfig, - retry_strategy: Retry, - router: &R, + &self, invoice: &Bolt11Invoice, payment_id: PaymentId, amount_msats: Option, + route_params_config: RouteParametersConfig, retry_strategy: Retry, router: &R, first_hops: Vec, compute_inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, - pending_events: &Mutex)>>, send_payment_along_path: SP, + pending_events: &Mutex)>>, + send_payment_along_path: SP, ) -> Result<(), Bolt11PaymentError> where R::Target: Router, @@ -899,21 +977,41 @@ impl OutboundPayments { let payment_params = PaymentParameters::from_bolt11_invoice(invoice) .with_user_config_ignoring_fee_limit(route_params_config); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amount); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params, amount); if let Some(max_fee_msat) = route_params_config.max_total_routing_fee_msat { route_params.max_total_routing_fee_msat = Some(max_fee_msat); } - self.send_payment_for_non_bolt12_invoice(payment_id, payment_hash, recipient_onion, None, retry_strategy, route_params, - router, first_hops, compute_inflight_htlcs, - entropy_source, node_signer, best_block_height, logger, - pending_events, send_payment_along_path - ).map_err(|err| Bolt11PaymentError::SendingFailed(err)) + self.send_payment_for_non_bolt12_invoice( + payment_id, + payment_hash, + recipient_onion, + None, + retry_strategy, + route_params, + router, + first_hops, + compute_inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + send_payment_along_path, + ) + .map_err(|err| Bolt11PaymentError::SendingFailed(err)) } pub(super) fn send_payment_for_bolt12_invoice< - R: Deref, ES: Deref, NS: Deref, NL: Deref, IH, SP, L: Deref + R: Deref, + ES: Deref, + NS: Deref, + NL: Deref, + IH, + SP, + L: Deref, >( &self, invoice: &Bolt12Invoice, payment_id: PaymentId, router: &R, first_hops: Vec, features: Bolt12InvoiceFeatures, inflight_htlcs: IH, @@ -937,7 +1035,9 @@ impl OutboundPayments { match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(entry) => match entry.get() { PendingOutboundPayment::AwaitingInvoice { - retry_strategy: retry, route_params_config, .. + retry_strategy: retry, + route_params_config, + .. } => { retry_strategy = *retry; params_config = *route_params_config; @@ -954,35 +1054,59 @@ impl OutboundPayments { if invoice.invoice_features().requires_unknown_bits_from(&features) { self.abandon_payment( - payment_id, PaymentFailureReason::UnknownRequiredFeatures, pending_events, + payment_id, + PaymentFailureReason::UnknownRequiredFeatures, + pending_events, ); return Err(Bolt12PaymentError::UnknownRequiredFeatures); } let mut route_params = RouteParameters::from_payment_params_and_value( PaymentParameters::from_bolt12_invoice(&invoice) - .with_user_config_ignoring_fee_limit(params_config), invoice.amount_msats() + .with_user_config_ignoring_fee_limit(params_config), + invoice.amount_msats(), ); if let Some(max_fee_msat) = params_config.max_total_routing_fee_msat { route_params.max_total_routing_fee_msat = Some(max_fee_msat); } let invoice = PaidBolt12Invoice::Bolt12Invoice(invoice.clone()); self.send_payment_for_bolt12_invoice_internal( - payment_id, payment_hash, None, None, invoice, route_params, retry_strategy, router, first_hops, - inflight_htlcs, entropy_source, node_signer, node_id_lookup, secp_ctx, best_block_height, - logger, pending_events, send_payment_along_path + payment_id, + payment_hash, + None, + None, + invoice, + route_params, + retry_strategy, + router, + first_hops, + inflight_htlcs, + entropy_source, + node_signer, + node_id_lookup, + secp_ctx, + best_block_height, + logger, + pending_events, + send_payment_along_path, ) } fn send_payment_for_bolt12_invoice_internal< - R: Deref, ES: Deref, NS: Deref, NL: Deref, IH, SP, L: Deref + R: Deref, + ES: Deref, + NS: Deref, + NL: Deref, + IH, + SP, + L: Deref, >( &self, payment_id: PaymentId, payment_hash: PaymentHash, keysend_preimage: Option, invoice_request: Option<&InvoiceRequest>, - bolt12_invoice: PaidBolt12Invoice, - mut route_params: RouteParameters, retry_strategy: Retry, router: &R, - first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, - node_id_lookup: &NL, secp_ctx: &Secp256k1, best_block_height: u32, logger: &L, + bolt12_invoice: PaidBolt12Invoice, mut route_params: RouteParameters, + retry_strategy: Retry, router: &R, first_hops: Vec, inflight_htlcs: IH, + entropy_source: &ES, node_signer: &NS, node_id_lookup: &NL, + secp_ctx: &Secp256k1, best_block_height: u32, logger: &L, pending_events: &Mutex)>>, send_payment_along_path: SP, ) -> Result<(), Bolt12PaymentError> @@ -1002,7 +1126,9 @@ impl OutboundPayments { IntroductionNode::NodeId(pubkey) => *pubkey, IntroductionNode::DirectedShortChannelId(direction, scid) => { match node_id_lookup.next_node_id(*scid) { - Some(next_node_id) => *direction.select_pubkey(&our_node_id, &next_node_id), + Some(next_node_id) => { + *direction.select_pubkey(&our_node_id, &next_node_id) + }, None => continue, } }, @@ -1019,8 +1145,17 @@ impl OutboundPayments { custom_tlvs: vec![], }; let route = match self.find_initial_route( - payment_id, payment_hash, &recipient_onion, keysend_preimage, invoice_request, - &mut route_params, router, &first_hops, &inflight_htlcs, node_signer, best_block_height, + payment_id, + payment_hash, + &recipient_onion, + keysend_preimage, + invoice_request, + &mut route_params, + router, + &first_hops, + &inflight_htlcs, + node_signer, + best_block_height, logger, ) { Ok(route) => route, @@ -1029,7 +1164,9 @@ impl OutboundPayments { RetryableSendFailure::PaymentExpired => PaymentFailureReason::PaymentExpired, RetryableSendFailure::RouteNotFound => PaymentFailureReason::RouteNotFound, RetryableSendFailure::DuplicatePayment => PaymentFailureReason::UnexpectedError, - RetryableSendFailure::OnionPacketSizeExceeded => PaymentFailureReason::UnexpectedError, + RetryableSendFailure::OnionPacketSizeExceeded => { + PaymentFailureReason::UnexpectedError + }, }; self.abandon_payment(payment_id, reason, pending_events); return Err(Bolt12PaymentError::SendingFailed(e)); @@ -1042,19 +1179,41 @@ impl OutboundPayments { hash_map::Entry::Occupied(entry) => match entry.get() { PendingOutboundPayment::InvoiceReceived { .. } => { let (retryable_payment, onion_session_privs) = Self::create_pending_payment( - payment_hash, recipient_onion.clone(), keysend_preimage, None, Some(bolt12_invoice), &route, - Some(retry_strategy), payment_params, entropy_source, best_block_height, + payment_hash, + recipient_onion.clone(), + keysend_preimage, + None, + Some(bolt12_invoice), + &route, + Some(retry_strategy), + payment_params, + entropy_source, + best_block_height, ); *entry.into_mut() = retryable_payment; onion_session_privs }, PendingOutboundPayment::StaticInvoiceReceived { .. } => { - let invreq = if let PendingOutboundPayment::StaticInvoiceReceived { invoice_request, .. } = entry.remove() { + let invreq = if let PendingOutboundPayment::StaticInvoiceReceived { + invoice_request, + .. + } = entry.remove() + { invoice_request - } else { unreachable!() }; + } else { + unreachable!() + }; let (retryable_payment, onion_session_privs) = Self::create_pending_payment( - payment_hash, recipient_onion.clone(), keysend_preimage, Some(invreq), Some(bolt12_invoice), &route, - Some(retry_strategy), payment_params, entropy_source, best_block_height + payment_hash, + recipient_onion.clone(), + keysend_preimage, + Some(invreq), + Some(bolt12_invoice), + &route, + Some(retry_strategy), + payment_params, + entropy_source, + best_block_height, ); outbounds.insert(payment_id, retryable_payment); onion_session_privs @@ -1066,19 +1225,42 @@ impl OutboundPayments { core::mem::drop(outbounds); let result = self.pay_route_internal( - &route, payment_hash, &recipient_onion, keysend_preimage, invoice_request, payment_id, - Some(route_params.final_value_msat), &onion_session_privs, node_signer, best_block_height, - &send_payment_along_path + &route, + payment_hash, + &recipient_onion, + keysend_preimage, + invoice_request, + payment_id, + Some(route_params.final_value_msat), + &onion_session_privs, + node_signer, + best_block_height, + &send_payment_along_path, ); log_info!( - logger, "Sending payment with id {} and hash {} returned {:?}", payment_id, - payment_hash, result + logger, + "Sending payment with id {} and hash {} returned {:?}", + payment_id, + payment_hash, + result ); if let Err(e) = result { self.handle_pay_route_err( - e, payment_id, payment_hash, route, route_params, onion_session_privs, router, first_hops, - &inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, - &send_payment_along_path + e, + payment_id, + payment_hash, + route, + route_params, + onion_session_privs, + router, + first_hops, + &inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + &send_payment_along_path, ); } Ok(()) @@ -1088,8 +1270,11 @@ impl OutboundPayments { pub(super) fn static_invoice_received( &self, invoice: &StaticInvoice, payment_id: PaymentId, features: Bolt12InvoiceFeatures, best_block_height: u32, duration_since_epoch: Duration, entropy_source: ES, - pending_events: &Mutex)>> - ) -> Result<(), Bolt12PaymentError> where ES::Target: EntropySource { + pending_events: &Mutex)>>, + ) -> Result<(), Bolt12PaymentError> + where + ES::Target: EntropySource, + { macro_rules! abandon_with_entry { ($payment: expr, $reason: expr) => { assert!( @@ -1108,47 +1293,65 @@ impl OutboundPayments { match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(mut entry) => match entry.get_mut() { PendingOutboundPayment::AwaitingInvoice { - retry_strategy, retryable_invoice_request, route_params_config, .. + retry_strategy, + retryable_invoice_request, + route_params_config, + .. } => { let invreq = &retryable_invoice_request .as_ref() .ok_or(Bolt12PaymentError::UnexpectedInvoice)? .invoice_request; if !invoice.is_from_same_offer(invreq) { - return Err(Bolt12PaymentError::UnexpectedInvoice) + return Err(Bolt12PaymentError::UnexpectedInvoice); } if invoice.invoice_features().requires_unknown_bits_from(&features) { abandon_with_entry!(entry, PaymentFailureReason::UnknownRequiredFeatures); - return Err(Bolt12PaymentError::UnknownRequiredFeatures) + return Err(Bolt12PaymentError::UnknownRequiredFeatures); } - if duration_since_epoch > invoice.created_at().saturating_add(invoice.relative_expiry()) { + if duration_since_epoch + > invoice.created_at().saturating_add(invoice.relative_expiry()) + { abandon_with_entry!(entry, PaymentFailureReason::PaymentExpired); - return Err(Bolt12PaymentError::SendingFailed(RetryableSendFailure::PaymentExpired)) + return Err(Bolt12PaymentError::SendingFailed( + RetryableSendFailure::PaymentExpired, + )); } - let amount_msat = match InvoiceBuilder::::amount_msats(invreq) { + let amount_msat = match InvoiceBuilder::::amount_msats( + invreq, + ) { Ok(amt) => amt, Err(_) => { // We check this during invoice request parsing, when constructing the invreq's // contents from its TLV stream. debug_assert!(false, "LDK requires an msat amount in either the invreq or the invreq's underlying offer"); abandon_with_entry!(entry, PaymentFailureReason::UnexpectedError); - return Err(Bolt12PaymentError::UnknownRequiredFeatures) - } + return Err(Bolt12PaymentError::UnknownRequiredFeatures); + }, }; - let keysend_preimage = PaymentPreimage(entropy_source.get_secure_random_bytes()); - let payment_hash = PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array()); + let keysend_preimage = + PaymentPreimage(entropy_source.get_secure_random_bytes()); + let payment_hash = + PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array()); let pay_params = PaymentParameters::from_static_invoice(invoice) .with_user_config_ignoring_fee_limit(*route_params_config); - let mut route_params = RouteParameters::from_payment_params_and_value(pay_params, amount_msat); - route_params.max_total_routing_fee_msat = route_params_config.max_total_routing_fee_msat; + let mut route_params = + RouteParameters::from_payment_params_and_value(pay_params, amount_msat); + route_params.max_total_routing_fee_msat = + route_params_config.max_total_routing_fee_msat; if let Err(()) = onion_utils::set_max_path_length( - &mut route_params, &RecipientOnionFields::spontaneous_empty(), Some(keysend_preimage), - Some(invreq), best_block_height + &mut route_params, + &RecipientOnionFields::spontaneous_empty(), + Some(keysend_preimage), + Some(invreq), + best_block_height, ) { abandon_with_entry!(entry, PaymentFailureReason::RouteNotFound); - return Err(Bolt12PaymentError::SendingFailed(RetryableSendFailure::OnionPacketSizeExceeded)) + return Err(Bolt12PaymentError::SendingFailed( + RetryableSendFailure::OnionPacketSizeExceeded, + )); } *entry.into_mut() = PendingOutboundPayment::StaticInvoiceReceived { @@ -1156,14 +1359,13 @@ impl OutboundPayments { keysend_preimage, retry_strategy: *retry_strategy, route_params, - invoice_request: - retryable_invoice_request + invoice_request: retryable_invoice_request .take() .ok_or(Bolt12PaymentError::UnexpectedInvoice)? .invoice_request, static_invoice: invoice.clone(), }; - return Ok(()) + return Ok(()); }, _ => return Err(Bolt12PaymentError::DuplicateInvoice), }, @@ -1173,10 +1375,16 @@ impl OutboundPayments { #[cfg(async_payments)] pub(super) fn send_payment_for_static_invoice< - R: Deref, ES: Deref, NS: Deref, NL: Deref, IH, SP, L: Deref + R: Deref, + ES: Deref, + NS: Deref, + NL: Deref, + IH, + SP, + L: Deref, >( - &self, payment_id: PaymentId, router: &R, first_hops: Vec, inflight_htlcs: IH, - entropy_source: &ES, node_signer: &NS, node_id_lookup: &NL, + &self, payment_id: PaymentId, router: &R, first_hops: Vec, + inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1, best_block_height: u32, logger: &L, pending_events: &Mutex)>>, send_payment_along_path: SP, @@ -1190,34 +1398,64 @@ impl OutboundPayments { IH: Fn() -> InFlightHtlcs, SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - let (payment_hash, keysend_preimage, route_params, retry_strategy, invoice_request, invoice) = - match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { - hash_map::Entry::Occupied(entry) => match entry.get() { - PendingOutboundPayment::StaticInvoiceReceived { - payment_hash, route_params, retry_strategy, keysend_preimage, invoice_request, static_invoice, .. - } => { - (*payment_hash, *keysend_preimage, route_params.clone(), *retry_strategy, - invoice_request.clone(), static_invoice.clone()) - }, - _ => return Err(Bolt12PaymentError::DuplicateInvoice), - }, - hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice), - }; + let ( + payment_hash, + keysend_preimage, + route_params, + retry_strategy, + invoice_request, + invoice, + ) = match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { + hash_map::Entry::Occupied(entry) => match entry.get() { + PendingOutboundPayment::StaticInvoiceReceived { + payment_hash, + route_params, + retry_strategy, + keysend_preimage, + invoice_request, + static_invoice, + .. + } => ( + *payment_hash, + *keysend_preimage, + route_params.clone(), + *retry_strategy, + invoice_request.clone(), + static_invoice.clone(), + ), + _ => return Err(Bolt12PaymentError::DuplicateInvoice), + }, + hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice), + }; let invoice = PaidBolt12Invoice::StaticInvoice(invoice); self.send_payment_for_bolt12_invoice_internal( - payment_id, payment_hash, Some(keysend_preimage), Some(&invoice_request), invoice, route_params, - retry_strategy, router, first_hops, inflight_htlcs, entropy_source, node_signer, - node_id_lookup, secp_ctx, best_block_height, logger, pending_events, send_payment_along_path + payment_id, + payment_hash, + Some(keysend_preimage), + Some(&invoice_request), + invoice, + route_params, + retry_strategy, + router, + first_hops, + inflight_htlcs, + entropy_source, + node_signer, + node_id_lookup, + secp_ctx, + best_block_height, + logger, + pending_events, + send_payment_along_path, ) } pub(super) fn check_retry_payments( - &self, router: &R, first_hops: FH, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, - best_block_height: u32, - pending_events: &Mutex)>>, logger: &L, - send_payment_along_path: SP, - ) - where + &self, router: &R, first_hops: FH, inflight_htlcs: IH, entropy_source: &ES, + node_signer: &NS, best_block_height: u32, + pending_events: &Mutex)>>, + logger: &L, send_payment_along_path: SP, + ) where R::Target: Router, ES::Target: EntropySource, NS::Target: NodeSigner, @@ -1232,35 +1470,71 @@ impl OutboundPayments { let mut retry_id_route_params = None; for (pmt_id, pmt) in outbounds.iter_mut() { if pmt.is_auto_retryable_now() { - if let PendingOutboundPayment::Retryable { pending_amt_msat, total_msat, payment_params: Some(params), payment_hash, remaining_max_total_routing_fee_msat, .. } = pmt { + if let PendingOutboundPayment::Retryable { + pending_amt_msat, + total_msat, + payment_params: Some(params), + payment_hash, + remaining_max_total_routing_fee_msat, + .. + } = pmt + { if pending_amt_msat < total_msat { - retry_id_route_params = Some((*payment_hash, *pmt_id, RouteParameters { - final_value_msat: *total_msat - *pending_amt_msat, - payment_params: params.clone(), - max_total_routing_fee_msat: *remaining_max_total_routing_fee_msat, - })); - break + retry_id_route_params = Some(( + *payment_hash, + *pmt_id, + RouteParameters { + final_value_msat: *total_msat - *pending_amt_msat, + payment_params: params.clone(), + max_total_routing_fee_msat: + *remaining_max_total_routing_fee_msat, + }, + )); + break; } - } else { debug_assert!(false); } + } else { + debug_assert!(false); + } } } core::mem::drop(outbounds); if let Some((payment_hash, payment_id, route_params)) = retry_id_route_params { - self.find_route_and_send_payment(payment_hash, payment_id, route_params, router, first_hops(), &inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, &send_payment_along_path) - } else { break } + self.find_route_and_send_payment( + payment_hash, + payment_id, + route_params, + router, + first_hops(), + &inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + &send_payment_along_path, + ) + } else { + break; + } } let mut outbounds = self.pending_outbound_payments.lock().unwrap(); outbounds.retain(|pmt_id, pmt| { let mut retain = true; - if !pmt.is_auto_retryable_now() && pmt.remaining_parts() == 0 && !pmt.is_awaiting_invoice() { + if !pmt.is_auto_retryable_now() + && pmt.remaining_parts() == 0 + && !pmt.is_awaiting_invoice() + { pmt.mark_abandoned(PaymentFailureReason::RetriesExhausted); if let PendingOutboundPayment::Abandoned { payment_hash, reason, .. } = pmt { - pending_events.lock().unwrap().push_back((events::Event::PaymentFailed { - payment_id: *pmt_id, - payment_hash: Some(*payment_hash), - reason: *reason, - }, None)); + pending_events.lock().unwrap().push_back(( + events::Event::PaymentFailed { + payment_id: *pmt_id, + payment_hash: Some(*payment_hash), + reason: *reason, + }, + None, + )); retain = false; } } @@ -1270,16 +1544,20 @@ impl OutboundPayments { pub(super) fn needs_abandon(&self) -> bool { let outbounds = self.pending_outbound_payments.lock().unwrap(); - outbounds.iter().any(|(_, pmt)| - !pmt.is_auto_retryable_now() && pmt.remaining_parts() == 0 && !pmt.is_fulfilled() && - !pmt.is_awaiting_invoice()) + outbounds.iter().any(|(_, pmt)| { + !pmt.is_auto_retryable_now() + && pmt.remaining_parts() == 0 + && !pmt.is_fulfilled() + && !pmt.is_awaiting_invoice() + }) } fn find_initial_route( - &self, payment_id: PaymentId, payment_hash: PaymentHash, recipient_onion: &RecipientOnionFields, - keysend_preimage: Option, invoice_request: Option<&InvoiceRequest>, - route_params: &mut RouteParameters, router: &R, first_hops: &Vec, - inflight_htlcs: &IH, node_signer: &NS, best_block_height: u32, logger: &L, + &self, payment_id: PaymentId, payment_hash: PaymentHash, + recipient_onion: &RecipientOnionFields, keysend_preimage: Option, + invoice_request: Option<&InvoiceRequest>, route_params: &mut RouteParameters, router: &R, + first_hops: &Vec, inflight_htlcs: &IH, node_signer: &NS, + best_block_height: u32, logger: &L, ) -> Result where R::Target: Router, @@ -1287,33 +1565,56 @@ impl OutboundPayments { L::Target: Logger, IH: Fn() -> InFlightHtlcs, { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if has_expired(&route_params) { - log_error!(logger, "Payment with id {} and hash {} had expired before we started paying", - payment_id, payment_hash); - return Err(RetryableSendFailure::PaymentExpired) + log_error!( + logger, + "Payment with id {} and hash {} had expired before we started paying", + payment_id, + payment_hash + ); + return Err(RetryableSendFailure::PaymentExpired); } } onion_utils::set_max_path_length( - route_params, recipient_onion, keysend_preimage, invoice_request, best_block_height + route_params, + recipient_onion, + keysend_preimage, + invoice_request, + best_block_height, ) - .map_err(|()| { - log_error!(logger, "Can't construct an onion packet without exceeding 1300-byte onion \ - hop_data length for payment with id {} and hash {}", payment_id, payment_hash); - RetryableSendFailure::OnionPacketSizeExceeded - })?; - - let mut route = router.find_route_with_id( - &node_signer.get_node_id(Recipient::Node).unwrap(), route_params, - Some(&first_hops.iter().collect::>()), inflight_htlcs(), - payment_hash, payment_id, - ).map_err(|_| { - log_error!(logger, "Failed to find route for payment with id {} and hash {}", - payment_id, payment_hash); - RetryableSendFailure::RouteNotFound + .map_err(|()| { + log_error!( + logger, + "Can't construct an onion packet without exceeding 1300-byte onion \ + hop_data length for payment with id {} and hash {}", + payment_id, + payment_hash + ); + RetryableSendFailure::OnionPacketSizeExceeded })?; + let mut route = router + .find_route_with_id( + &node_signer.get_node_id(Recipient::Node).unwrap(), + route_params, + Some(&first_hops.iter().collect::>()), + inflight_htlcs(), + payment_hash, + payment_id, + ) + .map_err(|_| { + log_error!( + logger, + "Failed to find route for payment with id {} and hash {}", + payment_id, + payment_hash + ); + RetryableSendFailure::RouteNotFound + })?; + if route.route_params.as_ref() != Some(route_params) { debug_assert!(false, "Routers are expected to return a Route which includes the requested RouteParameters. Got {:?}, expected {:?}", @@ -1330,11 +1631,13 @@ impl OutboundPayments { /// [`Event::PaymentPathFailed`]: crate::events::Event::PaymentPathFailed /// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed fn send_payment_for_non_bolt12_invoice( - &self, payment_id: PaymentId, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, - keysend_preimage: Option, retry_strategy: Retry, mut route_params: RouteParameters, - router: &R, first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, - node_signer: &NS, best_block_height: u32, logger: &L, - pending_events: &Mutex)>>, send_payment_along_path: SP, + &self, payment_id: PaymentId, payment_hash: PaymentHash, + recipient_onion: RecipientOnionFields, keysend_preimage: Option, + retry_strategy: Retry, mut route_params: RouteParameters, router: &R, + first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, + best_block_height: u32, logger: &L, + pending_events: &Mutex)>>, + send_payment_along_path: SP, ) -> Result<(), RetryableSendFailure> where R::Target: Router, @@ -1345,29 +1648,80 @@ impl OutboundPayments { SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, { let route = self.find_initial_route( - payment_id, payment_hash, &recipient_onion, keysend_preimage, None, &mut route_params, router, - &first_hops, &inflight_htlcs, node_signer, best_block_height, logger, + payment_id, + payment_hash, + &recipient_onion, + keysend_preimage, + None, + &mut route_params, + router, + &first_hops, + &inflight_htlcs, + node_signer, + best_block_height, + logger, )?; - let onion_session_privs = self.add_new_pending_payment(payment_hash, - recipient_onion.clone(), payment_id, keysend_preimage, &route, Some(retry_strategy), - Some(route_params.payment_params.clone()), entropy_source, best_block_height, None) + let onion_session_privs = self + .add_new_pending_payment( + payment_hash, + recipient_onion.clone(), + payment_id, + keysend_preimage, + &route, + Some(retry_strategy), + Some(route_params.payment_params.clone()), + entropy_source, + best_block_height, + None, + ) .map_err(|_| { - log_error!(logger, "Payment with id {} is already pending. New payment had payment hash {}", - payment_id, payment_hash); + log_error!( + logger, + "Payment with id {} is already pending. New payment had payment hash {}", + payment_id, + payment_hash + ); RetryableSendFailure::DuplicatePayment })?; - let res = self.pay_route_internal(&route, payment_hash, &recipient_onion, - keysend_preimage, None, payment_id, None, &onion_session_privs, node_signer, - best_block_height, &send_payment_along_path); - log_info!(logger, "Sending payment with id {} and hash {} returned {:?}", - payment_id, payment_hash, res); + let res = self.pay_route_internal( + &route, + payment_hash, + &recipient_onion, + keysend_preimage, + None, + payment_id, + None, + &onion_session_privs, + node_signer, + best_block_height, + &send_payment_along_path, + ); + log_info!( + logger, + "Sending payment with id {} and hash {} returned {:?}", + payment_id, + payment_hash, + res + ); if let Err(e) = res { self.handle_pay_route_err( - e, payment_id, payment_hash, route, route_params, onion_session_privs, router, first_hops, - &inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, - &send_payment_along_path + e, + payment_id, + payment_hash, + route, + route_params, + onion_session_privs, + router, + first_hops, + &inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + &send_payment_along_path, ); } Ok(()) @@ -1377,9 +1731,9 @@ impl OutboundPayments { &self, payment_hash: PaymentHash, payment_id: PaymentId, route_params: RouteParameters, router: &R, first_hops: Vec, inflight_htlcs: &IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, - pending_events: &Mutex)>>, send_payment_along_path: &SP, - ) - where + pending_events: &Mutex)>>, + send_payment_along_path: &SP, + ) where R::Target: Router, ES::Target: EntropySource, NS::Target: NodeSigner, @@ -1387,25 +1741,46 @@ impl OutboundPayments { IH: Fn() -> InFlightHtlcs, SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if has_expired(&route_params) { - log_error!(logger, "Payment params expired on retry, abandoning payment {}", &payment_id); - self.abandon_payment(payment_id, PaymentFailureReason::PaymentExpired, pending_events); - return + log_error!( + logger, + "Payment params expired on retry, abandoning payment {}", + &payment_id + ); + self.abandon_payment( + payment_id, + PaymentFailureReason::PaymentExpired, + pending_events, + ); + return; } } let mut route = match router.find_route_with_id( - &node_signer.get_node_id(Recipient::Node).unwrap(), &route_params, - Some(&first_hops.iter().collect::>()), inflight_htlcs(), - payment_hash, payment_id, + &node_signer.get_node_id(Recipient::Node).unwrap(), + &route_params, + Some(&first_hops.iter().collect::>()), + inflight_htlcs(), + payment_hash, + payment_id, ) { Ok(route) => route, Err(e) => { - log_error!(logger, "Failed to find a route on retry, abandoning payment {}: {:#?}", &payment_id, e); - self.abandon_payment(payment_id, PaymentFailureReason::RouteNotFound, pending_events); - return - } + log_error!( + logger, + "Failed to find a route on retry, abandoning payment {}: {:#?}", + &payment_id, + e + ); + self.abandon_payment( + payment_id, + PaymentFailureReason::RouteNotFound, + pending_events, + ); + return; + }, }; if route.route_params.as_ref() != Some(&route_params) { @@ -1417,8 +1792,12 @@ impl OutboundPayments { for path in route.paths.iter() { if path.hops.len() == 0 { log_error!(logger, "Unusable path in route (path.hops.len() must be at least 1"); - self.abandon_payment(payment_id, PaymentFailureReason::UnexpectedError, pending_events); - return + self.abandon_payment( + payment_id, + PaymentFailureReason::UnexpectedError, + pending_events, + ); + return; } } @@ -1427,120 +1806,160 @@ impl OutboundPayments { $payment.get_mut().mark_abandoned($reason); if let PendingOutboundPayment::Abandoned { reason, .. } = $payment.get() { if $payment.get().remaining_parts() == 0 { - pending_events.lock().unwrap().push_back((events::Event::PaymentFailed { - payment_id, - payment_hash: Some(payment_hash), - reason: *reason, - }, None)); + pending_events.lock().unwrap().push_back(( + events::Event::PaymentFailed { + payment_id, + payment_hash: Some(payment_hash), + reason: *reason, + }, + None, + )); $payment.remove(); } } - } + }; } let (total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request) = { let mut outbounds = self.pending_outbound_payments.lock().unwrap(); match outbounds.entry(payment_id) { - hash_map::Entry::Occupied(mut payment) => { - match payment.get() { - PendingOutboundPayment::Retryable { - total_msat, keysend_preimage, payment_secret, payment_metadata, - custom_tlvs, pending_amt_msat, invoice_request, .. - } => { - const RETRY_OVERFLOW_PERCENTAGE: u64 = 10; - let retry_amt_msat = route.get_total_amount(); - if retry_amt_msat + *pending_amt_msat > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 { - log_error!(logger, "retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat); - abandon_with_entry!(payment, PaymentFailureReason::UnexpectedError); - return - } + hash_map::Entry::Occupied(mut payment) => match payment.get() { + PendingOutboundPayment::Retryable { + total_msat, + keysend_preimage, + payment_secret, + payment_metadata, + custom_tlvs, + pending_amt_msat, + invoice_request, + .. + } => { + const RETRY_OVERFLOW_PERCENTAGE: u64 = 10; + let retry_amt_msat = route.get_total_amount(); + if retry_amt_msat + *pending_amt_msat + > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 + { + log_error!(logger, "retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat); + abandon_with_entry!(payment, PaymentFailureReason::UnexpectedError); + return; + } - if !payment.get().is_retryable_now() { - log_error!(logger, "Retries exhausted for payment id {}", &payment_id); - abandon_with_entry!(payment, PaymentFailureReason::RetriesExhausted); - return - } + if !payment.get().is_retryable_now() { + log_error!(logger, "Retries exhausted for payment id {}", &payment_id); + abandon_with_entry!(payment, PaymentFailureReason::RetriesExhausted); + return; + } - let total_msat = *total_msat; - let recipient_onion = RecipientOnionFields { - payment_secret: *payment_secret, - payment_metadata: payment_metadata.clone(), - custom_tlvs: custom_tlvs.clone(), - }; - let keysend_preimage = *keysend_preimage; - let invoice_request = invoice_request.clone(); - - let mut onion_session_privs = Vec::with_capacity(route.paths.len()); - for _ in 0..route.paths.len() { - onion_session_privs.push(entropy_source.get_secure_random_bytes()); - } + let total_msat = *total_msat; + let recipient_onion = RecipientOnionFields { + payment_secret: *payment_secret, + payment_metadata: payment_metadata.clone(), + custom_tlvs: custom_tlvs.clone(), + }; + let keysend_preimage = *keysend_preimage; + let invoice_request = invoice_request.clone(); + + let mut onion_session_privs = Vec::with_capacity(route.paths.len()); + for _ in 0..route.paths.len() { + onion_session_privs.push(entropy_source.get_secure_random_bytes()); + } - for (path, session_priv_bytes) in route.paths.iter().zip(onion_session_privs.iter()) { - assert!(payment.get_mut().insert(*session_priv_bytes, path)); - } + for (path, session_priv_bytes) in + route.paths.iter().zip(onion_session_privs.iter()) + { + assert!(payment.get_mut().insert(*session_priv_bytes, path)); + } - payment.get_mut().increment_attempts(); + payment.get_mut().increment_attempts(); - (total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request) - }, - PendingOutboundPayment::Legacy { .. } => { - log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102"); - return - }, - PendingOutboundPayment::AwaitingInvoice { .. } - | PendingOutboundPayment::AwaitingOffer { .. } => - { - log_error!(logger, "Payment not yet sent"); - debug_assert!(false); - return - }, - PendingOutboundPayment::InvoiceReceived { .. } => { - log_error!(logger, "Payment already initiating"); - debug_assert!(false); - return - }, - PendingOutboundPayment::StaticInvoiceReceived { .. } => { - log_error!(logger, "Payment already initiating"); - debug_assert!(false); - return - }, - PendingOutboundPayment::Fulfilled { .. } => { - log_error!(logger, "Payment already completed"); - return - }, - PendingOutboundPayment::Abandoned { .. } => { - log_error!(logger, "Payment already abandoned (with some HTLCs still pending)"); - return - }, - } + ( + total_msat, + recipient_onion, + keysend_preimage, + onion_session_privs, + invoice_request, + ) + }, + PendingOutboundPayment::Legacy { .. } => { + log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102"); + return; + }, + PendingOutboundPayment::AwaitingInvoice { .. } + | PendingOutboundPayment::AwaitingOffer { .. } => { + log_error!(logger, "Payment not yet sent"); + debug_assert!(false); + return; + }, + PendingOutboundPayment::InvoiceReceived { .. } => { + log_error!(logger, "Payment already initiating"); + debug_assert!(false); + return; + }, + PendingOutboundPayment::StaticInvoiceReceived { .. } => { + log_error!(logger, "Payment already initiating"); + debug_assert!(false); + return; + }, + PendingOutboundPayment::Fulfilled { .. } => { + log_error!(logger, "Payment already completed"); + return; + }, + PendingOutboundPayment::Abandoned { .. } => { + log_error!( + logger, + "Payment already abandoned (with some HTLCs still pending)" + ); + return; + }, }, hash_map::Entry::Vacant(_) => { log_error!(logger, "Payment with ID {} not found", &payment_id); - return - } + return; + }, } }; - let res = self.pay_route_internal(&route, payment_hash, &recipient_onion, keysend_preimage, - invoice_request.as_ref(), payment_id, Some(total_msat), &onion_session_privs, node_signer, - best_block_height, &send_payment_along_path); + let res = self.pay_route_internal( + &route, + payment_hash, + &recipient_onion, + keysend_preimage, + invoice_request.as_ref(), + payment_id, + Some(total_msat), + &onion_session_privs, + node_signer, + best_block_height, + &send_payment_along_path, + ); log_info!(logger, "Result retrying payment id {}: {:?}", &payment_id, res); if let Err(e) = res { self.handle_pay_route_err( - e, payment_id, payment_hash, route, route_params, onion_session_privs, router, first_hops, - inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, - send_payment_along_path + e, + payment_id, + payment_hash, + route, + route_params, + onion_session_privs, + router, + first_hops, + inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + send_payment_along_path, ); } } fn handle_pay_route_err( - &self, err: PaymentSendFailure, payment_id: PaymentId, payment_hash: PaymentHash, route: Route, - mut route_params: RouteParameters, onion_session_privs: Vec<[u8; 32]>, router: &R, - first_hops: Vec, inflight_htlcs: &IH, entropy_source: &ES, node_signer: &NS, - best_block_height: u32, logger: &L, + &self, err: PaymentSendFailure, payment_id: PaymentId, payment_hash: PaymentHash, + route: Route, mut route_params: RouteParameters, onion_session_privs: Vec<[u8; 32]>, + router: &R, first_hops: Vec, inflight_htlcs: &IH, entropy_source: &ES, + node_signer: &NS, best_block_height: u32, logger: &L, pending_events: &Mutex)>>, send_payment_along_path: &SP, - ) - where + ) where R::Target: Router, ES::Target: EntropySource, NS::Target: NodeSigner, @@ -1550,29 +1969,80 @@ impl OutboundPayments { { match err { PaymentSendFailure::AllFailedResendSafe(errs) => { - self.remove_session_privs(payment_id, route.paths.iter().zip(onion_session_privs.iter())); - Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, errs.into_iter().map(|e| Err(e)), logger, pending_events); - self.find_route_and_send_payment(payment_hash, payment_id, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path); + self.remove_session_privs( + payment_id, + route.paths.iter().zip(onion_session_privs.iter()), + ); + Self::push_path_failed_evs_and_scids( + payment_id, + payment_hash, + &mut route_params, + route.paths, + errs.into_iter().map(|e| Err(e)), + logger, + pending_events, + ); + self.find_route_and_send_payment( + payment_hash, + payment_id, + route_params, + router, + first_hops, + inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + send_payment_along_path, + ); }, - PaymentSendFailure::PartialFailure { failed_paths_retry: Some(mut retry), results, .. } => { + PaymentSendFailure::PartialFailure { + failed_paths_retry: Some(mut retry), + results, + .. + } => { debug_assert_eq!(results.len(), route.paths.len()); debug_assert_eq!(results.len(), onion_session_privs.len()); - let failed_paths = results.iter().zip(route.paths.iter().zip(onion_session_privs.iter())) + let failed_paths = results + .iter() + .zip(route.paths.iter().zip(onion_session_privs.iter())) .filter_map(|(path_res, (path, session_priv))| { match path_res { // While a MonitorUpdateInProgress is an Err(_), the payment is still // considered "in flight" and we shouldn't remove it from the // PendingOutboundPayment set. Ok(_) | Err(APIError::MonitorUpdateInProgress) => None, - _ => Some((path, session_priv)) + _ => Some((path, session_priv)), } }); self.remove_session_privs(payment_id, failed_paths); - Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut retry, route.paths, results.into_iter(), logger, pending_events); + Self::push_path_failed_evs_and_scids( + payment_id, + payment_hash, + &mut retry, + route.paths, + results.into_iter(), + logger, + pending_events, + ); // Some paths were sent, even if we failed to send the full MPP value our recipient may // misbehave and claim the funds, at which point we have to consider the payment sent, so // return `Ok()` here, ignoring any retry errors. - self.find_route_and_send_payment(payment_hash, payment_id, retry, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path); + self.find_route_and_send_payment( + payment_hash, + payment_id, + retry, + router, + first_hops, + inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + send_payment_along_path, + ); }, PaymentSendFailure::PartialFailure { failed_paths_retry: None, .. } => { // This may happen if we send a payment and some paths fail, but only due to a temporary @@ -1581,29 +2051,62 @@ impl OutboundPayments { }, PaymentSendFailure::PathParameterError(results) => { log_error!(logger, "Failed to send to route due to parameter error in a single path. Your router is buggy"); - self.remove_session_privs(payment_id, route.paths.iter().zip(onion_session_privs.iter())); - Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, results.into_iter(), logger, pending_events); - self.abandon_payment(payment_id, PaymentFailureReason::UnexpectedError, pending_events); + self.remove_session_privs( + payment_id, + route.paths.iter().zip(onion_session_privs.iter()), + ); + Self::push_path_failed_evs_and_scids( + payment_id, + payment_hash, + &mut route_params, + route.paths, + results.into_iter(), + logger, + pending_events, + ); + self.abandon_payment( + payment_id, + PaymentFailureReason::UnexpectedError, + pending_events, + ); }, PaymentSendFailure::ParameterError(e) => { - log_error!(logger, "Failed to send to route due to parameter error: {:?}. Your router is buggy", e); - self.remove_session_privs(payment_id, route.paths.iter().zip(onion_session_privs.iter())); - self.abandon_payment(payment_id, PaymentFailureReason::UnexpectedError, pending_events); + log_error!( + logger, + "Failed to send to route due to parameter error: {:?}. Your router is buggy", + e + ); + self.remove_session_privs( + payment_id, + route.paths.iter().zip(onion_session_privs.iter()), + ); + self.abandon_payment( + payment_id, + PaymentFailureReason::UnexpectedError, + pending_events, + ); }, PaymentSendFailure::DuplicatePayment => debug_assert!(false), // unreachable } } - fn push_path_failed_evs_and_scids>, L: Deref>( + fn push_path_failed_evs_and_scids< + I: ExactSizeIterator + Iterator>, + L: Deref, + >( payment_id: PaymentId, payment_hash: PaymentHash, route_params: &mut RouteParameters, paths: Vec, path_results: I, logger: &L, pending_events: &Mutex)>>, - ) where L::Target: Logger { + ) where + L::Target: Logger, + { let mut events = pending_events.lock().unwrap(); debug_assert_eq!(paths.len(), path_results.len()); for (path, path_res) in paths.into_iter().zip(path_results) { if let Err(e) = path_res { - if let APIError::MonitorUpdateInProgress = e { continue } + if let APIError::MonitorUpdateInProgress = e { + continue; + } log_error!(logger, "Failed to send along path due to error: {:?}", e); let mut failed_scid = None; if let APIError::ChannelUnavailable { .. } = e { @@ -1611,18 +2114,21 @@ impl OutboundPayments { failed_scid = Some(scid); route_params.payment_params.previously_failed_channels.push(scid); } - events.push_back((events::Event::PaymentPathFailed { - payment_id: Some(payment_id), - payment_hash, - payment_failed_permanently: false, - failure: events::PathFailure::InitialSend { err: e }, - path, - short_channel_id: failed_scid, - #[cfg(any(test, feature = "_test_utils"))] - error_code: None, - #[cfg(any(test, feature = "_test_utils"))] - error_data: None, - }, None)); + events.push_back(( + events::Event::PaymentPathFailed { + payment_id: Some(payment_id), + payment_hash, + payment_failed_permanently: false, + failure: events::PathFailure::InitialSend { err: e }, + path, + short_channel_id: failed_scid, + #[cfg(any(test, feature = "_test_utils"))] + error_code: None, + #[cfg(any(test, feature = "_test_utils"))] + error_data: None, + }, + None, + )); } } } @@ -1630,12 +2136,15 @@ impl OutboundPayments { // If a payment fails after adding the pending payment but before any HTLCs are locked into // channels, we need to clear the session_privs in order for abandoning the payment to succeed. fn remove_session_privs<'a, I: Iterator>( - &self, payment_id: PaymentId, path_session_priv: I + &self, payment_id: PaymentId, path_session_priv: I, ) { if let Some(payment) = self.pending_outbound_payments.lock().unwrap().get_mut(&payment_id) { for (path, session_priv_bytes) in path_session_priv { let removed = payment.remove(session_priv_bytes, Some(path)); - debug_assert!(removed, "This can't happen as the payment has an entry for this path added by callers"); + debug_assert!( + removed, + "This can't happen as the payment has an entry for this path added by callers" + ); } } else { debug_assert!(false, "This can't happen as the payment was added by callers"); @@ -1644,7 +2153,7 @@ impl OutboundPayments { pub(super) fn send_probe( &self, path: Path, probing_cookie_secret: [u8; 32], entropy_source: &ES, node_signer: &NS, - best_block_height: u32, send_payment_along_path: F + best_block_height: u32, send_payment_along_path: F, ) -> Result<(PaymentHash, PaymentId), ProbeSendFailure> where ES::Target: EntropySource, @@ -1658,54 +2167,78 @@ impl OutboundPayments { if path.hops.len() < 2 && path.blinded_tail.is_none() { return Err(ProbeSendFailure::ParameterError(APIError::APIMisuseError { - err: "No need probing a path with less than two hops".to_string() - })) + err: "No need probing a path with less than two hops".to_string(), + })); } let route = Route { paths: vec![path], route_params: None }; - let onion_session_privs = self.add_new_pending_payment(payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id, None, &route, None, None, - entropy_source, best_block_height, None - ).map_err(|e| { - debug_assert!(matches!(e, PaymentSendFailure::DuplicatePayment)); - ProbeSendFailure::DuplicateProbe - })?; + let onion_session_privs = self + .add_new_pending_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + None, + &route, + None, + None, + entropy_source, + best_block_height, + None, + ) + .map_err(|e| { + debug_assert!(matches!(e, PaymentSendFailure::DuplicatePayment)); + ProbeSendFailure::DuplicateProbe + })?; let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); - match self.pay_route_internal(&route, payment_hash, &recipient_onion_fields, - None, None, payment_id, None, &onion_session_privs, node_signer, best_block_height, - &send_payment_along_path + match self.pay_route_internal( + &route, + payment_hash, + &recipient_onion_fields, + None, + None, + payment_id, + None, + &onion_session_privs, + node_signer, + best_block_height, + &send_payment_along_path, ) { Ok(()) => Ok((payment_hash, payment_id)), Err(e) => { self.remove_outbound_if_all_failed(payment_id, &e); match e { PaymentSendFailure::DuplicatePayment => Err(ProbeSendFailure::DuplicateProbe), - PaymentSendFailure::ParameterError(err) => Err(ProbeSendFailure::ParameterError(err)), + PaymentSendFailure::ParameterError(err) => { + Err(ProbeSendFailure::ParameterError(err)) + }, PaymentSendFailure::PartialFailure { results, .. } | PaymentSendFailure::PathParameterError(results) => { debug_assert_eq!(results.len(), 1); - let err = results.into_iter() + let err = results + .into_iter() .find(|res| res.is_err()) .map(|err| err.unwrap_err()) - .unwrap_or(APIError::APIMisuseError { err: "Unexpected error".to_owned() }); + .unwrap_or(APIError::APIMisuseError { + err: "Unexpected error".to_owned(), + }); Err(ProbeSendFailure::ParameterError(err)) }, PaymentSendFailure::AllFailedResendSafe(mut errors) => { debug_assert_eq!(errors.len(), 1); - let err = errors - .pop() - .unwrap_or(APIError::APIMisuseError { err: "Unexpected error".to_owned() }); + let err = errors.pop().unwrap_or(APIError::APIMisuseError { + err: "Unexpected error".to_owned(), + }); Err(ProbeSendFailure::ParameterError(err)) - } + }, } - } + }, } } #[cfg(test)] pub(super) fn test_set_payment_metadata( - &self, payment_id: PaymentId, new_payment_metadata: Option> + &self, payment_id: PaymentId, new_payment_metadata: Option>, ) { match self.pending_outbound_payments.lock().unwrap().get_mut(&payment_id).unwrap() { PendingOutboundPayment::Retryable { payment_metadata, .. } => { @@ -1717,25 +2250,51 @@ impl OutboundPayments { #[cfg(any(test, feature = "_externalize_tests"))] pub(super) fn test_add_new_pending_payment( - &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, - route: &Route, retry_strategy: Option, entropy_source: &ES, best_block_height: u32 - ) -> Result, PaymentSendFailure> where ES::Target: EntropySource { - self.add_new_pending_payment(payment_hash, recipient_onion, payment_id, None, route, retry_strategy, None, entropy_source, best_block_height, None) + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + payment_id: PaymentId, route: &Route, retry_strategy: Option, entropy_source: &ES, + best_block_height: u32, + ) -> Result, PaymentSendFailure> + where + ES::Target: EntropySource, + { + self.add_new_pending_payment( + payment_hash, + recipient_onion, + payment_id, + None, + route, + retry_strategy, + None, + entropy_source, + best_block_height, + None, + ) } pub(super) fn add_new_pending_payment( - &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, - keysend_preimage: Option, route: &Route, retry_strategy: Option, - payment_params: Option, entropy_source: &ES, best_block_height: u32, - bolt12_invoice: Option - ) -> Result, PaymentSendFailure> where ES::Target: EntropySource { + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + payment_id: PaymentId, keysend_preimage: Option, route: &Route, + retry_strategy: Option, payment_params: Option, + entropy_source: &ES, best_block_height: u32, bolt12_invoice: Option, + ) -> Result, PaymentSendFailure> + where + ES::Target: EntropySource, + { let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap(); match pending_outbounds.entry(payment_id) { hash_map::Entry::Occupied(_) => Err(PaymentSendFailure::DuplicatePayment), hash_map::Entry::Vacant(entry) => { let (payment, onion_session_privs) = Self::create_pending_payment( - payment_hash, recipient_onion, keysend_preimage, None, bolt12_invoice, route, retry_strategy, - payment_params, entropy_source, best_block_height + payment_hash, + recipient_onion, + keysend_preimage, + None, + bolt12_invoice, + route, + retry_strategy, + payment_params, + entropy_source, + best_block_height, ); entry.insert(payment); Ok(onion_session_privs) @@ -1747,7 +2306,7 @@ impl OutboundPayments { payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, keysend_preimage: Option, invoice_request: Option, bolt12_invoice: Option, route: &Route, retry_strategy: Option, - payment_params: Option, entropy_source: &ES, best_block_height: u32 + payment_params: Option, entropy_source: &ES, best_block_height: u32, ) -> (PendingOutboundPayment, Vec<[u8; 32]>) where ES::Target: EntropySource, @@ -1773,8 +2332,10 @@ impl OutboundPayments { custom_tlvs: recipient_onion.custom_tlvs, starting_block_height: best_block_height, total_msat: route.get_total_amount(), - remaining_max_total_routing_fee_msat: - route.route_params.as_ref().and_then(|p| p.max_total_routing_fee_msat), + remaining_max_total_routing_fee_msat: route + .route_params + .as_ref() + .and_then(|p| p.max_total_routing_fee_msat), }; for (path, session_priv_bytes) in route.paths.iter().zip(onion_session_privs.iter()) { @@ -1806,7 +2367,9 @@ impl OutboundPayments { } #[cfg(feature = "dnssec")] - pub(super) fn amt_msats_for_payment_awaiting_offer(&self, payment_id: PaymentId) -> Result { + pub(super) fn amt_msats_for_payment_awaiting_offer( + &self, payment_id: PaymentId, + ) -> Result { match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(entry) => match entry.get() { PendingOutboundPayment::AwaitingOffer { amount_msats, .. } => Ok(*amount_msats), @@ -1823,7 +2386,10 @@ impl OutboundPayments { match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(entry) => match entry.get() { PendingOutboundPayment::AwaitingOffer { - expiration, retry_strategy, route_params_config, .. + expiration, + retry_strategy, + route_params_config, + .. } => { let mut new_val = PendingOutboundPayment::AwaitingInvoice { expiration: *expiration, @@ -1842,7 +2408,8 @@ impl OutboundPayments { pub(super) fn add_new_awaiting_invoice( &self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry, - route_params_config: RouteParametersConfig, retryable_invoice_request: Option + route_params_config: RouteParametersConfig, + retryable_invoice_request: Option, ) -> Result<(), ()> { let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap(); match pending_outbounds.entry(payment_id) { @@ -1867,40 +2434,62 @@ impl OutboundPayments { &self, route: &Route, payment_hash: PaymentHash, recipient_onion: &RecipientOnionFields, keysend_preimage: Option, invoice_request: Option<&InvoiceRequest>, payment_id: PaymentId, recv_value_msat: Option, onion_session_privs: &Vec<[u8; 32]>, - node_signer: &NS, best_block_height: u32, send_payment_along_path: &F + node_signer: &NS, best_block_height: u32, send_payment_along_path: &F, ) -> Result<(), PaymentSendFailure> where NS::Target: NodeSigner, F: Fn(SendAlongPathArgs) -> Result<(), APIError>, { if route.paths.len() < 1 { - return Err(PaymentSendFailure::ParameterError(APIError::InvalidRoute{err: "There must be at least one path to send over".to_owned()})); + return Err(PaymentSendFailure::ParameterError(APIError::InvalidRoute { + err: "There must be at least one path to send over".to_owned(), + })); } - if recipient_onion.payment_secret.is_none() && route.paths.len() > 1 + if recipient_onion.payment_secret.is_none() + && route.paths.len() > 1 && !route.paths.iter().any(|p| p.blinded_tail.is_some()) { - return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError{err: "Payment secret is required for multi-path payments".to_owned()})); + return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { + err: "Payment secret is required for multi-path payments".to_owned(), + })); } let mut total_value = 0; let our_node_id = node_signer.get_node_id(Recipient::Node).unwrap(); // TODO no unwrap let mut path_errs = Vec::with_capacity(route.paths.len()); 'path_check: for path in route.paths.iter() { if path.hops.len() < 1 || path.hops.len() > 20 { - path_errs.push(Err(APIError::InvalidRoute{err: "Path didn't go anywhere/had bogus size".to_owned()})); + path_errs.push(Err(APIError::InvalidRoute { + err: "Path didn't go anywhere/had bogus size".to_owned(), + })); continue 'path_check; } - let dest_hop_idx = if path.blinded_tail.is_some() && path.blinded_tail.as_ref().unwrap().hops.len() > 1 { - usize::max_value() } else { path.hops.len() - 1 }; + let dest_hop_idx = if path.blinded_tail.is_some() + && path.blinded_tail.as_ref().unwrap().hops.len() > 1 + { + usize::max_value() + } else { + path.hops.len() - 1 + }; for (idx, hop) in path.hops.iter().enumerate() { if idx != dest_hop_idx && hop.pubkey == our_node_id { - path_errs.push(Err(APIError::InvalidRoute{err: "Path went through us but wasn't a simple rebalance loop to us".to_owned()})); + path_errs.push(Err(APIError::InvalidRoute { + err: "Path went through us but wasn't a simple rebalance loop to us" + .to_owned(), + })); continue 'path_check; } } for (i, hop) in path.hops.iter().enumerate() { // Check for duplicate channel_id in the remaining hops of the path - if path.hops.iter().skip(i + 1).any(|other_hop| other_hop.short_channel_id == hop.short_channel_id) { - path_errs.push(Err(APIError::InvalidRoute{err: "Path went through the same channel twice".to_owned()})); + if path + .hops + .iter() + .skip(i + 1) + .any(|other_hop| other_hop.short_channel_id == hop.short_channel_id) + { + path_errs.push(Err(APIError::InvalidRoute { + err: "Path went through the same channel twice".to_owned(), + })); continue 'path_check; } } @@ -1919,9 +2508,15 @@ impl OutboundPayments { debug_assert_eq!(route.paths.len(), onion_session_privs.len()); for (path, session_priv_bytes) in route.paths.iter().zip(onion_session_privs.iter()) { let path_res = send_payment_along_path(SendAlongPathArgs { - path: &path, payment_hash: &payment_hash, recipient_onion, total_value, - cur_height, payment_id, keysend_preimage: &keysend_preimage, invoice_request, - session_priv_bytes: *session_priv_bytes + path: &path, + payment_hash: &payment_hash, + recipient_onion, + total_value, + cur_height, + payment_id, + keysend_preimage: &keysend_preimage, + invoice_request, + session_priv_bytes: *session_priv_bytes, }); results.push(path_res); } @@ -1936,7 +2531,9 @@ impl OutboundPayments { total_ok_fees_msat += path.fee_msat(); total_ok_amt_sent_msat += path.final_value_msat(); } - if res.is_err() { has_err = true; } + if res.is_err() { + has_err = true; + } if let &Err(APIError::MonitorUpdateInProgress) = res { // MonitorUpdateInProgress is inherently unsafe to retry, so we call it a // PartialFailure. @@ -1958,18 +2555,25 @@ impl OutboundPayments { // We calculate the leftover fee budget we're allowed to spend by // subtracting the used fee from the total fee budget. route_params.max_total_routing_fee_msat = route_params - .max_total_routing_fee_msat.map(|m| m.saturating_sub(total_ok_fees_msat)); + .max_total_routing_fee_msat + .map(|m| m.saturating_sub(total_ok_fees_msat)); // We calculate the remaining target amount by subtracting the succeded // path values. - route_params.final_value_msat = route_params.final_value_msat - .saturating_sub(total_ok_amt_sent_msat); + route_params.final_value_msat = + route_params.final_value_msat.saturating_sub(total_ok_amt_sent_msat); Some(route_params) - } else { None } - } else { None }, + } else { + None + } + } else { + None + }, }) } else if has_err { - Err(PaymentSendFailure::AllFailedResendSafe(results.drain(..).map(|r| r.unwrap_err()).collect())) + Err(PaymentSendFailure::AllFailedResendSafe( + results.drain(..).map(|r| r.unwrap_err()).collect(), + )) } else { Ok(()) } @@ -1978,18 +2582,31 @@ impl OutboundPayments { #[cfg(any(test, feature = "_externalize_tests"))] pub(super) fn test_send_payment_internal( &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, - keysend_preimage: Option, payment_id: PaymentId, recv_value_msat: Option, - onion_session_privs: Vec<[u8; 32]>, node_signer: &NS, best_block_height: u32, - send_payment_along_path: F + keysend_preimage: Option, payment_id: PaymentId, + recv_value_msat: Option, onion_session_privs: Vec<[u8; 32]>, node_signer: &NS, + best_block_height: u32, send_payment_along_path: F, ) -> Result<(), PaymentSendFailure> where NS::Target: NodeSigner, F: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - self.pay_route_internal(route, payment_hash, &recipient_onion, - keysend_preimage, None, payment_id, recv_value_msat, &onion_session_privs, - node_signer, best_block_height, &send_payment_along_path) - .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e }) + self.pay_route_internal( + route, + payment_hash, + &recipient_onion, + keysend_preimage, + None, + payment_id, + recv_value_msat, + &onion_session_privs, + node_signer, + best_block_height, + &send_payment_along_path, + ) + .map_err(|e| { + self.remove_outbound_if_all_failed(payment_id, &e); + e + }) } // If we failed to send any paths, remove the new PaymentId from the `pending_outbound_payments` @@ -1997,13 +2614,13 @@ impl OutboundPayments { fn remove_outbound_if_all_failed(&self, payment_id: PaymentId, err: &PaymentSendFailure) { match err { PaymentSendFailure::AllFailedResendSafe(_) - | PaymentSendFailure::ParameterError(_) - | PaymentSendFailure::PathParameterError(_) => - { - let removed = self.pending_outbound_payments.lock().unwrap().remove(&payment_id).is_some(); + | PaymentSendFailure::ParameterError(_) + | PaymentSendFailure::PathParameterError(_) => { + let removed = + self.pending_outbound_payments.lock().unwrap().remove(&payment_id).is_some(); debug_assert!(removed, "We should always have a pending payment to remove here"); }, - PaymentSendFailure::DuplicatePayment | PaymentSendFailure::PartialFailure { .. } => {} + PaymentSendFailure::DuplicatePayment | PaymentSendFailure::PartialFailure { .. } => {}, } } @@ -2012,7 +2629,9 @@ impl OutboundPayments { path: Path, from_onchain: bool, ev_completion_action: EventCompletionAction, pending_events: &Mutex)>>, logger: &L, - ) where L::Target: Logger { + ) where + L::Target: Logger, + { let mut session_priv_bytes = [0; 32]; session_priv_bytes.copy_from_slice(&session_priv[..]); let mut outbounds = self.pending_outbound_payments.lock().unwrap(); @@ -2023,14 +2642,17 @@ impl OutboundPayments { log_info!(logger, "Payment with id {} and hash {} sent!", payment_id, payment_hash); let fee_paid_msat = payment.get().get_pending_fee_msat(); let amount_msat = payment.get().total_msat(); - pending_events.push_back((events::Event::PaymentSent { - payment_id: Some(payment_id), - payment_preimage, - payment_hash, - amount_msat, - fee_paid_msat, - bolt12_invoice: payment.get().bolt12_invoice().cloned(), - }, Some(ev_completion_action.clone()))); + pending_events.push_back(( + events::Event::PaymentSent { + payment_id: Some(payment_id), + payment_preimage, + payment_hash, + amount_msat, + fee_paid_msat, + bolt12_invoice: payment.get().bolt12_invoice().cloned(), + }, + Some(ev_completion_action.clone()), + )); payment.get_mut().mark_fulfilled(); } @@ -2042,22 +2664,27 @@ impl OutboundPayments { // TODO: We should have a second monitor event that informs us of payments // irrevocably fulfilled. if payment.get_mut().remove(&session_priv_bytes, Some(&path)) { - let payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array())); - pending_events.push_back((events::Event::PaymentPathSuccessful { - payment_id, - payment_hash, - path, - }, Some(ev_completion_action))); + let payment_hash = + Some(PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array())); + pending_events.push_back(( + events::Event::PaymentPathSuccessful { payment_id, payment_hash, path }, + Some(ev_completion_action), + )); } } } else { - log_trace!(logger, "Received duplicative fulfill for HTLC with payment_preimage {}", &payment_preimage); + log_trace!( + logger, + "Received duplicative fulfill for HTLC with payment_preimage {}", + &payment_preimage + ); } } - pub(super) fn finalize_claims(&self, sources: Vec, - pending_events: &Mutex)>>) - { + pub(super) fn finalize_claims( + &self, sources: Vec, + pending_events: &Mutex)>>, + ) { let mut outbounds = self.pending_outbound_payments.lock().unwrap(); let mut pending_events = pending_events.lock().unwrap(); for source in sources { @@ -2069,11 +2696,10 @@ impl OutboundPayments { if payment.get_mut().remove(&session_priv_bytes, None) { let payment_hash = payment.get().payment_hash(); debug_assert!(payment_hash.is_some()); - pending_events.push_back((events::Event::PaymentPathSuccessful { - payment_id, - payment_hash, - path, - }, None)); + pending_events.push_back(( + events::Event::PaymentPathSuccessful { payment_id, payment_hash, path }, + None, + )); } } } @@ -2082,8 +2708,8 @@ impl OutboundPayments { pub(super) fn remove_stale_payments( &self, duration_since_epoch: Duration, - pending_events: &Mutex)>>) - { + pending_events: &Mutex)>>, + ) { let mut pending_outbound_payments = self.pending_outbound_payments.lock().unwrap(); let mut pending_events = pending_events.lock().unwrap(); pending_outbound_payments.retain(|payment_id, payment| match payment { @@ -2094,19 +2720,29 @@ impl OutboundPayments { // removal. This should be more than sufficient to ensure the idempotency of any // `send_payment` calls that were made at the same time the `PaymentSent` event was being // processed. - PendingOutboundPayment::Fulfilled { session_privs, timer_ticks_without_htlcs, .. } => { + PendingOutboundPayment::Fulfilled { + session_privs, timer_ticks_without_htlcs, .. + } => { let mut no_remaining_entries = session_privs.is_empty(); if no_remaining_entries { for (ev, _) in pending_events.iter() { match ev { - events::Event::PaymentSent { payment_id: Some(ev_payment_id), .. } | - events::Event::PaymentPathSuccessful { payment_id: ev_payment_id, .. } | - events::Event::PaymentPathFailed { payment_id: Some(ev_payment_id), .. } => { - if payment_id == ev_payment_id { - no_remaining_entries = false; - break; - } - }, + events::Event::PaymentSent { + payment_id: Some(ev_payment_id), .. + } + | events::Event::PaymentPathSuccessful { + payment_id: ev_payment_id, + .. + } + | events::Event::PaymentPathFailed { + payment_id: Some(ev_payment_id), + .. + } => { + if payment_id == ev_payment_id { + no_remaining_entries = false; + break; + } + }, _ => {}, } } @@ -2120,8 +2756,7 @@ impl OutboundPayments { } }, PendingOutboundPayment::AwaitingInvoice { expiration, .. } - | PendingOutboundPayment::AwaitingOffer { expiration, .. } => - { + | PendingOutboundPayment::AwaitingOffer { expiration, .. } => { let is_stale = match expiration { StaleExpiration::AbsoluteTimeout(absolute_expiry) => { *absolute_expiry <= duration_since_epoch @@ -2147,15 +2782,16 @@ impl OutboundPayments { true } }, - PendingOutboundPayment::StaticInvoiceReceived { route_params, payment_hash, .. } => { - let is_stale = - route_params.payment_params.expiry_time.unwrap_or(u64::MAX) < - duration_since_epoch.as_secs(); + PendingOutboundPayment::StaticInvoiceReceived { + route_params, payment_hash, .. + } => { + let is_stale = route_params.payment_params.expiry_time.unwrap_or(u64::MAX) + < duration_since_epoch.as_secs(); if is_stale { let fail_ev = events::Event::PaymentFailed { payment_id: *payment_id, payment_hash: Some(*payment_hash), - reason: Some(PaymentFailureReason::PaymentExpired) + reason: Some(PaymentFailureReason::PaymentExpired), }; pending_events.push_back((fail_ev, None)); false @@ -2172,16 +2808,29 @@ impl OutboundPayments { &self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, path: &Path, session_priv: &SecretKey, payment_id: &PaymentId, probing_cookie_secret: [u8; 32], secp_ctx: &Secp256k1, - pending_events: &Mutex)>>, logger: &L, - ) -> bool where L::Target: Logger { + pending_events: &Mutex)>>, + logger: &L, + ) -> bool + where + L::Target: Logger, + { #[cfg(any(test, feature = "_test_utils"))] let DecodedOnionFailure { - network_update, short_channel_id, payment_failed_permanently, onion_error_code, - onion_error_data, failed_within_blinded_path, .. + network_update, + short_channel_id, + payment_failed_permanently, + onion_error_code, + onion_error_data, + failed_within_blinded_path, + .. } = onion_error.decode_onion_failure(secp_ctx, logger, &source); #[cfg(not(any(test, feature = "_test_utils")))] let DecodedOnionFailure { - network_update, short_channel_id, payment_failed_permanently, failed_within_blinded_path, .. + network_update, + short_channel_id, + payment_failed_permanently, + failed_within_blinded_path, + .. } = onion_error.decode_onion_failure(secp_ctx, logger, &source); let payment_is_probe = payment_is_probe(payment_hash, &payment_id, probing_cookie_secret); @@ -2194,7 +2843,8 @@ impl OutboundPayments { let already_awaiting_retry = outbounds.iter().any(|(_, pmt)| { let mut awaiting_retry = false; if pmt.is_auto_retryable_now() { - if let PendingOutboundPayment::Retryable { pending_amt_msat, total_msat, .. } = pmt { + if let PendingOutboundPayment::Retryable { pending_amt_msat, total_msat, .. } = pmt + { if pending_amt_msat < total_msat { awaiting_retry = true; } @@ -2205,55 +2855,72 @@ impl OutboundPayments { let mut full_failure_ev = None; let mut pending_retry_ev = false; - let attempts_remaining = if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(*payment_id) { - if !payment.get_mut().remove(&session_priv_bytes, Some(&path)) { - log_trace!(logger, "Received duplicative fail for HTLC with payment_hash {}", &payment_hash); - return false - } - if payment.get().is_fulfilled() { - log_trace!(logger, "Received failure of HTLC with payment_hash {} after payment completion", &payment_hash); - return false - } - let mut is_retryable_now = payment.get().is_auto_retryable_now(); - if let Some(scid) = short_channel_id { - // TODO: If we decided to blame ourselves (or one of our channels) in - // process_onion_failure we should close that channel as it implies our - // next-hop is needlessly blaming us! - payment.get_mut().insert_previously_failed_scid(scid); - } - if failed_within_blinded_path { - debug_assert!(short_channel_id.is_none()); - if let Some(bt) = &path.blinded_tail { - payment.get_mut().insert_previously_failed_blinded_path(&bt); - } else { debug_assert!(false); } - } + let attempts_remaining = + if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(*payment_id) { + if !payment.get_mut().remove(&session_priv_bytes, Some(&path)) { + log_trace!( + logger, + "Received duplicative fail for HTLC with payment_hash {}", + &payment_hash + ); + return false; + } + if payment.get().is_fulfilled() { + log_trace!( + logger, + "Received failure of HTLC with payment_hash {} after payment completion", + &payment_hash + ); + return false; + } + let mut is_retryable_now = payment.get().is_auto_retryable_now(); + if let Some(scid) = short_channel_id { + // TODO: If we decided to blame ourselves (or one of our channels) in + // process_onion_failure we should close that channel as it implies our + // next-hop is needlessly blaming us! + payment.get_mut().insert_previously_failed_scid(scid); + } + if failed_within_blinded_path { + debug_assert!(short_channel_id.is_none()); + if let Some(bt) = &path.blinded_tail { + payment.get_mut().insert_previously_failed_blinded_path(&bt); + } else { + debug_assert!(false); + } + } - if payment_is_probe || !is_retryable_now || payment_failed_permanently { - let reason = if payment_failed_permanently { - PaymentFailureReason::RecipientRejected - } else { - PaymentFailureReason::RetriesExhausted - }; - payment.get_mut().mark_abandoned(reason); - is_retryable_now = false; - } - if payment.get().remaining_parts() == 0 { - if let PendingOutboundPayment::Abandoned { payment_hash, reason, .. } = payment.get() { - if !payment_is_probe { - full_failure_ev = Some(events::Event::PaymentFailed { - payment_id: *payment_id, - payment_hash: Some(*payment_hash), - reason: *reason, - }); + if payment_is_probe || !is_retryable_now || payment_failed_permanently { + let reason = if payment_failed_permanently { + PaymentFailureReason::RecipientRejected + } else { + PaymentFailureReason::RetriesExhausted + }; + payment.get_mut().mark_abandoned(reason); + is_retryable_now = false; + } + if payment.get().remaining_parts() == 0 { + if let PendingOutboundPayment::Abandoned { payment_hash, reason, .. } = + payment.get() + { + if !payment_is_probe { + full_failure_ev = Some(events::Event::PaymentFailed { + payment_id: *payment_id, + payment_hash: Some(*payment_hash), + reason: *reason, + }); + } + payment.remove(); } - payment.remove(); } - } - is_retryable_now - } else { - log_trace!(logger, "Received duplicative fail for HTLC with payment_hash {}", &payment_hash); - return false - }; + is_retryable_now + } else { + log_trace!( + logger, + "Received duplicative fail for HTLC with payment_hash {}", + &payment_hash + ); + return false; + }; core::mem::drop(outbounds); log_trace!(logger, "Failing outbound payment HTLC with payment_hash {}", &payment_hash); @@ -2290,19 +2957,21 @@ impl OutboundPayments { #[cfg(any(test, feature = "_test_utils"))] error_code: onion_error_code, #[cfg(any(test, feature = "_test_utils"))] - error_data: onion_error_data + error_data: onion_error_data, } } }; let mut pending_events = pending_events.lock().unwrap(); pending_events.push_back((path_failure, None)); - if let Some(ev) = full_failure_ev { pending_events.push_back((ev, None)); } + if let Some(ev) = full_failure_ev { + pending_events.push_back((ev, None)); + } pending_retry_ev } pub(super) fn abandon_payment( &self, payment_id: PaymentId, reason: PaymentFailureReason, - pending_events: &Mutex)>> + pending_events: &Mutex)>>, ) { let mut outbounds = self.pending_outbound_payments.lock().unwrap(); if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { @@ -2310,22 +2979,27 @@ impl OutboundPayments { match payment.get() { PendingOutboundPayment::Abandoned { payment_hash, reason, .. } => { if payment.get().remaining_parts() == 0 { - pending_events.lock().unwrap().push_back((events::Event::PaymentFailed { - payment_id, - payment_hash: Some(*payment_hash), - reason: *reason, - }, None)); + pending_events.lock().unwrap().push_back(( + events::Event::PaymentFailed { + payment_id, + payment_hash: Some(*payment_hash), + reason: *reason, + }, + None, + )); payment.remove(); } }, PendingOutboundPayment::AwaitingInvoice { .. } - | PendingOutboundPayment::AwaitingOffer { .. } => - { - pending_events.lock().unwrap().push_back((events::Event::PaymentFailed { - payment_id, - payment_hash: None, - reason: Some(reason), - }, None)); + | PendingOutboundPayment::AwaitingOffer { .. } => { + pending_events.lock().unwrap().push_back(( + events::Event::PaymentFailed { + payment_id, + payment_hash: None, + reason: Some(reason), + }, + None, + )); payment.remove(); }, _ => {}, @@ -2343,7 +3017,9 @@ impl OutboundPayments { self.pending_outbound_payments.lock().unwrap().clear() } - pub fn release_invoice_requests_awaiting_invoice(&self) -> Vec<(PaymentId, RetryableInvoiceRequest)> { + pub fn release_invoice_requests_awaiting_invoice( + &self, + ) -> Vec<(PaymentId, RetryableInvoiceRequest)> { if !self.awaiting_invoice.load(Ordering::Acquire) { return vec![]; } @@ -2353,12 +3029,16 @@ impl OutboundPayments { .iter_mut() .filter_map(|(payment_id, payment)| { if let PendingOutboundPayment::AwaitingInvoice { - retryable_invoice_request: Some(invreq), .. - } = payment { + retryable_invoice_request: Some(invreq), + .. + } = payment + { if invreq.needs_retry { invreq.needs_retry = false; Some((*payment_id, invreq.clone())) - } else { None } + } else { + None + } } else { None } @@ -2371,7 +3051,7 @@ impl OutboundPayments { pub(super) fn insert_from_monitor_on_startup( &self, payment_id: PaymentId, payment_hash: PaymentHash, session_priv_bytes: [u8; 32], - path: &Path, best_block_height: u32, logger: L + path: &Path, best_block_height: u32, logger: L, ) { let path_amt = path.final_value_msat(); let path_fee = path.fee_msat(); @@ -2402,11 +3082,10 @@ impl OutboundPayments { match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(mut entry) => { let newly_added = match entry.get() { - PendingOutboundPayment::AwaitingOffer { .. } | - PendingOutboundPayment::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } | - PendingOutboundPayment::StaticInvoiceReceived { .. } => - { + PendingOutboundPayment::AwaitingOffer { .. } + | PendingOutboundPayment::AwaitingInvoice { .. } + | PendingOutboundPayment::InvoiceReceived { .. } + | PendingOutboundPayment::StaticInvoiceReceived { .. } => { // If we've reached this point, it means we initiated a payment to a BOLT 12 invoice and // locked the htlc(s) into the `ChannelMonitor`(s), but failed to persist the // `ChannelManager` after transitioning from this state to `Retryable` prior to shutdown. @@ -2415,13 +3094,12 @@ impl OutboundPayments { *entry.get_mut() = new_retryable!(); true }, - PendingOutboundPayment::Legacy { .. } | - PendingOutboundPayment::Retryable { .. } | - PendingOutboundPayment::Fulfilled { .. } | - PendingOutboundPayment::Abandoned { .. } => - { + PendingOutboundPayment::Legacy { .. } + | PendingOutboundPayment::Retryable { .. } + | PendingOutboundPayment::Fulfilled { .. } + | PendingOutboundPayment::Abandoned { .. } => { entry.get_mut().insert(session_priv_bytes, &path) - } + }, }; log_info!(logger, "{} a pending payment path for {} msat for session priv {} on an existing pending payment with payment hash {}", if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), payment_hash); @@ -2430,16 +3108,16 @@ impl OutboundPayments { entry.insert(new_retryable!()); log_info!(logger, "Added a pending payment for {} msat with payment hash {} for path with session priv {}", path_amt, payment_hash, log_bytes!(session_priv_bytes)); - } + }, } } } /// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a /// payment probe. -pub(super) fn payment_is_probe(payment_hash: &PaymentHash, payment_id: &PaymentId, - probing_cookie_secret: [u8; 32]) -> bool -{ +pub(super) fn payment_is_probe( + payment_hash: &PaymentHash, payment_id: &PaymentId, probing_cookie_secret: [u8; 32], +) -> bool { let target_payment_hash = probing_cookie_from_id(payment_id, probing_cookie_secret); target_payment_hash == *payment_hash } @@ -2561,11 +3239,12 @@ mod tests { use crate::blinded_path::EmptyNodeIdLookUp; use crate::events::{Event, PathFailure, PaymentFailureReason}; - use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; use crate::ln::inbound_payment::ExpandedKey; - use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures}; - use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PendingOutboundPayment, Retry, RetryableSendFailure, StaleExpiration}; + use crate::ln::outbound_payment::{ + Bolt12PaymentError, OutboundPayments, PendingOutboundPayment, Retry, RetryableSendFailure, + StaleExpiration, + }; #[cfg(feature = "std")] use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY; use crate::offers::invoice_request::InvoiceRequest; @@ -2573,8 +3252,13 @@ mod tests { use crate::offers::offer::OfferBuilder; use crate::offers::test_utils::*; use crate::routing::gossip::NetworkGraph; - use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters, RouteParametersConfig}; + use crate::routing::router::{ + InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters, + RouteParametersConfig, + }; use crate::sync::{Arc, Mutex, RwLock}; + use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures}; + use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::errors::APIError; use crate::util::hash_tables::new_hash_map; use crate::util::test_utils; @@ -2585,21 +3269,13 @@ mod tests { fn test_recipient_onion_fields_with_custom_tlvs() { let onion_fields = RecipientOnionFields::spontaneous_empty(); - let bad_type_range_tlvs = vec![ - (0, vec![42]), - (1, vec![42; 32]), - ]; + let bad_type_range_tlvs = vec![(0, vec![42]), (1, vec![42; 32])]; assert!(onion_fields.clone().with_custom_tlvs(bad_type_range_tlvs).is_err()); - let keysend_tlv = vec![ - (5482373484, vec![42; 32]), - ]; + let keysend_tlv = vec![(5482373484, vec![42; 32])]; assert!(onion_fields.clone().with_custom_tlvs(keysend_tlv).is_err()); - let good_tlvs = vec![ - ((1 << 16) + 1, vec![42]), - ((1 << 16) + 3, vec![42; 32]), - ]; + let good_tlvs = vec![((1 << 16) + 1, vec![42]), ((1 << 16) + 3, vec![42; 32])]; assert!(onion_fields.with_custom_tlvs(good_tlvs).is_ok()); } @@ -2621,31 +3297,72 @@ mod tests { let past_expiry_time = std::time::SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() - 2; let payment_params = PaymentParameters::from_node_id( - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), - 0 - ).with_expiry_time(past_expiry_time); - let expired_route_params = RouteParameters::from_payment_params_and_value(payment_params, 0); + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), + 0, + ) + .with_expiry_time(past_expiry_time); + let expired_route_params = + RouteParameters::from_payment_params_and_value(payment_params, 0); let pending_events = Mutex::new(VecDeque::new()); if on_retry { - outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), - PaymentId([0; 32]), None, &Route { paths: vec![], route_params: None }, - Some(Retry::Attempts(1)), Some(expired_route_params.payment_params.clone()), - &&keys_manager, 0, None).unwrap(); + outbound_payments + .add_new_pending_payment( + PaymentHash([0; 32]), + RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), + None, + &Route { paths: vec![], route_params: None }, + Some(Retry::Attempts(1)), + Some(expired_route_params.payment_params.clone()), + &&keys_manager, + 0, + None, + ) + .unwrap(); outbound_payments.find_route_and_send_payment( - PaymentHash([0; 32]), PaymentId([0; 32]), expired_route_params, &&router, vec![], - &|| InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, - &|_| Ok(())); + PaymentHash([0; 32]), + PaymentId([0; 32]), + expired_route_params, + &&router, + vec![], + &|| InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + &|_| Ok(()), + ); let events = pending_events.lock().unwrap(); assert_eq!(events.len(), 1); if let Event::PaymentFailed { ref reason, .. } = events[0].0 { assert_eq!(reason.unwrap(), PaymentFailureReason::PaymentExpired); - } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } } else { - let err = outbound_payments.send_payment( - PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), - Retry::Attempts(0), expired_route_params, &&router, vec![], || InFlightHtlcs::new(), - &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, |_| Ok(())).unwrap_err(); - if let RetryableSendFailure::PaymentExpired = err { } else { panic!("Unexpected error"); } + let err = outbound_payments + .send_payment( + PaymentHash([0; 32]), + RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), + Retry::Attempts(0), + expired_route_params, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| Ok(()), + ) + .unwrap_err(); + if let RetryableSendFailure::PaymentExpired = err { + } else { + panic!("Unexpected error"); + } } } @@ -2664,30 +3381,71 @@ mod tests { let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let payment_params = PaymentParameters::from_node_id( - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0); + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), + 0, + ); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 0); router.expect_find_route(route_params.clone(), Err("")); let pending_events = Mutex::new(VecDeque::new()); if on_retry { - outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), - PaymentId([0; 32]), None, &Route { paths: vec![], route_params: None }, - Some(Retry::Attempts(1)), Some(route_params.payment_params.clone()), - &&keys_manager, 0, None).unwrap(); + outbound_payments + .add_new_pending_payment( + PaymentHash([0; 32]), + RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), + None, + &Route { paths: vec![], route_params: None }, + Some(Retry::Attempts(1)), + Some(route_params.payment_params.clone()), + &&keys_manager, + 0, + None, + ) + .unwrap(); outbound_payments.find_route_and_send_payment( - PaymentHash([0; 32]), PaymentId([0; 32]), route_params, &&router, vec![], - &|| InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, - &|_| Ok(())); + PaymentHash([0; 32]), + PaymentId([0; 32]), + route_params, + &&router, + vec![], + &|| InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + &|_| Ok(()), + ); let events = pending_events.lock().unwrap(); assert_eq!(events.len(), 1); - if let Event::PaymentFailed { .. } = events[0].0 { } else { panic!("Unexpected event"); } + if let Event::PaymentFailed { .. } = events[0].0 { + } else { + panic!("Unexpected event"); + } } else { - let err = outbound_payments.send_payment( - PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), - Retry::Attempts(0), route_params, &&router, vec![], || InFlightHtlcs::new(), - &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, |_| Ok(())).unwrap_err(); + let err = outbound_payments + .send_payment( + PaymentHash([0; 32]), + RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), + Retry::Attempts(0), + route_params, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| Ok(()), + ) + .unwrap_err(); if let RetryableSendFailure::RouteNotFound = err { - } else { panic!("Unexpected error"); } + } else { + panic!("Unexpected error"); + } } } @@ -2701,21 +3459,27 @@ mod tests { let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); - let sender_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let receiver_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap()); + let sender_pk = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); + let receiver_pk = + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap()); let payment_params = PaymentParameters::from_node_id(sender_pk, 0); - let route_params = RouteParameters::from_payment_params_and_value(payment_params.clone(), 0); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 0); let failed_scid = 42; let route = Route { - paths: vec![Path { hops: vec![RouteHop { - pubkey: receiver_pk, - node_features: NodeFeatures::empty(), - short_channel_id: failed_scid, - channel_features: ChannelFeatures::empty(), - fee_msat: 0, - cltv_expiry_delta: 0, - maybe_announced_channel: true, - }], blinded_tail: None }], + paths: vec![Path { + hops: vec![RouteHop { + pubkey: receiver_pk, + node_features: NodeFeatures::empty(), + short_channel_id: failed_scid, + channel_features: ChannelFeatures::empty(), + fee_msat: 0, + cltv_expiry_delta: 0, + maybe_announced_channel: true, + }], + blinded_tail: None, + }], route_params: Some(route_params.clone()), }; router.expect_find_route(route_params.clone(), Ok(route.clone())); @@ -2730,46 +3494,99 @@ mod tests { // Ensure that a ChannelUnavailable error will result in blaming an scid in the // PaymentPathFailed event. let pending_events = Mutex::new(VecDeque::new()); - outbound_payments.send_payment( - PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), - Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(), - &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, - |_| Err(APIError::ChannelUnavailable { err: "test".to_owned() })).unwrap(); + outbound_payments + .send_payment( + PaymentHash([0; 32]), + RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), + Retry::Attempts(0), + route_params.clone(), + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| Err(APIError::ChannelUnavailable { err: "test".to_owned() }), + ) + .unwrap(); let mut events = pending_events.lock().unwrap(); assert_eq!(events.len(), 2); if let Event::PaymentPathFailed { short_channel_id, - failure: PathFailure::InitialSend { err: APIError::ChannelUnavailable { .. }}, .. } = events[0].0 + failure: PathFailure::InitialSend { err: APIError::ChannelUnavailable { .. } }, + .. + } = events[0].0 { assert_eq!(short_channel_id, Some(failed_scid)); - } else { panic!("Unexpected event"); } - if let Event::PaymentFailed { .. } = events[1].0 { } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } + if let Event::PaymentFailed { .. } = events[1].0 { + } else { + panic!("Unexpected event"); + } events.clear(); core::mem::drop(events); // Ensure that a MonitorUpdateInProgress "error" will not result in a PaymentPathFailed event. - outbound_payments.send_payment( - PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), - Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(), - &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, - |_| Err(APIError::MonitorUpdateInProgress)).unwrap(); + outbound_payments + .send_payment( + PaymentHash([0; 32]), + RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), + Retry::Attempts(0), + route_params.clone(), + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| Err(APIError::MonitorUpdateInProgress), + ) + .unwrap(); assert_eq!(pending_events.lock().unwrap().len(), 0); // Ensure that any other error will result in a PaymentPathFailed event but no blamed scid. - outbound_payments.send_payment( - PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([1; 32]), - Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(), - &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, - |_| Err(APIError::APIMisuseError { err: "test".to_owned() })).unwrap(); + outbound_payments + .send_payment( + PaymentHash([0; 32]), + RecipientOnionFields::spontaneous_empty(), + PaymentId([1; 32]), + Retry::Attempts(0), + route_params.clone(), + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| Err(APIError::APIMisuseError { err: "test".to_owned() }), + ) + .unwrap(); let events = pending_events.lock().unwrap(); assert_eq!(events.len(), 2); if let Event::PaymentPathFailed { short_channel_id, - failure: PathFailure::InitialSend { err: APIError::APIMisuseError { .. }}, .. } = events[0].0 + failure: PathFailure::InitialSend { err: APIError::APIMisuseError { .. } }, + .. + } = events[0].0 { assert_eq!(short_channel_id, None); - } else { panic!("Unexpected event"); } - if let Event::PaymentFailed { .. } = events[1].0 { } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } + if let Event::PaymentFailed { .. } = events[1].0 { + } else { + panic!("Unexpected event"); + } } #[test] @@ -2782,11 +3599,15 @@ mod tests { let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(absolute_expiry)); assert!(!outbound_payments.has_pending_payments()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); for seconds_since_epoch in (0..absolute_expiry).step_by(tick_interval) { @@ -2804,26 +3625,37 @@ mod tests { assert!(!pending_events.lock().unwrap().is_empty()); assert_eq!( pending_events.lock().unwrap().pop_front(), - Some((Event::PaymentFailed { - payment_id, - payment_hash: None, - reason: Some(PaymentFailureReason::InvoiceRequestExpired), - }, None)), + Some(( + Event::PaymentFailed { + payment_id, + payment_hash: None, + reason: Some(PaymentFailureReason::InvoiceRequestExpired), + }, + None + )), ); assert!(pending_events.lock().unwrap().is_empty()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_err() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_err()); } #[test] @@ -2835,11 +3667,15 @@ mod tests { let expiration = StaleExpiration::TimerTicks(timer_ticks); assert!(!outbound_payments.has_pending_payments()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); for i in 0..timer_ticks { @@ -2857,26 +3693,37 @@ mod tests { assert!(!pending_events.lock().unwrap().is_empty()); assert_eq!( pending_events.lock().unwrap().pop_front(), - Some((Event::PaymentFailed { - payment_id, - payment_hash: None, - reason: Some(PaymentFailureReason::InvoiceRequestExpired), - }, None)), + Some(( + Event::PaymentFailed { + payment_id, + payment_hash: None, + reason: Some(PaymentFailureReason::InvoiceRequestExpired), + }, + None + )), ); assert!(pending_events.lock().unwrap().is_empty()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_err() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_err()); } #[test] @@ -2887,23 +3734,34 @@ mod tests { let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(100)); assert!(!outbound_payments.has_pending_payments()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); outbound_payments.abandon_payment( - payment_id, PaymentFailureReason::UserAbandoned, &pending_events + payment_id, + PaymentFailureReason::UserAbandoned, + &pending_events, ); assert!(!outbound_payments.has_pending_payments()); assert!(!pending_events.lock().unwrap().is_empty()); assert_eq!( pending_events.lock().unwrap().pop_front(), - Some((Event::PaymentFailed { - payment_id, payment_hash: None, reason: Some(PaymentFailureReason::UserAbandoned), - }, None)), + Some(( + Event::PaymentFailed { + payment_id, + payment_hash: None, + reason: Some(PaymentFailureReason::UserAbandoned), + }, + None + )), ); assert!(pending_events.lock().unwrap().is_empty()); } @@ -2925,28 +3783,49 @@ mod tests { let payment_id = PaymentId([0; 32]); let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(100)); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), RouteParametersConfig::default(), None, - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + RouteParametersConfig::default(), + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); let created_at = now() - DEFAULT_RELATIVE_EXPIRY; let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), created_at).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), created_at) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], Bolt12InvoiceFeatures::empty(), - || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, &EmptyNodeIdLookUp {}, - &secp_ctx, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + Bolt12InvoiceFeatures::empty(), + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + &EmptyNodeIdLookUp {}, + &secp_ctx, + 0, + &&logger, + &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::SendingFailed(RetryableSendFailure::PaymentExpired)), ); @@ -2981,21 +3860,31 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); - - let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee_msat(invoice.amount_msats() / 100 + 50_000); - - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), - route_params_config, None, - ).is_ok() - ); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); + + let route_params_config = RouteParametersConfig::default() + .with_max_total_routing_fee_msat(invoice.amount_msats() / 100 + 50_000); + + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + route_params_config, + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); let route_params = RouteParameters::from_payment_params_and_value( @@ -3006,9 +3895,20 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], Bolt12InvoiceFeatures::empty(), - || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, &EmptyNodeIdLookUp {}, - &secp_ctx, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + Bolt12InvoiceFeatures::empty(), + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + &EmptyNodeIdLookUp {}, + &secp_ctx, + 0, + &&logger, + &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::SendingFailed(RetryableSendFailure::RouteNotFound)), ); @@ -3043,12 +3943,18 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let route_params = RouteParameters { payment_params: PaymentParameters::from_bolt12_invoice(&invoice), @@ -3058,52 +3964,75 @@ mod tests { router.expect_find_route( route_params.clone(), Ok(Route { - paths: vec![ - Path { - hops: vec![ - RouteHop { - pubkey: recipient_pubkey(), - node_features: NodeFeatures::empty(), - short_channel_id: 42, - channel_features: ChannelFeatures::empty(), - fee_msat: invoice.amount_msats(), - cltv_expiry_delta: 0, - maybe_announced_channel: true, - } - ], - blinded_tail: None, - } - ], + paths: vec![Path { + hops: vec![RouteHop { + pubkey: recipient_pubkey(), + node_features: NodeFeatures::empty(), + short_channel_id: 42, + channel_features: ChannelFeatures::empty(), + fee_msat: invoice.amount_msats(), + cltv_expiry_delta: 0, + maybe_announced_channel: true, + }], + blinded_tail: None, + }], route_params: Some(route_params), - }) + }), ); assert!(!outbound_payments.has_pending_payments()); assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], Bolt12InvoiceFeatures::empty(), - || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, &EmptyNodeIdLookUp {}, - &secp_ctx, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + Bolt12InvoiceFeatures::empty(), + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + &EmptyNodeIdLookUp {}, + &secp_ctx, + 0, + &&logger, + &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::UnexpectedInvoice), ); assert!(!outbound_payments.has_pending_payments()); assert!(pending_events.lock().unwrap().is_empty()); - let route_params_config = RouteParametersConfig::default().with_max_total_routing_fee_msat(1234); + let route_params_config = + RouteParametersConfig::default().with_max_total_routing_fee_msat(1234); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), route_params_config, None, - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), + route_params_config, + None, + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], Bolt12InvoiceFeatures::empty(), - || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, &EmptyNodeIdLookUp {}, - &secp_ctx, 0, &&logger, &pending_events, |_| Ok(()) + &invoice, + payment_id, + &&router, + vec![], + Bolt12InvoiceFeatures::empty(), + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + &EmptyNodeIdLookUp {}, + &secp_ctx, + 0, + &&logger, + &pending_events, + |_| Ok(()) ), Ok(()), ); @@ -3112,9 +4041,20 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], Bolt12InvoiceFeatures::empty(), - || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, &EmptyNodeIdLookUp {}, - &secp_ctx, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + Bolt12InvoiceFeatures::empty(), + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + &EmptyNodeIdLookUp {}, + &secp_ctx, + 0, + &&logger, + &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::DuplicateInvoice), ); @@ -3131,7 +4071,8 @@ mod tests { OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() + .build() + .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() .build_and_sign() @@ -3166,7 +4107,8 @@ mod tests { core::mem::drop(outbounds); // The payment will not be removed if it isn't expired yet. - outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry), &pending_events); + outbound_payments + .remove_stale_payments(Duration::from_secs(absolute_expiry), &pending_events); let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap(); assert_eq!(outbounds.len(), 1); let events = pending_events.lock().unwrap(); @@ -3174,16 +4116,23 @@ mod tests { core::mem::drop(outbounds); core::mem::drop(events); - outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry + 1), &pending_events); + outbound_payments + .remove_stale_payments(Duration::from_secs(absolute_expiry + 1), &pending_events); let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap(); assert_eq!(outbounds.len(), 0); let events = pending_events.lock().unwrap(); assert_eq!(events.len(), 1); - assert_eq!(events[0], (Event::PaymentFailed { - payment_hash: Some(payment_hash), - payment_id, - reason: Some(PaymentFailureReason::PaymentExpired), - }, None)); + assert_eq!( + events[0], + ( + Event::PaymentFailed { + payment_hash: Some(payment_hash), + payment_id, + reason: Some(PaymentFailureReason::PaymentExpired), + }, + None + ) + ); } #[test] @@ -3214,16 +4163,24 @@ mod tests { core::mem::drop(outbounds); outbound_payments.abandon_payment( - payment_id, PaymentFailureReason::UserAbandoned, &pending_events + payment_id, + PaymentFailureReason::UserAbandoned, + &pending_events, ); let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap(); assert_eq!(outbounds.len(), 0); let events = pending_events.lock().unwrap(); assert_eq!(events.len(), 1); - assert_eq!(events[0], (Event::PaymentFailed { - payment_hash: Some(payment_hash), - payment_id, - reason: Some(PaymentFailureReason::UserAbandoned), - }, None)); + assert_eq!( + events[0], + ( + Event::PaymentFailed { + payment_hash: Some(payment_hash), + payment_id, + reason: Some(PaymentFailureReason::UserAbandoned), + }, + None + ) + ); } } diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index c62b80d5653..a51447a48a3 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -11,31 +11,46 @@ //! serialization ordering between ChannelManager/ChannelMonitors and ensuring we can still retry //! payments thereafter. +use crate::chain::channelmonitor::{ + ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, +}; use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen}; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS}; -use crate::sign::EntropySource; -use crate::events::{ClosureReason, Event, HTLCDestination, PathFailure, PaymentFailureReason, PaymentPurpose}; -use crate::ln::channel::{EXPIRE_PREV_CONFIG_TICKS, get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI}; -use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, RecentPaymentDetails, RecipientOnionFields, HTLCForwardInfo, PendingHTLCRouting, PendingAddHTLCInfo}; -use crate::types::features::{Bolt11InvoiceFeatures, ChannelTypeFeatures}; -use crate::ln::msgs; -use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentHash, PaymentSecret, PaymentPreimage}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, PathFailure, PaymentFailureReason, PaymentPurpose, +}; use crate::ln::chan_utils; +use crate::ln::channel::{ + get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI, + EXPIRE_PREV_CONFIG_TICKS, +}; +use crate::ln::channelmanager::{ + HTLCForwardInfo, PaymentId, PendingAddHTLCInfo, PendingHTLCRouting, RecentPaymentDetails, + RecipientOnionFields, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MPP_TIMEOUT_TICKS, +}; +use crate::ln::msgs; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent}; use crate::ln::onion_utils::{self, LocalHTLCFailureReason}; -use crate::ln::outbound_payment::{IDEMPOTENCY_TIMEOUT_TICKS, ProbeSendFailure, Retry, RetryableSendFailure}; +use crate::ln::outbound_payment::{ + ProbeSendFailure, Retry, RetryableSendFailure, IDEMPOTENCY_TIMEOUT_TICKS, +}; +use crate::ln::types::ChannelId; use crate::routing::gossip::{EffectiveCapacity, RoutingFees}; -use crate::routing::router::{get_route, Path, PaymentParameters, Route, Router, RouteHint, RouteHintHop, RouteHop, RouteParameters}; +use crate::routing::router::{ + get_route, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RouteParameters, + Router, +}; use crate::routing::scoring::ChannelUsage; +use crate::sign::EntropySource; +use crate::types::features::{Bolt11InvoiceFeatures, ChannelTypeFeatures}; +use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::config::UserConfig; -use crate::util::test_utils; use crate::util::errors::APIError; use crate::util::ser::Writeable; use crate::util::string::UntrustedString; +use crate::util::test_utils; -use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; use bitcoin::network::Network; use bitcoin::secp256k1::{Secp256k1, SecretKey}; @@ -48,7 +63,7 @@ use crate::routing::gossip::NodeId; #[cfg(feature = "std")] use { crate::util::time::Instant as TestTime, - std::time::{SystemTime, Instant, Duration}, + std::time::{Duration, Instant, SystemTime}, }; #[test] @@ -63,7 +78,8 @@ fn mpp_failure() { let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3).0.contents.short_channel_id; let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3).0.contents.short_channel_id; - let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); + let (mut route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[3], 100000); let path = route.paths[0].clone(); route.paths.push(path); route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -72,8 +88,20 @@ fn mpp_failure() { route.paths[1].hops[0].pubkey = nodes[2].node.get_our_node_id(); route.paths[1].hops[0].short_channel_id = chan_2_id; route.paths[1].hops[1].short_channel_id = chan_4_id; - send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, payment_secret); - fail_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_hash); + send_along_route_with_secret( + &nodes[0], + route, + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + 200_000, + payment_hash, + payment_secret, + ); + fail_payment_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_hash, + ); } #[test] @@ -88,14 +116,21 @@ fn mpp_retry() { let (chan_3_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 1, 3); let (chan_4_update, _, chan_4_id, _) = create_announced_chan_between_nodes(&nodes, 3, 2); // Rebalance - send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000); + send_payment(&nodes[3], &vec![&nodes[2]][..], 1_500_000); let amt_msat = 1_000_000; let max_total_routing_fee_msat = 50_000; - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()) + .unwrap(); let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!( - nodes[0], nodes[3], payment_params, amt_msat, Some(max_total_routing_fee_msat)); + nodes[0], + nodes[3], + payment_params, + amt_msat, + Some(max_total_routing_fee_msat) + ); let path = route.paths[0].clone(); route.paths.push(path); route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -110,48 +145,84 @@ fn mpp_retry() { let mut route_params = route.route_params.clone().unwrap(); nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - payment_id, route_params.clone(), Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + route_params.clone(), + Retry::Attempts(1), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); // one monitor per path let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); // Pass half of the payment along the success path. - let success_path_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 2_000_000, payment_hash, Some(payment_secret), success_path_msgs, false, None); + let success_path_msgs = + remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + 2_000_000, + payment_hash, + Some(payment_secret), + success_path_msgs, + false, + None, + ); // Add the HTLC along the first hop. - let fail_path_msgs_1 = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); + let fail_path_msgs_1 = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); let send_event = SendEvent::from_event(fail_path_msgs_1); nodes[2].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event.msgs[0]); commitment_signed_dance!(nodes[2], nodes[0], &send_event.commitment_msg, false); // Attempt to forward the payment and complete the 2nd path's failure. expect_pending_htlcs_forwardable!(&nodes[2]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[2], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_4_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + &nodes[2], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_4_id + }] + ); let htlc_updates = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); assert!(htlc_updates.update_add_htlcs.is_empty()); assert_eq!(htlc_updates.update_fail_htlcs.len(), 1); assert!(htlc_updates.update_fulfill_htlcs.is_empty()); assert!(htlc_updates.update_fail_malformed_htlcs.is_empty()); check_added_monitors!(nodes[2], 1); - nodes[0].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &htlc_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[2], htlc_updates.commitment_signed, false); let mut events = nodes[0].node.get_and_clear_pending_events(); match events[1] { Event::PendingHTLCsForwardable { .. } => {}, - _ => panic!("Unexpected event") + _ => panic!("Unexpected event"), } events.remove(1); - expect_payment_failed_conditions_event(events, payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain()); + expect_payment_failed_conditions_event( + events, + payment_hash, + false, + PaymentFailedConditions::new().mpp_parts_remain(), + ); // Rebalance the channel so the second half of the payment can succeed. - send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000); + send_payment(&nodes[3], &vec![&nodes[2]][..], 1_500_000); // Retry the second half of the payment and make sure it succeeds. route.paths.remove(0); route_params.final_value_msat = 1_000_000; - route_params.payment_params.previously_failed_channels.push(chan_4_update.contents.short_channel_id); + route_params + .payment_params + .previously_failed_channels + .push(chan_4_update.contents.short_channel_id); // Check the remaining max total routing fee for the second attempt is 50_000 - 1_000 msat fee // used by the first path route_params.max_total_routing_fee_msat = Some(max_total_routing_fee_msat - 1_000); @@ -161,10 +232,21 @@ fn mpp_retry() { check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 2_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + 2_000_000, + payment_hash, + Some(payment_secret), + events.pop().unwrap(), + true, + None, ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + payment_preimage, + )); } #[test] @@ -181,22 +263,41 @@ fn mpp_retry_overpay() { limited_config_1.channel_handshake_config.our_htlc_minimum_msat = 35_000_000; let mut limited_config_2 = user_config.clone(); limited_config_2.channel_handshake_config.our_htlc_minimum_msat = 34_500_000; - let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, - &[Some(user_config.clone()), Some(limited_config_1), Some(limited_config_2), Some(user_config)]); + let node_chanmgrs = create_node_chanmgrs( + 4, + &node_cfgs, + &[ + Some(user_config.clone()), + Some(limited_config_1), + Some(limited_config_2), + Some(user_config), + ], + ); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); - let (chan_1_update, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 40_000, 0); - let (chan_2_update, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 40_000, 0); - let (_chan_3_update, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 40_000, 0); - let (chan_4_update, _, chan_4_id, _) = create_announced_chan_between_nodes_with_value(&nodes, 3, 2, 40_000, 0); + let (chan_1_update, _, _, _) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 40_000, 0); + let (chan_2_update, _, _, _) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 40_000, 0); + let (_chan_3_update, _, _, _) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 40_000, 0); + let (chan_4_update, _, chan_4_id, _) = + create_announced_chan_between_nodes_with_value(&nodes, 3, 2, 40_000, 0); let amt_msat = 70_000_000; let max_total_routing_fee_msat = Some(1_000_000); - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()) + .unwrap(); let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!( - nodes[0], nodes[3], payment_params, amt_msat, max_total_routing_fee_msat); + nodes[0], + nodes[3], + payment_params, + amt_msat, + max_total_routing_fee_msat + ); // Check we overpay on the second path which we're about to fail. assert_eq!(chan_1_update.contents.fee_proportional_millionths, 0); @@ -213,28 +314,48 @@ fn mpp_retry_overpay() { let mut route_params = route.route_params.clone().unwrap(); nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - payment_id, route_params.clone(), Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + route_params.clone(), + Retry::Attempts(1), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); // one monitor per path let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); // Pass half of the payment along the success path. - let success_path_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], amt_msat, payment_hash, - Some(payment_secret), success_path_msgs, false, None); + let success_path_msgs = + remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + amt_msat, + payment_hash, + Some(payment_secret), + success_path_msgs, + false, + None, + ); // Add the HTLC along the first hop. - let fail_path_msgs_1 = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); + let fail_path_msgs_1 = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); let send_event = SendEvent::from_event(fail_path_msgs_1); nodes[2].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event.msgs[0]); commitment_signed_dance!(nodes[2], nodes[0], &send_event.commitment_msg, false); // Attempt to forward the payment and complete the 2nd path's failure. expect_pending_htlcs_forwardable!(&nodes[2]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[2], + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + &nodes[2], vec![HTLCDestination::NextHopChannel { - node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_4_id + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_4_id }] ); let htlc_updates = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); @@ -243,20 +364,26 @@ fn mpp_retry_overpay() { assert!(htlc_updates.update_fulfill_htlcs.is_empty()); assert!(htlc_updates.update_fail_malformed_htlcs.is_empty()); check_added_monitors!(nodes[2], 1); - nodes[0].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), - &htlc_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &htlc_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[2], htlc_updates.commitment_signed, false); let mut events = nodes[0].node.get_and_clear_pending_events(); match events[1] { Event::PendingHTLCsForwardable { .. } => {}, - _ => panic!("Unexpected event") + _ => panic!("Unexpected event"), } events.remove(1); - expect_payment_failed_conditions_event(events, payment_hash, false, - PaymentFailedConditions::new().mpp_parts_remain()); + expect_payment_failed_conditions_event( + events, + payment_hash, + false, + PaymentFailedConditions::new().mpp_parts_remain(), + ); // Rebalance the channel so the second half of the payment can succeed. - send_payment(&nodes[3], &vec!(&nodes[2])[..], 38_000_000); + send_payment(&nodes[3], &vec![&nodes[2]][..], 38_000_000); // Retry the second half of the payment and make sure it succeeds. let first_path_value = route.paths[0].final_value_msat(); @@ -264,7 +391,10 @@ fn mpp_retry_overpay() { route.paths.remove(0); route_params.final_value_msat -= first_path_value; - route_params.payment_params.previously_failed_channels.push(chan_4_update.contents.short_channel_id); + route_params + .payment_params + .previously_failed_channels + .push(chan_4_update.contents.short_channel_id); // Check the remaining max total routing fee for the second attempt accounts only for 1_000 msat // base fee, but not for overpaid value of the first try. route_params.max_total_routing_fee_msat.as_mut().map(|m| *m -= 1000); @@ -276,8 +406,16 @@ fn mpp_retry_overpay() { check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], amt_msat, payment_hash, - Some(payment_secret), events.pop().unwrap(), true, None); + pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + amt_msat, + payment_hash, + Some(payment_secret), + events.pop().unwrap(), + true, + None, + ); // Can't use claim_payment_along_route as it doesn't support overpayment, so we break out the // individual steps here. @@ -301,7 +439,8 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) { let (chan_3_update, _, chan_3_id, _) = create_announced_chan_between_nodes(&nodes, 1, 3); let (chan_4_update, _, _, _) = create_announced_chan_between_nodes(&nodes, 2, 3); - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 100_000); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[3], 100_000); let path = route.paths[0].clone(); route.paths.push(path); route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -312,15 +451,31 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) { route.paths[1].hops[1].short_channel_id = chan_4_update.contents.short_channel_id; // Initiate the MPP payment. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); // one monitor per path let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); // Pass half of the payment along the first path. let node_1_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 200_000, payment_hash, Some(payment_secret), node_1_msgs, false, None); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + 200_000, + payment_hash, + Some(payment_secret), + node_1_msgs, + false, + None, + ); if send_partial_mpp { // Time out the partial MPP @@ -329,35 +484,81 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) { } // Failed HTLC from node 3 -> 1 - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], vec![HTLCDestination::FailedPayment { payment_hash }]); - let htlc_fail_updates_3_1 = get_htlc_update_msgs!(nodes[3], nodes[1].node.get_our_node_id()); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[3], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); + let htlc_fail_updates_3_1 = + get_htlc_update_msgs!(nodes[3], nodes[1].node.get_our_node_id()); assert_eq!(htlc_fail_updates_3_1.update_fail_htlcs.len(), 1); - nodes[1].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &htlc_fail_updates_3_1.update_fail_htlcs[0]); + nodes[1].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &htlc_fail_updates_3_1.update_fail_htlcs[0], + ); check_added_monitors!(nodes[3], 1); - commitment_signed_dance!(nodes[1], nodes[3], htlc_fail_updates_3_1.commitment_signed, false); + commitment_signed_dance!( + nodes[1], + nodes[3], + htlc_fail_updates_3_1.commitment_signed, + false + ); // Failed HTLC from node 1 -> 0 - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_3_id }]); - let htlc_fail_updates_1_0 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_3_id + }] + ); + let htlc_fail_updates_1_0 = + get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert_eq!(htlc_fail_updates_1_0.update_fail_htlcs.len(), 1); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_fail_updates_1_0.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &htlc_fail_updates_1_0.update_fail_htlcs[0], + ); check_added_monitors!(nodes[1], 1); - commitment_signed_dance!(nodes[0], nodes[1], htlc_fail_updates_1_0.commitment_signed, false); + commitment_signed_dance!( + nodes[0], + nodes[1], + htlc_fail_updates_1_0.commitment_signed, + false + ); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain().expected_htlc_error_data(LocalHTLCFailureReason::MPPTimeout, &[][..])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .mpp_parts_remain() + .expected_htlc_error_data(LocalHTLCFailureReason::MPPTimeout, &[][..]), + ); } else { // Pass half of the payment along the second path. - let node_2_msgs = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash, Some(payment_secret), node_2_msgs, true, None); + let node_2_msgs = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); + pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + 200_000, + payment_hash, + Some(payment_secret), + node_2_msgs, + true, + None, + ); // Even after MPP_TIMEOUT_TICKS we should not timeout the MPP if we have all the parts for _ in 0..MPP_TIMEOUT_TICKS { nodes[3].node.timer_tick_occurred(); } - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) - ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + payment_preimage, + )); } } @@ -386,14 +587,22 @@ fn do_test_keysend_payments(public_node: bool) { } let payee_pubkey = nodes[1].node.get_our_node_id(); let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(payee_pubkey, 40, false), 10000); + PaymentParameters::for_keysend(payee_pubkey, 40, false), + 10000, + ); { let test_preimage = PaymentPreimage([42; 32]); - nodes[0].node.send_spontaneous_payment( - Some(test_preimage), RecipientOnionFields::spontaneous_empty(), PaymentId(test_preimage.0), - route_params, Retry::Attempts(1) - ).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + Some(test_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(test_preimage.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); } check_added_monitors!(nodes[0], 1); let send_event = SendEvent::from_node(&nodes[0]); @@ -406,9 +615,14 @@ fn do_test_keysend_payments(public_node: bool) { // extracting it from the onion nodes[1] received. let event = nodes[1].node.get_and_clear_pending_events(); assert_eq!(event.len(), 1); - if let Event::PaymentClaimable { purpose: PaymentPurpose::SpontaneousPayment(preimage), .. } = event[0] { + if let Event::PaymentClaimable { + purpose: PaymentPurpose::SpontaneousPayment(preimage), .. + } = event[0] + { claim_payment(&nodes[0], &[&nodes[1]], preimage); - } else { panic!(); } + } else { + panic!(); + } } #[test] @@ -426,14 +640,22 @@ fn test_mpp_keysend() { let payee_pubkey = nodes[3].node.get_our_node_id(); let recv_value = 15_000_000; let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(payee_pubkey, 40, true), recv_value); + PaymentParameters::for_keysend(payee_pubkey, 40, true), + recv_value, + ); let payment_preimage = PaymentPreimage([42; 32]); let payment_secret = PaymentSecret(payment_preimage.0); - let payment_hash = nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_preimage.0), route_params, Retry::Attempts(0) - ).unwrap(); + let payment_hash = nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_preimage.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]]; @@ -441,15 +663,33 @@ fn test_mpp_keysend() { assert_eq!(events.len(), 2); let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], expected_route[0], recv_value, payment_hash.clone(), - Some(payment_secret), ev.clone(), false, Some(payment_preimage)); + pass_along_path( + &nodes[0], + expected_route[0], + recv_value, + payment_hash.clone(), + Some(payment_secret), + ev.clone(), + false, + Some(payment_preimage), + ); let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], expected_route[1], recv_value, payment_hash.clone(), - Some(payment_secret), ev.clone(), true, Some(payment_preimage)); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage) + pass_along_path( + &nodes[0], + expected_route[1], + recv_value, + payment_hash.clone(), + Some(payment_secret), + ev.clone(), + true, + Some(payment_preimage), ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + expected_route, + payment_preimage, + )); } #[test] @@ -468,7 +708,8 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() { let (update_a, _, chan_4_channel_id, _) = create_announced_chan_between_nodes(&nodes, 2, 3); let chan_4_id = update_a.contents.short_channel_id; let amount = 40_000; - let (mut route, payment_hash, payment_preimage, _) = get_route_and_payment_hash!(nodes[0], nodes[3], amount); + let (mut route, payment_hash, payment_preimage, _) = + get_route_and_payment_hash!(nodes[0], nodes[3], amount); // Pay along nodes[1] route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -477,10 +718,16 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() { let payment_id_0 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); nodes[0].router.expect_find_route(route.route_params.clone().unwrap(), Ok(route.clone())); - nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_0, - route.route_params.clone().unwrap(), Retry::Attempts(0) - ).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_0, + route.route_params.clone().unwrap(), + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -501,16 +748,16 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() { for (_, pending_forwards) in nodes[3].node.forward_htlcs.lock().unwrap().iter_mut() { for f in pending_forwards.iter_mut() { match f { - &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => { - match forward_info.routing { - PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => { - *payment_data = Some(msgs::FinalOnionHopData { - payment_secret: PaymentSecret([42; 32]), - total_msat: amount * 2, - }); - }, - _ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"), - } + &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { + ref mut forward_info, .. + }) => match forward_info.routing { + PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => { + *payment_data = Some(msgs::FinalOnionHopData { + payment_secret: PaymentSecret([42; 32]), + total_msat: amount * 2, + }); + }, + _ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"), }, _ => {}, } @@ -525,10 +772,16 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() { let payment_id_1 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); nodes[0].router.expect_find_route(route.route_params.clone().unwrap(), Ok(route.clone())); - nodes[0].node.send_spontaneous_payment( - Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_1, - route.route_params.clone().unwrap(), Retry::Attempts(0) - ).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_1, + route.route_params.clone().unwrap(), + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_2 = get_htlc_update_msgs!(nodes[0], nodes[2].node.get_our_node_id()); @@ -549,7 +802,9 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() { for (_, pending_forwards) in nodes[3].node.forward_htlcs.lock().unwrap().iter_mut() { for f in pending_forwards.iter_mut() { match f { - &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => { + &mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { + ref mut forward_info, .. + }) => { match forward_info.routing { PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => { *payment_data = Some(msgs::FinalOnionHopData { @@ -565,24 +820,38 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() { } } nodes[3].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[3], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[3], 1); // Fail back along nodes[2] let update_fail_0 = get_htlc_update_msgs!(&nodes[3], &nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &update_fail_0.update_fail_htlcs[0]); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &update_fail_0.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[2], nodes[3], update_fail_0.commitment_signed, false); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_4_channel_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_4_channel_id + }] + ); check_added_monitors!(nodes[2], 1); let update_fail_1 = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &update_fail_1.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &update_fail_1.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[2], update_fail_1.commitment_signed, false); expect_payment_failed_conditions(&nodes[0], payment_hash, true, PaymentFailedConditions::new()); } - #[test] fn no_pending_leak_on_initial_send_failure() { // In an earlier version of our payment tracking, we'd have a retry entry even when the initial @@ -598,7 +867,8 @@ fn no_pending_leak_on_initial_send_failure() { create_announced_chan_between_nodes(&nodes, 0, 1); - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); @@ -640,11 +910,21 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // Send two payments - one which will get to nodes[2] and will be claimed, one which we'll time // out and retry. let amt_msat = 1_000_000; - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); - let (payment_preimage_1, payment_hash_1, _, payment_id_1) = send_along_route(&nodes[0], route.clone(), &[&nodes[1], &nodes[2]], 1_000_000); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); + let (payment_preimage_1, payment_hash_1, _, payment_id_1) = + send_along_route(&nodes[0], route.clone(), &[&nodes[1], &nodes[2]], 1_000_000); let route_params = route.route_params.unwrap().clone(); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -663,7 +943,10 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { expect_pending_htlcs_forwardable!(nodes[1]); expect_htlc_handling_failed_destinations!( nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2}] + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] ); check_added_monitors(&nodes[1], 1); // nodes[1] now immediately fails the HTLC as the next-hop channel is disconnected @@ -680,16 +963,31 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // The ChannelMonitor should always be the latest version, as we're required to persist it // during the `commitment_signed_dance!()`. let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - reload_node!(nodes[0], test_default_channel_config(), &nodes_0_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + test_default_channel_config(), + &nodes_0_serialized, + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and // force-close the channel. - check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::OutdatedChannelManager, + [nodes[1].node.get_our_node_id()], + 100000 + ); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[0].node.has_pending_payments()); nodes[0].node.timer_tick_occurred(); if !confirm_before_reload { - let as_broadcasted_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); + let as_broadcasted_txn = + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(as_broadcasted_txn.len(), 1); assert_eq!(as_broadcasted_txn[0].compute_txid(), as_commitment_tx.compute_txid()); } else { @@ -698,28 +996,52 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { check_added_monitors!(nodes[0], 1); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); // Now nodes[1] should send a channel reestablish, which nodes[0] will respond to with an // error, as the channel has hit the chain. - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_reestablish); let as_err = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(as_err.len(), 2); match as_err[1] { - MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => { + MessageSendEvent::HandleError { + node_id, + action: msgs::ErrorAction::SendErrorMessage { ref msg }, + } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()); nodes[1].node.handle_error(nodes[0].node.get_our_node_id(), msg); check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", &nodes[1].node.get_our_node_id())) }, [nodes[0].node.get_our_node_id()], 100000); check_added_monitors!(nodes[1], 1); - assert_eq!(nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0).len(), 1); + assert_eq!( + nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0).len(), + 1 + ); }, _ => panic!("Unexpected event"), } @@ -732,7 +1054,10 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { expect_payment_claimed!(nodes[2], payment_hash_1, 1_000_000); let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &htlc_fulfill_updates.update_fulfill_htlcs[0], + ); check_added_monitors!(nodes[1], 1); commitment_signed_dance!(nodes[1], nodes[2], htlc_fulfill_updates.commitment_signed, false); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], None, true, false); @@ -765,7 +1090,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { } mine_transaction(&nodes[0], &bs_htlc_claim_txn); expect_payment_sent(&nodes[0], payment_preimage_1, None, true, false); - connect_blocks(&nodes[0], TEST_FINAL_CLTV*4 + 20); + connect_blocks(&nodes[0], TEST_FINAL_CLTV * 4 + 20); let (first_htlc_timeout_tx, second_htlc_timeout_tx) = { let mut txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); assert_eq!(txn.len(), 2); @@ -773,13 +1098,19 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { }; check_spends!(first_htlc_timeout_tx, as_commitment_tx); check_spends!(second_htlc_timeout_tx, as_commitment_tx); - if first_htlc_timeout_tx.input[0].previous_output == bs_htlc_claim_txn.input[0].previous_output { + if first_htlc_timeout_tx.input[0].previous_output == bs_htlc_claim_txn.input[0].previous_output + { confirm_transaction(&nodes[0], &second_htlc_timeout_tx); } else { confirm_transaction(&nodes[0], &first_htlc_timeout_tx); } nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new()); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new(), + ); // Finally, retry the payment (which was reloaded from the ChannelMonitor when nodes[0] was // reloaded) via a route over the new channel, which work without issue and eventually be @@ -791,8 +1122,8 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // do_claim_payment_along_route expects us to never overpay. { let per_peer_state = nodes[1].node.per_peer_state.read().unwrap(); - let mut peer_state = per_peer_state.get(&nodes[2].node.get_our_node_id()) - .unwrap().lock().unwrap(); + let mut peer_state = + per_peer_state.get(&nodes[2].node.get_our_node_id()).unwrap().lock().unwrap(); let mut channel = peer_state.channel_by_id.get_mut(&chan_id_2).unwrap(); let mut new_config = channel.context().config(); new_config.forwarding_fee_base_msat += 100_000; @@ -805,17 +1136,42 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { nodes[1].node.timer_tick_occurred(); } - assert!(nodes[0].node.send_payment_with_route(new_route.clone(), payment_hash, // Shouldn't be allowed to retry a fulfilled payment - RecipientOnionFields::secret_only(payment_secret), payment_id_1).is_err()); - nodes[0].node.send_payment_with_route(new_route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + assert!(nodes[0] + .node + .send_payment_with_route( + new_route.clone(), + payment_hash, // Shouldn't be allowed to retry a fulfilled payment + RecipientOnionFields::secret_only(payment_secret), + payment_id_1 + ) + .is_err()); + nodes[0] + .node + .send_payment_with_route( + new_route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.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); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None); - do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[2]], + 1_000_000, + payment_hash, + Some(payment_secret), + events.pop().unwrap(), + true, + None, ); + do_claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + payment_preimage, + )); expect_payment_sent!(nodes[0], payment_preimage, Some(new_route.paths[0].hops[0].fee_msat)); } @@ -844,7 +1200,8 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { let third_persister; let third_new_chain_monitor; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(manually_accept_config), None]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[None, Some(manually_accept_config), None]); let first_nodes_0_deserialized; let second_nodes_0_deserialized; let third_nodes_0_deserialized; @@ -863,42 +1220,83 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // Serialize the ChannelManager prior to sending payments let mut nodes_0_serialized = nodes[0].node.encode(); - let route = get_route_and_payment_hash!(nodes[0], nodes[2], if use_dust { 1_000 } else { 1_000_000 }).0; - let (payment_preimage, payment_hash, payment_secret, payment_id) = send_along_route(&nodes[0], route, &[&nodes[1], &nodes[2]], if use_dust { 1_000 } else { 1_000_000 }); + let route = + get_route_and_payment_hash!(nodes[0], nodes[2], if use_dust { 1_000 } else { 1_000_000 }).0; + let (payment_preimage, payment_hash, payment_secret, payment_id) = send_along_route( + &nodes[0], + route, + &[&nodes[1], &nodes[2]], + if use_dust { 1_000 } else { 1_000_000 }, + ); // The ChannelMonitor should always be the latest version, as we're required to persist it // during the `commitment_signed_dance!()`. let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized], first_persister, first_new_chain_monitor, first_nodes_0_deserialized); + reload_node!( + nodes[0], + test_default_channel_config(), + nodes_0_serialized, + &[&chan_0_monitor_serialized], + first_persister, + first_new_chain_monitor, + first_nodes_0_deserialized + ); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and // force-close the channel. - check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::OutdatedChannelManager, + [nodes[1].node.get_our_node_id()], + 100000 + ); nodes[0].node.timer_tick_occurred(); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[0].node.has_pending_payments()); assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0).len(), 1); check_added_monitors!(nodes[0], 1); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); // Now nodes[1] should send a channel reestablish, which nodes[0] will respond to with an // error, as the channel has hit the chain. - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_reestablish); let as_err = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(as_err.len(), 2); let bs_commitment_tx; match as_err[1] { - MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => { + MessageSendEvent::HandleError { + node_id, + action: msgs::ErrorAction::SendErrorMessage { ref msg }, + } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()); nodes[1].node.handle_error(nodes[0].node.get_our_node_id(), msg); check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", &nodes[1].node.get_our_node_id())) } @@ -914,14 +1312,25 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // previous hop channel is already on-chain, but it makes nodes[2] willing to see additional // incoming HTLCs with the same payment hash later. nodes[2].node.fail_htlc_backwards(&payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], [HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + [HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[2], 1); let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &htlc_fulfill_updates.update_fail_htlcs[0]); + nodes[1].node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &htlc_fulfill_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[1], nodes[2], htlc_fulfill_updates.commitment_signed, false); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], - [HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + [HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] + ); // Connect the HTLC-Timeout transaction, timing out the HTLC on both nodes (but not confirming // the HTLC-Timeout transaction beyond 1 conf). For dust HTLCs, the HTLC is considered resolved @@ -954,10 +1363,16 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // If we attempt to retry prior to the HTLC-Timeout (or commitment transaction, for dust HTLCs) // confirming, we will fail as it's considered still-pending... - let (new_route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], if use_dust { 1_000 } else { 1_000_000 }); - match nodes[0].node.send_payment_with_route(new_route.clone(), payment_hash, RecipientOnionFields::secret_only(payment_secret), payment_id) { + let (new_route, _, _, _) = + get_route_and_payment_hash!(nodes[0], nodes[2], if use_dust { 1_000 } else { 1_000_000 }); + match nodes[0].node.send_payment_with_route( + new_route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + ) { Err(RetryableSendFailure::DuplicatePayment) => {}, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), } assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -966,18 +1381,38 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // (which should also still work). connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new()); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new(), + ); let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); let chan_1_monitor_serialized = get_monitor!(nodes[0], chan_id_3).encode(); nodes_0_serialized = nodes[0].node.encode(); // After the payment failed, we're free to send it again. - assert!(nodes[0].node.send_payment_with_route(new_route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id).is_ok()); + assert!(nodes[0] + .node + .send_payment_with_route( + new_route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id + ) + .is_ok()); assert!(!nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], second_persister, second_new_chain_monitor, second_nodes_0_deserialized); + reload_node!( + nodes[0], + test_default_channel_config(), + nodes_0_serialized, + &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], + second_persister, + second_new_chain_monitor, + second_nodes_0_deserialized + ); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); nodes[0].node.test_process_background_events(); @@ -988,15 +1423,33 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // Now resend the payment, delivering the HTLC and actually claiming it this time. This ensures // the payment is not (spuriously) listed as still pending. - assert!(nodes[0].node.send_payment_with_route(new_route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id).is_ok()); + assert!(nodes[0] + .node + .send_payment_with_route( + new_route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id + ) + .is_ok()); check_added_monitors!(nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], if use_dust { 1_000 } else { 1_000_000 }, payment_hash, payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + if use_dust { 1_000 } else { 1_000_000 }, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); - match nodes[0].node.send_payment_with_route(new_route.clone(), payment_hash, RecipientOnionFields::secret_only(payment_secret), payment_id) { + match nodes[0].node.send_payment_with_route( + new_route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + ) { Err(RetryableSendFailure::DuplicatePayment) => {}, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), } assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -1006,16 +1459,29 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // Check that after reload we can send the payment again (though we shouldn't, since it was // claimed previously). - reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], third_persister, third_new_chain_monitor, third_nodes_0_deserialized); + reload_node!( + nodes[0], + test_default_channel_config(), + nodes_0_serialized, + &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], + third_persister, + third_new_chain_monitor, + third_nodes_0_deserialized + ); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); nodes[0].node.test_process_background_events(); reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); - match nodes[0].node.send_payment_with_route(new_route, payment_hash, RecipientOnionFields::secret_only(payment_secret), payment_id) { + match nodes[0].node.send_payment_with_route( + new_route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + ) { Err(RetryableSendFailure::DuplicatePayment) => {}, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), } assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -1026,7 +1492,9 @@ fn test_completed_payment_not_retryable_on_reload() { do_test_completed_payment_not_retryable_on_reload(false); } -fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bool, confirm_commitment_tx: bool, payment_timeout: bool) { +fn do_test_dup_htlc_onchain_doesnt_fail_on_reload( + persist_manager_post_event: bool, confirm_commitment_tx: bool, payment_timeout: bool, +) { // When a Channel is closed, any outbound HTLCs which were relayed through it are simply // dropped. From there, the ChannelManager relies on the ChannelMonitor having a copy of the // relevant fail-/claim-back data and processes the HTLC fail/claim when the ChannelMonitor tells @@ -1049,10 +1517,23 @@ fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bo // Route a payment, but force-close the channel before the HTLC fulfill message arrives at // nodes[0]. let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 10_000_000); - nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); @@ -1074,7 +1555,13 @@ fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bo mine_transaction(&nodes[1], &commitment_tx); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let htlc_success_tx = { let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -1088,7 +1575,11 @@ fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bo connect_blocks(&nodes[0], BREAKDOWN_TIMEOUT as u32 - 1); } - let claim_block = create_dummy_block(nodes[0].best_block_hash(), 42, if payment_timeout { vec![htlc_timeout_tx] } else { vec![htlc_success_tx] }); + let claim_block = create_dummy_block( + nodes[0].best_block_hash(), + 42, + if payment_timeout { vec![htlc_timeout_tx] } else { vec![htlc_success_tx] }, + ); if payment_timeout { assert!(confirm_commitment_tx); // Otherwise we're spending below our CSV! @@ -1132,7 +1623,14 @@ fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bo } // Now reload nodes[0]... - reload_node!(nodes[0], &chan_manager_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + &chan_manager_serialized, + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); if persist_manager_post_event { assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); @@ -1189,20 +1687,36 @@ fn test_fulfill_restart_failure() { expect_payment_claimed!(nodes[1], payment_hash, 100_000); let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &htlc_fulfill_updates.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); // Now reload nodes[1]... - reload_node!(nodes[1], &chan_manager_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + &chan_manager_serialized, + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_1_deserialized + ); nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); nodes[1].node.fail_htlc_backwards(&payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[1], 1); let htlc_fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_fail_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &htlc_fail_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], htlc_fail_updates.commitment_signed, false); // nodes[0] shouldn't generate any events here, while it just got a payment failure completion // it had already considered the payment fulfilled, and now they just got free money. @@ -1220,30 +1734,59 @@ fn get_ldk_payment_preimage() { let amt_msat = 60_000; let expiry_secs = 60 * 60; - let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs, None).unwrap(); + let (payment_hash, payment_secret) = + nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs, None).unwrap(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); let scorer = test_utils::TestScorer::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); - let route = get_route( &nodes[0].node.get_our_node_id(), &route_params, + let route = get_route( + &nodes[0].node.get_our_node_id(), + &route_params, &nodes[0].network_graph.read_only(), - Some(&nodes[0].node.list_usable_channels().iter().collect::>()), nodes[0].logger, - &scorer, &Default::default(), &random_seed_bytes).unwrap(); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + Some(&nodes[0].node.list_usable_channels().iter().collect::>()), + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); // Make sure to use `get_payment_preimage` - let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap(); + let payment_preimage = + nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap(); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[1]], amt_msat, payment_hash, Some(payment_secret), events.pop().unwrap(), true, Some(payment_preimage)); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[1]], + amt_msat, + payment_hash, + Some(payment_secret), + events.pop().unwrap(), + true, + Some(payment_preimage), ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1]]], + payment_preimage, + )); } #[test] @@ -1313,14 +1856,16 @@ fn failed_probe_yields_event() { let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42); - let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], payment_params, 9_998_000); + let (route, _, _, _) = + get_route_and_payment_hash!(&nodes[0], nodes[2], payment_params, 9_998_000); let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap(); // node[0] -- update_add_htlcs -> node[1] check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), channel_id, updates); + let probe_event = + SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), channel_id, updates); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &probe_event.msgs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false); @@ -1331,7 +1876,9 @@ fn failed_probe_yields_event() { let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); // Skip the PendingHTLCsForwardable event let _events = nodes[1].node.get_and_clear_pending_events(); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); check_added_monitors!(nodes[0], 0); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false); @@ -1368,7 +1915,8 @@ fn onchain_failed_probe_yields_event() { // node[0] -- update_add_htlcs -> node[1] check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), chan_id, updates); + let probe_event = + SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), chan_id, updates); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &probe_event.msgs[0]); check_added_monitors!(nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false); @@ -1409,9 +1957,14 @@ fn preflight_probes_yield_event_skip_private_hop() { // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that. let mut no_htlc_limit_config = test_default_channel_config(); - no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; - - let user_configs = std::iter::repeat(no_htlc_limit_config).take(5).map(|c| Some(c)).collect::>>(); + no_htlc_limit_config + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 100; + + let user_configs = std::iter::repeat(no_htlc_limit_config) + .take(5) + .map(|c| Some(c)) + .collect::>>(); let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &user_configs); let nodes = create_network(5, &node_cfgs, &node_chanmgrs); @@ -1426,14 +1979,17 @@ fn preflight_probes_yield_event_skip_private_hop() { let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(invoice_features) + .unwrap(); let recv_value = 50_000_000; let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); - let expected_route: &[(&[&Node], PaymentHash)] = &[(&[&nodes[1], &nodes[2], &nodes[3]], res[0].0)]; + let expected_route: &[(&[&Node], PaymentHash)] = + &[(&[&nodes[1], &nodes[2], &nodes[3]], res[0].0)]; assert_eq!(res.len(), expected_route.len()); @@ -1451,9 +2007,14 @@ fn preflight_probes_yield_event() { // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that. let mut no_htlc_limit_config = test_default_channel_config(); - no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; - - let user_configs = std::iter::repeat(no_htlc_limit_config).take(4).map(|c| Some(c)).collect::>>(); + no_htlc_limit_config + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 100; + + let user_configs = std::iter::repeat(no_htlc_limit_config) + .take(4) + .map(|c| Some(c)) + .collect::>>(); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &user_configs); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); @@ -1472,14 +2033,17 @@ fn preflight_probes_yield_event() { let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(invoice_features) + .unwrap(); let recv_value = 50_000_000; let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); - let expected_route: &[(&[&Node], PaymentHash)] = &[(&[&nodes[1], &nodes[3]], res[0].0), (&[&nodes[2], &nodes[3]], res[1].0)]; + let expected_route: &[(&[&Node], PaymentHash)] = + &[(&[&nodes[1], &nodes[3]], res[0].0), (&[&nodes[2], &nodes[3]], res[1].0)]; assert_eq!(res.len(), expected_route.len()); @@ -1497,9 +2061,14 @@ fn preflight_probes_yield_event_and_skip() { // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that. let mut no_htlc_limit_config = test_default_channel_config(); - no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; - - let user_configs = std::iter::repeat(no_htlc_limit_config).take(5).map(|c| Some(c)).collect::>>(); + no_htlc_limit_config + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = 100; + + let user_configs = std::iter::repeat(no_htlc_limit_config) + .take(5) + .map(|c| Some(c)) + .collect::>>(); let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &user_configs); let nodes = create_network(5, &node_cfgs, &node_chanmgrs); @@ -1519,14 +2088,17 @@ fn preflight_probes_yield_event_and_skip() { let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(invoice_features) + .unwrap(); let recv_value = 80_000_000; let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); - let expected_route: &[(&[&Node], PaymentHash)] = &[(&[&nodes[1], &nodes[2], &nodes[4]], res[0].0)]; + let expected_route: &[(&[&Node], PaymentHash)] = + &[(&[&nodes[1], &nodes[2], &nodes[4]], res[0].0)]; // We check that only one probe was sent, the other one was skipped due to limited liquidity. assert_eq!(res.len(), 1); @@ -1548,15 +2120,21 @@ fn claimed_send_payment_idempotent() { create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (route, second_payment_hash, second_payment_preimage, second_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); - let (first_payment_preimage, _, _, payment_id) = send_along_route(&nodes[0], route.clone(), &[&nodes[1]], 100_000); + let (route, second_payment_hash, second_payment_preimage, second_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); + let (first_payment_preimage, _, _, payment_id) = + send_along_route(&nodes[0], route.clone(), &[&nodes[1]], 100_000); macro_rules! check_send_rejected { () => { // If we try to resend a new payment with a different payment_hash but with the same // payment_id, it should be rejected. - let send_result = nodes[0].node.send_payment_with_route(route.clone(), second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), payment_id); + let send_result = nodes[0].node.send_payment_with_route( + route.clone(), + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + payment_id, + ); match send_result { Err(RetryableSendFailure::DuplicatePayment) => {}, _ => panic!("Unexpected send result: {:?}", send_result), @@ -1565,14 +2143,17 @@ fn claimed_send_payment_idempotent() { // Further, if we try to send a spontaneous payment with the same payment_id it should // also be rejected. let send_result = nodes[0].node.send_spontaneous_payment( - None, RecipientOnionFields::spontaneous_empty(), payment_id, - route.route_params.clone().unwrap(), Retry::Attempts(0) + None, + RecipientOnionFields::spontaneous_empty(), + payment_id, + route.route_params.clone().unwrap(), + Retry::Attempts(0), ); match send_result { Err(RetryableSendFailure::DuplicatePayment) => {}, _ => panic!("Unexpected send result: {:?}", send_result), } - } + }; } check_send_rejected!(); @@ -1580,9 +2161,11 @@ fn claimed_send_payment_idempotent() { // Claim the payment backwards, but note that the PaymentSent event is still pending and has // not been seen by the user. At this point, from the user perspective nothing has changed, so // we must remain just as idempotent as we were before. - do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], first_payment_preimage) - ); + do_claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1]]], + first_payment_preimage, + )); for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS { nodes[0].node.timer_tick_occurred(); @@ -1609,10 +2192,23 @@ fn claimed_send_payment_idempotent() { nodes[0].node.timer_tick_occurred(); } - nodes[0].node.send_payment_with_route(route, second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), payment_id).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + payment_id, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1]]], 100_000, second_payment_hash, second_payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1]]], + 100_000, + second_payment_hash, + second_payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1]], second_payment_preimage); } @@ -1627,15 +2223,21 @@ fn abandoned_send_payment_idempotent() { create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (route, second_payment_hash, second_payment_preimage, second_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); - let (_, first_payment_hash, _, payment_id) = send_along_route(&nodes[0], route.clone(), &[&nodes[1]], 100_000); + let (route, second_payment_hash, second_payment_preimage, second_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); + let (_, first_payment_hash, _, payment_id) = + send_along_route(&nodes[0], route.clone(), &[&nodes[1]], 100_000); macro_rules! check_send_rejected { () => { // If we try to resend a new payment with a different payment_hash but with the same // payment_id, it should be rejected. - let send_result = nodes[0].node.send_payment_with_route(route.clone(), second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), payment_id); + let send_result = nodes[0].node.send_payment_with_route( + route.clone(), + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + payment_id, + ); match send_result { Err(RetryableSendFailure::DuplicatePayment) => {}, _ => panic!("Unexpected send result: {:?}", send_result), @@ -1644,20 +2246,26 @@ fn abandoned_send_payment_idempotent() { // Further, if we try to send a spontaneous payment with the same payment_id it should // also be rejected. let send_result = nodes[0].node.send_spontaneous_payment( - None, RecipientOnionFields::spontaneous_empty(), payment_id, - route.route_params.clone().unwrap(), Retry::Attempts(0) + None, + RecipientOnionFields::spontaneous_empty(), + payment_id, + route.route_params.clone().unwrap(), + Retry::Attempts(0), ); match send_result { Err(RetryableSendFailure::DuplicatePayment) => {}, _ => panic!("Unexpected send result: {:?}", send_result), } - } + }; } check_send_rejected!(); nodes[1].node.fail_htlc_backwards(&first_payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::FailedPayment { payment_hash: first_payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + [HTLCDestination::FailedPayment { payment_hash: first_payment_hash }] + ); // Until we abandon the payment upon path failure, no matter how many timer ticks pass, we still cannot reuse the // PaymentId. @@ -1666,14 +2274,33 @@ fn abandoned_send_payment_idempotent() { } check_send_rejected!(); - pass_failed_payment_back(&nodes[0], &[&[&nodes[1]]], false, first_payment_hash, PaymentFailureReason::RecipientRejected); + pass_failed_payment_back( + &nodes[0], + &[&[&nodes[1]]], + false, + first_payment_hash, + PaymentFailureReason::RecipientRejected, + ); // However, we can reuse the PaymentId immediately after we `abandon_payment` upon passing the // failed payment back. - nodes[0].node.send_payment_with_route(route, second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), payment_id).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + payment_id, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1]]], 100_000, second_payment_hash, second_payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1]]], + 100_000, + second_payment_hash, + second_payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1]], second_payment_preimage); } @@ -1685,7 +2312,7 @@ enum InterceptTest { } #[test] -fn test_trivial_inflight_htlc_tracking(){ +fn test_trivial_inflight_htlc_tracking() { // In this test, we test three scenarios: // (1) Sending + claiming a payment successfully should return `None` when querying InFlightHtlcs // (2) Sending a payment without claiming it should return the payment's value (500000) when querying InFlightHtlcs @@ -1704,31 +2331,46 @@ fn test_trivial_inflight_htlc_tracking(){ { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - let channel_1 = get_channel_ref!(&nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1_id); + let channel_1 = get_channel_ref!( + &nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_1_id + ); let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( - &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()), &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel_1.context().get_short_channel_id().unwrap() + channel_1.context().get_short_channel_id().unwrap(), ); assert_eq!(chan_1_used_liquidity, None); } { let mut node_1_per_peer_lock; let mut node_1_peer_state_lock; - let channel_2 = get_channel_ref!(&nodes[1], nodes[2], node_1_per_peer_lock, node_1_peer_state_lock, chan_2_id); + let channel_2 = get_channel_ref!( + &nodes[1], + nodes[2], + node_1_per_peer_lock, + node_1_peer_state_lock, + chan_2_id + ); let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( - &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), - channel_2.context().get_short_channel_id().unwrap() + channel_2.context().get_short_channel_id().unwrap(), ); assert_eq!(chan_2_used_liquidity, None); } let pending_payments = nodes[0].node.list_recent_payments(); assert_eq!(pending_payments.len(), 1); - assert_eq!(pending_payments[0], RecentPaymentDetails::Fulfilled { payment_hash: Some(payment_hash), payment_id }); + assert_eq!( + pending_payments[0], + RecentPaymentDetails::Fulfilled { payment_hash: Some(payment_hash), payment_id } + ); // Remove fulfilled payment for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS { @@ -1736,17 +2378,24 @@ fn test_trivial_inflight_htlc_tracking(){ } // Send the payment, but do not claim it. Our inflight HTLCs should contain the pending payment. - let (payment_preimage, payment_hash, _, payment_id) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 500000); + let (payment_preimage, payment_hash, _, payment_id) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 500000); let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs(); { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - let channel_1 = get_channel_ref!(&nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1_id); + let channel_1 = get_channel_ref!( + &nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_1_id + ); let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( - &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()), &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel_1.context().get_short_channel_id().unwrap() + channel_1.context().get_short_channel_id().unwrap(), ); // First hop accounts for expected 1000 msat fee assert_eq!(chan_1_used_liquidity, Some(501000)); @@ -1754,19 +2403,28 @@ fn test_trivial_inflight_htlc_tracking(){ { let mut node_1_per_peer_lock; let mut node_1_peer_state_lock; - let channel_2 = get_channel_ref!(&nodes[1], nodes[2], node_1_per_peer_lock, node_1_peer_state_lock, chan_2_id); + let channel_2 = get_channel_ref!( + &nodes[1], + nodes[2], + node_1_per_peer_lock, + node_1_peer_state_lock, + chan_2_id + ); let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( - &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), - channel_2.context().get_short_channel_id().unwrap() + channel_2.context().get_short_channel_id().unwrap(), ); assert_eq!(chan_2_used_liquidity, Some(500000)); } let pending_payments = nodes[0].node.list_recent_payments(); assert_eq!(pending_payments.len(), 1); - assert_eq!(pending_payments[0], RecentPaymentDetails::Pending { payment_id, payment_hash, total_msat: 500000 }); + assert_eq!( + pending_payments[0], + RecentPaymentDetails::Pending { payment_id, payment_hash, total_msat: 500000 } + ); // Now, let's claim the payment. This should result in the used liquidity to return `None`. claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); @@ -1780,24 +2438,36 @@ fn test_trivial_inflight_htlc_tracking(){ { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - let channel_1 = get_channel_ref!(&nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1_id); + let channel_1 = get_channel_ref!( + &nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_1_id + ); let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( - &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()), &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel_1.context().get_short_channel_id().unwrap() + channel_1.context().get_short_channel_id().unwrap(), ); assert_eq!(chan_1_used_liquidity, None); } { let mut node_1_per_peer_lock; let mut node_1_peer_state_lock; - let channel_2 = get_channel_ref!(&nodes[1], nodes[2], node_1_per_peer_lock, node_1_peer_state_lock, chan_2_id); + let channel_2 = get_channel_ref!( + &nodes[1], + nodes[2], + node_1_per_peer_lock, + node_1_peer_state_lock, + chan_2_id + ); let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( - &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), - channel_2.context().get_short_channel_id().unwrap() + channel_2.context().get_short_channel_id().unwrap(), ); assert_eq!(chan_2_used_liquidity, None); } @@ -1814,17 +2484,32 @@ fn test_holding_cell_inflight_htlcs() { let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (route, payment_hash_1, _, payment_secret_1) = + get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); let (_, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]); // Queue up two payments - one will be delivered right away, one immediately goes into the // holding cell as nodes[0] is AwaitingRAA. { - nodes[0].node.send_payment_with_route(route.clone(), payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - nodes[0].node.send_payment_with_route(route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 0); } @@ -1833,12 +2518,18 @@ fn test_holding_cell_inflight_htlcs() { { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - let channel = get_channel_ref!(&nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, channel_id); + let channel = get_channel_ref!( + &nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + channel_id + ); let used_liquidity = inflight_htlcs.used_liquidity_msat( - &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()), &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel.context().get_short_channel_id().unwrap() + channel.context().get_short_channel_id().unwrap(), ); assert_eq!(used_liquidity, Some(2000000)); @@ -1867,7 +2558,11 @@ fn do_test_intercepted_payment(test: InterceptTest) { zero_conf_chan_config.manually_accept_inbound_channels = true; let mut intercept_forwards_config = test_default_channel_config(); intercept_forwards_config.accept_intercept_htlcs = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), Some(zero_conf_chan_config)]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[None, Some(intercept_forwards_config), Some(zero_conf_chan_config)], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let scorer = test_utils::TestScorer::new(); @@ -1877,30 +2572,43 @@ fn do_test_intercepted_payment(test: InterceptTest) { let amt_msat = 100_000; let intercept_scid = nodes[1].node.get_intercept_scid(); - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_route_hints(vec![ - RouteHint(vec![RouteHintHop { + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_route_hints(vec![RouteHint(vec![RouteHintHop { src_node_id: nodes[1].node.get_our_node_id(), short_channel_id: intercept_scid, - fees: RoutingFees { - base_msat: 1000, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 1000, proportional_millionths: 0 }, cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA, htlc_minimum_msat: None, htlc_maximum_msat: None, - }]) - ]).unwrap() - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap(); + }])]) + .unwrap() + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let route = get_route( - &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), None, - nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes - ).unwrap(); - - let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + &nodes[0].node.get_our_node_id(), + &route_params, + &nodes[0].network_graph.read_only(), + None, + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); + + let (payment_hash, payment_secret) = + nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); let payment_event = { { let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); @@ -1920,26 +2628,48 @@ fn do_test_intercepted_payment(test: InterceptTest) { assert_eq!(events.len(), 1); let (intercept_id, expected_outbound_amount_msat) = match events[0] { crate::events::Event::HTLCIntercepted { - intercept_id, expected_outbound_amount_msat, payment_hash: pmt_hash, inbound_amount_msat, requested_next_hop_scid: short_channel_id + intercept_id, + expected_outbound_amount_msat, + payment_hash: pmt_hash, + inbound_amount_msat, + requested_next_hop_scid: short_channel_id, } => { assert_eq!(pmt_hash, payment_hash); assert_eq!(inbound_amount_msat, route.get_total_amount() + route.get_total_fees()); assert_eq!(short_channel_id, intercept_scid); (intercept_id, expected_outbound_amount_msat) }, - _ => panic!() + _ => panic!(), }; // Check for unknown channel id error. - let unknown_chan_id_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &ChannelId::from_bytes([42; 32]), nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err(); - assert_eq!(unknown_chan_id_err , APIError::ChannelUnavailable { - err: format!("Channel with id {} not found for the passed counterparty node_id {}", - log_bytes!([42; 32]), nodes[2].node.get_our_node_id()) }); + let unknown_chan_id_err = nodes[1] + .node + .forward_intercepted_htlc( + intercept_id, + &ChannelId::from_bytes([42; 32]), + nodes[2].node.get_our_node_id(), + expected_outbound_amount_msat, + ) + .unwrap_err(); + assert_eq!( + unknown_chan_id_err, + APIError::ChannelUnavailable { + err: format!( + "Channel with id {} not found for the passed counterparty node_id {}", + log_bytes!([42; 32]), + nodes[2].node.get_our_node_id() + ) + } + ); if test == InterceptTest::Fail { // Ensure we can fail the intercepted payment back. nodes[1].node.fail_intercepted_htlc(intercept_id).unwrap(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], vec![HTLCDestination::UnknownNextHop { requested_forward_scid: intercept_scid }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::UnknownNextHop { requested_forward_scid: intercept_scid }] + ); nodes[1].node.process_pending_htlc_forwards(); let update_fail = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(&nodes[1], 1); @@ -1956,18 +2686,44 @@ fn do_test_intercepted_payment(test: InterceptTest) { expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions); } else if test == InterceptTest::Forward { // Check that we'll fail as expected when sending to a channel that isn't in `ChannelReady` yet. - let temp_chan_id = nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); - let unusable_chan_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &temp_chan_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err(); - assert_eq!(unusable_chan_err , APIError::ChannelUnavailable { - err: format!("Channel with id {} for the passed counterparty node_id {} is still opening.", - temp_chan_id, nodes[2].node.get_our_node_id()) }); + let temp_chan_id = nodes[1] + .node + .create_channel(nodes[2].node.get_our_node_id(), 100_000, 0, 42, None, None) + .unwrap(); + let unusable_chan_err = nodes[1] + .node + .forward_intercepted_htlc( + intercept_id, + &temp_chan_id, + nodes[2].node.get_our_node_id(), + expected_outbound_amount_msat, + ) + .unwrap_err(); + assert_eq!( + unusable_chan_err, + APIError::ChannelUnavailable { + err: format!( + "Channel with id {} for the passed counterparty node_id {} is still opening.", + temp_chan_id, + nodes[2].node.get_our_node_id() + ) + } + ); assert_eq!(nodes[1].node.get_and_clear_pending_msg_events().len(), 1); // Open the just-in-time channel so the payment can then be forwarded. let (_, channel_id) = open_zero_conf_channel(&nodes[1], &nodes[2], None); // Finally, forward the intercepted payment through and claim it. - nodes[1].node.forward_intercepted_htlc(intercept_id, &channel_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap(); + nodes[1] + .node + .forward_intercepted_htlc( + intercept_id, + &channel_id, + nodes[2].node.get_our_node_id(), + expected_outbound_amount_msat, + ) + .unwrap(); expect_pending_htlcs_forwardable!(nodes[1]); let payment_event = { @@ -1980,30 +2736,47 @@ fn do_test_intercepted_payment(test: InterceptTest) { assert_eq!(events.len(), 1); SendEvent::from_event(events.remove(0)) }; - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[2] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[2], nodes[1], &payment_event.commitment_msg, false, true); expect_pending_htlcs_forwardable!(nodes[2]); - let payment_preimage = nodes[2].node.get_payment_preimage(payment_hash, payment_secret).unwrap(); - expect_payment_claimable!(&nodes[2], payment_hash, payment_secret, amt_msat, Some(payment_preimage), nodes[2].node.get_our_node_id()); - do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + let payment_preimage = + nodes[2].node.get_payment_preimage(payment_hash, payment_secret).unwrap(); + expect_payment_claimable!( + &nodes[2], + payment_hash, + payment_secret, + amt_msat, + Some(payment_preimage), + nodes[2].node.get_our_node_id() ); + do_claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + payment_preimage, + )); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentSent { payment_preimage: ref ev_preimage, payment_hash: ref ev_hash, ref fee_paid_msat, .. } => { + Event::PaymentSent { + payment_preimage: ref ev_preimage, + payment_hash: ref ev_hash, + ref fee_paid_msat, + .. + } => { assert_eq!(payment_preimage, *ev_preimage); assert_eq!(payment_hash, *ev_hash); assert_eq!(fee_paid_msat, &Some(1000)); }, - _ => panic!("Unexpected event") + _ => panic!("Unexpected event"), } match events[1] { Event::PaymentPathSuccessful { payment_hash: hash, .. } => { assert_eq!(hash, Some(payment_hash)); }, - _ => panic!("Unexpected event") + _ => panic!("Unexpected event"), } check_added_monitors(&nodes[0], 1); } else if test == InterceptTest::Timeout { @@ -2015,7 +2788,10 @@ fn do_test_intercepted_payment(test: InterceptTest) { connect_block(&nodes[0], &block); connect_block(&nodes[1], &block); } - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::InvalidForward { requested_forward_scid: intercept_scid }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::InvalidForward { requested_forward_scid: intercept_scid }] + ); check_added_monitors!(nodes[1], 1); let htlc_timeout_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(htlc_timeout_updates.update_add_htlcs.is_empty()); @@ -2023,16 +2799,44 @@ fn do_test_intercepted_payment(test: InterceptTest) { assert!(htlc_timeout_updates.update_fail_malformed_htlcs.is_empty()); assert!(htlc_timeout_updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_timeout_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &htlc_timeout_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], htlc_timeout_updates.commitment_signed, false); - expect_payment_failed!(nodes[0], payment_hash, false, LocalHTLCFailureReason::TemporaryNodeFailure, []); + expect_payment_failed!( + nodes[0], + payment_hash, + false, + LocalHTLCFailureReason::TemporaryNodeFailure, + [] + ); // Check for unknown intercept id error. let (_, channel_id) = open_zero_conf_channel(&nodes[1], &nodes[2], None); - let unknown_intercept_id_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &channel_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err(); - assert_eq!(unknown_intercept_id_err , APIError::APIMisuseError { err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) }); - let unknown_intercept_id_err = nodes[1].node.fail_intercepted_htlc(intercept_id).unwrap_err(); - assert_eq!(unknown_intercept_id_err , APIError::APIMisuseError { err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) }); + let unknown_intercept_id_err = nodes[1] + .node + .forward_intercepted_htlc( + intercept_id, + &channel_id, + nodes[2].node.get_our_node_id(), + expected_outbound_amount_msat, + ) + .unwrap_err(); + assert_eq!( + unknown_intercept_id_err, + APIError::APIMisuseError { + err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) + } + ); + let unknown_intercept_id_err = + nodes[1].node.fail_intercepted_htlc(intercept_id).unwrap_err(); + assert_eq!( + unknown_intercept_id_err, + APIError::APIMisuseError { + err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0)) + } + ); } } @@ -2049,11 +2853,18 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { let max_in_flight_percent = 10; let mut intercept_forwards_config = test_default_channel_config(); intercept_forwards_config.accept_intercept_htlcs = true; - intercept_forwards_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = max_in_flight_percent; + intercept_forwards_config + .channel_handshake_config + .max_inbound_htlc_value_in_flight_percent_of_channel = max_in_flight_percent; let mut underpay_config = test_default_channel_config(); underpay_config.channel_config.accept_underpaying_htlcs = true; - underpay_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = max_in_flight_percent; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), Some(underpay_config)]); + underpay_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = + max_in_flight_percent; + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[None, Some(intercept_forwards_config), Some(underpay_config)], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let amt_msat = 900_000; @@ -2061,9 +2872,13 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { let mut chan_ids = Vec::new(); for _ in 0..num_mpp_parts { // We choose the channel size so that there can be at most one part pending on each channel. - let channel_size = amt_msat / 1000 / num_mpp_parts as u64 * 100 / max_in_flight_percent as u64 + 100; + let channel_size = + amt_msat / 1000 / num_mpp_parts as u64 * 100 / max_in_flight_percent as u64 + 100; let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_size, 0); - let channel_id = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, channel_size, 0).0.channel_id; + let channel_id = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, channel_size, 0) + .0 + .channel_id; chan_ids.push(channel_id); } @@ -2074,24 +2889,38 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { route_hints.push(RouteHint(vec![RouteHintHop { src_node_id: nodes[1].node.get_our_node_id(), short_channel_id: nodes[1].node.get_intercept_scid(), - fees: RoutingFees { - base_msat: 1000, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 1000, proportional_millionths: 0 }, cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA, htlc_minimum_msat: None, htlc_maximum_msat: Some(amt_msat / num_mpp_parts as u64 + 5), }])); } - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_route_hints(route_hints).unwrap() - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_route_hints(route_hints) + .unwrap() + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); - let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + let (payment_hash, payment_secret) = + nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors!(nodes[0], num_mpp_parts); // one monitor per path - let mut events: Vec = nodes[0].node.get_and_clear_pending_msg_events().into_iter().map(|e| SendEvent::from_event(e)).collect(); + let mut events: Vec = nodes[0] + .node + .get_and_clear_pending_msg_events() + .into_iter() + .map(|e| SendEvent::from_event(e)) + .collect(); assert_eq!(events.len(), num_mpp_parts); // Forward the intercepted payments. @@ -2104,15 +2933,25 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { assert_eq!(events.len(), 1); let (intercept_id, expected_outbound_amt_msat) = match events[0] { crate::events::Event::HTLCIntercepted { - intercept_id, expected_outbound_amount_msat, payment_hash: pmt_hash, .. + intercept_id, + expected_outbound_amount_msat, + payment_hash: pmt_hash, + .. } => { assert_eq!(pmt_hash, payment_hash); (intercept_id, expected_outbound_amount_msat) }, - _ => panic!() + _ => panic!(), }; - nodes[1].node.forward_intercepted_htlc(intercept_id, &chan_ids[idx], - nodes[2].node.get_our_node_id(), expected_outbound_amt_msat - skimmed_fee_msat).unwrap(); + nodes[1] + .node + .forward_intercepted_htlc( + intercept_id, + &chan_ids[idx], + nodes[2].node.get_our_node_id(), + expected_outbound_amt_msat - skimmed_fee_msat, + ) + .unwrap(); expect_pending_htlcs_forwardable!(nodes[1]); let payment_event = { { @@ -2124,20 +2963,34 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { assert_eq!(events.len(), 1); SendEvent::from_event(events.remove(0)) }; - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); - do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event.commitment_msg, false, true); + nodes[2] + .node + .handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); + do_commitment_signed_dance( + &nodes[2], + &nodes[1], + &payment_event.commitment_msg, + false, + true, + ); if idx == num_mpp_parts - 1 { expect_pending_htlcs_forwardable!(nodes[2]); } } // Claim the payment and check that the skimmed fee is as expected. - let payment_preimage = nodes[2].node.get_payment_preimage(payment_hash, payment_secret).unwrap(); + let payment_preimage = + nodes[2].node.get_payment_preimage(payment_hash, payment_secret).unwrap(); let events = nodes[2].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { crate::events::Event::PaymentClaimable { - ref payment_hash, ref purpose, amount_msat, counterparty_skimmed_fee_msat, receiver_node_id, .. + ref payment_hash, + ref purpose, + amount_msat, + counterparty_skimmed_fee_msat, + receiver_node_id, + .. } => { assert_eq!(payment_hash, payment_hash); assert_eq!(amt_msat - skimmed_fee_msat * num_mpp_parts as u64, amount_msat); @@ -2159,15 +3012,24 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { } let mut expected_paths_vecs = Vec::new(); let mut expected_paths = Vec::new(); - for _ in 0..num_mpp_parts { expected_paths_vecs.push(vec!(&nodes[1], &nodes[2])); } - for i in 0..num_mpp_parts { expected_paths.push(&expected_paths_vecs[i][..]); } + for _ in 0..num_mpp_parts { + expected_paths_vecs.push(vec![&nodes[1], &nodes[2]]); + } + for i in 0..num_mpp_parts { + expected_paths.push(&expected_paths_vecs[i][..]); + } expected_paths[0].last().unwrap().node.claim_funds(payment_preimage); let args = ClaimAlongRouteArgs::new(&nodes[0], &expected_paths[..], payment_preimage) .with_expected_extra_fees(vec![skimmed_fee_msat as u32; num_mpp_parts]); let total_fee_msat = pass_claimed_payment_along_route(args); // The sender doesn't know that the penultimate hop took an extra fee. - expect_payment_sent(&nodes[0], payment_preimage, - Some(Some(total_fee_msat - skimmed_fee_msat * num_mpp_parts as u64)), true, true); + expect_payment_sent( + &nodes[0], + payment_preimage, + Some(Some(total_fee_msat - skimmed_fee_msat * num_mpp_parts as u64)), + true, + true, + ); } #[derive(PartialEq)] @@ -2214,11 +3076,14 @@ fn do_automatic_retries(test: AutoRetry) { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); - let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); + let (_, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); macro_rules! pass_failed_attempt_with_retry_along_path { ($failing_channel_id: expr, $expect_pending_htlcs_forwardable: expr) => { @@ -2271,8 +3136,16 @@ fn do_automatic_retries(test: AutoRetry) { if test == AutoRetry::Success { // Test that we can succeed on the first retry. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); pass_failed_attempt_with_retry_along_path!(channel_id_2, true); // Open a new channel with liquidity on the second hop so we can find a route for the retry @@ -2284,14 +3157,32 @@ fn do_automatic_retries(test: AutoRetry) { check_added_monitors!(nodes[0], 1); let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, Some(payment_secret), msg_events.pop().unwrap(), true, None); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[2]], + amt_msat, + payment_hash, + Some(payment_secret), + msg_events.pop().unwrap(), + true, + None, ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + payment_preimage, + )); } else if test == AutoRetry::Spontaneous { - nodes[0].node.send_spontaneous_payment(Some(payment_preimage), - RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), - Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(1), + ) + .unwrap(); pass_failed_attempt_with_retry_along_path!(channel_id_2, true); // Open a new channel with liquidity on the second hop so we can find a route for the retry @@ -2303,14 +3194,33 @@ fn do_automatic_retries(test: AutoRetry) { check_added_monitors!(nodes[0], 1); let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, None, msg_events.pop().unwrap(), true, Some(payment_preimage)); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[2]], + amt_msat, + payment_hash, + None, + msg_events.pop().unwrap(), + true, + Some(payment_preimage), ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + payment_preimage, + )); } else if test == AutoRetry::FailAttempts { // Ensure ChannelManager will not retry a payment if it has run out of payment attempts. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(1), + ) + .unwrap(); pass_failed_attempt_with_retry_along_path!(channel_id_2, true); // Open a new channel with no liquidity on the second hop so we can find a (bad) route for @@ -2326,10 +3236,19 @@ fn do_automatic_retries(test: AutoRetry) { let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 0); } else if test == AutoRetry::FailTimeout { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { // Ensure ChannelManager will not retry a payment if it times out due to Retry::Timeout. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Timeout(Duration::from_secs(60))).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Timeout(Duration::from_secs(60)), + ) + .unwrap(); pass_failed_attempt_with_retry_along_path!(channel_id_2, true); // Advance the time so the second attempt fails due to timeout. @@ -2343,7 +3262,11 @@ fn do_automatic_retries(test: AutoRetry) { let mut events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id, reason: ref ev_reason } => { + Event::PaymentFailed { + payment_hash: ref ev_payment_hash, + payment_id: ref ev_payment_id, + reason: ref ev_reason, + } => { assert_eq!(Some(payment_hash), *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RetriesExhausted, ev_reason.unwrap()); @@ -2354,8 +3277,16 @@ fn do_automatic_retries(test: AutoRetry) { } else if test == AutoRetry::FailOnRestart { // Ensure ChannelManager will not retry a payment after restart, even if there were retry // attempts remaining prior to restart. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(2)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(2), + ) + .unwrap(); pass_failed_attempt_with_retry_along_path!(channel_id_2, true); // Open a new channel with no liquidity on the second hop so we can find a (bad) route for @@ -2369,7 +3300,14 @@ fn do_automatic_retries(test: AutoRetry) { // Restart the node and ensure that ChannelManager does not use its remaining retry attempt let node_encoded = nodes[0].node.encode(); let chan_1_monitor_serialized = get_monitor!(nodes[0], channel_id_1).encode(); - reload_node!(nodes[0], node_encoded, &[&chan_1_monitor_serialized], persister, new_chain_monitor, node_0_deserialized); + reload_node!( + nodes[0], + node_encoded, + &[&chan_1_monitor_serialized], + persister, + new_chain_monitor, + node_0_deserialized + ); let mut events = nodes[0].node.get_and_clear_pending_events(); expect_pending_htlcs_forwardable_from_events!(nodes[0], events, true); @@ -2380,7 +3318,11 @@ fn do_automatic_retries(test: AutoRetry) { let mut events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id, reason: ref ev_reason } => { + Event::PaymentFailed { + payment_hash: ref ev_payment_hash, + payment_id: ref ev_payment_id, + reason: ref ev_reason, + } => { assert_eq!(Some(payment_hash), *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RetriesExhausted, ev_reason.unwrap()); @@ -2388,8 +3330,16 @@ fn do_automatic_retries(test: AutoRetry) { _ => panic!("Unexpected event"), } } else if test == AutoRetry::FailOnRetry { - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); pass_failed_attempt_with_retry_along_path!(channel_id_2, true); // We retry payments in `process_pending_htlc_forwards`. Since our channel closed, we should @@ -2401,7 +3351,11 @@ fn do_automatic_retries(test: AutoRetry) { let mut events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id, reason: ref ev_reason } => { + Event::PaymentFailed { + payment_hash: ref ev_payment_hash, + payment_id: ref ev_payment_id, + reason: ref ev_reason, + } => { assert_eq!(Some(payment_hash), *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RouteNotFound, ev_reason.unwrap()); @@ -2422,12 +3376,21 @@ fn auto_retry_partial_failure() { // Open three channels, the first has plenty of liquidity, the second and third have ~no // available liquidity, causing any outbound payments routed over it to fail immediately. let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; - let chan_2_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000).0.contents.short_channel_id; - let chan_3_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000).0.contents.short_channel_id; + let chan_2_id = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000) + .0 + .contents + .short_channel_id; + let chan_3_id = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000) + .0 + .contents + .short_channel_id; // Marshall data to send the payment let amt_msat = 10_000_000; - let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); + let (_, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -2436,9 +3399,11 @@ fn auto_retry_partial_failure() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); // Configure the initial send path let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); @@ -2446,24 +3411,30 @@ fn auto_retry_partial_failure() { let send_route = Route { paths: vec![ - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_1_id, - channel_features: nodes[1].node.channel_features(), - fee_msat: amt_msat / 2, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_2_id, - channel_features: nodes[1].node.channel_features(), - fee_msat: amt_msat / 2, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, + Path { + hops: vec![RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_1_id, + channel_features: nodes[1].node.channel_features(), + fee_msat: amt_msat / 2, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }], + blinded_tail: None, + }, + Path { + hops: vec![RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_2_id, + channel_features: nodes[1].node.channel_features(), + fee_msat: amt_msat / 2, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }], + blinded_tail: None, + }, ], route_params: Some(route_params.clone()), }; @@ -2472,29 +3443,36 @@ fn auto_retry_partial_failure() { // Configure the retry1 paths let mut payment_params = route_params.payment_params.clone(); payment_params.previously_failed_channels.push(chan_2_id); - let mut retry_1_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 2); + let mut retry_1_params = + RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 2); retry_1_params.max_total_routing_fee_msat = None; let retry_1_route = Route { paths: vec![ - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_1_id, - channel_features: nodes[1].node.channel_features(), - fee_msat: amt_msat / 4, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_3_id, - channel_features: nodes[1].node.channel_features(), - fee_msat: amt_msat / 4, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, + Path { + hops: vec![RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_1_id, + channel_features: nodes[1].node.channel_features(), + fee_msat: amt_msat / 4, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }], + blinded_tail: None, + }, + Path { + hops: vec![RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_3_id, + channel_features: nodes[1].node.channel_features(), + fee_msat: amt_msat / 4, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }], + blinded_tail: None, + }, ], route_params: Some(retry_1_params.clone()), }; @@ -2503,12 +3481,13 @@ fn auto_retry_partial_failure() { // Configure the retry2 path let mut payment_params = retry_1_params.payment_params.clone(); payment_params.previously_failed_channels.push(chan_3_id); - let mut retry_2_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 4); + let mut retry_2_params = + RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 4); retry_2_params.max_total_routing_fee_msat = None; let retry_2_route = Route { - paths: vec![ - Path { hops: vec![RouteHop { + paths: vec![Path { + hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), node_features: nodes[1].node.node_features(), short_channel_id: chan_1_id, @@ -2516,15 +3495,24 @@ fn auto_retry_partial_failure() { fee_msat: amt_msat / 4, cltv_expiry_delta: 100, maybe_announced_channel: true, - }], blinded_tail: None }, - ], + }], + blinded_tail: None, + }], route_params: Some(retry_2_params.clone()), }; nodes[0].router.expect_find_route(retry_2_params, Ok(retry_2_route)); // Send a payment that will partially fail on send, then partially fail on retry, then succeed. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(3)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(3), + ) + .unwrap(); let payment_failed_events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(payment_failed_events.len(), 2); match payment_failed_events[0] { @@ -2545,33 +3533,57 @@ fn auto_retry_partial_failure() { let mut payment_event = SendEvent::from_event(msg_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_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_first_raa, bs_first_cs) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_first_raa); check_added_monitors!(nodes[0], 1); let as_second_htlc_updates = SendEvent::from_node(&nodes[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); check_added_monitors!(nodes[0], 1); - let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_first_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_first_raa); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[0]); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[1]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_second_htlc_updates.commitment_msg); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[1]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_second_htlc_updates.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let (bs_second_raa, bs_second_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_second_raa, bs_second_cs) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_second_raa); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_cs); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_cs); check_added_monitors!(nodes[0], 1); - let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_second_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_second_raa); check_added_monitors!(nodes[1], 1); @@ -2584,43 +3596,78 @@ fn auto_retry_partial_failure() { let bs_claim_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert_eq!(bs_claim_update.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_claim_update.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_claim_update.update_fulfill_htlcs[0], + ); expect_payment_sent(&nodes[0], payment_preimage, None, false, false); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_claim_update.commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_claim_update.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let (as_third_raa, as_third_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (as_third_raa, as_third_cs) = + get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_third_raa); check_added_monitors!(nodes[1], 4); let bs_second_claim_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_third_cs); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_third_cs); check_added_monitors!(nodes[1], 1); - let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_third_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_third_raa); check_added_monitors!(nodes[0], 1); expect_payment_path_successful!(nodes[0]); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[0]); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[1]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_claim_update.commitment_signed); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_second_claim_update.update_fulfill_htlcs[0], + ); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &bs_second_claim_update.update_fulfill_htlcs[1], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_second_claim_update.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let (as_fourth_raa, as_fourth_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (as_fourth_raa, as_fourth_cs) = + get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_fourth_raa); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_fourth_cs); + nodes[1] + .node + .handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_fourth_cs); check_added_monitors!(nodes[1], 1); - let bs_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_second_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_second_raa); check_added_monitors!(nodes[0], 1); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); - if let Event::PaymentPathSuccessful { .. } = events[0] {} else { panic!(); } - if let Event::PaymentPathSuccessful { .. } = events[1] {} else { panic!(); } + if let Event::PaymentPathSuccessful { .. } = events[0] { + } else { + panic!(); + } + if let Event::PaymentPathSuccessful { .. } = events[1] { + } else { + panic!(); + } } #[test] @@ -2632,11 +3679,16 @@ fn auto_retry_zero_attempts_send_error() { // Open a single channel that does not have sufficient liquidity for the payment we want to // send. - let chan_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000).0.contents.short_channel_id; + let chan_id = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000) + .0 + .contents + .short_channel_id; // Marshall data to send the payment let amt_msat = 10_000_000; - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -2645,15 +3697,17 @@ fn auto_retry_zero_attempts_send_error() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); // Override the route search to return a route, rather than failing at the route-finding step. let send_route = Route { - paths: vec![ - Path { hops: vec![RouteHop { + paths: vec![Path { + hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), node_features: nodes[1].node.node_features(), short_channel_id: chan_id, @@ -2661,19 +3715,34 @@ fn auto_retry_zero_attempts_send_error() { fee_msat: amt_msat, cltv_expiry_delta: 100, maybe_announced_channel: true, - }], blinded_tail: None }, - ], + }], + blinded_tail: None, + }], route_params: Some(route_params.clone()), }; nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route)); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); - if let Event::PaymentPathFailed { .. } = events[0] { } else { panic!(); } - if let Event::PaymentFailed { .. } = events[1] { } else { panic!(); } + if let Event::PaymentPathFailed { .. } = events[0] { + } else { + panic!(); + } + if let Event::PaymentFailed { .. } = events[1] { + } else { + panic!(); + } check_added_monitors!(nodes[0], 0); } @@ -2688,7 +3757,8 @@ fn fails_paying_after_rejected_by_payee() { // Marshall data to send the payment let amt_msat = 20_000; - let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); + let (_, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -2697,13 +3767,23 @@ fn fails_paying_after_rejected_by_payee() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -2715,8 +3795,17 @@ fn fails_paying_after_rejected_by_payee() { expect_payment_claimable!(&nodes[1], payment_hash, payment_secret, amt_msat); nodes[1].node.fail_htlc_backwards(&payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::FailedPayment { payment_hash }]); - pass_failed_payment_back(&nodes[0], &[&[&nodes[1]]], false, payment_hash, PaymentFailureReason::RecipientRejected); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + [HTLCDestination::FailedPayment { payment_hash }] + ); + pass_failed_payment_back( + &nodes[0], + &[&[&nodes[1]]], + false, + payment_hash, + PaymentFailureReason::RecipientRejected, + ); } #[test] @@ -2732,7 +3821,8 @@ fn retry_multi_path_single_failed_payment() { let amt_msat = 100_010_000; - let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); + let (_, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -2741,34 +3831,42 @@ fn retry_multi_path_single_failed_payment() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), amt_msat); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), amt_msat); route_params.max_total_routing_fee_msat = None; let chans = nodes[0].node.list_usable_channels(); let mut route = Route { paths: vec![ - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chans[0].short_channel_id.unwrap(), - channel_features: nodes[1].node.channel_features(), - fee_msat: 10_000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chans[1].short_channel_id.unwrap(), - channel_features: nodes[1].node.channel_features(), - fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, + Path { + hops: vec![RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chans[0].short_channel_id.unwrap(), + channel_features: nodes[1].node.channel_features(), + fee_msat: 10_000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }], + blinded_tail: None, + }, + Path { + hops: vec![RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chans[1].short_channel_id.unwrap(), + channel_features: nodes[1].node.channel_features(), + fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }], + blinded_tail: None, + }, ], route_params: Some(route_params.clone()), }; @@ -2787,22 +3885,61 @@ fn retry_multi_path_single_failed_payment() { { let scorer = chanmon_cfgs[0].scorer.read().unwrap(); // The initial send attempt, 2 paths - scorer.expect_usage(chans[0].short_channel_id.unwrap(), ChannelUsage { amount_msat: 10_000, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown }); - scorer.expect_usage(chans[1].short_channel_id.unwrap(), ChannelUsage { amount_msat: 100_000_001, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown }); + scorer.expect_usage( + chans[0].short_channel_id.unwrap(), + ChannelUsage { + amount_msat: 10_000, + inflight_htlc_msat: 0, + effective_capacity: EffectiveCapacity::Unknown, + }, + ); + scorer.expect_usage( + chans[1].short_channel_id.unwrap(), + ChannelUsage { + amount_msat: 100_000_001, + inflight_htlc_msat: 0, + effective_capacity: EffectiveCapacity::Unknown, + }, + ); // The retry, 2 paths. Ensure that the in-flight HTLC amount is factored in. - scorer.expect_usage(chans[0].short_channel_id.unwrap(), ChannelUsage { amount_msat: 50_000_001, inflight_htlc_msat: 10_000, effective_capacity: EffectiveCapacity::Unknown }); - scorer.expect_usage(chans[1].short_channel_id.unwrap(), ChannelUsage { amount_msat: 50_000_000, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown }); + scorer.expect_usage( + chans[0].short_channel_id.unwrap(), + ChannelUsage { + amount_msat: 50_000_001, + inflight_htlc_msat: 10_000, + effective_capacity: EffectiveCapacity::Unknown, + }, + ); + scorer.expect_usage( + chans[1].short_channel_id.unwrap(), + ChannelUsage { + amount_msat: 50_000_000, + inflight_htlc_msat: 0, + effective_capacity: EffectiveCapacity::Unknown, + }, + ); } - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently: false, - failure: PathFailure::InitialSend { err: APIError::ChannelUnavailable { .. }}, - short_channel_id: Some(expected_scid), .. } => - { + Event::PaymentPathFailed { + payment_hash: ev_payment_hash, + payment_failed_permanently: false, + failure: PathFailure::InitialSend { err: APIError::ChannelUnavailable { .. } }, + short_channel_id: Some(expected_scid), + .. + } => { assert_eq!(payment_hash, ev_payment_hash); assert_eq!(expected_scid, route.paths[1].hops[0].short_channel_id); }, @@ -2825,7 +3962,8 @@ fn immediate_retry_on_failure() { create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); let amt_msat = 100_000_001; - let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); + let (_, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -2834,15 +3972,17 @@ fn immediate_retry_on_failure() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let chans = nodes[0].node.list_usable_channels(); let mut route = Route { - paths: vec![ - Path { hops: vec![RouteHop { + paths: vec![Path { + hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), node_features: nodes[1].node.node_features(), short_channel_id: chans[0].short_channel_id.unwrap(), @@ -2850,8 +3990,9 @@ fn immediate_retry_on_failure() { fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than cltv_expiry_delta: 100, maybe_announced_channel: true, - }], blinded_tail: None }, - ], + }], + blinded_tail: None, + }], route_params: Some(route_params.clone()), }; nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); @@ -2866,15 +4007,26 @@ fn immediate_retry_on_failure() { route.route_params = Some(retry_params.clone()); nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently: false, - failure: PathFailure::InitialSend { err: APIError::ChannelUnavailable { .. }}, - short_channel_id: Some(expected_scid), .. } => - { + Event::PaymentPathFailed { + payment_hash: ev_payment_hash, + payment_failed_permanently: false, + failure: PathFailure::InitialSend { err: APIError::ChannelUnavailable { .. } }, + short_channel_id: Some(expected_scid), + .. + } => { assert_eq!(payment_hash, ev_payment_hash); assert_eq!(expected_scid, route.paths[1].hops[0].short_channel_id); }, @@ -2913,7 +4065,8 @@ fn no_extra_retries_on_back_to_back_fail() { let chan_2_scid = chan_2.0.contents.short_channel_id; let amt_msat = 200_000_000; - let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); + let (_, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -2922,48 +4075,62 @@ fn no_extra_retries_on_back_to_back_fail() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); route_params.max_total_routing_fee_msat = None; let mut route = Route { paths: vec![ - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_1_scid, - channel_features: nodes[1].node.channel_features(), - fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }, RouteHop { - pubkey: nodes[2].node.get_our_node_id(), - node_features: nodes[2].node.node_features(), - short_channel_id: chan_2_scid, - channel_features: nodes[2].node.channel_features(), - fee_msat: 100_000_000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_1_scid, - channel_features: nodes[1].node.channel_features(), - fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }, RouteHop { - pubkey: nodes[2].node.get_our_node_id(), - node_features: nodes[2].node.node_features(), - short_channel_id: chan_2_scid, - channel_features: nodes[2].node.channel_features(), - fee_msat: 100_000_000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None } + Path { + hops: vec![ + RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_1_scid, + channel_features: nodes[1].node.channel_features(), + fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + RouteHop { + pubkey: nodes[2].node.get_our_node_id(), + node_features: nodes[2].node.node_features(), + short_channel_id: chan_2_scid, + channel_features: nodes[2].node.channel_features(), + fee_msat: 100_000_000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + ], + blinded_tail: None, + }, + Path { + hops: vec![ + RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_1_scid, + channel_features: nodes[1].node.channel_features(), + fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + RouteHop { + pubkey: nodes[2].node.get_our_node_id(), + node_features: nodes[2].node.node_features(), + short_channel_id: chan_2_scid, + channel_features: nodes[2].node.channel_features(), + fee_msat: 100_000_000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + ], + blinded_tail: None, + }, ], route_params: Some(route_params.clone()), }; @@ -2974,7 +4141,8 @@ fn no_extra_retries_on_back_to_back_fail() { // On retry, we'll only return one path route.paths.remove(1); route.paths[0].hops[1].fee_msat = amt_msat; - let mut retry_params = RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat); + let mut retry_params = + RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat); retry_params.max_total_routing_fee_msat = None; route.route_params = Some(retry_params.clone()); nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); @@ -2982,54 +4150,98 @@ fn no_extra_retries_on_back_to_back_fail() { // We can't use the commitment_signed_dance macro helper because in this test we'll be sending // two HTLCs back-to-back on the same channel, and the macro only expects to handle one at a // time. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); let first_htlc_updates = SendEvent::from_node(&nodes[0]); check_added_monitors!(nodes[0], 1); assert_eq!(first_htlc_updates.msgs.len(), 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &first_htlc_updates.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &first_htlc_updates.commitment_msg); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &first_htlc_updates.msgs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &first_htlc_updates.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_first_raa, bs_first_cs) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_first_raa); check_added_monitors!(nodes[0], 1); let second_htlc_updates = SendEvent::from_node(&nodes[0]); assert_eq!(second_htlc_updates.msgs.len(), 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); check_added_monitors!(nodes[0], 1); - let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_first_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_first_raa); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &second_htlc_updates.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &second_htlc_updates.commitment_msg); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &second_htlc_updates.msgs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &second_htlc_updates.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let (bs_second_raa, bs_second_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_second_raa, bs_second_cs) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_second_raa); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_cs); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_second_cs); check_added_monitors!(nodes[0], 1); - let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_second_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_second_raa); check_added_monitors!(nodes[1], 1); expect_pending_htlcs_forwardable!(nodes[1]); - let next_hop_failure = HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }; - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[next_hop_failure.clone(), next_hop_failure.clone()]); + let next_hop_failure = HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2, + }; + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[next_hop_failure.clone(), next_hop_failure.clone()] + ); check_added_monitors(&nodes[1], 1); let bs_fail_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert_eq!(bs_fail_update.update_fail_htlcs.len(), 2); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_fail_update.update_fail_htlcs[0]); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_fail_update.update_fail_htlcs[1]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &bs_fail_update.update_fail_htlcs[0], + ); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &bs_fail_update.update_fail_htlcs[1], + ); commitment_signed_dance!(nodes[0], nodes[1], bs_fail_update.commitment_signed, false); // At this point A has sent two HTLCs which both failed due to lack of fee. It now has two @@ -3047,7 +4259,11 @@ fn no_extra_retries_on_back_to_back_fail() { let mut events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 3); match events[0] { - Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, .. } => { + Event::PaymentPathFailed { + payment_hash: ev_payment_hash, + payment_failed_permanently, + .. + } => { assert_eq!(payment_hash, ev_payment_hash); assert_eq!(payment_failed_permanently, false); }, @@ -3058,7 +4274,11 @@ fn no_extra_retries_on_back_to_back_fail() { _ => panic!("Unexpected event"), } match events[2] { - Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, .. } => { + Event::PaymentPathFailed { + payment_hash: ev_payment_hash, + payment_failed_permanently, + .. + } => { assert_eq!(payment_hash, ev_payment_hash); assert_eq!(payment_failed_permanently, false); }, @@ -3069,27 +4289,43 @@ fn no_extra_retries_on_back_to_back_fail() { let retry_htlc_updates = SendEvent::from_node(&nodes[0]); check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &retry_htlc_updates.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &retry_htlc_updates.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], &retry_htlc_updates.commitment_msg, false, true); expect_pending_htlcs_forwardable!(nodes[1]); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[next_hop_failure.clone()]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[next_hop_failure.clone()] + ); check_added_monitors(&nodes[1], 1); let bs_fail_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_fail_update.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &bs_fail_update.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], &bs_fail_update.commitment_signed, false, true); let mut events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, .. } => { + Event::PaymentPathFailed { + payment_hash: ev_payment_hash, + payment_failed_permanently, + .. + } => { assert_eq!(payment_hash, ev_payment_hash); assert_eq!(payment_failed_permanently, false); }, _ => panic!("Unexpected event"), } match events[1] { - Event::PaymentFailed { payment_hash: ref ev_payment_hash, payment_id: ref ev_payment_id, reason: ref ev_reason } => { + Event::PaymentFailed { + payment_hash: ref ev_payment_hash, + payment_id: ref ev_payment_id, + reason: ref ev_reason, + } => { assert_eq!(Some(payment_hash), *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RetriesExhausted, ev_reason.unwrap()); @@ -3116,7 +4352,8 @@ fn test_simple_partial_retry() { let chan_2_scid = chan_2.0.contents.short_channel_id; let amt_msat = 200_000_000; - let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[2], amt_msat); + let (_, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[2], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -3125,48 +4362,62 @@ fn test_simple_partial_retry() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); route_params.max_total_routing_fee_msat = None; let mut route = Route { paths: vec![ - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_1_scid, - channel_features: nodes[1].node.channel_features(), - fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }, RouteHop { - pubkey: nodes[2].node.get_our_node_id(), - node_features: nodes[2].node.node_features(), - short_channel_id: chan_2_scid, - channel_features: nodes[2].node.channel_features(), - fee_msat: 100_000_000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_1_scid, - channel_features: nodes[1].node.channel_features(), - fee_msat: 100_000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }, RouteHop { - pubkey: nodes[2].node.get_our_node_id(), - node_features: nodes[2].node.node_features(), - short_channel_id: chan_2_scid, - channel_features: nodes[2].node.channel_features(), - fee_msat: 100_000_000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None } + Path { + hops: vec![ + RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_1_scid, + channel_features: nodes[1].node.channel_features(), + fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + RouteHop { + pubkey: nodes[2].node.get_our_node_id(), + node_features: nodes[2].node.node_features(), + short_channel_id: chan_2_scid, + channel_features: nodes[2].node.channel_features(), + fee_msat: 100_000_000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + ], + blinded_tail: None, + }, + Path { + hops: vec![ + RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_1_scid, + channel_features: nodes[1].node.channel_features(), + fee_msat: 100_000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + RouteHop { + pubkey: nodes[2].node.get_our_node_id(), + node_features: nodes[2].node.node_features(), + short_channel_id: chan_2_scid, + channel_features: nodes[2].node.channel_features(), + fee_msat: 100_000_000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + ], + blinded_tail: None, + }, ], route_params: Some(route_params.clone()), }; @@ -3177,7 +4428,8 @@ fn test_simple_partial_retry() { second_payment_params.previously_failed_channels = vec![chan_2_scid]; // On retry, we'll only be asked for one path (or 100k sats) route.paths.remove(0); - let mut retry_params = RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat / 2); + let mut retry_params = + RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat / 2); retry_params.max_total_routing_fee_msat = None; route.route_params = Some(retry_params.clone()); nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); @@ -3185,36 +4437,64 @@ fn test_simple_partial_retry() { // We can't use the commitment_signed_dance macro helper because in this test we'll be sending // two HTLCs back-to-back on the same channel, and the macro only expects to handle one at a // time. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(1), + ) + .unwrap(); let first_htlc_updates = SendEvent::from_node(&nodes[0]); check_added_monitors!(nodes[0], 1); assert_eq!(first_htlc_updates.msgs.len(), 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &first_htlc_updates.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &first_htlc_updates.commitment_msg); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &first_htlc_updates.msgs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &first_htlc_updates.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_first_raa, bs_first_cs) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_first_raa); check_added_monitors!(nodes[0], 1); let second_htlc_updates = SendEvent::from_node(&nodes[0]); assert_eq!(second_htlc_updates.msgs.len(), 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); + nodes[0] + .node + .handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_first_cs); check_added_monitors!(nodes[0], 1); - let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let as_first_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &as_first_raa); check_added_monitors!(nodes[1], 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &second_htlc_updates.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &second_htlc_updates.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], second_htlc_updates.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[1]); - let next_hop_failure = HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }; - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[next_hop_failure.clone()]); + let next_hop_failure = HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2, + }; + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[next_hop_failure.clone()] + ); check_added_monitors(&nodes[1], 2); { @@ -3224,11 +4504,17 @@ fn test_simple_partial_retry() { if let MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, updates } = event { if node_id == nodes[0].node.get_our_node_id() { assert_eq!(updates.update_fail_htlcs.len(), 1); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], &updates.commitment_signed, false); } else if node_id == nodes[2].node.get_our_node_id() { assert_eq!(updates.update_add_htlcs.len(), 1); - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[2].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_add_htlcs[0], + ); commitment_signed_dance!(nodes[2], nodes[1], &updates.commitment_signed, false); } else { panic!("Unexpected node_id for UpdateHTLCs send"); @@ -3244,7 +4530,11 @@ fn test_simple_partial_retry() { let mut events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, .. } => { + Event::PaymentPathFailed { + payment_hash: ev_payment_hash, + payment_failed_permanently, + .. + } => { assert_eq!(payment_hash, ev_payment_hash); assert_eq!(payment_failed_permanently, false); }, @@ -3259,15 +4549,25 @@ fn test_simple_partial_retry() { let retry_htlc_updates = SendEvent::from_node(&nodes[0]); check_added_monitors!(nodes[0], 1); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &retry_htlc_updates.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &retry_htlc_updates.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], &retry_htlc_updates.commitment_msg, false, true); expect_pending_htlcs_forwardable!(nodes[1]); check_added_monitors!(nodes[1], 1); let bs_second_forward_update = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &bs_second_forward_update.update_add_htlcs[0]); - commitment_signed_dance!(nodes[2], nodes[1], &bs_second_forward_update.commitment_signed, false); + nodes[2].node.handle_update_add_htlc( + nodes[1].node.get_our_node_id(), + &bs_second_forward_update.update_add_htlcs[0], + ); + commitment_signed_dance!( + nodes[2], + nodes[1], + &bs_second_forward_update.commitment_signed, + false + ); expect_pending_htlcs_forwardable!(nodes[2]); expect_payment_claimable!(nodes[2], payment_hash, payment_secret, amt_msat); @@ -3291,13 +4591,23 @@ fn test_threaded_payment_retries() { // keep things simple, we route one HTLC for 0.1% of the payment over channel 1 and the rest // out over channel 3+4. This will let us ignore 99% of the payment value and deal with only // our channel. - let chan_1_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0).0.contents.short_channel_id; + let chan_1_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0) + .0 + .contents + .short_channel_id; create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 10_000_000, 0); - let chan_3_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 10_000_000, 0).0.contents.short_channel_id; - let chan_4_scid = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 0).0.contents.short_channel_id; + let chan_3_scid = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 10_000_000, 0) + .0 + .contents + .short_channel_id; + let chan_4_scid = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 0) + .0 + .contents + .short_channel_id; let amt_msat = 100_000_000; - let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[2], amt_msat); + let (_, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(&nodes[0], nodes[2], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] @@ -3306,66 +4616,92 @@ fn test_threaded_payment_retries() { invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_expiry_time(payment_expiry_secs as u64) - .with_bolt11_features(invoice_features).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_expiry_time(payment_expiry_secs as u64) + .with_bolt11_features(invoice_features) + .unwrap(); let mut route_params = RouteParameters { - payment_params, final_value_msat: amt_msat, max_total_routing_fee_msat: Some(500_000), + payment_params, + final_value_msat: amt_msat, + max_total_routing_fee_msat: Some(500_000), }; let mut route = Route { paths: vec![ - Path { hops: vec![RouteHop { - pubkey: nodes[1].node.get_our_node_id(), - node_features: nodes[1].node.node_features(), - short_channel_id: chan_1_scid, - channel_features: nodes[1].node.channel_features(), - fee_msat: 0, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }, RouteHop { - pubkey: nodes[3].node.get_our_node_id(), - node_features: nodes[2].node.node_features(), - short_channel_id: 42, // Set a random SCID which nodes[1] will fail as unknown - channel_features: nodes[2].node.channel_features(), - fee_msat: amt_msat / 1000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None }, - Path { hops: vec![RouteHop { - pubkey: nodes[2].node.get_our_node_id(), - node_features: nodes[2].node.node_features(), - short_channel_id: chan_3_scid, - channel_features: nodes[2].node.channel_features(), - fee_msat: 100_000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }, RouteHop { - pubkey: nodes[3].node.get_our_node_id(), - node_features: nodes[3].node.node_features(), - short_channel_id: chan_4_scid, - channel_features: nodes[3].node.channel_features(), - fee_msat: amt_msat - amt_msat / 1000, - cltv_expiry_delta: 100, - maybe_announced_channel: true, - }], blinded_tail: None } + Path { + hops: vec![ + RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_1_scid, + channel_features: nodes[1].node.channel_features(), + fee_msat: 0, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + RouteHop { + pubkey: nodes[3].node.get_our_node_id(), + node_features: nodes[2].node.node_features(), + short_channel_id: 42, // Set a random SCID which nodes[1] will fail as unknown + channel_features: nodes[2].node.channel_features(), + fee_msat: amt_msat / 1000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + ], + blinded_tail: None, + }, + Path { + hops: vec![ + RouteHop { + pubkey: nodes[2].node.get_our_node_id(), + node_features: nodes[2].node.node_features(), + short_channel_id: chan_3_scid, + channel_features: nodes[2].node.channel_features(), + fee_msat: 100_000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + RouteHop { + pubkey: nodes[3].node.get_our_node_id(), + node_features: nodes[3].node.node_features(), + short_channel_id: chan_4_scid, + channel_features: nodes[3].node.channel_features(), + fee_msat: amt_msat - amt_msat / 1000, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }, + ], + blinded_tail: None, + }, ], route_params: Some(route_params.clone()), }; nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0xdeadbeef)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(0xdeadbeef), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); let mut send_msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(send_msg_events.len(), 2); - send_msg_events.retain(|msg| + send_msg_events.retain(|msg| { if let MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, .. } = msg { // Drop the commitment update for nodes[2], we can just let that one sit pending // forever. *node_id == nodes[1].node.get_our_node_id() - } else { panic!(); } - ); + } else { + panic!(); + } + }); // from here on out, the retry `RouteParameters` amount will be amt/1000 route_params.final_value_msat /= 1000; @@ -3388,7 +4724,9 @@ fn test_threaded_payment_retries() { } } } } let mut threads = Vec::new(); - for _ in 0..16 { threads.push(std::thread::spawn(thread_body!())); } + for _ in 0..16 { + threads.push(std::thread::spawn(thread_body!())); + } // Back in the main thread, poll pending messages and make sure that we never have more than // one HTLC pending at a time. Note that the commitment_signed_dance will fail horribly if @@ -3406,7 +4744,9 @@ fn test_threaded_payment_retries() { nodes[1].node.process_pending_htlc_forwards(); expect_htlc_handling_failed_destinations!( nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::UnknownNextHop { requested_forward_scid: route.paths[0].hops[1].short_channel_id }] + &[HTLCDestination::UnknownNextHop { + requested_forward_scid: route.paths[0].hops[1].short_channel_id + }] ); check_added_monitors(&nodes[1], 1); @@ -3416,25 +4756,39 @@ fn test_threaded_payment_retries() { // many HTLCs at once. let mut new_route_params = route_params.clone(); previously_failed_channels.push(route.paths[0].hops[1].short_channel_id); - new_route_params.payment_params.previously_failed_channels = previously_failed_channels.clone(); + new_route_params.payment_params.previously_failed_channels = + previously_failed_channels.clone(); new_route_params.max_total_routing_fee_msat.as_mut().map(|m| *m -= 100_000); route.paths[0].hops[1].short_channel_id += 1; route.route_params = Some(new_route_params.clone()); nodes[0].router.expect_find_route(new_route_params, Ok(route.clone())); let bs_fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_fail_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &bs_fail_updates.update_fail_htlcs[0], + ); // The "normal" commitment_signed_dance delivers the final RAA and then calls // `check_added_monitors` to ensure only the one RAA-generated monitor update was created. // This races with our other threads which may generate an add-HTLCs commitment update via // `process_pending_htlc_forwards`. Instead, we defer the monitor update check until after // *we've* called `process_pending_htlc_forwards` when its guaranteed to have two updates. - let last_raa = commitment_signed_dance!(nodes[0], nodes[1], bs_fail_updates.commitment_signed, false, true, false, true); + let last_raa = commitment_signed_dance!( + nodes[0], + nodes[1], + bs_fail_updates.commitment_signed, + false, + true, + false, + true + ); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &last_raa); let cur_time = Instant::now(); if cur_time > end_time { - for thread in threads.drain(..) { thread.join().unwrap(); } + for thread in threads.drain(..) { + thread.join().unwrap(); + } } // Make sure we have some events to handle when we go around... @@ -3468,7 +4822,8 @@ fn do_no_missing_sent_on_reload(persist_manager_with_payment: bool, at_midpoint: nodes_0_serialized = nodes[0].node.encode(); } - let (our_payment_preimage, our_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (our_payment_preimage, our_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 1_000_000); if persist_manager_with_payment { nodes_0_serialized = nodes[0].node.encode(); @@ -3480,12 +4835,21 @@ fn do_no_missing_sent_on_reload(persist_manager_with_payment: bool, at_midpoint: if at_midpoint { let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &updates.commitment_signed); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[0], 1); } else { let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &htlc_fulfill_updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], htlc_fulfill_updates.commitment_signed, false); // Ignore the PaymentSent event which is now pending on nodes[0] - if we were to handle it we'd // be expected to ignore the eventual conflicting PaymentFailed, but by not looking at it we @@ -3496,12 +4860,27 @@ fn do_no_missing_sent_on_reload(persist_manager_with_payment: bool, at_midpoint: // The ChannelMonitor should always be the latest version, as we're required to persist it // during the commitment signed handling. let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - reload_node!(nodes[0], test_default_channel_config(), &nodes_0_serialized, &[&chan_0_monitor_serialized], persister_a, chain_monitor_a, nodes_0_deserialized); + reload_node!( + nodes[0], + test_default_channel_config(), + &nodes_0_serialized, + &[&chan_0_monitor_serialized], + persister_a, + chain_monitor_a, + nodes_0_deserialized + ); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); - if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[0] {} else { panic!(); } - if let Event::PaymentSent { payment_preimage, .. } = events[1] { assert_eq!(payment_preimage, our_payment_preimage); } else { panic!(); } + if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[0] { + } else { + panic!(); + } + if let Event::PaymentSent { payment_preimage, .. } = events[1] { + assert_eq!(payment_preimage, our_payment_preimage); + } else { + panic!(); + } // Note that we don't get a PaymentPathSuccessful here as we leave the HTLC pending to avoid // the double-claim that would otherwise appear at the end of this test. nodes[0].node.timer_tick_occurred(); @@ -3513,23 +4892,43 @@ fn do_no_missing_sent_on_reload(persist_manager_with_payment: bool, at_midpoint: // payments have since been timed out thanks to `IDEMPOTENCY_TIMEOUT_TICKS`. // A naive implementation of the fix here would wipe the pending payments set, causing a // failure event when we restart. - for _ in 0..(IDEMPOTENCY_TIMEOUT_TICKS * 2) { nodes[0].node.timer_tick_occurred(); } + for _ in 0..(IDEMPOTENCY_TIMEOUT_TICKS * 2) { + nodes[0].node.timer_tick_occurred(); + } let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - reload_node!(nodes[0], test_default_channel_config(), &nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister_b, chain_monitor_b, nodes_0_deserialized_b); + reload_node!( + nodes[0], + test_default_channel_config(), + &nodes[0].node.encode(), + &[&chan_0_monitor_serialized], + persister_b, + chain_monitor_b, + nodes_0_deserialized_b + ); let events = nodes[0].node.get_and_clear_pending_events(); assert!(events.is_empty()); // Ensure that we don't generate any further events even after the channel-closing commitment // transaction is confirmed on-chain. confirm_transaction(&nodes[0], &as_broadcasted_txn[0]); - for _ in 0..(IDEMPOTENCY_TIMEOUT_TICKS * 2) { nodes[0].node.timer_tick_occurred(); } + for _ in 0..(IDEMPOTENCY_TIMEOUT_TICKS * 2) { + nodes[0].node.timer_tick_occurred(); + } let events = nodes[0].node.get_and_clear_pending_events(); assert!(events.is_empty()); let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - reload_node!(nodes[0], test_default_channel_config(), &nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister_c, chain_monitor_c, nodes_0_deserialized_c); + reload_node!( + nodes[0], + test_default_channel_config(), + &nodes[0].node.encode(), + &[&chan_0_monitor_serialized], + persister_c, + chain_monitor_c, + nodes_0_deserialized_c + ); let events = nodes[0].node.get_and_clear_pending_events(); assert!(events.is_empty()); } @@ -3573,14 +4972,29 @@ fn do_claim_from_closed_chan(fail_payment: bool) { create_announced_chan_between_nodes(&nodes, 2, 3); let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[3]); - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 10_000_000); - let mut route = nodes[0].router.find_route(&nodes[0].node.get_our_node_id(), &route_params, - None, nodes[0].node.compute_inflight_htlcs()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params, 10_000_000); + let mut route = nodes[0] + .router + .find_route( + &nodes[0].node.get_our_node_id(), + &route_params, + None, + nodes[0].node.compute_inflight_htlcs(), + ) + .unwrap(); // Make sure the route is ordered as the B->D path before C->D - route.paths.sort_by(|a, _| if a.hops[0].pubkey == nodes[1].node.get_our_node_id() { - std::cmp::Ordering::Less } else { std::cmp::Ordering::Greater }); + route.paths.sort_by(|a, _| { + if a.hops[0].pubkey == nodes[1].node.get_our_node_id() { + std::cmp::Ordering::Less + } else { + std::cmp::Ordering::Greater + } + }); // Note that we add an extra 1 in the send pipeline to compensate for any blocks found while // the HTLC is being relayed. @@ -3589,22 +5003,50 @@ fn do_claim_from_closed_chan(fail_payment: bool) { let final_cltv = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 8 + 1; nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + route_params.clone(), + Retry::Attempts(1), + ) + .unwrap(); check_added_monitors(&nodes[0], 2); let mut send_msgs = nodes[0].node.get_and_clear_pending_msg_events(); send_msgs.sort_by(|a, _| { let a_node_id = if let MessageSendEvent::UpdateHTLCs { node_id, .. } = a { node_id } else { panic!() }; let node_b_id = nodes[1].node.get_our_node_id(); - if *a_node_id == node_b_id { std::cmp::Ordering::Less } else { std::cmp::Ordering::Greater } + if *a_node_id == node_b_id { + std::cmp::Ordering::Less + } else { + std::cmp::Ordering::Greater + } }); assert_eq!(send_msgs.len(), 2); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 10_000_000, - payment_hash, Some(payment_secret), send_msgs.remove(0), false, None); - let receive_event = pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 10_000_000, - payment_hash, Some(payment_secret), send_msgs.remove(0), true, None); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + 10_000_000, + payment_hash, + Some(payment_secret), + send_msgs.remove(0), + false, + None, + ); + let receive_event = pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + 10_000_000, + payment_hash, + Some(payment_secret), + send_msgs.remove(0), + true, + None, + ); match receive_event.unwrap() { Event::PaymentClaimable { claim_deadline, .. } => { @@ -3615,8 +5057,13 @@ fn do_claim_from_closed_chan(fail_payment: bool) { // Ensure that the claim_deadline is correct, with the payment failing at exactly the given // height. - connect_blocks(&nodes[3], final_cltv - HTLC_FAIL_BACK_BUFFER - nodes[3].best_block_info().1 - - if fail_payment { 0 } else { 2 }); + connect_blocks( + &nodes[3], + final_cltv + - HTLC_FAIL_BACK_BUFFER + - nodes[3].best_block_info().1 + - if fail_payment { 0 } else { 2 }, + ); let error_message = "Channel force-closed"; if fail_payment { // We fail the HTLC on the A->B->D path first as it expires 4 blocks earlier. We go ahead @@ -3625,11 +5072,30 @@ fn do_claim_from_closed_chan(fail_payment: bool) { expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[3], [reason.clone()]); connect_blocks(&nodes[3], 4); expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[3], [reason]); - pass_failed_payment_back(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_hash, PaymentFailureReason::RecipientRejected); + pass_failed_payment_back( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_hash, + PaymentFailureReason::RecipientRejected, + ); } else { - nodes[1].node.force_close_broadcasting_latest_txn(&chan_bd, &nodes[3].node.get_our_node_id(), error_message.to_string()).unwrap(); - check_closed_event!(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, - [nodes[3].node.get_our_node_id()], 1000000); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_bd, + &nodes[3].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); + check_closed_event!( + &nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + [nodes[3].node.get_our_node_id()], + 1000000 + ); check_closed_broadcast(&nodes[1], 1, true); let bs_tx = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(bs_tx.len(), 1); @@ -3637,8 +5103,14 @@ fn do_claim_from_closed_chan(fail_payment: bool) { mine_transaction(&nodes[3], &bs_tx[0]); check_added_monitors(&nodes[3], 1); check_closed_broadcast(&nodes[3], 1, true); - check_closed_event!(&nodes[3], 1, ClosureReason::CommitmentTxConfirmed, false, - [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + &nodes[3], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + [nodes[1].node.get_our_node_id()], + 1000000 + ); nodes[3].node.claim_funds(payment_preimage); check_added_monitors(&nodes[3], 2); @@ -3656,28 +5128,44 @@ fn do_claim_from_closed_chan(fail_payment: bool) { check_added_monitors(&nodes[1], 1); assert_eq!(bs_claims.len(), 1); if let MessageSendEvent::UpdateHTLCs { updates, .. } = &bs_claims[0] { - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false, true); - } else { panic!(); } + } else { + panic!(); + } expect_payment_sent!(nodes[0], payment_preimage); let ds_claim_msgs = nodes[3].node.get_and_clear_pending_msg_events(); assert_eq!(ds_claim_msgs.len(), 1); - let cs_claim_msgs = if let MessageSendEvent::UpdateHTLCs { updates, .. } = &ds_claim_msgs[0] { - nodes[2].node.handle_update_fulfill_htlc(nodes[3].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + let cs_claim_msgs = if let MessageSendEvent::UpdateHTLCs { updates, .. } = &ds_claim_msgs[0] + { + nodes[2].node.handle_update_fulfill_htlc( + nodes[3].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); let cs_claim_msgs = nodes[2].node.get_and_clear_pending_msg_events(); check_added_monitors(&nodes[2], 1); commitment_signed_dance!(nodes[2], nodes[3], updates.commitment_signed, false, true); expect_payment_forwarded!(nodes[2], nodes[0], nodes[3], Some(1000), false, false); cs_claim_msgs - } else { panic!(); }; + } else { + panic!(); + }; assert_eq!(cs_claim_msgs.len(), 1); if let MessageSendEvent::UpdateHTLCs { updates, .. } = &cs_claim_msgs[0] { - nodes[0].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[2], updates.commitment_signed, false, true); - } else { panic!(); } + } else { + panic!(); + } expect_payment_path_successful!(nodes[0]); } @@ -3712,7 +5200,8 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) { create_announced_chan_between_nodes(&nodes, 0, 1); let amt_msat = 100_000; - let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(&nodes[0], &nodes[1], amt_msat); + let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(&nodes[0], &nodes[1], amt_msat); let payment_id = PaymentId(our_payment_hash.0); let custom_tlvs = vec![ (if even_tlvs { 5482373482 } else { 5482373483 }, vec![1, 2, 3, 4]), @@ -3721,15 +5210,24 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) { let onion_fields = RecipientOnionFields { payment_secret: if spontaneous { None } else { Some(our_payment_secret) }, payment_metadata: None, - custom_tlvs: custom_tlvs.clone() + custom_tlvs: custom_tlvs.clone(), }; if spontaneous { - nodes[0].node.send_spontaneous_payment( - Some(our_payment_preimage), onion_fields, payment_id, route.route_params.unwrap(), - Retry::Attempts(0) - ).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + Some(our_payment_preimage), + onion_fields, + payment_id, + route.route_params.unwrap(), + Retry::Attempts(0), + ) + .unwrap(); } else { - nodes[0].node.send_payment_with_route(route, our_payment_hash, onion_fields, payment_id).unwrap(); + nodes[0] + .node + .send_payment_with_route(route, our_payment_hash, onion_fields, payment_id) + .unwrap(); } check_added_monitors(&nodes[0], 1); @@ -3756,22 +5254,32 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) { nodes[1].node.claim_funds_with_known_custom_tlvs(our_payment_preimage); let expected_total_fee_msat = pass_claimed_payment_along_route( ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage) - .with_custom_tlvs(custom_tlvs) + .with_custom_tlvs(custom_tlvs), ); expect_payment_sent!(&nodes[0], our_payment_preimage, Some(expected_total_fee_msat)); }, (false, false) => { claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage) - .with_custom_tlvs(custom_tlvs) + .with_custom_tlvs(custom_tlvs), ); }, (false, true) => { nodes[1].node.claim_funds(our_payment_preimage); - let expected_destinations = vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]; - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], expected_destinations); - pass_failed_payment_back(&nodes[0], &[&[&nodes[1]]], false, our_payment_hash, PaymentFailureReason::RecipientRejected); - } + let expected_destinations = + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]; + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + expected_destinations + ); + pass_failed_payment_back( + &nodes[0], + &[&[&nodes[1]]], + false, + our_payment_hash, + PaymentFailureReason::RecipientRejected, + ); + }, } } @@ -3787,7 +5295,7 @@ fn test_retry_custom_tlvs() { let (chan_2_update, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 2, 1); // Rebalance - send_payment(&nodes[2], &vec!(&nodes[1])[..], 1_500_000); + send_payment(&nodes[2], &vec![&nodes[1]][..], 1_500_000); let amt_msat = 1_000_000; let (mut route, payment_hash, payment_preimage, payment_secret) = @@ -3802,8 +5310,16 @@ fn test_retry_custom_tlvs() { let onion_fields = onion_fields.with_custom_tlvs(custom_tlvs.clone()).unwrap(); nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment(payment_hash, onion_fields, - payment_id, route_params.clone(), Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + onion_fields, + payment_id, + route_params.clone(), + Retry::Attempts(1), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); // one monitor per path // Add the HTLC along the first hop. @@ -3815,11 +5331,13 @@ fn test_retry_custom_tlvs() { // Attempt to forward the payment and complete the path's failure. expect_pending_htlcs_forwardable!(&nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[1], + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + &nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2_id - }]); + }] + ); check_added_monitors!(nodes[1], 1); let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -3831,17 +5349,24 @@ fn test_retry_custom_tlvs() { let mut events = nodes[0].node.get_and_clear_pending_events(); match events[1] { Event::PendingHTLCsForwardable { .. } => {}, - _ => panic!("Unexpected event") + _ => panic!("Unexpected event"), } events.remove(1); - expect_payment_failed_conditions_event(events, payment_hash, false, - PaymentFailedConditions::new().mpp_parts_remain()); + expect_payment_failed_conditions_event( + events, + payment_hash, + false, + PaymentFailedConditions::new().mpp_parts_remain(), + ); // Rebalance the channel so the retry of the payment can succeed. - send_payment(&nodes[2], &vec!(&nodes[1])[..], 1_500_000); + send_payment(&nodes[2], &vec![&nodes[1]][..], 1_500_000); // Retry the payment and make sure it succeeds - route_params.payment_params.previously_failed_channels.push(chan_2_update.contents.short_channel_id); + route_params + .payment_params + .previously_failed_channels + .push(chan_2_update.contents.short_channel_id); route.route_params = Some(route_params.clone()); nodes[0].router.expect_find_route(route_params, Ok(route)); nodes[0].node.process_pending_htlc_forwards(); @@ -3849,22 +5374,23 @@ fn test_retry_custom_tlvs() { let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let path = &[&nodes[1], &nodes[2]]; - let args = PassAlongPathArgs::new(&nodes[0], path, 1_000_000, payment_hash, events.pop().unwrap()) - .with_payment_secret(payment_secret) - .with_custom_tlvs(custom_tlvs.clone()); + let args = + PassAlongPathArgs::new(&nodes[0], path, 1_000_000, payment_hash, events.pop().unwrap()) + .with_payment_secret(payment_secret) + .with_custom_tlvs(custom_tlvs.clone()); do_pass_along_path(args); claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) - .with_custom_tlvs(custom_tlvs) + .with_custom_tlvs(custom_tlvs), ); } #[test] fn test_custom_tlvs_consistency() { let even_type_1 = 1 << 16; - let odd_type_1 = (1 << 16)+ 1; + let odd_type_1 = (1 << 16) + 1; let even_type_2 = (1 << 16) + 2; - let odd_type_2 = (1 << 16) + 3; + let odd_type_2 = (1 << 16) + 3; let value_1 = || vec![1, 2, 3, 4]; let differing_value_1 = || vec![1, 2, 3, 5]; let value_2 = || vec![42u8; 16]; @@ -3895,9 +5421,10 @@ fn test_custom_tlvs_consistency() { ); } -fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: Vec<(u64, Vec)>, - expected_receive_tlvs: Option)>>) { - +fn do_test_custom_tlvs_consistency( + first_tlvs: Vec<(u64, Vec)>, second_tlvs: Vec<(u64, Vec)>, + expected_receive_tlvs: Option)>>, +) { let chanmon_cfgs = create_chanmon_cfgs(4); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); @@ -3908,17 +5435,23 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0); let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0); - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()) + .unwrap(); let mut route = get_route!(nodes[0], payment_params, 15_000_000).unwrap(); assert_eq!(route.paths.len(), 2); route.paths.sort_by(|path_a, _| { // Sort the path so that the path through nodes[1] comes first if path_a.hops[0].pubkey == nodes[1].node.get_our_node_id() { - core::cmp::Ordering::Less } else { core::cmp::Ordering::Greater } + core::cmp::Ordering::Less + } else { + core::cmp::Ordering::Greater + } }); - let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[3]); + let (our_payment_preimage, our_payment_hash, our_payment_secret) = + get_payment_preimage_hash!(&nodes[3]); let payment_id = PaymentId([42; 32]); let amt_msat = 15_000_000; @@ -3926,21 +5459,41 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: let onion_fields = RecipientOnionFields { payment_secret: Some(our_payment_secret), payment_metadata: None, - custom_tlvs: first_tlvs + custom_tlvs: first_tlvs, }; - let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, - onion_fields.clone(), payment_id, &route).unwrap(); + let session_privs = nodes[0] + .node + .test_add_new_pending_payment(our_payment_hash, onion_fields.clone(), payment_id, &route) + .unwrap(); let cur_height = nodes[0].best_block_info().1; - nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, - onion_fields.clone(), amt_msat, cur_height, payment_id, - &None, session_privs[0]).unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &route.paths[0], + &our_payment_hash, + onion_fields.clone(), + amt_msat, + cur_height, + payment_id, + &None, + session_privs[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); - pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], amt_msat, our_payment_hash, - Some(our_payment_secret), events.pop().unwrap(), false, None); + pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[3]], + amt_msat, + our_payment_hash, + Some(our_payment_secret), + events.pop().unwrap(), + false, + None, + ); } assert!(nodes[3].node.get_and_clear_pending_events().is_empty()); @@ -3948,10 +5501,21 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: let onion_fields = RecipientOnionFields { payment_secret: Some(our_payment_secret), payment_metadata: None, - custom_tlvs: second_tlvs + custom_tlvs: second_tlvs, }; - nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, - onion_fields.clone(), amt_msat, cur_height, payment_id, &None, session_privs[1]).unwrap(); + nodes[0] + .node + .test_send_payment_along_path( + &route.paths[1], + &our_payment_hash, + onion_fields.clone(), + amt_msat, + cur_height, + payment_id, + &None, + session_privs[1], + ) + .unwrap(); check_added_monitors!(nodes[0], 1); { @@ -3959,7 +5523,9 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[2].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[2] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[2], nodes[0], payment_event.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[2]); @@ -3969,7 +5535,9 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: assert_eq!(events.len(), 1); let payment_event = SendEvent::from_event(events.pop().unwrap()); - nodes[3].node.handle_update_add_htlc(nodes[2].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[3] + .node + .handle_update_add_htlc(nodes[2].node.get_our_node_id(), &payment_event.msgs[0]); check_added_monitors!(nodes[3], 0); commitment_signed_dance!(nodes[3], nodes[2], payment_event.commitment_msg, true, true); } @@ -3988,33 +5556,50 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: } do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], our_payment_preimage) - .with_custom_tlvs(expected_tlvs) + ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + our_payment_preimage, + ) + .with_custom_tlvs(expected_tlvs), ); expect_payment_sent(&nodes[0], our_payment_preimage, Some(Some(2000)), true, true); } else { // Expect fail back - let expected_destinations = vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]; + let expected_destinations = + vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]; expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], expected_destinations); check_added_monitors!(nodes[3], 1); let fail_updates_1 = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &fail_updates_1.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[2], nodes[3], fail_updates_1.commitment_signed, false); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![ - HTLCDestination::NextHopChannel { + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 - }]); + }] + ); check_added_monitors!(nodes[2], 1); let fail_updates_2 = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &fail_updates_2.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[2].node.get_our_node_id(), + &fail_updates_2.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[2], fail_updates_2.commitment_signed, false); - expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, - PaymentFailedConditions::new().mpp_parts_remain()); + expect_payment_failed_conditions( + &nodes[0], + our_payment_hash, + true, + PaymentFailedConditions::new().mpp_parts_remain(), + ); } } @@ -4032,7 +5617,11 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { let mut config = test_default_channel_config(); config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 50; - let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, Some(config.clone()), Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 4, + &node_cfgs, + &[None, Some(config.clone()), Some(config.clone()), Some(config.clone())], + ); let nodes_0_deserialized; let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs); @@ -4044,18 +5633,32 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { // Pay more than half of each channel's max, requiring MPP let amt_msat = 750_000_000; - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[3], Some(amt_msat)); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash!(nodes[3], Some(amt_msat)); let payment_id = PaymentId(payment_hash.0); let payment_metadata = vec![44, 49, 52, 142]; - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); // Send the MPP payment, delivering the updated commitment state to nodes[1]. - nodes[0].node.send_payment(payment_hash, RecipientOnionFields { - payment_secret: Some(payment_secret), payment_metadata: Some(payment_metadata), custom_tlvs: vec![], - }, payment_id, route_params.clone(), Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields { + payment_secret: Some(payment_secret), + payment_metadata: Some(payment_metadata), + custom_tlvs: vec![], + }, + payment_id, + route_params.clone(), + Retry::Attempts(1), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); let mut send_events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -4089,18 +5692,29 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { expect_pending_htlcs_forwardable!(nodes[2]); expect_htlc_handling_failed_destinations!( nodes[2].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_id_cd }] + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_id_cd + }] ); check_added_monitors(&nodes[2], 1); let cs_fail = get_htlc_update_msgs(&nodes[2], &nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &cs_fail.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &cs_fail.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[2], cs_fail.commitment_signed, false, true); let payment_fail_retryable_evs = nodes[0].node.get_and_clear_pending_events(); assert_eq!(payment_fail_retryable_evs.len(), 2); - if let Event::PaymentPathFailed { .. } = payment_fail_retryable_evs[0] {} else { panic!(); } - if let Event::PendingHTLCsForwardable { .. } = payment_fail_retryable_evs[1] {} else { panic!(); } + if let Event::PaymentPathFailed { .. } = payment_fail_retryable_evs[0] { + } else { + panic!(); + } + if let Event::PendingHTLCsForwardable { .. } = payment_fail_retryable_evs[1] { + } else { + panic!(); + } // Before we allow the HTLC to be retried, optionally change the payment_metadata we have // stored for our payment. @@ -4113,8 +5727,15 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { if do_reload { let mon_bd = get_monitor!(nodes[3], chan_id_bd).encode(); let mon_cd = get_monitor!(nodes[3], chan_id_cd).encode(); - reload_node!(nodes[3], config, &nodes[3].node.encode(), &[&mon_bd, &mon_cd], - persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[3], + config, + &nodes[3].node.encode(), + &[&mon_bd, &mon_cd], + persister, + new_chain_monitor, + nodes_0_deserialized + ); nodes[1].node.peer_disconnected(nodes[3].node.get_our_node_id()); reconnect_nodes(ReconnectArgs::new(&nodes[1], &nodes[3])); } @@ -4146,23 +5767,35 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { if do_modify { expect_pending_htlcs_forwardable_ignore!(nodes[3]); nodes[3].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_conditions(nodes[3].node.get_and_clear_pending_events(), - &[HTLCDestination::FailedPayment {payment_hash}]); + expect_pending_htlcs_forwardable_conditions( + nodes[3].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash }], + ); nodes[3].node.process_pending_htlc_forwards(); check_added_monitors(&nodes[3], 1); let ds_fail = get_htlc_update_msgs(&nodes[3], &nodes[2].node.get_our_node_id()); - nodes[2].node.handle_update_fail_htlc(nodes[3].node.get_our_node_id(), &ds_fail.update_fail_htlcs[0]); + nodes[2].node.handle_update_fail_htlc( + nodes[3].node.get_our_node_id(), + &ds_fail.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[2], nodes[3], ds_fail.commitment_signed, false, true); - expect_pending_htlcs_forwardable_conditions(nodes[2].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: cd_channel_used }]); + expect_pending_htlcs_forwardable_conditions( + nodes[2].node.get_and_clear_pending_events(), + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: cd_channel_used, + }], + ); } else { expect_pending_htlcs_forwardable!(nodes[3]); expect_payment_claimable!(nodes[3], payment_hash, payment_secret, amt_msat); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) - ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + payment_preimage, + )); } } @@ -4175,7 +5808,7 @@ fn test_payment_metadata_consistency() { } #[test] -fn test_htlc_forward_considers_anchor_outputs_value() { +fn test_htlc_forward_considers_anchor_outputs_value() { // Tests that: // // 1) Forwarding nodes don't forward HTLCs that would cause their balance to dip below the @@ -4193,21 +5826,38 @@ fn test_htlc_forward_considers_anchor_outputs_value() { // discovery of this bug. let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(config.clone()), Some(config.clone()), Some(config.clone())], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); const CHAN_AMT: u64 = 1_000_000; const PUSH_MSAT: u64 = 900_000_000; create_announced_chan_between_nodes_with_value(&nodes, 0, 1, CHAN_AMT, 500_000_000); - let (_, _, chan_id_2, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, CHAN_AMT, PUSH_MSAT); + let (_, _, chan_id_2, _) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, CHAN_AMT, PUSH_MSAT); - let channel_reserve_msat = get_holder_selected_channel_reserve_satoshis(CHAN_AMT, &config) * 1000; + let channel_reserve_msat = + get_holder_selected_channel_reserve_satoshis(CHAN_AMT, &config) * 1000; let commitment_fee_msat = chan_utils::commit_tx_fee_sat( - *nodes[1].fee_estimator.sat_per_kw.lock().unwrap(), 2, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + *nodes[1].fee_estimator.sat_per_kw.lock().unwrap(), + 2, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), ) * 1000; let anchor_outpus_value_msat = ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000; - let sendable_balance_msat = CHAN_AMT * 1000 - PUSH_MSAT - channel_reserve_msat - commitment_fee_msat - anchor_outpus_value_msat; - let channel_details = nodes[1].node.list_channels().into_iter().find(|channel| channel.channel_id == chan_id_2).unwrap(); + let sendable_balance_msat = CHAN_AMT * 1000 + - PUSH_MSAT + - channel_reserve_msat + - commitment_fee_msat + - anchor_outpus_value_msat; + let channel_details = nodes[1] + .node + .list_channels() + .into_iter() + .find(|channel| channel.channel_id == chan_id_2) + .unwrap(); assert!(sendable_balance_msat >= channel_details.next_outbound_htlc_minimum_msat); assert!(sendable_balance_msat <= channel_details.next_outbound_htlc_limit_msat); @@ -4217,17 +5867,29 @@ fn test_htlc_forward_considers_anchor_outputs_value() { // Send out an HTLC that would cause the forwarding node to dip below its reserve when // considering the value of anchor outputs. let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!( - nodes[0], nodes[2], sendable_balance_msat + anchor_outpus_value_msat + nodes[0], + nodes[2], + sendable_balance_msat + anchor_outpus_value_msat ); - nodes[0].node.send_payment_with_route( - route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.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); - let mut update_add_htlc = if let MessageSendEvent::UpdateHTLCs { updates, .. } = events.pop().unwrap() { - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + let mut update_add_htlc = if let MessageSendEvent::UpdateHTLCs { updates, .. } = + events.pop().unwrap() + { + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); check_added_monitors(&nodes[1], 0); commitment_signed_dance!(nodes[1], nodes[0], &updates.commitment_signed, false); updates.update_add_htlcs[0].clone() @@ -4237,16 +5899,22 @@ fn test_htlc_forward_considers_anchor_outputs_value() { // The forwarding node should reject forwarding it as expected. expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[1], vec![HTLCDestination::NextHopChannel { - node_id: Some(nodes[2].node.get_our_node_id()), - channel_id: chan_id_2 - }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + &nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] + ); check_added_monitors(&nodes[1], 1); let mut events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); if let MessageSendEvent::UpdateHTLCs { updates, .. } = events.pop().unwrap() { - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); check_added_monitors(&nodes[0], 0); commitment_signed_dance!(nodes[0], nodes[1], &updates.commitment_signed, false); } else { @@ -4259,9 +5927,16 @@ fn test_htlc_forward_considers_anchor_outputs_value() { // invalid update and closes the channel. update_add_htlc.channel_id = chan_id_2; nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &update_add_htlc); - check_closed_event(&nodes[2], 1, ClosureReason::ProcessingError { - err: "Remote HTLC add would put them under remote reserve value".to_owned() - }, false, &[nodes[1].node.get_our_node_id()], 1_000_000); + check_closed_event( + &nodes[2], + 1, + ClosureReason::ProcessingError { + err: "Remote HTLC add would put them under remote reserve value".to_owned(), + }, + false, + &[nodes[1].node.get_our_node_id()], + 1_000_000, + ); check_closed_broadcast(&nodes[2], 1, true); check_added_monitors(&nodes[2], 1); } @@ -4276,21 +5951,31 @@ fn peel_payment_onion_custom_tlvs() { let secp_ctx = Secp256k1::new(); let amt_msat = 1000; - let payment_params = PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(), - TEST_FINAL_CLTV, false); + let payment_params = + PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV, false); let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap(); let mut recipient_onion = RecipientOnionFields::spontaneous_empty() - .with_custom_tlvs(vec![(414141, vec![42; 1200])]).unwrap(); + .with_custom_tlvs(vec![(414141, vec![42; 1200])]) + .unwrap(); let prng_seed = chanmon_cfgs[0].keys_manager.get_secure_random_bytes(); let session_priv = SecretKey::from_slice(&prng_seed[..]).expect("RNG is busted"); let keysend_preimage = PaymentPreimage([42; 32]); let payment_hash = PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array()); let (onion_routing_packet, first_hop_msat, cltv_expiry) = onion_utils::create_payment_onion( - &secp_ctx, &route.paths[0], &session_priv, amt_msat, &recipient_onion, - nodes[0].best_block_info().1, &payment_hash, &Some(keysend_preimage), None, prng_seed - ).unwrap(); + &secp_ctx, + &route.paths[0], + &session_priv, + amt_msat, + &recipient_onion, + nodes[0].best_block_info().1, + &payment_hash, + &Some(keysend_preimage), + None, + prng_seed, + ) + .unwrap(); let update_add = msgs::UpdateAddHTLC { channel_id: ChannelId([0; 32]), @@ -4303,9 +5988,14 @@ fn peel_payment_onion_custom_tlvs() { blinding_point: None, }; let peeled_onion = crate::ln::onion_payment::peel_payment_onion( - &update_add, &chanmon_cfgs[1].keys_manager, &chanmon_cfgs[1].logger, &secp_ctx, - nodes[1].best_block_info().1, false - ).unwrap(); + &update_add, + &chanmon_cfgs[1].keys_manager, + &chanmon_cfgs[1].logger, + &secp_ctx, + nodes[1].best_block_info().1, + false, + ) + .unwrap(); assert_eq!(peeled_onion.incoming_amt_msat, Some(amt_msat)); match peeled_onion.routing { PendingHTLCRouting::ReceiveKeysend { @@ -4318,7 +6008,7 @@ fn peel_payment_onion_custom_tlvs() { assert!(payment_metadata.is_none()); assert!(payment_data.is_none()); }, - _ => panic!() + _ => panic!(), } } @@ -4328,27 +6018,44 @@ fn test_non_strict_forwarding() { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let mut config = test_default_channel_config(); config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config.clone()), Some(config.clone()), Some(config)]); + let node_chanmgrs = create_node_chanmgrs( + 3, + &node_cfgs, + &[Some(config.clone()), Some(config.clone()), Some(config)], + ); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Create a routing node with two outbound channels, each of which can forward 2 payments of // the given value. let payment_value = 1_500_000; create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); - let (chan_update_1, _, channel_id_1, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 4_950, 0); - let (chan_update_2, _, channel_id_2, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 5_000, 0); + let (chan_update_1, _, channel_id_1, _) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 4_950, 0); + let (chan_update_2, _, channel_id_2, _) = + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 5_000, 0); // Create a route once. - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap(); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, payment_value); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, payment_value); let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap(); // Send 4 payments over the same route. for i in 0..4 { - let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(payment_value), None); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (payment_preimage, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(payment_value), None); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); @@ -4365,11 +6072,7 @@ fn test_non_strict_forwarding() { // applying non-strict forwarding. // The channel with the least amount of outbound liquidity will be used to maximize the // probability of being able to successfully forward a subsequent HTLC. - assert_eq!(send_event.msgs[0].channel_id, if i < 2 { - channel_id_1 - } else { - channel_id_2 - }); + assert_eq!(send_event.msgs[0].channel_id, if i < 2 { channel_id_1 } else { channel_id_2 }); nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &send_event.msgs[0]); commitment_signed_dance!(nodes[2], nodes[1], &send_event.commitment_msg, false); @@ -4378,15 +6081,25 @@ fn test_non_strict_forwarding() { assert_eq!(events.len(), 1); assert!(matches!(events[0], Event::PaymentClaimable { .. })); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) - ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + payment_preimage, + )); } // Send a 5th payment which will fail. - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(payment_value), None); - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (_, payment_hash, payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(payment_value), None); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); @@ -4403,14 +6116,26 @@ fn test_non_strict_forwarding() { _ => panic!("Unexpected short channel id in route"), }; // The failure to forward will refer to the channel given in the onion. - expect_pending_htlcs_forwardable_conditions(nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: routed_channel_id }]); + expect_pending_htlcs_forwardable_conditions( + nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: routed_channel_id, + }], + ); let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false); let events = nodes[0].node.get_and_clear_pending_events(); - expect_payment_failed_conditions_event(events, payment_hash, false, PaymentFailedConditions::new().blamed_scid(routed_scid)); + expect_payment_failed_conditions_event( + events, + payment_hash, + false, + PaymentFailedConditions::new().blamed_scid(routed_scid), + ); } #[test] @@ -4426,8 +6151,10 @@ fn remove_pending_outbounds_on_buggy_router() { let amt_msat = 10_000; let payment_id = PaymentId([42; 32]); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 0) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); - let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, amt_msat); + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); + let (mut route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, amt_msat); // Extend the path by itself, essentially simulating route going through same channel twice let cloned_hops = route.paths[0].hops.clone(); @@ -4435,26 +6162,37 @@ fn remove_pending_outbounds_on_buggy_router() { let route_params = route.route_params.clone().unwrap(); nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); - nodes[0].node.send_payment( - payment_hash, RecipientOnionFields::secret_only(payment_secret), payment_id, route_params, - Retry::Attempts(1) // Even though another attempt is allowed, the payment should fail - ).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + route_params, + Retry::Attempts(1), // Even though another attempt is allowed, the payment should fail + ) + .unwrap(); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match &events[0] { Event::PaymentPathFailed { failure, payment_failed_permanently, .. } => { - assert_eq!(failure, &PathFailure::InitialSend { - err: APIError::InvalidRoute { err: "Path went through the same channel twice".to_string() } - }); + assert_eq!( + failure, + &PathFailure::InitialSend { + err: APIError::InvalidRoute { + err: "Path went through the same channel twice".to_string() + } + } + ); assert!(!payment_failed_permanently); }, - _ => panic!() + _ => panic!(), } match events[1] { Event::PaymentFailed { reason, .. } => { assert_eq!(reason.unwrap(), PaymentFailureReason::UnexpectedError); }, - _ => panic!() + _ => panic!(), } assert!(nodes[0].node.list_recent_payments().is_empty()); } @@ -4471,8 +6209,10 @@ fn remove_pending_outbound_probe_on_buggy_path() { let amt_msat = 10_000; let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 0) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); - let (mut route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, amt_msat); + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); + let (mut route, _, _, _) = + get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, amt_msat); // Extend the path by itself, essentially simulating route going through same channel twice let cloned_hops = route.paths[0].hops.clone(); @@ -4480,9 +6220,9 @@ fn remove_pending_outbound_probe_on_buggy_path() { assert_eq!( nodes[0].node.send_probe(route.paths.pop().unwrap()).unwrap_err(), - ProbeSendFailure::ParameterError( - APIError::InvalidRoute { err: "Path went through the same channel twice".to_string() } - ) + ProbeSendFailure::ParameterError(APIError::InvalidRoute { + err: "Path went through the same channel twice".to_string() + }) ); assert!(nodes[0].node.list_recent_payments().is_empty()); } @@ -4498,20 +6238,39 @@ fn pay_route_without_params() { create_announced_chan_between_nodes(&nodes, 0, 1); let amt_msat = 10_000; - let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, amt_msat); + let payment_params = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, amt_msat); route.route_params.take(); - nodes[0].node.send_payment_with_route( - route, payment_hash, RecipientOnionFields::secret_only(payment_secret), - PaymentId(payment_hash.0) - ).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.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); let node_1_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); - pass_along_path(&nodes[0], &[&nodes[1]], amt_msat, payment_hash, Some(payment_secret), node_1_msgs, true, None); - claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage) + pass_along_path( + &nodes[0], + &[&nodes[1]], + amt_msat, + payment_hash, + Some(payment_secret), + node_1_msgs, + true, + None, ); + claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[1]]], + payment_preimage, + )); } diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index 00e45afb4d8..5533289f4ef 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,25 +671,52 @@ 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 { - let their_node_id = PublicKey::from_slice(&>::from_hex("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap(); + let their_node_id = PublicKey::from_slice( + &>::from_hex( + "028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7", + ) + .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()); + 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()[..]); 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 our_node_id = SecretKey::from_slice( + &>::from_hex( + "2121212121212121212121212121212121212121212121212121212121212121", + ) + .unwrap()[..], + ) + .unwrap(); + let our_ephemeral = SecretKey::from_slice( + &>::from_hex( + "2222222222222222222222222222222222222222222222222222222222222222", + ) + .unwrap()[..], + ) + .unwrap(); let secp_ctx = Secp256k1::new(); let node_signer = TestNodeSigner::new(our_node_id); @@ -601,18 +728,48 @@ mod tests { let act_three = >::from_hex("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").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()[..]); + assert_eq!( + inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], + >::from_hex( + "034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa" + ) + .unwrap()[..] + ); match inbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, >::from_hex("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); + assert_eq!( + sk, + >::from_hex( + "bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442" + ) + .unwrap()[..] + ); assert_eq!(sn, 0); - assert_eq!(sck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, >::from_hex("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); + assert_eq!( + sck, + >::from_hex( + "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01" + ) + .unwrap()[..] + ); + assert_eq!( + rk, + >::from_hex( + "969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9" + ) + .unwrap()[..] + ); assert_eq!(rn, 0); - assert_eq!(rck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); + assert_eq!( + rck, + >::from_hex( + "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01" + ) + .unwrap()[..] + ); }, - _ => panic!() + _ => panic!(), } inbound_peer @@ -620,7 +777,13 @@ mod tests { #[test] fn noise_initiator_test_vectors() { - let our_node_id = SecretKey::from_slice(&>::from_hex("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); + let our_node_id = SecretKey::from_slice( + &>::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()[..], + ) + .unwrap(); let node_signer = TestNodeSigner::new(our_node_id); { @@ -632,14 +795,38 @@ mod tests { match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, >::from_hex("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); + assert_eq!( + sk, + >::from_hex( + "969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9" + ) + .unwrap()[..] + ); assert_eq!(sn, 0); - assert_eq!(sck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, >::from_hex("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); + assert_eq!( + sck, + >::from_hex( + "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01" + ) + .unwrap()[..] + ); + assert_eq!( + rk, + >::from_hex( + "bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442" + ) + .unwrap()[..] + ); assert_eq!(rn, 0); - assert_eq!(rck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); + assert_eq!( + rck, + >::from_hex( + "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01" + ) + .unwrap()[..] + ); }, - _ => panic!() + _ => panic!(), } } { @@ -673,8 +860,20 @@ mod tests { #[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 our_node_id = SecretKey::from_slice( + &>::from_hex( + "2121212121212121212121212121212121212121212121212121212121212121", + ) + .unwrap()[..], + ) + .unwrap(); + let our_ephemeral = SecretKey::from_slice( + &>::from_hex( + "2222222222222222222222222222222222222222222222222222222222222222", + ) + .unwrap()[..], + ) + .unwrap(); let secp_ctx = Secp256k1::new(); let node_signer = TestNodeSigner::new(our_node_id); @@ -690,21 +889,42 @@ mod tests { let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = >::from_hex("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").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 act_one =>::from_hex("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").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 MAC test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let act_one = >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").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 @@ -752,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 @@ -760,7 +979,13 @@ 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 our_node_id = SecretKey::from_slice( + &>::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()[..], + ) + .unwrap(); let node_signer = TestNodeSigner::new(our_node_id); let act_two = >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); @@ -768,14 +993,38 @@ mod tests { match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, >::from_hex("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); + assert_eq!( + sk, + >::from_hex( + "969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9" + ) + .unwrap()[..] + ); assert_eq!(sn, 0); - assert_eq!(sck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, >::from_hex("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); + assert_eq!( + sck, + >::from_hex( + "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01" + ) + .unwrap()[..] + ); + assert_eq!( + rk, + >::from_hex( + "bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442" + ) + .unwrap()[..] + ); assert_eq!(rn, 0); - assert_eq!(rck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); + assert_eq!( + rck, + >::from_hex( + "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01" + ) + .unwrap()[..] + ); }, - _ => panic!() + _ => panic!(), } } @@ -784,10 +1033,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 { assert_eq!(res, >::from_hex("cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95").unwrap()); @@ -803,7 +1055,7 @@ mod tests { assert_eq!(res, >::from_hex("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").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/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 07e63cf576c..dd9cca2aece 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -15,28 +15,39 @@ //! call into the provided message handlers (probably a ChannelManager and P2PGossipSync) with //! messages they should handle, and encoding/sending response messages. -use bitcoin::Txid; use bitcoin::constants::ChainHash; -use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey}; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; +use bitcoin::Txid; use crate::blinded_path::message::{AsyncPaymentsContext, DNSResolverContext, OffersContext}; -use crate::sign::{NodeSigner, Recipient}; -use crate::ln::types::ChannelId; -use crate::types::features::{InitFeatures, NodeFeatures}; use crate::ln::msgs; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, Init, LightningError, SocketAddress, MessageSendEvent, OnionMessageHandler, RoutingMessageHandler}; -use crate::util::ser::{VecWriter, Writeable, Writer}; -use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE}; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, Init, LightningError, MessageSendEvent, + OnionMessageHandler, RoutingMessageHandler, SocketAddress, +}; +use crate::ln::peer_channel_encryptor::{ + MessageBuf, NextNoiseStep, PeerChannelEncryptor, MSG_BUF_ALLOC_SIZE, +}; +use crate::ln::types::ChannelId; use crate::ln::wire; use crate::ln::wire::{Encode, Type}; -use crate::onion_message::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc}; -use crate::onion_message::dns_resolution::{DNSResolverMessageHandler, DNSResolverMessage, DNSSECProof, DNSSECQuery}; -use crate::onion_message::messenger::{CustomOnionMessageHandler, Responder, ResponseInstruction, MessageSendInstructions}; +use crate::onion_message::async_payments::{ + AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc, +}; +use crate::onion_message::dns_resolution::{ + DNSResolverMessage, DNSResolverMessageHandler, DNSSECProof, DNSSECQuery, +}; +use crate::onion_message::messenger::{ + CustomOnionMessageHandler, MessageSendInstructions, Responder, ResponseInstruction, +}; use crate::onion_message::offers::{OffersMessage, OffersMessageHandler}; use crate::onion_message::packet::OnionMessageContents; -use crate::routing::gossip::{NodeId, NodeAlias}; +use crate::routing::gossip::{NodeAlias, NodeId}; +use crate::sign::{NodeSigner, Recipient}; +use crate::types::features::{InitFeatures, NodeFeatures}; use crate::util::atomic_counter::AtomicCounter; use crate::util::logger::{Level, Logger, WithContext}; +use crate::util::ser::{VecWriter, Writeable, Writer}; use crate::util::string::PrintableString; #[allow(unused_imports)] @@ -45,11 +56,11 @@ use crate::prelude::*; use alloc::collections::{btree_map, BTreeMap}; use crate::io; -use crate::sync::{Mutex, MutexGuard, FairRwLock}; -use core::sync::atomic::{AtomicBool, AtomicU32, AtomicI32, Ordering}; -use core::{cmp, hash, fmt, mem}; -use core::ops::Deref; +use crate::sync::{FairRwLock, Mutex, MutexGuard}; use core::convert::Infallible; +use core::ops::Deref; +use core::sync::atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering}; +use core::{cmp, fmt, hash, mem}; #[cfg(not(c_bindings))] use { crate::ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager}, @@ -61,7 +72,7 @@ use { use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256::HashEngine as Sha256Engine; -use bitcoin::hashes::{HashEngine, Hash}; +use bitcoin::hashes::{Hash, HashEngine}; /// A handler provided to [`PeerManager`] for reading and handling custom messages. /// @@ -75,7 +86,9 @@ pub trait CustomMessageHandler: wire::CustomMessageReader { /// Handles the given message sent from `sender_node_id`, possibly producing messages for /// [`CustomMessageHandler::get_and_clear_pending_msg`] to return and thus for [`PeerManager`] /// to send. - fn handle_custom_message(&self, msg: Self::CustomMessage, sender_node_id: PublicKey) -> Result<(), LightningError>; + fn handle_custom_message( + &self, msg: Self::CustomMessage, sender_node_id: PublicKey, + ) -> Result<(), LightningError>; /// Returns the list of pending messages that were generated by the handler, clearing the list /// in the process. Each message is paired with the node id of the intended recipient. If no @@ -92,7 +105,8 @@ pub trait CustomMessageHandler: wire::CustomMessageReader { /// 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<(), ()>; /// Gets the node feature flags which this handler itself supports. All available handlers are /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`] @@ -111,39 +125,90 @@ pub trait CustomMessageHandler: wire::CustomMessageReader { /// A dummy struct which implements `RoutingMessageHandler` without storing any routing information /// or doing any processing. You can provide one of these as the route_handler in a MessageHandler. -pub struct IgnoringMessageHandler{} +pub struct IgnoringMessageHandler {} impl BaseMessageHandler for IgnoringMessageHandler { fn peer_disconnected(&self, _their_node_id: PublicKey) {} - fn peer_connected(&self, _their_node_id: PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) } - fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } + fn peer_connected( + &self, _their_node_id: PublicKey, _init: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { + Ok(()) + } + fn provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } fn provided_init_features(&self, _their_node_id: PublicKey) -> InitFeatures { InitFeatures::empty() } - fn get_and_clear_pending_msg_events(&self) -> Vec { Vec::new() } + fn get_and_clear_pending_msg_events(&self) -> Vec { + Vec::new() + } } impl RoutingMessageHandler for IgnoringMessageHandler { - fn handle_node_announcement(&self, _their_node_id: Option, _msg: &msgs::NodeAnnouncement) -> Result { Ok(false) } - fn handle_channel_announcement(&self, _their_node_id: Option, _msg: &msgs::ChannelAnnouncement) -> Result { Ok(false) } - fn handle_channel_update(&self, _their_node_id: Option, _msg: &msgs::ChannelUpdate) -> Result { Ok(false) } - fn get_next_channel_announcement(&self, _starting_point: u64) -> - Option<(msgs::ChannelAnnouncement, Option, Option)> { None } - fn get_next_node_announcement(&self, _starting_point: Option<&NodeId>) -> Option { None } - fn handle_reply_channel_range(&self, _their_node_id: PublicKey, _msg: msgs::ReplyChannelRange) -> Result<(), LightningError> { Ok(()) } - fn handle_reply_short_channel_ids_end(&self, _their_node_id: PublicKey, _msg: msgs::ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) } - fn handle_query_channel_range(&self, _their_node_id: PublicKey, _msg: msgs::QueryChannelRange) -> Result<(), LightningError> { Ok(()) } - fn handle_query_short_channel_ids(&self, _their_node_id: PublicKey, _msg: msgs::QueryShortChannelIds) -> Result<(), LightningError> { Ok(()) } - fn processing_queue_high(&self) -> bool { false } + fn handle_node_announcement( + &self, _their_node_id: Option, _msg: &msgs::NodeAnnouncement, + ) -> Result { + Ok(false) + } + fn handle_channel_announcement( + &self, _their_node_id: Option, _msg: &msgs::ChannelAnnouncement, + ) -> Result { + Ok(false) + } + fn handle_channel_update( + &self, _their_node_id: Option, _msg: &msgs::ChannelUpdate, + ) -> Result { + Ok(false) + } + fn get_next_channel_announcement( + &self, _starting_point: u64, + ) -> Option<(msgs::ChannelAnnouncement, Option, Option)> + { + None + } + fn get_next_node_announcement( + &self, _starting_point: Option<&NodeId>, + ) -> Option { + None + } + fn handle_reply_channel_range( + &self, _their_node_id: PublicKey, _msg: msgs::ReplyChannelRange, + ) -> Result<(), LightningError> { + Ok(()) + } + fn handle_reply_short_channel_ids_end( + &self, _their_node_id: PublicKey, _msg: msgs::ReplyShortChannelIdsEnd, + ) -> Result<(), LightningError> { + Ok(()) + } + fn handle_query_channel_range( + &self, _their_node_id: PublicKey, _msg: msgs::QueryChannelRange, + ) -> Result<(), LightningError> { + Ok(()) + } + fn handle_query_short_channel_ids( + &self, _their_node_id: PublicKey, _msg: msgs::QueryShortChannelIds, + ) -> Result<(), LightningError> { + Ok(()) + } + fn processing_queue_high(&self) -> bool { + false + } } impl OnionMessageHandler for IgnoringMessageHandler { fn handle_onion_message(&self, _their_node_id: PublicKey, _msg: &msgs::OnionMessage) {} - fn next_onion_message_for_peer(&self, _peer_node_id: PublicKey) -> Option { None } + fn next_onion_message_for_peer(&self, _peer_node_id: PublicKey) -> Option { + None + } fn timer_tick_occurred(&self) {} } impl OffersMessageHandler for IgnoringMessageHandler { - fn handle_message(&self, _message: OffersMessage, _context: Option, _responder: Option) -> Option<(OffersMessage, ResponseInstruction)> { + fn handle_message( + &self, _message: OffersMessage, _context: Option, + _responder: Option, + ) -> Option<(OffersMessage, ResponseInstruction)> { None } } @@ -166,11 +231,18 @@ impl DNSResolverMessageHandler for IgnoringMessageHandler { } impl CustomOnionMessageHandler for IgnoringMessageHandler { type CustomMessage = Infallible; - fn handle_custom_message(&self, _message: Infallible, _context: Option>, _responder: Option) -> Option<(Infallible, ResponseInstruction)> { + fn handle_custom_message( + &self, _message: Infallible, _context: Option>, _responder: Option, + ) -> Option<(Infallible, ResponseInstruction)> { // Since we always return `None` in the read the handle method should never be called. unreachable!(); } - fn read_custom_message(&self, _msg_type: u64, _buffer: &mut R) -> Result, msgs::DecodeError> where Self: Sized { + fn read_custom_message( + &self, _msg_type: u64, _buffer: &mut R, + ) -> Result, msgs::DecodeError> + where + Self: Sized, + { Ok(None) } fn release_pending_custom_messages(&self) -> Vec<(Infallible, MessageSendInstructions)> { @@ -179,16 +251,24 @@ impl CustomOnionMessageHandler for IgnoringMessageHandler { } impl OnionMessageContents for Infallible { - fn tlv_type(&self) -> u64 { unreachable!(); } + fn tlv_type(&self) -> u64 { + unreachable!(); + } #[cfg(c_bindings)] - fn msg_type(&self) -> String { unreachable!(); } + fn msg_type(&self) -> String { + unreachable!(); + } #[cfg(not(c_bindings))] - fn msg_type(&self) -> &'static str { unreachable!(); } + fn msg_type(&self) -> &'static str { + unreachable!(); + } } impl Deref for IgnoringMessageHandler { type Target = IgnoringMessageHandler; - fn deref(&self) -> &Self { self } + fn deref(&self) -> &Self { + self + } } // Implement Type for Infallible, note that it cannot be constructed, and thus you can never call a @@ -206,24 +286,36 @@ impl Writeable for Infallible { impl wire::CustomMessageReader for IgnoringMessageHandler { type CustomMessage = Infallible; - fn read(&self, _message_type: u16, _buffer: &mut R) -> Result, msgs::DecodeError> { + fn read( + &self, _message_type: u16, _buffer: &mut R, + ) -> Result, msgs::DecodeError> { Ok(None) } } impl CustomMessageHandler for IgnoringMessageHandler { - fn handle_custom_message(&self, _msg: Infallible, _sender_node_id: PublicKey) -> Result<(), LightningError> { + fn handle_custom_message( + &self, _msg: Infallible, _sender_node_id: PublicKey, + ) -> Result<(), LightningError> { // Since we always return `None` in the read the handle method should never be called. unreachable!(); } - fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { Vec::new() } + fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { + Vec::new() + } fn peer_disconnected(&self, _their_node_id: PublicKey) {} - fn peer_connected(&self, _their_node_id: PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> { Ok(()) } + fn peer_connected( + &self, _their_node_id: PublicKey, _msg: &Init, _inbound: bool, + ) -> Result<(), ()> { + Ok(()) + } - fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } + fn provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } fn provided_init_features(&self, _their_node_id: PublicKey) -> InitFeatures { InitFeatures::empty() @@ -233,7 +325,7 @@ impl CustomMessageHandler for IgnoringMessageHandler { /// A dummy struct which implements `ChannelMessageHandler` without having any channels. /// You can provide one of these as the route_handler in a MessageHandler. pub struct ErroringMessageHandler { - message_queue: Mutex> + message_queue: Mutex>, } impl ErroringMessageHandler { /// Constructs a new ErroringMessageHandler @@ -243,7 +335,10 @@ impl ErroringMessageHandler { fn push_error(&self, node_id: PublicKey, channel_id: ChannelId) { self.message_queue.lock().unwrap().push(MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { channel_id, data: "We do not support channel messages, sorry.".to_owned() }, + msg: msgs::ErrorMessage { + channel_id, + data: "We do not support channel messages, sorry.".to_owned(), + }, }, node_id, }); @@ -251,8 +346,14 @@ impl ErroringMessageHandler { } impl BaseMessageHandler for ErroringMessageHandler { fn peer_disconnected(&self, _their_node_id: PublicKey) {} - fn peer_connected(&self, _their_node_id: PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) } - fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } + fn peer_connected( + &self, _their_node_id: PublicKey, _init: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { + Ok(()) + } + fn provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } fn provided_init_features(&self, _their_node_id: PublicKey) -> InitFeatures { // Set a number of features which various nodes may require to talk to us. It's totally // reasonable to indicate we "support" all kinds of channel features...we just reject all @@ -284,10 +385,18 @@ impl ChannelMessageHandler for ErroringMessageHandler { // Any messages which are related to a specific channel generate an error message to let the // peer know we don't care about channels. fn handle_open_channel(&self, their_node_id: PublicKey, msg: &msgs::OpenChannel) { - ErroringMessageHandler::push_error(self, their_node_id, msg.common_fields.temporary_channel_id); + ErroringMessageHandler::push_error( + self, + their_node_id, + msg.common_fields.temporary_channel_id, + ); } fn handle_accept_channel(&self, their_node_id: PublicKey, msg: &msgs::AcceptChannel) { - ErroringMessageHandler::push_error(self, their_node_id, msg.common_fields.temporary_channel_id); + ErroringMessageHandler::push_error( + self, + their_node_id, + msg.common_fields.temporary_channel_id, + ); } fn handle_funding_created(&self, their_node_id: PublicKey, msg: &msgs::FundingCreated) { ErroringMessageHandler::push_error(self, their_node_id, msg.temporary_channel_id); @@ -328,7 +437,9 @@ impl ChannelMessageHandler for ErroringMessageHandler { fn handle_update_fail_htlc(&self, their_node_id: PublicKey, msg: &msgs::UpdateFailHTLC) { ErroringMessageHandler::push_error(self, their_node_id, msg.channel_id); } - fn handle_update_fail_malformed_htlc(&self, their_node_id: PublicKey, msg: &msgs::UpdateFailMalformedHTLC) { + fn handle_update_fail_malformed_htlc( + &self, their_node_id: PublicKey, msg: &msgs::UpdateFailMalformedHTLC, + ) { ErroringMessageHandler::push_error(self, their_node_id, msg.channel_id); } fn handle_commitment_signed(&self, their_node_id: PublicKey, msg: &msgs::CommitmentSigned) { @@ -346,7 +457,9 @@ impl ChannelMessageHandler for ErroringMessageHandler { fn handle_update_fee(&self, their_node_id: PublicKey, msg: &msgs::UpdateFee) { ErroringMessageHandler::push_error(self, their_node_id, msg.channel_id); } - fn handle_announcement_signatures(&self, their_node_id: PublicKey, msg: &msgs::AnnouncementSignatures) { + fn handle_announcement_signatures( + &self, their_node_id: PublicKey, msg: &msgs::AnnouncementSignatures, + ) { ErroringMessageHandler::push_error(self, their_node_id, msg.channel_id); } fn handle_channel_reestablish(&self, their_node_id: PublicKey, msg: &msgs::ChannelReestablish) { @@ -356,7 +469,10 @@ impl ChannelMessageHandler for ErroringMessageHandler { fn handle_channel_update(&self, _their_node_id: PublicKey, _msg: &msgs::ChannelUpdate) {} fn handle_peer_storage(&self, _their_node_id: PublicKey, _msg: msgs::PeerStorage) {} - fn handle_peer_storage_retrieval(&self, _their_node_id: PublicKey, _msg: msgs::PeerStorageRetrieval) {} + fn handle_peer_storage_retrieval( + &self, _their_node_id: PublicKey, _msg: msgs::PeerStorageRetrieval, + ) { + } fn handle_error(&self, _their_node_id: PublicKey, _msg: &msgs::ErrorMessage) {} @@ -368,11 +484,19 @@ impl ChannelMessageHandler for ErroringMessageHandler { } fn handle_open_channel_v2(&self, their_node_id: PublicKey, msg: &msgs::OpenChannelV2) { - ErroringMessageHandler::push_error(self, their_node_id, msg.common_fields.temporary_channel_id); + ErroringMessageHandler::push_error( + self, + their_node_id, + msg.common_fields.temporary_channel_id, + ); } fn handle_accept_channel_v2(&self, their_node_id: PublicKey, msg: &msgs::AcceptChannelV2) { - ErroringMessageHandler::push_error(self, their_node_id, msg.common_fields.temporary_channel_id); + ErroringMessageHandler::push_error( + self, + their_node_id, + msg.common_fields.temporary_channel_id, + ); } fn handle_tx_add_input(&self, their_node_id: PublicKey, msg: &msgs::TxAddInput) { @@ -416,11 +540,14 @@ impl ChannelMessageHandler for ErroringMessageHandler { impl Deref for ErroringMessageHandler { type Target = ErroringMessageHandler; - fn deref(&self) -> &Self { self } + fn deref(&self) -> &Self { + self + } } /// Provides references to trait impls which handle different types of messages. -pub struct MessageHandler where +pub struct MessageHandler +where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, @@ -460,7 +587,7 @@ pub struct MessageHandler where /// further calls to the [`PeerManager`] related to the original socket occur. This allows you to /// use a file descriptor for your SocketDescriptor directly, however for simplicity you may wish /// to simply use another value which is guaranteed to be globally unique instead. -pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone { +pub trait SocketDescriptor: cmp::Eq + hash::Hash + Clone { /// Attempts to send some data from the given slice to the peer. /// /// Returns the amount of data which was sent, possibly 0 if the socket has since disconnected. @@ -510,7 +637,7 @@ pub struct PeerDetails { /// generate no further read_event/write_buffer_space_avail/socket_disconnected calls for the /// descriptor. #[derive(Clone)] -pub struct PeerHandleError { } +pub struct PeerHandleError {} impl fmt::Debug for PeerHandleError { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { formatter.write_str("Peer Sent Invalid Data") @@ -523,7 +650,7 @@ impl fmt::Display for PeerHandleError { } /// Internal struct for keeping track of the gossip syncing progress with a given peer -enum InitSyncTracker{ +enum InitSyncTracker { /// Only sync ad-hoc gossip as it comes in, do not send historical gossip. /// Upon receipt of a GossipTimestampFilter message, this is the default initial state if the /// contained timestamp is less than 6 hours old. @@ -548,7 +675,8 @@ const FORWARD_INIT_SYNC_BUFFER_LIMIT_RATIO: usize = 2; const OUTBOUND_BUFFER_LIMIT_READ_PAUSE: usize = 12; /// When the outbound buffer has this many messages, we'll simply skip relaying gossip messages to /// the peer. -const OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP: usize = OUTBOUND_BUFFER_LIMIT_READ_PAUSE * FORWARD_INIT_SYNC_BUFFER_LIMIT_RATIO; +const OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP: usize = + OUTBOUND_BUFFER_LIMIT_READ_PAUSE * FORWARD_INIT_SYNC_BUFFER_LIMIT_RATIO; /// If we've sent a ping, and are still awaiting a response, we may need to churn our way through /// the socket receive buffer before receiving the ping. @@ -636,11 +764,14 @@ impl Peer { /// point and we shouldn't send it yet to avoid sending duplicate updates. If we've already /// sent the old versions, we should send the update, and so return true here. fn should_forward_channel_announcement(&self, channel_id: u64) -> bool { - if !self.handshake_complete() { return false; } - if self.their_features.as_ref().unwrap().supports_gossip_queries() && - !self.sent_gossip_timestamp_filter { - return false; - } + if !self.handshake_complete() { + return false; + } + if self.their_features.as_ref().unwrap().supports_gossip_queries() + && !self.sent_gossip_timestamp_filter + { + return false; + } match self.sync_status { InitSyncTracker::NoSyncRequested => true, InitSyncTracker::ChannelsSyncing(i) => i < channel_id, @@ -650,15 +781,20 @@ impl Peer { /// Similar to the above, but for node announcements indexed by node_id. fn should_forward_node_announcement(&self, node_id: NodeId) -> bool { - if !self.handshake_complete() { return false; } - if self.their_features.as_ref().unwrap().supports_gossip_queries() && - !self.sent_gossip_timestamp_filter { - return false; - } + if !self.handshake_complete() { + return false; + } + if self.their_features.as_ref().unwrap().supports_gossip_queries() + && !self.sent_gossip_timestamp_filter + { + return false; + } match self.sync_status { InitSyncTracker::NoSyncRequested => true, InitSyncTracker::ChannelsSyncing(_) => false, - InitSyncTracker::NodesSyncing(sync_node_id) => sync_node_id.as_slice() < node_id.as_slice(), + InitSyncTracker::NodesSyncing(sync_node_id) => { + sync_node_id.as_slice() < node_id.as_slice() + }, } } @@ -668,14 +804,15 @@ impl Peer { if !gossip_processing_backlogged { self.received_channel_announce_since_backlogged = false; } - self.pending_outbound_buffer.len() < OUTBOUND_BUFFER_LIMIT_READ_PAUSE && - (!gossip_processing_backlogged || !self.received_channel_announce_since_backlogged) + self.pending_outbound_buffer.len() < OUTBOUND_BUFFER_LIMIT_READ_PAUSE + && (!gossip_processing_backlogged || !self.received_channel_announce_since_backlogged) } /// Determines if we should push additional gossip background sync (aka "backfill") onto a peer's /// outbound buffer. This is checked every time the peer's buffer may have been drained. fn should_buffer_gossip_backfill(&self) -> bool { - self.pending_outbound_buffer.is_empty() && self.gossip_broadcast_buffer.is_empty() + self.pending_outbound_buffer.is_empty() + && self.gossip_broadcast_buffer.is_empty() && self.msgs_sent_since_pong < BUFFER_DRAIN_MSGS_PER_TICK && self.handshake_complete() } @@ -683,14 +820,16 @@ impl Peer { /// Determines if we should push an onion message onto a peer's outbound buffer. This is checked /// every time the peer's buffer may have been drained. fn should_buffer_onion_message(&self) -> bool { - self.pending_outbound_buffer.is_empty() && self.handshake_complete() + self.pending_outbound_buffer.is_empty() + && self.handshake_complete() && self.msgs_sent_since_pong < BUFFER_DRAIN_MSGS_PER_TICK } /// Determines if we should push additional gossip broadcast messages onto a peer's outbound /// buffer. This is checked every time the peer's buffer may have been drained. fn should_buffer_gossip_broadcast(&self) -> bool { - self.pending_outbound_buffer.is_empty() && self.handshake_complete() + self.pending_outbound_buffer.is_empty() + && self.handshake_complete() && self.msgs_sent_since_pong < BUFFER_DRAIN_MSGS_PER_TICK } @@ -699,8 +838,9 @@ impl Peer { let total_outbound_buffered = self.gossip_broadcast_buffer.len() + self.pending_outbound_buffer.len(); - total_outbound_buffered > OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP || - self.msgs_sent_since_pong > BUFFER_DRAIN_MSGS_PER_TICK * FORWARD_INIT_SYNC_BUFFER_LIMIT_RATIO + total_outbound_buffered > OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP + || self.msgs_sent_since_pong + > BUFFER_DRAIN_MSGS_PER_TICK * FORWARD_INIT_SYNC_BUFFER_LIMIT_RATIO } fn set_their_node_id(&mut self, node_id: PublicKey) { @@ -723,7 +863,7 @@ pub type SimpleArcPeerManager = PeerManager< Arc>, Arc, IgnoringMessageHandler, - Arc + Arc, >; /// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference @@ -736,7 +876,25 @@ pub type SimpleArcPeerManager = PeerManager< /// This is not exported to bindings users as type aliases aren't supported in most languages. #[cfg(not(c_bindings))] pub type SimpleRefPeerManager< - 'a, 'b, 'c, 'd, 'e, 'f, 'logger, 'h, 'i, 'j, 'graph, 'k, 'mr, SD, M, T, F, C, L + 'a, + 'b, + 'c, + 'd, + 'e, + 'f, + 'logger, + 'h, + 'i, + 'j, + 'graph, + 'k, + 'mr, + SD, + M, + T, + F, + C, + L, > = PeerManager< SD, &'j SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'graph, 'logger, 'i, 'mr, M, T, F, L>, @@ -744,10 +902,9 @@ pub type SimpleRefPeerManager< &'h SimpleRefOnionMessenger<'a, 'b, 'c, 'd, 'e, 'graph, 'logger, 'i, 'j, 'k, M, T, F, L>, &'logger L, IgnoringMessageHandler, - &'c KeysManager + &'c KeysManager, >; - /// A generic trait which is implemented for all [`PeerManager`]s. This makes bounding functions or /// structs on any [`PeerManager`] much simpler as only this trait is needed as a bound, rather /// than the full set of bounds on [`PeerManager`] itself. @@ -758,23 +915,33 @@ pub type SimpleRefPeerManager< pub trait APeerManager { type Descriptor: SocketDescriptor; type CMT: ChannelMessageHandler + ?Sized; - type CM: Deref; + type CM: Deref; type RMT: RoutingMessageHandler + ?Sized; - type RM: Deref; + type RM: Deref; type OMT: OnionMessageHandler + ?Sized; - type OM: Deref; + type OM: Deref; type LT: Logger + ?Sized; - type L: Deref; + type L: Deref; type CMHT: CustomMessageHandler + ?Sized; - type CMH: Deref; + type CMH: Deref; type NST: NodeSigner + ?Sized; - type NS: Deref; + type NS: Deref; /// Gets a reference to the underlying [`PeerManager`]. - fn as_ref(&self) -> &PeerManager; + fn as_ref( + &self, + ) -> &PeerManager; } -impl -APeerManager for PeerManager where +impl< + Descriptor: SocketDescriptor, + CM: Deref, + RM: Deref, + OM: Deref, + L: Deref, + CMH: Deref, + NS: Deref, + > APeerManager for PeerManager +where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, @@ -795,7 +962,9 @@ APeerManager for PeerManager where type CMH = CMH; type NST = ::Target; type NS = NS; - fn as_ref(&self) -> &PeerManager { self } + fn as_ref(&self) -> &PeerManager { + self + } } /// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls @@ -817,13 +986,22 @@ APeerManager for PeerManager where /// you're using lightning-net-tokio. /// /// [`read_event`]: PeerManager::read_event -pub struct PeerManager where - CM::Target: ChannelMessageHandler, - RM::Target: RoutingMessageHandler, - OM::Target: OnionMessageHandler, - L::Target: Logger, - CMH::Target: CustomMessageHandler, - NS::Target: NodeSigner { +pub struct PeerManager< + Descriptor: SocketDescriptor, + CM: Deref, + RM: Deref, + OM: Deref, + L: Deref, + CMH: Deref, + NS: Deref, +> where + CM::Target: ChannelMessageHandler, + RM::Target: RoutingMessageHandler, + OM::Target: OnionMessageHandler, + L::Target: Logger, + CMH::Target: CustomMessageHandler, + NS::Target: NodeSigner, +{ message_handler: MessageHandler, /// Connection state for each connected peer - we have an outer read-write lock which is taken /// as read while we're doing processing for a peer and taken write when a peer is being added @@ -866,7 +1044,7 @@ pub struct PeerManager + secp_ctx: Secp256k1, } enum LogicalMessage { @@ -896,14 +1074,17 @@ macro_rules! encode_msg { let mut buffer = VecWriter(Vec::with_capacity(MSG_BUF_ALLOC_SIZE)); wire::write($msg, &mut buffer).unwrap(); buffer.0 - }} + }}; } -impl PeerManager where - CM::Target: ChannelMessageHandler, - OM::Target: OnionMessageHandler, - L::Target: Logger, - NS::Target: NodeSigner { +impl + PeerManager +where + CM::Target: ChannelMessageHandler, + OM::Target: OnionMessageHandler, + L::Target: Logger, + NS::Target: NodeSigner, +{ /// Constructs a new `PeerManager` with the given `ChannelMessageHandler` and /// `OnionMessageHandler`. No routing message handler is used and network graph messages are /// ignored. @@ -917,20 +1098,39 @@ impl Pe /// minute should suffice. /// /// This is not exported to bindings users as we can't export a PeerManager with a dummy route handler - pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self { - Self::new(MessageHandler { - chan_handler: channel_message_handler, - route_handler: IgnoringMessageHandler{}, - onion_message_handler, - custom_message_handler: IgnoringMessageHandler{}, - }, current_time, ephemeral_random_data, logger, node_signer) + pub fn new_channel_only( + channel_message_handler: CM, onion_message_handler: OM, current_time: u32, + ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS, + ) -> Self { + Self::new( + MessageHandler { + chan_handler: channel_message_handler, + route_handler: IgnoringMessageHandler {}, + onion_message_handler, + custom_message_handler: IgnoringMessageHandler {}, + }, + current_time, + ephemeral_random_data, + logger, + node_signer, + ) } } -impl PeerManager where - RM::Target: RoutingMessageHandler, - L::Target: Logger, - NS::Target: NodeSigner { +impl + PeerManager< + Descriptor, + ErroringMessageHandler, + RM, + IgnoringMessageHandler, + L, + IgnoringMessageHandler, + NS, + > where + RM::Target: RoutingMessageHandler, + L::Target: Logger, + NS::Target: NodeSigner, +{ /// Constructs a new `PeerManager` with the given `RoutingMessageHandler`. No channel message /// handler or onion message handler is used and onion and channel messages will be ignored (or /// generate error messages). Note that some other lightning implementations time-out connections @@ -945,13 +1145,22 @@ impl PeerManager Self { - Self::new(MessageHandler { - chan_handler: ErroringMessageHandler::new(), - route_handler: routing_message_handler, - onion_message_handler: IgnoringMessageHandler{}, - custom_message_handler: IgnoringMessageHandler{}, - }, current_time, ephemeral_random_data, logger, node_signer) + pub fn new_routing_only( + routing_message_handler: RM, current_time: u32, ephemeral_random_data: &[u8; 32], + logger: L, node_signer: NS, + ) -> Self { + Self::new( + MessageHandler { + chan_handler: ErroringMessageHandler::new(), + route_handler: routing_message_handler, + onion_message_handler: IgnoringMessageHandler {}, + custom_message_handler: IgnoringMessageHandler {}, + }, + current_time, + ephemeral_random_data, + logger, + node_signer, + ) } } @@ -962,7 +1171,11 @@ impl PeerManager(&'a Option<(PublicKey, NodeId)>); impl core::fmt::Display for OptionalFromDebugger<'_> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { - if let Some((node_id, _)) = self.0 { write!(f, " from {}", log_pubkey!(node_id)) } else { Ok(()) } + if let Some((node_id, _)) = self.0 { + write!(f, " from {}", log_pubkey!(node_id)) + } else { + Ok(()) + } } } @@ -970,39 +1183,51 @@ impl core::fmt::Display for OptionalFromDebugger<'_> { /// /// fn filter_addresses(ip_address: Option) -> Option { - match ip_address{ + match ip_address { // For IPv4 range 10.0.0.0 - 10.255.255.255 (10/8) - Some(SocketAddress::TcpIpV4{addr: [10, _, _, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [10, _, _, _], port: _ }) => None, // For IPv4 range 0.0.0.0 - 0.255.255.255 (0/8) - Some(SocketAddress::TcpIpV4{addr: [0, _, _, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [0, _, _, _], port: _ }) => None, // For IPv4 range 100.64.0.0 - 100.127.255.255 (100.64/10) - Some(SocketAddress::TcpIpV4{addr: [100, 64..=127, _, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [100, 64..=127, _, _], port: _ }) => None, // For IPv4 range 127.0.0.0 - 127.255.255.255 (127/8) - Some(SocketAddress::TcpIpV4{addr: [127, _, _, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [127, _, _, _], port: _ }) => None, // For IPv4 range 169.254.0.0 - 169.254.255.255 (169.254/16) - Some(SocketAddress::TcpIpV4{addr: [169, 254, _, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [169, 254, _, _], port: _ }) => None, // For IPv4 range 172.16.0.0 - 172.31.255.255 (172.16/12) - Some(SocketAddress::TcpIpV4{addr: [172, 16..=31, _, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [172, 16..=31, _, _], port: _ }) => None, // For IPv4 range 192.168.0.0 - 192.168.255.255 (192.168/16) - Some(SocketAddress::TcpIpV4{addr: [192, 168, _, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [192, 168, _, _], port: _ }) => None, // For IPv4 range 192.88.99.0 - 192.88.99.255 (192.88.99/24) - Some(SocketAddress::TcpIpV4{addr: [192, 88, 99, _], port: _}) => None, + Some(SocketAddress::TcpIpV4 { addr: [192, 88, 99, _], port: _ }) => None, // For IPv6 range 2000:0000:0000:0000:0000:0000:0000:0000 - 3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff (2000::/3) - Some(SocketAddress::TcpIpV6{addr: [0x20..=0x3F, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _], port: _}) => ip_address, + Some(SocketAddress::TcpIpV6 { + addr: [0x20..=0x3F, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _], + port: _, + }) => ip_address, // For remaining addresses - Some(SocketAddress::TcpIpV6{addr: _, port: _}) => None, + Some(SocketAddress::TcpIpV6 { addr: _, port: _ }) => None, Some(..) => ip_address, None => None, } } -impl PeerManager where - CM::Target: ChannelMessageHandler, - RM::Target: RoutingMessageHandler, - OM::Target: OnionMessageHandler, - L::Target: Logger, - CMH::Target: CustomMessageHandler, - NS::Target: NodeSigner +impl< + Descriptor: SocketDescriptor, + CM: Deref, + RM: Deref, + OM: Deref, + L: Deref, + CMH: Deref, + NS: Deref, + > PeerManager +where + CM::Target: ChannelMessageHandler, + RM::Target: RoutingMessageHandler, + OM::Target: OnionMessageHandler, + L::Target: Logger, + CMH::Target: CustomMessageHandler, + NS::Target: NodeSigner, { /// Constructs a new `PeerManager` with the given message handlers. /// @@ -1013,7 +1238,10 @@ impl, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self { + pub fn new( + message_handler: MessageHandler, current_time: u32, + ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS, + ) -> Self { let mut ephemeral_key_midstate = Sha256::engine(); ephemeral_key_midstate.input(ephemeral_random_data); @@ -1041,23 +1269,26 @@ impl Vec { let peers = self.peers.read().unwrap(); - peers.values().filter_map(|peer_mutex| { - let p = peer_mutex.lock().unwrap(); - if !p.handshake_complete() { - return None; - } - let details = PeerDetails { - // unwrap safety: their_node_id is guaranteed to be `Some` after the handshake - // completed. - counterparty_node_id: p.their_node_id.unwrap().0, - socket_address: p.their_socket_address.clone(), - // unwrap safety: their_features is guaranteed to be `Some` after the handshake - // completed. - init_features: p.their_features.clone().unwrap(), - is_inbound_connection: p.inbound_connection, - }; - Some(details) - }).collect() + peers + .values() + .filter_map(|peer_mutex| { + let p = peer_mutex.lock().unwrap(); + if !p.handshake_complete() { + return None; + } + let details = PeerDetails { + // unwrap safety: their_node_id is guaranteed to be `Some` after the handshake + // completed. + counterparty_node_id: p.their_node_id.unwrap().0, + socket_address: p.their_socket_address.clone(), + // unwrap safety: their_features is guaranteed to be `Some` after the handshake + // completed. + init_features: p.their_features.clone().unwrap(), + is_inbound_connection: p.inbound_connection, + }; + Some(details) + }) + .collect() } /// Returns the [`PeerDetails`] of a connected peer that has completed the initial handshake. @@ -1095,7 +1326,8 @@ impl InitFeatures { @@ -1120,8 +1352,12 @@ impl) -> Result, PeerHandleError> { - let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone(), self.get_ephemeral_key()); + pub fn new_outbound_connection( + &self, their_node_id: PublicKey, descriptor: Descriptor, + remote_network_address: Option, + ) -> Result, PeerHandleError> { + let mut peer_encryptor = + PeerChannelEncryptor::new_outbound(their_node_id.clone(), self.get_ephemeral_key()); let res = peer_encryptor.get_act_one(&self.secp_ctx).to_vec(); let pending_read_buffer = [0; 50].to_vec(); // Noise act two is 50 bytes @@ -1160,7 +1396,7 @@ impl) -> Result<(), PeerHandleError> { + pub fn new_inbound_connection( + &self, descriptor: Descriptor, remote_network_address: Option, + ) -> Result<(), PeerHandleError> { let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.node_signer); let pending_read_buffer = [0; 50].to_vec(); // Noise act one is 50 bytes @@ -1218,7 +1456,7 @@ impl { - if let Some(msg) = self.message_handler.route_handler.get_next_node_announcement(None) { + if let Some(msg) = + self.message_handler.route_handler.get_next_node_announcement(None) + { self.enqueue_message(peer, &msg); peer.sync_status = InitSyncTracker::NodesSyncing(msg.contents.node_id); } else { @@ -1279,7 +1528,11 @@ impl unreachable!(), InitSyncTracker::NodesSyncing(sync_node_id) => { - if let Some(msg) = self.message_handler.route_handler.get_next_node_announcement(Some(&sync_node_id)) { + if let Some(msg) = self + .message_handler + .route_handler + .get_next_node_announcement(Some(&sync_node_id)) + { self.enqueue_message(peer, &msg); peer.sync_status = InitSyncTracker::NodesSyncing(msg.contents.node_id); } else { @@ -1301,7 +1554,7 @@ impl buff, }; @@ -1338,20 +1591,22 @@ impl Result<(), PeerHandleError> { + pub fn write_buffer_space_avail( + &self, descriptor: &mut Descriptor, + ) -> Result<(), PeerHandleError> { let peers = self.peers.read().unwrap(); match peers.get(descriptor) { None => { // This is most likely a simple race condition where the user found that the socket // was writeable, then we told the user to `disconnect_socket()`, then they called // this method. Return an error to make sure we get disconnected. - return Err(PeerHandleError { }); + return Err(PeerHandleError {}); }, Some(peer_mutex) => { let mut peer = peer_mutex.lock().unwrap(); peer.awaiting_write_event = false; self.do_attempt_write_data(descriptor, &mut peer, false); - } + }, }; Ok(()) } @@ -1373,13 +1628,15 @@ impl Result { + pub fn read_event( + &self, peer_descriptor: &mut Descriptor, data: &[u8], + ) -> Result { match self.do_read_event(peer_descriptor, data) { Ok(res) => Ok(res), Err(e) => { self.disconnect_event_internal(peer_descriptor, "of a protocol error"); Err(e) - } + }, } } @@ -1387,9 +1644,19 @@ impl(&self, peer: &mut Peer, message: &M) { let logger = WithContext::from(&self.logger, peer.their_node_id.map(|p| p.0), None, None); if is_gossip_msg(message.type_id()) { - log_gossip!(logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap().0)); + log_gossip!( + logger, + "Enqueueing message {:?} to {}", + message, + log_pubkey!(peer.their_node_id.unwrap().0) + ); } else { - log_trace!(logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap().0)) + log_trace!( + logger, + "Enqueueing message {:?} to {}", + message, + log_pubkey!(peer.their_node_id.unwrap().0) + ) } peer.msgs_sent_since_pong += 1; peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(message)); @@ -1401,7 +1668,9 @@ impl Result { + fn do_read_event( + &self, peer_descriptor: &mut Descriptor, data: &[u8], + ) -> Result { let mut pause_read = false; let peers = self.peers.read().unwrap(); let mut msgs_to_forward = Vec::new(); @@ -1411,7 +1680,7 @@ impl { let mut read_pos = 0; @@ -1480,8 +1749,13 @@ impl peer.pending_read_buffer_pos); { - let data_to_copy = cmp::min(peer.pending_read_buffer.len() - peer.pending_read_buffer_pos, data.len() - read_pos); - peer.pending_read_buffer[peer.pending_read_buffer_pos..peer.pending_read_buffer_pos + data_to_copy].copy_from_slice(&data[read_pos..read_pos + data_to_copy]); + let data_to_copy = cmp::min( + peer.pending_read_buffer.len() - peer.pending_read_buffer_pos, + data.len() - read_pos, + ); + peer.pending_read_buffer[peer.pending_read_buffer_pos + ..peer.pending_read_buffer_pos + data_to_copy] + .copy_from_slice(&data[read_pos..read_pos + data_to_copy]); read_pos += data_to_copy; peer.pending_read_buffer_pos += data_to_copy; } @@ -1513,16 +1787,27 @@ impl { - let act_two = try_potential_handleerror!(peer, peer.channel_encryptor - .process_act_one_with_keys(&peer.pending_read_buffer[..], - &self.node_signer, self.get_ephemeral_key(), &self.secp_ctx)).to_vec(); + let act_two = try_potential_handleerror!( + peer, + peer.channel_encryptor.process_act_one_with_keys( + &peer.pending_read_buffer[..], + &self.node_signer, + self.get_ephemeral_key(), + &self.secp_ctx + ) + ) + .to_vec(); peer.pending_outbound_buffer.push_back(act_two); peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long }, NextNoiseStep::ActTwo => { - let (act_three, their_node_id) = try_potential_handleerror!(peer, - peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], - &self.node_signer)); + let (act_three, their_node_id) = try_potential_handleerror!( + peer, + peer.channel_encryptor.process_act_two( + &peer.pending_read_buffer[..], + &self.node_signer + ) + ); peer.pending_outbound_buffer.push_back(act_three.to_vec()); peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes peer.pending_read_is_header = true; @@ -1531,47 +1816,79 @@ impl { - let their_node_id = try_potential_handleerror!(peer, - peer.channel_encryptor.process_act_three(&peer.pending_read_buffer[..])); + let their_node_id = try_potential_handleerror!( + peer, + peer.channel_encryptor + .process_act_three(&peer.pending_read_buffer[..]) + ); peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes peer.pending_read_is_header = true; peer.set_their_node_id(their_node_id); insert_node_id!(); let features = self.init_features(their_node_id); let networks = self.message_handler.chan_handler.get_chain_hashes(); - let resp = msgs::Init { features, networks, remote_network_address: filter_addresses(peer.their_socket_address.clone()) }; + let resp = msgs::Init { + features, + networks, + remote_network_address: filter_addresses( + peer.their_socket_address.clone(), + ), + }; self.enqueue_message(peer, &resp); }, NextNoiseStep::NoiseComplete => { if peer.pending_read_is_header { - let msg_len = try_potential_handleerror!(peer, - peer.channel_encryptor.decrypt_length_header(&peer.pending_read_buffer[..])); - if peer.pending_read_buffer.capacity() > 8192 { peer.pending_read_buffer = Vec::new(); } + let msg_len = try_potential_handleerror!( + peer, + peer.channel_encryptor + .decrypt_length_header(&peer.pending_read_buffer[..]) + ); + if peer.pending_read_buffer.capacity() > 8192 { + peer.pending_read_buffer = Vec::new(); + } peer.pending_read_buffer.resize(msg_len as usize + 16, 0); - if msg_len < 2 { // Need at least the message type tag - return Err(PeerHandleError { }); + if msg_len < 2 { + // Need at least the message type tag + return Err(PeerHandleError {}); } peer.pending_read_is_header = false; } else { debug_assert!(peer.pending_read_buffer.len() >= 2 + 16); - try_potential_handleerror!(peer, - peer.channel_encryptor.decrypt_message(&mut peer.pending_read_buffer[..])); + try_potential_handleerror!( + peer, + peer.channel_encryptor + .decrypt_message(&mut peer.pending_read_buffer[..]) + ); let message_result = wire::read( - &mut &peer.pending_read_buffer[..peer.pending_read_buffer.len() - 16], - &*self.message_handler.custom_message_handler + &mut &peer.pending_read_buffer + [..peer.pending_read_buffer.len() - 16], + &*self.message_handler.custom_message_handler, ); // Reset read buffer - if peer.pending_read_buffer.capacity() > 8192 { peer.pending_read_buffer = Vec::new(); } + if peer.pending_read_buffer.capacity() > 8192 { + peer.pending_read_buffer = Vec::new(); + } peer.pending_read_buffer.resize(18, 0); peer.pending_read_is_header = true; - let logger = WithContext::from(&self.logger, peer.their_node_id.map(|p| p.0), None, None); + let logger = WithContext::from( + &self.logger, + peer.their_node_id.map(|p| p.0), + None, + None, + ); let message = match message_result { Ok(x) => x, Err(e) => { @@ -1580,15 +1897,18 @@ impl { + ( + msgs::DecodeError::UnknownRequiredFeature, + Some(ty), + ) if is_gossip_msg(ty) => { log_gossip!(logger, "Got a channel/node announcement with an unknown required feature flag, you may want to update!"); continue; - } + }, (msgs::DecodeError::UnsupportedCompression, _) => { log_gossip!(logger, "We don't support zlib-compressed message fields, sending a warning and ignoring message"); self.enqueue_message(peer, &msgs::WarningMessage { channel_id: ChannelId::new_zero(), data: "Unsupported message compression: zlib".to_owned() }); continue; - } + }, (_, Some(ty)) if is_gossip_msg(ty) => { log_gossip!(logger, "Got an invalid value while deserializing a gossip message"); self.enqueue_message(peer, &msgs::WarningMessage { @@ -1596,30 +1916,38 @@ impl { log_debug!(logger, "Received a message with an unknown required feature flag or TLV, you may want to update!"); - return Err(PeerHandleError { }); - } - (msgs::DecodeError::UnknownVersion, _) => return Err(PeerHandleError { }), + return Err(PeerHandleError {}); + }, + (msgs::DecodeError::UnknownVersion, _) => { + return Err(PeerHandleError {}) + }, (msgs::DecodeError::InvalidValue, _) => { log_debug!(logger, "Got an invalid value while deserializing message"); - return Err(PeerHandleError { }); - } + return Err(PeerHandleError {}); + }, (msgs::DecodeError::ShortRead, _) => { log_debug!(logger, "Deserialization failed due to shortness of message"); - return Err(PeerHandleError { }); - } - (msgs::DecodeError::BadLengthDescriptor, _) => return Err(PeerHandleError { }), - (msgs::DecodeError::Io(_), _) => return Err(PeerHandleError { }), - (msgs::DecodeError::DangerousValue, _) => return Err(PeerHandleError { }), + return Err(PeerHandleError {}); + }, + (msgs::DecodeError::BadLengthDescriptor, _) => { + return Err(PeerHandleError {}) + }, + (msgs::DecodeError::Io(_), _) => { + return Err(PeerHandleError {}) + }, + (msgs::DecodeError::DangerousValue, _) => { + return Err(PeerHandleError {}) + }, } - } + }, }; msg_to_handle = Some(message); } - } + }, } } pause_read = !self.peer_should_read(peer); @@ -1627,9 +1955,12 @@ impl match handling_error { - MessageHandlingError::PeerHandleError(e) => { return Err(e) }, + MessageHandlingError::PeerHandleError(e) => return Err(e), MessageHandlingError::LightningError(e) => { - try_potential_handleerror!(&mut peer_mutex.lock().unwrap(), Err(e)); + try_potential_handleerror!( + &mut peer_mutex.lock().unwrap(), + Err(e) + ); }, }, Ok(Some(msg)) => { @@ -1639,11 +1970,16 @@ impl, - peer_lock: MutexGuard, - message: wire::Message<<::Target as wire::CustomMessageReader>::CustomMessage> - ) -> Result::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError> { - let their_node_id = peer_lock.their_node_id.expect("We know the peer's public key by the time we receive messages").0; + &self, peer_mutex: &Mutex, peer_lock: MutexGuard, + message: wire::Message< + <::Target as wire::CustomMessageReader>::CustomMessage, + >, + ) -> Result< + Option::Target as wire::CustomMessageReader>::CustomMessage>>, + MessageHandlingError, + > { + let their_node_id = peer_lock + .their_node_id + .expect("We know the peer's public key by the time we receive messages") + .0; let logger = WithContext::from(&self.logger, Some(their_node_id), None, None); - let unprocessed_message = self.do_handle_message_holding_peer_lock(peer_lock, message, their_node_id, &logger)?; + let unprocessed_message = + self.do_handle_message_holding_peer_lock(peer_lock, message, their_node_id, &logger)?; self.message_handler.chan_handler.message_received(); match unprocessed_message { - Some(LogicalMessage::FromWire(message)) => { - self.do_handle_message_without_peer_lock(peer_mutex, message, their_node_id, &logger) - }, + Some(LogicalMessage::FromWire(message)) => self.do_handle_message_without_peer_lock( + peer_mutex, + message, + their_node_id, + &logger, + ), Some(LogicalMessage::CommitmentSignedBatch(channel_id, batch)) => { - log_trace!(logger, "Received commitment_signed batch {:?} from {}", batch, log_pubkey!(their_node_id)); - self.message_handler.chan_handler.handle_commitment_signed_batch(their_node_id, channel_id, batch); + log_trace!( + logger, + "Received commitment_signed batch {:?} from {}", + batch, + log_pubkey!(their_node_id) + ); + self.message_handler.chan_handler.handle_commitment_signed_batch( + their_node_id, + channel_id, + batch, + ); return Ok(None); }, None => Ok(None), @@ -1683,13 +2038,17 @@ impl( - &self, - mut peer_lock: MutexGuard, - message: wire::Message<<::Target as wire::CustomMessageReader>::CustomMessage>, - their_node_id: PublicKey, - logger: &WithContext<'a, L> - ) -> Result::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError> - { + &self, mut peer_lock: MutexGuard, + message: wire::Message< + <::Target as wire::CustomMessageReader>::CustomMessage, + >, + their_node_id: PublicKey, logger: &WithContext<'a, L>, + ) -> Result< + Option< + LogicalMessage<<::Target as wire::CustomMessageReader>::CustomMessage>, + >, + MessageHandlingError, + > { peer_lock.received_message_since_timer_tick = true; // Need an Init as first message @@ -1708,56 +2067,101 @@ impl { entry.insert(msg); }, + btree_map::Entry::Vacant(entry) => { + entry.insert(msg); + }, btree_map::Entry::Occupied(_) => { log_debug!(logger, "Peer {} sent batched commitment_signed with duplicate funding_txid {} for channel {}", log_pubkey!(their_node_id), channel_id, &batch.funding_txid); - return Err(PeerHandleError { }.into()); - } + return Err(PeerHandleError {}.into()); + }, } if buffer.len() >= batch_size { - let (channel_id, batch) = peer_lock.commitment_signed_batch.take().expect("batch should have been inserted"); + let (channel_id, batch) = peer_lock + .commitment_signed_batch + .take() + .expect("batch should have been inserted"); return Ok(Some(LogicalMessage::CommitmentSignedBatch(channel_id, batch))); } else { return Ok(None); } } else if peer_lock.commitment_signed_batch.is_some() { log_debug!(logger, "Peer {} sent non-batched commitment_signed for channel {} when expecting batched commitment_signed", log_pubkey!(their_node_id), &msg.channel_id); - return Err(PeerHandleError { }.into()); + return Err(PeerHandleError {}.into()); } else { return Ok(Some(LogicalMessage::FromWire(wire::Message::CommitmentSigned(msg)))); } } else if peer_lock.commitment_signed_batch.is_some() { log_debug!(logger, "Peer {} sent non-commitment_signed message when expecting batched commitment_signed", log_pubkey!(their_node_id)); - return Err(PeerHandleError { }.into()); + return Err(PeerHandleError {}.into()); } if let wire::Message::GossipTimestampFilter(_msg) = message { // When supporting gossip messages, start initial gossip sync only after we receive // a GossipTimestampFilter - if peer_lock.their_features.as_ref().unwrap().supports_gossip_queries() && - !peer_lock.sent_gossip_timestamp_filter { + if peer_lock.their_features.as_ref().unwrap().supports_gossip_queries() + && !peer_lock.sent_gossip_timestamp_filter + { peer_lock.sent_gossip_timestamp_filter = true; #[allow(unused_mut)] @@ -1827,7 +2242,10 @@ impl 1970").as_secs() - 6 * 3600; + let full_sync_threshold = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs() - 6 * 3600; if (_msg.first_timestamp as u64) > full_sync_threshold { should_do_full_sync = false; } @@ -1852,17 +2270,29 @@ impl( - &self, - peer_mutex: &Mutex, - message: wire::Message<<::Target as wire::CustomMessageReader>::CustomMessage>, - their_node_id: PublicKey, - logger: &WithContext<'a, L> - ) -> Result::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError> - { + &self, peer_mutex: &Mutex, + message: wire::Message< + <::Target as wire::CustomMessageReader>::CustomMessage, + >, + their_node_id: PublicKey, logger: &WithContext<'a, L>, + ) -> Result< + Option::Target as wire::CustomMessageReader>::CustomMessage>>, + MessageHandlingError, + > { if is_gossip_msg(message.type_id()) { - log_gossip!(logger, "Received message {:?} from {}", message, log_pubkey!(their_node_id)); + log_gossip!( + logger, + "Received message {:?} from {}", + message, + log_pubkey!(their_node_id) + ); } else { - log_trace!(logger, "Received message {:?} from {}", message, log_pubkey!(their_node_id)); + log_trace!( + logger, + "Received message {:?} from {}", + message, + log_pubkey!(their_node_id) + ); } let mut should_forward = None; @@ -1876,14 +2306,24 @@ impl { - log_debug!(logger, "Got Err message from {}: {}", log_pubkey!(their_node_id), PrintableString(&msg.data)); + log_debug!( + logger, + "Got Err message from {}: {}", + log_pubkey!(their_node_id), + PrintableString(&msg.data) + ); self.message_handler.chan_handler.handle_error(their_node_id, &msg); if msg.channel_id.is_zero() { - return Err(PeerHandleError { }.into()); + return Err(PeerHandleError {}.into()); } }, wire::Message::Warning(msg) => { - log_debug!(logger, "Got warning message from {}: {}", log_pubkey!(their_node_id), PrintableString(&msg.data)); + log_debug!( + logger, + "Got warning message from {}: {}", + log_pubkey!(their_node_id), + PrintableString(&msg.data) + ); }, wire::Message::Ping(msg) => { @@ -1931,21 +2371,21 @@ impl { self.message_handler.chan_handler.handle_stfu(their_node_id, &msg); - } + }, #[cfg(splicing)] // Splicing messages: wire::Message::SpliceInit(msg) => { self.message_handler.chan_handler.handle_splice_init(their_node_id, &msg); - } + }, #[cfg(splicing)] wire::Message::SpliceAck(msg) => { self.message_handler.chan_handler.handle_splice_ack(their_node_id, &msg); - } + }, #[cfg(splicing)] wire::Message::SpliceLocked(msg) => { self.message_handler.chan_handler.handle_splice_locked(their_node_id, &msg); - } + }, // Interactive transaction construction messages: wire::Message::TxAddInput(msg) => { @@ -1974,7 +2414,7 @@ impl { self.message_handler.chan_handler.handle_tx_abort(their_node_id, &msg); - } + }, wire::Message::Shutdown(msg) => { self.message_handler.chan_handler.handle_shutdown(their_node_id, &msg); @@ -1994,7 +2434,9 @@ impl { - self.message_handler.chan_handler.handle_update_fail_malformed_htlc(their_node_id, &msg); + self.message_handler + .chan_handler + .handle_update_fail_malformed_htlc(their_node_id, &msg); }, wire::Message::CommitmentSigned(msg) => { @@ -2012,58 +2454,88 @@ impl { - self.message_handler.chan_handler.handle_announcement_signatures(their_node_id, &msg); + self.message_handler + .chan_handler + .handle_announcement_signatures(their_node_id, &msg); }, wire::Message::ChannelAnnouncement(msg) => { - if self.message_handler.route_handler.handle_channel_announcement(Some(their_node_id), &msg) - .map_err(|e| -> MessageHandlingError { e.into() })? { + if self + .message_handler + .route_handler + .handle_channel_announcement(Some(their_node_id), &msg) + .map_err(|e| -> MessageHandlingError { e.into() })? + { should_forward = Some(wire::Message::ChannelAnnouncement(msg)); } self.update_gossip_backlogged(); }, wire::Message::NodeAnnouncement(msg) => { - if self.message_handler.route_handler.handle_node_announcement(Some(their_node_id), &msg) - .map_err(|e| -> MessageHandlingError { e.into() })? { + if self + .message_handler + .route_handler + .handle_node_announcement(Some(their_node_id), &msg) + .map_err(|e| -> MessageHandlingError { e.into() })? + { should_forward = Some(wire::Message::NodeAnnouncement(msg)); } self.update_gossip_backlogged(); }, wire::Message::ChannelUpdate(msg) => { self.message_handler.chan_handler.handle_channel_update(their_node_id, &msg); - if self.message_handler.route_handler.handle_channel_update(Some(their_node_id), &msg) - .map_err(|e| -> MessageHandlingError { e.into() })? { + if self + .message_handler + .route_handler + .handle_channel_update(Some(their_node_id), &msg) + .map_err(|e| -> MessageHandlingError { e.into() })? + { should_forward = Some(wire::Message::ChannelUpdate(msg)); } self.update_gossip_backlogged(); }, wire::Message::QueryShortChannelIds(msg) => { - self.message_handler.route_handler.handle_query_short_channel_ids(their_node_id, msg)?; + self.message_handler + .route_handler + .handle_query_short_channel_ids(their_node_id, msg)?; }, wire::Message::ReplyShortChannelIdsEnd(msg) => { - self.message_handler.route_handler.handle_reply_short_channel_ids_end(their_node_id, msg)?; + self.message_handler + .route_handler + .handle_reply_short_channel_ids_end(their_node_id, msg)?; }, wire::Message::QueryChannelRange(msg) => { - self.message_handler.route_handler.handle_query_channel_range(their_node_id, msg)?; + self.message_handler + .route_handler + .handle_query_channel_range(their_node_id, msg)?; }, wire::Message::ReplyChannelRange(msg) => { - self.message_handler.route_handler.handle_reply_channel_range(their_node_id, msg)?; + self.message_handler + .route_handler + .handle_reply_channel_range(their_node_id, msg)?; }, // Onion message: wire::Message::OnionMessage(msg) => { - self.message_handler.onion_message_handler.handle_onion_message(their_node_id, &msg); + self.message_handler + .onion_message_handler + .handle_onion_message(their_node_id, &msg); }, // Unknown messages: wire::Message::Unknown(type_id) if message.is_even() => { - log_debug!(logger, "Received unknown even message of type {}, disconnecting peer!", type_id); - return Err(PeerHandleError { }.into()); + log_debug!( + logger, + "Received unknown even message of type {}, disconnecting peer!", + type_id + ); + return Err(PeerHandleError {}.into()); }, wire::Message::Unknown(type_id) => { log_trace!(logger, "Received unknown odd message of type {}, ignoring", type_id); }, wire::Message::Custom(custom) => { - self.message_handler.custom_message_handler.handle_custom_message(custom, their_node_id)?; + self.message_handler + .custom_message_handler + .handle_custom_message(custom, their_node_id)?; }, }; Ok(should_forward) @@ -2087,43 +2559,75 @@ impl { - log_gossip!(self.logger, "Sending message to all peers except {:?} or the announced node: {:?}", except_node, msg); + log_gossip!( + self.logger, + "Sending message to all peers except {:?} or the announced node: {:?}", + except_node, + msg + ); let encoded_msg = encode_msg!(msg); for (_, peer_mutex) in peers.iter() { let mut peer = peer_mutex.lock().unwrap(); - if !peer.handshake_complete() || - !peer.should_forward_node_announcement(msg.contents.node_id) { - continue + if !peer.handshake_complete() + || !peer.should_forward_node_announcement(msg.contents.node_id) + { + continue; } debug_assert!(peer.their_node_id.is_some()); debug_assert!(peer.channel_encryptor.is_ready_for_encryption()); - let logger = WithContext::from(&self.logger, peer.their_node_id.map(|p| p.0), None, None); + let logger = WithContext::from( + &self.logger, + peer.their_node_id.map(|p| p.0), + None, + None, + ); if peer.buffer_full_drop_gossip_broadcast() && !allow_large_buffer { - log_gossip!(logger, "Skipping broadcast message to {:?} as its outbound buffer is full", peer.their_node_id); + log_gossip!( + logger, + "Skipping broadcast message to {:?} as its outbound buffer is full", + peer.their_node_id + ); continue; } if let Some((_, their_node_id)) = peer.their_node_id { @@ -2131,36 +2635,63 @@ impl { - log_gossip!(self.logger, "Sending message to all peers except {:?}: {:?}", except_node, msg); + log_gossip!( + self.logger, + "Sending message to all peers except {:?}: {:?}", + except_node, + msg + ); let encoded_msg = encode_msg!(msg); for (_, peer_mutex) in peers.iter() { let mut peer = peer_mutex.lock().unwrap(); - if !peer.handshake_complete() || - !peer.should_forward_channel_announcement(msg.contents.short_channel_id) { - continue + if !peer.handshake_complete() + || !peer.should_forward_channel_announcement(msg.contents.short_channel_id) + { + continue; } debug_assert!(peer.their_node_id.is_some()); debug_assert!(peer.channel_encryptor.is_ready_for_encryption()); - let logger = WithContext::from(&self.logger, peer.their_node_id.map(|p| p.0), None, None); + let logger = WithContext::from( + &self.logger, + peer.their_node_id.map(|p| p.0), + None, + None, + ); if peer.buffer_full_drop_gossip_broadcast() && !allow_large_buffer { - log_gossip!(logger, "Skipping broadcast message to {:?} as its outbound buffer is full", peer.their_node_id); + log_gossip!( + logger, + "Skipping broadcast message to {:?} as its outbound buffer is full", + peer.their_node_id + ); continue; } - if except_node.is_some() && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node { + if except_node.is_some() + && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node + { continue; } - self.enqueue_encoded_gossip_broadcast(&mut *peer, MessageBuf::from_encoded(&encoded_msg)); + self.enqueue_encoded_gossip_broadcast( + &mut *peer, + MessageBuf::from_encoded(&encoded_msg), + ); } }, - _ => debug_assert!(false, "We shouldn't attempt to forward anything but gossip messages"), + _ => { + debug_assert!(false, "We shouldn't attempt to forward anything but gossip messages") + }, } } @@ -2193,7 +2724,8 @@ impl { - { - if peers_to_disconnect.get($node_id).is_some() { - // If we've "disconnected" this peer, do not send to it. - None - } else { - let descriptor_opt = self.node_id_to_descriptor.lock().unwrap().get($node_id).cloned(); - match descriptor_opt { - Some(descriptor) => match peers.get(&descriptor) { - Some(peer_mutex) => { - let peer_lock = peer_mutex.lock().unwrap(); - if !peer_lock.handshake_complete() { - None - } else { - Some(peer_lock) - } - }, - None => { - debug_assert!(false, "Inconsistent peers set state!"); + ($node_id: expr) => {{ + if peers_to_disconnect.get($node_id).is_some() { + // If we've "disconnected" this peer, do not send to it. + None + } else { + let descriptor_opt = + self.node_id_to_descriptor.lock().unwrap().get($node_id).cloned(); + match descriptor_opt { + Some(descriptor) => match peers.get(&descriptor) { + Some(peer_mutex) => { + let peer_lock = peer_mutex.lock().unwrap(); + if !peer_lock.handshake_complete() { None + } else { + Some(peer_lock) } }, None => { + debug_assert!(false, "Inconsistent peers set state!"); None }, - } + }, + None => None, } } - } + }}; } // Handles a `MessageSendEvent`, using `from_chan_handler` to decide if we should @@ -2238,11 +2767,19 @@ impl { - log_debug!(self.logger, "Handling SendPeerStorage event in peer_handler for {}", log_pubkey!(node_id)); + log_debug!( + self.logger, + "Handling SendPeerStorage event in peer_handler for {}", + log_pubkey!(node_id) + ); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); }, MessageSendEvent::SendPeerStorageRetrieval { ref node_id, ref msg } => { - log_debug!(self.logger, "Handling SendPeerStorageRetrieval event in peer_handler for {}", log_pubkey!(node_id)); + log_debug!( + self.logger, + "Handling SendPeerStorageRetrieval event in peer_handler for {}", + log_pubkey!(node_id) + ); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); }, MessageSendEvent::SendAcceptChannel { ref node_id, ref msg } => { @@ -2290,34 +2827,54 @@ impl { - let logger = WithContext::from(&self.logger, Some(*node_id), Some(msg.channel_id), None); + MessageSendEvent::SendStfu { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + None, + ); log_debug!(logger, "Handling SendStfu event in peer_handler for node {} for channel {}", log_pubkey!(node_id), &msg.channel_id); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); - } - MessageSendEvent::SendSpliceInit { ref node_id, ref msg} => { - let logger = WithContext::from(&self.logger, Some(*node_id), Some(msg.channel_id), None); + }, + MessageSendEvent::SendSpliceInit { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + None, + ); log_debug!(logger, "Handling SendSpliceInit event in peer_handler for node {} for channel {}", log_pubkey!(node_id), &msg.channel_id); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); - } - MessageSendEvent::SendSpliceAck { ref node_id, ref msg} => { - let logger = WithContext::from(&self.logger, Some(*node_id), Some(msg.channel_id), None); + }, + MessageSendEvent::SendSpliceAck { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + None, + ); log_debug!(logger, "Handling SendSpliceAck event in peer_handler for node {} for channel {}", log_pubkey!(node_id), &msg.channel_id); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); - } - MessageSendEvent::SendSpliceLocked { ref node_id, ref msg} => { - let logger = WithContext::from(&self.logger, Some(*node_id), Some(msg.channel_id), None); + }, + MessageSendEvent::SendSpliceLocked { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + None, + ); log_debug!(logger, "Handling SendSpliceLocked event in peer_handler for node {} for channel {}", log_pubkey!(node_id), &msg.channel_id); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); - } + }, MessageSendEvent::SendTxAddInput { ref node_id, ref msg } => { log_debug!(WithContext::from(&self.logger, Some(*node_id), Some(msg.channel_id), None), "Handling SendTxAddInput event in peer_handler for node {} for channel {}", log_pubkey!(node_id), @@ -2378,7 +2935,19 @@ impl { + MessageSendEvent::UpdateHTLCs { + ref node_id, + ref channel_id, + updates: + msgs::CommitmentUpdate { + ref update_add_htlcs, + ref update_fulfill_htlcs, + ref update_fail_htlcs, + ref update_fail_malformed_htlcs, + ref update_fee, + ref commitment_signed, + }, + } => { log_debug!(WithContext::from(&self.logger, Some(*node_id), Some(*channel_id), None), "Handling UpdateHTLCs event in peer_handler for node {} with {} adds, {} fulfills, {} fails, {} commits for channel {}", log_pubkey!(node_id), update_add_htlcs.len(), @@ -2430,27 +2999,60 @@ impl { + MessageSendEvent::SendChannelAnnouncement { + ref node_id, + ref msg, + ref update_msg, + } => { log_debug!(WithContext::from(&self.logger, Some(*node_id), None, None), "Handling SendChannelAnnouncement event in peer_handler for node {} for short channel id {}", log_pubkey!(node_id), msg.contents.short_channel_id); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); - self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, update_msg); + self.enqueue_message( + &mut *get_peer_for_forwarding!(node_id)?, + update_msg, + ); }, MessageSendEvent::BroadcastChannelAnnouncement { msg, update_msg } => { log_debug!(self.logger, "Handling BroadcastChannelAnnouncement event in peer_handler for short channel id {}", msg.contents.short_channel_id); - match self.message_handler.route_handler.handle_channel_announcement(None, &msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => { + match self + .message_handler + .route_handler + .handle_channel_announcement(None, &msg) + { + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => { let forward = wire::Message::ChannelAnnouncement(msg); - self.forward_broadcast_msg(peers, &forward, None, from_chan_handler); + self.forward_broadcast_msg( + peers, + &forward, + None, + from_chan_handler, + ); }, _ => {}, } if let Some(msg) = update_msg { - match self.message_handler.route_handler.handle_channel_update(None, &msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => { + match self + .message_handler + .route_handler + .handle_channel_update(None, &msg) + { + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => { let forward = wire::Message::ChannelUpdate(msg); - self.forward_broadcast_msg(peers, &forward, None, from_chan_handler); + self.forward_broadcast_msg( + peers, + &forward, + None, + from_chan_handler, + ); }, _ => {}, } @@ -2458,20 +3060,46 @@ impl { log_debug!(self.logger, "Handling BroadcastChannelUpdate event in peer_handler for contents {:?}", msg.contents); - match self.message_handler.route_handler.handle_channel_update(None, &msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => { + match self + .message_handler + .route_handler + .handle_channel_update(None, &msg) + { + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => { let forward = wire::Message::ChannelUpdate(msg); - self.forward_broadcast_msg(peers, &forward, None, from_chan_handler); + self.forward_broadcast_msg( + peers, + &forward, + None, + from_chan_handler, + ); }, _ => {}, } }, MessageSendEvent::BroadcastNodeAnnouncement { msg } => { log_debug!(self.logger, "Handling BroadcastNodeAnnouncement event in peer_handler for node {}", msg.contents.node_id); - match self.message_handler.route_handler.handle_node_announcement(None, &msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => { + match self + .message_handler + .route_handler + .handle_node_announcement(None, &msg) + { + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => { let forward = wire::Message::NodeAnnouncement(msg); - self.forward_broadcast_msg(peers, &forward, None, from_chan_handler); + self.forward_broadcast_msg( + peers, + &forward, + None, + from_chan_handler, + ); }, _ => {}, } @@ -2495,7 +3123,9 @@ impl::Target as wire::CustomMessageReader>::CustomMessage>::Error(msg)); + let msg = msg.map(|msg| { + wire::Message::<<::Target as wire::CustomMessageReader>::CustomMessage>::Error(msg) + }); peers_to_disconnect.insert(node_id, msg); }, msgs::ErrorAction::DisconnectPeerWithWarning { msg } => { @@ -2504,26 +3134,45 @@ impl { - log_given_level!(logger, level, "Received a HandleError event to be ignored for node {}", log_pubkey!(node_id)); + log_given_level!( + logger, + level, + "Received a HandleError event to be ignored for node {}", + log_pubkey!(node_id) + ); }, msgs::ErrorAction::IgnoreDuplicateGossip => {}, msgs::ErrorAction::IgnoreError => { - log_debug!(logger, "Received a HandleError event to be ignored for node {}", log_pubkey!(node_id)); - }, + log_debug!( + logger, + "Received a HandleError event to be ignored for node {}", + log_pubkey!(node_id) + ); + }, msgs::ErrorAction::SendErrorMessage { ref msg } => { log_trace!(logger, "Handling SendErrorMessage HandleError event in peer_handler for node {} with message {}", log_pubkey!(node_id), msg.data); - self.enqueue_message(&mut *get_peer_for_forwarding!(&node_id)?, msg); + self.enqueue_message( + &mut *get_peer_for_forwarding!(&node_id)?, + msg, + ); }, - msgs::ErrorAction::SendWarningMessage { ref msg, ref log_level } => { + msgs::ErrorAction::SendWarningMessage { + ref msg, + ref log_level, + } => { log_given_level!(logger, *log_level, "Handling SendWarningMessage HandleError event in peer_handler for node {} with message {}", log_pubkey!(node_id), msg.data); - self.enqueue_message(&mut *get_peer_for_forwarding!(&node_id)?, msg); + self.enqueue_message( + &mut *get_peer_for_forwarding!(&node_id)?, + msg, + ); }, } }, @@ -2539,7 +3188,7 @@ impl { log_gossip!(WithContext::from(&self.logger, Some(*node_id), None, None), "Handling SendReplyChannelRange event in peer_handler for node {} with num_scids={} first_blocknum={} number_of_blocks={}, sync_complete={}", log_pubkey!(node_id), @@ -2548,42 +3197,62 @@ impl { log_gossip!(WithContext::from(&self.logger, Some(*node_id), None, None), "Handling SendGossipTimestampFilter event in peer_handler for node {} with first_timestamp={}, timestamp_range={}", log_pubkey!(node_id), msg.first_timestamp, msg.timestamp_range); self.enqueue_message(&mut *get_peer_for_forwarding!(node_id)?, msg); - } + }, } Some(()) }; - let chan_events = self.message_handler.chan_handler.get_and_clear_pending_msg_events(); + let chan_events = + self.message_handler.chan_handler.get_and_clear_pending_msg_events(); for event in chan_events { handle_event(event, true); } - let route_events = self.message_handler.route_handler.get_and_clear_pending_msg_events(); + let route_events = + self.message_handler.route_handler.get_and_clear_pending_msg_events(); for event in route_events { handle_event(event, false); } - let onion_msg_events = self.message_handler.onion_message_handler.get_and_clear_pending_msg_events(); + let onion_msg_events = + self.message_handler.onion_message_handler.get_and_clear_pending_msg_events(); for event in onion_msg_events { handle_event(event, false); } - for (node_id, msg) in self.message_handler.custom_message_handler.get_and_clear_pending_msg() { - if peers_to_disconnect.get(&node_id).is_some() { continue; } - self.enqueue_message(&mut *if let Some(peer) = get_peer_for_forwarding!(&node_id) { peer } else { continue; }, &msg); + for (node_id, msg) in + self.message_handler.custom_message_handler.get_and_clear_pending_msg() + { + if peers_to_disconnect.get(&node_id).is_some() { + continue; + } + self.enqueue_message( + &mut *if let Some(peer) = get_peer_for_forwarding!(&node_id) { + peer + } else { + continue; + }, + &msg, + ); } for (descriptor, peer_mutex) in peers.iter() { let mut peer = peer_mutex.lock().unwrap(); - if flush_read_disabled { peer.received_channel_announce_since_backlogged = false; } - self.do_attempt_write_data(&mut (*descriptor).clone(), &mut *peer, flush_read_disabled); + if flush_read_disabled { + peer.received_channel_announce_since_backlogged = false; + } + self.do_attempt_write_data( + &mut (*descriptor).clone(), + &mut *peer, + flush_read_disabled, + ); } } if !peers_to_disconnect.is_empty() { @@ -2595,7 +3264,8 @@ impl 0 && !peer.received_message_since_timer_tick) - || peer.awaiting_pong_timer_tick_intervals as u64 > - MAX_BUFFER_DRAIN_TICK_INTERVALS_PER_PEER as u64 * peers_lock.len() as u64 + if (peer.awaiting_pong_timer_tick_intervals > 0 + && !peer.received_message_since_timer_tick) + || peer.awaiting_pong_timer_tick_intervals as u64 + > MAX_BUFFER_DRAIN_TICK_INTERVALS_PER_PEER as u64 + * peers_lock.len() as u64 { descriptors_needing_disconnect.push(descriptor.clone()); break; @@ -2773,14 +3470,15 @@ impl) { + pub fn broadcast_node_announcement( + &self, rgb: [u8; 3], alias: [u8; 32], mut addresses: Vec, + ) { if addresses.len() > 100 { panic!("More than half the message size was taken up by public addresses!"); } @@ -2849,9 +3550,10 @@ impl sig, Err(_) => { log_error!(self.logger, "Failed to generate signature for node_announcement"); @@ -2859,27 +3561,32 @@ impl bool { match type_id { - msgs::ChannelAnnouncement::TYPE | - msgs::ChannelUpdate::TYPE | - msgs::NodeAnnouncement::TYPE | - msgs::QueryChannelRange::TYPE | - msgs::ReplyChannelRange::TYPE | - msgs::QueryShortChannelIds::TYPE | - msgs::ReplyShortChannelIdsEnd::TYPE => true, - _ => false + msgs::ChannelAnnouncement::TYPE + | msgs::ChannelUpdate::TYPE + | msgs::NodeAnnouncement::TYPE + | msgs::QueryChannelRange::TYPE + | msgs::ReplyChannelRange::TYPE + | msgs::QueryShortChannelIds::TYPE + | msgs::ReplyShortChannelIdsEnd::TYPE => true, + _ => false, } } @@ -2887,18 +3594,18 @@ fn is_gossip_msg(type_id: u16) -> bool { mod tests { use super::*; - use crate::sign::{NodeSigner, Recipient}; use crate::io; - use crate::ln::types::ChannelId; - use crate::types::features::{InitFeatures, NodeFeatures}; + use crate::ln::msgs::{Init, LightningError, SocketAddress}; use crate::ln::peer_channel_encryptor::PeerChannelEncryptor; + use crate::ln::types::ChannelId; use crate::ln::{msgs, wire}; - use crate::ln::msgs::{Init, LightningError, SocketAddress}; + use crate::sign::{NodeSigner, Recipient}; + use crate::types::features::{InitFeatures, NodeFeatures}; use crate::util::test_utils; - use bitcoin::Network; use bitcoin::constants::ChainHash; - use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1}; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; + use bitcoin::Network; use crate::sync::{Arc, Mutex}; use core::convert::Infallible; @@ -2919,7 +3626,7 @@ mod tests { self.fd == other.fd } } - impl Eq for FileDescriptor { } + impl Eq for FileDescriptor {} impl core::hash::Hash for FileDescriptor { fn hash(&self, hasher: &mut H) { self.fd.hash(hasher) @@ -2936,7 +3643,9 @@ mod tests { } } - fn disconnect_socket(&mut self) { self.disconnect.store(true, Ordering::Release); } + fn disconnect_socket(&mut self) { + self.disconnect.store(true, Ordering::Release); + } } impl FileDescriptor { @@ -2965,16 +3674,15 @@ mod tests { impl TestCustomMessageHandler { fn new(features: InitFeatures) -> Self { - Self { - features, - conn_tracker: test_utils::ConnectionTracker::new(), - } + Self { features, conn_tracker: test_utils::ConnectionTracker::new() } } } impl wire::CustomMessageReader for TestCustomMessageHandler { type CustomMessage = Infallible; - fn read(&self, _: u16, _: &mut R) -> Result, msgs::DecodeError> { + fn read( + &self, _: u16, _: &mut R, + ) -> Result, msgs::DecodeError> { Ok(None) } } @@ -2984,17 +3692,23 @@ mod tests { unreachable!(); } - fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { Vec::new() } + fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { + Vec::new() + } fn peer_disconnected(&self, their_node_id: PublicKey) { self.conn_tracker.peer_disconnected(their_node_id); } - 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<(), ()> { self.conn_tracker.peer_connected(their_node_id) } - fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } + fn provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } fn provided_init_features(&self, _: PublicKey) -> InitFeatures { self.features.clone() @@ -3010,15 +3724,15 @@ mod tests { feature_bits[32] = 0b00000001; InitFeatures::from_le_bytes(feature_bits) }; - cfgs.push( - PeerManagerCfg{ - chan_handler: test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet)), - logger: test_utils::TestLogger::with_id(i.to_string()), - routing_handler: test_utils::TestRoutingMessageHandler::new(), - custom_handler: TestCustomMessageHandler::new(features), - node_signer: test_utils::TestNodeSigner::new(node_secret), - } - ); + cfgs.push(PeerManagerCfg { + chan_handler: test_utils::TestChannelMessageHandler::new( + ChainHash::using_genesis_block(Network::Testnet), + ), + logger: test_utils::TestLogger::with_id(i.to_string()), + routing_handler: test_utils::TestRoutingMessageHandler::new(), + custom_handler: TestCustomMessageHandler::new(features), + node_signer: test_utils::TestNodeSigner::new(node_secret), + }); } cfgs @@ -3033,15 +3747,15 @@ mod tests { feature_bits[33 + i] = 0b00000001; InitFeatures::from_le_bytes(feature_bits) }; - cfgs.push( - PeerManagerCfg{ - chan_handler: test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet)), - logger: test_utils::TestLogger::new(), - routing_handler: test_utils::TestRoutingMessageHandler::new(), - custom_handler: TestCustomMessageHandler::new(features), - node_signer: test_utils::TestNodeSigner::new(node_secret), - } - ); + cfgs.push(PeerManagerCfg { + chan_handler: test_utils::TestChannelMessageHandler::new( + ChainHash::using_genesis_block(Network::Testnet), + ), + logger: test_utils::TestLogger::new(), + routing_handler: test_utils::TestRoutingMessageHandler::new(), + custom_handler: TestCustomMessageHandler::new(features), + node_signer: test_utils::TestNodeSigner::new(node_secret), + }); } cfgs @@ -3053,38 +3767,80 @@ mod tests { let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap(); let features = InitFeatures::from_le_bytes(vec![0u8; 33]); let network = ChainHash::from(&[i as u8; 32]); - cfgs.push( - PeerManagerCfg{ - chan_handler: test_utils::TestChannelMessageHandler::new(network), - logger: test_utils::TestLogger::new(), - routing_handler: test_utils::TestRoutingMessageHandler::new(), - custom_handler: TestCustomMessageHandler::new(features), - node_signer: test_utils::TestNodeSigner::new(node_secret), - } - ); + cfgs.push(PeerManagerCfg { + chan_handler: test_utils::TestChannelMessageHandler::new(network), + logger: test_utils::TestLogger::new(), + routing_handler: test_utils::TestRoutingMessageHandler::new(), + custom_handler: TestCustomMessageHandler::new(features), + node_signer: test_utils::TestNodeSigner::new(node_secret), + }); } cfgs } - fn create_network<'a>(peer_count: usize, cfgs: &'a Vec) -> Vec> { + fn create_network<'a>( + peer_count: usize, cfgs: &'a Vec, + ) -> Vec< + PeerManager< + FileDescriptor, + &'a test_utils::TestChannelMessageHandler, + &'a test_utils::TestRoutingMessageHandler, + IgnoringMessageHandler, + &'a test_utils::TestLogger, + &'a TestCustomMessageHandler, + &'a test_utils::TestNodeSigner, + >, + > { let mut peers = Vec::new(); for i in 0..peer_count { let ephemeral_bytes = [i as u8; 32]; let msg_handler = MessageHandler { - chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler, - onion_message_handler: IgnoringMessageHandler {}, custom_message_handler: &cfgs[i].custom_handler + chan_handler: &cfgs[i].chan_handler, + route_handler: &cfgs[i].routing_handler, + onion_message_handler: IgnoringMessageHandler {}, + custom_message_handler: &cfgs[i].custom_handler, }; - let peer = PeerManager::new(msg_handler, 0, &ephemeral_bytes, &cfgs[i].logger, &cfgs[i].node_signer); + let peer = PeerManager::new( + msg_handler, + 0, + &ephemeral_bytes, + &cfgs[i].logger, + &cfgs[i].node_signer, + ); peers.push(peer); } peers } - fn try_establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor, Result, Result) { - let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; - let addr_b = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1001}; + fn try_establish_connection<'a>( + peer_a: &PeerManager< + FileDescriptor, + &'a test_utils::TestChannelMessageHandler, + &'a test_utils::TestRoutingMessageHandler, + IgnoringMessageHandler, + &'a test_utils::TestLogger, + &'a TestCustomMessageHandler, + &'a test_utils::TestNodeSigner, + >, + peer_b: &PeerManager< + FileDescriptor, + &'a test_utils::TestChannelMessageHandler, + &'a test_utils::TestRoutingMessageHandler, + IgnoringMessageHandler, + &'a test_utils::TestLogger, + &'a TestCustomMessageHandler, + &'a test_utils::TestNodeSigner, + >, + ) -> ( + FileDescriptor, + FileDescriptor, + Result, + Result, + ) { + let addr_a = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1000 }; + let addr_b = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1001 }; static FD_COUNTER: AtomicUsize = AtomicUsize::new(0); let fd = FD_COUNTER.fetch_add(1, Ordering::Relaxed) as u16; @@ -3093,7 +3849,8 @@ mod tests { let mut fd_a = FileDescriptor::new(fd); let mut fd_b = FileDescriptor::new(fd); - let initial_data = peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap(); + let initial_data = + peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap(); peer_a.new_inbound_connection(fd_a.clone(), Some(addr_b.clone())).unwrap(); assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false); peer_a.process_events(); @@ -3112,10 +3869,28 @@ mod tests { (fd_a, fd_b, a_refused, b_refused) } - - fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { - let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; - let addr_b = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1001}; + fn establish_connection<'a>( + peer_a: &PeerManager< + FileDescriptor, + &'a test_utils::TestChannelMessageHandler, + &'a test_utils::TestRoutingMessageHandler, + IgnoringMessageHandler, + &'a test_utils::TestLogger, + &'a TestCustomMessageHandler, + &'a test_utils::TestNodeSigner, + >, + peer_b: &PeerManager< + FileDescriptor, + &'a test_utils::TestChannelMessageHandler, + &'a test_utils::TestRoutingMessageHandler, + IgnoringMessageHandler, + &'a test_utils::TestLogger, + &'a TestCustomMessageHandler, + &'a test_utils::TestNodeSigner, + >, + ) -> (FileDescriptor, FileDescriptor) { + let addr_a = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1000 }; + let addr_b = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1001 }; let id_a = peer_a.node_signer.get_node_id(Recipient::Node).unwrap(); let id_b = peer_b.node_signer.get_node_id(Recipient::Node).unwrap(); @@ -3148,62 +3923,86 @@ mod tests { let peers = Arc::new(create_network(2, unsafe { &*(&*cfgs as *const _) as &'static _ })); let start_time = std::time::Instant::now(); - macro_rules! spawn_thread { ($id: expr) => { { - let peers = Arc::clone(&peers); - let cfgs = Arc::clone(&cfgs); - std::thread::spawn(move || { - let mut ctr = 0; - while start_time.elapsed() < std::time::Duration::from_secs(1) { - let id_a = peers[0].node_signer.get_node_id(Recipient::Node).unwrap(); - let mut fd_a = FileDescriptor::new($id + ctr * 3); - let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; - let mut fd_b = FileDescriptor::new($id + ctr * 3); - let addr_b = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1001}; - let initial_data = peers[1].new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap(); - peers[0].new_inbound_connection(fd_a.clone(), Some(addr_b.clone())).unwrap(); - if peers[0].read_event(&mut fd_a, &initial_data).is_err() { break; } - + macro_rules! spawn_thread { + ($id: expr) => {{ + let peers = Arc::clone(&peers); + let cfgs = Arc::clone(&cfgs); + std::thread::spawn(move || { + let mut ctr = 0; while start_time.elapsed() < std::time::Duration::from_secs(1) { - peers[0].process_events(); - if fd_a.disconnect.load(Ordering::Acquire) { break; } - let a_data = fd_a.outbound_data.lock().unwrap().split_off(0); - if peers[1].read_event(&mut fd_b, &a_data).is_err() { break; } - - peers[1].process_events(); - if fd_b.disconnect.load(Ordering::Acquire) { break; } - let b_data = fd_b.outbound_data.lock().unwrap().split_off(0); - if peers[0].read_event(&mut fd_a, &b_data).is_err() { break; } - - cfgs[0].chan_handler.pending_events.lock().unwrap() - .push(MessageSendEvent::SendShutdown { - node_id: peers[1].node_signer.get_node_id(Recipient::Node).unwrap(), - msg: msgs::Shutdown { - channel_id: ChannelId::new_zero(), - scriptpubkey: bitcoin::ScriptBuf::new(), + let id_a = peers[0].node_signer.get_node_id(Recipient::Node).unwrap(); + let mut fd_a = FileDescriptor::new($id + ctr * 3); + let addr_a = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1000 }; + let mut fd_b = FileDescriptor::new($id + ctr * 3); + let addr_b = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1001 }; + let initial_data = peers[1] + .new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())) + .unwrap(); + peers[0] + .new_inbound_connection(fd_a.clone(), Some(addr_b.clone())) + .unwrap(); + if peers[0].read_event(&mut fd_a, &initial_data).is_err() { + break; + } + + while start_time.elapsed() < std::time::Duration::from_secs(1) { + peers[0].process_events(); + if fd_a.disconnect.load(Ordering::Acquire) { + break; + } + let a_data = fd_a.outbound_data.lock().unwrap().split_off(0); + if peers[1].read_event(&mut fd_b, &a_data).is_err() { + break; + } + + peers[1].process_events(); + if fd_b.disconnect.load(Ordering::Acquire) { + break; + } + let b_data = fd_b.outbound_data.lock().unwrap().split_off(0); + if peers[0].read_event(&mut fd_a, &b_data).is_err() { + break; + } + + cfgs[0].chan_handler.pending_events.lock().unwrap().push( + MessageSendEvent::SendShutdown { + node_id: peers[1] + .node_signer + .get_node_id(Recipient::Node) + .unwrap(), + msg: msgs::Shutdown { + channel_id: ChannelId::new_zero(), + scriptpubkey: bitcoin::ScriptBuf::new(), + }, }, - }); - cfgs[1].chan_handler.pending_events.lock().unwrap() - .push(MessageSendEvent::SendShutdown { - node_id: peers[0].node_signer.get_node_id(Recipient::Node).unwrap(), - msg: msgs::Shutdown { - channel_id: ChannelId::new_zero(), - scriptpubkey: bitcoin::ScriptBuf::new(), + ); + cfgs[1].chan_handler.pending_events.lock().unwrap().push( + MessageSendEvent::SendShutdown { + node_id: peers[0] + .node_signer + .get_node_id(Recipient::Node) + .unwrap(), + msg: msgs::Shutdown { + channel_id: ChannelId::new_zero(), + scriptpubkey: bitcoin::ScriptBuf::new(), + }, }, - }); + ); - if ctr % 2 == 0 { - peers[0].timer_tick_occurred(); - peers[1].timer_tick_occurred(); + if ctr % 2 == 0 { + peers[0].timer_tick_occurred(); + peers[1].timer_tick_occurred(); + } } - } - peers[0].socket_disconnected(&fd_a); - peers[1].socket_disconnected(&fd_b); - ctr += 1; - std::thread::sleep(std::time::Duration::from_micros(1)); - } - }) - } } } + peers[0].socket_disconnected(&fd_a); + peers[1].socket_disconnected(&fd_b); + ctr += 1; + std::thread::sleep(std::time::Duration::from_micros(1)); + } + }) + }}; + } let thrd_a = spawn_thread!(1); let thrd_b = spawn_thread!(2); @@ -3222,10 +4021,11 @@ mod tests { for (peer_a, peer_b) in peer_pairs.iter() { let id_a = peer_a.node_signer.get_node_id(Recipient::Node).unwrap(); let mut fd_a = FileDescriptor::new(1); - let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; + let addr_a = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1000 }; let mut fd_b = FileDescriptor::new(1); - let addr_b = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1001}; - let initial_data = peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap(); + let addr_b = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1001 }; + let initial_data = + peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap(); peer_a.new_inbound_connection(fd_a.clone(), Some(addr_b.clone())).unwrap(); assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false); peer_a.process_events(); @@ -3252,10 +4052,11 @@ mod tests { for (peer_a, peer_b) in peer_pairs.iter() { let id_a = peer_a.node_signer.get_node_id(Recipient::Node).unwrap(); let mut fd_a = FileDescriptor::new(1); - let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; + let addr_a = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1000 }; let mut fd_b = FileDescriptor::new(1); - let addr_b = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1001}; - let initial_data = peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap(); + let addr_b = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1001 }; + let initial_data = + peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap(); peer_a.new_inbound_connection(fd_a.clone(), Some(addr_b.clone())).unwrap(); assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false); peer_a.process_events(); @@ -3295,18 +4096,27 @@ mod tests { // Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and // push a message from one peer to another. let cfgs = create_peermgr_cfgs(2); - let a_chan_handler = test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet)); - let b_chan_handler = test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet)); + let a_chan_handler = test_utils::TestChannelMessageHandler::new( + ChainHash::using_genesis_block(Network::Testnet), + ); + let b_chan_handler = test_utils::TestChannelMessageHandler::new( + ChainHash::using_genesis_block(Network::Testnet), + ); let mut peers = create_network(2, &cfgs); let (fd_a, mut fd_b) = establish_connection(&peers[0], &peers[1]); assert_eq!(peers[0].peers.read().unwrap().len(), 1); let their_id = peers[1].node_signer.get_node_id(Recipient::Node).unwrap(); - let msg = msgs::Shutdown { channel_id: ChannelId::from_bytes([42; 32]), scriptpubkey: bitcoin::ScriptBuf::new() }; - a_chan_handler.pending_events.lock().unwrap().push(MessageSendEvent::SendShutdown { - node_id: their_id, msg: msg.clone() - }); + let msg = msgs::Shutdown { + channel_id: ChannelId::from_bytes([42; 32]), + scriptpubkey: bitcoin::ScriptBuf::new(), + }; + a_chan_handler + .pending_events + .lock() + .unwrap() + .push(MessageSendEvent::SendShutdown { node_id: their_id, msg: msg.clone() }); peers[0].message_handler.chan_handler = &a_chan_handler; b_chan_handler.expect_receive_msg(wire::Message::Shutdown(msg)); @@ -3328,11 +4138,12 @@ mod tests { let peers = create_network(2, &cfgs); let mut fd_dup = FileDescriptor::new(3); - let addr_dup = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1003}; + let addr_dup = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1003 }; let id_a = cfgs[0].node_signer.get_node_id(Recipient::Node).unwrap(); peers[0].new_inbound_connection(fd_dup.clone(), Some(addr_dup.clone())).unwrap(); - let mut dup_encryptor = PeerChannelEncryptor::new_outbound(id_a, SecretKey::from_slice(&[42; 32]).unwrap()); + let mut dup_encryptor = + PeerChannelEncryptor::new_outbound(id_a, SecretKey::from_slice(&[42; 32]).unwrap()); let initial_data = dup_encryptor.get_act_one(&peers[1].secp_ctx); assert_eq!(peers[0].read_event(&mut fd_dup, &initial_data).unwrap(), false); peers[0].process_events(); @@ -3388,14 +4199,29 @@ mod tests { match handler & !1 { 0 => { - peers[handler & 1].message_handler.chan_handler.conn_tracker.fail_connections.store(true, Ordering::Release); - } + peers[handler & 1] + .message_handler + .chan_handler + .conn_tracker + .fail_connections + .store(true, Ordering::Release); + }, 2 => { - peers[handler & 1].message_handler.route_handler.conn_tracker.fail_connections.store(true, Ordering::Release); - } + peers[handler & 1] + .message_handler + .route_handler + .conn_tracker + .fail_connections + .store(true, Ordering::Release); + }, 4 => { - peers[handler & 1].message_handler.custom_message_handler.conn_tracker.fail_connections.store(true, Ordering::Release); - } + peers[handler & 1] + .message_handler + .custom_message_handler + .conn_tracker + .fail_connections + .store(true, Ordering::Release); + }, _ => panic!(), } let (_sd1, _sd2, a_refused, b_refused) = try_establish_connection(&peers[0], &peers[1]); @@ -3407,13 +4233,51 @@ mod tests { assert!(peers[1].list_peers().is_empty()); } // At least one message handler should have seen the connection. - assert!(peers[handler & 1].message_handler.chan_handler.conn_tracker.had_peers.load(Ordering::Acquire) || - peers[handler & 1].message_handler.route_handler.conn_tracker.had_peers.load(Ordering::Acquire) || - peers[handler & 1].message_handler.custom_message_handler.conn_tracker.had_peers.load(Ordering::Acquire)); + assert!( + peers[handler & 1] + .message_handler + .chan_handler + .conn_tracker + .had_peers + .load(Ordering::Acquire) + || peers[handler & 1] + .message_handler + .route_handler + .conn_tracker + .had_peers + .load(Ordering::Acquire) + || peers[handler & 1] + .message_handler + .custom_message_handler + .conn_tracker + .had_peers + .load(Ordering::Acquire) + ); // And both message handlers doing tracking should see the disconnection - assert!(peers[handler & 1].message_handler.chan_handler.conn_tracker.connected_peers.lock().unwrap().is_empty()); - assert!(peers[handler & 1].message_handler.route_handler.conn_tracker.connected_peers.lock().unwrap().is_empty()); - assert!(peers[handler & 1].message_handler.custom_message_handler.conn_tracker.connected_peers.lock().unwrap().is_empty()); + assert!(peers[handler & 1] + .message_handler + .chan_handler + .conn_tracker + .connected_peers + .lock() + .unwrap() + .is_empty()); + assert!(peers[handler & 1] + .message_handler + .route_handler + .conn_tracker + .connected_peers + .lock() + .unwrap() + .is_empty()); + assert!(peers[handler & 1] + .message_handler + .custom_message_handler + .conn_tracker + .connected_peers + .lock() + .unwrap() + .is_empty()); } #[test] @@ -3443,7 +4307,7 @@ mod tests { // Make each peer to read the messages that the other peer just wrote to them. Note that // due to the max-message-before-ping limits this may take a few iterations to complete. - for _ in 0..150/super::BUFFER_DRAIN_MSGS_PER_TICK + 1 { + for _ in 0..150 / super::BUFFER_DRAIN_MSGS_PER_TICK + 1 { peers[1].process_events(); let a_read_data = fd_b.outbound_data.lock().unwrap().split_off(0); assert!(!a_read_data.is_empty()); @@ -3456,7 +4320,11 @@ mod tests { peers[1].read_event(&mut fd_b, &b_read_data).unwrap(); peers[0].process_events(); - assert_eq!(fd_a.outbound_data.lock().unwrap().len(), 0, "Until A receives data, it shouldn't send more messages"); + assert_eq!( + fd_a.outbound_data.lock().unwrap().len(), + 0, + "Until A receives data, it shouldn't send more messages" + ); } // Check that each peer has received the expected number of channel updates and channel @@ -3508,20 +4376,34 @@ mod tests { // two of the noise handshake along with our init message but before we receive their init // message. let logger = test_utils::TestLogger::new(); - let node_signer_a = test_utils::TestNodeSigner::new(SecretKey::from_slice(&[42; 32]).unwrap()); - let node_signer_b = test_utils::TestNodeSigner::new(SecretKey::from_slice(&[43; 32]).unwrap()); - let peer_a = PeerManager::new(MessageHandler { - chan_handler: ErroringMessageHandler::new(), - route_handler: IgnoringMessageHandler {}, - onion_message_handler: IgnoringMessageHandler {}, - custom_message_handler: IgnoringMessageHandler {}, - }, 0, &[0; 32], &logger, &node_signer_a); - let peer_b = PeerManager::new(MessageHandler { - chan_handler: ErroringMessageHandler::new(), - route_handler: IgnoringMessageHandler {}, - onion_message_handler: IgnoringMessageHandler {}, - custom_message_handler: IgnoringMessageHandler {}, - }, 0, &[1; 32], &logger, &node_signer_b); + let node_signer_a = + test_utils::TestNodeSigner::new(SecretKey::from_slice(&[42; 32]).unwrap()); + let node_signer_b = + test_utils::TestNodeSigner::new(SecretKey::from_slice(&[43; 32]).unwrap()); + let peer_a = PeerManager::new( + MessageHandler { + chan_handler: ErroringMessageHandler::new(), + route_handler: IgnoringMessageHandler {}, + onion_message_handler: IgnoringMessageHandler {}, + custom_message_handler: IgnoringMessageHandler {}, + }, + 0, + &[0; 32], + &logger, + &node_signer_a, + ); + let peer_b = PeerManager::new( + MessageHandler { + chan_handler: ErroringMessageHandler::new(), + route_handler: IgnoringMessageHandler {}, + onion_message_handler: IgnoringMessageHandler {}, + custom_message_handler: IgnoringMessageHandler {}, + }, + 0, + &[1; 32], + &logger, + &node_signer_b, + ); let a_id = node_signer_a.get_node_id(Recipient::Node).unwrap(); let mut fd_a = FileDescriptor::new(1); @@ -3542,18 +4424,50 @@ mod tests { peer_b.timer_tick_occurred(); let act_three_with_init_b = fd_b.outbound_data.lock().unwrap().split_off(0); - assert!(!peer_a.peers.read().unwrap().get(&fd_a).unwrap().lock().unwrap().handshake_complete()); + assert!(!peer_a + .peers + .read() + .unwrap() + .get(&fd_a) + .unwrap() + .lock() + .unwrap() + .handshake_complete()); assert_eq!(peer_a.read_event(&mut fd_a, &act_three_with_init_b).unwrap(), false); peer_a.process_events(); - assert!(peer_a.peers.read().unwrap().get(&fd_a).unwrap().lock().unwrap().handshake_complete()); + assert!(peer_a + .peers + .read() + .unwrap() + .get(&fd_a) + .unwrap() + .lock() + .unwrap() + .handshake_complete()); let init_a = fd_a.outbound_data.lock().unwrap().split_off(0); assert!(!init_a.is_empty()); - assert!(!peer_b.peers.read().unwrap().get(&fd_b).unwrap().lock().unwrap().handshake_complete()); + assert!(!peer_b + .peers + .read() + .unwrap() + .get(&fd_b) + .unwrap() + .lock() + .unwrap() + .handshake_complete()); assert_eq!(peer_b.read_event(&mut fd_b, &init_a).unwrap(), false); peer_b.process_events(); - assert!(peer_b.peers.read().unwrap().get(&fd_b).unwrap().lock().unwrap().handshake_complete()); + assert!(peer_b + .peers + .read() + .unwrap() + .get(&fd_b) + .unwrap() + .lock() + .unwrap() + .handshake_complete()); // Make sure we're still connected. assert_eq!(peer_b.peers.read().unwrap().len(), 1); @@ -3568,10 +4482,13 @@ mod tests { { let peers = peer_a.peers.read().unwrap(); let mut peer_b = peers.get(&fd_a).unwrap().lock().unwrap(); - peer_a.enqueue_message(&mut peer_b, &msgs::WarningMessage { - channel_id: ChannelId([0; 32]), - data: "no disconnect plz".to_string(), - }); + peer_a.enqueue_message( + &mut peer_b, + &msgs::WarningMessage { + channel_id: ChannelId([0; 32]), + data: "no disconnect plz".to_string(), + }, + ); } peer_a.process_events(); let msg = fd_a.outbound_data.lock().unwrap().split_off(0); @@ -3605,24 +4522,26 @@ mod tests { let peers = create_network(2, &cfgs); let (mut fd_a, mut fd_b) = establish_connection(&peers[0], &peers[1]); - macro_rules! drain_queues { () => { - loop { - peers[0].process_events(); - peers[1].process_events(); + macro_rules! drain_queues { + () => { + loop { + peers[0].process_events(); + peers[1].process_events(); - let msg = fd_a.outbound_data.lock().unwrap().split_off(0); - if !msg.is_empty() { - assert_eq!(peers[1].read_event(&mut fd_b, &msg).unwrap(), false); - continue; - } - let msg = fd_b.outbound_data.lock().unwrap().split_off(0); - if !msg.is_empty() { - assert_eq!(peers[0].read_event(&mut fd_a, &msg).unwrap(), false); - continue; + let msg = fd_a.outbound_data.lock().unwrap().split_off(0); + if !msg.is_empty() { + assert_eq!(peers[1].read_event(&mut fd_b, &msg).unwrap(), false); + continue; + } + let msg = fd_b.outbound_data.lock().unwrap().split_off(0); + if !msg.is_empty() { + assert_eq!(peers[0].read_event(&mut fd_a, &msg).unwrap(), false); + continue; + } + break; } - break; - } - } } + }; + } // First, make sure all pending messages have been processed and queues drained. drain_queues!(); @@ -3630,10 +4549,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let key = SecretKey::from_slice(&[1; 32]).unwrap(); let msg = channel_announcement(&key, &key, ChannelFeatures::empty(), 42, &secp_ctx); - let msg_ev = MessageSendEvent::BroadcastChannelAnnouncement { - msg, - update_msg: None, - }; + let msg_ev = MessageSendEvent::BroadcastChannelAnnouncement { msg, update_msg: None }; fd_a.hang_writes.store(true, Ordering::Relaxed); @@ -3644,15 +4560,37 @@ mod tests { peers[0].process_events(); } - assert_eq!(peers[0].peers.read().unwrap().get(&fd_a).unwrap().lock().unwrap().gossip_broadcast_buffer.len(), - OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP); + assert_eq!( + peers[0] + .peers + .read() + .unwrap() + .get(&fd_a) + .unwrap() + .lock() + .unwrap() + .gossip_broadcast_buffer + .len(), + OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP + ); // Check that if a broadcast message comes in from the channel handler (i.e. it is an // announcement for our own channel), it gets queued anyway. cfgs[0].chan_handler.pending_events.lock().unwrap().push(msg_ev); peers[0].process_events(); - assert_eq!(peers[0].peers.read().unwrap().get(&fd_a).unwrap().lock().unwrap().gossip_broadcast_buffer.len(), - OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP + 1); + assert_eq!( + peers[0] + .peers + .read() + .unwrap() + .get(&fd_a) + .unwrap() + .lock() + .unwrap() + .gossip_broadcast_buffer + .len(), + OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP + 1 + ); // Finally, deliver all the messages and make sure we got the right count. Note that there // was an extra message that had already moved from the broadcast queue to the encrypted @@ -3662,101 +4600,130 @@ mod tests { peers[0].write_buffer_space_avail(&mut fd_a).unwrap(); drain_queues!(); - assert!(peers[0].peers.read().unwrap().get(&fd_a).unwrap().lock().unwrap().gossip_broadcast_buffer.is_empty()); - assert_eq!(cfgs[1].routing_handler.chan_anns_recvd.load(Ordering::Relaxed), - OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP + 2); + assert!(peers[0] + .peers + .read() + .unwrap() + .get(&fd_a) + .unwrap() + .lock() + .unwrap() + .gossip_broadcast_buffer + .is_empty()); + assert_eq!( + cfgs[1].routing_handler.chan_anns_recvd.load(Ordering::Relaxed), + OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP + 2 + ); } #[test] - fn test_filter_addresses(){ + fn test_filter_addresses() { // Tests the filter_addresses function. // For (10/8) - let ip_address = SocketAddress::TcpIpV4{addr: [10, 0, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [10, 0, 0, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [10, 0, 255, 201], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [10, 0, 255, 201], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [10, 255, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [10, 255, 255, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (0/8) - let ip_address = SocketAddress::TcpIpV4{addr: [0, 0, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [0, 0, 0, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [0, 0, 255, 187], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [0, 0, 255, 187], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [0, 255, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [0, 255, 255, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (100.64/10) - let ip_address = SocketAddress::TcpIpV4{addr: [100, 64, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [100, 64, 0, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [100, 78, 255, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [100, 78, 255, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [100, 127, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [100, 127, 255, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (127/8) - let ip_address = SocketAddress::TcpIpV4{addr: [127, 0, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [127, 65, 73, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [127, 65, 73, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [127, 255, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [127, 255, 255, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (169.254/16) - let ip_address = SocketAddress::TcpIpV4{addr: [169, 254, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [169, 254, 0, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [169, 254, 221, 101], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [169, 254, 221, 101], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [169, 254, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [169, 254, 255, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (172.16/12) - let ip_address = SocketAddress::TcpIpV4{addr: [172, 16, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [172, 16, 0, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [172, 27, 101, 23], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [172, 27, 101, 23], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [172, 31, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [172, 31, 255, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (192.168/16) - let ip_address = SocketAddress::TcpIpV4{addr: [192, 168, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [192, 168, 0, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [192, 168, 205, 159], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [192, 168, 205, 159], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [192, 168, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [192, 168, 255, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (192.88.99/24) - let ip_address = SocketAddress::TcpIpV4{addr: [192, 88, 99, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [192, 88, 99, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [192, 88, 99, 140], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [192, 88, 99, 140], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV4{addr: [192, 88, 99, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [192, 88, 99, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For other IPv4 addresses - let ip_address = SocketAddress::TcpIpV4{addr: [188, 255, 99, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [188, 255, 99, 0], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), Some(ip_address.clone())); - let ip_address = SocketAddress::TcpIpV4{addr: [123, 8, 129, 14], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [123, 8, 129, 14], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), Some(ip_address.clone())); - let ip_address = SocketAddress::TcpIpV4{addr: [2, 88, 9, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV4 { addr: [2, 88, 9, 255], port: 1000 }; assert_eq!(filter_addresses(Some(ip_address.clone())), Some(ip_address.clone())); // For (2000::/3) - let ip_address = SocketAddress::TcpIpV6{addr: [32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV6 { + addr: [32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + port: 1000, + }; assert_eq!(filter_addresses(Some(ip_address.clone())), Some(ip_address.clone())); - let ip_address = SocketAddress::TcpIpV6{addr: [45, 34, 209, 190, 0, 123, 55, 34, 0, 0, 3, 27, 201, 0, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV6 { + addr: [45, 34, 209, 190, 0, 123, 55, 34, 0, 0, 3, 27, 201, 0, 0, 0], + port: 1000, + }; assert_eq!(filter_addresses(Some(ip_address.clone())), Some(ip_address.clone())); - let ip_address = SocketAddress::TcpIpV6{addr: [63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], port: 1000}; + let ip_address = SocketAddress::TcpIpV6 { + addr: [63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + port: 1000, + }; assert_eq!(filter_addresses(Some(ip_address.clone())), Some(ip_address.clone())); // For other IPv6 addresses - let ip_address = SocketAddress::TcpIpV6{addr: [24, 240, 12, 32, 0, 0, 0, 0, 20, 97, 0, 32, 121, 254, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV6 { + addr: [24, 240, 12, 32, 0, 0, 0, 0, 20, 97, 0, 32, 121, 254, 0, 0], + port: 1000, + }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV6{addr: [68, 23, 56, 63, 0, 0, 2, 7, 75, 109, 0, 39, 0, 0, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV6 { + addr: [68, 23, 56, 63, 0, 0, 2, 7, 75, 109, 0, 39, 0, 0, 0, 0], + port: 1000, + }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); - let ip_address = SocketAddress::TcpIpV6{addr: [101, 38, 140, 230, 100, 0, 30, 98, 0, 26, 0, 0, 57, 96, 0, 0], port: 1000}; + let ip_address = SocketAddress::TcpIpV6 { + addr: [101, 38, 140, 230, 100, 0, 30, 98, 0, 26, 0, 0, 57, 96, 0, 0], + port: 1000, + }; assert_eq!(filter_addresses(Some(ip_address.clone())), None); // For (None) @@ -3778,7 +4745,9 @@ mod tests { // sure we observe a value greater than one at least once. let cfg = Arc::new(create_peermgr_cfgs(1)); // Until we have std::thread::scoped we have to unsafe { turn off the borrow checker }. - let peer = Arc::new(create_network(1, unsafe { &*(&*cfg as *const _) as &'static _ }).pop().unwrap()); + let peer = Arc::new( + create_network(1, unsafe { &*(&*cfg as *const _) as &'static _ }).pop().unwrap(), + ); let end_time = Instant::now() + Duration::from_millis(100); let observed_loop = Arc::new(AtomicBool::new(false)); @@ -3787,9 +4756,13 @@ mod tests { let thread_observed_loop = Arc::clone(&observed_loop); move || { while Instant::now() < end_time || !thread_observed_loop.load(Ordering::Acquire) { - test_utils::TestChannelMessageHandler::MESSAGE_FETCH_COUNTER.with(|val| val.store(0, Ordering::Relaxed)); + test_utils::TestChannelMessageHandler::MESSAGE_FETCH_COUNTER + .with(|val| val.store(0, Ordering::Relaxed)); thread_peer.process_events(); - if test_utils::TestChannelMessageHandler::MESSAGE_FETCH_COUNTER.with(|val| val.load(Ordering::Relaxed)) > 1 { + if test_utils::TestChannelMessageHandler::MESSAGE_FETCH_COUNTER + .with(|val| val.load(Ordering::Relaxed)) + > 1 + { thread_observed_loop.store(true, Ordering::Release); return; } diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index ed707771f84..0c16396951c 100644 --- a/lightning/src/ln/priv_short_conf_tests.rs +++ b/lightning/src/ln/priv_short_conf_tests.rs @@ -13,14 +13,16 @@ use crate::chain::ChannelMonitorUpdateStatus; use crate::events::{ClosureReason, Event, HTLCDestination}; -use crate::ln::channelmanager::{MIN_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields}; +use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA}; +use crate::ln::msgs; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent, RoutingMessageHandler, +}; use crate::ln::onion_utils::LocalHTLCFailureReason; +use crate::ln::types::ChannelId; use crate::routing::gossip::RoutingFees; use crate::routing::router::{PaymentParameters, RouteHint, RouteHintHop}; use crate::types::features::ChannelTypeFeatures; -use crate::ln::msgs; -use crate::ln::types::ChannelId; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, RoutingMessageHandler, ErrorAction, MessageSendEvent}; use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::ser::Writeable; @@ -39,12 +41,17 @@ fn test_priv_forwarding_rejection() { no_announce_cfg.accept_forwards_to_priv_channels = false; let persister; let new_chain_monitor; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(no_announce_cfg.clone()), None]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[None, Some(no_announce_cfg.clone()), None]); let nodes_1_deserialized; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let chan_id_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000).2; - let chan_id_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000).0.channel_id; + let chan_id_1 = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000).2; + let chan_id_2 = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000) + .0 + .channel_id; // We should always be able to forward through nodes[1] as long as its out through a public // channel: @@ -61,21 +68,36 @@ fn test_priv_forwarding_rejection() { htlc_maximum_msat: None, }]); let last_hops = vec![route_hint]; - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap() - .with_route_hints(last_hops).unwrap(); - let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000); - - nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_route_hints(last_hops) + .unwrap(); + let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000); + + nodes[0] + .node + .send_payment_with_route( + route.clone(), + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - let payment_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); + let payment_event = + SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false, true); expect_pending_htlcs_forwardable!(nodes[1]); expect_htlc_handling_failed_destinations!( nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }] + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] ); check_added_monitors(&nodes[1], 1); @@ -85,9 +107,18 @@ fn test_priv_forwarding_rejection() { assert!(htlc_fail_updates.update_fail_malformed_htlcs.is_empty()); assert!(htlc_fail_updates.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_fail_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &htlc_fail_updates.update_fail_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], htlc_fail_updates.commitment_signed, true, true); - expect_payment_failed_with_update!(nodes[0], our_payment_hash, false, nodes[2].node.list_channels()[0].short_channel_id.unwrap(), true); + expect_payment_failed_with_update!( + nodes[0], + our_payment_hash, + false, + nodes[2].node.list_channels()[0].short_channel_id.unwrap(), + true + ); // Now disconnect nodes[1] from its peers and restart with accept_forwards_to_priv_channels set // to true. Sadly there is currently no way to change it at runtime. @@ -100,14 +131,40 @@ fn test_priv_forwarding_rejection() { let monitor_b_serialized = get_monitor!(nodes[1], chan_id_2).encode(); no_announce_cfg.accept_forwards_to_priv_channels = true; - reload_node!(nodes[1], no_announce_cfg, &nodes_1_serialized, &[&monitor_a_serialized, &monitor_b_serialized], persister, new_chain_monitor, nodes_1_deserialized); - - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + reload_node!( + nodes[1], + no_announce_cfg, + &nodes_1_serialized, + &[&monitor_a_serialized, &monitor_b_serialized], + persister, + new_chain_monitor, + nodes_1_deserialized + ); + + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &as_reestablish); @@ -115,12 +172,30 @@ fn test_priv_forwarding_rejection() { get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); - nodes[1].node.peer_connected(nodes[2].node.get_our_node_id(), &msgs::Init { - features: nodes[2].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[2].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[2].node.get_our_node_id(), + &msgs::Init { + features: nodes[2].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[2] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[2]).pop().unwrap(); let cs_reestablish = get_chan_reestablish_msgs!(nodes[2], nodes[1]).pop().unwrap(); nodes[2].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &bs_reestablish); @@ -128,10 +203,23 @@ fn test_priv_forwarding_rejection() { get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id()); get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); - nodes[0].node.send_payment_with_route(route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 10_000, our_payment_hash, our_payment_secret); + pass_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[2]]], + 10_000, + our_payment_hash, + our_payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], our_payment_preimage); } @@ -142,33 +230,48 @@ fn do_test_1_conf_open(connect_style: ConnectStyle) { alice_config.channel_handshake_config.minimum_depth = 1; alice_config.channel_handshake_config.announce_for_forwarding = true; alice_config.channel_handshake_limits.force_announced_channel_preference = false; - alice_config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); + alice_config.channel_config.max_dust_htlc_exposure = + MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); let mut bob_config = UserConfig::default(); bob_config.channel_handshake_config.minimum_depth = 1; bob_config.channel_handshake_config.announce_for_forwarding = true; bob_config.channel_handshake_limits.force_announced_channel_preference = false; - bob_config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); + bob_config.channel_config.max_dust_htlc_exposure = + MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(alice_config), Some(bob_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(alice_config), Some(bob_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); *nodes[0].connect_style.borrow_mut() = connect_style; let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001); mine_transaction(&nodes[1], &tx); - nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_channel_ready( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelReady, + nodes[0].node.get_our_node_id() + ), + ); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); mine_transaction(&nodes[0], &tx); let as_msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(as_msg_events.len(), 2); - let as_channel_ready = if let MessageSendEvent::SendChannelReady { ref node_id, ref msg } = as_msg_events[0] { - assert_eq!(*node_id, nodes[1].node.get_our_node_id()); - msg.clone() - } else { panic!("Unexpected event"); }; + let as_channel_ready = + if let MessageSendEvent::SendChannelReady { ref node_id, ref msg } = as_msg_events[0] { + assert_eq!(*node_id, nodes[1].node.get_our_node_id()); + msg.clone() + } else { + panic!("Unexpected event"); + }; if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = as_msg_events[1] { assert_eq!(*node_id, nodes[1].node.get_our_node_id()); - } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &as_channel_ready); expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id()); @@ -177,7 +280,9 @@ fn do_test_1_conf_open(connect_style: ConnectStyle) { assert_eq!(bs_msg_events.len(), 1); if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = bs_msg_events[0] { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - } else { panic!("Unexpected event"); } + } else { + panic!("Unexpected event"); + } send_payment(&nodes[0], &[&nodes[1]], 100_000); @@ -186,31 +291,58 @@ fn do_test_1_conf_open(connect_style: ConnectStyle) { connect_blocks(&nodes[0], 4); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); connect_blocks(&nodes[0], 1); - nodes[1].node.handle_announcement_signatures(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendAnnouncementSignatures, nodes[1].node.get_our_node_id())); + nodes[1].node.handle_announcement_signatures( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendAnnouncementSignatures, + nodes[1].node.get_our_node_id() + ), + ); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); connect_blocks(&nodes[1], 5); let bs_announce_events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(bs_announce_events.len(), 2); - let bs_announcement_sigs = if let MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } = bs_announce_events[1] { - assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - msg.clone() - } else { panic!("Unexpected event"); }; - let (bs_announcement, bs_update) = if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = bs_announce_events[0] { - (msg.clone(), update_msg.clone().unwrap()) - } else { panic!("Unexpected event"); }; - - nodes[0].node.handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); + let bs_announcement_sigs = + if let MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } = + bs_announce_events[1] + { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + msg.clone() + } else { + panic!("Unexpected event"); + }; + let (bs_announcement, bs_update) = + if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = + bs_announce_events[0] + { + (msg.clone(), update_msg.clone().unwrap()) + } else { + panic!("Unexpected event"); + }; + + nodes[0] + .node + .handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); let as_announce_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(as_announce_events.len(), 1); - let (announcement, as_update) = if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = as_announce_events[0] { - (msg.clone(), update_msg.clone().unwrap()) - } else { panic!("Unexpected event"); }; + let (announcement, as_update) = + if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = + as_announce_events[0] + { + (msg.clone(), update_msg.clone().unwrap()) + } else { + panic!("Unexpected event"); + }; assert_eq!(announcement, bs_announcement); for (i, node) in nodes.iter().enumerate() { let counterparty_node_id = nodes[(i + 1) % 2].node.get_our_node_id(); - assert!(node.gossip_sync.handle_channel_announcement(Some(counterparty_node_id), &announcement).unwrap()); + assert!(node + .gossip_sync + .handle_channel_announcement(Some(counterparty_node_id), &announcement) + .unwrap()); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &as_update).unwrap(); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &bs_update).unwrap(); } @@ -233,7 +365,8 @@ fn test_routed_scid_alias() { let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000).2; - let mut as_channel_ready = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000).0; + let mut as_channel_ready = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000).0; let last_hop = nodes[2].node.list_usable_channels(); let hop_hints = vec![RouteHint(vec![RouteHintHop { @@ -241,19 +374,40 @@ fn test_routed_scid_alias() { short_channel_id: last_hop[0].inbound_scid_alias.unwrap(), fees: RoutingFees { base_msat: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_base_msat, - proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths, + proportional_millionths: last_hop[0] + .counterparty + .forwarding_info + .as_ref() + .unwrap() + .fee_proportional_millionths, }, - cltv_expiry_delta: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().cltv_expiry_delta, + cltv_expiry_delta: last_hop[0] + .counterparty + .forwarding_info + .as_ref() + .unwrap() + .cltv_expiry_delta, htlc_maximum_msat: None, htlc_minimum_msat: None, }])]; - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap() - .with_route_hints(hop_hints).unwrap(); - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_route_hints(hop_hints) + .unwrap(); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000); assert_eq!(route.paths[0].hops[1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap()); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 100_000, payment_hash, payment_secret); @@ -292,8 +446,22 @@ fn test_scid_privacy_on_pub_channel() { let mut scid_privacy_cfg = test_default_channel_config(); scid_privacy_cfg.channel_handshake_config.announce_for_forwarding = true; scid_privacy_cfg.channel_handshake_config.negotiate_scid_privacy = true; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(scid_privacy_cfg)).unwrap(); - let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100000, + 10001, + 42, + None, + Some(scid_privacy_cfg), + ) + .unwrap(); + let mut open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert!(!open_channel.common_fields.channel_type.as_ref().unwrap().supports_scid_privacy()); // we ignore `negotiate_scid_privacy` on pub channels open_channel.common_fields.channel_type.as_mut().unwrap().set_scid_privacy_required(); @@ -316,24 +484,57 @@ fn test_scid_privacy_negotiation() { let mut scid_privacy_cfg = test_default_channel_config(); scid_privacy_cfg.channel_handshake_config.announce_for_forwarding = false; scid_privacy_cfg.channel_handshake_config.negotiate_scid_privacy = true; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(scid_privacy_cfg)).unwrap(); - - let init_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100000, + 10001, + 42, + None, + Some(scid_privacy_cfg), + ) + .unwrap(); + + let init_open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert!(init_open_channel.common_fields.channel_type.as_ref().unwrap().supports_scid_privacy()); assert!(nodes[0].node.list_channels()[0].channel_type.is_none()); // channel_type is none until counterparty accepts // now simulate nodes[1] responding with an Error message, indicating it doesn't understand // SCID alias. - nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { - channel_id: init_open_channel.common_fields.temporary_channel_id, - data: "Yo, no SCID aliases, no privacy here!".to_string() - }); + nodes[0].node.handle_error( + nodes[1].node.get_our_node_id(), + &msgs::ErrorMessage { + channel_id: init_open_channel.common_fields.temporary_channel_id, + data: "Yo, no SCID aliases, no privacy here!".to_string(), + }, + ); assert!(nodes[0].node.list_channels()[0].channel_type.is_none()); // channel_type is none until counterparty accepts - let second_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - assert!(!second_open_channel.common_fields.channel_type.as_ref().unwrap().supports_scid_privacy()); + let second_open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); + assert!(!second_open_channel + .common_fields + .channel_type + .as_ref() + .unwrap() + .supports_scid_privacy()); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &second_open_channel); - nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + nodes[0].node.handle_accept_channel( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ), + ); let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); @@ -342,8 +543,16 @@ fn test_scid_privacy_negotiation() { _ => panic!("Unexpected event"), } - assert!(!nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap().supports_scid_privacy()); - assert!(!nodes[1].node.list_channels()[0].channel_type.as_ref().unwrap().supports_scid_privacy()); + assert!(!nodes[0].node.list_channels()[0] + .channel_type + .as_ref() + .unwrap() + .supports_scid_privacy()); + assert!(!nodes[1].node.list_channels()[0] + .channel_type + .as_ref() + .unwrap() + .supports_scid_privacy()); } #[test] @@ -354,7 +563,8 @@ fn test_inbound_scid_privacy() { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let mut accept_forward_cfg = test_default_channel_config(); accept_forward_cfg.accept_forwards_to_priv_channels = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(accept_forward_cfg), None]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[None, Some(accept_forward_cfg), None]); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); @@ -362,39 +572,96 @@ fn test_inbound_scid_privacy() { let mut no_announce_cfg = test_default_channel_config(); no_announce_cfg.channel_handshake_config.announce_for_forwarding = false; no_announce_cfg.channel_handshake_config.negotiate_scid_privacy = true; - nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 10_000, 42, None, Some(no_announce_cfg)).unwrap(); - let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[2].node.get_our_node_id()); + nodes[1] + .node + .create_channel( + nodes[2].node.get_our_node_id(), + 100_000, + 10_000, + 42, + None, + Some(no_announce_cfg), + ) + .unwrap(); + let mut open_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendOpenChannel, + nodes[2].node.get_our_node_id() + ); assert!(open_channel.common_fields.channel_type.as_ref().unwrap().requires_scid_privacy()); nodes[2].node.handle_open_channel(nodes[1].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[1].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[2], + MessageSendEvent::SendAcceptChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_accept_channel(nodes[2].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[1], &nodes[2].node.get_our_node_id(), 100_000, 42); - nodes[1].node.funding_transaction_generated(temporary_channel_id, nodes[2].node.get_our_node_id(), tx.clone()).unwrap(); - nodes[2].node.handle_funding_created(nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingCreated, nodes[2].node.get_our_node_id())); + let (temporary_channel_id, tx, _) = + create_funding_transaction(&nodes[1], &nodes[2].node.get_our_node_id(), 100_000, 42); + nodes[1] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[2].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); + nodes[2].node.handle_funding_created( + nodes[1].node.get_our_node_id(), + &get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingCreated, + nodes[2].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[2], 1); - let cs_funding_signed = get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, nodes[1].node.get_our_node_id()); + let cs_funding_signed = get_event_msg!( + nodes[2], + MessageSendEvent::SendFundingSigned, + nodes[1].node.get_our_node_id() + ); expect_channel_pending_event(&nodes[2], &nodes[1].node.get_our_node_id()); nodes[1].node.handle_funding_signed(nodes[2].node.get_our_node_id(), &cs_funding_signed); expect_channel_pending_event(&nodes[1], &nodes[2].node.get_our_node_id()); check_added_monitors!(nodes[1], 1); - let conf_height = core::cmp::max(nodes[1].best_block_info().1 + 1, nodes[2].best_block_info().1 + 1); + let conf_height = + core::cmp::max(nodes[1].best_block_info().1 + 1, nodes[2].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[2], &tx, conf_height); connect_blocks(&nodes[2], CHAN_CONFIRM_DEPTH - 1); - let bs_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[2].node.get_our_node_id()); - nodes[1].node.handle_channel_ready(nodes[2].node.get_our_node_id(), &get_event_msg!(nodes[2], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id())); + let bs_channel_ready = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelReady, + nodes[2].node.get_our_node_id() + ); + nodes[1].node.handle_channel_ready( + nodes[2].node.get_our_node_id(), + &get_event_msg!( + nodes[2], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ), + ); expect_channel_ready_event(&nodes[1], &nodes[2].node.get_our_node_id()); - let bs_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id()); + let bs_update = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[2].node.get_our_node_id() + ); nodes[2].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &bs_channel_ready); expect_channel_ready_event(&nodes[2], &nodes[1].node.get_our_node_id()); - let cs_update = get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); + let cs_update = get_event_msg!( + nodes[2], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_channel_update(nodes[2].node.get_our_node_id(), &cs_update); nodes[2].node.handle_channel_update(nodes[1].node.get_our_node_id(), &bs_update); @@ -407,19 +674,40 @@ fn test_inbound_scid_privacy() { short_channel_id: last_hop[0].inbound_scid_alias.unwrap(), fees: RoutingFees { base_msat: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_base_msat, - proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths, + proportional_millionths: last_hop[0] + .counterparty + .forwarding_info + .as_ref() + .unwrap() + .fee_proportional_millionths, }, - cltv_expiry_delta: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().cltv_expiry_delta, + cltv_expiry_delta: last_hop[0] + .counterparty + .forwarding_info + .as_ref() + .unwrap() + .cltv_expiry_delta, htlc_maximum_msat: None, htlc_minimum_msat: None, }])]; - let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap() - .with_route_hints(hop_hints.clone()).unwrap(); - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000); + let payment_params = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_route_hints(hop_hints.clone()) + .unwrap(); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000); assert_eq!(route.paths[0].hops[1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap()); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 100_000, payment_hash, payment_secret); @@ -429,13 +717,24 @@ fn test_inbound_scid_privacy() { // what channel we're talking about. hop_hints[0].0[0].short_channel_id = last_hop[0].short_channel_id.unwrap(); - let payment_params_2 = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap() - .with_route_hints(hop_hints).unwrap(); - let (route_2, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params_2, 100_000); + let payment_params_2 = + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_route_hints(hop_hints) + .unwrap(); + let (route_2, payment_hash_2, _, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[2], payment_params_2, 100_000); assert_eq!(route_2.paths[0].hops[1].short_channel_id, last_hop[0].short_channel_id.unwrap()); - nodes[0].node.send_payment_with_route(route_2, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route_2, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let payment_event = SendEvent::from_node(&nodes[0]); @@ -445,19 +744,37 @@ fn test_inbound_scid_privacy() { expect_pending_htlcs_forwardable!(nodes[1]); expect_htlc_handling_failed_destinations!( nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: last_hop[0].channel_id }] + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: last_hop[0].channel_id + }] ); check_added_monitors(&nodes[1], 1); - nodes[1].logger.assert_log_regex("lightning::ln::channelmanager", regex::Regex::new(r"Refusing to forward over real channel SCID as our counterparty requested").unwrap(), 1); + nodes[1].logger.assert_log_regex( + "lightning::ln::channelmanager", + regex::Regex::new( + r"Refusing to forward over real channel SCID as our counterparty requested", + ) + .unwrap(), + 1, + ); let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false); - expect_payment_failed_conditions(&nodes[0], payment_hash_2, false, - PaymentFailedConditions::new().blamed_scid(last_hop[0].short_channel_id.unwrap()) - .blamed_chan_closed(true).expected_htlc_error_data(LocalHTLCFailureReason::UnknownNextPeer, &[0; 0])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash_2, + false, + PaymentFailedConditions::new() + .blamed_scid(last_hop[0].short_channel_id.unwrap()) + .blamed_chan_closed(true) + .expected_htlc_error_data(LocalHTLCFailureReason::UnknownNextPeer, &[0; 0]), + ); } #[test] @@ -469,7 +786,8 @@ fn test_scid_alias_returned() { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let mut accept_forward_cfg = test_default_channel_config(); accept_forward_cfg.accept_forwards_to_priv_channels = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(accept_forward_cfg), None]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[None, Some(accept_forward_cfg), None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0); @@ -481,69 +799,128 @@ fn test_scid_alias_returned() { short_channel_id: last_hop[0].inbound_scid_alias.unwrap(), fees: RoutingFees { base_msat: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_base_msat, - proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths, + proportional_millionths: last_hop[0] + .counterparty + .forwarding_info + .as_ref() + .unwrap() + .fee_proportional_millionths, }, - cltv_expiry_delta: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().cltv_expiry_delta, + cltv_expiry_delta: last_hop[0] + .counterparty + .forwarding_info + .as_ref() + .unwrap() + .cltv_expiry_delta, htlc_maximum_msat: None, htlc_minimum_msat: None, }])]; let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42) - .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap() - .with_route_hints(hop_hints).unwrap(); - let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000); - assert_eq!(route.paths[0].hops[1].short_channel_id, nodes[2].node.list_usable_channels()[0].inbound_scid_alias.unwrap()); + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()) + .unwrap() + .with_route_hints(hop_hints) + .unwrap(); + let (mut route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000); + assert_eq!( + route.paths[0].hops[1].short_channel_id, + nodes[2].node.list_usable_channels()[0].inbound_scid_alias.unwrap() + ); route.paths[0].hops[1].fee_msat = 10_000_000; // Overshoot the last channel's value // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route.clone(), payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route.clone(), + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let as_updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], &as_updates.commitment_signed, false, true); expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan.0.channel_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan.0.channel_id + }] + ); check_added_monitors!(nodes[1], 1); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, false, true); let err_data = 0u16.to_be_bytes(); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().blamed_scid(last_hop[0].inbound_scid_alias.unwrap()) - .blamed_chan_closed(false).expected_htlc_error_data(LocalHTLCFailureReason::TemporaryChannelFailure, &err_data)); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .blamed_scid(last_hop[0].inbound_scid_alias.unwrap()) + .blamed_chan_closed(false) + .expected_htlc_error_data(LocalHTLCFailureReason::TemporaryChannelFailure, &err_data), + ); route.paths[0].hops[1].fee_msat = 10_000; // Reset to the correct payment amount route.paths[0].hops[0].fee_msat = 0; // But set fee paid to the middle hop to 0 // Route the HTLC through to the destination. - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let as_updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], &as_updates.commitment_signed, false, true); expect_pending_htlcs_forwardable!(nodes[1]); expect_htlc_handling_failed_destinations!( nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan.0.channel_id }] + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan.0.channel_id + }] ); check_added_monitors(&nodes[1], 1); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], bs_updates.commitment_signed, false, true); let mut err_data = Vec::new(); err_data.extend_from_slice(&10_000u64.to_be_bytes()); err_data.extend_from_slice(&0u16.to_be_bytes()); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, - PaymentFailedConditions::new().blamed_scid(last_hop[0].inbound_scid_alias.unwrap()) - .blamed_chan_closed(false).expected_htlc_error_data(LocalHTLCFailureReason::FeeInsufficient, &err_data)); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .blamed_scid(last_hop[0].inbound_scid_alias.unwrap()) + .blamed_chan_closed(false) + .expected_htlc_error_data(LocalHTLCFailureReason::FeeInsufficient, &err_data), + ); } #[test] @@ -578,32 +955,64 @@ fn test_0conf_channel_with_async_monitor() { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let mut chan_config = test_default_channel_config(); chan_config.manually_accept_inbound_channels = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(chan_config.clone()), None]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[None, Some(chan_config.clone()), None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); chan_config.channel_handshake_config.announce_for_forwarding = false; - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(chan_config)).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, Some(chan_config)) + .unwrap(); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) + .unwrap(); }, _ => panic!("Unexpected event"), }; - let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let mut accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); assert_eq!(accept_channel.common_fields.minimum_depth, 0); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); - let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); - nodes[0].node.funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); - let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let (temporary_channel_id, tx, funding_output) = + create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + nodes[0] + .node + .funding_transaction_generated( + temporary_channel_id, + nodes[1].node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); + let funding_created = get_event_msg!( + nodes[0], + MessageSendEvent::SendFundingCreated, + nodes[1].node.get_our_node_id() + ); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created); @@ -623,14 +1032,14 @@ fn test_0conf_channel_with_async_monitor() { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &msg); check_added_monitors!(nodes[0], 1); - } + }, _ => panic!("Unexpected event"), } match &bs_signed_locked[1] { MessageSendEvent::SendChannelReady { node_id, msg } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &msg); - } + }, _ => panic!("Unexpected event"), } @@ -665,18 +1074,22 @@ fn test_0conf_channel_with_async_monitor() { MessageSendEvent::SendChannelReady { node_id, msg } => { assert_eq!(*node_id, nodes[1].node.get_our_node_id()); nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &msg); - } + }, _ => panic!("Unexpected event"), } expect_channel_ready_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); + let bs_channel_update = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[0].node.get_our_node_id() + ); let as_channel_update = match &as_locked_update[1] { MessageSendEvent::SendChannelUpdate { node_id, msg } => { assert_eq!(*node_id, nodes[1].node.get_our_node_id()); msg.clone() - } + }, _ => panic!("Unexpected event"), }; @@ -693,32 +1106,65 @@ fn test_0conf_channel_with_async_monitor() { // Now that we have useful channels, try sending a payment where the we hit a temporary monitor // failure before we've ever confirmed the funding transaction. This previously caused a panic. - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000); - - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000); + + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let as_send = SendEvent::from_node(&nodes[0]); nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &as_send.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &as_send.commitment_msg); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &as_send.commitment_msg, + ); check_added_monitors!(nodes[1], 1); - let (bs_raa, bs_commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let (bs_raa, bs_commitment_signed) = + get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &bs_raa); check_added_monitors!(nodes[0], 1); - nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &bs_commitment_signed); + nodes[0].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &bs_commitment_signed, + ); check_added_monitors!(nodes[0], 1); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress); - nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id())); + nodes[1].node.handle_revoke_and_ack( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ), + ); check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (_, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&bs_raa.channel_id).unwrap().clone(); - nodes[1].chain_monitor.chain_monitor.channel_monitor_updated(bs_raa.channel_id, latest_update).unwrap(); + let (_, latest_update) = nodes[1] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&bs_raa.channel_id) + .unwrap() + .clone(); + nodes[1] + .chain_monitor + .chain_monitor + .channel_monitor_updated(bs_raa.channel_id, latest_update) + .unwrap(); check_added_monitors!(nodes[1], 0); expect_pending_htlcs_forwardable!(nodes[1]); check_added_monitors!(nodes[1], 1); @@ -758,7 +1204,13 @@ fn test_0conf_close_no_early_chan_update() { nodes[0].node.force_close_all_channels_broadcasting_latest_txn(error_message.to_string()); check_added_monitors!(nodes[0], 1); - check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); let _ = get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id()); } @@ -781,12 +1233,24 @@ fn test_public_0conf_channel() { send_payment(&nodes[0], &[&nodes[1]], 100_000); let scid = confirm_transaction(&nodes[0], &tx); - let as_announcement_sigs = get_event_msg!(nodes[0], MessageSendEvent::SendAnnouncementSignatures, nodes[1].node.get_our_node_id()); + let as_announcement_sigs = get_event_msg!( + nodes[0], + MessageSendEvent::SendAnnouncementSignatures, + nodes[1].node.get_our_node_id() + ); assert_eq!(confirm_transaction(&nodes[1], &tx), scid); - let bs_announcement_sigs = get_event_msg!(nodes[1], MessageSendEvent::SendAnnouncementSignatures, nodes[0].node.get_our_node_id()); + let bs_announcement_sigs = get_event_msg!( + nodes[1], + MessageSendEvent::SendAnnouncementSignatures, + nodes[0].node.get_our_node_id() + ); - nodes[1].node.handle_announcement_signatures(nodes[0].node.get_our_node_id(), &as_announcement_sigs); - nodes[0].node.handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); + nodes[1] + .node + .handle_announcement_signatures(nodes[0].node.get_our_node_id(), &as_announcement_sigs); + nodes[0] + .node + .handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); let bs_announcement = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(bs_announcement.len(), 1); @@ -807,7 +1271,10 @@ fn test_public_0conf_channel() { assert!(announcement == *msg); let update_msg = update_msg.as_ref().unwrap(); assert_eq!(update_msg.contents.short_channel_id, scid); - assert_eq!(update_msg.contents.short_channel_id, announcement.contents.short_channel_id); + assert_eq!( + update_msg.contents.short_channel_id, + announcement.contents.short_channel_id + ); assert_eq!(update_msg.contents.short_channel_id, bs_update.contents.short_channel_id); }, _ => panic!("Unexpected event"), @@ -842,9 +1309,17 @@ fn test_0conf_channel_reorg() { let real_scid = nodes[0].node.list_usable_channels()[0].short_channel_id.unwrap(); assert_eq!(nodes[1].node.list_usable_channels()[0].short_channel_id.unwrap(), real_scid); - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 10_000); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 10_000); assert_eq!(route.paths[0].hops[0].short_channel_id, real_scid); - send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1]]], 10_000, payment_hash, payment_secret); + send_along_route_with_secret( + &nodes[0], + route, + &[&[&nodes[1]]], + 10_000, + payment_hash, + payment_secret, + ); claim_payment(&nodes[0], &[&nodes[1]], payment_preimage); disconnect_blocks(&nodes[0], 1); @@ -853,14 +1328,28 @@ fn test_0conf_channel_reorg() { // At this point the channel no longer has an SCID again. In the future we should likely // support simply un-setting the SCID and waiting until the channel gets re-confirmed, but for // now we force-close the channel here. - check_closed_event!(&nodes[0], 1, ClosureReason::ProcessingError { - err: "Funding transaction was un-confirmed. Locked at 0 confs, now have 0 confs.".to_owned() - }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::ProcessingError { + err: "Funding transaction was un-confirmed. Locked at 0 confs, now have 0 confs." + .to_owned() + }, + [nodes[1].node.get_our_node_id()], + 100000 + ); check_closed_broadcast!(nodes[0], true); check_added_monitors(&nodes[0], 1); - check_closed_event!(&nodes[1], 1, ClosureReason::ProcessingError { - err: "Funding transaction was un-confirmed. Locked at 0 confs, now have 0 confs.".to_owned() - }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[1], + 1, + ClosureReason::ProcessingError { + err: "Funding transaction was un-confirmed. Locked at 0 confs, now have 0 confs." + .to_owned() + }, + [nodes[0].node.get_our_node_id()], + 100000 + ); check_closed_broadcast!(nodes[1], true); check_added_monitors(&nodes[1], 1); } @@ -876,8 +1365,15 @@ fn test_zero_conf_accept_reject() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let mut open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); open_channel_msg.common_fields.channel_type = Some(channel_type_features.clone()); @@ -885,7 +1381,10 @@ fn test_zero_conf_accept_reject() { let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); match msg_events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg, .. }, .. } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg, .. }, + .. + } => { assert_eq!(msg.data, "No zero confirmation channels accepted".to_owned()); }, _ => panic!(), @@ -897,15 +1396,27 @@ fn test_zero_conf_accept_reject() { let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, - &[None, Some(manually_accept_conf.clone())]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf.clone())]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // 2.1 First try the non-0conf method to manually accept - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, - None, Some(manually_accept_conf.clone())).unwrap(); - let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, - nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100000, + 10001, + 42, + None, + Some(manually_accept_conf.clone()), + ) + .unwrap(); + let mut open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); open_channel_msg.common_fields.channel_type = Some(channel_type_features.clone()); @@ -919,25 +1430,47 @@ fn test_zero_conf_accept_reject() { match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { // Assert we fail to accept via the non-0conf method - assert!(nodes[1].node.accept_inbound_channel(&temporary_channel_id, - &nodes[0].node.get_our_node_id(), 0, None).is_err()); + assert!(nodes[1] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None + ) + .is_err()); }, _ => panic!(), } let msg_events = nodes[1].node.get_and_clear_pending_msg_events(); match msg_events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg, .. }, .. } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg, .. }, + .. + } => { assert_eq!(msg.data, "No zero confirmation channels accepted".to_owned()); }, _ => panic!(), } // 2.2 Try again with the 0conf method to manually accept - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, - None, Some(manually_accept_conf)).unwrap(); - let mut open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, - nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel( + nodes[1].node.get_our_node_id(), + 100000, + 10001, + 42, + None, + Some(manually_accept_conf), + ) + .unwrap(); + let mut open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); open_channel_msg.common_fields.channel_type = Some(channel_type_features); @@ -948,8 +1481,15 @@ fn test_zero_conf_accept_reject() { match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { // Assert we can accept via the 0conf method - assert!(nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf( - &temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).is_ok()); + assert!(nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None + ) + .is_ok()); }, _ => panic!(), } @@ -976,20 +1516,39 @@ fn test_connect_before_funding() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_accept_conf)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 10_001, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100_000, 10_001, 42, None, None) + .unwrap(); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { Event::OpenChannelRequest { temporary_channel_id, .. } => { - nodes[1].node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0, None).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + None, + ) + .unwrap(); }, _ => panic!("Unexpected event"), }; - let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let mut accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); assert_eq!(accept_channel.common_fields.minimum_depth, 0); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); @@ -1026,15 +1585,27 @@ fn test_0conf_ann_sigs_racing_conf() { send_payment(&nodes[0], &[&nodes[1]], 100_000); let scid = confirm_transaction(&nodes[0], &tx); - let as_announcement_sigs = get_event_msg!(nodes[0], MessageSendEvent::SendAnnouncementSignatures, nodes[1].node.get_our_node_id()); + let as_announcement_sigs = get_event_msg!( + nodes[0], + MessageSendEvent::SendAnnouncementSignatures, + nodes[1].node.get_our_node_id() + ); // Handling the announcement_signatures prior to the first confirmation would panic before. - nodes[1].node.handle_announcement_signatures(nodes[0].node.get_our_node_id(), &as_announcement_sigs); + nodes[1] + .node + .handle_announcement_signatures(nodes[0].node.get_our_node_id(), &as_announcement_sigs); assert_eq!(confirm_transaction(&nodes[1], &tx), scid); - let bs_announcement_sigs = get_event_msg!(nodes[1], MessageSendEvent::SendAnnouncementSignatures, nodes[0].node.get_our_node_id()); + let bs_announcement_sigs = get_event_msg!( + nodes[1], + MessageSendEvent::SendAnnouncementSignatures, + nodes[0].node.get_our_node_id() + ); - nodes[0].node.handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); + nodes[0] + .node + .handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); let as_announcement = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(as_announcement.len(), 1); } diff --git a/lightning/src/ln/reload_tests.rs b/lightning/src/ln/reload_tests.rs index a2d567dba96..a203214cf82 100644 --- a/lightning/src/ln/reload_tests.rs +++ b/lightning/src/ln/reload_tests.rs @@ -9,25 +9,29 @@ //! Functional tests which test for correct behavior across node restarts. -use crate::chain::{ChannelMonitorUpdateStatus, Watch}; use crate::chain::chaininterface::LowerBoundedFeeEstimator; use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateStep}; -use crate::routing::router::{PaymentParameters, RouteParameters}; -use crate::sign::EntropySource; use crate::chain::transaction::OutPoint; +use crate::chain::{ChannelMonitorUpdateStatus, Watch}; use crate::events::{ClosureReason, Event, HTLCDestination}; -use crate::ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, PaymentId, RecipientOnionFields, RAACommitmentOrder}; +use crate::ln::channelmanager::{ + ChannelManager, ChannelManagerReadArgs, PaymentId, RAACommitmentOrder, RecipientOnionFields, +}; use crate::ln::msgs; +use crate::ln::msgs::{ + BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent, RoutingMessageHandler, +}; use crate::ln::types::ChannelId; -use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, RoutingMessageHandler, ErrorAction, MessageSendEvent}; +use crate::routing::router::{PaymentParameters, RouteParameters}; +use crate::sign::EntropySource; +use crate::util::config::UserConfig; +use crate::util::errors::APIError; +use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_utils; -use crate::util::errors::APIError; -use crate::util::ser::{Writeable, ReadableArgs}; -use crate::util::config::UserConfig; -use bitcoin::hashes::Hash; use bitcoin::hash_types::BlockHash; +use bitcoin::hashes::Hash; use types::payment::{PaymentHash, PaymentPreimage}; use crate::prelude::*; @@ -65,13 +69,31 @@ fn test_funding_peer_disconnect() { let events_2 = nodes[1].node.get_and_clear_pending_msg_events(); assert!(events_2.is_empty()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let as_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); // nodes[0] hasn't yet received a channel_ready, so it only sends that on reconnect. @@ -144,7 +166,9 @@ fn test_funding_peer_disconnect() { // When we deliver nodes[1]'s announcement_signatures to nodes[0], nodes[0] should immediately // broadcast the channel announcement globally, as well as re-send its (now-public) // channel_update. - nodes[0].node.handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); + nodes[0] + .node + .handle_announcement_signatures(nodes[1].node.get_our_node_id(), &bs_announcement_sigs); let events_7 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_7.len(), 1); let (chan_announcement, as_update) = match events_7[0] { @@ -156,7 +180,9 @@ fn test_funding_peer_disconnect() { // Finally, deliver nodes[0]'s announcement_signatures to nodes[1] and make sure it creates the // same channel_announcement. - nodes[1].node.handle_announcement_signatures(nodes[0].node.get_our_node_id(), &as_announcement_sigs); + nodes[1] + .node + .handle_announcement_signatures(nodes[0].node.get_our_node_id(), &as_announcement_sigs); let events_8 = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events_8.len(), 1); let bs_update = match events_8[0] { @@ -169,7 +195,10 @@ fn test_funding_peer_disconnect() { // Provide the channel announcement and public updates to the network graph let node_1_pubkey = nodes[1].node.get_our_node_id(); - nodes[0].gossip_sync.handle_channel_announcement(Some(node_1_pubkey), &chan_announcement).unwrap(); + nodes[0] + .gossip_sync + .handle_channel_announcement(Some(node_1_pubkey), &chan_announcement) + .unwrap(); nodes[0].gossip_sync.handle_channel_update(Some(node_1_pubkey), &bs_update).unwrap(); nodes[0].gossip_sync.handle_channel_update(Some(node_1_pubkey), &as_update).unwrap(); @@ -183,7 +212,14 @@ fn test_funding_peer_disconnect() { let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - reload_node!(nodes[0], &nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + &nodes[0].node.encode(), + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); } @@ -203,17 +239,45 @@ fn test_no_txn_manager_serialize_deserialize() { nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - let chan_0_monitor_serialized = - get_monitor!(nodes[0], ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 0 })).encode(); - reload_node!(nodes[0], nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + let chan_0_monitor_serialized = get_monitor!( + nodes[0], + ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 0 }) + ) + .encode(); + reload_node!( + nodes[0], + nodes[0].node.encode(), + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); @@ -221,11 +285,16 @@ fn test_no_txn_manager_serialize_deserialize() { nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - let (channel_ready, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); - let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); + let (channel_ready, _) = + create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); + let (announcement, as_update, bs_update) = + create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); for (i, node) in nodes.iter().enumerate() { let counterparty_node_id = nodes[(i + 1) % 2].node.get_our_node_id(); - assert!(node.gossip_sync.handle_channel_announcement(Some(counterparty_node_id), &announcement).unwrap()); + assert!(node + .gossip_sync + .handle_channel_announcement(Some(counterparty_node_id), &announcement) + .unwrap()); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &as_update).unwrap(); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &bs_update).unwrap(); } @@ -250,18 +319,37 @@ fn test_manager_serialize_deserialize_events() { let push_msat = 10001; let node_a = nodes.remove(0); let node_b = nodes.remove(0); - node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None).unwrap(); - node_b.node.handle_open_channel(node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id())); - node_a.node.handle_accept_channel(node_b.node.get_our_node_id(), &get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id())); - - let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&node_a, &node_b.node.get_our_node_id(), channel_value, 42); + node_a + .node + .create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None) + .unwrap(); + node_b.node.handle_open_channel( + node_a.node.get_our_node_id(), + &get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id()), + ); + node_a.node.handle_accept_channel( + node_b.node.get_our_node_id(), + &get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id()), + ); - node_a.node.funding_transaction_generated(temporary_channel_id, node_b.node.get_our_node_id(), tx.clone()).unwrap(); + let (temporary_channel_id, tx, funding_output) = + create_funding_transaction(&node_a, &node_b.node.get_our_node_id(), channel_value, 42); + + node_a + .node + .funding_transaction_generated( + temporary_channel_id, + node_b.node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors!(node_a, 0); - let funding_created = get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id()); + let funding_created = + get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id()); let channel_id = ChannelId::v1_from_funding_txid( - funding_created.funding_txid.as_byte_array(), funding_created.funding_output_index + funding_created.funding_txid.as_byte_array(), + funding_created.funding_output_index, ); node_b.node.handle_funding_created(node_a.node.get_our_node_id(), &funding_created); @@ -272,7 +360,8 @@ fn test_manager_serialize_deserialize_events() { added_monitors.clear(); } - let bs_funding_signed = get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a.node.get_our_node_id()); + let bs_funding_signed = + get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a.node.get_our_node_id()); node_a.node.handle_funding_signed(node_b.node.get_our_node_id(), &bs_funding_signed); { let mut added_monitors = node_a.chain_monitor.added_monitors.lock().unwrap(); @@ -290,7 +379,14 @@ fn test_manager_serialize_deserialize_events() { // Start the de/seriailization process mid-channel creation to check that the channel manager will hold onto events that are serialized let chan_0_monitor_serialized = get_monitor!(nodes[0], bs_funding_signed.channel_id).encode(); - reload_node!(nodes[0], nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + nodes[0].node.encode(), + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); @@ -298,18 +394,39 @@ fn test_manager_serialize_deserialize_events() { let events_4 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_4.len(), 0); assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); - assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].compute_txid(), funding_output.txid); + assert_eq!( + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].compute_txid(), + funding_output.txid + ); // Make sure the channel is functioning as though the de/serialization never happened assert_eq!(nodes[0].node.list_channels().len(), 1); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); @@ -317,11 +434,16 @@ fn test_manager_serialize_deserialize_events() { nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - let (channel_ready, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); - let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); + let (channel_ready, _) = + create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); + let (announcement, as_update, bs_update) = + create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); for (i, node) in nodes.iter().enumerate() { let counterparty_node_id = nodes[(i + 1) % 2].node.get_our_node_id(); - assert!(node.gossip_sync.handle_channel_announcement(Some(counterparty_node_id), &announcement).unwrap()); + assert!(node + .gossip_sync + .handle_channel_announcement(Some(counterparty_node_id), &announcement) + .unwrap()); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &as_update).unwrap(); node.gossip_sync.handle_channel_update(Some(counterparty_node_id), &bs_update).unwrap(); } @@ -347,7 +469,14 @@ fn test_simple_manager_serialize_deserialize() { nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - reload_node!(nodes[0], nodes[0].node.encode(), &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + nodes[0].node.encode(), + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); @@ -401,14 +530,24 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { fee_estimator = test_utils::TestFeeEstimator::new(253); persister = test_utils::TestPersister::new(); let keys_manager = &chanmon_cfgs[0].keys_manager; - new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster, &logger, &fee_estimator, &persister, keys_manager); + new_chain_monitor = test_utils::TestChainMonitor::new( + Some(nodes[0].chain_source), + nodes[0].tx_broadcaster, + &logger, + &fee_estimator, + &persister, + keys_manager, + ); nodes[0].chain_monitor = &new_chain_monitor; - let mut node_0_stale_monitors = Vec::new(); for serialized in node_0_stale_monitors_serialized.iter() { let mut read = &serialized[..]; - let (_, monitor) = <(BlockHash, ChannelMonitor)>::read(&mut read, (keys_manager, keys_manager)).unwrap(); + let (_, monitor) = <(BlockHash, ChannelMonitor)>::read( + &mut read, + (keys_manager, keys_manager), + ) + .unwrap(); assert!(read.is_empty()); node_0_stale_monitors.push(monitor); } @@ -416,56 +555,107 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let mut node_0_monitors = Vec::new(); for serialized in node_0_monitors_serialized.iter() { let mut read = &serialized[..]; - let (_, monitor) = <(BlockHash, ChannelMonitor)>::read(&mut read, (keys_manager, keys_manager)).unwrap(); + let (_, monitor) = <(BlockHash, ChannelMonitor)>::read( + &mut read, + (keys_manager, keys_manager), + ) + .unwrap(); assert!(read.is_empty()); node_0_monitors.push(monitor); } let mut nodes_0_read = &nodes_0_serialized[..]; - if let Err(msgs::DecodeError::DangerousValue) = - <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestMessageRouter, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs { - default_config: UserConfig::default(), - entropy_source: keys_manager, - node_signer: keys_manager, - signer_provider: keys_manager, - fee_estimator: &fee_estimator, - router: &nodes[0].router, - message_router: &nodes[0].message_router, - chain_monitor: nodes[0].chain_monitor, - tx_broadcaster: nodes[0].tx_broadcaster, - logger: &logger, - channel_monitors: node_0_stale_monitors.iter().map(|monitor| { (monitor.channel_id(), monitor) }).collect(), - }) { } else { + if let Err(msgs::DecodeError::DangerousValue) = <( + BlockHash, + ChannelManager< + &test_utils::TestChainMonitor, + &test_utils::TestBroadcaster, + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestFeeEstimator, + &test_utils::TestRouter, + &test_utils::TestMessageRouter, + &test_utils::TestLogger, + >, + )>::read( + &mut nodes_0_read, + ChannelManagerReadArgs { + default_config: UserConfig::default(), + entropy_source: keys_manager, + node_signer: keys_manager, + signer_provider: keys_manager, + fee_estimator: &fee_estimator, + router: &nodes[0].router, + message_router: &nodes[0].message_router, + chain_monitor: nodes[0].chain_monitor, + tx_broadcaster: nodes[0].tx_broadcaster, + logger: &logger, + channel_monitors: node_0_stale_monitors + .iter() + .map(|monitor| (monitor.channel_id(), monitor)) + .collect(), + }, + ) { + } else { panic!("If the monitor(s) are stale, this indicates a bug and we should get an Err return"); }; let mut nodes_0_read = &nodes_0_serialized[..]; - let (_, nodes_0_deserialized_tmp) = - <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestMessageRouter, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs { - default_config: UserConfig::default(), - entropy_source: keys_manager, - node_signer: keys_manager, - signer_provider: keys_manager, - fee_estimator: &fee_estimator, - router: nodes[0].router, - message_router: &nodes[0].message_router, - chain_monitor: nodes[0].chain_monitor, - tx_broadcaster: nodes[0].tx_broadcaster, - logger: &logger, - channel_monitors: node_0_monitors.iter().map(|monitor| { (monitor.channel_id(), monitor) }).collect(), - }).unwrap(); + let (_, nodes_0_deserialized_tmp) = <( + BlockHash, + ChannelManager< + &test_utils::TestChainMonitor, + &test_utils::TestBroadcaster, + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestFeeEstimator, + &test_utils::TestRouter, + &test_utils::TestMessageRouter, + &test_utils::TestLogger, + >, + )>::read( + &mut nodes_0_read, + ChannelManagerReadArgs { + default_config: UserConfig::default(), + entropy_source: keys_manager, + node_signer: keys_manager, + signer_provider: keys_manager, + fee_estimator: &fee_estimator, + router: nodes[0].router, + message_router: &nodes[0].message_router, + chain_monitor: nodes[0].chain_monitor, + tx_broadcaster: nodes[0].tx_broadcaster, + logger: &logger, + channel_monitors: node_0_monitors + .iter() + .map(|monitor| (monitor.channel_id(), monitor)) + .collect(), + }, + ) + .unwrap(); nodes_0_deserialized = nodes_0_deserialized_tmp; assert!(nodes_0_read.is_empty()); for monitor in node_0_monitors.drain(..) { - assert_eq!(nodes[0].chain_monitor.watch_channel(monitor.channel_id(), monitor), - Ok(ChannelMonitorUpdateStatus::Completed)); + assert_eq!( + nodes[0].chain_monitor.watch_channel(monitor.channel_id(), monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); check_added_monitors!(nodes[0], 1); } nodes[0].node = &nodes_0_deserialized; - check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager, [nodes[3].node.get_our_node_id()], 100000); - { // Channel close should result in a commitment tx + check_closed_event!( + nodes[0], + 1, + ClosureReason::OutdatedChannelManager, + [nodes[3].node.get_our_node_id()], + 100000 + ); + { + // Channel close should result in a commitment tx nodes[0].node.timer_tick_occurred(); let txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(txn.len(), 1); @@ -480,13 +670,31 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { //... and we can even still claim the payment! claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage); - nodes[3].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[3] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish = get_chan_reestablish_msgs!(nodes[3], nodes[0]).pop().unwrap(); - nodes[0].node.peer_connected(nodes[3].node.get_our_node_id(), &msgs::Init { - features: nodes[3].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[3].node.get_our_node_id(), + &msgs::Init { + features: nodes[3].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); nodes[0].node.handle_channel_reestablish(nodes[3].node.get_our_node_id(), &reestablish); let mut found_err = false; for msg_event in nodes[0].node.get_and_clear_pending_msg_events() { @@ -536,14 +744,29 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, // Previously, we'd only hit the data_loss_protect assertion if we had a state which // revoked at least two revocations ago, not the latest revocation. Here, we use // `not_stale` to test the boundary condition. - let pay_params = PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(), 100, false); + let pay_params = + PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(), 100, false); let route_params = RouteParameters::from_payment_params_and_value(pay_params, 40000); - nodes[0].node.send_spontaneous_payment(None, RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + None, + RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let update_add_commit = SendEvent::from_node(&nodes[0]); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &update_add_commit.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &update_add_commit.commitment_msg); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &update_add_commit.msgs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &update_add_commit.commitment_msg, + ); check_added_monitors(&nodes[1], 1); let (raa, cs) = get_revoke_commit_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); @@ -554,7 +777,11 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, nodes[0].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &cs); check_added_monitors(&nodes[0], 1); // A now revokes their original state, at which point reconnect should panic - let raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); + let raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &raa); check_added_monitors(&nodes[1], 1); expect_pending_htlcs_forwardable_ignore!(nodes[1]); @@ -567,21 +794,48 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - reload_node!(nodes[0], previous_node_state, &[&previous_chain_monitor_state], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + previous_node_state, + &[&previous_chain_monitor_state], + persister, + new_chain_monitor, + nodes_0_deserialized + ); if reconnect_panicing { - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); // If A has fallen behind substantially, B should send it a message letting it know // that. - nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); + nodes[1] + .node + .handle_channel_reestablish(nodes[0].node.get_our_node_id(), &reestablish_1[0]); let reestablish_msg; if substantially_old { let warn_msg = "Peer attempted to reestablish channel with a very old local commitment transaction: 0 (received) vs 4 (expected)".to_owned(); @@ -589,7 +843,10 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, let warn_reestablish = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(warn_reestablish.len(), 2); match warn_reestablish[1] { - MessageSendEvent::HandleError { action: ErrorAction::SendWarningMessage { ref msg, .. }, .. } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendWarningMessage { ref msg, .. }, + .. + } => { assert_eq!(msg.data, warn_msg); }, _ => panic!("Unexpected events: {:?}", warn_reestablish), @@ -605,7 +862,9 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, Some(MessageSendEvent::SendChannelUpdate { .. }) => {}, _ => panic!("Unexpected events: {:?}", msgs), } - assert!(msgs.iter().any(|msg| matches!(msg, MessageSendEvent::SendRevokeAndACK { .. }))); + assert!(msgs + .iter() + .any(|msg| matches!(msg, MessageSendEvent::SendRevokeAndACK { .. }))); assert!(msgs.iter().any(|msg| matches!(msg, MessageSendEvent::UpdateHTLCs { .. }))); reestablish_msg = match &msgs[0] { MessageSendEvent::SendChannelReestablish { msg, .. } => msg.clone(), @@ -621,7 +880,9 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, // Check A panics upon seeing proof it has fallen behind. let reconnect_res = std::panic::catch_unwind(|| { - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_msg); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_msg); }); if not_stale { assert!(reconnect_res.is_ok()); @@ -641,9 +902,22 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, let error_message = "Channel force-closed"; assert!(!not_stale, "We only care about the stale case when not testing panicking"); - nodes[0].node.force_close_without_broadcasting_txn(&chan.2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_without_broadcasting_txn( + &chan.2, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + [nodes[1].node.get_our_node_id()], + 1000000 + ); { let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 0); @@ -666,17 +940,39 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, // after the warning message sent by B, we should not able to // use the channel, or reconnect with success to the channel. assert!(nodes[0].node.list_usable_channels().is_empty()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let retry_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &retry_reestablish[0]); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &retry_reestablish[0]); let mut err_msgs_0 = Vec::with_capacity(1); - if let MessageSendEvent::HandleError { ref action, .. } = nodes[0].node.get_and_clear_pending_msg_events()[1] { + if let MessageSendEvent::HandleError { ref action, .. } = + nodes[0].node.get_and_clear_pending_msg_events()[1] + { match action { &ErrorAction::SendErrorMessage { ref msg } => { assert_eq!(msg.data, format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", &nodes[1].node.get_our_node_id())); @@ -725,9 +1021,17 @@ fn test_forwardable_regen() { let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2).2; // First send a payment to nodes[1] - let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + let (route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -739,9 +1043,17 @@ fn test_forwardable_regen() { expect_pending_htlcs_forwardable_ignore!(nodes[1]); // Next send a payment which is forwarded by nodes[1] - let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], 200_000); - nodes[0].node.send_payment_with_route(route_2, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = + get_route_and_payment_hash!(nodes[0], nodes[2], 200_000); + nodes[0] + .node + .send_payment_with_route( + route_2, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -756,7 +1068,14 @@ fn test_forwardable_regen() { let chan_0_monitor_serialized = get_monitor!(nodes[1], chan_id_1).encode(); let chan_1_monitor_serialized = get_monitor!(nodes[1], chan_id_2).encode(); - reload_node!(nodes[1], nodes[1].node.encode(), &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + nodes[1].node.encode(), + &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], + persister, + new_chain_monitor, + nodes_1_deserialized + ); reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); // Note that nodes[1] and nodes[2] resend their channel_ready here since they haven't updated @@ -809,33 +1128,64 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0); - let chan_id_persisted = create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0).2; - let chan_id_not_persisted = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0).2; + let chan_id_persisted = + create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0).2; + let chan_id_not_persisted = + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0).2; // Create an MPP route for 15k sats, more than the default htlc-max of 10% - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 15_000_000); + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[3], 15_000_000); assert_eq!(route.paths.len(), 2); route.paths.sort_by(|path_a, _| { // Sort the path so that the path through nodes[1] comes first if path_a.hops[0].pubkey == nodes[1].node.get_our_node_id() { - core::cmp::Ordering::Less } else { core::cmp::Ordering::Greater } + core::cmp::Ordering::Less + } else { + core::cmp::Ordering::Greater + } }); - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); // Send the payment through to nodes[3] *without* clearing the PaymentClaimable event let mut send_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(send_events.len(), 2); - let node_1_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut send_events); - let node_2_msgs = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut send_events); - do_pass_along_path(PassAlongPathArgs::new(&nodes[0],&[&nodes[1], &nodes[3]], 15_000_000, payment_hash, node_1_msgs) + let node_1_msgs = + remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut send_events); + let node_2_msgs = + remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut send_events); + do_pass_along_path( + PassAlongPathArgs::new( + &nodes[0], + &[&nodes[1], &nodes[3]], + 15_000_000, + payment_hash, + node_1_msgs, + ) .with_payment_secret(payment_secret) - .without_clearing_recipient_events()); - do_pass_along_path(PassAlongPathArgs::new(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, payment_hash, node_2_msgs) + .without_clearing_recipient_events(), + ); + do_pass_along_path( + PassAlongPathArgs::new( + &nodes[0], + &[&nodes[2], &nodes[3]], + 15_000_000, + payment_hash, + node_2_msgs, + ) .with_payment_secret(payment_secret) - .without_clearing_recipient_events()); + .without_clearing_recipient_events(), + ); // Now that we have an MPP payment pending, get the latest encoded copies of nodes[3]'s // monitors and ChannelManager, for use later, if we don't want to persist both monitors. @@ -844,7 +1194,13 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { for channel_id in nodes[3].chain_monitor.chain_monitor.list_monitors() { if channel_id == chan_id_not_persisted { assert!(original_monitor.0.is_empty()); - nodes[3].chain_monitor.chain_monitor.get_monitor(channel_id).unwrap().write(&mut original_monitor).unwrap(); + nodes[3] + .chain_monitor + .chain_monitor + .get_monitor(channel_id) + .unwrap() + .write(&mut original_monitor) + .unwrap(); } } } @@ -864,7 +1220,13 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { for channel_id in nodes[3].chain_monitor.chain_monitor.list_monitors() { if channel_id == chan_id_persisted { assert!(updated_monitor.0.is_empty()); - nodes[3].chain_monitor.chain_monitor.get_monitor(channel_id).unwrap().write(&mut updated_monitor).unwrap(); + nodes[3] + .chain_monitor + .chain_monitor + .get_monitor(channel_id) + .unwrap() + .write(&mut updated_monitor) + .unwrap(); } } // If `persist_both_monitors` is set, get the second monitor here as well @@ -872,19 +1234,36 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { for channel_id in nodes[3].chain_monitor.chain_monitor.list_monitors() { if channel_id == chan_id_not_persisted { assert!(original_monitor.0.is_empty()); - nodes[3].chain_monitor.chain_monitor.get_monitor(channel_id).unwrap().write(&mut original_monitor).unwrap(); + nodes[3] + .chain_monitor + .chain_monitor + .get_monitor(channel_id) + .unwrap() + .write(&mut original_monitor) + .unwrap(); } } } // Now restart nodes[3]. - reload_node!(nodes[3], original_manager, &[&updated_monitor.0, &original_monitor.0], persister, new_chain_monitor, nodes_3_deserialized); + reload_node!( + nodes[3], + original_manager, + &[&updated_monitor.0, &original_monitor.0], + persister, + new_chain_monitor, + nodes_3_deserialized + ); // Until the startup background events are processed (in `get_and_clear_pending_events`, // below), the preimage is not copied to the non-persisted monitor... - assert!(get_monitor!(nodes[3], chan_id_persisted).get_stored_preimages().contains_key(&payment_hash)); + assert!(get_monitor!(nodes[3], chan_id_persisted) + .get_stored_preimages() + .contains_key(&payment_hash)); assert_eq!( - get_monitor!(nodes[3], chan_id_not_persisted).get_stored_preimages().contains_key(&payment_hash), + get_monitor!(nodes[3], chan_id_not_persisted) + .get_stored_preimages() + .contains_key(&payment_hash), persist_both_monitors, ); @@ -897,69 +1276,134 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { // preimage onto the non-persisted monitor. let events = nodes[3].node.get_and_clear_pending_events(); assert_eq!(events.len(), if persist_both_monitors { 4 } else { 3 }); - if let Event::PaymentClaimable { amount_msat: 15_000_000, .. } = events[0] { } else { panic!(); } - if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[1] { } else { panic!(); } + if let Event::PaymentClaimable { amount_msat: 15_000_000, .. } = events[0] { + } else { + panic!(); + } + if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[1] { + } else { + panic!(); + } if persist_both_monitors { - if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = events[2] { } else { panic!(); } - if let Event::PaymentClaimed { amount_msat: 15_000_000, .. } = events[3] { } else { panic!(); } + if let Event::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = + events[2] + { + } else { + panic!(); + } + if let Event::PaymentClaimed { amount_msat: 15_000_000, .. } = events[3] { + } else { + panic!(); + } check_added_monitors(&nodes[3], 4); } else { - if let Event::PaymentClaimed { amount_msat: 15_000_000, .. } = events[2] { } else { panic!(); } + if let Event::PaymentClaimed { amount_msat: 15_000_000, .. } = events[2] { + } else { + panic!(); + } check_added_monitors(&nodes[3], 3); } // Now that we've processed background events, the preimage should have been copied into the // non-persisted monitor: - assert!(get_monitor!(nodes[3], chan_id_persisted).get_stored_preimages().contains_key(&payment_hash)); - assert!(get_monitor!(nodes[3], chan_id_not_persisted).get_stored_preimages().contains_key(&payment_hash)); + assert!(get_monitor!(nodes[3], chan_id_persisted) + .get_stored_preimages() + .contains_key(&payment_hash)); + assert!(get_monitor!(nodes[3], chan_id_not_persisted) + .get_stored_preimages() + .contains_key(&payment_hash)); // On restart, we should also get a duplicate PaymentClaimed event as we persisted the // ChannelManager prior to handling the original one. - if let Event::PaymentClaimed { payment_hash: our_payment_hash, amount_msat: 15_000_000, .. } = - events[if persist_both_monitors { 3 } else { 2 }] + if let Event::PaymentClaimed { + payment_hash: our_payment_hash, amount_msat: 15_000_000, .. + } = events[if persist_both_monitors { 3 } else { 2 }] { assert_eq!(payment_hash, our_payment_hash); - } else { panic!(); } + } else { + panic!(); + } assert_eq!(nodes[3].node.list_channels().len(), if persist_both_monitors { 0 } else { 1 }); if !persist_both_monitors { // If one of the two channels is still live, reveal the payment preimage over it. - nodes[3].node.peer_connected(nodes[2].node.get_our_node_id(), &msgs::Init { - features: nodes[2].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[3] + .node + .peer_connected( + nodes[2].node.get_our_node_id(), + &msgs::Init { + features: nodes[2].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[3], nodes[2]); - nodes[2].node.peer_connected(nodes[3].node.get_our_node_id(), &msgs::Init { - features: nodes[3].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[2] + .node + .peer_connected( + nodes[3].node.get_our_node_id(), + &msgs::Init { + features: nodes[3].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[2], nodes[3]); - nodes[2].node.handle_channel_reestablish(nodes[3].node.get_our_node_id(), &reestablish_1[0]); - get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[3].node.get_our_node_id()); + nodes[2] + .node + .handle_channel_reestablish(nodes[3].node.get_our_node_id(), &reestablish_1[0]); + get_event_msg!( + nodes[2], + MessageSendEvent::SendChannelUpdate, + nodes[3].node.get_our_node_id() + ); assert!(nodes[2].node.get_and_clear_pending_msg_events().is_empty()); - nodes[3].node.handle_channel_reestablish(nodes[2].node.get_our_node_id(), &reestablish_2[0]); + nodes[3] + .node + .handle_channel_reestablish(nodes[2].node.get_our_node_id(), &reestablish_2[0]); // Once we call `get_and_clear_pending_msg_events` the holding cell is cleared and the HTLC // claim should fly. let ds_msgs = nodes[3].node.get_and_clear_pending_msg_events(); check_added_monitors!(nodes[3], 1); assert_eq!(ds_msgs.len(), 2); - if let MessageSendEvent::SendChannelUpdate { .. } = ds_msgs[0] {} else { panic!(); } + if let MessageSendEvent::SendChannelUpdate { .. } = ds_msgs[0] { + } else { + panic!(); + } let cs_updates = match ds_msgs[1] { MessageSendEvent::UpdateHTLCs { ref updates, .. } => { - nodes[2].node.handle_update_fulfill_htlc(nodes[3].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[2].node.handle_update_fulfill_htlc( + nodes[3].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); check_added_monitors!(nodes[2], 1); let cs_updates = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); expect_payment_forwarded!(nodes[2], nodes[0], nodes[3], Some(1000), false, false); - commitment_signed_dance!(nodes[2], nodes[3], updates.commitment_signed, false, true); + commitment_signed_dance!( + nodes[2], + nodes[3], + updates.commitment_signed, + false, + true + ); cs_updates - } + }, _ => panic!(), }; - nodes[0].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &cs_updates.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[2], cs_updates.commitment_signed, false, true); expect_payment_sent!(nodes[0], payment_preimage); @@ -967,7 +1411,9 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { // cycle of commitment updates the payment preimage is ultimately pruned). nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); send_payment(&nodes[0], &[&nodes[2], &nodes[3]], 100_000); - assert!(!get_monitor!(nodes[3], chan_id_not_persisted).get_stored_preimages().contains_key(&payment_hash)); + assert!(!get_monitor!(nodes[3], chan_id_not_persisted) + .get_stored_preimages() + .contains_key(&payment_hash)); } } @@ -977,8 +1423,12 @@ fn test_partial_claim_before_restart() { do_test_partial_claim_before_restart(true); } -fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_htlc: bool, use_intercept: bool) { - if !use_cs_commitment { assert!(!claim_htlc); } +fn do_forwarded_payment_no_manager_persistence( + use_cs_commitment: bool, claim_htlc: bool, use_intercept: bool, +) { + if !use_cs_commitment { + assert!(!claim_htlc); + } // If we go to forward a payment, and the ChannelMonitor persistence completes, but the // ChannelManager does not, we shouldn't try to forward the payment again, nor should we fail // it back until the ChannelMonitor decides the fate of the HTLC. @@ -990,7 +1440,8 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht let mut intercept_forwards_config = test_default_channel_config(); intercept_forwards_config.accept_intercept_htlcs = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), None]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), None]); let nodes_1_deserialized; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); @@ -1007,8 +1458,15 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht } let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); let htlc_expiry = nodes[0].best_block_info().1 + TEST_FINAL_CLTV; - nodes[0].node.send_payment_with_route(route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id).unwrap(); + nodes[0] + .node + .send_payment_with_route( + route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let payment_event = SendEvent::from_node(&nodes[0]); @@ -1029,27 +1487,44 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht let events = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::HTLCIntercepted { intercept_id: ev_id, expected_outbound_amount_msat: ev_amt, .. } => { + Event::HTLCIntercepted { + intercept_id: ev_id, + expected_outbound_amount_msat: ev_amt, + .. + } => { intercept_id = Some(ev_id); expected_outbound_amount_msat = Some(ev_amt); }, - _ => panic!() + _ => panic!(), } - nodes[1].node.forward_intercepted_htlc(intercept_id.unwrap(), &chan_id_2, - nodes[2].node.get_our_node_id(), expected_outbound_amount_msat.unwrap()).unwrap(); + nodes[1] + .node + .forward_intercepted_htlc( + intercept_id.unwrap(), + &chan_id_2, + nodes[2].node.get_our_node_id(), + expected_outbound_amount_msat.unwrap(), + ) + .unwrap(); } nodes[1].node.process_pending_htlc_forwards(); let payment_event = SendEvent::from_node(&nodes[1]); nodes[2].node.handle_update_add_htlc(nodes[1].node.get_our_node_id(), &payment_event.msgs[0]); - nodes[2].node.handle_commitment_signed_batch_test(nodes[1].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[2].node.handle_commitment_signed_batch_test( + nodes[1].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors!(nodes[2], 1); if claim_htlc { get_monitor!(nodes[2], chan_id_2).provide_payment_preimage_unsafe_legacy( - &payment_hash, &payment_preimage, &nodes[2].tx_broadcaster, - &LowerBoundedFeeEstimator(nodes[2].fee_estimator), &nodes[2].logger + &payment_hash, + &payment_preimage, + &nodes[2].tx_broadcaster, + &LowerBoundedFeeEstimator(nodes[2].fee_estimator), + &nodes[2].logger, ); } assert!(nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty()); @@ -1057,30 +1532,69 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht let _ = nodes[2].node.get_and_clear_pending_msg_events(); let error_message = "Channel force-closed"; - nodes[2].node.force_close_broadcasting_latest_txn(&chan_id_2, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[2] + .node + .force_close_broadcasting_latest_txn( + &chan_id_2, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); let cs_commitment_tx = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(cs_commitment_tx.len(), if claim_htlc { 2 } else { 1 }); check_added_monitors!(nodes[2], 1); - check_closed_event!(nodes[2], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[1].node.get_our_node_id()], + 100000 + ); check_closed_broadcast!(nodes[2], true); let chan_0_monitor_serialized = get_monitor!(nodes[1], chan_id_1).encode(); let chan_1_monitor_serialized = get_monitor!(nodes[1], chan_id_2).encode(); - reload_node!(nodes[1], node_encoded, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + node_encoded, + &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], + persister, + new_chain_monitor, + nodes_1_deserialized + ); // Note that this checks that this is the only event on nodes[1], implying the // `HTLCIntercepted` event has been removed in the `use_intercept` case. - check_closed_event!(nodes[1], 1, ClosureReason::OutdatedChannelManager, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::OutdatedChannelManager, + [nodes[2].node.get_our_node_id()], + 100000 + ); if use_intercept { // Attempt to forward the HTLC back out over nodes[1]' still-open channel, ensuring we get // a intercept-doesn't-exist error. - let forward_err = nodes[1].node.forward_intercepted_htlc(intercept_id.unwrap(), &chan_id_1, - nodes[0].node.get_our_node_id(), expected_outbound_amount_msat.unwrap()).unwrap_err(); - assert_eq!(forward_err, APIError::APIMisuseError { - err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.unwrap().0)) - }); + let forward_err = nodes[1] + .node + .forward_intercepted_htlc( + intercept_id.unwrap(), + &chan_id_1, + nodes[0].node.get_our_node_id(), + expected_outbound_amount_msat.unwrap(), + ) + .unwrap_err(); + assert_eq!( + forward_err, + APIError::APIMisuseError { + err: format!( + "Payment with intercept id {} not found", + log_bytes!(intercept_id.unwrap().0) + ) + } + ); } nodes[1].node.timer_tick_occurred(); @@ -1103,7 +1617,10 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht } else { connect_blocks(&nodes[1], htlc_expiry - nodes[1].best_block_info().1 + 1); let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); - assert_eq!(txn.len(), if nodes[1].connect_style.borrow().updates_best_block_first() { 2 } else { 1 }); + assert_eq!( + txn.len(), + if nodes[1].connect_style.borrow().updates_best_block_first() { 2 } else { 1 } + ); let bs_htlc_timeout_tx = txn.pop().unwrap(); confirm_transaction(&nodes[1], &bs_htlc_timeout_tx); } @@ -1112,7 +1629,13 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht } if !claim_htlc { - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + [HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] + ); } else { expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, true); } @@ -1121,11 +1644,26 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match &events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { update_fulfill_htlcs, update_fail_htlcs, commitment_signed, .. }, .. } => { + MessageSendEvent::UpdateHTLCs { + updates: + msgs::CommitmentUpdate { + update_fulfill_htlcs, + update_fail_htlcs, + commitment_signed, + .. + }, + .. + } => { if claim_htlc { - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &update_fulfill_htlcs[0], + ); } else { - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &update_fail_htlcs[0], + ); } commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false); }, @@ -1178,13 +1716,21 @@ fn removed_payment_no_manager_persistence() { let node_encoded = nodes[1].node.encode(); nodes[2].node.fail_htlc_backwards(&payment_hash); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], [HTLCDestination::FailedPayment { payment_hash }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[2], + [HTLCDestination::FailedPayment { payment_hash }] + ); check_added_monitors!(nodes[2], 1); let events = nodes[2].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match &events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. }, .. } => { - nodes[1].node.handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &update_fail_htlcs[0]); + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. }, + .. + } => { + nodes[1] + .node + .handle_update_fail_htlc(nodes[2].node.get_our_node_id(), &update_fail_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[2], commitment_signed, false); }, _ => panic!("Unexpected event"), @@ -1192,7 +1738,14 @@ fn removed_payment_no_manager_persistence() { let chan_0_monitor_serialized = get_monitor!(nodes[1], chan_id_1).encode(); let chan_1_monitor_serialized = get_monitor!(nodes[1], chan_id_2).encode(); - reload_node!(nodes[1], node_encoded, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized); + reload_node!( + nodes[1], + node_encoded, + &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], + persister, + new_chain_monitor, + nodes_1_deserialized + ); match nodes[1].node.pop_pending_event().unwrap() { Event::ChannelClosed { ref reason, .. } => { @@ -1210,13 +1763,24 @@ fn removed_payment_no_manager_persistence() { nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + [HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }] + ); check_added_monitors!(nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match &events[0] { - MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. }, .. } => { - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); + MessageSendEvent::UpdateHTLCs { + updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. }, + .. + } => { + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false); }, _ => panic!("Unexpected event"), @@ -1237,10 +1801,10 @@ fn test_reload_partial_funding_batch() { let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Initiate channel opening and create the batch channel funding transaction. - let (tx, funding_created_msgs) = create_batch_channel_funding(&nodes[0], &[ - (&nodes[1], 100_000, 0, 42, None), - (&nodes[2], 200_000, 0, 43, None), - ]); + let (tx, funding_created_msgs) = create_batch_channel_funding( + &nodes[0], + &[(&nodes[1], 100_000, 0, 42, None), (&nodes[2], 200_000, 0, 43, None)], + ); // Go through the funding_created and funding_signed flow with node 1. nodes[1].node.handle_funding_created(nodes[0].node.get_our_node_id(), &funding_created_msgs[0]); @@ -1248,7 +1812,11 @@ fn test_reload_partial_funding_batch() { expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); // The monitor is persisted when receiving funding_signed. - let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!( + nodes[1], + MessageSendEvent::SendFundingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_signed(nodes[1].node.get_our_node_id(), &funding_signed_msg); check_added_monitors(&nodes[0], 1); @@ -1256,10 +1824,18 @@ fn test_reload_partial_funding_batch() { assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0); // Reload the node while a subset of the channels in the funding batch have persisted monitors. - let channel_id_1 = ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 0 }); + let channel_id_1 = + ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 0 }); let node_encoded = nodes[0].node.encode(); let channel_monitor_1_serialized = get_monitor!(nodes[0], channel_id_1).encode(); - reload_node!(nodes[0], node_encoded, &[&channel_monitor_1_serialized], new_persister, new_chain_monitor, new_channel_manager); + reload_node!( + nodes[0], + node_encoded, + &[&channel_monitor_1_serialized], + new_persister, + new_chain_monitor, + new_channel_manager + ); // Process monitor events. assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); @@ -1271,7 +1847,10 @@ fn test_reload_partial_funding_batch() { let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap(); assert_eq!(monitor_updates_1.len(), 1); assert_eq!(monitor_updates_1[0].updates.len(), 1); - assert!(matches!(monitor_updates_1[0].updates[0], ChannelMonitorUpdateStep::ChannelForceClosed { .. })); + assert!(matches!( + monitor_updates_1[0].updates[0], + ChannelMonitorUpdateStep::ChannelForceClosed { .. } + )); } // The funding transaction should not have been broadcast, but we broadcast the force-close @@ -1307,24 +1886,46 @@ fn test_htlc_localremoved_persistence() { let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]); let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::for_keysend(payee_pubkey, 40, false), 10_000); - let route = find_route( - &nodes[0], &route_params - ).unwrap(); + PaymentParameters::for_keysend(payee_pubkey, 40, false), + 10_000, + ); + let route = find_route(&nodes[0], &route_params).unwrap(); let test_preimage = PaymentPreimage([42; 32]); let mismatch_payment_hash = PaymentHash([43; 32]); - let session_privs = nodes[0].node.test_add_new_pending_payment(mismatch_payment_hash, - RecipientOnionFields::spontaneous_empty(), PaymentId(mismatch_payment_hash.0), &route).unwrap(); - nodes[0].node.test_send_payment_internal(&route, mismatch_payment_hash, - RecipientOnionFields::spontaneous_empty(), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap(); + let session_privs = nodes[0] + .node + .test_add_new_pending_payment( + mismatch_payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(mismatch_payment_hash.0), + &route, + ) + .unwrap(); + nodes[0] + .node + .test_send_payment_internal( + &route, + mismatch_payment_hash, + RecipientOnionFields::spontaneous_empty(), + Some(test_preimage), + PaymentId(mismatch_payment_hash.0), + None, + session_privs, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); commitment_signed_dance!(nodes[1], nodes[0], &updates.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[1]); - expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash: mismatch_payment_hash }]); + expect_htlc_handling_failed_destinations!( + nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::FailedPayment { payment_hash: mismatch_payment_hash }] + ); check_added_monitors(&nodes[1], 1); // Save the update_fail_htlc message for later comparison. @@ -1336,16 +1937,41 @@ fn test_htlc_localremoved_persistence() { nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); let monitor_encoded = get_monitor!(nodes[1], _chan.3).encode(); - reload_node!(nodes[1], nodes[1].node.encode(), &[&monitor_encoded], persister, chain_monitor, deserialized_chanmgr); + reload_node!( + nodes[1], + nodes[1].node.encode(), + &[&monitor_encoded], + persister, + chain_monitor, + deserialized_chanmgr + ); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]); assert_eq!(reestablish_1.len(), 1); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]); assert_eq!(reestablish_2.len(), 1); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &reestablish_2[0]); diff --git a/lightning/src/ln/reorg_tests.rs b/lightning/src/ln/reorg_tests.rs index 7c6ac7dffa0..5ad56364a81 100644 --- a/lightning/src/ln/reorg_tests.rs +++ b/lightning/src/ln/reorg_tests.rs @@ -13,15 +13,15 @@ use crate::chain::chaininterface::LowerBoundedFeeEstimator; use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS}; use crate::chain::transaction::OutPoint; use crate::chain::Confirm; -use crate::events::{Event, ClosureReason, HTLCDestination}; +use crate::events::{ClosureReason, Event, HTLCDestination}; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, Init, MessageSendEvent}; use crate::ln::types::ChannelId; use crate::sign::OutputSpender; use crate::util::ser::Writeable; use crate::util::string::UntrustedString; -use bitcoin::script::Builder; use bitcoin::opcodes; +use bitcoin::script::Builder; use bitcoin::secp256k1::Secp256k1; use crate::prelude::*; @@ -53,11 +53,12 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) { let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); // Make sure all nodes are at the same starting height - connect_blocks(&nodes[0], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); - connect_blocks(&nodes[1], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); - connect_blocks(&nodes[2], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); + connect_blocks(&nodes[0], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1); + connect_blocks(&nodes[1], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1); + connect_blocks(&nodes[2], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1); - let (our_payment_preimage, our_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); + let (our_payment_preimage, our_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000); // Provide preimage to node 2 by claiming payment nodes[2].node.claim_funds(our_payment_preimage); @@ -74,18 +75,31 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) { check_spends!(node_1_commitment_txn[1], node_1_commitment_txn[0]); // Give node 2 node 1's transactions and get its response (claiming the HTLC instead). - connect_block(&nodes[2], &create_dummy_block(nodes[2].best_block_hash(), 42, node_1_commitment_txn.clone())); + connect_block( + &nodes[2], + &create_dummy_block(nodes[2].best_block_hash(), 42, node_1_commitment_txn.clone()), + ); check_added_monitors!(nodes[2], 1); check_closed_broadcast!(nodes[2], true); // We should get a BroadcastChannelUpdate (and *only* a BroadcstChannelUpdate) - check_closed_event!(nodes[2], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); - let node_2_commitment_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); + let node_2_commitment_txn = + nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(node_2_commitment_txn.len(), 1); // ChannelMonitor: 1 offered HTLC-Claim check_spends!(node_2_commitment_txn[0], node_1_commitment_txn[0]); // Make sure node 1's height is the same as the !local_commitment case connect_blocks(&nodes[1], 1); // Confirm node 1's commitment txn (and HTLC-Timeout) on node 1 - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, node_1_commitment_txn.clone())); + connect_block( + &nodes[1], + &create_dummy_block(nodes[1].best_block_hash(), 42, node_1_commitment_txn.clone()), + ); // ...but return node 1's commitment tx in case claim is set and we're preparing to reorg vec![node_1_commitment_txn[0].clone(), node_2_commitment_txn[0].clone()] @@ -111,7 +125,13 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) { }; check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); // We should get a BroadcastChannelUpdate (and *only* a BroadcstChannelUpdate) - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[2].node.get_our_node_id()], + 100000 + ); // Connect ANTI_REORG_DELAY - 2 blocks, giving us a confirmation count of ANTI_REORG_DELAY - 1. connect_blocks(&nodes[1], ANTI_REORG_DELAY - 2); check_added_monitors!(nodes[1], 0); @@ -130,7 +150,13 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) { } else { // Confirm the timeout tx and check that we fail the HTLC backwards connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, Vec::new())); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] + ); } check_added_monitors!(nodes[1], 1); @@ -138,16 +164,28 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) { let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); if claim { assert_eq!(htlc_updates.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &htlc_updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &htlc_updates.update_fulfill_htlcs[0], + ); } else { assert_eq!(htlc_updates.update_fail_htlcs.len(), 1); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]); + nodes[0].node.handle_update_fail_htlc( + nodes[1].node.get_our_node_id(), + &htlc_updates.update_fail_htlcs[0], + ); } commitment_signed_dance!(nodes[0], nodes[1], htlc_updates.commitment_signed, false, true); if claim { expect_payment_sent!(nodes[0], our_payment_preimage); } else { - expect_payment_failed_with_update!(nodes[0], our_payment_hash, false, chan_2.0.contents.short_channel_id, true); + expect_payment_failed_with_update!( + nodes[0], + our_payment_hash, + false, + chan_2.0.contents.short_channel_id, + true + ); } } @@ -188,7 +226,8 @@ fn test_counterparty_revoked_reorg() { // Now add two HTLCs in each direction, one dust and one not. route_payment(&nodes[0], &[&nodes[1]], 5_000_000); route_payment(&nodes[0], &[&nodes[1]], 5_000); - let (payment_preimage_3, payment_hash_3, ..) = route_payment(&nodes[1], &[&nodes[0]], 4_000_000); + let (payment_preimage_3, payment_hash_3, ..) = + route_payment(&nodes[1], &[&nodes[0]], 4_000_000); let payment_hash_4 = route_payment(&nodes[1], &[&nodes[0]], 4_000).1; nodes[0].node.claim_funds(payment_preimage_3); @@ -198,14 +237,22 @@ fn test_counterparty_revoked_reorg() { let mut unrevoked_local_txn = get_local_commitment_txn!(nodes[0], chan.2); assert_eq!(unrevoked_local_txn.len(), 3); // commitment + 2 HTLC txn - // Sort the unrevoked transactions in reverse order, ie commitment tx, then HTLC 1 then HTLC 3 - unrevoked_local_txn.sort_unstable_by_key(|tx| 1_000_000 - tx.output.iter().map(|outp| outp.value.to_sat()).sum::()); + // Sort the unrevoked transactions in reverse order, ie commitment tx, then HTLC 1 then HTLC 3 + unrevoked_local_txn.sort_unstable_by_key(|tx| { + 1_000_000 - tx.output.iter().map(|outp| outp.value.to_sat()).sum::() + }); // Now mine A's old commitment transaction, which should close the channel, but take no action // on any of the HTLCs, at least until we get six confirmations (which we won't get). mine_transaction(&nodes[1], &revoked_local_txn[0]); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); check_closed_broadcast!(nodes[1], true); // Connect up to one block before the revoked transaction would be considered final, then do a @@ -239,7 +286,10 @@ fn test_counterparty_revoked_reorg() { expect_payment_failed!(nodes[1], payment_hash_4, false); } -fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_unconfirmed: bool, connect_style: ConnectStyle) { +fn do_test_unconf_chan( + reload_node: bool, reorg_after_reload: bool, use_funding_unconfirmed: bool, + connect_style: ConnectStyle, +) { // After creating a chan between nodes, we disconnect all blocks previously seen to force a // channel close on nodes[0] side. We also use this to provide very basic testing of logic // around freeing background events which store monitor updates during block_[dis]connected. @@ -254,12 +304,14 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_ let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); *nodes[0].connect_style.borrow_mut() = connect_style; - let chan_conf_height = core::cmp::max(nodes[0].best_block_info().1 + 1, nodes[1].best_block_info().1 + 1); + let chan_conf_height = + core::cmp::max(nodes[0].best_block_info().1 + 1, nodes[1].best_block_info().1 + 1); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let peer_state = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let peer_state = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); assert_eq!(peer_state.channel_by_id.len(), 1); assert_eq!(nodes[0].node.short_to_chan_info.read().unwrap().len(), 2); } @@ -301,7 +353,8 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_ { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let peer_state = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let peer_state = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); assert_eq!(peer_state.channel_by_id.len(), 0); assert_eq!(nodes[0].node.short_to_chan_info.read().unwrap().len(), 0); } @@ -317,7 +370,15 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_ let nodes_0_serialized = nodes[0].node.encode(); let chan_0_monitor_serialized = get_monitor!(nodes[0], chan.2).encode(); - reload_node!(nodes[0], nodes[0].node.get_current_default_configuration().clone(), &nodes_0_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); + reload_node!( + nodes[0], + nodes[0].node.get_current_default_configuration().clone(), + &nodes_0_serialized, + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); } if reorg_after_reload { @@ -352,7 +413,8 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_ { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); - let peer_state = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); + let peer_state = + per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); assert_eq!(peer_state.channel_by_id.len(), 0); assert_eq!(nodes[0].node.short_to_chan_info.read().unwrap().len(), 0); } @@ -372,21 +434,45 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_ if reorg_after_reload || !reload_node { handle_announce_close_broadcast_events(&nodes, 0, 1, true, "Channel closed because of an exception: Funding transaction was un-confirmed. Locked at 6 confs, now have 0 confs."); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Channel closed because of an exception: {}", expected_err)) } - , [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyForceClosed { + peer_msg: UntrustedString(format!( + "Channel closed because of an exception: {}", + expected_err + )) + }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } - check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: expected_err.to_owned() }, - [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::ProcessingError { err: expected_err.to_owned() }, + [nodes[1].node.get_our_node_id()], + 100000 + ); // Now check that we can create a new channel if reload_node && nodes[0].node.per_peer_state.read().unwrap().len() == 0 { // If we dropped the channel before reloading the node, nodes[1] was also dropped from // nodes[0] storage, and hence not connected again on startup. We therefore need to // reconnect to the node before attempting to create a new channel. - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); } create_announced_chan_between_nodes(&nodes, 0, 1); send_payment(&nodes[0], &[&nodes[1]], 8000000); @@ -442,8 +528,10 @@ fn test_set_outpoints_partial_claiming() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000); - let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[1], &[&nodes[0]], 3_000_000); - let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[1], &[&nodes[0]], 3_000_000); + let (payment_preimage_1, payment_hash_1, ..) = + route_payment(&nodes[1], &[&nodes[0]], 3_000_000); + let (payment_preimage_2, payment_hash_2, ..) = + route_payment(&nodes[1], &[&nodes[0]], 3_000_000); // Remote commitment txn with 4 outputs: to_local, to_remote, 2 outgoing HTLC let remote_txn = get_local_commitment_txn!(nodes[1], chan.2); @@ -466,7 +554,13 @@ fn test_set_outpoints_partial_claiming() { // Connect blocks on node A commitment transaction mine_transaction(&nodes[0], &remote_txn[0]); check_closed_broadcast!(nodes[0], true); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 1000000 + ); check_added_monitors!(nodes[0], 1); // Verify node A broadcast tx claiming both HTLCs { @@ -481,7 +575,13 @@ fn test_set_outpoints_partial_claiming() { // Connect blocks on node B connect_blocks(&nodes[1], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::HTLCsTimedOut, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HTLCsTimedOut, + [nodes[0].node.get_our_node_id()], + 1000000 + ); check_added_monitors!(nodes[1], 1); // Verify node B broadcast 2 HTLC-timeout txn let partial_claim_tx = { @@ -558,11 +658,23 @@ fn do_test_to_remote_after_local_detection(style: ConnectStyle) { assert!(nodes[0].node.list_channels().is_empty()); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 1000000 + ); assert!(nodes[1].node.list_channels().is_empty()); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[0].node.get_our_node_id()], + 1000000 + ); assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty()); @@ -599,8 +711,18 @@ fn do_test_to_remote_after_local_detection(style: ConnectStyle) { if let Event::SpendableOutputs { outputs, channel_id } = node_a_spendable.pop().unwrap() { assert_eq!(outputs.len(), 1); assert_eq!(channel_id, Some(chan_id)); - let spend_tx = nodes[0].keys_manager.backing.spend_spendable_outputs(&[&outputs[0]], Vec::new(), - Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), 253, None, &Secp256k1::new()).unwrap(); + let spend_tx = nodes[0] + .keys_manager + .backing + .spend_spendable_outputs( + &[&outputs[0]], + Vec::new(), + Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), + 253, + None, + &Secp256k1::new(), + ) + .unwrap(); check_spends!(spend_tx, remote_txn_b[0]); } @@ -620,8 +742,18 @@ fn do_test_to_remote_after_local_detection(style: ConnectStyle) { if let Event::SpendableOutputs { outputs, channel_id } = node_b_spendable.pop().unwrap() { assert_eq!(outputs.len(), 1); assert_eq!(channel_id, Some(chan_id)); - let spend_tx = nodes[1].keys_manager.backing.spend_spendable_outputs(&[&outputs[0]], Vec::new(), - Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), 253, None, &Secp256k1::new()).unwrap(); + let spend_tx = nodes[1] + .keys_manager + .backing + .spend_spendable_outputs( + &[&outputs[0]], + Vec::new(), + Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), + 253, + None, + &Secp256k1::new(), + ) + .unwrap(); check_spends!(spend_tx, remote_txn_a[0]); } } @@ -655,15 +787,43 @@ fn test_htlc_preimage_claim_holder_commitment_after_counterparty_commitment_reor // Force close with the latest counterparty commitment, confirm it, and reorg it with the latest // holder commitment. - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[1].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); - nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); check_added_monitors(&nodes[1], 1); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -690,8 +850,11 @@ fn test_htlc_preimage_claim_holder_commitment_after_counterparty_commitment_reor // Provide the preimage now, such that we only claim from the holder commitment (since it's // currently confirmed) and not the counterparty's. get_monitor!(nodes[1], chan_id).provide_payment_preimage_unsafe_legacy( - &payment_hash, &payment_preimage, &nodes[1].tx_broadcaster, - &LowerBoundedFeeEstimator(nodes[1].fee_estimator), &nodes[1].logger + &payment_hash, + &payment_preimage, + &nodes[1].tx_broadcaster, + &LowerBoundedFeeEstimator(nodes[1].fee_estimator), + &nodes[1].logger, ); let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); @@ -701,7 +864,8 @@ fn test_htlc_preimage_claim_holder_commitment_after_counterparty_commitment_reor } #[test] -fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterparty_commitment_reorg() { +fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterparty_commitment_reorg( +) { // We detect a counterparty commitment confirm onchain, followed by a reorg and a // confirmation of the previous (still unrevoked) counterparty commitment. Then, if we learn // of the preimage for an HTLC in both commitments, test that we only claim the currently @@ -724,24 +888,42 @@ fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterpa check_added_monitors(&nodes[0], 1); let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); - let (update_fee, commit_sig) = if let MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, mut updates } = msg_events.pop().unwrap() { - assert_eq!(node_id, nodes[1].node.get_our_node_id()); - (updates.update_fee.take().unwrap(), updates.commitment_signed) - } else { - panic!("Unexpected message send event"); - }; + let (update_fee, commit_sig) = + if let MessageSendEvent::UpdateHTLCs { node_id, channel_id: _, mut updates } = + msg_events.pop().unwrap() + { + assert_eq!(node_id, nodes[1].node.get_our_node_id()); + (updates.update_fee.take().unwrap(), updates.commitment_signed) + } else { + panic!("Unexpected message send event"); + }; // Handle the fee update on the other side, but don't send the last RAA such that the previous // commitment is still valid (unrevoked). nodes[1].node().handle_update_fee(nodes[0].node.get_our_node_id(), &update_fee); - let _last_revoke_and_ack = commitment_signed_dance!(nodes[1], nodes[0], commit_sig, false, true, false, true); + let _last_revoke_and_ack = + commitment_signed_dance!(nodes[1], nodes[0], commit_sig, false, true, false, true); let error_message = "Channel force-closed"; // Force close with the latest commitment, confirm it, and reorg it with the previous commitment. - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[1].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[1].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -754,7 +936,14 @@ fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterpa check_closed_broadcast(&nodes[1], 1, true); check_added_monitors(&nodes[1], 1); - check_closed_event(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); disconnect_blocks(&nodes[0], 1); disconnect_blocks(&nodes[1], 1); @@ -765,8 +954,11 @@ fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterpa // Provide the preimage now, such that we only claim from the previous commitment (since it's // currently confirmed) and not the latest. get_monitor!(nodes[1], chan_id).provide_payment_preimage_unsafe_legacy( - &payment_hash, &payment_preimage, &nodes[1].tx_broadcaster, - &LowerBoundedFeeEstimator(nodes[1].fee_estimator), &nodes[1].logger + &payment_hash, + &payment_preimage, + &nodes[1].tx_broadcaster, + &LowerBoundedFeeEstimator(nodes[1].fee_estimator), + &nodes[1].logger, ); let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); @@ -775,10 +967,15 @@ fn test_htlc_preimage_claim_prev_counterparty_commitment_after_current_counterpa check_spends!(htlc_preimage_tx, prev_commitment_a); // Make sure it was indeed a preimage claim and not a revocation claim since the previous // commitment (still unrevoked) is the currently confirmed closing transaction. - assert_eq!(htlc_preimage_tx.input[0].witness.second_to_last().unwrap(), &payment_preimage.0[..]); + assert_eq!( + htlc_preimage_tx.input[0].witness.second_to_last().unwrap(), + &payment_preimage.0[..] + ); } -fn do_test_retries_own_commitment_broadcast_after_reorg(anchors: bool, revoked_counterparty_commitment: bool) { +fn do_test_retries_own_commitment_broadcast_after_reorg( + anchors: bool, revoked_counterparty_commitment: bool, +) { // Tests that a node will retry broadcasting its own commitment after seeing a confirmed // counterparty commitment be reorged out. let mut chanmon_cfgs = create_chanmon_cfgs(2); @@ -793,7 +990,8 @@ fn do_test_retries_own_commitment_broadcast_after_reorg(anchors: bool, revoked_c } let persister; let new_chain_monitor; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config.clone())]); let nodes_1_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); @@ -814,11 +1012,19 @@ fn do_test_retries_own_commitment_broadcast_after_reorg(anchors: bool, revoked_c check_added_monitors!(nodes[0], 1); let fee_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), &fee_update.update_fee.unwrap()); + nodes[1] + .node + .handle_update_fee(nodes[0].node.get_our_node_id(), &fee_update.update_fee.unwrap()); commitment_signed_dance!(nodes[1], nodes[0], fee_update.commitment_signed, false); reload_node!( - nodes[1], config, &serialized_node, &[&serialized_monitor], persister, new_chain_monitor, nodes_1_deserialized + nodes[1], + config, + &serialized_node, + &[&serialized_monitor], + persister, + new_chain_monitor, + nodes_1_deserialized ); } @@ -826,7 +1032,14 @@ fn do_test_retries_own_commitment_broadcast_after_reorg(anchors: bool, revoked_c connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event(&nodes[0], 1, ClosureReason::HTLCsTimedOut, false, &[nodes[1].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HTLCsTimedOut, + false, + &[nodes[1].node.get_our_node_id()], + 100_000, + ); { let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); @@ -844,10 +1057,24 @@ fn do_test_retries_own_commitment_broadcast_after_reorg(anchors: bool, revoked_c }; // B will also broadcast its own commitment. - nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_id, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); check_added_monitors(&nodes[1], 1); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[0].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + false, + &[nodes[0].node.get_our_node_id()], + 100_000, + ); let commitment_b = { let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); diff --git a/lightning/src/ln/shutdown_tests.rs b/lightning/src/ln/shutdown_tests.rs index ae4f73231e6..708f49fdfb1 100644 --- a/lightning/src/ln/shutdown_tests.rs +++ b/lightning/src/ln/shutdown_tests.rs @@ -10,32 +10,32 @@ //! Tests of our shutdown and closing_signed negotiation logic as well as some assorted force-close //! handling tests. -use crate::sign::{EntropySource, SignerProvider}; -use crate::chain::ChannelMonitorUpdateStatus; use crate::chain::transaction::OutPoint; -use crate::events::{Event, HTLCDestination, ClosureReason}; +use crate::chain::ChannelMonitorUpdateStatus; +use crate::events::{ClosureReason, Event, HTLCDestination}; use crate::ln::channel_state::{ChannelDetails, ChannelShutdownState}; use crate::ln::channelmanager::{self, PaymentId, RecipientOnionFields, Retry}; -use crate::routing::router::{PaymentParameters, get_route, RouteParameters}; use crate::ln::msgs; -use crate::ln::types::ChannelId; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, ErrorAction, MessageSendEvent}; use crate::ln::onion_utils::LocalHTLCFailureReason; use crate::ln::script::ShutdownScript; -use crate::util::test_utils; -use crate::util::test_utils::OnGetShutdownScriptpubkey; -use crate::util::errors::APIError; +use crate::ln::types::ChannelId; +use crate::prelude::*; +use crate::routing::router::{get_route, PaymentParameters, RouteParameters}; +use crate::sign::{EntropySource, SignerProvider}; use crate::util::config::UserConfig; +use crate::util::errors::APIError; use crate::util::string::UntrustedString; -use crate::prelude::*; +use crate::util::test_utils; +use crate::util::test_utils::OnGetShutdownScriptpubkey; -use bitcoin::{Transaction, TxOut, WitnessProgram, WitnessVersion}; use bitcoin::amount::Amount; use bitcoin::locktime::absolute::LockTime; -use bitcoin::script::Builder; -use bitcoin::opcodes; use bitcoin::network::Network; +use bitcoin::opcodes; +use bitcoin::script::Builder; use bitcoin::transaction::Version; +use bitcoin::{Transaction, TxOut, WitnessProgram, WitnessVersion}; use crate::ln::functional_test_utils::*; @@ -50,25 +50,58 @@ fn pre_funding_lock_shutdown_test() { mine_transaction(&nodes[0], &tx); mine_transaction(&nodes[1], &tx); - nodes[0].node.close_channel(&ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 0 }), &nodes[1].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .close_channel( + &ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.compute_txid(), index: 0 }), + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[1].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 8000000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 8000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 8000000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 8000000 + ); } #[test] @@ -87,7 +120,8 @@ fn expect_channel_shutdown_state() { expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); // node1 goes into NegotiatingClosingFee since there are no HTLCs in flight, note that it @@ -95,25 +129,51 @@ fn expect_channel_shutdown_state() { expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NegotiatingClosingFee); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NegotiatingClosingFee); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NegotiatingClosingFee); - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[1].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -126,7 +186,8 @@ fn expect_channel_shutdown_state_with_htlc() { let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); let _chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); - let (payment_preimage_0, payment_hash_0, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); + let (payment_preimage_0, payment_hash_0, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NotShuttingDown); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown); @@ -136,13 +197,15 @@ fn expect_channel_shutdown_state_with_htlc() { expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ShutdownInitiated); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::ResolvingHTLCs); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::ResolvingHTLCs); @@ -163,7 +226,10 @@ fn expect_channel_shutdown_state_with_htlc() { assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false); check_added_monitors!(nodes[1], 1); let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -178,7 +244,10 @@ fn expect_channel_shutdown_state_with_htlc() { assert!(updates_2.update_fail_malformed_htlcs.is_empty()); assert!(updates_2.update_fee.is_none()); assert_eq!(updates_2.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates_2.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates_2.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates_2.commitment_signed, false, true); expect_payment_sent!(nodes[0], payment_preimage_0); @@ -187,16 +256,41 @@ fn expect_channel_shutdown_state_with_htlc() { expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NegotiatingClosingFee); // ClosingSignNegotion process - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); // Shutdown basically removes the channelDetails, testing of shutdowncomplete state unnecessary assert!(nodes[0].node.list_channels().is_empty()); @@ -216,22 +310,34 @@ fn test_lnd_bug_6039() { let (payment_preimage, ..) = route_payment(&nodes[0], &[&nodes[1]], 100_000); nodes[0].node.close_channel(&chan.2, &nodes[1].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); // Generate an lnd-like error message and check that we respond by simply screaming louder to // see if LND will accept our protocol compliance. - let err_msg = msgs::ErrorMessage { channel_id: chan.2, data: "link failed to shutdown".to_string() }; + let err_msg = + msgs::ErrorMessage { channel_id: chan.2, data: "link failed to shutdown".to_string() }; nodes[0].node.handle_error(nodes[1].node.get_our_node_id(), &err_msg); let node_a_responses = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(node_a_responses[0], MessageSendEvent::SendShutdown { + assert_eq!( + node_a_responses[0], + MessageSendEvent::SendShutdown { node_id: nodes[1].node.get_our_node_id(), msg: node_0_shutdown, - }); - if let MessageSendEvent::HandleError { action: msgs::ErrorAction::SendWarningMessage { .. }, .. } - = node_a_responses[1] {} else { panic!(); } + } + ); + if let MessageSendEvent::HandleError { + action: msgs::ErrorAction::SendWarningMessage { .. }, + .. + } = node_a_responses[1] + { + } else { + panic!(); + } - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); @@ -242,16 +348,41 @@ fn test_lnd_bug_6039() { nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); // ClosingSignNegotion process - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); // Shutdown basically removes the channelDetails, testing of shutdowncomplete state unnecessary assert!(nodes[0].node.list_channels().is_empty()); @@ -265,18 +396,33 @@ fn shutdown_on_unfunded_channel() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 100_000, 0, None, None).unwrap(); - let open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 100_000, 0, None, None) + .unwrap(); + let open_chan = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); // Create a dummy P2WPKH script - let script = Builder::new().push_int(0) - .push_slice(&[0; 20]) - .into_script(); - - nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &msgs::Shutdown { - channel_id: open_chan.common_fields.temporary_channel_id, scriptpubkey: script, - }); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyCoopClosedUnfundedChannel, [nodes[1].node.get_our_node_id()], 1_000_000); + let script = Builder::new().push_int(0).push_slice(&[0; 20]).into_script(); + + nodes[0].node.handle_shutdown( + nodes[1].node.get_our_node_id(), + &msgs::Shutdown { + channel_id: open_chan.common_fields.temporary_channel_id, + scriptpubkey: script, + }, + ); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyCoopClosedUnfundedChannel, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); } #[test] @@ -287,11 +433,24 @@ fn close_on_unfunded_channel() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let chan_id = nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 100_000, 0, None, None).unwrap(); - let _open_chan = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + let chan_id = nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 100_000, 0, None, None) + .unwrap(); + let _open_chan = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, [nodes[1].node.get_our_node_id()], 1_000_000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); } #[test] @@ -307,7 +466,14 @@ fn expect_channel_shutdown_state_with_force_closure() { expect_channel_shutdown_state!(nodes[0], chan_1.2, ChannelShutdownState::NotShuttingDown); expect_channel_shutdown_state!(nodes[1], chan_1.2, ChannelShutdownState::NotShuttingDown); - nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &chan_1.2, + &nodes[0].node.get_our_node_id(), + error_message.to_string(), + ) + .unwrap(); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); @@ -323,8 +489,20 @@ fn expect_channel_shutdown_state_with_force_closure() { assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[1].node.list_channels().is_empty()); check_closed_broadcast!(nodes[0], true); - check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CommitmentTxConfirmed, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -341,12 +519,15 @@ fn updates_shutdown_wait() { let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let (payment_preimage_0, payment_hash_0, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); + let (payment_preimage_0, payment_hash_0, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); nodes[0].node.close_channel(&chan_1.2, &nodes[1].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -354,22 +535,62 @@ fn updates_shutdown_wait() { let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]); - let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let payment_params_1 = + PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params_1, 100_000); - let route_1 = get_route(&nodes[0].node.get_our_node_id(), &route_params, - &nodes[0].network_graph.read_only(), None, &logger, &scorer, &Default::default(), &random_seed_bytes).unwrap(); - let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[0].node.bolt11_invoice_features()).unwrap(); + let route_1 = get_route( + &nodes[0].node.get_our_node_id(), + &route_params, + &nodes[0].network_graph.read_only(), + None, + &logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); + let payment_params_2 = + PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[0].node.bolt11_invoice_features()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params_2, 100_000); - let route_2 = get_route(&nodes[1].node.get_our_node_id(), &route_params, - &nodes[1].network_graph.read_only(), None, &logger, &scorer, &Default::default(), &random_seed_bytes).unwrap(); - unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route_1, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ), true, APIError::ChannelUnavailable {..}, {}); - unwrap_send_err!(nodes[1], nodes[1].node.send_payment_with_route(route_2, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ), true, APIError::ChannelUnavailable {..}, {}); + let route_2 = get_route( + &nodes[1].node.get_our_node_id(), + &route_params, + &nodes[1].network_graph.read_only(), + None, + &logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); + unwrap_send_err!( + nodes[0], + nodes[0].node.send_payment_with_route( + route_1, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); + unwrap_send_err!( + nodes[1], + nodes[1].node.send_payment_with_route( + route_2, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); nodes[2].node.claim_funds(payment_preimage_0); check_added_monitors!(nodes[2], 1); @@ -381,7 +602,10 @@ fn updates_shutdown_wait() { assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false); check_added_monitors!(nodes[1], 1); let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -392,20 +616,48 @@ fn updates_shutdown_wait() { assert!(updates_2.update_fail_malformed_htlcs.is_empty()); assert!(updates_2.update_fee.is_none()); assert_eq!(updates_2.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates_2.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates_2.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates_2.commitment_signed, false, true); expect_payment_sent!(nodes[0], payment_preimage_0); - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); assert!(nodes[0].node.list_channels().is_empty()); @@ -414,8 +666,20 @@ fn updates_shutdown_wait() { close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true); assert!(nodes[1].node.list_channels().is_empty()); assert!(nodes[2].node.list_channels().is_empty()); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -434,19 +698,34 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); let amt_msat = 100000; - let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); + let (_, our_payment_hash, our_payment_secret) = + get_payment_preimage_hash(&nodes[2], Some(amt_msat), None); let route_params = if blinded_recipient { crate::ln::blinded_payment_tests::get_blinded_route_parameters( - amt_msat, our_payment_secret, 1, 100000000, - nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_2.0.contents], - &chanmon_cfgs[2].keys_manager) + amt_msat, + our_payment_secret, + 1, + 100000000, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_2.0.contents], + &chanmon_cfgs[2].keys_manager, + ) } else { RouteParameters::from_payment_params_and_value( - PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV), amt_msat) + PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV), + amt_msat, + ) }; - nodes[0].node.send_payment(our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), - PaymentId(our_payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); assert_eq!(updates.update_add_htlcs.len(), 1); @@ -456,19 +735,29 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { assert!(updates.update_fee.is_none()); nodes[1].node.close_channel(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap(); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); - - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &updates.commitment_signed); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); commitment_signed_dance!(nodes[1], nodes[0], (), false, true, false, false); expect_pending_htlcs_forwardable!(nodes[1]); expect_htlc_handling_failed_destinations!( nodes[1].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }] + &[HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2.2 + }] ); check_added_monitors(&nodes[1], 1); @@ -479,14 +768,27 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { assert!(updates_2.update_fail_malformed_htlcs.is_empty()); assert!(updates_2.update_fee.is_none()); - nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates_2.update_fail_htlcs[0]); + nodes[0] + .node + .handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates_2.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], updates_2.commitment_signed, false, true); if blinded_recipient { - expect_payment_failed_conditions(&nodes[0], our_payment_hash, false, - PaymentFailedConditions::new().expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + our_payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(LocalHTLCFailureReason::InvalidOnionBlinding, &[0; 32]), + ); } else { - expect_payment_failed_with_update!(nodes[0], our_payment_hash, false, chan_2.0.contents.short_channel_id, true); + expect_payment_failed_with_update!( + nodes[0], + our_payment_hash, + false, + chan_2.0.contents.short_channel_id, + true + ); } let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -501,11 +803,20 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); assert!(nodes[0].node.list_channels().is_empty()); @@ -515,7 +826,13 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true); assert!(nodes[1].node.list_channels().is_empty()); assert!(nodes[2].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); let event1 = ExpectedCloseEvent { channel_capacity_sats: Some(100000), channel_id: None, @@ -535,7 +852,13 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) { user_channel_id: None, }; check_closed_events(&nodes[1], &[event1, event2]); - check_closed_event!(nodes[2], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } fn do_test_shutdown_rebroadcast(recv_count: u8) { @@ -548,13 +871,19 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); - let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); + let (payment_preimage, payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000); nodes[1].node.close_channel(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap(); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); if recv_count > 0 { nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = get_event_msg!( + nodes[0], + MessageSendEvent::SendShutdown, + nodes[1].node.get_our_node_id() + ); if recv_count > 1 { nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); } @@ -563,26 +892,53 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let node_0_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let node_1_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &node_0_reestablish); - let node_1_2nd_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_2nd_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); assert!(node_1_shutdown == node_1_2nd_shutdown); nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &node_1_reestablish); let node_0_2nd_shutdown = if recv_count > 0 { - let node_0_2nd_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_2nd_shutdown = get_event_msg!( + nodes[0], + MessageSendEvent::SendShutdown, + nodes[1].node.get_our_node_id() + ); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_2nd_shutdown); node_0_2nd_shutdown } else { - let node_0_chan_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); + let node_0_chan_update = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ); assert_eq!(node_0_chan_update.contents.channel_flags & 2, 0); // "disabled" flag must not be set as we just reconnected. nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_2nd_shutdown); get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()) @@ -602,7 +958,10 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); assert_eq!(updates.update_fulfill_htlcs.len(), 1); - nodes[1].node.handle_update_fulfill_htlc(nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[1].node.handle_update_fulfill_htlc( + nodes[2].node.get_our_node_id(), + &updates.update_fulfill_htlcs[0], + ); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false); check_added_monitors!(nodes[1], 1); let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -613,34 +972,70 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { assert!(updates_2.update_fail_malformed_htlcs.is_empty()); assert!(updates_2.update_fee.is_none()); assert_eq!(updates_2.update_fulfill_htlcs.len(), 1); - nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &updates_2.update_fulfill_htlcs[0]); + nodes[0].node.handle_update_fulfill_htlc( + nodes[1].node.get_our_node_id(), + &updates_2.update_fulfill_htlcs[0], + ); commitment_signed_dance!(nodes[0], nodes[1], updates_2.commitment_signed, false, true); expect_payment_sent!(nodes[0], payment_preimage); - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); if recv_count > 0 { - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1] + .node + .handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); + nodes[0] + .node + .handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); assert!(node_0_2nd_closing_signed.is_some()); } nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); - nodes[1].node.peer_connected(nodes[0].node.get_our_node_id(), &msgs::Init { - features: nodes[0].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + nodes[1] + .node + .peer_connected( + nodes[0].node.get_our_node_id(), + &msgs::Init { + features: nodes[0].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let node_1_2nd_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); - nodes[0].node.peer_connected(nodes[1].node.get_our_node_id(), &msgs::Init { - features: nodes[1].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + nodes[0] + .node + .peer_connected( + nodes[1].node.get_our_node_id(), + &msgs::Init { + features: nodes[1].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); if recv_count == 0 { // If all closing_signeds weren't delivered we can just resume where we left off... let node_0_2nd_reestablish = get_chan_reestablish_msgs!(nodes[0], nodes[1]).pop().unwrap(); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &node_1_2nd_reestablish); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &node_1_2nd_reestablish); let node_0_msgs = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(node_0_msgs.len(), 2); let node_0_2nd_closing_signed = match node_0_msgs[1] { @@ -660,8 +1055,14 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { }; assert!(node_0_2nd_shutdown == node_0_3rd_shutdown); - nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), &node_0_2nd_reestablish); - let node_1_3rd_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_channel_reestablish(nodes[0].node.get_our_node_id(), &node_0_2nd_reestablish); + let node_1_3rd_shutdown = get_event_msg!( + nodes[1], + MessageSendEvent::SendShutdown, + nodes[0].node.get_our_node_id() + ); assert!(node_1_3rd_shutdown == node_1_2nd_shutdown); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_3rd_shutdown); @@ -669,14 +1070,33 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_3rd_shutdown); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + nodes[1] + .node + .handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); + nodes[0] + .node + .handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); + let (_, node_0_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.unwrap(), + ); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } else { // If one node, however, received + responded with an identical closing_signed we end // up erroring and node[0] will try to broadcast its own latest commitment transaction. @@ -687,7 +1107,9 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { // transaction. assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), &node_1_2nd_reestablish); + nodes[0] + .node + .handle_channel_reestablish(nodes[1].node.get_our_node_id(), &node_1_2nd_reestablish); let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 2); if let MessageSendEvent::HandleError { ref action, .. } = msg_events[1] { @@ -698,7 +1120,9 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { }, _ => panic!("Unexpected event!"), } - } else { panic!("Needed SendErrorMessage close"); } + } else { + panic!("Needed SendErrorMessage close"); + } // get_closing_signed_broadcast usually eats the BroadcastChannelUpdate for us and // checks it, but in this case nodes[1] didn't ever get a chance to receive a @@ -716,9 +1140,27 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) { close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true); assert!(nodes[1].node.list_channels().is_empty()); assert!(nodes[2].node.list_channels().is_empty()); - check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -746,9 +1188,11 @@ fn test_upfront_shutdown_script() { // We test that in case of peer committing upfront to a script, if it changes at closing, we refuse to sign let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1000000, 1000000); nodes[0].node.close_channel(&chan.2, &nodes[2].node.get_our_node_id()).unwrap(); - let node_0_orig_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id()); + let node_0_orig_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id()); let mut node_0_shutdown = node_0_orig_shutdown.clone(); - node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh(); + node_0_shutdown.scriptpubkey = + Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh(); // Test we enforce upfront_scriptpbukey if by providing a different one at closing that we warn // the peer and ignore the message. nodes[2].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); @@ -761,13 +1205,16 @@ fn test_upfront_shutdown_script() { // We test that in case of peer committing upfront to a script, if it doesn't change at closing, we sign let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1000000, 1000000); nodes[0].node.close_channel(&chan.2, &nodes[2].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id()); // We test that in case of peer committing upfront to a script, if it oesn't change at closing, we sign nodes[2].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); let events = nodes[2].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::SendShutdown { node_id, .. } => { assert_eq!(node_id, nodes[0].node.get_our_node_id()) } + MessageSendEvent::SendShutdown { node_id, .. } => { + assert_eq!(node_id, nodes[0].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } @@ -777,13 +1224,16 @@ fn test_upfront_shutdown_script() { *nodes[0].override_init_features.borrow_mut() = Some(features); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000); nodes[0].node.close_channel(&chan.2, &nodes[1].node.get_our_node_id()).unwrap(); - let node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_1_shutdown); check_added_monitors!(nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::SendShutdown { node_id, .. } => { assert_eq!(node_id, nodes[0].node.get_our_node_id()) } + MessageSendEvent::SendShutdown { node_id, .. } => { + assert_eq!(node_id, nodes[0].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } @@ -793,12 +1243,15 @@ fn test_upfront_shutdown_script() { let chan = create_announced_chan_between_nodes_with_value(&nodes, 1, 0, 1000000, 1000000); nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap(); check_added_monitors!(nodes[1], 1); - let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_0_shutdown); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::SendShutdown { node_id, .. } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()) } + MessageSendEvent::SendShutdown { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } @@ -807,16 +1260,21 @@ fn test_upfront_shutdown_script() { let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000); nodes[1].node.close_channel(&chan.2, &nodes[0].node.get_our_node_id()).unwrap(); check_added_monitors!(nodes[1], 1); - let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_0_shutdown); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); match events[0] { - MessageSendEvent::SendShutdown { node_id, .. } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()) } + MessageSendEvent::SendShutdown { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } match events[1] { - MessageSendEvent::SendClosingSigned { node_id, .. } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()) } + MessageSendEvent::SendClosingSigned { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } } @@ -833,21 +1291,28 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // Use a non-v0 segwit script supported by option_shutdown_anysegwit - let anysegwit_shutdown_script = Builder::new() - .push_int(16) - .push_slice(&[0, 40]) - .into_script(); + let anysegwit_shutdown_script = Builder::new().push_int(16).push_slice(&[0, 40]).into_script(); // Check script when handling an open_channel message - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let mut open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); open_channel.common_fields.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone()); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { assert_eq!(node_id, nodes[0].node.get_our_node_id()); assert_eq!(msg.data, "Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: OP_PUSHNUM_16 OP_PUSHBYTES_2 0028"); }, @@ -864,17 +1329,31 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // Check script when handling an accept_channel message - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); - let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); + let open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); - let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + let mut accept_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendAcceptChannel, + nodes[0].node.get_our_node_id() + ); accept_channel.common_fields.shutdown_scriptpubkey = Some(anysegwit_shutdown_script.clone()); nodes[0].node.handle_accept_channel(nodes[1].node.get_our_node_id(), &accept_channel); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()); assert_eq!(msg.data, "Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: OP_PUSHNUM_16 OP_PUSHBYTES_2 0028"); }, @@ -891,19 +1370,28 @@ fn test_invalid_upfront_shutdown_script() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None).unwrap(); + nodes[0] + .node + .create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None, None) + .unwrap(); // Use a segwit v0 script with an unsupported witness program - let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - open_channel.common_fields.shutdown_scriptpubkey = Some(Builder::new().push_int(0) - .push_slice(&[0, 0]) - .into_script()); + let mut open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); + open_channel.common_fields.shutdown_scriptpubkey = + Some(Builder::new().push_int(0).push_slice(&[0, 0]).into_script()); nodes[1].node.handle_open_channel(nodes[0].node.get_our_node_id(), &open_channel); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + MessageSendEvent::HandleError { + action: ErrorAction::SendErrorMessage { ref msg }, + node_id, + } => { assert_eq!(node_id, nodes[0].node.get_our_node_id()); assert_eq!(msg.data, "Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: OP_0 OP_PUSHBYTES_2 0000"); }, @@ -928,20 +1416,23 @@ fn test_segwit_v0_shutdown_script() { check_added_monitors!(nodes[1], 1); // Use a segwit v0 script supported even without option_shutdown_anysegwit - let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); - node_0_shutdown.scriptpubkey = Builder::new().push_int(0) - .push_slice(&[0; 20]) - .into_script(); + let mut node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + node_0_shutdown.scriptpubkey = Builder::new().push_int(0).push_slice(&[0; 20]).into_script(); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_0_shutdown); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); match events[0] { - MessageSendEvent::SendShutdown { node_id, .. } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()) } + MessageSendEvent::SendShutdown { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } match events[1] { - MessageSendEvent::SendClosingSigned { node_id, .. } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()) } + MessageSendEvent::SendClosingSigned { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } } @@ -963,20 +1454,23 @@ fn test_anysegwit_shutdown_script() { check_added_monitors!(nodes[1], 1); // Use a non-v0 segwit script supported by option_shutdown_anysegwit - let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); - node_0_shutdown.scriptpubkey = Builder::new().push_int(16) - .push_slice(&[0, 0]) - .into_script(); + let mut node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + node_0_shutdown.scriptpubkey = Builder::new().push_int(16).push_slice(&[0, 0]).into_script(); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_0_shutdown); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); match events[0] { - MessageSendEvent::SendShutdown { node_id, .. } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()) } + MessageSendEvent::SendShutdown { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } match events[1] { - MessageSendEvent::SendClosingSigned { node_id, .. } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()) } + MessageSendEvent::SendClosingSigned { node_id, .. } => { + assert_eq!(node_id, nodes[1].node.get_our_node_id()) + }, _ => panic!("Unexpected event"), } } @@ -998,11 +1492,13 @@ fn test_unsupported_anysegwit_shutdown_script() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Check that using an unsupported shutdown script fails and a supported one succeeds. - let supported_shutdown_script = chanmon_cfgs[1].keys_manager.get_shutdown_scriptpubkey().unwrap(); + let supported_shutdown_script = + chanmon_cfgs[1].keys_manager.get_shutdown_scriptpubkey().unwrap(); let unsupported_witness_program = WitnessProgram::new(WitnessVersion::V16, &[0, 40]).unwrap(); let unsupported_shutdown_script = ShutdownScript::new_witness_program(&unsupported_witness_program).unwrap(); - chanmon_cfgs[1].keys_manager + chanmon_cfgs[1] + .keys_manager .expect(OnGetShutdownScriptpubkey { returns: unsupported_shutdown_script.clone() }) .expect(OnGetShutdownScriptpubkey { returns: supported_shutdown_script }); @@ -1018,12 +1514,15 @@ fn test_unsupported_anysegwit_shutdown_script() { check_added_monitors!(nodes[1], 1); // Use a non-v0 segwit script unsupported without option_shutdown_anysegwit - let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let mut node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); node_0_shutdown.scriptpubkey = unsupported_shutdown_script.into_inner(); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_0_shutdown); - assert_eq!(&check_warn_msg!(nodes[0], nodes[1].node.get_our_node_id(), chan.2), - "Got a nonstandard scriptpubkey (60020028) from remote peer"); + assert_eq!( + &check_warn_msg!(nodes[0], nodes[1].node.get_our_node_id(), chan.2), + "Got a nonstandard scriptpubkey (60020028) from remote peer" + ); } #[test] @@ -1043,14 +1542,15 @@ fn test_invalid_shutdown_script() { check_added_monitors!(nodes[1], 1); // Use a segwit v0 script with an unsupported witness program - let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); - node_0_shutdown.scriptpubkey = Builder::new().push_int(0) - .push_slice(&[0, 0]) - .into_script(); + let mut node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + node_0_shutdown.scriptpubkey = Builder::new().push_int(0).push_slice(&[0, 0]).into_script(); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_0_shutdown); - assert_eq!(&check_warn_msg!(nodes[0], nodes[1].node.get_our_node_id(), chan.2), - "Got a nonstandard scriptpubkey (00020000) from remote peer"); + assert_eq!( + &check_warn_msg!(nodes[0], nodes[1].node.get_our_node_id(), chan.2), + "Got a nonstandard scriptpubkey (00020000) from remote peer" + ); } #[test] @@ -1066,17 +1566,24 @@ fn test_user_shutdown_script() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Segwit v0 script of the form OP_0 <20-byte hash> - let script = Builder::new().push_int(0) - .push_slice(&[0; 20]) - .into_script(); + let script = Builder::new().push_int(0).push_slice(&[0; 20]).into_script(); let shutdown_script = ShutdownScript::try_from(script.clone()).unwrap(); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - nodes[1].node.close_channel_with_feerate_and_script(&chan.2, &nodes[0].node.get_our_node_id(), None, Some(shutdown_script)).unwrap(); + nodes[1] + .node + .close_channel_with_feerate_and_script( + &chan.2, + &nodes[0].node.get_our_node_id(), + None, + Some(shutdown_script), + ) + .unwrap(); check_added_monitors!(nodes[1], 1); - let mut node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let mut node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); assert_eq!(node_0_shutdown.scriptpubkey, script); } @@ -1093,16 +1600,24 @@ fn test_already_set_user_shutdown_script() { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); // Segwit v0 script of the form OP_0 <20-byte hash> - let script = Builder::new().push_int(0) - .push_slice(&[0; 20]) - .into_script(); + let script = Builder::new().push_int(0).push_slice(&[0; 20]).into_script(); let shutdown_script = ShutdownScript::try_from(script).unwrap(); let chan = create_announced_chan_between_nodes(&nodes, 0, 1); - let result = nodes[1].node.close_channel_with_feerate_and_script(&chan.2, &nodes[0].node.get_our_node_id(), None, Some(shutdown_script)); + let result = nodes[1].node.close_channel_with_feerate_and_script( + &chan.2, + &nodes[0].node.get_our_node_id(), + None, + Some(shutdown_script), + ); - assert_eq!(result, Err(APIError::APIMisuseError { err: "Cannot override shutdown script for a channel with one already set".to_string() })); + assert_eq!( + result, + Err(APIError::APIMisuseError { + err: "Cannot override shutdown script for a channel with one already set".to_string() + }) + ); } #[derive(PartialEq)] @@ -1130,9 +1645,11 @@ fn do_test_closing_signed_reinit_timeout(timeout_step: TimeoutStep) { send_payment(&nodes[0], &[&nodes[1]], 8_000_000); nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); { @@ -1143,13 +1660,19 @@ fn do_test_closing_signed_reinit_timeout(timeout_step: TimeoutStep) { *feerate_lock *= 10; } - let mut node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let mut node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); // nodes[0] should use a "reasonable" feerate, well under the 10 sat/vByte that nodes[1] thinks // is the current prevailing feerate. assert!(node_0_closing_signed.fee_satoshis <= 500); if timeout_step != TimeoutStep::AfterShutdown { - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); + nodes[1] + .node + .handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); assert!(check_warn_msg!(nodes[1], nodes[0].node.get_our_node_id(), chan_id) .starts_with("Unable to come to consensus about closing feerate")); @@ -1159,17 +1682,52 @@ fn do_test_closing_signed_reinit_timeout(timeout_step: TimeoutStep) { { let mut node_0_per_peer_lock; let mut node_0_peer_state_lock; - get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_id).context_mut().closing_fee_limits.as_mut().unwrap().1 *= 10; + get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_id + ) + .context_mut() + .closing_fee_limits + .as_mut() + .unwrap() + .1 *= 10; } - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let node_1_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); - nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let node_0_2nd_closing_signed = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1] + .node + .handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); + let node_1_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); + nodes[0] + .node + .handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); + let node_0_2nd_closing_signed = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); if timeout_step == TimeoutStep::NoTimeout { - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_2nd_closing_signed.1.unwrap()); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + nodes[1].node.handle_closing_signed( + nodes[0].node.get_our_node_id(), + &node_0_2nd_closing_signed.1.unwrap(), + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } if timeout_step != TimeoutStep::NoTimeout { @@ -1186,14 +1744,24 @@ fn do_test_closing_signed_reinit_timeout(timeout_step: TimeoutStep) { assert_eq!(txn[0].output.len(), 2); if timeout_step != TimeoutStep::NoTimeout { - assert!((txn[0].output[0].script_pubkey.is_p2wpkh() && - txn[0].output[1].script_pubkey.is_p2wsh()) || - (txn[0].output[1].script_pubkey.is_p2wpkh() && - txn[0].output[0].script_pubkey.is_p2wsh())); + assert!( + (txn[0].output[0].script_pubkey.is_p2wpkh() + && txn[0].output[1].script_pubkey.is_p2wsh()) + || (txn[0].output[1].script_pubkey.is_p2wpkh() + && txn[0].output[0].script_pubkey.is_p2wsh()) + ); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "closing_signed negotiation failed to finish within two timer ticks".to_string() } - , [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::ProcessingError { + err: "closing_signed negotiation failed to finish within two timer ticks" + .to_string() + }, + [nodes[0].node.get_our_node_id()], + 100000 + ); } else { assert!(txn[0].output[0].script_pubkey.is_p2wpkh()); assert!(txn[0].output[1].script_pubkey.is_p2wpkh()); @@ -1233,12 +1801,18 @@ fn do_simple_legacy_shutdown_test(high_initiator_fee: bool) { } nodes[0].node.close_channel(&chan.2, &nodes[1].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); - let mut node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let mut node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); node_0_closing_signed.fee_range = None; if high_initiator_fee { assert!(node_0_closing_signed.fee_satoshis > 500); @@ -1247,14 +1821,30 @@ fn do_simple_legacy_shutdown_test(high_initiator_fee: bool) { } nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let (_, mut node_1_closing_signed) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, mut node_1_closing_signed) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); node_1_closing_signed.as_mut().unwrap().fee_range = None; - nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed.unwrap()); - let (_, node_0_none) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[0] + .node + .handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed.unwrap()); + let (_, node_0_none) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); assert!(node_0_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CounterpartyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1274,42 +1864,86 @@ fn simple_target_feerate_shutdown() { let chan = create_announced_chan_between_nodes(&nodes, 0, 1); let chan_id = chan.2; - nodes[0].node.close_channel_with_feerate_and_script(&chan_id, &nodes[1].node.get_our_node_id(), Some(253 * 10), None).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); - nodes[1].node.close_channel_with_feerate_and_script(&chan_id, &nodes[0].node.get_our_node_id(), Some(253 * 5), None).unwrap(); - let node_1_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + nodes[0] + .node + .close_channel_with_feerate_and_script( + &chan_id, + &nodes[1].node.get_our_node_id(), + Some(253 * 10), + None, + ) + .unwrap(); + let node_0_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + nodes[1] + .node + .close_channel_with_feerate_and_script( + &chan_id, + &nodes[0].node.get_our_node_id(), + Some(253 * 5), + None, + ) + .unwrap(); + let node_1_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_0_shutdown); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_1_shutdown); - let node_0_closing_signed = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id()); + let node_0_closing_signed = get_event_msg!( + nodes[0], + MessageSendEvent::SendClosingSigned, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &node_0_closing_signed); - let (_, node_1_closing_signed_opt) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, node_1_closing_signed_opt) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); let node_1_closing_signed = node_1_closing_signed_opt.unwrap(); // nodes[1] was passed a target which was larger than the current channel feerate, which it // should ignore in favor of the channel fee, as there is no use demanding a minimum higher // than what will be paid on a force-close transaction. Note that we have to consider rounding, // so only check that we're within 10 sats. - assert!(node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis >= - node_1_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis * 10 - 5); - assert!(node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis <= - node_1_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis * 10 + 5); + assert!( + node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis + >= node_1_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis * 10 - 5 + ); + assert!( + node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis + <= node_1_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis * 10 + 5 + ); // Further, because nodes[0]'s target fee is larger than the `Normal` fee estimation plus our // force-closure-avoidance buffer, min should equal max, and the nodes[1]-selected fee should // be the nodes[0] only available fee. - assert_eq!(node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis, - node_0_closing_signed.fee_range.as_ref().unwrap().max_fee_satoshis); - assert_eq!(node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis, - node_0_closing_signed.fee_satoshis); + assert_eq!( + node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis, + node_0_closing_signed.fee_range.as_ref().unwrap().max_fee_satoshis + ); + assert_eq!( + node_0_closing_signed.fee_range.as_ref().unwrap().min_fee_satoshis, + node_0_closing_signed.fee_satoshis + ); assert_eq!(node_0_closing_signed.fee_satoshis, node_1_closing_signed.fee_satoshis); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &node_1_closing_signed); - let (_, node_0_none) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + let (_, node_0_none) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); assert!(node_0_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { @@ -1327,16 +1961,15 @@ fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; send_payment(&nodes[0], &[&nodes[1]], 1_000_000); - let payment_hash_opt = if use_htlc { - Some(route_payment(&nodes[1], &[&nodes[0]], 10_000).1) - } else { - None - }; + let payment_hash_opt = + if use_htlc { Some(route_payment(&nodes[1], &[&nodes[0]], 10_000).1) } else { None }; if use_htlc { nodes[0].node.fail_htlc_backwards(&payment_hash_opt.unwrap()); - expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[0], - [HTLCDestination::FailedPayment { payment_hash: payment_hash_opt.unwrap() }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!( + nodes[0], + [HTLCDestination::FailedPayment { payment_hash: payment_hash_opt.unwrap() }] + ); } else { *chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap() *= 10; nodes[0].node.timer_tick_occurred(); @@ -1345,19 +1978,29 @@ fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { check_added_monitors(&nodes[0], 1); nodes[1].node.close_channel(&chan_id, &nodes[0].node.get_our_node_id()).unwrap(); - let node_0_shutdown = get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); + let node_0_shutdown = + get_event_msg!(nodes[1], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id()); nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); - let node_1_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); + let node_1_shutdown = + get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id()); nodes[0].node.handle_shutdown(nodes[1].node.get_our_node_id(), &node_0_shutdown); nodes[1].node.handle_shutdown(nodes[0].node.get_our_node_id(), &node_1_shutdown); if use_htlc { - nodes[1].node.handle_update_fail_htlc(nodes[0].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + nodes[1].node.handle_update_fail_htlc( + nodes[0].node.get_our_node_id(), + &updates.update_fail_htlcs[0], + ); } else { - nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), &updates.update_fee.unwrap()); + nodes[1] + .node + .handle_update_fee(nodes[0].node.get_our_node_id(), &updates.update_fee.unwrap()); } - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &updates.commitment_signed); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors(&nodes[1], 1); let (bs_raa, bs_cs) = get_revoke_commit_msgs(&nodes[1], &nodes[0].node.get_our_node_id()); @@ -1376,7 +2019,14 @@ fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { expect_channel_shutdown_state!(nodes[0], chan_id, ChannelShutdownState::ResolvingHTLCs); assert_eq!(nodes[0].node.get_and_clear_pending_msg_events(), Vec::new()); - let (latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone(); + let (latest_update, _) = nodes[0] + .chain_monitor + .latest_monitor_update_id + .lock() + .unwrap() + .get(&chan_id) + .unwrap() + .clone(); nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_id, latest_update); let as_raa_closing_signed = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1388,21 +2038,45 @@ fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { if use_htlc { expect_payment_failed!(nodes[1], payment_hash_opt.unwrap(), true); } - } else { panic!("Unexpected message {:?}", as_raa_closing_signed[0]); } + } else { + panic!("Unexpected message {:?}", as_raa_closing_signed[0]); + } if let MessageSendEvent::SendClosingSigned { msg, .. } = &as_raa_closing_signed[1] { nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &msg); - } else { panic!("Unexpected message {:?}", as_raa_closing_signed[1]); } + } else { + panic!("Unexpected message {:?}", as_raa_closing_signed[1]); + } - let bs_closing_signed = get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()); + let bs_closing_signed = get_event_msg!( + nodes[1], + MessageSendEvent::SendClosingSigned, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_closing_signed(nodes[1].node.get_our_node_id(), &bs_closing_signed); - let (_, as_2nd_closing_signed) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_closing_signed(nodes[0].node.get_our_node_id(), &as_2nd_closing_signed.unwrap()); - let (_, node_1_none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_, as_2nd_closing_signed) = + get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + nodes[1] + .node + .handle_closing_signed(nodes[0].node.get_our_node_id(), &as_2nd_closing_signed.unwrap()); + let (_, node_1_none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); assert!(node_1_none.is_none()); - check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::LocallyInitiatedCooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1426,23 +2100,49 @@ fn batch_funding_failure() { assert_eq!(events.len(), 2); // Build a transaction which only has the output for one of the two channels we're trying to // confirm. Previously this led to a deadlock in channel closure handling. - let mut tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + let mut tx = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }; let mut chans = Vec::new(); for (idx, ev) in events.iter().enumerate() { - if let Event::FundingGenerationReady { temporary_channel_id, counterparty_node_id, output_script, .. } = ev { + if let Event::FundingGenerationReady { + temporary_channel_id, + counterparty_node_id, + output_script, + .. + } = ev + { if idx == 0 { - tx.output.push(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: output_script.clone() }); + tx.output.push(TxOut { + value: Amount::from_sat(1_000_000), + script_pubkey: output_script.clone(), + }); } chans.push((temporary_channel_id, counterparty_node_id)); - } else { panic!(); } + } else { + panic!(); + } } let err = "Error in transaction funding: Misuse error: No output matched the script_pubkey and value in the FundingGenerationReady event".to_string(); - let temp_err = "No output matched the script_pubkey and value in the FundingGenerationReady event".to_string(); + let temp_err = + "No output matched the script_pubkey and value in the FundingGenerationReady event" + .to_string(); let post_funding_chan_id_a = ChannelId::v1_from_funding_txid(tx.compute_txid().as_ref(), 0); let close = [ - ExpectedCloseEvent::from_id_reason(post_funding_chan_id_a, true, ClosureReason::ProcessingError { err: err.clone() }), - ExpectedCloseEvent::from_id_reason(temp_chan_id_b, false, ClosureReason::ProcessingError { err: temp_err }), + ExpectedCloseEvent::from_id_reason( + post_funding_chan_id_a, + true, + ClosureReason::ProcessingError { err: err.clone() }, + ), + ExpectedCloseEvent::from_id_reason( + temp_chan_id_b, + false, + ClosureReason::ProcessingError { err: temp_err }, + ), ]; nodes[0].node.batch_funding_transaction_generated(&chans, tx).unwrap_err(); @@ -1452,25 +2152,52 @@ fn batch_funding_failure() { // We currently spuriously send `FundingCreated` for the first channel and then immediately // fail both channels, which isn't ideal but should be fine. assert!(msgs.iter().any(|msg| { - if let MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { channel_id, .. }, .. - }, .. } = msg { + if let MessageSendEvent::HandleError { + action: + msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { channel_id, .. }, .. + }, + .. + } = msg + { *channel_id == temp_chan_id_b - } else { false } + } else { + false + } })); - let funding_created_pos = msgs.iter().position(|msg| { - if let MessageSendEvent::SendFundingCreated { msg: msgs::FundingCreated { temporary_channel_id, .. }, .. } = msg { - assert_eq!(*temporary_channel_id, temp_chan_id_a); - true - } else { false } - }).unwrap(); - let funded_channel_close_pos = msgs.iter().position(|msg| { - if let MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { channel_id, .. }, .. - }, .. } = msg { - *channel_id == post_funding_chan_id_a - } else { false } - }).unwrap(); + let funding_created_pos = msgs + .iter() + .position(|msg| { + if let MessageSendEvent::SendFundingCreated { + msg: msgs::FundingCreated { temporary_channel_id, .. }, + .. + } = msg + { + assert_eq!(*temporary_channel_id, temp_chan_id_a); + true + } else { + false + } + }) + .unwrap(); + let funded_channel_close_pos = msgs + .iter() + .position(|msg| { + if let MessageSendEvent::HandleError { + action: + msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { channel_id, .. }, + .. + }, + .. + } = msg + { + *channel_id == post_funding_chan_id_a + } else { + false + } + }) + .unwrap(); // The error message uses the funded channel_id so must come after the funding_created assert!(funded_channel_close_pos > funding_created_pos); @@ -1531,6 +2258,9 @@ fn test_force_closure_on_low_stale_fee() { connect_blocks(&nodes[1], 1); check_added_monitors!(nodes[1], 1); check_closed_broadcast(&nodes[1], 1, true); - let reason = ClosureReason::PeerFeerateTooLow { peer_feerate_sat_per_kw: 253, required_feerate_sat_per_kw: 253 * 2 }; + let reason = ClosureReason::PeerFeerateTooLow { + peer_feerate_sat_per_kw: 253, + required_feerate_sat_per_kw: 253 * 2, + }; check_closed_events(&nodes[1], &[ExpectedCloseEvent::from_id_reason(chan_id, false, reason)]); } diff --git a/lightning/src/routing/mod.rs b/lightning/src/routing/mod.rs index ca2d2c8cc77..cb16461dd66 100644 --- a/lightning/src/routing/mod.rs +++ b/lightning/src/routing/mod.rs @@ -9,10 +9,10 @@ //! Structs and impls for receiving messages about the network and storing the topology live here. -pub mod utxo; pub mod gossip; +mod log_approx; pub mod router; pub mod scoring; -mod log_approx; #[cfg(test)] pub(crate) mod test_utils; +pub mod utxo; diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 14d06355bc0..7f68cea8245 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -9,33 +9,40 @@ //! The router finds paths within a [`NetworkGraph`] for a payment. -use bitcoin::secp256k1::{PublicKey, Secp256k1, self}; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; use lightning_invoice::Bolt11Invoice; +use crate::blinded_path::payment::{ + BlindedPaymentPath, ForwardTlvs, PaymentConstraints, PaymentForwardNode, PaymentRelay, + ReceiveTlvs, +}; use crate::blinded_path::{BlindedHop, Direction, IntroductionNode}; -use crate::blinded_path::payment::{BlindedPaymentPath, ForwardTlvs, PaymentConstraints, PaymentForwardNode, PaymentRelay, ReceiveTlvs}; -use crate::types::payment::{PaymentHash, PaymentPreimage}; +use crate::crypto::chacha20::ChaCha20; use crate::ln::channel_state::ChannelDetails; -use crate::ln::channelmanager::{PaymentId, MIN_FINAL_CLTV_EXPIRY_DELTA, RecipientOnionFields}; -use crate::types::features::{BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures}; +use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, MIN_FINAL_CLTV_EXPIRY_DELTA}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; use crate::ln::onion_utils; +use crate::offers::invoice::Bolt12Invoice; #[cfg(async_payments)] use crate::offers::static_invoice::StaticInvoice; -use crate::offers::invoice::Bolt12Invoice; -use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId}; +use crate::routing::gossip::{ + DirectedChannelInfo, EffectiveCapacity, NetworkGraph, NodeId, ReadOnlyNetworkGraph, +}; use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::sign::EntropySource; use crate::sync::Mutex; -use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer}; +use crate::types::features::{ + BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures, +}; +use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::logger::Logger; -use crate::crypto::chacha20::ChaCha20; +use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; use crate::io; use crate::prelude::*; use alloc::collections::BinaryHeap; -use core::{cmp, fmt}; use core::ops::Deref; +use core::{cmp, fmt}; use lightning_types::routing::RoutingFees; @@ -49,9 +56,16 @@ pub use lightning_types::routing::{RouteHint, RouteHintHop}; /// it will create a one-hop path using the recipient as the introduction node if it is a announced /// node. Otherwise, there is no way to find a path to the introduction node in order to send a /// payment, and thus an `Err` is returned. -pub struct DefaultRouter>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where +pub struct DefaultRouter< + G: Deref>, + L: Deref, + ES: Deref, + S: Deref, + SP: Sized, + Sc: ScoreLookUp, +> where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>, ES::Target: EntropySource, { network_graph: G, @@ -61,43 +75,60 @@ pub struct DefaultRouter>, L: Deref, ES: Deref score_params: SP, } -impl>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where +impl< + G: Deref>, + L: Deref, + ES: Deref, + S: Deref, + SP: Sized, + Sc: ScoreLookUp, + > DefaultRouter +where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>, ES::Target: EntropySource, { /// Creates a new router. - pub fn new(network_graph: G, logger: L, entropy_source: ES, scorer: S, score_params: SP) -> Self { + pub fn new( + network_graph: G, logger: L, entropy_source: ES, scorer: S, score_params: SP, + ) -> Self { Self { network_graph, logger, entropy_source, scorer, score_params } } } -impl>, L: Deref, ES: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where +impl< + G: Deref>, + L: Deref, + ES: Deref, + S: Deref, + SP: Sized, + Sc: ScoreLookUp, + > Router for DefaultRouter +where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>, ES::Target: EntropySource, { fn find_route( - &self, - payer: &PublicKey, - params: &RouteParameters, - first_hops: Option<&[&ChannelDetails]>, - inflight_htlcs: InFlightHtlcs + &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, + inflight_htlcs: InFlightHtlcs, ) -> Result { let random_seed_bytes = self.entropy_source.get_secure_random_bytes(); find_route( - payer, params, &self.network_graph, first_hops, &*self.logger, + payer, + params, + &self.network_graph, + first_hops, + &*self.logger, &ScorerAccountingForInFlightHtlcs::new(self.scorer.read_lock(), &inflight_htlcs), &self.score_params, - &random_seed_bytes + &random_seed_bytes, ) } - fn create_blinded_payment_paths< - T: secp256k1::Signing + secp256k1::Verification - > ( + fn create_blinded_payment_paths( &self, recipient: PublicKey, first_hops: Vec, tlvs: ReceiveTlvs, - amount_msats: Option, secp_ctx: &Secp256k1 + amount_msats: Option, secp_ctx: &Secp256k1, ) -> Result, ()> { // Limit the number of blinded paths that are computed. const MAX_PAYMENT_PATHS: usize = 3; @@ -109,29 +140,33 @@ impl>, L: Deref, ES: Deref, S: Deref, SP: Size let has_one_peer = first_hops .first() .map(|details| details.counterparty.node_id) - .map(|node_id| first_hops - .iter() - .skip(1) - .all(|details| details.counterparty.node_id == node_id) - ) + .map(|node_id| { + first_hops.iter().skip(1).all(|details| details.counterparty.node_id == node_id) + }) .unwrap_or(false); let network_graph = self.network_graph.deref().read_only(); let is_recipient_announced = network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)); - let paths = first_hops.into_iter() + let paths = first_hops + .into_iter() .filter(|details| details.counterparty.features.supports_route_blinding()) .filter(|details| amount_msats.unwrap_or(0) <= details.inbound_capacity_msat) - .filter(|details| amount_msats.unwrap_or(u64::MAX) >= details.inbound_htlc_minimum_msat.unwrap_or(0)) - .filter(|details| amount_msats.unwrap_or(0) <= details.inbound_htlc_maximum_msat.unwrap_or(u64::MAX)) + .filter(|details| { + amount_msats.unwrap_or(u64::MAX) >= details.inbound_htlc_minimum_msat.unwrap_or(0) + }) + .filter(|details| { + amount_msats.unwrap_or(0) <= details.inbound_htlc_maximum_msat.unwrap_or(u64::MAX) + }) // Limit to peers with announced channels unless the recipient is unannounced. - .filter(|details| network_graph + .filter(|details| { + network_graph .node(&NodeId::from_pubkey(&details.counterparty.node_id)) .map(|node| !is_recipient_announced || node.channels.len() >= MIN_PEER_CHANNELS) // Allow payments directly with the only peer when unannounced. .unwrap_or(!is_recipient_announced && has_one_peer) - ) + }) .filter_map(|details| { let short_channel_id = match details.get_inbound_payment_scid() { Some(short_channel_id) => short_channel_id, @@ -147,7 +182,8 @@ impl>, L: Deref, ES: Deref, S: Deref, SP: Size let cltv_expiry_delta = payment_relay.cltv_expiry_delta as u32; let payment_constraints = PaymentConstraints { - max_cltv_expiry: tlvs.tlvs().payment_constraints.max_cltv_expiry + cltv_expiry_delta, + max_cltv_expiry: tlvs.tlvs().payment_constraints.max_cltv_expiry + + cltv_expiry_delta, htlc_minimum_msat: details.inbound_htlc_minimum_msat.unwrap_or(0), }; Some(PaymentForwardNode { @@ -164,8 +200,13 @@ impl>, L: Deref, ES: Deref, S: Deref, SP: Size }) .map(|forward_node| { BlindedPaymentPath::new( - &[forward_node], recipient, tlvs.clone(), u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, - &*self.entropy_source, secp_ctx + &[forward_node], + recipient, + tlvs.clone(), + u64::MAX, + MIN_FINAL_CLTV_EXPIRY_DELTA, + &*self.entropy_source, + secp_ctx, ) }) .take(MAX_PAYMENT_PATHS) @@ -176,9 +217,15 @@ impl>, L: Deref, ES: Deref, S: Deref, SP: Size _ => { if network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)) { BlindedPaymentPath::new( - &[], recipient, tlvs, u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source, - secp_ctx - ).map(|path| vec![path]) + &[], + recipient, + tlvs, + u64::MAX, + MIN_FINAL_CLTV_EXPIRY_DELTA, + &*self.entropy_source, + secp_ctx, + ) + .map(|path| vec![path]) } else { Err(()) } @@ -204,16 +251,14 @@ impl FixedRouter { impl Router for FixedRouter { fn find_route( &self, _payer: &PublicKey, _route_params: &RouteParameters, - _first_hops: Option<&[&ChannelDetails]>, _inflight_htlcs: InFlightHtlcs + _first_hops: Option<&[&ChannelDetails]>, _inflight_htlcs: InFlightHtlcs, ) -> Result { self.route.lock().unwrap().take().ok_or("Can't use this router to return multiple routes") } - fn create_blinded_payment_paths< - T: secp256k1::Signing + secp256k1::Verification - > ( + fn create_blinded_payment_paths( &self, _recipient: PublicKey, _first_hops: Vec, _tlvs: ReceiveTlvs, - _amount_msats: Option, _secp_ctx: &Secp256k1 + _amount_msats: Option, _secp_ctx: &Secp256k1, ) -> Result, ()> { // Should be unreachable as this router is only intended to provide a one-time payment route. debug_assert!(false); @@ -229,7 +274,7 @@ pub trait Router { /// and [`RouteParameters::final_value_msat`], respectively. fn find_route( &self, payer: &PublicKey, route_params: &RouteParameters, - first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs + first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs, ) -> Result; /// Finds a [`Route`] for a payment between the given `payer` and a payee. @@ -242,7 +287,7 @@ pub trait Router { fn find_route_with_id( &self, payer: &PublicKey, route_params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs, - _payment_hash: PaymentHash, _payment_id: PaymentId + _payment_hash: PaymentHash, _payment_id: PaymentId, ) -> Result { self.find_route(payer, route_params, first_hops, inflight_htlcs) } @@ -250,11 +295,9 @@ pub trait Router { /// Creates [`BlindedPaymentPath`]s for payment to the `recipient` node. The channels in `first_hops` /// are assumed to be with the `recipient`'s peers. The payment secret and any constraints are /// given in `tlvs`. - fn create_blinded_payment_paths< - T: secp256k1::Signing + secp256k1::Verification - > ( + fn create_blinded_payment_paths( &self, recipient: PublicKey, first_hops: Vec, tlvs: ReceiveTlvs, - amount_msats: Option, secp_ctx: &Secp256k1 + amount_msats: Option, secp_ctx: &Secp256k1, ) -> Result, ()>; } @@ -264,24 +307,32 @@ pub trait Router { /// [`find_route`]. /// /// [`ScoreLookUp`]: crate::routing::scoring::ScoreLookUp -pub struct ScorerAccountingForInFlightHtlcs<'a, S: Deref> where S::Target: ScoreLookUp { +pub struct ScorerAccountingForInFlightHtlcs<'a, S: Deref> +where + S::Target: ScoreLookUp, +{ scorer: S, // Maps a channel's short channel id and its direction to the liquidity used up. inflight_htlcs: &'a InFlightHtlcs, } -impl<'a, S: Deref> ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: ScoreLookUp { +impl<'a, S: Deref> ScorerAccountingForInFlightHtlcs<'a, S> +where + S::Target: ScoreLookUp, +{ /// Initialize a new `ScorerAccountingForInFlightHtlcs`. pub fn new(scorer: S, inflight_htlcs: &'a InFlightHtlcs) -> Self { - ScorerAccountingForInFlightHtlcs { - scorer, - inflight_htlcs - } + ScorerAccountingForInFlightHtlcs { scorer, inflight_htlcs } } } -impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> where S::Target: ScoreLookUp { +impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> +where + S::Target: ScoreLookUp, +{ type ScoreParams = ::ScoreParams; - fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 { + fn channel_penalty_msat( + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams, + ) -> u64 { let target = match candidate.target() { Some(target) => target, None => return self.scorer.channel_penalty_msat(candidate, usage, score_params), @@ -291,9 +342,9 @@ impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S> where None => return self.scorer.channel_penalty_msat(candidate, usage, score_params), }; let source = candidate.source(); - if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( - &source, &target, short_channel_id - ) { + if let Some(used_liquidity) = + self.inflight_htlcs.used_liquidity_msat(&source, &target, short_channel_id) + { let usage = ChannelUsage { inflight_htlc_msat: usage.inflight_htlc_msat.saturating_add(used_liquidity), ..usage @@ -314,16 +365,20 @@ pub struct InFlightHtlcs( // is traveling in. The direction boolean is determined by checking if the HTLC source's public // key is less than its destination. See `InFlightHtlcs::used_liquidity_msat` for more // details. - HashMap<(u64, bool), u64> + HashMap<(u64, bool), u64>, ); impl InFlightHtlcs { /// Constructs an empty `InFlightHtlcs`. - pub fn new() -> Self { InFlightHtlcs(new_hash_map()) } + pub fn new() -> Self { + InFlightHtlcs(new_hash_map()) + } /// Takes in a path with payer's node id and adds the path's details to `InFlightHtlcs`. pub fn process_path(&mut self, path: &Path, payer_node_id: PublicKey) { - if path.hops.is_empty() { return }; + if path.hops.is_empty() { + return; + }; let mut cumulative_msat = 0; if let Some(tail) = &path.blinded_tail { @@ -335,7 +390,11 @@ impl InFlightHtlcs { // the router excludes the payer node. In the following lines, the payer's information is // hardcoded with an inflight value of 0 so that we can correctly represent the first hop // in our sliding window of two. - let reversed_hops_with_payer = path.hops.iter().rev().skip(1) + let reversed_hops_with_payer = path + .hops + .iter() + .rev() + .skip(1) .map(|hop| hop.pubkey) .chain(core::iter::once(payer_node_id)); @@ -345,7 +404,10 @@ impl InFlightHtlcs { for (next_hop, prev_hop) in path.hops.iter().rev().zip(reversed_hops_with_payer) { cumulative_msat += next_hop.fee_msat; self.0 - .entry((next_hop.short_channel_id, NodeId::from_pubkey(&prev_hop) < NodeId::from_pubkey(&next_hop.pubkey))) + .entry(( + next_hop.short_channel_id, + NodeId::from_pubkey(&prev_hop) < NodeId::from_pubkey(&next_hop.pubkey), + )) .and_modify(|used_liquidity_msat| *used_liquidity_msat += cumulative_msat) .or_insert(cumulative_msat); } @@ -353,7 +415,9 @@ impl InFlightHtlcs { /// Adds a known HTLC given the public key of the HTLC source, target, and short channel /// id. - pub fn add_inflight_htlc(&mut self, source: &NodeId, target: &NodeId, channel_scid: u64, used_msat: u64){ + pub fn add_inflight_htlc( + &mut self, source: &NodeId, target: &NodeId, channel_scid: u64, used_msat: u64, + ) { self.0 .entry((channel_scid, source < target)) .and_modify(|used_liquidity_msat| *used_liquidity_msat += used_msat) @@ -362,13 +426,17 @@ impl InFlightHtlcs { /// Returns liquidity in msat given the public key of the HTLC source, target, and short channel /// id. - pub fn used_liquidity_msat(&self, source: &NodeId, target: &NodeId, channel_scid: u64) -> Option { + pub fn used_liquidity_msat( + &self, source: &NodeId, target: &NodeId, channel_scid: u64, + ) -> Option { self.0.get(&(channel_scid, source < target)).map(|v| *v) } } impl Writeable for InFlightHtlcs { - fn write(&self, writer: &mut W) -> Result<(), io::Error> { self.0.write(writer) } + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + self.0.write(writer) + } } impl Readable for InFlightHtlcs { @@ -498,9 +566,10 @@ impl Path { Some(_) => self.hops.iter().map(|hop| hop.fee_msat).sum::(), None => { // Do not count last hop of each path since that's the full value of the payment - self.hops.split_last().map_or(0, - |(_, path_prefix)| path_prefix.iter().map(|hop| hop.fee_msat).sum()) - } + self.hops + .split_last() + .map_or(0, |(_, path_prefix)| path_prefix.iter().map(|hop| hop.fee_msat).sum()) + }, } } @@ -508,7 +577,7 @@ impl Path { pub fn final_value_msat(&self) -> u64 { match &self.blinded_tail { Some(blinded_tail) => blinded_tail.final_value_msat, - None => self.hops.last().map_or(0, |hop| hop.fee_msat) + None => self.hops.last().map_or(0, |hop| hop.fee_msat), } } @@ -516,7 +585,7 @@ impl Path { pub fn final_cltv_expiry_delta(&self) -> Option { match &self.blinded_tail { Some(_) => None, - None => self.hops.last().map(|hop| hop.cltv_expiry_delta) + None => self.hops.last().map(|hop| hop.cltv_expiry_delta), } } @@ -551,7 +620,9 @@ impl Route { /// /// [`htlc_minimum_msat`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#the-channel_update-message pub fn get_total_fees(&self) -> u64 { - let overpaid_value_msat = self.route_params.as_ref() + let overpaid_value_msat = self + .route_params + .as_ref() .map_or(0, |p| self.get_total_amount().saturating_sub(p.final_value_msat)); overpaid_value_msat + self.paths.iter().map(|path| path.fee_msat()).sum::() } @@ -594,7 +665,9 @@ impl Writeable for Route { } } blinded_tails.push(Some(blinded_tail)); - } else if !blinded_tails.is_empty() { blinded_tails.push(None); } + } else if !blinded_tails.is_empty() { + blinded_tails.push(None); + } } write_tlv_fields!(writer, { // For compatibility with LDK versions prior to 0.0.117, we take the individual @@ -612,7 +685,9 @@ impl Readable for Route { fn read(reader: &mut R) -> Result { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let path_count: u64 = Readable::read(reader)?; - if path_count == 0 { return Err(DecodeError::InvalidValue); } + if path_count == 0 { + return Err(DecodeError::InvalidValue); + } let mut paths = Vec::with_capacity(cmp::min(path_count, 128) as usize); let mut min_final_cltv_expiry_delta = u32::max_value(); for _ in 0..path_count { @@ -621,7 +696,9 @@ impl Readable for Route { for _ in 0..hop_count { hops.push(Readable::read(reader)?); } - if hops.is_empty() { return Err(DecodeError::InvalidValue); } + if hops.is_empty() { + return Err(DecodeError::InvalidValue); + } min_final_cltv_expiry_delta = cmp::min(min_final_cltv_expiry_delta, hops.last().unwrap().cltv_expiry_delta); paths.push(Path { hops, blinded_tail: None }); @@ -634,7 +711,9 @@ impl Readable for Route { }); let blinded_tails = blinded_tails.unwrap_or(Vec::new()); if blinded_tails.len() != 0 { - if blinded_tails.len() != paths.len() { return Err(DecodeError::InvalidValue) } + if blinded_tails.len() != paths.len() { + return Err(DecodeError::InvalidValue); + } for (path, blinded_tail_opt) in paths.iter_mut().zip(blinded_tails.into_iter()) { path.blinded_tail = blinded_tail_opt; } @@ -642,9 +721,11 @@ impl Readable for Route { // If we previously wrote the corresponding fields, reconstruct RouteParameters. let route_params = match (payment_params, final_value_msat) { - (Some(payment_params), Some(final_value_msat)) => { - Some(RouteParameters { payment_params, final_value_msat, max_total_routing_fee_msat }) - } + (Some(payment_params), Some(final_value_msat)) => Some(RouteParameters { + payment_params, + final_value_msat, + max_total_routing_fee_msat, + }), _ => None, }; @@ -676,19 +757,29 @@ impl RouteParameters { /// Constructs [`RouteParameters`] from the given [`PaymentParameters`] and a payment amount. /// /// [`Self::max_total_routing_fee_msat`] defaults to 1% of the payment amount + 50 sats - pub fn from_payment_params_and_value(payment_params: PaymentParameters, final_value_msat: u64) -> Self { - Self { payment_params, final_value_msat, max_total_routing_fee_msat: Some(final_value_msat / 100 + 50_000) } + pub fn from_payment_params_and_value( + payment_params: PaymentParameters, final_value_msat: u64, + ) -> Self { + Self { + payment_params, + final_value_msat, + max_total_routing_fee_msat: Some(final_value_msat / 100 + 50_000), + } } /// Sets the maximum number of hops that can be included in a payment path, based on the provided /// [`RecipientOnionFields`] and blinded paths. pub fn set_max_path_length( - &mut self, recipient_onion: &RecipientOnionFields, is_keysend: bool, best_block_height: u32 + &mut self, recipient_onion: &RecipientOnionFields, is_keysend: bool, best_block_height: u32, ) -> Result<(), ()> { let keysend_preimage_opt = is_keysend.then(|| PaymentPreimage([42; 32])); // TODO: no way to account for the invoice request here yet onion_utils::set_max_path_length( - self, recipient_onion, keysend_preimage_opt, None, best_block_height + self, + recipient_onion, + keysend_preimage_opt, + None, + best_block_height, ) } } @@ -811,9 +902,10 @@ impl Writeable for PaymentParameters { match &self.payee { Payee::Clear { route_hints, .. } => clear_hints = route_hints, Payee::Blinded { route_hints, .. } => { - let hints_iter = route_hints.iter().map(|path| (&path.payinfo, path.inner_blinded_path())); + let hints_iter = + route_hints.iter().map(|path| (&path.payinfo, path.inner_blinded_path())); blinded_hints = Some(crate::util::ser::IterableOwned(hints_iter)); - } + }, } write_tlv_fields!(writer, { (0, self.payee.node_id(), option), @@ -834,7 +926,9 @@ impl Writeable for PaymentParameters { } impl ReadableArgs for PaymentParameters { - fn read(reader: &mut R, default_final_cltv_expiry_delta: u32) -> Result { + fn read( + reader: &mut R, default_final_cltv_expiry_delta: u32, + ) -> Result { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payee_pubkey, option), (1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)), @@ -851,7 +945,9 @@ impl ReadableArgs for PaymentParameters { }); let blinded_route_hints = blinded_route_hints.unwrap_or(vec![]); let payee = if blinded_route_hints.len() != 0 { - if clear_route_hints.len() != 0 || payee_pubkey.is_some() { return Err(DecodeError::InvalidValue) } + if clear_route_hints.len() != 0 || payee_pubkey.is_some() { + return Err(DecodeError::InvalidValue); + } Payee::Blinded { route_hints: blinded_route_hints .into_iter() @@ -868,19 +964,28 @@ impl ReadableArgs for PaymentParameters { } }; Ok(Self { - max_total_cltv_expiry_delta: _init_tlv_based_struct_field!(max_total_cltv_expiry_delta, (default_value, unused)), + max_total_cltv_expiry_delta: _init_tlv_based_struct_field!( + max_total_cltv_expiry_delta, + (default_value, unused) + ), max_path_count: _init_tlv_based_struct_field!(max_path_count, (default_value, unused)), payee, - max_channel_saturation_power_of_half: _init_tlv_based_struct_field!(max_channel_saturation_power_of_half, (default_value, unused)), + max_channel_saturation_power_of_half: _init_tlv_based_struct_field!( + max_channel_saturation_power_of_half, + (default_value, unused) + ), expiry_time, previously_failed_channels: previously_failed_channels.unwrap_or(Vec::new()), - previously_failed_blinded_path_idxs: previously_failed_blinded_path_idxs.unwrap_or(Vec::new()), - max_path_length: _init_tlv_based_struct_field!(max_path_length, (default_value, unused)), + previously_failed_blinded_path_idxs: previously_failed_blinded_path_idxs + .unwrap_or(Vec::new()), + max_path_length: _init_tlv_based_struct_field!( + max_path_length, + (default_value, unused) + ), }) } } - impl PaymentParameters { /// Creates a payee with the node id of the given `pubkey`. /// @@ -888,7 +993,12 @@ impl PaymentParameters { /// provided. pub fn from_node_id(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32) -> Self { Self { - payee: Payee::Clear { node_id: payee_pubkey, route_hints: vec![], features: None, final_cltv_expiry_delta }, + payee: Payee::Clear { + node_id: payee_pubkey, + route_hints: vec![], + features: None, + final_cltv_expiry_delta, + }, expiry_time: None, max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, max_path_count: DEFAULT_MAX_PATH_COUNT, @@ -910,10 +1020,14 @@ impl PaymentParameters { /// [`RecipientOnionFields::secret_only`]. /// /// [`RecipientOnionFields::secret_only`]: crate::ln::channelmanager::RecipientOnionFields::secret_only - pub fn for_keysend(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32, allow_mpp: bool) -> Self { + pub fn for_keysend( + payee_pubkey: PublicKey, final_cltv_expiry_delta: u32, allow_mpp: bool, + ) -> Self { Self::from_node_id(payee_pubkey, final_cltv_expiry_delta) .with_bolt11_features(Bolt11InvoiceFeatures::for_keysend(allow_mpp)) - .expect("PaymentParameters::from_node_id should always initialize the payee as unblinded") + .expect( + "PaymentParameters::from_node_id should always initialize the payee as unblinded", + ) } /// Creates parameters for paying to a blinded payee from the provided invoice. Sets @@ -942,8 +1056,11 @@ impl PaymentParameters { /// [`PaymentParameters::expiry_time`]. pub fn from_bolt12_invoice(invoice: &Bolt12Invoice) -> Self { Self::blinded(invoice.payment_paths().to_vec()) - .with_bolt12_features(invoice.invoice_features().clone()).unwrap() - .with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs())) + .with_bolt12_features(invoice.invoice_features().clone()) + .unwrap() + .with_expiry_time( + invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs()), + ) } /// Creates parameters for paying to a blinded payee from the provided invoice. Sets @@ -952,8 +1069,11 @@ impl PaymentParameters { #[cfg(async_payments)] pub fn from_static_invoice(invoice: &StaticInvoice) -> Self { Self::blinded(invoice.payment_paths().to_vec()) - .with_bolt12_features(invoice.invoice_features().clone()).unwrap() - .with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs())) + .with_bolt12_features(invoice.invoice_features().clone()) + .unwrap() + .with_expiry_time( + invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs()), + ) } /// Creates parameters for paying to a blinded payee from the provided blinded route hints. @@ -976,11 +1096,14 @@ impl PaymentParameters { /// We *do not* apply `max_total_routing_fee_msat` here, as it is unique to each route. /// Instead, we apply only the parameters that are common across multiple route-finding sessions /// for a payment across retries. - pub(crate) fn with_user_config_ignoring_fee_limit(self, params_config: RouteParametersConfig) -> Self { + pub(crate) fn with_user_config_ignoring_fee_limit( + self, params_config: RouteParametersConfig, + ) -> Self { Self { max_total_cltv_expiry_delta: params_config.max_total_cltv_expiry_delta, max_path_count: params_config.max_path_count, - max_channel_saturation_power_of_half: params_config.max_channel_saturation_power_of_half, + max_channel_saturation_power_of_half: params_config + .max_channel_saturation_power_of_half, ..self } } @@ -992,8 +1115,9 @@ impl PaymentParameters { pub fn with_bolt12_features(self, features: Bolt12InvoiceFeatures) -> Result { match self.payee { Payee::Clear { .. } => Err(()), - Payee::Blinded { route_hints, .. } => + Payee::Blinded { route_hints, .. } => { Ok(Self { payee: Payee::Blinded { route_hints, features: Some(features) }, ..self }) + }, } } @@ -1004,12 +1128,15 @@ impl PaymentParameters { pub fn with_bolt11_features(self, features: Bolt11InvoiceFeatures) -> Result { match self.payee { Payee::Blinded { .. } => Err(()), - Payee::Clear { route_hints, node_id, final_cltv_expiry_delta, .. } => - Ok(Self { - payee: Payee::Clear { - route_hints, node_id, features: Some(features), final_cltv_expiry_delta - }, ..self - }) + Payee::Clear { route_hints, node_id, final_cltv_expiry_delta, .. } => Ok(Self { + payee: Payee::Clear { + route_hints, + node_id, + features: Some(features), + final_cltv_expiry_delta, + }, + ..self + }), } } @@ -1020,12 +1147,10 @@ impl PaymentParameters { pub fn with_route_hints(self, route_hints: Vec) -> Result { match self.payee { Payee::Blinded { .. } => Err(()), - Payee::Clear { node_id, features, final_cltv_expiry_delta, .. } => - Ok(Self { - payee: Payee::Clear { - route_hints, node_id, features, final_cltv_expiry_delta, - }, ..self - }) + Payee::Clear { node_id, features, final_cltv_expiry_delta, .. } => Ok(Self { + payee: Payee::Clear { route_hints, node_id, features, final_cltv_expiry_delta }, + ..self + }), } } @@ -1054,15 +1179,19 @@ impl PaymentParameters { /// a power of 1/2. See [`PaymentParameters::max_channel_saturation_power_of_half`]. /// /// This is not exported to bindings users since bindings don't support move semantics - pub fn with_max_channel_saturation_power_of_half(self, max_channel_saturation_power_of_half: u8) -> Self { + pub fn with_max_channel_saturation_power_of_half( + self, max_channel_saturation_power_of_half: u8, + ) -> Self { Self { max_channel_saturation_power_of_half, ..self } } - pub(crate) fn insert_previously_failed_blinded_path(&mut self, failed_blinded_tail: &BlindedTail) { + pub(crate) fn insert_previously_failed_blinded_path( + &mut self, failed_blinded_tail: &BlindedTail, + ) { let mut found_blinded_tail = false; for (idx, path) in self.payee.blinded_route_hints().iter().enumerate() { - if &failed_blinded_tail.hops == path.blinded_hops() && - failed_blinded_tail.blinding_point == path.blinding_point() + if &failed_blinded_tail.hops == path.blinded_hops() + && failed_blinded_tail.blinding_point == path.blinding_point() { self.previously_failed_blinded_path_idxs.push(idx as u64); found_blinded_tail = true; @@ -1142,7 +1271,9 @@ impl RouteParametersConfig { /// a power of 1/2. See [`PaymentParameters::max_channel_saturation_power_of_half`]. /// /// This is not exported to bindings users since bindings don't support move semantics - pub fn with_max_channel_saturation_power_of_half(self, max_channel_saturation_power_of_half: u8) -> Self { + pub fn with_max_channel_saturation_power_of_half( + self, max_channel_saturation_power_of_half: u8, + ) -> Self { Self { max_channel_saturation_power_of_half, ..self } } } @@ -1208,8 +1339,12 @@ impl Payee { } fn supports_basic_mpp(&self) -> bool { match self { - Self::Clear { features, .. } => features.as_ref().map_or(false, |f| f.supports_basic_mpp()), - Self::Blinded { features, .. } => features.as_ref().map_or(false, |f| f.supports_basic_mpp()), + Self::Clear { features, .. } => { + features.as_ref().map_or(false, |f| f.supports_basic_mpp()) + }, + Self::Blinded { features, .. } => { + features.as_ref().map_or(false, |f| f.supports_basic_mpp()) + }, } } fn features(&self) -> Option { @@ -1227,21 +1362,21 @@ impl Payee { pub(crate) fn blinded_route_hints(&self) -> &[BlindedPaymentPath] { match self { Self::Blinded { route_hints, .. } => &route_hints[..], - Self::Clear { .. } => &[] + Self::Clear { .. } => &[], } } pub(crate) fn blinded_route_hints_mut(&mut self) -> &mut [BlindedPaymentPath] { match self { Self::Blinded { route_hints, .. } => &mut route_hints[..], - Self::Clear { .. } => &mut [] + Self::Clear { .. } => &mut [], } } fn unblinded_route_hints(&self) -> &[RouteHint] { match self { Self::Blinded { .. } => &[], - Self::Clear { route_hints, .. } => &route_hints[..] + Self::Clear { route_hints, .. } => &route_hints[..], } } } @@ -1281,7 +1416,9 @@ impl<'a> Writeable for FeaturesRef<'a> { impl ReadableArgs for Features { fn read(reader: &mut R, bolt11: bool) -> Result { - if bolt11 { return Ok(Self::Bolt11(Readable::read(reader)?)) } + if bolt11 { + return Ok(Self::Bolt11(Readable::read(reader)?)); + } Ok(Self::Bolt12(Readable::read(reader)?)) } } @@ -1335,7 +1472,9 @@ struct RouteGraphNode { impl cmp::Ord for RouteGraphNode { fn cmp(&self, other: &RouteGraphNode) -> cmp::Ordering { - other.score.cmp(&self.score) + other + .score + .cmp(&self.score) .then_with(|| self.value_contribution_msat.cmp(&other.value_contribution_msat)) .then_with(|| other.path_length_to_node.cmp(&self.path_length_to_node)) .then_with(|| other.node_counter.cmp(&self.node_counter)) @@ -1558,7 +1697,13 @@ impl<'a> CandidateRouteHop<'a> { #[inline] pub fn globally_unique_short_channel_id(&self) -> Option { match self { - CandidateRouteHop::FirstHop(hop) => if hop.details.is_announced { hop.details.short_channel_id } else { None }, + CandidateRouteHop::FirstHop(hop) => { + if hop.details.is_announced { + hop.details.short_channel_id + } else { + None + } + }, CandidateRouteHop::PublicHop(hop) => Some(hop.short_channel_id), CandidateRouteHop::PrivateHop(_) => None, CandidateRouteHop::Blinded(_) => None, @@ -1631,19 +1776,18 @@ impl<'a> CandidateRouteHop<'a> { #[inline] pub fn fees(&self) -> RoutingFees { match self { - CandidateRouteHop::FirstHop(_) => RoutingFees { - base_msat: 0, proportional_millionths: 0, + CandidateRouteHop::FirstHop(_) => { + RoutingFees { base_msat: 0, proportional_millionths: 0 } }, CandidateRouteHop::PublicHop(hop) => hop.info.direction().fees, CandidateRouteHop::PrivateHop(hop) => hop.hint.fees, - CandidateRouteHop::Blinded(hop) => { - RoutingFees { - base_msat: hop.hint.payinfo.fee_base_msat, - proportional_millionths: hop.hint.payinfo.fee_proportional_millionths - } + CandidateRouteHop::Blinded(hop) => RoutingFees { + base_msat: hop.hint.payinfo.fee_base_msat, + proportional_millionths: hop.hint.payinfo.fee_proportional_millionths, + }, + CandidateRouteHop::OneHopBlinded(_) => { + RoutingFees { base_msat: 0, proportional_millionths: 0 } }, - CandidateRouteHop::OneHopBlinded(_) => - RoutingFees { base_msat: 0, proportional_millionths: 0 }, } } @@ -1657,12 +1801,17 @@ impl<'a> CandidateRouteHop<'a> { liquidity_msat: hop.details.next_outbound_htlc_limit_msat, }, CandidateRouteHop::PublicHop(hop) => hop.info.effective_capacity(), - CandidateRouteHop::PrivateHop(PrivateHopCandidate { hint: RouteHintHop { htlc_maximum_msat: Some(max), .. }, .. }) => - EffectiveCapacity::HintMaxHTLC { amount_msat: *max }, - CandidateRouteHop::PrivateHop(PrivateHopCandidate { hint: RouteHintHop { htlc_maximum_msat: None, .. }, .. }) => - EffectiveCapacity::Infinite, - CandidateRouteHop::Blinded(hop) => - EffectiveCapacity::HintMaxHTLC { amount_msat: hop.hint.payinfo.htlc_maximum_msat }, + CandidateRouteHop::PrivateHop(PrivateHopCandidate { + hint: RouteHintHop { htlc_maximum_msat: Some(max), .. }, + .. + }) => EffectiveCapacity::HintMaxHTLC { amount_msat: *max }, + CandidateRouteHop::PrivateHop(PrivateHopCandidate { + hint: RouteHintHop { htlc_maximum_msat: None, .. }, + .. + }) => EffectiveCapacity::Infinite, + CandidateRouteHop::Blinded(hop) => { + EffectiveCapacity::HintMaxHTLC { amount_msat: hop.hint.payinfo.htlc_maximum_msat } + }, CandidateRouteHop::OneHopBlinded(_) => EffectiveCapacity::Infinite, } } @@ -1675,23 +1824,23 @@ impl<'a> CandidateRouteHop<'a> { match self { CandidateRouteHop::Blinded(hop) => CandidateHopId::Blinded(hop.hint_idx), CandidateRouteHop::OneHopBlinded(hop) => CandidateHopId::Blinded(hop.hint_idx), - _ => CandidateHopId::Clear((self.short_channel_id().unwrap(), self.source() < self.target().unwrap())), + _ => CandidateHopId::Clear(( + self.short_channel_id().unwrap(), + self.source() < self.target().unwrap(), + )), } } fn blinded_path(&self) -> Option<&'a BlindedPaymentPath> { match self { - CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => { - Some(&hint) - }, + CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) + | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => Some(&hint), _ => None, } } fn blinded_hint_idx(&self) -> Option { match self { - Self::Blinded(BlindedPathCandidate { hint_idx, .. }) | - Self::OneHopBlinded(OneHopBlindedPathCandidate { hint_idx, .. }) => { - Some(*hint_idx) - }, + Self::Blinded(BlindedPathCandidate { hint_idx, .. }) + | Self::OneHopBlinded(OneHopBlindedPathCandidate { hint_idx, .. }) => Some(*hint_idx), _ => None, } } @@ -1794,22 +1943,23 @@ impl<'a> NodeCountersBuilder<'a> { fn select_node_counter_for_id(&mut self, node_id: NodeId) -> u32 { // For any node_id, we first have to check if its in the existing network graph, and then // ensure that we always look up in our internal map first. - self.0.network_graph.nodes().get(&node_id) - .map(|node| node.node_counter) - .unwrap_or_else(|| { - let next_node_counter = self.0.network_graph.max_node_counter() + 1 + - self.0.private_node_id_to_node_counter.len() as u32; + self.0.network_graph.nodes().get(&node_id).map(|node| node.node_counter).unwrap_or_else( + || { + let next_node_counter = self.0.network_graph.max_node_counter() + + 1 + self.0.private_node_id_to_node_counter.len() as u32; *self.0.private_node_id_to_node_counter.entry(node_id).or_insert(next_node_counter) - }) + }, + ) } - fn build(self) -> NodeCounters<'a> { self.0 } + fn build(self) -> NodeCounters<'a> { + self.0 + } } impl<'a> NodeCounters<'a> { fn max_counter(&self) -> u32 { - self.network_graph.max_node_counter() + - self.private_node_id_to_node_counter.len() as u32 + self.network_graph.max_node_counter() + self.private_node_id_to_node_counter.len() as u32 } fn private_node_counter_from_pubkey(&self, pubkey: &PublicKey) -> Option<&(NodeId, u32)> { @@ -1817,11 +1967,14 @@ impl<'a> NodeCounters<'a> { } fn node_counter_from_id(&self, node_id: &NodeId) -> Option<(&NodeId, u32)> { - self.private_node_id_to_node_counter.get_key_value(node_id).map(|(a, b)| (a, *b)) - .or_else(|| { - self.network_graph.nodes().get_key_value(node_id) + self.private_node_id_to_node_counter.get_key_value(node_id).map(|(a, b)| (a, *b)).or_else( + || { + self.network_graph + .nodes() + .get_key_value(node_id) .map(|(node_id, node)| (node_id, node.node_counter)) - }) + }, + ) } } @@ -1832,8 +1985,13 @@ fn calculate_blinded_path_intro_points<'a, L: Deref>( network_graph: &ReadOnlyNetworkGraph, logger: &L, our_node_id: NodeId, first_hop_targets: &HashMap, u32)>, ) -> Result>, &'static str> -where L::Target: Logger { - let introduction_node_id_cache = payment_params.payee.blinded_route_hints().iter() +where + L::Target: Logger, +{ + let introduction_node_id_cache = payment_params + .payee + .blinded_route_hints() + .iter() .map(|path| { match path.introduction_node() { IntroductionNode::NodeId(pubkey) => { @@ -1841,18 +1999,20 @@ where L::Target: Logger { // us (i.e. a channel counterparty or in the network graph). node_counters.node_counter_from_id(&NodeId::from_pubkey(&pubkey)) }, - IntroductionNode::DirectedShortChannelId(direction, scid) => { - path.public_introduction_node_id(network_graph) - .map(|node_id_ref| *node_id_ref) - .or_else(|| { - first_hop_targets.iter().find(|(_, (channels, _))| - channels - .iter() - .any(|details| Some(*scid) == details.get_outbound_payment_scid()) - ).map(|(cp, _)| direction.select_node_id(our_node_id, *cp)) - }) - .and_then(|node_id| node_counters.node_counter_from_id(&node_id)) - }, + IntroductionNode::DirectedShortChannelId(direction, scid) => path + .public_introduction_node_id(network_graph) + .map(|node_id_ref| *node_id_ref) + .or_else(|| { + first_hop_targets + .iter() + .find(|(_, (channels, _))| { + channels.iter().any(|details| { + Some(*scid) == details.get_outbound_payment_scid() + }) + }) + .map(|(cp, _)| direction.select_node_id(our_node_id, *cp)) + }) + .and_then(|node_id| node_counters.node_counter_from_id(&node_id)), } }) .collect::>(); @@ -1867,10 +2027,15 @@ where L::Target: Logger { } }, Payee::Blinded { route_hints, .. } => { - if introduction_node_id_cache.iter().all(|info_opt| info_opt.map(|(a, _)| a) == Some(&our_node_id)) { + if introduction_node_id_cache + .iter() + .all(|info_opt| info_opt.map(|(a, _)| a) == Some(&our_node_id)) + { return Err("Cannot generate a route to blinded paths if we are the introduction node to all of them"); } - for (blinded_path, info_opt) in route_hints.iter().zip(introduction_node_id_cache.iter()) { + for (blinded_path, info_opt) in + route_hints.iter().zip(introduction_node_id_cache.iter()) + { if blinded_path.blinded_hops().len() == 0 { return Err("0-hop blinded path provided"); } @@ -1879,47 +2044,64 @@ where L::Target: Logger { Some(info) => info.0, }; if *introduction_node_id == our_node_id { - log_info!(logger, "Got blinded path with ourselves as the introduction node, ignoring"); - } else if blinded_path.blinded_hops().len() == 1 && - route_hints - .iter().zip(introduction_node_id_cache.iter()) + log_info!( + logger, + "Got blinded path with ourselves as the introduction node, ignoring" + ); + } else if blinded_path.blinded_hops().len() == 1 + && route_hints + .iter() + .zip(introduction_node_id_cache.iter()) .filter(|(p, _)| p.blinded_hops().len() == 1) - .any(|(_, iter_info_opt)| iter_info_opt.is_some() && iter_info_opt != info_opt) - { + .any(|(_, iter_info_opt)| { + iter_info_opt.is_some() && iter_info_opt != info_opt + }) { return Err("1-hop blinded paths must all have matching introduction node ids"); } } - } + }, } Ok(introduction_node_id_cache) } #[inline] -fn max_htlc_from_capacity(capacity: EffectiveCapacity, max_channel_saturation_power_of_half: u8) -> u64 { +fn max_htlc_from_capacity( + capacity: EffectiveCapacity, max_channel_saturation_power_of_half: u8, +) -> u64 { let saturation_shift: u32 = max_channel_saturation_power_of_half as u32; match capacity { EffectiveCapacity::ExactLiquidity { liquidity_msat } => liquidity_msat, EffectiveCapacity::Infinite => u64::max_value(), EffectiveCapacity::Unknown => EffectiveCapacity::Unknown.as_msat(), - EffectiveCapacity::AdvertisedMaxHTLC { amount_msat } => - amount_msat.checked_shr(saturation_shift).unwrap_or(0), + EffectiveCapacity::AdvertisedMaxHTLC { amount_msat } => { + amount_msat.checked_shr(saturation_shift).unwrap_or(0) + }, // Treat htlc_maximum_msat from a route hint as an exact liquidity amount, since the invoice is // expected to have been generated from up-to-date capacity information. EffectiveCapacity::HintMaxHTLC { amount_msat } => amount_msat, - EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat } => - cmp::min(capacity_msat.checked_shr(saturation_shift).unwrap_or(0), htlc_maximum_msat), + EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat } => { + cmp::min(capacity_msat.checked_shr(saturation_shift).unwrap_or(0), htlc_maximum_msat) + }, } } -fn iter_equal(mut iter_a: I1, mut iter_b: I2) --> bool where I1::Item: PartialEq { +fn iter_equal(mut iter_a: I1, mut iter_b: I2) -> bool +where + I1::Item: PartialEq, +{ loop { let a = iter_a.next(); let b = iter_b.next(); - if a.is_none() && b.is_none() { return true; } - if a.is_none() || b.is_none() { return false; } - if a.unwrap().ne(&b.unwrap()) { return false; } + if a.is_none() && b.is_none() { + return true; + } + if a.is_none() || b.is_none() { + return false; + } + if a.unwrap().ne(&b.unwrap()) { + return false; + } } } @@ -1978,7 +2160,8 @@ struct PathBuildingHop<'a> { } const _NODE_MAP_SIZE_TWO_CACHE_LINES: usize = 128 - core::mem::size_of::>(); -const _NODE_MAP_SIZE_EXACTLY_TWO_CACHE_LINES: usize = core::mem::size_of::>() - 128; +const _NODE_MAP_SIZE_EXACTLY_TWO_CACHE_LINES: usize = + core::mem::size_of::>() - 128; impl<'a> core::fmt::Debug for PathBuildingHop<'a> { fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { @@ -1992,7 +2175,13 @@ impl<'a> core::fmt::Debug for PathBuildingHop<'a> { .field("total_fee_msat", &self.total_fee_msat) .field("next_hops_fee_msat", &self.next_hops_fee_msat) .field("hop_use_fee_msat", &self.hop_use_fee_msat) - .field("total_fee_msat - (next_hops_fee_msat + hop_use_fee_msat)", &(&self.total_fee_msat.saturating_sub(self.next_hops_fee_msat).saturating_sub(self.hop_use_fee_msat))) + .field( + "total_fee_msat - (next_hops_fee_msat + hop_use_fee_msat)", + &(&self + .total_fee_msat + .saturating_sub(self.next_hops_fee_msat) + .saturating_sub(self.hop_use_fee_msat)), + ) .field("path_penalty_msat", &self.path_penalty_msat) .field("path_htlc_minimum_msat", &self.path_htlc_minimum_msat) .field("cltv_expiry_delta", &self.candidate.cltv_expiry_delta()) @@ -2071,7 +2260,9 @@ impl<'a> PaymentPath<'a> { // set it too high just to maliciously take more fees by exploiting this // match htlc_minimum_msat logic. let mut cur_hop_transferred_amount_msat = total_fee_paid_msat + value_msat; - if let Some(extra_fees_msat) = cur_hop.candidate.htlc_minimum_msat().checked_sub(cur_hop_transferred_amount_msat) { + if let Some(extra_fees_msat) = + cur_hop.candidate.htlc_minimum_msat().checked_sub(cur_hop_transferred_amount_msat) + { // Note that there is a risk that *previous hops* (those closer to us, as we go // payee->our_node here) would exceed their htlc_maximum_msat or available balance. // @@ -2106,7 +2297,9 @@ impl<'a> PaymentPath<'a> { // Irrelevant for the first hop, as it doesn't have the previous hop, and the use of // this channel is free for us. if i != 0 { - if let Some(new_fee) = compute_fees(cur_hop_transferred_amount_msat, cur_hop.candidate.fees()) { + if let Some(new_fee) = + compute_fees(cur_hop_transferred_amount_msat, cur_hop.candidate.fees()) + { cur_hop.hop_use_fee_msat = new_fee; total_fee_paid_msat += new_fee; } else { @@ -2124,7 +2317,8 @@ impl<'a> PaymentPath<'a> { #[inline(always)] /// Calculate the fees required to route the given amount over a channel with the given fees. fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option { - amount_msat.checked_mul(channel_fees.proportional_millionths as u64) + amount_msat + .checked_mul(channel_fees.proportional_millionths as u64) .and_then(|part| (channel_fees.base_msat as u64).checked_add(part / 1_000_000)) } @@ -2132,8 +2326,10 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option { /// Calculate the fees required to route the given amount over a channel with the given fees, /// saturating to [`u64::max_value`]. fn compute_fees_saturating(amount_msat: u64, channel_fees: RoutingFees) -> u64 { - amount_msat.checked_mul(channel_fees.proportional_millionths as u64) - .map(|prop| prop / 1_000_000).unwrap_or(u64::max_value()) + amount_msat + .checked_mul(channel_fees.proportional_millionths as u64) + .map(|prop| prop / 1_000_000) + .unwrap_or(u64::max_value()) .saturating_add(channel_fees.base_msat as u64) } @@ -2156,9 +2352,7 @@ impl fmt::Display for LoggedPayeePubkey { "payee node id ".fmt(f)?; pk.fmt(f) }, - None => { - "blinded payee".fmt(f) - }, + None => "blinded payee".fmt(f), } } } @@ -2167,20 +2361,19 @@ struct LoggedCandidateHop<'a>(&'a CandidateRouteHop<'a>); impl<'a> fmt::Display for LoggedCandidateHop<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => { + CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) + | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => { "blinded route hint with introduction node ".fmt(f)?; match hint.introduction_node() { IntroductionNode::NodeId(pubkey) => write!(f, "id {}", pubkey)?, - IntroductionNode::DirectedShortChannelId(direction, scid) => { - match direction { - Direction::NodeOne => { - write!(f, "one on channel with SCID {}", scid)?; - }, - Direction::NodeTwo => { - write!(f, "two on channel with SCID {}", scid)?; - }, - } - } + IntroductionNode::DirectedShortChannelId(direction, scid) => match direction { + Direction::NodeOne => { + write!(f, "one on channel with SCID {}", scid)?; + }, + Direction::NodeTwo => { + write!(f, "two on channel with SCID {}", scid)?; + }, + }, } " and blinding point ".fmt(f)?; hint.blinding_point().fmt(f) @@ -2204,7 +2397,7 @@ impl<'a> fmt::Display for LoggedCandidateHop<'a> { #[inline] fn sort_first_hop_channels( channels: &mut Vec<&ChannelDetails>, used_liquidities: &HashMap, - recommended_value_msat: u64, our_node_pubkey: &PublicKey + recommended_value_msat: u64, our_node_pubkey: &PublicKey, ) { // Sort the first_hops channels to the same node(s) in priority order of which channel we'd // most like to use. @@ -2220,13 +2413,25 @@ fn sort_first_hop_channels( // // Available outbound balances factor in liquidity already reserved for previously found paths. channels.sort_unstable_by(|chan_a, chan_b| { - let chan_a_outbound_limit_msat = chan_a.next_outbound_htlc_limit_msat - .saturating_sub(*used_liquidities.get(&CandidateHopId::Clear((chan_a.get_outbound_payment_scid().unwrap(), - our_node_pubkey < &chan_a.counterparty.node_id))).unwrap_or(&0)); - let chan_b_outbound_limit_msat = chan_b.next_outbound_htlc_limit_msat - .saturating_sub(*used_liquidities.get(&CandidateHopId::Clear((chan_b.get_outbound_payment_scid().unwrap(), - our_node_pubkey < &chan_b.counterparty.node_id))).unwrap_or(&0)); - if chan_b_outbound_limit_msat < recommended_value_msat || chan_a_outbound_limit_msat < recommended_value_msat { + let chan_a_outbound_limit_msat = chan_a.next_outbound_htlc_limit_msat.saturating_sub( + *used_liquidities + .get(&CandidateHopId::Clear(( + chan_a.get_outbound_payment_scid().unwrap(), + our_node_pubkey < &chan_a.counterparty.node_id, + ))) + .unwrap_or(&0), + ); + let chan_b_outbound_limit_msat = chan_b.next_outbound_htlc_limit_msat.saturating_sub( + *used_liquidities + .get(&CandidateHopId::Clear(( + chan_b.get_outbound_payment_scid().unwrap(), + our_node_pubkey < &chan_b.counterparty.node_id, + ))) + .unwrap_or(&0), + ); + if chan_b_outbound_limit_msat < recommended_value_msat + || chan_a_outbound_limit_msat < recommended_value_msat + { // Sort in descending order chan_b_outbound_limit_msat.cmp(&chan_a_outbound_limit_msat) } else { @@ -2262,25 +2467,42 @@ fn sort_first_hop_channels( /// [`Event::PaymentPathFailed`]: crate::events::Event::PaymentPathFailed /// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph pub fn find_route( - our_node_pubkey: &PublicKey, route_params: &RouteParameters, - network_graph: &NetworkGraph, first_hops: Option<&[&ChannelDetails]>, logger: L, - scorer: &S, score_params: &S::ScoreParams, random_seed_bytes: &[u8; 32] + our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &NetworkGraph, + first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &S::ScoreParams, + random_seed_bytes: &[u8; 32], ) -> Result -where L::Target: Logger, GL::Target: Logger { +where + L::Target: Logger, + GL::Target: Logger, +{ let graph_lock = network_graph.read_only(); - let mut route = get_route(our_node_pubkey, &route_params, &graph_lock, first_hops, logger, - scorer, score_params, random_seed_bytes)?; - add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes); + let mut route = get_route( + our_node_pubkey, + &route_params, + &graph_lock, + first_hops, + logger, + scorer, + score_params, + random_seed_bytes, + )?; + add_random_cltv_offset( + &mut route, + &route_params.payment_params, + &graph_lock, + random_seed_bytes, + ); Ok(route) } pub(crate) fn get_route( - our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &ReadOnlyNetworkGraph, - first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &S::ScoreParams, - _random_seed_bytes: &[u8; 32] + our_node_pubkey: &PublicKey, route_params: &RouteParameters, + network_graph: &ReadOnlyNetworkGraph, first_hops: Option<&[&ChannelDetails]>, logger: L, + scorer: &S, score_params: &S::ScoreParams, _random_seed_bytes: &[u8; 32], ) -> Result -where L::Target: Logger { - +where + L::Target: Logger, +{ let payment_params = &route_params.payment_params; let max_path_length = core::cmp::min(payment_params.max_path_length, MAX_PATH_LENGTH_ESTIMATE); let final_value_msat = route_params.final_value_msat; @@ -2289,7 +2511,10 @@ where L::Target: Logger { // so use a dummy id for this in the blinded case. let payee_node_id_opt = payment_params.payee.node_id().map(|pk| NodeId::from_pubkey(&pk)); const DUMMY_BLINDED_PAYEE_ID: [u8; 33] = [2; 33]; - let maybe_dummy_payee_pk = payment_params.payee.node_id().unwrap_or_else(|| PublicKey::from_slice(&DUMMY_BLINDED_PAYEE_ID).unwrap()); + let maybe_dummy_payee_pk = payment_params + .payee + .node_id() + .unwrap_or_else(|| PublicKey::from_slice(&DUMMY_BLINDED_PAYEE_ID).unwrap()); let maybe_dummy_payee_node_id = NodeId::from_pubkey(&maybe_dummy_payee_pk); let our_node_id = NodeId::from_pubkey(&our_node_pubkey); @@ -2384,11 +2609,17 @@ where L::Target: Logger { } else if payment_params.payee.supports_basic_mpp() { true } else if let Some(payee) = payee_node_id_opt { - network_nodes.get(&payee).map_or(false, |node| node.announcement_info.as_ref().map_or(false, - |info| info.features().supports_basic_mpp())) - } else { false }; + network_nodes.get(&payee).map_or(false, |node| { + node.announcement_info + .as_ref() + .map_or(false, |info| info.features().supports_basic_mpp()) + }) + } else { + false + }; - let max_total_routing_fee_msat = route_params.max_total_routing_fee_msat.unwrap_or(u64::max_value()); + let max_total_routing_fee_msat = + route_params.max_total_routing_fee_msat.unwrap_or(u64::max_value()); let first_hop_count = first_hops.map(|hops| hops.len()).unwrap_or(0); log_trace!(logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph of {} nodes and {} channels with a fee limit of {} msat", @@ -2416,7 +2647,8 @@ where L::Target: Logger { let mut node_counter_builder = NodeCountersBuilder::new(&network_graph); let payer_node_counter = node_counter_builder.select_node_counter_for_pubkey(*our_node_pubkey); - let payee_node_counter = node_counter_builder.select_node_counter_for_pubkey(maybe_dummy_payee_pk); + let payee_node_counter = + node_counter_builder.select_node_counter_for_pubkey(maybe_dummy_payee_pk); for route in payment_params.payee.unblinded_route_hints().iter() { for hop in route.0.iter() { @@ -2431,7 +2663,11 @@ where L::Target: Logger { // For blinded last-hop paths, look up their introduction point and cache the node counters // identifying them. let mut first_hop_targets: HashMap<_, (Vec<&ChannelDetails>, u32)> = - hash_map_with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 }); + hash_map_with_capacity(if first_hops.is_some() { + first_hops.as_ref().unwrap().len() + } else { + 0 + }); if let Some(hops) = first_hops { for chan in hops { if chan.get_outbound_payment_scid().is_none() { @@ -2445,10 +2681,12 @@ where L::Target: Logger { .entry(counterparty_id) .or_insert_with(|| { // Make sure there's a counter assigned for the counterparty - let node_counter = node_counter_builder.select_node_counter_for_id(counterparty_id); + let node_counter = + node_counter_builder.select_node_counter_for_id(counterparty_id); (Vec::new(), node_counter) }) - .0.push(chan); + .0 + .push(chan); } if first_hop_targets.is_empty() { return Err("Cannot route when there are no outbound routes away from us"); @@ -2458,35 +2696,41 @@ where L::Target: Logger { let node_counters = node_counter_builder.build(); let introduction_node_id_cache = calculate_blinded_path_intro_points( - &payment_params, &node_counters, network_graph, &logger, our_node_id, &first_hop_targets, + &payment_params, + &node_counters, + network_graph, + &logger, + our_node_id, + &first_hop_targets, )?; let mut last_hop_candidates = hash_map_with_capacity(payment_params.payee.unblinded_route_hints().len()); - for route in payment_params.payee.unblinded_route_hints().iter() - .filter(|route| !route.0.is_empty()) + for route in + payment_params.payee.unblinded_route_hints().iter().filter(|route| !route.0.is_empty()) { let hop_iter = route.0.iter().rev(); - let prev_hop_iter = core::iter::once(&maybe_dummy_payee_pk).chain( - route.0.iter().skip(1).rev().map(|hop| &hop.src_node_id)); + let prev_hop_iter = core::iter::once(&maybe_dummy_payee_pk) + .chain(route.0.iter().skip(1).rev().map(|hop| &hop.src_node_id)); for (hop, prev_hop_id) in hop_iter.zip(prev_hop_iter) { let (target, private_target_node_counter) = - node_counters.private_node_counter_from_pubkey(&prev_hop_id) - .ok_or_else(|| { - debug_assert!(false); - "We should always have private target node counters available" - })?; - let (_src_id, private_source_node_counter) = - node_counters.private_node_counter_from_pubkey(&hop.src_node_id) - .ok_or_else(|| { - debug_assert!(false); - "We should always have private source node counters available" - })?; + node_counters.private_node_counter_from_pubkey(&prev_hop_id).ok_or_else(|| { + debug_assert!(false); + "We should always have private target node counters available" + })?; + let (_src_id, private_source_node_counter) = node_counters + .private_node_counter_from_pubkey(&hop.src_node_id) + .ok_or_else(|| { + debug_assert!(false); + "We should always have private source node counters available" + })?; if let Some((first_channels, _)) = first_hop_targets.get(target) { - let matches_an_scid = |d: &&ChannelDetails| - d.outbound_scid_alias == Some(hop.short_channel_id) || d.short_channel_id == Some(hop.short_channel_id); + let matches_an_scid = |d: &&ChannelDetails| { + d.outbound_scid_alias == Some(hop.short_channel_id) + || d.short_channel_id == Some(hop.short_channel_id) + }; if first_channels.iter().any(matches_an_scid) { log_trace!(logger, "Ignoring route hint with SCID {} (and any previous) due to it being a direct channel of ours.", hop.short_channel_id); @@ -2497,17 +2741,25 @@ where L::Target: Logger { let candidate = network_channels .get(&hop.short_channel_id) .and_then(|channel| channel.as_directed_to(target)) - .map(|(info, _)| CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: hop.short_channel_id, - })) - .unwrap_or_else(|| CandidateRouteHop::PrivateHop(PrivateHopCandidate { - hint: hop, target_node_id: target, - source_node_counter: *private_source_node_counter, - target_node_counter: *private_target_node_counter, - })); + .map(|(info, _)| { + CandidateRouteHop::PublicHop(PublicHopCandidate { + info, + short_channel_id: hop.short_channel_id, + }) + }) + .unwrap_or_else(|| { + CandidateRouteHop::PrivateHop(PrivateHopCandidate { + hint: hop, + target_node_id: target, + source_node_counter: *private_source_node_counter, + target_node_counter: *private_target_node_counter, + }) + }); - last_hop_candidates.entry(private_target_node_counter).or_insert_with(Vec::new).push(candidate); + last_hop_candidates + .entry(private_target_node_counter) + .or_insert_with(Vec::new) + .push(candidate); } } @@ -2544,7 +2796,8 @@ where L::Target: Logger { // This requirement is currently set to be 1/max_path_count of the payment // value to ensure we only ever return routes that do not violate this limit. let minimal_value_contribution_msat: u64 = if allow_mpp { - (final_value_msat + (payment_params.max_path_count as u64 - 1)) / payment_params.max_path_count as u64 + (final_value_msat + (payment_params.max_path_count as u64 - 1)) + / payment_params.max_path_count as u64 } else { final_value_msat }; @@ -2567,12 +2820,21 @@ where L::Target: Logger { let mut already_collected_value_msat = 0; for (_, (channels, _)) in first_hop_targets.iter_mut() { - sort_first_hop_channels(channels, &used_liquidities, recommended_value_msat, - our_node_pubkey); + sort_first_hop_channels( + channels, + &used_liquidities, + recommended_value_msat, + our_node_pubkey, + ); } - log_trace!(logger, "Building path from {} to payer {} for value {} msat.", - LoggedPayeePubkey(payment_params.payee.node_id()), our_node_pubkey, final_value_msat); + log_trace!( + logger, + "Building path from {} to payer {} for value {} msat.", + LoggedPayeePubkey(payment_params.payee.node_id()), + our_node_pubkey, + final_value_msat + ); // Remember how many candidates we ignored to allow for some logging afterwards. let mut num_ignored_value_contribution: u32 = 0; @@ -2969,25 +3231,39 @@ where L::Target: Logger { if is_last_hop_target { if let Some(candidates) = last_hop_candidates.get(&$node_counter) { for candidate in candidates { - add_entry!(candidate, fee_to_target_msat, + add_entry!( + candidate, + fee_to_target_msat, $next_hops_value_contribution, - next_hops_path_htlc_minimum_msat, next_hops_path_penalty_msat, - $next_hops_cltv_delta, $next_hops_path_length); + next_hops_path_htlc_minimum_msat, + next_hops_path_penalty_msat, + $next_hops_cltv_delta, + $next_hops_path_length + ); } } } if is_first_hop_target { - if let Some((first_channels, peer_node_counter)) = first_hop_targets.get(&$node_id) { + if let Some((first_channels, peer_node_counter)) = + first_hop_targets.get(&$node_id) + { for details in first_channels { debug_assert_eq!(*peer_node_counter, $node_counter); let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate { - details, payer_node_id: &our_node_id, payer_node_counter, + details, + payer_node_id: &our_node_id, + payer_node_counter, target_node_counter: $node_counter, }); - add_entry!(&candidate, fee_to_target_msat, + add_entry!( + &candidate, + fee_to_target_msat, $next_hops_value_contribution, - next_hops_path_htlc_minimum_msat, next_hops_path_penalty_msat, - $next_hops_cltv_delta, $next_hops_path_length); + next_hops_path_htlc_minimum_msat, + next_hops_path_penalty_msat, + $next_hops_cltv_delta, + $next_hops_path_length + ); } } } @@ -3003,19 +3279,25 @@ where L::Target: Logger { for chan_id in node.channels.iter() { let chan = network_channels.get(chan_id).unwrap(); if !chan.features.requires_unknown_bits() { - if let Some((directed_channel, source)) = chan.as_directed_to(&$node_id) { + if let Some((directed_channel, source)) = + chan.as_directed_to(&$node_id) + { if first_hops.is_none() || *source != our_node_id { if directed_channel.direction().enabled { - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info: directed_channel, - short_channel_id: *chan_id, - }); - add_entry!(&candidate, + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { + info: directed_channel, + short_channel_id: *chan_id, + }); + add_entry!( + &candidate, fee_to_target_msat, $next_hops_value_contribution, next_hops_path_htlc_minimum_msat, next_hops_path_penalty_msat, - $next_hops_cltv_delta, $next_hops_path_length); + $next_hops_cltv_delta, + $next_hops_path_length + ); } } } @@ -3083,7 +3365,9 @@ where L::Target: Logger { // Note that all the fields (except `is_{first,last}_hop_target`) will be overwritten // whenever we find a path to the target, so are left as dummies here. debug_assert!(!candidates.is_empty()); - if candidates.is_empty() { continue } + if candidates.is_empty() { + continue; + } let entry = &mut dist[**target_node_counter as usize]; if let Some(hop) = entry { hop.is_last_hop_target = true; @@ -3119,7 +3403,12 @@ where L::Target: Logger { entry.value_contribution_msat = path_value_msat; } add_entries_to_cheapest_to_target_node!( - network_nodes.get(&payee), payee_node_counter, payee, path_value_msat, 0, 0 + network_nodes.get(&payee), + payee_node_counter, + payee, + path_value_msat, + 0, + 0 ); } @@ -3128,26 +3417,39 @@ where L::Target: Logger { introduction_node_id_cache.len(), "introduction_node_id_cache was built by iterating the blinded_route_hints, so they should be the same len" ); - let mut blind_intros_added = hash_map_with_capacity(payment_params.payee.blinded_route_hints().len()); + let mut blind_intros_added = + hash_map_with_capacity(payment_params.payee.blinded_route_hints().len()); for (hint_idx, hint) in payment_params.payee.blinded_route_hints().iter().enumerate() { // Only add the hops in this route to our candidate set if either // we have a direct channel to the first hop or the first hop is // in the regular network graph. let source_node_opt = introduction_node_id_cache[hint_idx]; - let (source_node_id, source_node_counter) = if let Some(v) = source_node_opt { v } else { continue }; - if our_node_id == *source_node_id { continue } + let (source_node_id, source_node_counter) = + if let Some(v) = source_node_opt { v } else { continue }; + if our_node_id == *source_node_id { + continue; + } let candidate = if hint.blinded_hops().len() == 1 { - CandidateRouteHop::OneHopBlinded( - OneHopBlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx } - ) + CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { + source_node_counter, + source_node_id, + hint, + hint_idx, + }) } else { - CandidateRouteHop::Blinded(BlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx }) + CandidateRouteHop::Blinded(BlindedPathCandidate { + source_node_counter, + source_node_id, + hint, + hint_idx, + }) }; - if let Some(hop_used_msat) = add_entry!(&candidate, - 0, path_value_msat, 0, 0_u64, 0, 0) + if let Some(hop_used_msat) = add_entry!(&candidate, 0, path_value_msat, 0, 0_u64, 0, 0) { blind_intros_added.insert(source_node_id, (hop_used_msat, candidate)); - } else { continue } + } else { + continue; + } } // If we added a blinded path from an introduction node to the destination, where the // introduction node is one of our direct peers, we need to scan our `first_channels` @@ -3158,28 +3460,48 @@ where L::Target: Logger { // Thus, we track the nodes that we added paths from in `blind_intros_added` and scan for // introduction points we have a channel with after processing all blinded paths. for (source_node_id, (path_contribution_msat, candidate)) in blind_intros_added { - if let Some((first_channels, peer_node_counter)) = first_hop_targets.get_mut(source_node_id) { + if let Some((first_channels, peer_node_counter)) = + first_hop_targets.get_mut(source_node_id) + { sort_first_hop_channels( - first_channels, &used_liquidities, recommended_value_msat, our_node_pubkey + first_channels, + &used_liquidities, + recommended_value_msat, + our_node_pubkey, ); for details in first_channels { let first_hop_candidate = CandidateRouteHop::FirstHop(FirstHopCandidate { - details, payer_node_id: &our_node_id, payer_node_counter, + details, + payer_node_id: &our_node_id, + payer_node_counter, target_node_counter: *peer_node_counter, }); - let blinded_path_fee = match compute_fees(path_contribution_msat, candidate.fees()) { - Some(fee) => fee, - None => continue - }; + let blinded_path_fee = + match compute_fees(path_contribution_msat, candidate.fees()) { + Some(fee) => fee, + None => continue, + }; let path_min = candidate.htlc_minimum_msat().saturating_add( - compute_fees_saturating(candidate.htlc_minimum_msat(), candidate.fees())); - add_entry!(&first_hop_candidate, blinded_path_fee, path_contribution_msat, path_min, - 0_u64, candidate.cltv_expiry_delta(), 0); + compute_fees_saturating(candidate.htlc_minimum_msat(), candidate.fees()), + ); + add_entry!( + &first_hop_candidate, + blinded_path_fee, + path_contribution_msat, + path_min, + 0_u64, + candidate.cltv_expiry_delta(), + 0 + ); } } } - log_trace!(logger, "Starting main path collection loop with {} nodes pre-filled from first/last hops.", targets.len()); + log_trace!( + logger, + "Starting main path collection loop with {} nodes pre-filled from first/last hops.", + targets.len() + ); // At this point, targets are filled with the data from first and // last hops communicated by the caller, and the payment receiver. @@ -3194,13 +3516,21 @@ where L::Target: Logger { // Both these cases (and other cases except reaching recommended_value_msat) mean that // paths_collection will be stopped because found_new_path==false. // This is not necessarily a routing failure. - 'path_construction: while let Some(RouteGraphNode { node_id, node_counter, total_cltv_delta, mut value_contribution_msat, path_length_to_node, .. }) = targets.pop() { - + 'path_construction: while let Some(RouteGraphNode { + node_id, + node_counter, + total_cltv_delta, + mut value_contribution_msat, + path_length_to_node, + .. + }) = targets.pop() + { // Since we're going payee-to-payer, hitting our node as a target means we should stop // traversing the graph and arrange the path out of what we found. if node_id == our_node_id { let mut new_entry = dist[payer_node_counter as usize].take().unwrap(); - let mut ordered_hops: Vec<(PathBuildingHop, NodeFeatures)> = vec!((new_entry.clone(), default_node_features.clone())); + let mut ordered_hops: Vec<(PathBuildingHop, NodeFeatures)> = + vec![(new_entry.clone(), default_node_features.clone())]; 'path_walk: loop { let mut features_set = false; @@ -3209,11 +3539,16 @@ where L::Target: Logger { let target_node_counter = candidate.target_node_counter(); if let Some((first_channels, _)) = first_hop_targets.get(&target) { for details in first_channels { - if let CandidateRouteHop::FirstHop(FirstHopCandidate { details: last_hop_details, .. }) - = candidate + if let CandidateRouteHop::FirstHop(FirstHopCandidate { + details: last_hop_details, + .. + }) = candidate { - if details.get_outbound_payment_scid() == last_hop_details.get_outbound_payment_scid() { - ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context(); + if details.get_outbound_payment_scid() + == last_hop_details.get_outbound_payment_scid() + { + ordered_hops.last_mut().unwrap().1 = + details.counterparty.features.to_context(); features_set = true; break; } @@ -3241,7 +3576,9 @@ where L::Target: Logger { if target_node_counter.is_none() { break 'path_walk; } - if target_node_counter == Some(payee_node_counter) { break 'path_walk; } + if target_node_counter == Some(payee_node_counter) { + break 'path_walk; + } new_entry = match dist[target_node_counter.unwrap() as usize].take() { Some(payment_hop) => payment_hop, @@ -3261,7 +3598,7 @@ where L::Target: Logger { log_trace!(logger, "Found a path back to us from the target with {} hops contributing up to {} msat: \n {:#?}", ordered_hops.len(), value_contribution_msat, ordered_hops.iter().map(|h| &(h.0)).collect::>()); - let mut payment_path = PaymentPath {hops: ordered_hops}; + let mut payment_path = PaymentPath { hops: ordered_hops }; // We could have possibly constructed a slightly inconsistent path: since we reduce // value being transferred along the way, we could have violated htlc_minimum_msat @@ -3269,8 +3606,10 @@ where L::Target: Logger { // recompute the fees again, so that if that's the case, we match the currently // underpaid htlc_minimum_msat with fees. debug_assert_eq!(payment_path.get_value_msat(), value_contribution_msat); - let desired_value_contribution = cmp::min(value_contribution_msat, final_value_msat); - value_contribution_msat = payment_path.update_value_and_recompute_fees(desired_value_contribution); + let desired_value_contribution = + cmp::min(value_contribution_msat, final_value_msat); + value_contribution_msat = + payment_path.update_value_and_recompute_fees(desired_value_contribution); // Since a path allows to transfer as much value as // the smallest channel it has ("bottleneck"), we should recompute @@ -3289,7 +3628,8 @@ where L::Target: Logger { .and_modify(|used_liquidity_msat| *used_liquidity_msat += spent_on_hop_msat) .or_insert(spent_on_hop_msat); let hop_capacity = hop.candidate.effective_capacity(); - let hop_max_msat = max_htlc_from_capacity(hop_capacity, channel_saturation_pow_half); + let hop_max_msat = + max_htlc_from_capacity(hop_capacity, channel_saturation_pow_half); if *used_liquidity_msat == hop_max_msat { // If this path used all of this channel's available liquidity, we know // this path will not be selected again in the next loop iteration. @@ -3301,14 +3641,18 @@ where L::Target: Logger { // If we weren't capped by hitting a liquidity limit on a channel in the path, // we'll probably end up picking the same path again on the next iteration. // Decrease the available liquidity of a hop in the middle of the path. - let victim_candidate = &payment_path.hops[(payment_path.hops.len()) / 2].0.candidate; + let victim_candidate = + &payment_path.hops[(payment_path.hops.len()) / 2].0.candidate; let exhausted = u64::max_value(); log_trace!(logger, "Disabling route candidate {} for future path building iterations to avoid duplicates.", LoggedCandidateHop(victim_candidate)); if let Some(scid) = victim_candidate.short_channel_id() { - *used_liquidities.entry(CandidateHopId::Clear((scid, false))).or_default() = exhausted; - *used_liquidities.entry(CandidateHopId::Clear((scid, true))).or_default() = exhausted; + *used_liquidities + .entry(CandidateHopId::Clear((scid, false))) + .or_default() = exhausted; + *used_liquidities.entry(CandidateHopId::Clear((scid, true))).or_default() = + exhausted; } } @@ -3324,15 +3668,20 @@ where L::Target: Logger { // If we found a path back to the payee, we shouldn't try to process it again. This is // the equivalent of the `elem.was_processed` check in // add_entries_to_cheapest_to_target_node!() (see comment there for more info). - if node_id == maybe_dummy_payee_node_id { continue 'path_construction; } + if node_id == maybe_dummy_payee_node_id { + continue 'path_construction; + } // Otherwise, since the current target node is not us, // keep "unrolling" the payment graph from payee to payer by // finding a way to reach the current target from the payer side. add_entries_to_cheapest_to_target_node!( - network_nodes.get(&node_id), node_counter, node_id, + network_nodes.get(&node_id), + node_counter, + node_id, value_contribution_msat, - total_cltv_delta, path_length_to_node + total_cltv_delta, + path_length_to_node ); } @@ -3352,14 +3701,21 @@ where L::Target: Logger { // because we deterministically terminated the search due to low liquidity. if !found_new_path && channel_saturation_pow_half != 0 { channel_saturation_pow_half = 0; - } else if !found_new_path && hit_minimum_limit && already_collected_value_msat < final_value_msat && path_value_msat != recommended_value_msat { + } else if !found_new_path + && hit_minimum_limit + && already_collected_value_msat < final_value_msat + && path_value_msat != recommended_value_msat + { log_trace!(logger, "Failed to collect enough value, but running again to collect extra paths with a potentially higher limit."); path_value_msat = recommended_value_msat; } else if already_collected_value_msat >= recommended_value_msat || !found_new_path { log_trace!(logger, "Have now collected {} msat (seeking {} msat) in paths. Last path loop {} a new path.", already_collected_value_msat, recommended_value_msat, if found_new_path { "found" } else { "did not find" }); break 'paths_collection; - } else if found_new_path && already_collected_value_msat == final_value_msat && payment_paths.len() == 1 { + } else if found_new_path + && already_collected_value_msat == final_value_msat + && payment_paths.len() == 1 + { // Further, if this was our first walk of the graph, and we weren't limited by an // htlc_minimum_msat, return immediately because this path should suffice. If we were // limited by an htlc_minimum_msat value, find another path with a higher value, @@ -3374,10 +3730,13 @@ where L::Target: Logger { } } - let num_ignored_total = num_ignored_value_contribution + num_ignored_path_length_limit + - num_ignored_cltv_delta_limit + num_ignored_previously_failed + - num_ignored_avoid_overpayment + num_ignored_htlc_minimum_msat_limit + - num_ignored_total_fee_limit; + let num_ignored_total = num_ignored_value_contribution + + num_ignored_path_length_limit + + num_ignored_cltv_delta_limit + + num_ignored_previously_failed + + num_ignored_avoid_overpayment + + num_ignored_htlc_minimum_msat_limit + + num_ignored_total_fee_limit; if num_ignored_total > 0 { log_trace!(logger, "Ignored {} candidate hops due to insufficient value contribution, {} due to path length limit, {} due to CLTV delta limit, {} due to previous payment failure, {} due to htlc_minimum_msat limit, {} to avoid overpaying, {} due to maximum total fee limit. Total: {} ignored candidates.", @@ -3399,22 +3758,25 @@ where L::Target: Logger { // Step (6). let mut selected_route = payment_paths; - debug_assert_eq!(selected_route.iter().map(|p| p.get_value_msat()).sum::(), already_collected_value_msat); + debug_assert_eq!( + selected_route.iter().map(|p| p.get_value_msat()).sum::(), + already_collected_value_msat + ); let mut overpaid_value_msat = already_collected_value_msat - final_value_msat; // First, sort by the cost-per-value of the path, dropping the paths that cost the most for // the value they contribute towards the payment amount. // We sort in descending order as we will remove from the front in `retain`, next. - selected_route.sort_unstable_by(|a, b| + selected_route.sort_unstable_by(|a, b| { (((b.get_cost_msat() as u128) << 64) / (b.get_value_msat() as u128)) .cmp(&(((a.get_cost_msat() as u128) << 64) / (a.get_value_msat() as u128))) - ); + }); // We should make sure that at least 1 path left. let mut paths_left = selected_route.len(); selected_route.retain(|path| { if paths_left == 1 { - return true + return true; } let path_value_msat = path.get_value_msat(); if path_value_msat <= overpaid_value_msat { @@ -3432,15 +3794,24 @@ where L::Target: Logger { // TODO: this could also be optimized by also sorting by feerate_per_sat_routed, // so that the sender pays less fees overall. And also htlc_minimum_msat. selected_route.sort_unstable_by(|a, b| { - let a_f = a.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::(); - let b_f = b.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::(); + let a_f = a + .hops + .iter() + .map(|hop| hop.0.candidate.fees().proportional_millionths as u64) + .sum::(); + let b_f = b + .hops + .iter() + .map(|hop| hop.0.candidate.fees().proportional_millionths as u64) + .sum::(); a_f.cmp(&b_f).then_with(|| b.get_cost_msat().cmp(&a.get_cost_msat())) }); let expensive_payment_path = selected_route.first_mut().unwrap(); // We already dropped all the paths with value below `overpaid_value_msat` above, thus this // can't go negative. - let expensive_path_new_value_msat = expensive_payment_path.get_value_msat() - overpaid_value_msat; + let expensive_path_new_value_msat = + expensive_payment_path.get_value_msat() - overpaid_value_msat; expensive_payment_path.update_value_and_recompute_fees(expensive_path_new_value_msat); } @@ -3450,18 +3821,26 @@ where L::Target: Logger { // compare both SCIDs and NodeIds as individual nodes may use random aliases causing collisions // across nodes. selected_route.sort_unstable_by_key(|path| { - let mut key = [CandidateHopId::Clear((42, true)) ; MAX_PATH_LENGTH_ESTIMATE as usize]; + let mut key = [CandidateHopId::Clear((42, true)); MAX_PATH_LENGTH_ESTIMATE as usize]; debug_assert!(path.hops.len() <= key.len()); - for (scid, key) in path.hops.iter() .map(|h| h.0.candidate.id()).zip(key.iter_mut()) { + for (scid, key) in path.hops.iter().map(|h| h.0.candidate.id()).zip(key.iter_mut()) { *key = scid; } key }); for idx in 0..(selected_route.len() - 1) { - if idx + 1 >= selected_route.len() { break; } - if iter_equal(selected_route[idx ].hops.iter().map(|h| (h.0.candidate.id(), h.0.candidate.target())), - selected_route[idx + 1].hops.iter().map(|h| (h.0.candidate.id(), h.0.candidate.target()))) { - let new_value = selected_route[idx].get_value_msat() + selected_route[idx + 1].get_value_msat(); + if idx + 1 >= selected_route.len() { + break; + } + if iter_equal( + selected_route[idx].hops.iter().map(|h| (h.0.candidate.id(), h.0.candidate.target())), + selected_route[idx + 1] + .hops + .iter() + .map(|h| (h.0.candidate.id(), h.0.candidate.target())), + ) { + let new_value = + selected_route[idx].get_value_msat() + selected_route[idx + 1].get_value_msat(); selected_route[idx].update_value_and_recompute_fees(new_value); selected_route.remove(idx + 1); } @@ -3470,10 +3849,11 @@ where L::Target: Logger { let mut paths = Vec::new(); for payment_path in selected_route { let mut hops = Vec::with_capacity(payment_path.hops.len()); - for (hop, node_features) in payment_path.hops.iter() - .filter(|(h, _)| h.candidate.short_channel_id().is_some()) + for (hop, node_features) in + payment_path.hops.iter().filter(|(h, _)| h.candidate.short_channel_id().is_some()) { - let target = hop.candidate.target().expect("target is defined when short_channel_id is defined"); + let target = + hop.candidate.target().expect("target is defined when short_channel_id is defined"); let maybe_announced_channel = if let CandidateRouteHop::PublicHop(_) = hop.candidate { // If we sourced the hop from the graph we're sure the target node is announced. true @@ -3485,14 +3865,18 @@ where L::Target: Logger { // there are announced channels between the endpoints. If so, the hop might be // referring to any of the announced channels, as its `short_channel_id` might be // an alias, in which case we don't take any chances here. - network_graph.node(&target).map_or(false, |hop_node| - hop_node.channels.iter().any(|scid| network_graph.channel(*scid) - .map_or(false, |c| c.as_directed_from(&hop.candidate.source()).is_some())) - ) + network_graph.node(&target).map_or(false, |hop_node| { + hop_node.channels.iter().any(|scid| { + network_graph.channel(*scid).map_or(false, |c| { + c.as_directed_from(&hop.candidate.source()).is_some() + }) + }) + }) }; hops.push(RouteHop { - pubkey: PublicKey::from_slice(target.as_slice()).map_err(|_| "A PublicKey in NetworkGraph is invalid!")?, + pubkey: PublicKey::from_slice(target.as_slice()) + .map_err(|_| "A PublicKey in NetworkGraph is invalid!")?, node_features: node_features.clone(), short_channel_id: hop.candidate.short_channel_id().unwrap(), channel_features: hop.candidate.features(), @@ -3513,7 +3897,9 @@ where L::Target: Logger { excess_final_cltv_expiry_delta: 0, final_value_msat: h.fee_msat, }) - } else { None } + } else { + None + } }); // Propagate the cltv_expiry_delta one hop backwards since the delta from the current hop is // applicable for the previous hop. @@ -3549,8 +3935,9 @@ where L::Target: Logger { // destination, if the remaining CLTV expiry delta exactly matches a feasible path in the network // graph. In order to improve privacy, this method obfuscates the CLTV expiry deltas along the // payment path by adding a randomized 'shadow route' offset to the final hop. -fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, - network_graph: &ReadOnlyNetworkGraph, random_seed_bytes: &[u8; 32] +fn add_random_cltv_offset( + route: &mut Route, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph, + random_seed_bytes: &[u8; 32], ) { let network_channels = network_graph.channels(); let network_nodes = network_graph.nodes(); @@ -3560,17 +3947,23 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, // Remember the last three nodes of the random walk and avoid looping back on them. // Init with the last three nodes from the actual path, if possible. - let mut nodes_to_avoid: [NodeId; 3] = [NodeId::from_pubkey(&path.hops.last().unwrap().pubkey), + let mut nodes_to_avoid: [NodeId; 3] = [ + NodeId::from_pubkey(&path.hops.last().unwrap().pubkey), NodeId::from_pubkey(&path.hops.get(path.hops.len().saturating_sub(2)).unwrap().pubkey), - NodeId::from_pubkey(&path.hops.get(path.hops.len().saturating_sub(3)).unwrap().pubkey)]; + NodeId::from_pubkey(&path.hops.get(path.hops.len().saturating_sub(3)).unwrap().pubkey), + ]; // Choose the last publicly known node as the starting point for the random walk. let mut cur_hop: Option = None; let mut path_nonce = [0u8; 12]; - if let Some(starting_hop) = path.hops.iter().rev() - .find(|h| network_nodes.contains_key(&NodeId::from_pubkey(&h.pubkey))) { - cur_hop = Some(NodeId::from_pubkey(&starting_hop.pubkey)); - path_nonce.copy_from_slice(&cur_hop.unwrap().as_slice()[..12]); + if let Some(starting_hop) = path + .hops + .iter() + .rev() + .find(|h| network_nodes.contains_key(&NodeId::from_pubkey(&h.pubkey))) + { + cur_hop = Some(NodeId::from_pubkey(&starting_hop.pubkey)); + path_nonce.copy_from_slice(&cur_hop.unwrap().as_slice()[..12]); } // Init PRNG with the path-dependant nonce, which is static for private paths. @@ -3579,7 +3972,8 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, // Pick a random path length in [1 .. 3] prng.process_in_place(&mut random_path_bytes); - let random_walk_length = usize::from_be_bytes(random_path_bytes).wrapping_rem(3).wrapping_add(1); + let random_walk_length = + usize::from_be_bytes(random_path_bytes).wrapping_rem(3).wrapping_add(1); for random_hop in 0..random_walk_length { // If we don't find a suitable offset in the public network graph, we default to @@ -3593,15 +3987,16 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, if let Some(random_channel) = usize::from_be_bytes(random_path_bytes) .checked_rem(cur_node.channels.len()) .and_then(|index| cur_node.channels.get(index)) - .and_then(|id| network_channels.get(id)) { - random_channel.as_directed_from(&cur_node_id).map(|(dir_info, next_id)| { - if !nodes_to_avoid.iter().any(|x| x == next_id) { - nodes_to_avoid[random_hop] = *next_id; - random_hop_offset = dir_info.direction().cltv_expiry_delta.into(); - cur_hop = Some(*next_id); - } - }); - } + .and_then(|id| network_channels.get(id)) + { + random_channel.as_directed_from(&cur_node_id).map(|(dir_info, next_id)| { + if !nodes_to_avoid.iter().any(|x| x == next_id) { + nodes_to_avoid[random_hop] = *next_id; + random_hop_offset = dir_info.direction().cltv_expiry_delta.into(); + cur_hop = Some(*next_id); + } + }); + } } } @@ -3611,26 +4006,34 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, } // Limit the total offset to reduce the worst-case locked liquidity timevalue - const MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET: u32 = 3*144; - shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET); + const MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET: u32 = 3 * 144; + shadow_ctlv_expiry_delta_offset = + cmp::min(shadow_ctlv_expiry_delta_offset, MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET); // Limit the offset so we never exceed the max_total_cltv_expiry_delta. To improve plausibility, // we choose the limit to be the largest possible multiple of MEDIAN_HOP_CLTV_EXPIRY_DELTA. let path_total_cltv_expiry_delta: u32 = path.hops.iter().map(|h| h.cltv_expiry_delta).sum(); - let mut max_path_offset = payment_params.max_total_cltv_expiry_delta - path_total_cltv_expiry_delta; + let mut max_path_offset = + payment_params.max_total_cltv_expiry_delta - path_total_cltv_expiry_delta; max_path_offset = cmp::max( max_path_offset - (max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA), - max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA); - shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, max_path_offset); + max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA, + ); + shadow_ctlv_expiry_delta_offset = + cmp::min(shadow_ctlv_expiry_delta_offset, max_path_offset); // Add 'shadow' CLTV offset to the final hop if let Some(tail) = path.blinded_tail.as_mut() { - tail.excess_final_cltv_expiry_delta = tail.excess_final_cltv_expiry_delta - .checked_add(shadow_ctlv_expiry_delta_offset).unwrap_or(tail.excess_final_cltv_expiry_delta); + tail.excess_final_cltv_expiry_delta = tail + .excess_final_cltv_expiry_delta + .checked_add(shadow_ctlv_expiry_delta_offset) + .unwrap_or(tail.excess_final_cltv_expiry_delta); } if let Some(last_hop) = path.hops.last_mut() { - last_hop.cltv_expiry_delta = last_hop.cltv_expiry_delta - .checked_add(shadow_ctlv_expiry_delta_offset).unwrap_or(last_hop.cltv_expiry_delta); + last_hop.cltv_expiry_delta = last_hop + .cltv_expiry_delta + .checked_add(shadow_ctlv_expiry_delta_offset) + .unwrap_or(last_hop.cltv_expiry_delta); } } } @@ -3641,21 +4044,37 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, /// Re-uses logic from `find_route`, so the restrictions described there also apply here. pub fn build_route_from_hops( our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters, - network_graph: &NetworkGraph, logger: L, random_seed_bytes: &[u8; 32] + network_graph: &NetworkGraph, logger: L, random_seed_bytes: &[u8; 32], ) -> Result -where L::Target: Logger, GL::Target: Logger { +where + L::Target: Logger, + GL::Target: Logger, +{ let graph_lock = network_graph.read_only(); - let mut route = build_route_from_hops_internal(our_node_pubkey, hops, &route_params, - &graph_lock, logger, random_seed_bytes)?; - add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes); + let mut route = build_route_from_hops_internal( + our_node_pubkey, + hops, + &route_params, + &graph_lock, + logger, + random_seed_bytes, + )?; + add_random_cltv_offset( + &mut route, + &route_params.payment_params, + &graph_lock, + random_seed_bytes, + ); Ok(route) } fn build_route_from_hops_internal( our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters, network_graph: &ReadOnlyNetworkGraph, logger: L, random_seed_bytes: &[u8; 32], -) -> Result where L::Target: Logger { - +) -> Result +where + L::Target: Logger, +{ struct HopScorer { our_node_id: NodeId, hop_ids: [Option; MAX_PATH_LENGTH_ESTIMATE as usize], @@ -3663,9 +4082,10 @@ fn build_route_from_hops_internal( impl ScoreLookUp for HopScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, - _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 - { + fn channel_penalty_msat( + &self, candidate: &CandidateRouteHop, _usage: ChannelUsage, + _score_params: &Self::ScoreParams, + ) -> u64 { let mut cur_id = self.our_node_id; for i in 0..self.hop_ids.len() { if let Some(next_id) = self.hop_ids[i] { @@ -3700,50 +4120,70 @@ fn build_route_from_hops_internal( let scorer = HopScorer { our_node_id, hop_ids }; - get_route(our_node_pubkey, route_params, network_graph, None, logger, &scorer, &Default::default(), random_seed_bytes) + get_route( + our_node_pubkey, + route_params, + network_graph, + None, + logger, + &scorer, + &Default::default(), + random_seed_bytes, + ) } #[cfg(test)] mod tests { - use crate::blinded_path::BlindedHop; use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath}; - use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, EffectiveCapacity}; - use crate::routing::utxo::UtxoResult; - use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features, - BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, - DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE, RouteParameters, CandidateRouteHop, PublicHopCandidate}; - use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, ScoreLookUp, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters}; - use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel}; + use crate::blinded_path::BlindedHop; use crate::chain::transaction::OutPoint; + use crate::crypto::chacha20::ChaCha20; use crate::ln::channel_state::{ChannelCounterparty, ChannelDetails, ChannelShutdownState}; + use crate::ln::channelmanager; + use crate::ln::msgs::{UnsignedChannelUpdate, MAX_VALUE_MSAT}; use crate::ln::types::ChannelId; + use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, P2PGossipSync}; + use crate::routing::router::{ + add_random_cltv_offset, build_route_from_hops_internal, default_node_features, get_route, + BlindedTail, CandidateRouteHop, InFlightHtlcs, Path, PaymentParameters, PublicHopCandidate, + Route, RouteHint, RouteHintHop, RouteHop, RouteParameters, RoutingFees, + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE, + }; + use crate::routing::scoring::{ + ChannelUsage, FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringDecayParameters, + ProbabilisticScoringFeeParameters, ScoreLookUp, + }; + use crate::routing::test_utils::{ + add_channel, add_or_update_node, build_graph, build_line_graph, get_nodes, + id_to_feature_flags, update_channel, + }; + use crate::routing::utxo::UtxoResult; use crate::types::features::{BlindedHopFeatures, ChannelFeatures, InitFeatures, NodeFeatures}; - use crate::ln::msgs::{UnsignedChannelUpdate, MAX_VALUE_MSAT}; - use crate::ln::channelmanager; use crate::util::config::UserConfig; - use crate::util::test_utils as ln_test_utils; - use crate::crypto::chacha20::ChaCha20; - use crate::util::ser::{FixedLengthReader, Readable, ReadableArgs, Writeable}; #[cfg(c_bindings)] use crate::util::ser::Writer; + use crate::util::ser::{FixedLengthReader, Readable, ReadableArgs, Writeable}; + use crate::util::test_utils as ln_test_utils; use bitcoin::amount::Amount; + use bitcoin::constants::ChainHash; use bitcoin::hashes::Hash; + use bitcoin::hex::FromHex; use bitcoin::network::Network; - use bitcoin::constants::ChainHash; - use bitcoin::script::Builder; use bitcoin::opcodes; - use bitcoin::transaction::TxOut; - use bitcoin::hex::FromHex; - use bitcoin::secp256k1::{PublicKey,SecretKey}; + use bitcoin::script::Builder; use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + use bitcoin::transaction::TxOut; use crate::io::Cursor; use crate::prelude::*; use crate::sync::Arc; - fn get_channel_details(short_channel_id: Option, node_id: PublicKey, - features: InitFeatures, outbound_capacity_msat: u64) -> ChannelDetails { + fn get_channel_details( + short_channel_id: Option, node_id: PublicKey, features: InitFeatures, + outbound_capacity_msat: u64, + ) -> ChannelDetails { #[allow(deprecated)] // TODO: Remove once balance_msat is removed. ChannelDetails { channel_id: ChannelId::new_zero(), @@ -3755,7 +4195,10 @@ mod tests { outbound_htlc_minimum_msat: None, outbound_htlc_maximum_msat: None, }, - funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }), + funding_txo: Some(OutPoint { + txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), + index: 0, + }), channel_type: None, short_channel_id, outbound_scid_alias: None, @@ -3770,8 +4213,10 @@ mod tests { confirmations_required: None, confirmations: None, force_close_spend_delay: None, - is_outbound: true, is_channel_ready: true, - is_usable: true, is_announced: true, + is_outbound: true, + is_channel_ready: true, + is_usable: true, + is_announced: true, inbound_htlc_minimum_msat: None, inbound_htlc_maximum_msat: None, config: None, @@ -3784,22 +4229,33 @@ mod tests { fn dummy_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath { BlindedPaymentPath::from_raw( - intro_node, ln_test_utils::pubkey(42), + intro_node, + ln_test_utils::pubkey(42), vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }, - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() } + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42 as u8), + encrypted_payload: Vec::new(), + }, + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42 as u8), + encrypted_payload: Vec::new(), + }, ], - payinfo + payinfo, ) } - fn dummy_one_hop_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath { + fn dummy_one_hop_blinded_path( + intro_node: PublicKey, payinfo: BlindedPayInfo, + ) -> BlindedPaymentPath { BlindedPaymentPath::from_raw( - intro_node, ln_test_utils::pubkey(42), - vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }, - ], - payinfo + intro_node, + ln_test_utils::pubkey(42), + vec![BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42 as u8), + encrypted_payload: Vec::new(), + }], + payinfo, ) } @@ -3813,18 +4269,36 @@ mod tests { // Simple route to 2 via 1 - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 0); - if let Err(err) = get_route(&our_id, - &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Cannot send a payment of 0 msat"); - } else { panic!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 0); + if let Err(err) = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Cannot send a payment of 0 msat"); + } else { + panic!(); + } payment_params.max_path_length = 2; let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -3842,8 +4316,17 @@ mod tests { assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4)); route_params.payment_params.max_path_length = 1; - get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err(); + get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap_err(); } #[test] @@ -3856,17 +4339,40 @@ mod tests { // Simple route to 2 via 1 - let our_chans = vec![get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)]; + let our_chans = vec![get_channel_details( + Some(2), + our_id, + InitFeatures::from_le_bytes(vec![0b11]), + 100000, + )]; let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - if let Err(err) = get_route(&our_id, - &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::>()), - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "First hop cannot have our_node_pubkey as a destination."); - } else { panic!(); } - - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + if let Err(err) = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "First hop cannot have our_node_pubkey as a destination."); + } else { + panic!(); + } + + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 2); } @@ -3881,131 +4387,189 @@ mod tests { // Simple route to 2 via 1 // Disable other paths - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Check against amount_to_transfer_over_msat. // Set minimal HTLC of 200_000_000 msat. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 3, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 200_000_000, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 3, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 200_000_000, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Second hop only allows to forward 199_999_999 at most, thus not allowing the first hop to // be used. - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 3, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 199_999_999, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 3, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 199_999_999, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Not possible to send 199_999_999, because the minimum on channel=2 is 200_000_000. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 199_999_999); - if let Err(err) = get_route(&our_id, - &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, 199_999_999); + if let Err(err) = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a path to the given destination"); + } else { + panic!(); + } // Lift the restriction on the first hop. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 4, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 4, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // A payment above the minimum should pass - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 2); } @@ -4023,81 +4587,115 @@ mod tests { // A route to node#2 via two paths. // One path allows transferring 35-40 sats, another one also allows 35-40 sats. // Thus, they can't send 60 without overpaying. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 35_000, - htlc_maximum_msat: 40_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 3, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 35_000, - htlc_maximum_msat: 40_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 35_000, + htlc_maximum_msat: 40_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 3, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 35_000, + htlc_maximum_msat: 40_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Make 0 fee. - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Disable other paths - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 3, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 3, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 60_000); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 60_000); route_params.max_total_routing_fee_msat = Some(15_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); // Overpay fees to hit htlc_minimum_msat. let overpaid_fees = route.paths[0].hops[0].fee_msat + route.paths[1].hops[0].fee_msat; // TODO: this could be better balanced to overpay 10k and not 15k. @@ -4105,48 +4703,72 @@ mod tests { // Now, test that if there are 2 paths, a "cheaper" by fee path wouldn't be prioritized // while taking even more fee to match htlc_minimum_msat. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 4, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 65_000, - htlc_maximum_msat: 80_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 3, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 4, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 100_000, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 4, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 65_000, + htlc_maximum_msat: 80_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 3, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 4, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 100_000, + excess_data: Vec::new(), + }, + ); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); // Fine to overpay for htlc_minimum_msat if it allows us to save fee. assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops[0].short_channel_id, 12); @@ -4154,8 +4776,17 @@ mod tests { assert_eq!(fees, 5_000); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 50_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); // Not fine to overpay for htlc_minimum_msat if it requires paying more than fee on // the other channel. assert_eq!(route.paths.len(), 1); @@ -4169,60 +4800,90 @@ mod tests { let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph(); let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[2], 42) + .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) + .unwrap(); let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; // Route to node2 over a single path which requires overpaying the recipient themselves. // First disable all paths except the us -> node1 -> node2 path - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 3, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 0, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 3, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 0, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Set channel 4 to free but with a high htlc_minimum_msat - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 15_000, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 15_000, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Now check that we'll fail to find a path if we fail to find a path if the htlc_minimum // is overrun. Note that the fees are actually calculated on 3*payment amount as that's // what we try to find a route for, so this test only just happens to work out to exactly // the fee limit. - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 5_000); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 5_000); route_params.max_total_routing_fee_msat = Some(9_999); - if let Err(err) = get_route(&our_id, - &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find route that adheres to the maximum total fee limit"); - } else { panic!(); } - - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 5_000); + if let Err(err) = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find route that adheres to the maximum total fee limit"); + } else { + panic!(); + } + + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 5_000); route_params.max_total_routing_fee_msat = Some(10_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.get_total_fees(), 10_000); } @@ -4235,48 +4896,79 @@ mod tests { let random_seed_bytes = [42; 32]; // // Disable channels 4 and 12 by flags=2 - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // If all the channels require some features we don't understand, route should fail let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - if let Err(err) = get_route(&our_id, - &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!(); } + if let Err(err) = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a path to the given destination"); + } else { + panic!(); + } // If we specify a channel to node7, that overrides our local channel view and that gets used - let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), - InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; + let our_chans = vec![get_channel_details( + Some(42), + nodes[7].clone(), + InitFeatures::from_le_bytes(vec![0b11]), + 250_000_000, + )]; route_params.payment_params.max_path_length = 2; - let route = get_route(&our_id, &route_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); @@ -4311,18 +5003,39 @@ mod tests { // If all nodes require some features we don't understand, route should fail let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - if let Err(err) = get_route(&our_id, - &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!(); } + if let Err(err) = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a path to the given destination"); + } else { + panic!(); + } // If we specify a channel to node7, that overrides our local channel view and that gets used - let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), - InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; - let route = get_route(&our_id, &route_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let our_chans = vec![get_channel_details( + Some(42), + nodes[7].clone(), + InitFeatures::from_le_bytes(vec![0b11]), + 250_000_000, + )]; + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); @@ -4354,8 +5067,17 @@ mod tests { // Route to 1 via 2 and 3 because our channel to 1 is disabled let payment_params = PaymentParameters::from_node_id(nodes[0], 42); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 3); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -4382,11 +5104,23 @@ mod tests { // If we specify a channel to node7, that overrides our local channel view and that gets used let payment_params = PaymentParameters::from_node_id(nodes[2], 42); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), - InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; - let route = get_route(&our_id, &route_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let our_chans = vec![get_channel_details( + Some(42), + nodes[7].clone(), + InitFeatures::from_le_bytes(vec![0b11]), + 250_000_000, + )]; + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); @@ -4405,79 +5139,73 @@ mod tests { } fn last_hops(nodes: &Vec) -> Vec { - let zero_fees = RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }; - vec![RouteHint(vec![RouteHintHop { - src_node_id: nodes[3], - short_channel_id: 8, - fees: zero_fees, - cltv_expiry_delta: (8 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - } - ]), RouteHint(vec![RouteHintHop { - src_node_id: nodes[4], - short_channel_id: 9, - fees: RoutingFees { - base_msat: 1001, - proportional_millionths: 0, - }, - cltv_expiry_delta: (9 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }]), RouteHint(vec![RouteHintHop { - src_node_id: nodes[5], - short_channel_id: 10, - fees: zero_fees, - cltv_expiry_delta: (10 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }])] + let zero_fees = RoutingFees { base_msat: 0, proportional_millionths: 0 }; + vec![ + RouteHint(vec![RouteHintHop { + src_node_id: nodes[3], + short_channel_id: 8, + fees: zero_fees, + cltv_expiry_delta: (8 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + RouteHint(vec![RouteHintHop { + src_node_id: nodes[4], + short_channel_id: 9, + fees: RoutingFees { base_msat: 1001, proportional_millionths: 0 }, + cltv_expiry_delta: (9 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + RouteHint(vec![RouteHintHop { + src_node_id: nodes[5], + short_channel_id: 10, + fees: zero_fees, + cltv_expiry_delta: (10 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + ] } fn last_hops_multi_private_channels(nodes: &Vec) -> Vec { - let zero_fees = RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }; - vec![RouteHint(vec![RouteHintHop { - src_node_id: nodes[2], - short_channel_id: 5, - fees: RoutingFees { - base_msat: 100, - proportional_millionths: 0, - }, - cltv_expiry_delta: (5 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }, RouteHintHop { - src_node_id: nodes[3], - short_channel_id: 8, - fees: zero_fees, - cltv_expiry_delta: (8 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - } - ]), RouteHint(vec![RouteHintHop { - src_node_id: nodes[4], - short_channel_id: 9, - fees: RoutingFees { - base_msat: 1001, - proportional_millionths: 0, - }, - cltv_expiry_delta: (9 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }]), RouteHint(vec![RouteHintHop { - src_node_id: nodes[5], - short_channel_id: 10, - fees: zero_fees, - cltv_expiry_delta: (10 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }])] + let zero_fees = RoutingFees { base_msat: 0, proportional_millionths: 0 }; + vec![ + RouteHint(vec![ + RouteHintHop { + src_node_id: nodes[2], + short_channel_id: 5, + fees: RoutingFees { base_msat: 100, proportional_millionths: 0 }, + cltv_expiry_delta: (5 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + RouteHintHop { + src_node_id: nodes[3], + short_channel_id: 8, + fees: zero_fees, + cltv_expiry_delta: (8 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + ]), + RouteHint(vec![RouteHintHop { + src_node_id: nodes[4], + short_channel_id: 9, + fees: RoutingFees { base_msat: 1001, proportional_millionths: 0 }, + cltv_expiry_delta: (9 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + RouteHint(vec![RouteHintHop { + src_node_id: nodes[5], + short_channel_id: 10, + fees: zero_fees, + cltv_expiry_delta: (10 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + ] } #[test] @@ -4495,10 +5223,7 @@ mod tests { let invalid_last_hop = RouteHint(vec![RouteHintHop { src_node_id: nodes[6], short_channel_id: 8, - fees: RoutingFees { - base_msat: 1000, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 1000, proportional_millionths: 0 }, cltv_expiry_delta: (8 << 4) | 1, htlc_minimum_msat: None, htlc_maximum_msat: None, @@ -4508,21 +5233,41 @@ mod tests { invalid_last_hops.push(invalid_last_hop); { let payment_params = PaymentParameters::from_node_id(nodes[6], 42) - .with_route_hints(invalid_last_hops).unwrap(); + .with_route_hints(invalid_last_hops) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - if let Err(err) = get_route(&our_id, - &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Route hint cannot have the payee as the source."); - } else { panic!(); } + if let Err(err) = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Route hint cannot have the payee as the source."); + } else { + panic!(); + } } let mut payment_params = PaymentParameters::from_node_id(nodes[6], 42) - .with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap(); + .with_route_hints(last_hops_multi_private_channels(&nodes)) + .unwrap(); payment_params.max_path_length = 5; let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -4559,46 +5304,60 @@ mod tests { assert_eq!(route.paths[0].hops[4].short_channel_id, 8); assert_eq!(route.paths[0].hops[4].fee_msat, 100); assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet - assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly + assert_eq!( + route.paths[0].hops[4].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet + assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); + // We can't learn any flags from invoices, sadly } fn empty_last_hop(nodes: &Vec) -> Vec { - let zero_fees = RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }; - vec![RouteHint(vec![RouteHintHop { - src_node_id: nodes[3], - short_channel_id: 8, - fees: zero_fees, - cltv_expiry_delta: (8 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }]), RouteHint(vec![ - - ]), RouteHint(vec![RouteHintHop { - src_node_id: nodes[5], - short_channel_id: 10, - fees: zero_fees, - cltv_expiry_delta: (10 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }])] + let zero_fees = RoutingFees { base_msat: 0, proportional_millionths: 0 }; + vec![ + RouteHint(vec![RouteHintHop { + src_node_id: nodes[3], + short_channel_id: 8, + fees: zero_fees, + cltv_expiry_delta: (8 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + RouteHint(vec![]), + RouteHint(vec![RouteHintHop { + src_node_id: nodes[5], + short_channel_id: 10, + fees: zero_fees, + cltv_expiry_delta: (10 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + ] } #[test] fn ignores_empty_last_hops_test() { let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(empty_last_hop(&nodes)).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[6], 42) + .with_route_hints(empty_last_hop(&nodes)) + .unwrap(); let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; // Test handling of an empty RouteHint passed in Invoice. let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -4635,35 +5394,36 @@ mod tests { assert_eq!(route.paths[0].hops[4].short_channel_id, 8); assert_eq!(route.paths[0].hops[4].fee_msat, 100); assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet - assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly + assert_eq!( + route.paths[0].hops[4].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet + assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); + // We can't learn any flags from invoices, sadly } /// Builds a trivial last-hop hint that passes through the two nodes given, with channel 0xff00 /// and 0xff01. fn multi_hop_last_hops_hint(hint_hops: [PublicKey; 2]) -> Vec { - let zero_fees = RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }; - vec![RouteHint(vec![RouteHintHop { - src_node_id: hint_hops[0], - short_channel_id: 0xff00, - fees: RoutingFees { - base_msat: 100, - proportional_millionths: 0, - }, - cltv_expiry_delta: (5 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }, RouteHintHop { - src_node_id: hint_hops[1], - short_channel_id: 0xff01, - fees: zero_fees, - cltv_expiry_delta: (8 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }])] + let zero_fees = RoutingFees { base_msat: 0, proportional_millionths: 0 }; + vec![RouteHint(vec![ + RouteHintHop { + src_node_id: hint_hops[0], + short_channel_id: 0xff00, + fees: RoutingFees { base_msat: 100, proportional_millionths: 0 }, + cltv_expiry_delta: (5 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + RouteHintHop { + src_node_id: hint_hops[1], + short_channel_id: 0xff01, + fees: zero_fees, + cltv_expiry_delta: (8 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + ])] } #[test] @@ -4671,7 +5431,9 @@ mod tests { let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph(); let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let last_hops = multi_hop_last_hops_hint([nodes[2], nodes[3]]); - let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[6], 42) + .with_route_hints(last_hops.clone()) + .unwrap(); let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; @@ -4680,37 +5442,56 @@ mod tests { // max path length. // Disabling channels 6 & 7 by flags=2 - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); route_params.payment_params.max_path_length = 4; - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -4738,11 +5519,23 @@ mod tests { assert_eq!(route.paths[0].hops[3].short_channel_id, last_hops[0].0[1].short_channel_id); assert_eq!(route.paths[0].hops[3].fee_msat, 100); assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet + assert_eq!( + route.paths[0].hops[3].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly route_params.payment_params.max_path_length = 3; - get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err(); + get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap_err(); } #[test] @@ -4750,46 +5543,70 @@ mod tests { let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph(); let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); - let non_announced_privkey = SecretKey::from_slice(&>::from_hex(&format!("{:02x}", 0xf0).repeat(32)).unwrap()[..]).unwrap(); + let non_announced_privkey = SecretKey::from_slice( + &>::from_hex(&format!("{:02x}", 0xf0).repeat(32)).unwrap()[..], + ) + .unwrap(); let non_announced_pubkey = PublicKey::from_secret_key(&secp_ctx, &non_announced_privkey); let last_hops = multi_hop_last_hops_hint([nodes[2], non_announced_pubkey]); - let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[6], 42) + .with_route_hints(last_hops.clone()) + .unwrap(); let scorer = ln_test_utils::TestScorer::new(); // Test through channels 2, 3, 0xff00, 0xff01. // Test shows that multiple hop hints are considered. // Disabling channels 6 & 7 by flags=2 - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, // to disable - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, // to disable + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &[42u8; 32]).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &[42u8; 32], + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -4810,61 +5627,71 @@ mod tests { assert_eq!(route.paths[0].hops[2].short_channel_id, last_hops[0].0[0].short_channel_id); assert_eq!(route.paths[0].hops[2].fee_msat, 0); assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 129); - assert_eq!(route.paths[0].hops[2].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet + assert_eq!( + route.paths[0].hops[2].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly assert_eq!(route.paths[0].hops[3].pubkey, nodes[6]); assert_eq!(route.paths[0].hops[3].short_channel_id, last_hops[0].0[1].short_channel_id); assert_eq!(route.paths[0].hops[3].fee_msat, 100); assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet - assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly + assert_eq!( + route.paths[0].hops[3].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet + assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::::new()); + // We can't learn any flags from invoices, sadly } fn last_hops_with_public_channel(nodes: &Vec) -> Vec { - let zero_fees = RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }; - vec![RouteHint(vec![RouteHintHop { - src_node_id: nodes[4], - short_channel_id: 11, - fees: zero_fees, - cltv_expiry_delta: (11 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }, RouteHintHop { - src_node_id: nodes[3], - short_channel_id: 8, - fees: zero_fees, - cltv_expiry_delta: (8 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }]), RouteHint(vec![RouteHintHop { - src_node_id: nodes[4], - short_channel_id: 9, - fees: RoutingFees { - base_msat: 1001, - proportional_millionths: 0, - }, - cltv_expiry_delta: (9 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }]), RouteHint(vec![RouteHintHop { - src_node_id: nodes[5], - short_channel_id: 10, - fees: zero_fees, - cltv_expiry_delta: (10 << 4) | 1, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }])] + let zero_fees = RoutingFees { base_msat: 0, proportional_millionths: 0 }; + vec![ + RouteHint(vec![ + RouteHintHop { + src_node_id: nodes[4], + short_channel_id: 11, + fees: zero_fees, + cltv_expiry_delta: (11 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + RouteHintHop { + src_node_id: nodes[3], + short_channel_id: 8, + fees: zero_fees, + cltv_expiry_delta: (8 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }, + ]), + RouteHint(vec![RouteHintHop { + src_node_id: nodes[4], + short_channel_id: 9, + fees: RoutingFees { base_msat: 1001, proportional_millionths: 0 }, + cltv_expiry_delta: (9 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + RouteHint(vec![RouteHintHop { + src_node_id: nodes[5], + short_channel_id: 10, + fees: zero_fees, + cltv_expiry_delta: (10 << 4) | 1, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }]), + ] } #[test] fn last_hops_with_public_channel_test() { let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_with_public_channel(&nodes)).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[6], 42) + .with_route_hints(last_hops_with_public_channel(&nodes)) + .unwrap(); let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; @@ -4872,8 +5699,17 @@ mod tests { // which would be handled in the same manner. let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -4910,8 +5746,12 @@ mod tests { assert_eq!(route.paths[0].hops[4].short_channel_id, 8); assert_eq!(route.paths[0].hops[4].fee_msat, 100); assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet - assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly + assert_eq!( + route.paths[0].hops[4].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet + assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); + // We can't learn any flags from invoices, sadly } #[test] @@ -4922,14 +5762,28 @@ mod tests { let random_seed_bytes = [42; 32]; // Simple test with outbound channel to 4 to test that last_hops and first_hops connect - let our_chans = vec![get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)]; + let our_chans = vec![get_channel_details( + Some(42), + nodes[3].clone(), + InitFeatures::from_le_bytes(vec![0b11]), + 250_000_000, + )]; let mut last_hops = last_hops(&nodes); let payment_params = PaymentParameters::from_node_id(nodes[6], 42) - .with_route_hints(last_hops.clone()).unwrap(); + .with_route_hints(last_hops.clone()) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[3]); @@ -4943,18 +5797,30 @@ mod tests { assert_eq!(route.paths[0].hops[1].short_channel_id, 8); assert_eq!(route.paths[0].hops[1].fee_msat, 100); assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[1].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet + assert_eq!( + route.paths[0].hops[1].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly last_hops[0].0[0].fees.base_msat = 1000; // Revert to via 6 as the fee on 8 goes up - let payment_params = PaymentParameters::from_node_id(nodes[6], 42) - .with_route_hints(last_hops).unwrap(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let payment_params = + PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 4); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -4984,13 +5850,25 @@ mod tests { assert_eq!(route.paths[0].hops[3].short_channel_id, 10); assert_eq!(route.paths[0].hops[3].fee_msat, 100); assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet + assert_eq!( + route.paths[0].hops[3].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly // ...but still use 8 for larger payments as 6 has a variable feerate let route_params = RouteParameters::from_payment_params_and_value(payment_params, 2000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths[0].hops.len(), 5); assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]); @@ -5027,37 +5905,74 @@ mod tests { assert_eq!(route.paths[0].hops[4].short_channel_id, 8); assert_eq!(route.paths[0].hops[4].fee_msat, 2000); assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet - assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); // We can't learn any flags from invoices, sadly + assert_eq!( + route.paths[0].hops[4].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet + assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::::new()); + // We can't learn any flags from invoices, sadly } - fn do_unannounced_path_test(last_hop_htlc_max: Option, last_hop_fee_prop: u32, outbound_capacity_msat: u64, route_val: u64) -> Result { - let source_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&>::from_hex(&format!("{:02}", 41).repeat(32)).unwrap()[..]).unwrap()); - let middle_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..]).unwrap()); - let target_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..]).unwrap()); + fn do_unannounced_path_test( + last_hop_htlc_max: Option, last_hop_fee_prop: u32, outbound_capacity_msat: u64, + route_val: u64, + ) -> Result { + let source_node_id = PublicKey::from_secret_key( + &Secp256k1::new(), + &SecretKey::from_slice( + &>::from_hex(&format!("{:02}", 41).repeat(32)).unwrap()[..], + ) + .unwrap(), + ); + let middle_node_id = PublicKey::from_secret_key( + &Secp256k1::new(), + &SecretKey::from_slice( + &>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..], + ) + .unwrap(), + ); + let target_node_id = PublicKey::from_secret_key( + &Secp256k1::new(), + &SecretKey::from_slice( + &>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..], + ) + .unwrap(), + ); // If we specify a channel to a middle hop, that overrides our local channel view and that gets used let last_hops = RouteHint(vec![RouteHintHop { src_node_id: middle_node_id, short_channel_id: 8, - fees: RoutingFees { - base_msat: 1000, - proportional_millionths: last_hop_fee_prop, - }, + fees: RoutingFees { base_msat: 1000, proportional_millionths: last_hop_fee_prop }, cltv_expiry_delta: (8 << 4) | 1, htlc_minimum_msat: None, htlc_maximum_msat: last_hop_htlc_max, }]); - let payment_params = PaymentParameters::from_node_id(target_node_id, 42).with_route_hints(vec![last_hops]).unwrap(); - let our_chans = vec![get_channel_details(Some(42), middle_node_id, InitFeatures::from_le_bytes(vec![0b11]), outbound_capacity_msat)]; + let payment_params = PaymentParameters::from_node_id(target_node_id, 42) + .with_route_hints(vec![last_hops]) + .unwrap(); + let our_chans = vec![get_channel_details( + Some(42), + middle_node_id, + InitFeatures::from_le_bytes(vec![0b11]), + outbound_capacity_msat, + )]; let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; let logger = ln_test_utils::TestLogger::new(); let network_graph = NetworkGraph::new(Network::Testnet, &logger); - let route_params = RouteParameters::from_payment_params_and_value(payment_params, route_val); - let route = get_route(&source_node_id, &route_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), &logger, &scorer, &Default::default(), - &random_seed_bytes); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, route_val); + let route = get_route( + &source_node_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + &logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ); route } @@ -5068,8 +5983,20 @@ mod tests { // hints. let route = do_unannounced_path_test(None, 1, 2000000, 1000000).unwrap(); - let middle_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..]).unwrap()); - let target_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..]).unwrap()); + let middle_node_id = PublicKey::from_secret_key( + &Secp256k1::new(), + &SecretKey::from_slice( + &>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..], + ) + .unwrap(), + ); + let target_node_id = PublicKey::from_secret_key( + &Secp256k1::new(), + &SecretKey::from_slice( + &>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..], + ) + .unwrap(), + ); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, middle_node_id); @@ -5083,7 +6010,10 @@ mod tests { assert_eq!(route.paths[0].hops[1].short_channel_id, 8); assert_eq!(route.paths[0].hops[1].fee_msat, 1000000); assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[1].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet + assert_eq!( + route.paths[0].hops[1].node_features.le_flags(), + default_node_features().le_flags() + ); // We dont pass flags in from invoices yet assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &[0; 0]); // We can't learn any flags from invoices, sadly } @@ -5095,14 +6025,26 @@ mod tests { // we'd built a path (as our node is in the "best candidate" set), when we had not. // In this test, we previously hit a subtraction underflow due to having less available // liquidity at the last hop than 0. - assert!(do_unannounced_path_test(Some(21_000_000_0000_0000_000), 0, 21_000_000_0000_0000_000, 21_000_000_0000_0000_000).is_err()); + assert!(do_unannounced_path_test( + Some(21_000_000_0000_0000_000), + 0, + 21_000_000_0000_0000_000, + 21_000_000_0000_0000_000 + ) + .is_err()); } #[test] fn overflow_unannounced_path_test_feerate_overflow() { // This tests for the same case as above, except instead of hitting a subtraction // underflow, we hit a case where the fee charged at a hop overflowed. - assert!(do_unannounced_path_test(Some(21_000_000_0000_0000_000), 50000, 21_000_000_0000_0000_000, 21_000_000_0000_0000_000).is_err()); + assert!(do_unannounced_path_test( + Some(21_000_000_0000_0000_000), + 50000, + 21_000_000_0000_0000_000, + 21_000_000_0000_0000_000 + ) + .is_err()); } #[test] @@ -5122,82 +6064,120 @@ mod tests { // our node to node2 via node0: channels {1, 3}. // First disable all other paths. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Make the first channel (#1) very permissive, // and we will be testing all limits on the second channel. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 1_000_000_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 1_000_000_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // First, let's see if routing works if we have absolutely no idea about the available amount. // In this case, it should be set to 250_000 sats. - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 250_000_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 250_000_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 250_000_001); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 250_000_001); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route an exact amount we have should be fine. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 250_000_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 250_000_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -5207,42 +6187,68 @@ mod tests { // Check that setting next_outbound_htlc_limit_msat in first_hops limits the channels. // Disable channel #1 and use another first hop. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 3, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 1_000_000_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 3, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 1_000_000_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Now, limit the first_hop by the next_outbound_htlc_limit_msat of 200_000 sats. - let our_chans = vec![get_channel_details(Some(42), nodes[0].clone(), InitFeatures::from_le_bytes(vec![0b11]), 200_000_000)]; + let our_chans = vec![get_channel_details( + Some(42), + nodes[0].clone(), + InitFeatures::from_le_bytes(vec![0b11]), + 200_000_000, + )]; { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 200_000_001); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 200_000_001); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route an exact amount we have should be fine. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 200_000_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), - Some(&our_chans.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 200_000_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&our_chans.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -5251,53 +6257,80 @@ mod tests { } // Enable channel #1 back. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 4, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 1_000_000_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 4, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 1_000_000_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Now let's see if routing works if we know only htlc_maximum_msat. - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 3, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 15_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 3, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 15_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_001); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 15_001); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route an exact amount we have should be fine. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 15_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -5309,75 +6342,120 @@ mod tests { // We can't change UTXO capacity on the fly, so we'll disable // the existing channel and add another one with the capacity we need. - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 4, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - let good_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2) - .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[0]).serialize()) - .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[2]).serialize()) - .push_opcode(opcodes::all::OP_PUSHNUM_2) - .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_p2wsh(); - - *chain_monitor.utxo_ret.lock().unwrap() = - UtxoResult::Sync(Ok(TxOut { value: Amount::from_sat(15), script_pubkey: good_script.clone() })); - gossip_sync.add_utxo_lookup(Some(chain_monitor)); - - add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 333, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (3 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: 15_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 333, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: (3 << 4) | 2, - htlc_minimum_msat: 0, - htlc_maximum_msat: 15_000, - fee_base_msat: 100, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 4, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + let good_script = Builder::new() + .push_opcode(opcodes::all::OP_PUSHNUM_2) + .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[0]).serialize()) + .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[2]).serialize()) + .push_opcode(opcodes::all::OP_PUSHNUM_2) + .push_opcode(opcodes::all::OP_CHECKMULTISIG) + .into_script() + .to_p2wsh(); + + *chain_monitor.utxo_ret.lock().unwrap() = UtxoResult::Sync(Ok(TxOut { + value: Amount::from_sat(15), + script_pubkey: good_script.clone(), + })); + gossip_sync.add_utxo_lookup(Some(chain_monitor)); + + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + &privkeys[2], + ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), + 333, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 333, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (3 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: 15_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 333, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: (3 << 4) | 2, + htlc_minimum_msat: 0, + htlc_maximum_msat: 15_000, + fee_base_msat: 100, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_001); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 15_001); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route an exact amount we have should be fine. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 15_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 15_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -5386,37 +6464,60 @@ mod tests { } // Now let's see if routing chooses htlc_maximum_msat over UTXO capacity. - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 333, - timestamp: 6, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 10_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 333, + timestamp: 6, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 10_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 10_001); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 10_001); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route an exact amount we have should be fine. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 10_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 10_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let path = route.paths.last().unwrap(); assert_eq!(path.hops.len(), 2); @@ -5443,105 +6544,153 @@ mod tests { // Total capacity: 50 sats. // Disable other potential paths. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Limit capacities - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 50_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 11, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 50_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 11, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 60_000); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 60_000); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route 49 sats (just a bit below the capacity). - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 49_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 49_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -5554,10 +6703,19 @@ mod tests { { // Attempt to route an exact amount is also fine - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 50_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, 50_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -5578,38 +6736,57 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[2], 42); // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50). - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 1_000_000, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 50_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 1_000_000, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 50_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 50_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, 50_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -5633,7 +6810,8 @@ mod tests { // MPP to a 1-hop blinded path for nodes[2] let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); - let blinded_payinfo = BlindedPayInfo { // These fields are ignored for 1-hop blinded paths + let blinded_payinfo = BlindedPayInfo { + // These fields are ignored for 1-hop blinded paths fee_base_msat: 0, fee_proportional_millionths: 0, htlc_minimum_msat: 0, @@ -5643,7 +6821,8 @@ mod tests { }; let blinded_path = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone()); let one_hop_blinded_payment_params = PaymentParameters::blinded(vec![blinded_path.clone()]) - .with_bolt12_features(bolt12_features.clone()).unwrap(); + .with_bolt12_features(bolt12_features.clone()) + .unwrap(); do_simple_mpp_route_test(one_hop_blinded_payment_params.clone()); // MPP to 3 2-hop blinded paths @@ -5659,13 +6838,16 @@ mod tests { node_1_payinfo.htlc_maximum_msat = 180_000; let blinded_path_node_1 = dummy_blinded_path(nodes[1], node_1_payinfo); - let two_hop_blinded_payment_params = PaymentParameters::blinded( - vec![blinded_path_node_0, blinded_path_node_7, blinded_path_node_1]) - .with_bolt12_features(bolt12_features).unwrap(); + let two_hop_blinded_payment_params = PaymentParameters::blinded(vec![ + blinded_path_node_0, + blinded_path_node_7, + blinded_path_node_1, + ]) + .with_bolt12_features(bolt12_features) + .unwrap(); do_simple_mpp_route_test(two_hop_blinded_payment_params); } - fn do_simple_mpp_route_test(payment_params: PaymentParameters) { let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph(); let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx); @@ -5681,112 +6863,160 @@ mod tests { // Their aggregate capacity will be 50 + 60 + 180 = 290 sats. // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50). - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 50_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 50_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via node7 is channels {12, 13}. Limit them to 60 and 60 sats // (total limit 60). - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 60_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 60_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 60_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 60_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via node1 is channels {2, 4}. Limit them to 200 and 180 sats // (total capacity 180 sats). - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 200_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 180_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 200_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 180_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 300_000); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 300_000); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Attempt to route while setting max_path_count to 0 results in a failure. let zero_payment_params = payment_params.clone().with_max_path_count(0); - let route_params = RouteParameters::from_payment_params_and_value( - zero_payment_params, 100); + let route_params = + RouteParameters::from_payment_params_and_value(zero_payment_params, 100); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Can't find a route with no paths allowed."); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Can't find a route with no paths allowed."); + } else { + panic!(); + } } { @@ -5794,22 +7024,40 @@ mod tests { // This is the case because the minimal_value_contribution_msat would require each path // to account for 1/3 of the total value, which is violated by 2 out of 3 paths. let fail_payment_params = payment_params.clone().with_max_path_count(3); - let route_params = RouteParameters::from_payment_params_and_value( - fail_payment_params, 250_000); + let route_params = + RouteParameters::from_payment_params_and_value(fail_payment_params, 250_000); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route 250 sats (just a bit below the capacity). // Our algorithm should provide us with these 3 paths. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 250_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 250_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -5826,22 +7074,37 @@ mod tests { { // Attempt to route an exact amount is also fine - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 290_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 290_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { if payment_params.payee.blinded_route_hints().len() != 0 { - assert!(path.blinded_tail.is_some()) } else { assert!(path.blinded_tail.is_none()) } + assert!(path.blinded_tail.is_some()) + } else { + assert!(path.blinded_tail.is_none()) + } if let Some(bt) = &path.blinded_tail { assert_eq!(path.hops.len() + if bt.hops.len() == 1 { 0 } else { 1 }, 2); if bt.hops.len() > 1 { let network_graph = network_graph.read_only(); assert_eq!( NodeId::from_pubkey(&path.hops.last().unwrap().pubkey), - payment_params.payee.blinded_route_hints().iter() + payment_params + .payee + .blinded_route_hints() + .iter() .find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat()) .and_then(|p| p.public_introduction_node_id(&network_graph)) .copied() @@ -5919,154 +7182,218 @@ mod tests { // Each channel will have 100 sats capacity except for 6 and 11, which have 200. // Disable other potential paths. - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via {node0, node2} is channels {1, 3, 5}. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(16)), 16); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 16, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 1_000, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 16, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 3, // disable direction 1 - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 1_000, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + &privkeys[3], + ChannelFeatures::from_le_bytes(id_to_feature_flags(16)), + 16, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 16, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 1_000, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[3], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 16, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 3, // disable direction 1 + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 1_000, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. // Add 100 sats to the capacities of {12, 13}, because these channels // are also used for 3rd path. 100 sats for the rest. Total capacity: 100 sats. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 200_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 11, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 200_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 200_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 11, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 200_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via {node7, node2} is channels {12, 13, 5}. // We already limited them to 200 sats (they are used twice for 100 sats). // Nothing to do here. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt); - let res = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt); + let res = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ); res } @@ -6094,89 +7421,126 @@ mod tests { // It's fine to ignore this concern for now. // Disable other potential paths. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 2, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 2, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via {node0, node2} is channels {1, 3, 5}. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 5, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 5, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 3, // Disable direction 1 - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + &privkeys[3], + ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), + 5, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[3], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 3, // Disable direction 1 + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. // All channels should be 100 sats capacity. But for the fee experiment, @@ -6188,88 +7552,141 @@ mod tests { // - channel 12 capacity is 250 sats // - fee for channel 6 is 150 sats // Let's test this by enforcing these 2 conditions and removing other limits. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 250_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 250_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 150_000, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 11, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 150_000, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 11, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 210_000); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 210_000); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Attempt to route while setting max_total_routing_fee_msat to 149_999 results in a failure. - let route_params = RouteParameters { payment_params: payment_params.clone(), final_value_msat: 200_000, - max_total_routing_fee_msat: Some(149_999) }; + let route_params = RouteParameters { + payment_params: payment_params.clone(), + final_value_msat: 200_000, + max_total_routing_fee_msat: Some(149_999), + }; if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route 200 sats (exact amount we can route). - let route_params = RouteParameters { payment_params: payment_params.clone(), final_value_msat: 200_000, - max_total_routing_fee_msat: Some(150_000) }; - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters { + payment_params: payment_params.clone(), + final_value_msat: 200_000, + max_total_routing_fee_msat: Some(150_000), + }; + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; @@ -6302,81 +7719,113 @@ mod tests { let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; let config = UserConfig::default(); - let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap(), 42) - .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap() - .with_route_hints(vec![RouteHint(vec![RouteHintHop { - src_node_id: nodes[2], - short_channel_id: 42, - fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, - cltv_expiry_delta: 42, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }])]).unwrap().with_max_channel_saturation_power_of_half(0); + let payment_params = + PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap(), 42) + .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) + .unwrap() + .with_route_hints(vec![RouteHint(vec![RouteHintHop { + src_node_id: nodes[2], + short_channel_id: 42, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, + cltv_expiry_delta: 42, + htlc_minimum_msat: None, + htlc_maximum_msat: None, + }])]) + .unwrap() + .with_max_channel_saturation_power_of_half(0); // Keep only two paths from us to nodes[2], both with a 99sat HTLC maximum, with one with // no fee and one with a 1msat fee. Previously, trying to route 100 sats to nodes[2] here // would first use the no-fee route and then fail to find a path along the second route as // we think we can only send up to 1 additional sat over the last-hop but refuse to as its // under 5% of our payment amount. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (5 << 4) | 5, - htlc_minimum_msat: 0, - htlc_maximum_msat: 99_000, - fee_base_msat: u32::max_value(), - fee_proportional_millionths: u32::max_value(), - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (5 << 4) | 3, - htlc_minimum_msat: 0, - htlc_maximum_msat: 99_000, - fee_base_msat: u32::max_value(), - fee_proportional_millionths: u32::max_value(), - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (4 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 1, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0|2, // Channel disabled - cltv_expiry_delta: (13 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 2000000, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (5 << 4) | 5, + htlc_minimum_msat: 0, + htlc_maximum_msat: 99_000, + fee_base_msat: u32::max_value(), + fee_proportional_millionths: u32::max_value(), + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (5 << 4) | 3, + htlc_minimum_msat: 0, + htlc_maximum_msat: 99_000, + fee_base_msat: u32::max_value(), + fee_proportional_millionths: u32::max_value(), + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (4 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 1, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0 | 2, // Channel disabled + cltv_expiry_delta: (13 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 2000000, + excess_data: Vec::new(), + }, + ); // Get a route for 100 sats and check that we found the MPP route no problem and didn't // overpay at all. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100_000); - let mut route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100_000); + let mut route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); route.paths.sort_by_key(|path| path.hops[0].short_channel_id); // Paths are manually ordered ordered by SCID, so: @@ -6416,107 +7865,155 @@ mod tests { // Their aggregate capacity will be 50 + 60 + 20 = 130 sats. // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 100_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 50_000, - fee_base_msat: 100, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 100_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 50_000, + fee_base_msat: 100, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via node7 is channels {12, 13}. Limit them to 60 and 60 sats (total limit 60); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 60_000, - fee_base_msat: 100, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 60_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 60_000, + fee_base_msat: 100, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 60_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); // Path via node1 is channels {2, 4}. Limit them to 20 and 20 sats (total capacity 20 sats). - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 20_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 20_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 20_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 20_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 150_000); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 150_000); if let Err(err) = get_route( - &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a sufficient route to the given destination"); + } else { + panic!(); + } } { // Now, attempt to route 125 sats (just a bit below the capacity of 3 channels). // Our algorithm should provide us with these 3 paths. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 125_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 125_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 3); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -6529,10 +8026,19 @@ mod tests { { // Attempt to route without the last small cheap channel - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 90_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, 90_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; for path in &route.paths { @@ -6579,119 +8085,230 @@ mod tests { let random_seed_bytes = [42; 32]; let payment_params = PaymentParameters::from_node_id(nodes[6], 42); - add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6); + add_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + &privkeys[1], + ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), + 6, + ); for (key, channel_flags) in [(&our_privkey, 0), (&privkeys[1], 3)] { - update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags, - cltv_expiry_delta: (6 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + key, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags, + cltv_expiry_delta: (6 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); } - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0); + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[1], + NodeFeatures::from_le_bytes(id_to_feature_flags(1)), + 0, + ); - add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + &privkeys[4], + ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), + 5, + ); for (key, channel_flags) in [(&privkeys[1], 0), (&privkeys[4], 3)] { - update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 5, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags, - cltv_expiry_delta: (5 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 100, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + key, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags, + cltv_expiry_delta: (5 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 100, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); } - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0); + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[4], + NodeFeatures::from_le_bytes(id_to_feature_flags(4)), + 0, + ); - add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + &privkeys[3], + ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), + 4, + ); for (key, channel_flags) in [(&privkeys[4], 0), (&privkeys[3], 3)] { - update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags, - cltv_expiry_delta: (4 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + key, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags, + cltv_expiry_delta: (4 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); } - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0); + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[3], + NodeFeatures::from_le_bytes(id_to_feature_flags(3)), + 0, + ); - add_channel(&gossip_sync, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[3], + &privkeys[2], + ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), + 3, + ); for (key, channel_flags) in [(&privkeys[3], 0), (&privkeys[2], 3)] { - update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags, - cltv_expiry_delta: (3 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + key, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags, + cltv_expiry_delta: (3 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); } - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0); + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[2], + NodeFeatures::from_le_bytes(id_to_feature_flags(2)), + 0, + ); - add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + &privkeys[4], + ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), + 2, + ); for (key, channel_flags) in [(&privkeys[2], 0), (&privkeys[4], 3)] { - update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags, - cltv_expiry_delta: (2 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + key, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags, + cltv_expiry_delta: (2 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); } - add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + &privkeys[6], + ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), + 1, + ); for (key, channel_flags) in [(&privkeys[4], 0), (&privkeys[6], 3)] { - update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags, - cltv_expiry_delta: (1 << 4) | 0, - htlc_minimum_msat: 100, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + key, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags, + cltv_expiry_delta: (1 << 4) | 0, + htlc_minimum_msat: 100, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); } - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[6], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0); + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[6], + NodeFeatures::from_le_bytes(id_to_feature_flags(6)), + 0, + ); { // Now ensure the route flows simply over nodes 1 and 4 to 6. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 10_000); - let route = get_route(&our_id, &route_params, &network.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, 10_000); + let route = get_route( + &our_id, + &route_params, + &network.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 3); @@ -6718,7 +8335,6 @@ mod tests { } } - #[test] fn exact_fee_liquidity_limit() { // Test that if, while walking the graph, we find a hop that has exactly enough liquidity @@ -6731,59 +8347,84 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[2], 42); // We modify the graph to set the htlc_maximum of channel 2 to below the value we wish to - // send. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 85_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + // send. + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 85_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (4 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: 270_000, - fee_base_msat: 0, - fee_proportional_millionths: 1000000, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (4 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: 270_000, + fee_base_msat: 0, + fee_proportional_millionths: 1000000, + excess_data: Vec::new(), + }, + ); { // Now, attempt to route 90 sats, which is exactly 90 sats at the last hop, plus the // 200% fee charged channel 13 in the 1-to-2 direction. - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, 90_000); - route_params.max_total_routing_fee_msat = Some(90_000*2); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params, 90_000); + route_params.max_total_routing_fee_msat = Some(90_000 * 2); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); assert_eq!(route.paths[0].hops[0].short_channel_id, 12); - assert_eq!(route.paths[0].hops[0].fee_msat, 90_000*2); + assert_eq!(route.paths[0].hops[0].fee_msat, 90_000 * 2); assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1); assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(8)); - assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(12)); + assert_eq!( + route.paths[0].hops[0].channel_features.le_flags(), + &id_to_feature_flags(12) + ); assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]); assert_eq!(route.paths[0].hops[1].short_channel_id, 13); assert_eq!(route.paths[0].hops[1].fee_msat, 90_000); assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42); assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3)); - assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13)); + assert_eq!( + route.paths[0].hops[1].channel_features.le_flags(), + &id_to_feature_flags(13) + ); } } @@ -6805,58 +8446,86 @@ mod tests { // We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2 // gets an htlc_maximum_msat of 80_000 and channel 4 an htlc_minimum_msat of 90_000. We // then try to send 90_000. - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: 80_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (4 << 4) | 1, - htlc_minimum_msat: 90_000, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: 80_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (4 << 4) | 1, + htlc_minimum_msat: 90_000, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); { // Now, attempt to route 90 sats, hitting the htlc_minimum on channel 4, but // overshooting the htlc_maximum on channel 2. Thus, we should pick the (absurdly // expensive) channels 12-13 path. - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, 90_000); - route_params.max_total_routing_fee_msat = Some(90_000*2); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params, 90_000); + route_params.max_total_routing_fee_msat = Some(90_000 * 2); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 2); assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]); assert_eq!(route.paths[0].hops[0].short_channel_id, 12); - assert_eq!(route.paths[0].hops[0].fee_msat, 90_000*2); + assert_eq!(route.paths[0].hops[0].fee_msat, 90_000 * 2); assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1); assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(8)); - assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(12)); + assert_eq!( + route.paths[0].hops[0].channel_features.le_flags(), + &id_to_feature_flags(12) + ); assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]); assert_eq!(route.paths[0].hops[1].short_channel_id, 13); assert_eq!(route.paths[0].hops[1].fee_msat, 90_000); assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42); - assert_eq!(route.paths[0].hops[1].node_features.le_flags(), channelmanager::provided_bolt11_invoice_features(&config).le_flags()); - assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13)); + assert_eq!( + route.paths[0].hops[1].node_features.le_flags(), + channelmanager::provided_bolt11_invoice_features(&config).le_flags() + ); + assert_eq!( + route.paths[0].hops[1].channel_features.le_flags(), + &id_to_feature_flags(13) + ); } } @@ -6880,12 +8549,32 @@ mod tests { let random_seed_bytes = [42; 32]; { - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[ - &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000), - &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000), - ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&[ + &get_channel_details( + Some(3), + nodes[0], + channelmanager::provided_init_features(&config), + 200_000, + ), + &get_channel_details( + Some(2), + nodes[0], + channelmanager::provided_init_features(&config), + 10_000, + ), + ]), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 1); @@ -6894,18 +8583,42 @@ mod tests { assert_eq!(route.paths[0].hops[0].fee_msat, 100_000); } { - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[ - &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000), - &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000), - ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&[ + &get_channel_details( + Some(3), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + &get_channel_details( + Some(2), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + ]), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); assert_eq!(route.paths[0].hops.len(), 1); assert_eq!(route.paths[1].hops.len(), 1); - assert!((route.paths[0].hops[0].short_channel_id == 3 && route.paths[1].hops[0].short_channel_id == 2) || - (route.paths[0].hops[0].short_channel_id == 2 && route.paths[1].hops[0].short_channel_id == 3)); + assert!( + (route.paths[0].hops[0].short_channel_id == 3 + && route.paths[1].hops[0].short_channel_id == 2) + || (route.paths[0].hops[0].short_channel_id == 2 + && route.paths[1].hops[0].short_channel_id == 3) + ); assert_eq!(route.paths[0].hops[0].pubkey, nodes[0]); assert_eq!(route.paths[0].hops[0].fee_msat, 50_000); @@ -6922,18 +8635,68 @@ mod tests { // If we have several options above the 3xpayment value threshold, we should pick the // smallest of them, avoiding further fragmenting our available outbound balance to // this node. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[ - &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000), - &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000), - &get_channel_details(Some(5), nodes[0], channelmanager::provided_init_features(&config), 50_000), - &get_channel_details(Some(6), nodes[0], channelmanager::provided_init_features(&config), 300_000), - &get_channel_details(Some(7), nodes[0], channelmanager::provided_init_features(&config), 50_000), - &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000), - &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000), - &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000), - ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, 100_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + Some(&[ + &get_channel_details( + Some(2), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + &get_channel_details( + Some(3), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + &get_channel_details( + Some(5), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + &get_channel_details( + Some(6), + nodes[0], + channelmanager::provided_init_features(&config), + 300_000, + ), + &get_channel_details( + Some(7), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + &get_channel_details( + Some(8), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + &get_channel_details( + Some(9), + nodes[0], + channelmanager::provided_init_features(&config), + 50_000, + ), + &get_channel_details( + Some(4), + nodes[0], + channelmanager::provided_init_features(&config), + 1_000_000, + ), + ]), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 1); @@ -6947,15 +8710,26 @@ mod tests { fn prefers_shorter_route_with_higher_fees() { let (secp_ctx, network_graph, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[6], 42) + .with_route_hints(last_hops(&nodes)) + .unwrap(); // Without penalizing each hop 100 msats, a longer path with lower fees is chosen. let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); - let route = get_route( &our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert_eq!(route.get_total_fees(), 100); @@ -6965,10 +8739,18 @@ mod tests { // Applying a 100 msat penalty to each hop results in taking channels 7 and 10 to nodes[6] // from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper. let scorer = FixedPenaltyScorer::with_penalty(100); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100); - let route = get_route( &our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert_eq!(route.get_total_fees(), 300); @@ -6982,12 +8764,21 @@ mod tests { #[cfg(c_bindings)] impl Writeable for BadChannelScorer { - fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } + fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { + unimplemented!() + } } impl ScoreLookUp for BadChannelScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { - if candidate.short_channel_id() == Some(self.short_channel_id) { u64::max_value() } else { 0 } + fn channel_penalty_msat( + &self, candidate: &CandidateRouteHop, _: ChannelUsage, + _score_params: &Self::ScoreParams, + ) -> u64 { + if candidate.short_channel_id() == Some(self.short_channel_id) { + u64::max_value() + } else { + 0 + } } } @@ -6997,13 +8788,22 @@ mod tests { #[cfg(c_bindings)] impl Writeable for BadNodeScorer { - fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } + fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { + unimplemented!() + } } impl ScoreLookUp for BadNodeScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { - if candidate.target() == Some(self.node_id) { u64::max_value() } else { 0 } + fn channel_penalty_msat( + &self, candidate: &CandidateRouteHop, _: ChannelUsage, + _score_params: &Self::ScoreParams, + ) -> u64 { + if candidate.target() == Some(self.node_id) { + u64::max_value() + } else { + 0 + } } } @@ -7011,16 +8811,26 @@ mod tests { fn avoids_routing_through_bad_channels_and_nodes() { let (secp_ctx, network, _, _, logger) = build_graph(); let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[6], 42) + .with_route_hints(last_hops(&nodes)) + .unwrap(); let network_graph = network.read_only(); // A path to nodes[6] exists when no penalties are applied to any channel. let scorer = ln_test_utils::TestScorer::new(); let random_seed_bytes = [42; 32]; - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100); - let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert_eq!(route.get_total_fees(), 100); @@ -7029,8 +8839,17 @@ mod tests { // A different path to nodes[6] exists if channel 6 cannot be routed over. let scorer = BadChannelScorer { short_channel_id: 6 }; - let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert_eq!(route.get_total_fees(), 300); @@ -7039,12 +8858,20 @@ mod tests { // A path to nodes[6] does not exist if nodes[2] cannot be routed through. let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) }; - match get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) { - Err(err) => { - assert_eq!(err, "Failed to find a path to the given destination"); - }, - Ok(_) => panic!("Expected error"), + match get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + Err(err) => { + assert_eq!(err, "Failed to find a path to the given destination"); + }, + Ok(_) => panic!("Expected error"), } } @@ -7129,25 +8956,44 @@ mod tests { // Make sure that generally there is at least one route available let feasible_max_total_cltv_delta = 1008; - let feasible_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap() + let feasible_payment_params = PaymentParameters::from_node_id(nodes[6], 0) + .with_route_hints(last_hops(&nodes)) + .unwrap() .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta); let random_seed_bytes = [42; 32]; - let route_params = RouteParameters::from_payment_params_and_value( - feasible_payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(feasible_payment_params, 100); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert_ne!(path.len(), 0); // But not if we exclude all paths on the basis of their accumulated CLTV delta let fail_max_total_cltv_delta = 23; - let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap() + let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0) + .with_route_hints(last_hops(&nodes)) + .unwrap() .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta); - let route_params = RouteParameters::from_payment_params_and_value( - fail_payment_params, 100); - match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) - { + let route_params = RouteParameters::from_payment_params_and_value(fail_payment_params, 100); + match get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { Err(err) => { assert_eq!(err, "Failed to find a path to the given destination"); }, @@ -7164,29 +9010,53 @@ mod tests { let network_graph = network.read_only(); let scorer = ln_test_utils::TestScorer::new(); - let mut payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap() + let mut payment_params = PaymentParameters::from_node_id(nodes[6], 0) + .with_route_hints(last_hops(&nodes)) + .unwrap() .with_max_path_count(1); let random_seed_bytes = [42; 32]; // We should be able to find a route initially, and then after we fail a few random // channels eventually we won't be able to any longer. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); - assert!(get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).is_ok()); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100); + assert!(get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes + ) + .is_ok()); loop { - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); - if let Ok(route) = get_route(&our_id, &route_params, &network_graph, None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) - { + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100); + if let Ok(route) = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { for chan in route.paths[0].hops.iter() { - assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id)); + assert!(!payment_params + .previously_failed_channels + .contains(&chan.short_channel_id)); } - let victim = (u64::from_ne_bytes(random_seed_bytes[0..8].try_into().unwrap()) as usize) - % route.paths[0].hops.len(); - payment_params.previously_failed_channels.push(route.paths[0].hops[victim].short_channel_id); - } else { break; } + let victim = (u64::from_ne_bytes(random_seed_bytes[0..8].try_into().unwrap()) + as usize) % route.paths[0].hops.len(); + payment_params + .previously_failed_channels + .push(route.paths[0].hops[victim].short_channel_id); + } else { + break; + } } } @@ -7201,20 +9071,35 @@ mod tests { // First check we can actually create a long route on this graph. let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0); - let route_params = RouteParameters::from_payment_params_and_value( - feasible_payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(feasible_payment_params, 100); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::>(); assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into()); // But we can't create a path surpassing the MAX_PATH_LENGTH_ESTIMATE limit. let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0); - let route_params = RouteParameters::from_payment_params_and_value( - fail_payment_params, 100); - match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) - { + let route_params = RouteParameters::from_payment_params_and_value(fail_payment_params, 100); + match get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { Err(err) => { assert_eq!(err, "Failed to find a path to the given destination"); }, @@ -7229,30 +9114,58 @@ mod tests { let scorer = ln_test_utils::TestScorer::new(); - let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap(); + let payment_params = PaymentParameters::from_node_id(nodes[6], 42) + .with_route_hints(last_hops(&nodes)) + .unwrap(); let random_seed_bytes = [42; 32]; - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); - let cltv_expiry_deltas_before = route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::>(); + let cltv_expiry_deltas_before = + route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::>(); // Check whether the offset added to the last hop by default is in [1 .. DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA] let mut route_default = route.clone(); - add_random_cltv_offset(&mut route_default, &payment_params, &network_graph.read_only(), &random_seed_bytes); - let cltv_expiry_deltas_default = route_default.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::>(); - assert_eq!(cltv_expiry_deltas_before.split_last().unwrap().1, cltv_expiry_deltas_default.split_last().unwrap().1); + add_random_cltv_offset( + &mut route_default, + &payment_params, + &network_graph.read_only(), + &random_seed_bytes, + ); + let cltv_expiry_deltas_default = + route_default.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::>(); + assert_eq!( + cltv_expiry_deltas_before.split_last().unwrap().1, + cltv_expiry_deltas_default.split_last().unwrap().1 + ); assert!(cltv_expiry_deltas_default.last() > cltv_expiry_deltas_before.last()); assert!(cltv_expiry_deltas_default.last().unwrap() <= &DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA); // Check that no offset is added when we restrict the max_total_cltv_expiry_delta let mut route_limited = route.clone(); let limited_max_total_cltv_expiry_delta = cltv_expiry_deltas_before.iter().sum(); - let limited_payment_params = payment_params.with_max_total_cltv_expiry_delta(limited_max_total_cltv_expiry_delta); - add_random_cltv_offset(&mut route_limited, &limited_payment_params, &network_graph.read_only(), &random_seed_bytes); - let cltv_expiry_deltas_limited = route_limited.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::>(); + let limited_payment_params = + payment_params.with_max_total_cltv_expiry_delta(limited_max_total_cltv_expiry_delta); + add_random_cltv_offset( + &mut route_limited, + &limited_payment_params, + &network_graph.read_only(), + &random_seed_bytes, + ); + let cltv_expiry_deltas_limited = + route_limited.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::>(); assert_eq!(cltv_expiry_deltas_before, cltv_expiry_deltas_limited); } @@ -7267,10 +9180,19 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[3], 0); let random_seed_bytes = [42; 32]; - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 100); - let mut route = get_route(&our_id, &route_params, &network_graph, None, - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 100); + let mut route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes); let mut path_plausibility = vec![]; @@ -7282,10 +9204,12 @@ mod tests { prng.process_in_place(&mut random_bytes); let random_path_index = usize::from_be_bytes(random_bytes).wrapping_rem(p.hops.len()); - let observation_point = NodeId::from_pubkey(&p.hops.get(random_path_index).unwrap().pubkey); + let observation_point = + NodeId::from_pubkey(&p.hops.get(random_path_index).unwrap().pubkey); // 2. Calculate what CLTV expiry delta we would observe there - let observed_cltv_expiry_delta: u32 = p.hops[random_path_index..].iter().map(|h| h.cltv_expiry_delta).sum(); + let observed_cltv_expiry_delta: u32 = + p.hops[random_path_index..].iter().map(|h| h.cltv_expiry_delta).sum(); // 3. Starting from the observation point, find candidate paths let mut candidates: VecDeque<(NodeId, Vec)> = VecDeque::new(); @@ -7293,9 +9217,16 @@ mod tests { let mut found_plausible_candidate = false; - 'candidate_loop: while let Some((cur_node_id, cur_path_cltv_deltas)) = candidates.pop_front() { - if let Some(remaining) = observed_cltv_expiry_delta.checked_sub(cur_path_cltv_deltas.iter().sum::()) { - if remaining == 0 || remaining.wrapping_rem(40) == 0 || remaining.wrapping_rem(144) == 0 { + 'candidate_loop: while let Some((cur_node_id, cur_path_cltv_deltas)) = + candidates.pop_front() + { + if let Some(remaining) = + observed_cltv_expiry_delta.checked_sub(cur_path_cltv_deltas.iter().sum::()) + { + if remaining == 0 + || remaining.wrapping_rem(40) == 0 + || remaining.wrapping_rem(144) == 0 + { found_plausible_candidate = true; break 'candidate_loop; } @@ -7304,10 +9235,17 @@ mod tests { if let Some(cur_node) = network_nodes.get(&cur_node_id) { for channel_id in &cur_node.channels { if let Some(channel_info) = network_channels.get(&channel_id) { - if let Some((dir_info, next_id)) = channel_info.as_directed_from(&cur_node_id) { - let next_cltv_expiry_delta = dir_info.direction().cltv_expiry_delta as u32; - if cur_path_cltv_deltas.iter().sum::() - .saturating_add(next_cltv_expiry_delta) <= observed_cltv_expiry_delta { + if let Some((dir_info, next_id)) = + channel_info.as_directed_from(&cur_node_id) + { + let next_cltv_expiry_delta = + dir_info.direction().cltv_expiry_delta as u32; + if cur_path_cltv_deltas + .iter() + .sum::() + .saturating_add(next_cltv_expiry_delta) + <= observed_cltv_expiry_delta + { let mut new_path_cltv_deltas = cur_path_cltv_deltas.clone(); new_path_cltv_deltas.push(next_cltv_expiry_delta); candidates.push_back((*next_id, new_path_cltv_deltas)); @@ -7333,9 +9271,17 @@ mod tests { let payment_params = PaymentParameters::from_node_id(nodes[3], 0); let hops = [nodes[1], nodes[2], nodes[4], nodes[3]]; let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - let route = build_route_from_hops_internal(&our_id, &hops, &route_params, &network_graph, - Arc::clone(&logger), &random_seed_bytes).unwrap(); - let route_hop_pubkeys = route.paths[0].hops.iter().map(|hop| hop.pubkey).collect::>(); + let route = build_route_from_hops_internal( + &our_id, + &hops, + &route_params, + &network_graph, + Arc::clone(&logger), + &random_seed_bytes, + ) + .unwrap(); + let route_hop_pubkeys = + route.paths[0].hops.iter().map(|hop| hop.pubkey).collect::>(); assert_eq!(hops.len(), route.paths[0].hops.len()); for (idx, hop_pubkey) in hops.iter().enumerate() { assert!(*hop_pubkey == route_hop_pubkeys[idx]); @@ -7351,32 +9297,42 @@ mod tests { // Set the fee on channel 13 to 0% to match channel 4 giving us two equivalent paths (us // -> node 7 -> node2 and us -> node 1 -> node 2) which we should balance over. - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (4 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: 250_000_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (13 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: 250_000_000, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (4 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: 250_000_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (13 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: 250_000_000, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); let config = UserConfig::default(); let payment_params = PaymentParameters::from_node_id(nodes[2], 42) @@ -7388,13 +9344,26 @@ mod tests { // applying max_channel_saturation_power_of_half. This value also ensures the cost of paths // considered when applying max_channel_saturation_power_of_half is less than the cost of // those when it is not applied. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 75_000_000); - let route = get_route(&our_id, &route_params, &network_graph.read_only(), None, - Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap(); + let route_params = + RouteParameters::from_payment_params_and_value(payment_params, 75_000_000); + let route = get_route( + &our_id, + &route_params, + &network_graph.read_only(), + None, + Arc::clone(&logger), + &scorer, + &ProbabilisticScoringFeeParameters::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); - assert!((route.paths[0].hops[1].short_channel_id == 4 && route.paths[1].hops[1].short_channel_id == 13) || - (route.paths[1].hops[1].short_channel_id == 4 && route.paths[0].hops[1].short_channel_id == 13)); + assert!( + (route.paths[0].hops[1].short_channel_id == 4 + && route.paths[1].hops[1].short_channel_id == 13) + || (route.paths[1].hops[1].short_channel_id == 4 + && route.paths[0].hops[1].short_channel_id == 13) + ); } pub(super) fn random_init_seed() -> u64 { @@ -7421,7 +9390,15 @@ mod tests { let params = ProbabilisticScoringFeeParameters::default(); let features = super::Bolt11InvoiceFeatures::empty(); - super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 0, 2); + super::bench_utils::generate_test_routes( + &graph, + &mut scorer, + ¶ms, + features, + random_init_seed(), + 0, + 2, + ); } #[test] @@ -7440,7 +9417,15 @@ mod tests { let params = ProbabilisticScoringFeeParameters::default(); let features = channelmanager::provided_bolt11_invoice_features(&UserConfig::default()); - super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 0, 2); + super::bench_utils::generate_test_routes( + &graph, + &mut scorer, + ¶ms, + features, + random_init_seed(), + 0, + 2, + ); } #[test] @@ -7459,7 +9444,15 @@ mod tests { let params = ProbabilisticScoringFeeParameters::default(); let features = channelmanager::provided_bolt11_invoice_features(&UserConfig::default()); - super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 1_000_000, 2); + super::bench_utils::generate_test_routes( + &graph, + &mut scorer, + ¶ms, + features, + random_init_seed(), + 1_000_000, + 2, + ); } #[test] @@ -7469,13 +9462,20 @@ mod tests { let random_seed_bytes = [42; 32]; let mut scorer_params = ProbabilisticScoringFeeParameters::default(); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger)); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + Arc::clone(&network_graph), + Arc::clone(&logger), + ); // First check set manual penalties are returned by the scorer. let usage = ChannelUsage { amount_msat: 0, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024_000, + htlc_maximum_msat: 1_000, + }, }; scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123); scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456); @@ -7483,28 +9483,51 @@ mod tests { let channels = network_graph.channels(); let channel = channels.get(&5).unwrap(); let info = channel.as_directed_from(&NodeId::from_pubkey(&nodes[3])).unwrap(); - let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop(PublicHopCandidate { - info: info.0, - short_channel_id: 5, - }); + let candidate: CandidateRouteHop = + CandidateRouteHop::PublicHop(PublicHopCandidate { info: info.0, short_channel_id: 5 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, &scorer_params), 456); // Then check we can get a normal route let payment_params = PaymentParameters::from_node_id(nodes[10], 42); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100); - let route = get_route(&our_id, &route_params, &network_graph, None, - Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &scorer_params, + &random_seed_bytes, + ); assert!(route.is_ok()); // Then check that we can't get a route if we ban an intermediate node. scorer_params.add_banned(&NodeId::from_pubkey(&nodes[3])); - let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &scorer_params, + &random_seed_bytes, + ); assert!(route.is_err()); // Finally make sure we can route again, when we remove the ban. scorer_params.remove_banned(&NodeId::from_pubkey(&nodes[3])); - let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &scorer_params, + &random_seed_bytes, + ); assert!(route.is_ok()); } @@ -7523,44 +9546,60 @@ mod tests { let route_hint_1 = RouteHint(vec![RouteHintHop { src_node_id: nodes[2], short_channel_id: 42, - fees: RoutingFees { - base_msat: 100, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 100, proportional_millionths: 0 }, cltv_expiry_delta: 10, htlc_minimum_msat: None, htlc_maximum_msat: Some(max_htlc_msat), }]); let dest_node_id = ln_test_utils::pubkey(42); let payment_params = PaymentParameters::from_node_id(dest_node_id, 42) - .with_route_hints(vec![route_hint_1.clone()]).unwrap() + .with_route_hints(vec![route_hint_1.clone()]) + .unwrap() .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) .unwrap(); // Make sure we'll error if our route hints don't have enough liquidity according to their // htlc_maximum_msat. - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, max_htlc_msat + 1); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params, max_htlc_msat + 1); route_params.max_total_routing_fee_msat = None; - if let Err(err) = get_route(&our_id, - &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), - &random_seed_bytes) - { + if let Err(err) = get_route( + &our_id, + &route_params, + &netgraph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { assert_eq!(err, "Failed to find a sufficient route to the given destination"); - } else { panic!(); } + } else { + panic!(); + } // Make sure we'll split an MPP payment across route hints if their htlc_maximum_msat warrants. let mut route_hint_2 = route_hint_1.clone(); route_hint_2.0[0].short_channel_id = 43; let payment_params = PaymentParameters::from_node_id(dest_node_id, 42) - .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap() + .with_route_hints(vec![route_hint_1, route_hint_2]) + .unwrap() .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) .unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params, max_htlc_msat + 1); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params, max_htlc_msat + 1); route_params.max_total_routing_fee_msat = Some(max_htlc_msat * 2); - let route = get_route(&our_id, &route_params, &netgraph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &netgraph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat); assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat); @@ -7578,46 +9617,56 @@ mod tests { let our_node_id = ln_test_utils::pubkey(42); let intermed_node_id = ln_test_utils::pubkey(43); - let first_hop = vec![get_channel_details(Some(42), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), 10_000_000)]; + let first_hop = vec![get_channel_details( + Some(42), + intermed_node_id, + InitFeatures::from_le_bytes(vec![0b11]), + 10_000_000, + )]; let amt_msat = 900_000; let max_htlc_msat = 500_000; - let route_hint_1 = RouteHint(vec![RouteHintHop { - src_node_id: intermed_node_id, - short_channel_id: 44, - fees: RoutingFees { - base_msat: 100, - proportional_millionths: 0, + let route_hint_1 = RouteHint(vec![ + RouteHintHop { + src_node_id: intermed_node_id, + short_channel_id: 44, + fees: RoutingFees { base_msat: 100, proportional_millionths: 0 }, + cltv_expiry_delta: 10, + htlc_minimum_msat: None, + htlc_maximum_msat: Some(max_htlc_msat), }, - cltv_expiry_delta: 10, - htlc_minimum_msat: None, - htlc_maximum_msat: Some(max_htlc_msat), - }, RouteHintHop { - src_node_id: intermed_node_id, - short_channel_id: 45, - fees: RoutingFees { - base_msat: 100, - proportional_millionths: 0, + RouteHintHop { + src_node_id: intermed_node_id, + short_channel_id: 45, + fees: RoutingFees { base_msat: 100, proportional_millionths: 0 }, + cltv_expiry_delta: 10, + htlc_minimum_msat: None, + // Check that later route hint max htlcs don't override earlier ones + htlc_maximum_msat: Some(max_htlc_msat - 50), }, - cltv_expiry_delta: 10, - htlc_minimum_msat: None, - // Check that later route hint max htlcs don't override earlier ones - htlc_maximum_msat: Some(max_htlc_msat - 50), - }]); + ]); let mut route_hint_2 = route_hint_1.clone(); route_hint_2.0[0].short_channel_id = 46; route_hint_2.0[1].short_channel_id = 47; let dest_node_id = ln_test_utils::pubkey(44); let payment_params = PaymentParameters::from_node_id(dest_node_id, 42) - .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap() + .with_route_hints(vec![route_hint_1, route_hint_2]) + .unwrap() .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) .unwrap(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); - let route = get_route(&our_node_id, &route_params, &network_graph.read_only(), - Some(&first_hop.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route = get_route( + &our_node_id, + &route_params, + &network_graph.read_only(), + Some(&first_hop.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat); assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat); @@ -7626,12 +9675,30 @@ mod tests { // Re-run but with two first hop channels connected to the same route hint peers that must be // split between. let first_hops = vec![ - get_channel_details(Some(42), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10), - get_channel_details(Some(43), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10), + get_channel_details( + Some(42), + intermed_node_id, + InitFeatures::from_le_bytes(vec![0b11]), + amt_msat - 10, + ), + get_channel_details( + Some(43), + intermed_node_id, + InitFeatures::from_le_bytes(vec![0b11]), + amt_msat - 10, + ), ]; - let route = get_route(&our_node_id, &route_params, &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_node_id, + &route_params, + &network_graph.read_only(), + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat); assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat); @@ -7648,14 +9715,22 @@ mod tests { }; let blinded_path = dummy_blinded_path(intermed_node_id, blinded_payinfo); let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); - let payment_params = PaymentParameters::blinded(vec![ - blinded_path.clone(), blinded_path.clone() - ]).with_bolt12_features(bolt12_features).unwrap(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); - let route = get_route(&our_node_id, &route_params, &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let payment_params = + PaymentParameters::blinded(vec![blinded_path.clone(), blinded_path.clone()]) + .with_bolt12_features(bolt12_features) + .unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route = get_route( + &our_node_id, + &route_params, + &network_graph.read_only(), + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat); assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat); @@ -7665,35 +9740,48 @@ mod tests { #[test] fn blinded_route_ser() { // (De)serialize a Route with 1 blinded path out of two total paths. - let mut route = Route { paths: vec![Path { - hops: vec![RouteHop { - pubkey: ln_test_utils::pubkey(50), - node_features: NodeFeatures::empty(), - short_channel_id: 42, - channel_features: ChannelFeatures::empty(), - fee_msat: 100, - cltv_expiry_delta: 0, - maybe_announced_channel: true, - }], - blinded_tail: Some(BlindedTail { - trampoline_hops: vec![], - hops: vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(44), encrypted_payload: Vec::new() }, - BlindedHop { blinded_node_id: ln_test_utils::pubkey(45), encrypted_payload: Vec::new() } - ], - blinding_point: ln_test_utils::pubkey(43), - excess_final_cltv_expiry_delta: 40, - final_value_msat: 100, - })}, Path { - hops: vec![RouteHop { - pubkey: ln_test_utils::pubkey(51), - node_features: NodeFeatures::empty(), - short_channel_id: 43, - channel_features: ChannelFeatures::empty(), - fee_msat: 100, - cltv_expiry_delta: 0, - maybe_announced_channel: true, - }], blinded_tail: None }], + let mut route = Route { + paths: vec![ + Path { + hops: vec![RouteHop { + pubkey: ln_test_utils::pubkey(50), + node_features: NodeFeatures::empty(), + short_channel_id: 42, + channel_features: ChannelFeatures::empty(), + fee_msat: 100, + cltv_expiry_delta: 0, + maybe_announced_channel: true, + }], + blinded_tail: Some(BlindedTail { + trampoline_hops: vec![], + hops: vec![ + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(44), + encrypted_payload: Vec::new(), + }, + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(45), + encrypted_payload: Vec::new(), + }, + ], + blinding_point: ln_test_utils::pubkey(43), + excess_final_cltv_expiry_delta: 40, + final_value_msat: 100, + }), + }, + Path { + hops: vec![RouteHop { + pubkey: ln_test_utils::pubkey(51), + node_features: NodeFeatures::empty(), + short_channel_id: 43, + channel_features: ChannelFeatures::empty(), + fee_msat: 100, + cltv_expiry_delta: 0, + maybe_announced_channel: true, + }], + blinded_tail: None, + }, + ], route_params: None, }; let encoded_route = route.encode(); @@ -7705,8 +9793,14 @@ mod tests { route.paths[1].blinded_tail = Some(BlindedTail { trampoline_hops: vec![], hops: vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(48), encrypted_payload: Vec::new() }, - BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() } + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(48), + encrypted_payload: Vec::new(), + }, + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(49), + encrypted_payload: Vec::new(), + }, ], blinding_point: ln_test_utils::pubkey(47), excess_final_cltv_expiry_delta: 41, @@ -7724,27 +9818,32 @@ mod tests { // account for the blinded tail's final amount_msat. let mut inflight_htlcs = InFlightHtlcs::new(); let path = Path { - hops: vec![RouteHop { - pubkey: ln_test_utils::pubkey(42), - node_features: NodeFeatures::empty(), - short_channel_id: 42, - channel_features: ChannelFeatures::empty(), - fee_msat: 100, - cltv_expiry_delta: 0, - maybe_announced_channel: false, - }, - RouteHop { - pubkey: ln_test_utils::pubkey(43), - node_features: NodeFeatures::empty(), - short_channel_id: 43, - channel_features: ChannelFeatures::empty(), - fee_msat: 1, - cltv_expiry_delta: 0, - maybe_announced_channel: false, - }], + hops: vec![ + RouteHop { + pubkey: ln_test_utils::pubkey(42), + node_features: NodeFeatures::empty(), + short_channel_id: 42, + channel_features: ChannelFeatures::empty(), + fee_msat: 100, + cltv_expiry_delta: 0, + maybe_announced_channel: false, + }, + RouteHop { + pubkey: ln_test_utils::pubkey(43), + node_features: NodeFeatures::empty(), + short_channel_id: 43, + channel_features: ChannelFeatures::empty(), + fee_msat: 1, + cltv_expiry_delta: 0, + maybe_announced_channel: false, + }, + ], blinded_tail: Some(BlindedTail { trampoline_hops: vec![], - hops: vec![BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() }], + hops: vec![BlindedHop { + blinded_node_id: ln_test_utils::pubkey(49), + encrypted_payload: Vec::new(), + }], blinding_point: ln_test_utils::pubkey(48), excess_final_cltv_expiry_delta: 0, final_value_msat: 200, @@ -7758,42 +9857,55 @@ mod tests { #[test] fn blinded_path_cltv_shadow_offset() { // Make sure we add a shadow offset when sending to blinded paths. - let mut route = Route { paths: vec![Path { - hops: vec![RouteHop { - pubkey: ln_test_utils::pubkey(42), - node_features: NodeFeatures::empty(), - short_channel_id: 42, - channel_features: ChannelFeatures::empty(), - fee_msat: 100, - cltv_expiry_delta: 0, - maybe_announced_channel: false, - }, - RouteHop { - pubkey: ln_test_utils::pubkey(43), - node_features: NodeFeatures::empty(), - short_channel_id: 43, - channel_features: ChannelFeatures::empty(), - fee_msat: 1, - cltv_expiry_delta: 0, - maybe_announced_channel: false, - } - ], - blinded_tail: Some(BlindedTail { - trampoline_hops: vec![], + let mut route = Route { + paths: vec![Path { hops: vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(45), encrypted_payload: Vec::new() }, - BlindedHop { blinded_node_id: ln_test_utils::pubkey(46), encrypted_payload: Vec::new() } + RouteHop { + pubkey: ln_test_utils::pubkey(42), + node_features: NodeFeatures::empty(), + short_channel_id: 42, + channel_features: ChannelFeatures::empty(), + fee_msat: 100, + cltv_expiry_delta: 0, + maybe_announced_channel: false, + }, + RouteHop { + pubkey: ln_test_utils::pubkey(43), + node_features: NodeFeatures::empty(), + short_channel_id: 43, + channel_features: ChannelFeatures::empty(), + fee_msat: 1, + cltv_expiry_delta: 0, + maybe_announced_channel: false, + }, ], - blinding_point: ln_test_utils::pubkey(44), - excess_final_cltv_expiry_delta: 0, - final_value_msat: 200, - }), - }], route_params: None}; + blinded_tail: Some(BlindedTail { + trampoline_hops: vec![], + hops: vec![ + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(45), + encrypted_payload: Vec::new(), + }, + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(46), + encrypted_payload: Vec::new(), + }, + ], + blinding_point: ln_test_utils::pubkey(44), + excess_final_cltv_expiry_delta: 0, + final_value_msat: 200, + }), + }], + route_params: None, + }; let payment_params = PaymentParameters::from_node_id(ln_test_utils::pubkey(47), 18); let (_, network_graph, _, _, _) = build_line_graph(); add_random_cltv_offset(&mut route, &payment_params, &network_graph.read_only(), &[0; 32]); - assert_eq!(route.paths[0].blinded_tail.as_ref().unwrap().excess_final_cltv_expiry_delta, 40); + assert_eq!( + route.paths[0].blinded_tail.as_ref().unwrap().excess_final_cltv_expiry_delta, + 40 + ); assert_eq!(route.paths[0].hops.last().unwrap().cltv_expiry_delta, 40); } @@ -7815,9 +9927,10 @@ mod tests { let mut blinded_hops = Vec::new(); for i in 0..num_blinded_hops { - blinded_hops.push( - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 + i as u8), encrypted_payload: Vec::new() }, - ); + blinded_hops.push(BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42 + i as u8), + encrypted_payload: Vec::new(), + }); } let blinded_payinfo = BlindedPayInfo { fee_base_msat: 100, @@ -7827,8 +9940,14 @@ mod tests { cltv_expiry_delta: 15, features: BlindedHopFeatures::empty(), }; - let blinded_path = BlindedPaymentPath::from_raw(nodes[2], ln_test_utils::pubkey(42), blinded_hops, blinded_payinfo.clone()); - let payment_params = PaymentParameters::blinded(vec![blinded_path.clone(), blinded_path.clone()]); + let blinded_path = BlindedPaymentPath::from_raw( + nodes[2], + ln_test_utils::pubkey(42), + blinded_hops, + blinded_payinfo.clone(), + ); + let payment_params = + PaymentParameters::blinded(vec![blinded_path.clone(), blinded_path.clone()]); // Make sure we can round-trip read and write blinded payment params. let encoded_params = payment_params.encode(); @@ -7837,10 +9956,18 @@ mod tests { let decoded_params: PaymentParameters = ReadableArgs::read(&mut reader, 42).unwrap(); assert_eq!(payment_params, decoded_params); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 1001); - let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), 2); @@ -7855,8 +9982,12 @@ mod tests { *blinded_path.public_introduction_node_id(&network_graph).unwrap() ); if tail.hops.len() > 1 { - assert_eq!(final_hop.fee_msat, - blinded_payinfo.fee_base_msat as u64 + blinded_payinfo.fee_proportional_millionths as u64 * tail.final_value_msat / 1000000); + assert_eq!( + final_hop.fee_msat, + blinded_payinfo.fee_base_msat as u64 + + blinded_payinfo.fee_proportional_millionths as u64 * tail.final_value_msat + / 1000000 + ); assert_eq!(final_hop.cltv_expiry_delta, blinded_payinfo.cltv_expiry_delta as u32); } else { assert_eq!(final_hop.fee_msat, 0); @@ -7885,41 +10016,63 @@ mod tests { let invalid_blinded_path_2 = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone()); let invalid_blinded_path_3 = dummy_one_hop_blinded_path(nodes[3], blinded_payinfo.clone()); - let payment_params = PaymentParameters::blinded(vec![ - invalid_blinded_path_2, invalid_blinded_path_3]); + let payment_params = + PaymentParameters::blinded(vec![invalid_blinded_path_2, invalid_blinded_path_3]); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001); - match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes) - { + match get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { Err(err) => { assert_eq!(err, "1-hop blinded paths must all have matching introduction node ids"); }, - _ => panic!("Expected error") + _ => panic!("Expected error"), } let invalid_blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone()); let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001); - match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) - { + match get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { Err(err) => { assert_eq!(err, "Cannot generate a route to blinded paths if we are the introduction node to all of them"); }, - _ => panic!("Expected error") + _ => panic!("Expected error"), } - let mut invalid_blinded_path = dummy_one_hop_blinded_path(ln_test_utils::pubkey(46), blinded_payinfo); + let mut invalid_blinded_path = + dummy_one_hop_blinded_path(ln_test_utils::pubkey(46), blinded_payinfo); invalid_blinded_path.clear_blinded_hops(); let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001); - match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) - { + match get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { Err(err) => { assert_eq!(err, "0-hop blinded path provided"); }, - _ => panic!("Expected error") + _ => panic!("Expected error"), } } @@ -7948,31 +10101,57 @@ mod tests { let mut blinded_payinfo_2 = blinded_payinfo_1; blinded_payinfo_2.htlc_maximum_msat = 70_000; - let blinded_path_2 = BlindedPaymentPath::from_raw(nodes[2], ln_test_utils::pubkey(43), + let blinded_path_2 = BlindedPaymentPath::from_raw( + nodes[2], + ln_test_utils::pubkey(43), vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }, - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() } + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42 as u8), + encrypted_payload: Vec::new(), + }, + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42 as u8), + encrypted_payload: Vec::new(), + }, ], - blinded_payinfo_2 + blinded_payinfo_2, ); let blinded_hints = vec![blinded_path_1.clone(), blinded_path_2.clone()]; let payment_params = PaymentParameters::blinded(blinded_hints.clone()) - .with_bolt12_features(bolt12_features).unwrap(); + .with_bolt12_features(bolt12_features) + .unwrap(); - let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100_000); + let mut route_params = + RouteParameters::from_payment_params_and_value(payment_params, 100_000); route_params.max_total_routing_fee_msat = Some(100_000); - let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_id, + &route_params, + &network_graph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 2); let mut total_amount_paid_msat = 0; for path in route.paths.into_iter() { assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); if let Some(bt) = &path.blinded_tail { - assert_eq!(bt.blinding_point, - blinded_hints.iter().find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat()) - .map(|bp| bp.blinding_point()).unwrap()); - } else { panic!(); } + assert_eq!( + bt.blinding_point, + blinded_hints + .iter() + .find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat()) + .map(|bp| bp.blinding_point()) + .unwrap() + ); + } else { + panic!(); + } total_amount_paid_msat += path.final_value_msat(); } assert_eq!(total_amount_paid_msat, 100_000); @@ -7998,36 +10177,56 @@ mod tests { let amt_msat = 10_000_000; let (_, _, privkeys, nodes) = get_nodes(&secp_ctx); - add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[1], - ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 42, - htlc_minimum_msat: 1_000, - htlc_maximum_msat: 10_000_000, - fee_base_msat: 800, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: 42, - htlc_minimum_msat: 1_000, - htlc_maximum_msat: 10_000_000, - fee_base_msat: 800, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - let first_hops = vec![ - get_channel_details(Some(1), nodes[1], InitFeatures::from_le_bytes(vec![0b11]), 10_000_000)]; + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + &privkeys[1], + ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), + 1, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 42, + htlc_minimum_msat: 1_000, + htlc_maximum_msat: 10_000_000, + fee_base_msat: 800, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: 42, + htlc_minimum_msat: 1_000, + htlc_maximum_msat: 10_000_000, + fee_base_msat: 800, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + let first_hops = vec![get_channel_details( + Some(1), + nodes[1], + InitFeatures::from_le_bytes(vec![0b11]), + 10_000_000, + )]; let blinded_payinfo = BlindedPayInfo { fee_base_msat: 1000, @@ -8043,21 +10242,40 @@ mod tests { let payment_params = PaymentParameters::blinded(blinded_hints.clone()); let netgraph = network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), amt_msat); - if let Err(err) = get_route(&nodes[0], &route_params, &netgraph, - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes) { - assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!("Expected error") } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), amt_msat); + if let Err(err) = get_route( + &nodes[0], + &route_params, + &netgraph, + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) { + assert_eq!(err, "Failed to find a path to the given destination"); + } else { + panic!("Expected error") + } // Sending an exact amount accounting for the blinded path fee works. let amt_minus_blinded_path_fee = amt_msat - blinded_payinfo.fee_base_msat as u64; let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_minus_blinded_path_fee); - let route = get_route(&nodes[0], &route_params, &netgraph, - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + payment_params, + amt_minus_blinded_path_fee, + ); + let route = get_route( + &nodes[0], + &route_params, + &netgraph, + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64); assert_eq!(route.get_total_amount(), amt_minus_blinded_path_fee); } @@ -8086,9 +10304,12 @@ mod tests { // Values are taken from the fuzz input that uncovered this panic. let amt_msat = 21_7020_5185_1403_2640; let (_, _, _, nodes) = get_nodes(&secp_ctx); - let first_hops = vec![ - get_channel_details(Some(1), nodes[1], channelmanager::provided_init_features(&config), - 18446744073709551615)]; + let first_hops = vec![get_channel_details( + Some(1), + nodes[1], + channelmanager::provided_init_features(&config), + 18446744073709551615, + )]; let blinded_payinfo = BlindedPayInfo { fee_base_msat: 5046_2720, @@ -8108,14 +10329,22 @@ mod tests { let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); let payment_params = PaymentParameters::blinded(blinded_hints.clone()) - .with_bolt12_features(bolt12_features).unwrap(); + .with_bolt12_features(bolt12_features) + .unwrap(); let netgraph = network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); - let route = get_route(&nodes[0], &route_params, &netgraph, - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route = get_route( + &nodes[0], + &route_params, + &netgraph, + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64); assert_eq!(route.get_total_amount(), amt_msat); } @@ -8149,16 +10378,25 @@ mod tests { let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); let payment_params = PaymentParameters::blinded(blinded_hints.clone()) - .with_bolt12_features(bolt12_features.clone()).unwrap(); + .with_bolt12_features(bolt12_features.clone()) + .unwrap(); let netgraph = network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); if let Err(err) = get_route( - &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes + &our_id, + &route_params, + &netgraph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, ) { assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!() } + } else { + panic!() + } } #[test] @@ -8185,9 +10423,8 @@ mod tests { features: BlindedHopFeatures::empty(), }; let blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone()); - let mut blinded_hints = vec![ - blinded_path.clone(), blinded_path.clone(), blinded_path.clone(), - ]; + let mut blinded_hints = + vec![blinded_path.clone(), blinded_path.clone(), blinded_path.clone()]; blinded_hints[1].payinfo.fee_base_msat = 5052_9027; blinded_hints[1].payinfo.htlc_minimum_msat = 21_7020_5185_1423_0019; blinded_hints[1].payinfo.htlc_maximum_msat = 1844_6744_0737_0955_1615; @@ -8196,16 +10433,25 @@ mod tests { let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); let payment_params = PaymentParameters::blinded(blinded_hints.clone()) - .with_bolt12_features(bolt12_features.clone()).unwrap(); + .with_bolt12_features(bolt12_features.clone()) + .unwrap(); let netgraph = network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); if let Err(err) = get_route( - &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes + &our_id, + &route_params, + &netgraph, + None, + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, ) { assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!() } + } else { + panic!() + } } #[test] @@ -8230,8 +10476,10 @@ mod tests { let (_, our_id, _, nodes) = get_nodes(&secp_ctx); let first_hop_outbound_capacity = 2_7345_2000; let first_hops = vec![get_channel_details( - Some(200), nodes[0], channelmanager::provided_init_features(&config), - first_hop_outbound_capacity + Some(200), + nodes[0], + channelmanager::provided_init_features(&config), + first_hop_outbound_capacity, )]; let base_fee = 1_6778_3453; @@ -8248,41 +10496,47 @@ mod tests { let blinded_path = dummy_blinded_path(nodes[0], blinded_payinfo); let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); PaymentParameters::blinded(vec![blinded_path]) - .with_bolt12_features(bolt12_features.clone()).unwrap() + .with_bolt12_features(bolt12_features.clone()) + .unwrap() } else { let route_hint = RouteHint(vec![RouteHintHop { src_node_id: nodes[0], short_channel_id: 42, - fees: RoutingFees { - base_msat: base_fee, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: base_fee, proportional_millionths: 0 }, cltv_expiry_delta: 10, htlc_minimum_msat: Some(htlc_min), htlc_maximum_msat: None, }]); PaymentParameters::from_node_id(nodes[1], 42) - .with_route_hints(vec![route_hint]).unwrap() - .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap() + .with_route_hints(vec![route_hint]) + .unwrap() + .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) + .unwrap() }; let netgraph = network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); if let Err(err) = get_route( - &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::>()), - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes + &our_id, + &route_params, + &netgraph, + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, ) { assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!() } + } else { + panic!() + } } #[test] fn previously_used_liquidity_violates_max_htlc() { do_previously_used_liquidity_violates_max_htlc(true); do_previously_used_liquidity_violates_max_htlc(false); - } fn do_previously_used_liquidity_violates_max_htlc(blinded_payee: bool) { // Test that if a candidate first_hop<>route_hint_src_node channel does not have enough @@ -8300,11 +10554,20 @@ mod tests { // Values are taken from the fuzz input that uncovered this panic. let amt_msat = 52_4288; let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let first_hops = vec![get_channel_details( - Some(161), nodes[0], channelmanager::provided_init_features(&config), 486_4000 - ), get_channel_details( - Some(122), nodes[0], channelmanager::provided_init_features(&config), 179_5000 - )]; + let first_hops = vec![ + get_channel_details( + Some(161), + nodes[0], + channelmanager::provided_init_features(&config), + 486_4000, + ), + get_channel_details( + Some(122), + nodes[0], + channelmanager::provided_init_features(&config), + 179_5000, + ), + ]; let base_fees = [0, 425_9840, 0, 0]; let htlc_mins = [1_4392, 19_7401, 1027, 6_5535]; @@ -8323,35 +10586,41 @@ mod tests { } let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); PaymentParameters::blinded(blinded_hints.clone()) - .with_bolt12_features(bolt12_features.clone()).unwrap() + .with_bolt12_features(bolt12_features.clone()) + .unwrap() } else { let mut route_hints = Vec::new(); for (idx, (base_fee, htlc_min)) in base_fees.iter().zip(htlc_mins.iter()).enumerate() { route_hints.push(RouteHint(vec![RouteHintHop { src_node_id: nodes[0], short_channel_id: 42 + idx as u64, - fees: RoutingFees { - base_msat: *base_fee, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: *base_fee, proportional_millionths: 0 }, cltv_expiry_delta: 10, htlc_minimum_msat: Some(*htlc_min), htlc_maximum_msat: Some(htlc_min * 100), }])); } PaymentParameters::from_node_id(nodes[1], 42) - .with_route_hints(route_hints).unwrap() - .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap() + .with_route_hints(route_hints) + .unwrap() + .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) + .unwrap() }; let netgraph = network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let route = get_route( - &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::>()), - Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes - ).unwrap(); + &our_id, + &route_params, + &netgraph, + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.get_total_amount(), amt_msat); } @@ -8367,7 +10636,11 @@ mod tests { let logger = Arc::new(ln_test_utils::TestLogger::new()); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger))); let gossip_sync = P2PGossipSync::new(network_graph.clone(), None, logger.clone()); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), network_graph.clone(), logger.clone()); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + network_graph.clone(), + logger.clone(), + ); let random_seed_bytes = [42; 32]; let config = UserConfig::default(); @@ -8375,50 +10648,79 @@ mod tests { let amt_msat = 7_4009_8048; let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx); let first_hops = vec![get_channel_details( - Some(200), nodes[0], channelmanager::provided_init_features(&config), 2_7345_2000 + Some(200), + nodes[0], + channelmanager::provided_init_features(&config), + 2_7345_2000, )]; - add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (6 << 4) | 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + &privkeys[6], + ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), + 6, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (6 << 4) | 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[0], + NodeFeatures::from_le_bytes(id_to_feature_flags(1)), + 0, + ); let htlc_min = 2_5165_8240; - let blinded_hints = vec![ - dummy_blinded_path(nodes[0], BlindedPayInfo { + let blinded_hints = vec![dummy_blinded_path( + nodes[0], + BlindedPayInfo { fee_base_msat: 1_6778_3453, fee_proportional_millionths: 0, htlc_minimum_msat: htlc_min, htlc_maximum_msat: htlc_min * 100, cltv_expiry_delta: 10, features: BlindedHopFeatures::empty(), - }) - ]; + }, + )]; let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); let payment_params = PaymentParameters::blinded(blinded_hints.clone()) - .with_bolt12_features(bolt12_features.clone()).unwrap(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + .with_bolt12_features(bolt12_features.clone()) + .unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let netgraph = network_graph.read_only(); if let Err(err) = get_route( - &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::>()), - Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), - &random_seed_bytes + &our_id, + &route_params, + &netgraph, + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &ProbabilisticScoringFeeParameters::default(), + &random_seed_bytes, ) { assert_eq!(err, "Failed to find a path to the given destination"); - } else { panic!() } + } else { + panic!() + } } #[test] @@ -8430,18 +10732,23 @@ mod tests { let secp_ctx = Secp256k1::new(); let logger = Arc::new(ln_test_utils::TestLogger::new()); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger))); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), network_graph.clone(), logger.clone()); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + network_graph.clone(), + logger.clone(), + ); let random_seed_bytes = [42; 32]; let config = UserConfig::default(); // Values are taken from the fuzz input that uncovered this panic. let amt_msat = 562_0000; let (_, our_id, _, nodes) = get_nodes(&secp_ctx); - let first_hops = vec![ - get_channel_details( - Some(83), nodes[0], channelmanager::provided_init_features(&config), 2199_0000, - ), - ]; + let first_hops = vec![get_channel_details( + Some(83), + nodes[0], + channelmanager::provided_init_features(&config), + 2199_0000, + )]; let htlc_mins = [49_0000, 1125_0000]; let payment_params = { @@ -8459,17 +10766,23 @@ mod tests { } let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); PaymentParameters::blinded(blinded_hints.clone()) - .with_bolt12_features(bolt12_features.clone()).unwrap() + .with_bolt12_features(bolt12_features.clone()) + .unwrap() }; let netgraph = network_graph.read_only(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let route = get_route( - &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::>()), - Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), - &random_seed_bytes - ).unwrap(); + &our_id, + &route_params, + &netgraph, + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &ProbabilisticScoringFeeParameters::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.get_total_amount(), amt_msat); } @@ -8489,104 +10802,145 @@ mod tests { let amt_msat = 1_000_000; let (our_privkey, our_node_id, privkeys, nodes) = get_nodes(&secp_ctx); - add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[0], - ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 42, - htlc_minimum_msat: 1_000, - htlc_maximum_msat: 10_000_000, - fee_base_msat: 800, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: 42, - htlc_minimum_msat: 1_000, - htlc_maximum_msat: 10_000_000, - fee_base_msat: 800, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + add_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + &privkeys[0], + ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), + 1, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 42, + htlc_minimum_msat: 1_000, + htlc_maximum_msat: 10_000_000, + fee_base_msat: 800, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: 42, + htlc_minimum_msat: 1_000, + htlc_maximum_msat: 10_000_000, + fee_base_msat: 800, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); - add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[1], - ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 2); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: 42, - htlc_minimum_msat: 1_000, - htlc_maximum_msat: 10_000_000, - fee_base_msat: 800, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 2, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: 42, - htlc_minimum_msat: 1_000, - htlc_maximum_msat: 10_000_000, - fee_base_msat: 800, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + &privkeys[1], + ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), + 2, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: 42, + htlc_minimum_msat: 1_000, + htlc_maximum_msat: 10_000_000, + fee_base_msat: 800, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 2, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: 42, + htlc_minimum_msat: 1_000, + htlc_maximum_msat: 10_000_000, + fee_base_msat: 800, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); let dest_node_id = nodes[2]; - let route_hint = RouteHint(vec![RouteHintHop { - src_node_id: our_node_id, - short_channel_id: 44, - fees: RoutingFees { - base_msat: 234, - proportional_millionths: 0, + let route_hint = RouteHint(vec![ + RouteHintHop { + src_node_id: our_node_id, + short_channel_id: 44, + fees: RoutingFees { base_msat: 234, proportional_millionths: 0 }, + cltv_expiry_delta: 10, + htlc_minimum_msat: None, + htlc_maximum_msat: Some(5_000_000), }, - cltv_expiry_delta: 10, - htlc_minimum_msat: None, - htlc_maximum_msat: Some(5_000_000), - }, - RouteHintHop { - src_node_id: nodes[0], - short_channel_id: 45, - fees: RoutingFees { - base_msat: 123, - proportional_millionths: 0, + RouteHintHop { + src_node_id: nodes[0], + short_channel_id: 45, + fees: RoutingFees { base_msat: 123, proportional_millionths: 0 }, + cltv_expiry_delta: 10, + htlc_minimum_msat: None, + htlc_maximum_msat: None, }, - cltv_expiry_delta: 10, - htlc_minimum_msat: None, - htlc_maximum_msat: None, - }]); + ]); let payment_params = PaymentParameters::from_node_id(dest_node_id, 42) - .with_route_hints(vec![route_hint]).unwrap() - .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap(); - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + .with_route_hints(vec![route_hint]) + .unwrap() + .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) + .unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); // First create an insufficient first hop for channel with SCID 1 and check we'd use the // route hint. - let first_hop = get_channel_details(Some(1), nodes[0], - channelmanager::provided_init_features(&config), 999_999); + let first_hop = get_channel_details( + Some(1), + nodes[0], + channelmanager::provided_init_features(&config), + 999_999, + ); let first_hops = vec![first_hop]; - let route = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_node_id, + &route_params.clone(), + &network_graph.read_only(), + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.get_total_amount(), amt_msat); assert_eq!(route.paths[0].hops.len(), 2); @@ -8596,25 +10950,49 @@ mod tests { // Now check we would trust our first hop info, i.e., fail if we detect the route hint is // for a first hop channel. - let mut first_hop = get_channel_details(Some(1), nodes[0], channelmanager::provided_init_features(&config), 999_999); + let mut first_hop = get_channel_details( + Some(1), + nodes[0], + channelmanager::provided_init_features(&config), + 999_999, + ); first_hop.outbound_scid_alias = Some(44); let first_hops = vec![first_hop]; - let route_res = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes); + let route_res = get_route( + &our_node_id, + &route_params.clone(), + &network_graph.read_only(), + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ); assert!(route_res.is_err()); // Finally check we'd use the first hop if has sufficient outbound capacity. But we'd stil // use the cheaper second hop of the route hint. - let mut first_hop = get_channel_details(Some(1), nodes[0], - channelmanager::provided_init_features(&config), 10_000_000); + let mut first_hop = get_channel_details( + Some(1), + nodes[0], + channelmanager::provided_init_features(&config), + 10_000_000, + ); first_hop.outbound_scid_alias = Some(44); let first_hops = vec![first_hop]; - let route = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_node_id, + &route_params.clone(), + &network_graph.read_only(), + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.get_total_amount(), amt_msat); assert_eq!(route.paths[0].hops.len(), 2); @@ -8638,32 +11016,42 @@ mod tests { let amt_msat = 1_000_000; let dest_node_id = nodes[1]; - let first_hop = get_channel_details(Some(1), nodes[0], channelmanager::provided_init_features(&config), 10_000_000); + let first_hop = get_channel_details( + Some(1), + nodes[0], + channelmanager::provided_init_features(&config), + 10_000_000, + ); let first_hops = vec![first_hop]; let route_hint = RouteHint(vec![RouteHintHop { src_node_id: our_node_id, short_channel_id: 44, - fees: RoutingFees { - base_msat: 123, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 123, proportional_millionths: 0 }, cltv_expiry_delta: 10, htlc_minimum_msat: None, htlc_maximum_msat: None, }]); let payment_params = PaymentParameters::from_node_id(dest_node_id, 42) - .with_route_hints(vec![route_hint]).unwrap() - .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap(); - - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, amt_msat); + .with_route_hints(vec![route_hint]) + .unwrap() + .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)) + .unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); - let route = get_route(&our_node_id, &route_params, &network_graph.read_only(), - Some(&first_hops.iter().collect::>()), Arc::clone(&logger), &scorer, - &Default::default(), &random_seed_bytes).unwrap(); + let route = get_route( + &our_node_id, + &route_params, + &network_graph.read_only(), + Some(&first_hops.iter().collect::>()), + Arc::clone(&logger), + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.get_total_amount(), amt_msat); @@ -8677,26 +11065,27 @@ mod tests { #[cfg(any(test, ldk_bench))] pub(crate) mod bench_utils { use super::*; - use std::fs::File; - use std::io::Read; use bitcoin::hashes::Hash; use bitcoin::secp256k1::SecretKey; + use std::fs::File; + use std::io::Read; use crate::chain::transaction::OutPoint; - use crate::routing::scoring::{ProbabilisticScorer, ScoreUpdate}; use crate::ln::channel_state::{ChannelCounterparty, ChannelShutdownState}; use crate::ln::channelmanager; use crate::ln::types::ChannelId; + use crate::routing::scoring::{ProbabilisticScorer, ScoreUpdate}; + use crate::sync::Arc; use crate::util::config::UserConfig; use crate::util::test_utils::TestLogger; - use crate::sync::Arc; /// Tries to open a network graph file, or panics with a URL to fetch it. pub(crate) fn get_graph_scorer_file() -> Result<(std::fs::File, std::fs::File), &'static str> { let load_file = |fname, err_str| { File::open(fname) // By default we're run in RL/lightning .or_else(|_| File::open(&format!("lightning/{}", fname))) // We may be run manually in RL/ - .or_else(|_| { // Fall back to guessing based on the binary location + .or_else(|_| { + // Fall back to guessing based on the binary location // path is likely something like .../rust-lightning/target/debug/deps/lightning-... let mut path = std::env::current_exe().unwrap(); path.pop(); // lightning-... @@ -8707,7 +11096,8 @@ pub(crate) mod bench_utils { path.push(fname); File::open(path) }) - .or_else(|_| { // Fall back to guessing based on the binary location for a subcrate + .or_else(|_| { + // Fall back to guessing based on the binary location for a subcrate // path is likely something like .../rust-lightning/bench/target/debug/deps/bench.. let mut path = std::env::current_exe().unwrap(); path.pop(); // bench... @@ -8719,7 +11109,7 @@ pub(crate) mod bench_utils { path.push(fname); File::open(path) }) - .map_err(|_| err_str) + .map_err(|_| err_str) }; let graph_res = load_file( "net_graph-2023-12-10.bin", @@ -8735,8 +11125,15 @@ pub(crate) mod bench_utils { return Ok((graph_res?, scorer_res?)); } - pub(crate) fn read_graph_scorer(logger: &TestLogger) - -> Result<(Arc>, ProbabilisticScorer>, &TestLogger>), &'static str> { + pub(crate) fn read_graph_scorer( + logger: &TestLogger, + ) -> Result< + ( + Arc>, + ProbabilisticScorer>, &TestLogger>, + ), + &'static str, + > { let (mut graph_file, mut scorer_file) = get_graph_scorer_file()?; let mut graph_buffer = Vec::new(); let mut scorer_buffer = Vec::new(); @@ -8767,7 +11164,8 @@ pub(crate) mod bench_utils { outbound_htlc_maximum_msat: None, }, funding_txo: Some(OutPoint { - txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 + txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), + index: 0, }), channel_type: None, short_channel_id: Some(1), @@ -8797,9 +11195,9 @@ pub(crate) mod bench_utils { } } - pub(crate) fn generate_test_routes(graph: &NetworkGraph<&TestLogger>, scorer: &mut S, - score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, mut seed: u64, - starting_amount: u64, route_count: usize, + pub(crate) fn generate_test_routes( + graph: &NetworkGraph<&TestLogger>, scorer: &mut S, score_params: &S::ScoreParams, + features: Bolt11InvoiceFeatures, mut seed: u64, starting_amount: u64, route_count: usize, ) -> Vec<(ChannelDetails, PaymentParameters, u64)> { let payer = payer_pubkey(); let random_seed_bytes = [42; 32]; @@ -8809,20 +11207,43 @@ pub(crate) mod bench_utils { for _ in 0..route_count { loop { seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0; - let src = PublicKey::from_slice(nodes.unordered_keys() - .skip((seed as usize) % nodes.len()).next().unwrap().as_slice()).unwrap(); + let src = PublicKey::from_slice( + nodes + .unordered_keys() + .skip((seed as usize) % nodes.len()) + .next() + .unwrap() + .as_slice(), + ) + .unwrap(); seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0; - let dst = PublicKey::from_slice(nodes.unordered_keys() - .skip((seed as usize) % nodes.len()).next().unwrap().as_slice()).unwrap(); + let dst = PublicKey::from_slice( + nodes + .unordered_keys() + .skip((seed as usize) % nodes.len()) + .next() + .unwrap() + .as_slice(), + ) + .unwrap(); let params = PaymentParameters::from_node_id(dst, 42) - .with_bolt11_features(features.clone()).unwrap(); + .with_bolt11_features(features.clone()) + .unwrap(); let first_hop = first_hop(src); let amt_msat = starting_amount + seed % 1_000_000; - let route_params = RouteParameters::from_payment_params_and_value( - params.clone(), amt_msat); - let path_exists = - get_route(&payer, &route_params, &graph.read_only(), Some(&[&first_hop]), - &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok(); + let route_params = + RouteParameters::from_payment_params_and_value(params.clone(), amt_msat); + let path_exists = get_route( + &payer, + &route_params, + &graph.read_only(), + Some(&[&first_hop]), + &TestLogger::new(), + scorer, + score_params, + &random_seed_bytes, + ) + .is_ok(); if path_exists { route_endpoints.push((first_hop, params, amt_msat)); break; @@ -8837,11 +11258,11 @@ pub(crate) mod bench_utils { #[cfg(ldk_bench)] pub mod benches { use super::*; - use crate::routing::scoring::{ScoreUpdate, ScoreLookUp}; use crate::ln::channelmanager; - use crate::types::features::Bolt11InvoiceFeatures; use crate::routing::gossip::NetworkGraph; use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScoringFeeParameters}; + use crate::routing::scoring::{ScoreLookUp, ScoreUpdate}; + use crate::types::features::Bolt11InvoiceFeatures; use crate::util::config::UserConfig; use crate::util::logger::{Logger, Record}; use crate::util::test_utils::TestLogger; @@ -8857,43 +11278,75 @@ pub mod benches { let logger = TestLogger::new(); let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap(); let scorer = FixedPenaltyScorer::with_penalty(0); - generate_routes(bench, &network_graph, scorer, &Default::default(), - Bolt11InvoiceFeatures::empty(), 0, "generate_routes_with_zero_penalty_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + &Default::default(), + Bolt11InvoiceFeatures::empty(), + 0, + "generate_routes_with_zero_penalty_scorer", + ); } pub fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Criterion) { let logger = TestLogger::new(); let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap(); let scorer = FixedPenaltyScorer::with_penalty(0); - generate_routes(bench, &network_graph, scorer, &Default::default(), - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, - "generate_mpp_routes_with_zero_penalty_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + &Default::default(), + channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), + 0, + "generate_mpp_routes_with_zero_penalty_scorer", + ); } pub fn generate_routes_with_probabilistic_scorer(bench: &mut Criterion) { let logger = TestLogger::new(); let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap(); let params = ProbabilisticScoringFeeParameters::default(); - generate_routes(bench, &network_graph, scorer, ¶ms, Bolt11InvoiceFeatures::empty(), 0, - "generate_routes_with_probabilistic_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + ¶ms, + Bolt11InvoiceFeatures::empty(), + 0, + "generate_routes_with_probabilistic_scorer", + ); } pub fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Criterion) { let logger = TestLogger::new(); let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap(); let params = ProbabilisticScoringFeeParameters::default(); - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, - "generate_mpp_routes_with_probabilistic_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + ¶ms, + channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), + 0, + "generate_mpp_routes_with_probabilistic_scorer", + ); } pub fn generate_large_mpp_routes_with_probabilistic_scorer(bench: &mut Criterion) { let logger = TestLogger::new(); let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap(); let params = ProbabilisticScoringFeeParameters::default(); - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 100_000_000, - "generate_large_mpp_routes_with_probabilistic_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + ¶ms, + channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), + 100_000_000, + "generate_large_mpp_routes_with_probabilistic_scorer", + ); } pub fn generate_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) { @@ -8901,9 +11354,15 @@ pub mod benches { let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap(); let mut params = ProbabilisticScoringFeeParameters::default(); params.linear_success_probability = false; - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, - "generate_routes_with_nonlinear_probabilistic_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + ¶ms, + channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), + 0, + "generate_routes_with_nonlinear_probabilistic_scorer", + ); } pub fn generate_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) { @@ -8911,9 +11370,15 @@ pub mod benches { let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap(); let mut params = ProbabilisticScoringFeeParameters::default(); params.linear_success_probability = false; - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, - "generate_mpp_routes_with_nonlinear_probabilistic_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + ¶ms, + channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), + 0, + "generate_mpp_routes_with_nonlinear_probabilistic_scorer", + ); } pub fn generate_large_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) { @@ -8921,9 +11386,15 @@ pub mod benches { let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap(); let mut params = ProbabilisticScoringFeeParameters::default(); params.linear_success_probability = false; - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 100_000_000, - "generate_large_mpp_routes_with_nonlinear_probabilistic_scorer"); + generate_routes( + bench, + &network_graph, + scorer, + ¶ms, + channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), + 100_000_000, + "generate_large_mpp_routes_with_nonlinear_probabilistic_scorer", + ); } fn generate_routes( @@ -8932,7 +11403,15 @@ pub mod benches { bench_name: &'static str, ) { // First, get 100 (source, destination) pairs for which route-getting actually succeeds... - let route_endpoints = bench_utils::generate_test_routes(graph, &mut scorer, score_params, features, 0xdeadbeef, starting_amount, 50); + let route_endpoints = bench_utils::generate_test_routes( + graph, + &mut scorer, + score_params, + features, + 0xdeadbeef, + starting_amount, + 50, + ); // ...then benchmark finding paths between the nodes we learned. do_route_bench(bench, graph, scorer, score_params, bench_name, route_endpoints); @@ -8948,12 +11427,24 @@ pub mod benches { let random_seed_bytes = [42; 32]; let mut idx = 0; - bench.bench_function(bench_name, |b| b.iter(|| { - let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()]; - let route_params = RouteParameters::from_payment_params_and_value(params.clone(), *amt); - assert!(get_route(&payer, &route_params, &graph.read_only(), Some(&[first_hop]), - &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok()); - idx += 1; - })); + bench.bench_function(bench_name, |b| { + b.iter(|| { + let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()]; + let route_params = + RouteParameters::from_payment_params_and_value(params.clone(), *amt); + assert!(get_route( + &payer, + &route_params, + &graph.read_only(), + Some(&[first_hop]), + &DummyLogger {}, + &scorer, + score_params, + &random_seed_bytes + ) + .is_ok()); + idx += 1; + }) + }); } } diff --git a/lightning/src/routing/scoring.rs b/lightning/src/routing/scoring.rs index 6403889df6d..a185d018a92 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -51,24 +51,27 @@ //! //! [`find_route`]: crate::routing::router::find_route +use crate::io::{self, Read}; use crate::ln::msgs::DecodeError; +use crate::prelude::hash_map::Entry; +use crate::prelude::*; use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, NetworkGraph, NodeId}; -use crate::routing::router::{Path, CandidateRouteHop, PublicHopCandidate}; use crate::routing::log_approx; -use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; +use crate::routing::router::{CandidateRouteHop, Path, PublicHopCandidate}; +use crate::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::util::logger::Logger; -use crate::prelude::*; -use crate::prelude::hash_map::Entry; -use core::{cmp, fmt, mem}; +use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; +use bucketed_history::{ + DirectedHistoricalLiquidityTracker, HistoricalBucketRangeTracker, HistoricalLiquidityTracker, + LegacyHistoricalBucketRangeTracker, +}; use core::ops::{Deref, DerefMut}; use core::time::Duration; -use crate::io::{self, Read}; -use crate::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; -use bucketed_history::{LegacyHistoricalBucketRangeTracker, HistoricalBucketRangeTracker, DirectedHistoricalLiquidityTracker, HistoricalLiquidityTracker}; +use core::{cmp, fmt, mem}; #[cfg(not(c_bindings))] use { - core::cell::{RefCell, RefMut, Ref}, crate::sync::{Mutex, MutexGuard}, + core::cell::{Ref, RefCell, RefMut}, }; /// We define Score ever-so-slightly differently based on whether we are being built for C bindings @@ -324,7 +327,8 @@ impl<'a, T: 'a + Score> Deref for MultiThreadedScoreLockRead<'a, T> { #[cfg(c_bindings)] impl<'a, T: Score> ScoreLookUp for MultiThreadedScoreLockRead<'a, T> { type ScoreParams = T::ScoreParams; - fn channel_penalty_msat(&self, candidate:&CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams + fn channel_penalty_msat( + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams, ) -> u64 { self.0.channel_penalty_msat(candidate, usage, score_params) } @@ -355,7 +359,9 @@ impl<'a, T: 'a + Score> DerefMut for MultiThreadedScoreLockWrite<'a, T> { #[cfg(c_bindings)] impl<'a, T: Score> ScoreUpdate for MultiThreadedScoreLockWrite<'a, T> { - fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) { + fn payment_path_failed( + &mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration, + ) { self.0.payment_path_failed(path, short_channel_id, duration_since_epoch) } @@ -376,7 +382,6 @@ impl<'a, T: Score> ScoreUpdate for MultiThreadedScoreLockWrite<'a, T> { } } - /// Proposed use of a channel passed as a parameter to [`ScoreLookUp::channel_penalty_msat`]. #[derive(Clone, Copy, Debug, PartialEq)] pub struct ChannelUsage { @@ -406,17 +411,25 @@ impl FixedPenaltyScorer { impl ScoreLookUp for FixedPenaltyScorer { type ScoreParams = (); - fn channel_penalty_msat(&self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 { + fn channel_penalty_msat( + &self, _: &CandidateRouteHop, _: ChannelUsage, _score_params: &Self::ScoreParams, + ) -> u64 { self.penalty_msat } } impl ScoreUpdate for FixedPenaltyScorer { - fn payment_path_failed(&mut self, _path: &Path, _short_channel_id: u64, _duration_since_epoch: Duration) {} + fn payment_path_failed( + &mut self, _path: &Path, _short_channel_id: u64, _duration_since_epoch: Duration, + ) { + } fn payment_path_successful(&mut self, _path: &Path, _duration_since_epoch: Duration) {} - fn probe_failed(&mut self, _path: &Path, _short_channel_id: u64, _duration_since_epoch: Duration) {} + fn probe_failed( + &mut self, _path: &Path, _short_channel_id: u64, _duration_since_epoch: Duration, + ) { + } fn probe_successful(&mut self, _path: &Path, _duration_since_epoch: Duration) {} @@ -471,7 +484,9 @@ impl ReadableArgs for FixedPenaltyScorer { /// [`historical_liquidity_penalty_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_multiplier_msat /// [`historical_liquidity_penalty_amount_multiplier_msat`]: ProbabilisticScoringFeeParameters::historical_liquidity_penalty_amount_multiplier_msat pub struct ProbabilisticScorer>, L: Deref> -where L::Target: Logger { +where + L::Target: Logger, +{ decay_params: ProbabilisticScoringDecayParameters, network_graph: G, logger: L, @@ -489,12 +504,21 @@ impl ChannelLiquidities { Self(new_hash_map()) } - fn time_passed(&mut self, duration_since_epoch: Duration, decay_params: ProbabilisticScoringDecayParameters) { + fn time_passed( + &mut self, duration_since_epoch: Duration, + decay_params: ProbabilisticScoringDecayParameters, + ) { self.0.retain(|_scid, liquidity| { - liquidity.min_liquidity_offset_msat = - liquidity.decayed_offset(liquidity.min_liquidity_offset_msat, duration_since_epoch, decay_params); - liquidity.max_liquidity_offset_msat = - liquidity.decayed_offset(liquidity.max_liquidity_offset_msat, duration_since_epoch, decay_params); + liquidity.min_liquidity_offset_msat = liquidity.decayed_offset( + liquidity.min_liquidity_offset_msat, + duration_since_epoch, + decay_params, + ); + liquidity.max_liquidity_offset_msat = liquidity.decayed_offset( + liquidity.max_liquidity_offset_msat, + duration_since_epoch, + decay_params, + ); liquidity.last_updated = duration_since_epoch; // Only decay the historical buckets if there hasn't been new data for a while. This ties back to our @@ -509,12 +533,15 @@ impl ChannelLiquidities { if elapsed_time > decay_params.historical_no_updates_half_life { let half_life = decay_params.historical_no_updates_half_life.as_secs_f64(); if half_life != 0.0 { - liquidity.liquidity_history.decay_buckets(elapsed_time.as_secs_f64() / half_life); + liquidity + .liquidity_history + .decay_buckets(elapsed_time.as_secs_f64() / half_life); liquidity.offset_history_last_updated = duration_since_epoch; } } - liquidity.min_liquidity_offset_msat != 0 || liquidity.max_liquidity_offset_msat != 0 || - liquidity.liquidity_history.has_datapoints() + liquidity.min_liquidity_offset_msat != 0 + || liquidity.max_liquidity_offset_msat != 0 + || liquidity.liquidity_history.has_datapoints() }); } @@ -522,7 +549,9 @@ impl ChannelLiquidities { self.0.get(short_channel_id) } - fn insert(&mut self, short_channel_id: u64, liquidity: ChannelLiquidity) -> Option { + fn insert( + &mut self, short_channel_id: u64, liquidity: ChannelLiquidity, + ) -> Option { self.0.insert(short_channel_id, liquidity) } @@ -936,7 +965,11 @@ struct ChannelLiquidity { } /// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity. -struct DirectedChannelLiquidity, HT: Deref, T: Deref> { +struct DirectedChannelLiquidity< + L: Deref, + HT: Deref, + T: Deref, +> { min_liquidity_offset_msat: L, max_liquidity_offset_msat: L, liquidity_history: DirectedHistoricalLiquidityTracker, @@ -946,10 +979,15 @@ struct DirectedChannelLiquidity, HT: Deref>, L: Deref> ProbabilisticScorer where L::Target: Logger { +impl>, L: Deref> ProbabilisticScorer +where + L::Target: Logger, +{ /// Creates a new scorer using the given scoring parameters for sending payments from a node /// through a network graph. - pub fn new(decay_params: ProbabilisticScoringDecayParameters, network_graph: G, logger: L) -> Self { + pub fn new( + decay_params: ProbabilisticScoringDecayParameters, network_graph: G, logger: L, + ) -> Self { Self { decay_params, network_graph, @@ -978,8 +1016,10 @@ impl>, L: Deref> ProbabilisticScorer whe let amt = directed_info.effective_capacity().as_msat(); let dir_liq = liq.as_directed(source, target, amt); - let min_buckets = &dir_liq.liquidity_history.min_liquidity_offset_history_buckets(); - let max_buckets = &dir_liq.liquidity_history.max_liquidity_offset_history_buckets(); + let min_buckets = + &dir_liq.liquidity_history.min_liquidity_offset_history_buckets(); + let max_buckets = + &dir_liq.liquidity_history.max_liquidity_offset_history_buckets(); log_debug!(self.logger, core::concat!( "Liquidity from {} to {} via {} is in the range ({}, {}).\n", @@ -1007,7 +1047,13 @@ impl>, L: Deref> ProbabilisticScorer whe max_buckets[ 7], max_buckets[ 6], max_buckets[ 5], max_buckets[ 4], max_buckets[ 3], max_buckets[ 2], max_buckets[ 1], max_buckets[ 0]); } else { - log_debug!(self.logger, "No amount known for SCID {} from {:?} to {:?}", scid, source, target); + log_debug!( + self.logger, + "No amount known for SCID {} from {:?} to {:?}", + scid, + source, + target + ); } }; @@ -1021,7 +1067,9 @@ impl>, L: Deref> ProbabilisticScorer whe /// Query the estimated minimum and maximum liquidity available for sending a payment over the /// channel with `scid` towards the given `target` node. - pub fn estimated_channel_liquidity_range(&self, scid: u64, target: &NodeId) -> Option<(u64, u64)> { + pub fn estimated_channel_liquidity_range( + &self, scid: u64, target: &NodeId, + ) -> Option<(u64, u64)> { let graph = self.network_graph.read_only(); if let Some(chan) = graph.channels().get(&scid) { @@ -1062,8 +1110,9 @@ impl>, L: Deref> ProbabilisticScorer whe /// /// In order to fetch a single success probability from the buckets provided here, as used in /// the scoring model, see [`Self::historical_estimated_payment_success_probability`]. - pub fn historical_estimated_channel_liquidity_probabilities(&self, scid: u64, target: &NodeId) - -> Option<([u16; 32], [u16; 32])> { + pub fn historical_estimated_channel_liquidity_probabilities( + &self, scid: u64, target: &NodeId, + ) -> Option<([u16; 32], [u16; 32])> { let graph = self.network_graph.read_only(); if let Some(chan) = graph.channels().get(&scid) { @@ -1072,8 +1121,10 @@ impl>, L: Deref> ProbabilisticScorer whe let amt = directed_info.effective_capacity().as_msat(); let dir_liq = liq.as_directed(source, target, amt); - let min_buckets = *dir_liq.liquidity_history.min_liquidity_offset_history_buckets(); - let mut max_buckets = *dir_liq.liquidity_history.max_liquidity_offset_history_buckets(); + let min_buckets = + *dir_liq.liquidity_history.min_liquidity_offset_history_buckets(); + let mut max_buckets = + *dir_liq.liquidity_history.max_liquidity_offset_history_buckets(); // Note that the liquidity buckets are an offset from the edge, so we inverse // the max order to get the probabilities from zero. @@ -1099,8 +1150,8 @@ impl>, L: Deref> ProbabilisticScorer whe /// [`Self::historical_estimated_channel_liquidity_probabilities`] (but not those returned by /// [`Self::estimated_channel_liquidity_range`]). pub fn historical_estimated_payment_success_probability( - &self, scid: u64, target: &NodeId, amount_msat: u64, params: &ProbabilisticScoringFeeParameters, - allow_fallback_estimation: bool, + &self, scid: u64, target: &NodeId, amount_msat: u64, + params: &ProbabilisticScoringFeeParameters, allow_fallback_estimation: bool, ) -> Option { let graph = self.network_graph.read_only(); @@ -1110,18 +1161,29 @@ impl>, L: Deref> ProbabilisticScorer whe let capacity_msat = directed_info.effective_capacity().as_msat(); let dir_liq = liq.as_directed(source, target, capacity_msat); - let res = dir_liq.liquidity_history.calculate_success_probability_times_billion( - ¶ms, amount_msat, capacity_msat - ).map(|p| p as f64 / (1024 * 1024 * 1024) as f64); + let res = dir_liq + .liquidity_history + .calculate_success_probability_times_billion( + ¶ms, + amount_msat, + capacity_msat, + ) + .map(|p| p as f64 / (1024 * 1024 * 1024) as f64); if res.is_some() { return res; } } if allow_fallback_estimation { let amt = amount_msat; - return Some( - self.calc_live_prob(scid, source, target, directed_info, amt, params, true) - ); + return Some(self.calc_live_prob( + scid, + source, + target, + directed_info, + amt, + params, + true, + )); } } } @@ -1130,14 +1192,15 @@ impl>, L: Deref> ProbabilisticScorer whe fn calc_live_prob( &self, scid: u64, source: &NodeId, target: &NodeId, directed_info: DirectedChannelInfo, - amt: u64, params: &ProbabilisticScoringFeeParameters, - min_zero_penalty: bool, + amt: u64, params: &ProbabilisticScoringFeeParameters, min_zero_penalty: bool, ) -> f64 { let capacity_msat = directed_info.effective_capacity().as_msat(); let dummy_liq = ChannelLiquidity::new(Duration::ZERO); - let liq = self.channel_liquidities.get(&scid) - .unwrap_or(&dummy_liq) - .as_directed(&source, &target, capacity_msat); + let liq = self.channel_liquidities.get(&scid).unwrap_or(&dummy_liq).as_directed( + &source, + &target, + capacity_msat, + ); let min_liq = liq.min_liquidity_msat(); let max_liq = liq.max_liquidity_msat(); if amt <= liq.min_liquidity_msat() { @@ -1156,13 +1219,22 @@ impl>, L: Deref> ProbabilisticScorer whe /// This will return `Some` for any channel which is present in the [`NetworkGraph`], including /// if we have no bound information beside the channel's capacity. pub fn live_estimated_payment_success_probability( - &self, scid: u64, target: &NodeId, amount_msat: u64, params: &ProbabilisticScoringFeeParameters, + &self, scid: u64, target: &NodeId, amount_msat: u64, + params: &ProbabilisticScoringFeeParameters, ) -> Option { let graph = self.network_graph.read_only(); if let Some(chan) = graph.channels().get(&scid) { if let Some((directed_info, source)) = chan.as_directed_to(target) { - return Some(self.calc_live_prob(scid, source, target, directed_info, amount_msat, params, false)); + return Some(self.calc_live_prob( + scid, + source, + target, + directed_info, + amount_msat, + params, + false, + )); } } None @@ -1193,8 +1265,10 @@ impl ChannelLiquidity { fn merge(&mut self, other: &Self) { // Take average for min/max liquidity offsets. - self.min_liquidity_offset_msat = (self.min_liquidity_offset_msat + other.min_liquidity_offset_msat) / 2; - self.max_liquidity_offset_msat = (self.max_liquidity_offset_msat + other.max_liquidity_offset_msat) / 2; + self.min_liquidity_offset_msat = + (self.min_liquidity_offset_msat + other.min_liquidity_offset_msat) / 2; + self.max_liquidity_offset_msat = + (self.max_liquidity_offset_msat + other.max_liquidity_offset_msat) / 2; // Merge historical liquidity data. self.liquidity_history.merge(&other.liquidity_history); @@ -1206,12 +1280,11 @@ impl ChannelLiquidity { &self, source: &NodeId, target: &NodeId, capacity_msat: u64, ) -> DirectedChannelLiquidity<&u64, &HistoricalLiquidityTracker, &Duration> { let source_less_than_target = source < target; - let (min_liquidity_offset_msat, max_liquidity_offset_msat) = - if source_less_than_target { - (&self.min_liquidity_offset_msat, &self.max_liquidity_offset_msat) - } else { - (&self.max_liquidity_offset_msat, &self.min_liquidity_offset_msat) - }; + let (min_liquidity_offset_msat, max_liquidity_offset_msat) = if source_less_than_target { + (&self.min_liquidity_offset_msat, &self.max_liquidity_offset_msat) + } else { + (&self.max_liquidity_offset_msat, &self.min_liquidity_offset_msat) + }; DirectedChannelLiquidity { min_liquidity_offset_msat, @@ -1230,12 +1303,11 @@ impl ChannelLiquidity { &mut self, source: &NodeId, target: &NodeId, capacity_msat: u64, ) -> DirectedChannelLiquidity<&mut u64, &mut HistoricalLiquidityTracker, &mut Duration> { let source_less_than_target = source < target; - let (min_liquidity_offset_msat, max_liquidity_offset_msat) = - if source_less_than_target { - (&mut self.min_liquidity_offset_msat, &mut self.max_liquidity_offset_msat) - } else { - (&mut self.max_liquidity_offset_msat, &mut self.min_liquidity_offset_msat) - }; + let (min_liquidity_offset_msat, max_liquidity_offset_msat) = if source_less_than_target { + (&mut self.min_liquidity_offset_msat, &mut self.max_liquidity_offset_msat) + } else { + (&mut self.max_liquidity_offset_msat, &mut self.min_liquidity_offset_msat) + }; DirectedChannelLiquidity { min_liquidity_offset_msat, @@ -1299,12 +1371,14 @@ fn linear_success_probability( total_inflight_amount_msat: u64, min_liquidity_msat: u64, max_liquidity_msat: u64, min_zero_implies_no_successes: bool, ) -> (u64, u64) { - let (numerator, mut denominator) = - (max_liquidity_msat - total_inflight_amount_msat, - (max_liquidity_msat - min_liquidity_msat).saturating_add(1)); - - if min_zero_implies_no_successes && min_liquidity_msat == 0 && - denominator < u64::max_value() / MIN_ZERO_IMPLIES_NO_SUCCESSES_PENALTY_ON_64 + let (numerator, mut denominator) = ( + max_liquidity_msat - total_inflight_amount_msat, + (max_liquidity_msat - min_liquidity_msat).saturating_add(1), + ); + + if min_zero_implies_no_successes + && min_liquidity_msat == 0 + && denominator < u64::max_value() / MIN_ZERO_IMPLIES_NO_SUCCESSES_PENALTY_ON_64 { denominator = denominator * MIN_ZERO_IMPLIES_NO_SUCCESSES_PENALTY_ON_64 / 64 } @@ -1336,7 +1410,8 @@ fn nonlinear_success_probability( // multiple), as it will come out in the division of num / den. let (max_norm, min_norm, amt_norm) = (max - 0.5, min - 0.5, amount - 0.5); let (max_pow, min_pow, amt_pow) = three_f64_pow_9(max_norm, min_norm, amt_norm); - let (max_v, min_v, amt_v) = (max_pow + max_norm / 256.0, min_pow + min_norm / 256.0, amt_pow + amt_norm / 256.0); + let (max_v, min_v, amt_v) = + (max_pow + max_norm / 256.0, min_pow + min_norm / 256.0, amt_pow + amt_norm / 256.0); let mut denominator = max_v - min_v; let numerator = max_v - amt_v; @@ -1366,10 +1441,21 @@ fn success_probability_float( debug_assert!(max_liquidity_msat <= capacity_msat); if params.linear_success_probability { - let (numerator, denominator) = linear_success_probability(total_inflight_amount_msat, min_liquidity_msat, max_liquidity_msat, min_zero_implies_no_successes); + let (numerator, denominator) = linear_success_probability( + total_inflight_amount_msat, + min_liquidity_msat, + max_liquidity_msat, + min_zero_implies_no_successes, + ); (numerator as f64, denominator as f64) } else { - nonlinear_success_probability(total_inflight_amount_msat, min_liquidity_msat, max_liquidity_msat, capacity_msat, min_zero_implies_no_successes) + nonlinear_success_probability( + total_inflight_amount_msat, + min_liquidity_msat, + max_liquidity_msat, + capacity_msat, + min_zero_implies_no_successes, + ) } } @@ -1387,12 +1473,20 @@ fn success_probability( debug_assert!(max_liquidity_msat <= capacity_msat); if params.linear_success_probability { - linear_success_probability(total_inflight_amount_msat, min_liquidity_msat, max_liquidity_msat, min_zero_implies_no_successes) + linear_success_probability( + total_inflight_amount_msat, + min_liquidity_msat, + max_liquidity_msat, + min_zero_implies_no_successes, + ) } else { // We calculate the nonlinear probabilities using floats anyway, so just stub out to // the float version and then convert to integers. let (num, den) = nonlinear_success_probability( - total_inflight_amount_msat, min_liquidity_msat, max_liquidity_msat, capacity_msat, + total_inflight_amount_msat, + min_liquidity_msat, + max_liquidity_msat, + capacity_msat, min_zero_implies_no_successes, ); @@ -1401,14 +1495,28 @@ fn success_probability( const BILLIONISH: f64 = 1024.0 * 1024.0 * 1024.0 * 64.0; let numerator = (num * BILLIONISH) as u64 + 1; let denominator = (den * BILLIONISH) as u64 + 1; - debug_assert!(numerator <= 1 << 30, "Got large numerator ({}) from float {}.", numerator, num); - debug_assert!(denominator <= 1 << 30, "Got large denominator ({}) from float {}.", denominator, den); + debug_assert!( + numerator <= 1 << 30, + "Got large numerator ({}) from float {}.", + numerator, + num + ); + debug_assert!( + denominator <= 1 << 30, + "Got large denominator ({}) from float {}.", + denominator, + den + ); (numerator, denominator) } } -impl, HT: Deref, T: Deref> -DirectedChannelLiquidity< L, HT, T> { +impl< + L: Deref, + HT: Deref, + T: Deref, + > DirectedChannelLiquidity +{ /// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in /// this direction. fn penalty_msat( @@ -1421,8 +1529,9 @@ DirectedChannelLiquidity< L, HT, T> { let min_liquidity_msat = core::cmp::min(self.min_liquidity_msat(), max_liquidity_msat); let mut res = 0; - if score_params.liquidity_penalty_multiplier_msat != 0 || - score_params.liquidity_penalty_amount_multiplier_msat != 0 { + if score_params.liquidity_penalty_multiplier_msat != 0 + || score_params.liquidity_penalty_amount_multiplier_msat != 0 + { if total_inflight_amount_msat <= min_liquidity_msat { // If the in-flight is less than the minimum liquidity estimate, we don't assign a // liquidity penalty at all (as the success probability is 100%). @@ -1431,13 +1540,20 @@ DirectedChannelLiquidity< L, HT, T> { // capacity and without any certainty on the liquidity upper bound, plus the // impossibility penalty. let negative_log10_times_2048 = NEGATIVE_LOG10_UPPER_BOUND * 2048; - res = Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, - score_params.liquidity_penalty_multiplier_msat, - score_params.liquidity_penalty_amount_multiplier_msat); + res = Self::combined_penalty_msat( + amount_msat, + negative_log10_times_2048, + score_params.liquidity_penalty_multiplier_msat, + score_params.liquidity_penalty_amount_multiplier_msat, + ); } else { let (numerator, denominator) = success_probability( - total_inflight_amount_msat, min_liquidity_msat, max_liquidity_msat, - available_capacity, score_params, false, + total_inflight_amount_msat, + min_liquidity_msat, + max_liquidity_msat, + available_capacity, + score_params, + false, ); if denominator - numerator < denominator / PRECISION_LOWER_BOUND_DENOMINATOR { // If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64), @@ -1446,9 +1562,12 @@ DirectedChannelLiquidity< L, HT, T> { } else { let negative_log10_times_2048 = log_approx::negative_log10_times_2048(numerator, denominator); - res = Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, + res = Self::combined_penalty_msat( + amount_msat, + negative_log10_times_2048, score_params.liquidity_penalty_multiplier_msat, - score_params.liquidity_penalty_amount_multiplier_msat); + score_params.liquidity_penalty_amount_multiplier_msat, + ); } } } @@ -1459,38 +1578,54 @@ DirectedChannelLiquidity< L, HT, T> { if total_inflight_amount_msat >= available_capacity { // We're trying to send more than the capacity, use a max penalty. - res = res.saturating_add(Self::combined_penalty_msat(amount_msat, + res = res.saturating_add(Self::combined_penalty_msat( + amount_msat, NEGATIVE_LOG10_UPPER_BOUND * 2048, score_params.historical_liquidity_penalty_multiplier_msat, - score_params.historical_liquidity_penalty_amount_multiplier_msat)); + score_params.historical_liquidity_penalty_amount_multiplier_msat, + )); return res; } - if score_params.historical_liquidity_penalty_multiplier_msat != 0 || - score_params.historical_liquidity_penalty_amount_multiplier_msat != 0 { - if let Some(cumulative_success_prob_times_billion) = self.liquidity_history - .calculate_success_probability_times_billion( - score_params, total_inflight_amount_msat, self.capacity_msat - ) - { - let historical_negative_log10_times_2048 = - log_approx::negative_log10_times_2048(cumulative_success_prob_times_billion + 1, 1024 * 1024 * 1024); - res = res.saturating_add(Self::combined_penalty_msat(amount_msat, - historical_negative_log10_times_2048, score_params.historical_liquidity_penalty_multiplier_msat, - score_params.historical_liquidity_penalty_amount_multiplier_msat)); + if score_params.historical_liquidity_penalty_multiplier_msat != 0 + || score_params.historical_liquidity_penalty_amount_multiplier_msat != 0 + { + if let Some(cumulative_success_prob_times_billion) = + self.liquidity_history.calculate_success_probability_times_billion( + score_params, + total_inflight_amount_msat, + self.capacity_msat, + ) { + let historical_negative_log10_times_2048 = log_approx::negative_log10_times_2048( + cumulative_success_prob_times_billion + 1, + 1024 * 1024 * 1024, + ); + res = res.saturating_add(Self::combined_penalty_msat( + amount_msat, + historical_negative_log10_times_2048, + score_params.historical_liquidity_penalty_multiplier_msat, + score_params.historical_liquidity_penalty_amount_multiplier_msat, + )); } else { // If we don't have any valid points (or, once decayed, we have less than a full // point), redo the non-historical calculation with no liquidity bounds tracked and // the historical penalty multipliers. let (numerator, denominator) = success_probability( - total_inflight_amount_msat, 0, available_capacity, available_capacity, - score_params, true, + total_inflight_amount_msat, + 0, + available_capacity, + available_capacity, + score_params, + true, ); let negative_log10_times_2048 = log_approx::negative_log10_times_2048(numerator, denominator); - res = res.saturating_add(Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, + res = res.saturating_add(Self::combined_penalty_msat( + amount_msat, + negative_log10_times_2048, score_params.historical_liquidity_penalty_multiplier_msat, - score_params.historical_liquidity_penalty_amount_multiplier_msat)); + score_params.historical_liquidity_penalty_amount_multiplier_msat, + )); } } @@ -1511,18 +1646,20 @@ DirectedChannelLiquidity< L, HT, T> { /// Computes the liquidity penalty from the penalty multipliers. #[inline(always)] - fn combined_penalty_msat(amount_msat: u64, mut negative_log10_times_2048: u64, + fn combined_penalty_msat( + amount_msat: u64, mut negative_log10_times_2048: u64, liquidity_penalty_multiplier_msat: u64, liquidity_penalty_amount_multiplier_msat: u64, ) -> u64 { negative_log10_times_2048 = negative_log10_times_2048.min(NEGATIVE_LOG10_UPPER_BOUND * 2048); // Upper bound the liquidity penalty to ensure some channel is selected. - let liquidity_penalty_msat = negative_log10_times_2048 - .saturating_mul(liquidity_penalty_multiplier_msat) / 2048; + let liquidity_penalty_msat = + negative_log10_times_2048.saturating_mul(liquidity_penalty_multiplier_msat) / 2048; let amount_penalty_msat = negative_log10_times_2048 .saturating_mul(liquidity_penalty_amount_multiplier_msat) - .saturating_mul(amount_msat) / 2048 / AMOUNT_PENALTY_DIVISOR; + .saturating_mul(amount_msat) + / 2048 / AMOUNT_PENALTY_DIVISOR; liquidity_penalty_msat.saturating_add(amount_penalty_msat) } @@ -1536,24 +1673,41 @@ DirectedChannelLiquidity< L, HT, T> { /// Returns the upper bound of the channel liquidity balance in this direction. #[inline(always)] fn max_liquidity_msat(&self) -> u64 { - self.capacity_msat - .saturating_sub(*self.max_liquidity_offset_msat) + self.capacity_msat.saturating_sub(*self.max_liquidity_offset_msat) } } -impl, HT: DerefMut, T: DerefMut> -DirectedChannelLiquidity { +impl< + L: DerefMut, + HT: DerefMut, + T: DerefMut, + > DirectedChannelLiquidity +{ /// Adjusts the channel liquidity balance bounds when failing to route `amount_msat`. fn failed_at_channel( - &mut self, amount_msat: u64, duration_since_epoch: Duration, chan_descr: fmt::Arguments, logger: &Log - ) where Log::Target: Logger { + &mut self, amount_msat: u64, duration_since_epoch: Duration, chan_descr: fmt::Arguments, + logger: &Log, + ) where + Log::Target: Logger, + { let existing_max_msat = self.max_liquidity_msat(); if amount_msat < existing_max_msat { - log_debug!(logger, "Setting max liquidity of {} from {} to {}", chan_descr, existing_max_msat, amount_msat); + log_debug!( + logger, + "Setting max liquidity of {} from {} to {}", + chan_descr, + existing_max_msat, + amount_msat + ); self.set_max_liquidity_msat(amount_msat, duration_since_epoch); } else { - log_trace!(logger, "Max liquidity of {} is {} (already less than or equal to {})", - chan_descr, existing_max_msat, amount_msat); + log_trace!( + logger, + "Max liquidity of {} is {} (already less than or equal to {})", + chan_descr, + existing_max_msat, + amount_msat + ); } self.update_history_buckets(0, duration_since_epoch); *self.last_datapoint_time = duration_since_epoch; @@ -1561,26 +1715,49 @@ DirectedChannelLiquidity { /// Adjusts the channel liquidity balance bounds when failing to route `amount_msat` downstream. fn failed_downstream( - &mut self, amount_msat: u64, duration_since_epoch: Duration, chan_descr: fmt::Arguments, logger: &Log - ) where Log::Target: Logger { + &mut self, amount_msat: u64, duration_since_epoch: Duration, chan_descr: fmt::Arguments, + logger: &Log, + ) where + Log::Target: Logger, + { let existing_min_msat = self.min_liquidity_msat(); if amount_msat > existing_min_msat { - log_debug!(logger, "Setting min liquidity of {} from {} to {}", existing_min_msat, chan_descr, amount_msat); + log_debug!( + logger, + "Setting min liquidity of {} from {} to {}", + existing_min_msat, + chan_descr, + amount_msat + ); self.set_min_liquidity_msat(amount_msat, duration_since_epoch); } else { - log_trace!(logger, "Min liquidity of {} is {} (already greater than or equal to {})", - chan_descr, existing_min_msat, amount_msat); + log_trace!( + logger, + "Min liquidity of {} is {} (already greater than or equal to {})", + chan_descr, + existing_min_msat, + amount_msat + ); } self.update_history_buckets(0, duration_since_epoch); *self.last_datapoint_time = duration_since_epoch; } /// Adjusts the channel liquidity balance bounds when successfully routing `amount_msat`. - fn successful(&mut self, - amount_msat: u64, duration_since_epoch: Duration, chan_descr: fmt::Arguments, logger: &Log - ) where Log::Target: Logger { + fn successful( + &mut self, amount_msat: u64, duration_since_epoch: Duration, chan_descr: fmt::Arguments, + logger: &Log, + ) where + Log::Target: Logger, + { let max_liquidity_msat = self.max_liquidity_msat().checked_sub(amount_msat).unwrap_or(0); - log_debug!(logger, "Subtracting {} from max liquidity of {} (setting it to {})", amount_msat, chan_descr, max_liquidity_msat); + log_debug!( + logger, + "Subtracting {} from max liquidity of {} (setting it to {})", + amount_msat, + chan_descr, + max_liquidity_msat + ); self.set_max_liquidity_msat(max_liquidity_msat, duration_since_epoch); *self.last_datapoint_time = duration_since_epoch; self.update_history_buckets(amount_msat, duration_since_epoch); @@ -1618,10 +1795,14 @@ DirectedChannelLiquidity { } } -impl>, L: Deref> ScoreLookUp for ProbabilisticScorer where L::Target: Logger { +impl>, L: Deref> ScoreLookUp for ProbabilisticScorer +where + L::Target: Logger, +{ type ScoreParams = ProbabilisticScoringFeeParameters; fn channel_penalty_msat( - &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, + score_params: &ProbabilisticScoringFeeParameters, ) -> u64 { let (scid, target) = match candidate { CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id }) => { @@ -1635,14 +1816,14 @@ impl>, L: Deref> ScoreLookUp for Probabilistic } let base_penalty_msat = score_params.base_penalty_msat.saturating_add( - score_params.base_penalty_amount_multiplier_msat - .saturating_mul(usage.amount_msat) / BASE_AMOUNT_PENALTY_DIVISOR); + score_params.base_penalty_amount_multiplier_msat.saturating_mul(usage.amount_msat) + / BASE_AMOUNT_PENALTY_DIVISOR, + ); let mut anti_probing_penalty_msat = 0; match usage.effective_capacity { - EffectiveCapacity::ExactLiquidity { liquidity_msat: amount_msat } | - EffectiveCapacity::HintMaxHTLC { amount_msat } => - { + EffectiveCapacity::ExactLiquidity { liquidity_msat: amount_msat } + | EffectiveCapacity::HintMaxHTLC { amount_msat } => { if usage.amount_msat > amount_msat { return u64::max_value(); } else { @@ -1650,7 +1831,7 @@ impl>, L: Deref> ScoreLookUp for Probabilistic } }, EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat } => { - if htlc_maximum_msat >= capacity_msat/2 { + if htlc_maximum_msat >= capacity_msat / 2 { anti_probing_penalty_msat = score_params.anti_probing_penalty_msat; } }, @@ -1669,14 +1850,25 @@ impl>, L: Deref> ScoreLookUp for Probabilistic } } -impl>, L: Deref> ScoreUpdate for ProbabilisticScorer where L::Target: Logger { - fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) { +impl>, L: Deref> ScoreUpdate for ProbabilisticScorer +where + L::Target: Logger, +{ + fn payment_path_failed( + &mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration, + ) { let amount_msat = path.final_value_msat(); - log_trace!(self.logger, "Scoring path through to SCID {} as having failed at {} msat", short_channel_id, amount_msat); + log_trace!( + self.logger, + "Scoring path through to SCID {} as having failed at {} msat", + short_channel_id, + amount_msat + ); let network_graph = self.network_graph.read_only(); for (hop_idx, hop) in path.hops.iter().enumerate() { let target = NodeId::from_pubkey(&hop.pubkey); - let channel_directed_from_source = network_graph.channels() + let channel_directed_from_source = network_graph + .channels() .get(&hop.short_channel_id) .and_then(|channel| channel.as_directed_to(&target)); @@ -1693,33 +1885,48 @@ impl>, L: Deref> ScoreUpdate for Probabilistic .entry(hop.short_channel_id) .or_insert_with(|| ChannelLiquidity::new(duration_since_epoch)) .as_directed_mut(source, &target, capacity_msat) - .failed_at_channel(amount_msat, duration_since_epoch, - format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger); + .failed_at_channel( + amount_msat, + duration_since_epoch, + format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), + &self.logger, + ); } else { self.channel_liquidities .entry(hop.short_channel_id) .or_insert_with(|| ChannelLiquidity::new(duration_since_epoch)) .as_directed_mut(source, &target, capacity_msat) - .failed_downstream(amount_msat, duration_since_epoch, - format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger); + .failed_downstream( + amount_msat, + duration_since_epoch, + format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), + &self.logger, + ); } } else { log_debug!(self.logger, "Not able to penalize channel with SCID {} as we do not have graph info for it (likely a route-hint last-hop).", hop.short_channel_id); } - if at_failed_channel { break; } + if at_failed_channel { + break; + } } self.last_update_time = duration_since_epoch; } fn payment_path_successful(&mut self, path: &Path, duration_since_epoch: Duration) { let amount_msat = path.final_value_msat(); - log_trace!(self.logger, "Scoring path through SCID {} as having succeeded at {} msat.", - path.hops.split_last().map(|(hop, _)| hop.short_channel_id).unwrap_or(0), amount_msat); + log_trace!( + self.logger, + "Scoring path through SCID {} as having succeeded at {} msat.", + path.hops.split_last().map(|(hop, _)| hop.short_channel_id).unwrap_or(0), + amount_msat + ); let network_graph = self.network_graph.read_only(); for hop in &path.hops { let target = NodeId::from_pubkey(&hop.pubkey); - let channel_directed_from_source = network_graph.channels() + let channel_directed_from_source = network_graph + .channels() .get(&hop.short_channel_id) .and_then(|channel| channel.as_directed_to(&target)); @@ -1730,8 +1937,12 @@ impl>, L: Deref> ScoreUpdate for Probabilistic .entry(hop.short_channel_id) .or_insert_with(|| ChannelLiquidity::new(duration_since_epoch)) .as_directed_mut(source, &target, capacity_msat) - .successful(amount_msat, duration_since_epoch, - format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), &self.logger); + .successful( + amount_msat, + duration_since_epoch, + format_args!("SCID {}, towards {:?}", hop.short_channel_id, target), + &self.logger, + ); } else { log_debug!(self.logger, "Not able to learn for channel with SCID {} as we do not have graph info for it (likely a route-hint last-hop).", hop.short_channel_id); @@ -1765,12 +1976,18 @@ impl>, L: Deref> ScoreUpdate for Probabilistic /// /// Note that only the locally acquired data is persisted. After a restart, the external scores will be lost and must be /// resupplied. -pub struct CombinedScorer>, L: Deref> where L::Target: Logger { +pub struct CombinedScorer>, L: Deref> +where + L::Target: Logger, +{ local_only_scorer: ProbabilisticScorer, - scorer: ProbabilisticScorer, + scorer: ProbabilisticScorer, } -impl> + Clone, L: Deref + Clone> CombinedScorer where L::Target: Logger { +impl> + Clone, L: Deref + Clone> CombinedScorer +where + L::Target: Logger, +{ /// Create a new combined scorer with the given local scorer. pub fn new(local_scorer: ProbabilisticScorer) -> Self { let decay_params = local_scorer.decay_params; @@ -1780,14 +1997,13 @@ impl> + Clone, L: Deref + Clone> CombinedScore scorer.channel_liquidities = local_scorer.channel_liquidities.clone(); - Self { - local_only_scorer: local_scorer, - scorer: scorer, - } + Self { local_only_scorer: local_scorer, scorer } } /// Merge external channel liquidity information into the scorer. - pub fn merge(&mut self, mut external_scores: ChannelLiquidities, duration_since_epoch: Duration) { + pub fn merge( + &mut self, mut external_scores: ChannelLiquidities, duration_since_epoch: Duration, + ) { // Decay both sets of scores to make them comparable and mergeable. self.local_only_scorer.time_passed(duration_since_epoch); external_scores.time_passed(duration_since_epoch, self.local_only_scorer.decay_params); @@ -1809,52 +2025,66 @@ impl> + Clone, L: Deref + Clone> CombinedScore } } -impl>, L: Deref> ScoreLookUp for CombinedScorer where L::Target: Logger { +impl>, L: Deref> ScoreLookUp for CombinedScorer +where + L::Target: Logger, +{ type ScoreParams = ProbabilisticScoringFeeParameters; fn channel_penalty_msat( - &self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &ProbabilisticScoringFeeParameters + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, + score_params: &ProbabilisticScoringFeeParameters, ) -> u64 { self.scorer.channel_penalty_msat(candidate, usage, score_params) } } -impl>, L: Deref> ScoreUpdate for CombinedScorer where L::Target: Logger { - fn payment_path_failed(&mut self,path: &Path,short_channel_id:u64,duration_since_epoch:Duration) { +impl>, L: Deref> ScoreUpdate for CombinedScorer +where + L::Target: Logger, +{ + fn payment_path_failed( + &mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration, + ) { self.local_only_scorer.payment_path_failed(path, short_channel_id, duration_since_epoch); self.scorer.payment_path_failed(path, short_channel_id, duration_since_epoch); } - fn payment_path_successful(&mut self,path: &Path,duration_since_epoch:Duration) { + fn payment_path_successful(&mut self, path: &Path, duration_since_epoch: Duration) { self.local_only_scorer.payment_path_successful(path, duration_since_epoch); self.scorer.payment_path_successful(path, duration_since_epoch); } - fn probe_failed(&mut self,path: &Path,short_channel_id:u64,duration_since_epoch:Duration) { + fn probe_failed(&mut self, path: &Path, short_channel_id: u64, duration_since_epoch: Duration) { self.local_only_scorer.probe_failed(path, short_channel_id, duration_since_epoch); self.scorer.probe_failed(path, short_channel_id, duration_since_epoch); } - fn probe_successful(&mut self,path: &Path,duration_since_epoch:Duration) { + fn probe_successful(&mut self, path: &Path, duration_since_epoch: Duration) { self.local_only_scorer.probe_successful(path, duration_since_epoch); self.scorer.probe_successful(path, duration_since_epoch); } - fn time_passed(&mut self,duration_since_epoch:Duration) { + fn time_passed(&mut self, duration_since_epoch: Duration) { self.local_only_scorer.time_passed(duration_since_epoch); self.scorer.time_passed(duration_since_epoch); } } -impl>, L: Deref> Writeable for CombinedScorer where L::Target: Logger { +impl>, L: Deref> Writeable for CombinedScorer +where + L::Target: Logger, +{ fn write(&self, writer: &mut W) -> Result<(), crate::io::Error> { self.local_only_scorer.write(writer) } } #[cfg(c_bindings)] -impl>, L: Deref> Score for ProbabilisticScorer -where L::Target: Logger {} +impl>, L: Deref> Score for ProbabilisticScorer where + L::Target: Logger +{ +} #[cfg(feature = "std")] #[inline] @@ -1889,21 +2119,23 @@ mod bucketed_history { impl BucketStartPos { const fn new() -> Self { Self([ - 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 3072, 4096, 6144, 8192, 10240, 12288, - 13312, 14336, 15360, 15872, 16128, 16256, 16320, 16352, 16368, 16376, 16380, 16382, 16383, 16384, + 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 3072, 4096, 6144, 8192, + 10240, 12288, 13312, 14336, 15360, 15872, 16128, 16256, 16320, 16352, 16368, 16376, + 16380, 16382, 16383, 16384, ]) } } impl core::ops::Index for BucketStartPos { type Output = u16; #[inline(always)] - fn index(&self, index: usize) -> &u16 { &self.0[index] } + fn index(&self, index: usize) -> &u16 { + &self.0[index] + } } const BUCKET_START_POS: BucketStartPos = BucketStartPos::new(); - const LEGACY_TO_BUCKET_RANGE: [(u8, u8); 8] = [ - (0, 12), (12, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 20), (20, 32) - ]; + const LEGACY_TO_BUCKET_RANGE: [(u8, u8); 8] = + [(0, 12), (12, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 20), (20, 32)]; const POSITION_TICKS: u16 = 1 << 14; @@ -1921,8 +2153,9 @@ mod bucketed_history { #[test] fn check_bucket_maps() { const BUCKET_WIDTH_IN_16384S: [u16; 32] = [ - 1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 1024, 1024, 2048, 2048, - 2048, 2048, 1024, 1024, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 1]; + 1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 1024, 1024, 2048, 2048, 2048, 2048, + 1024, 1024, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 1, + ]; let mut min_size_iter = 0; let mut legacy_bucket_iter = 0; @@ -1935,7 +2168,10 @@ mod bucketed_history { if min_size_iter % (POSITION_TICKS / 8) == 0 { assert_eq!(LEGACY_TO_BUCKET_RANGE[legacy_bucket_iter].1 as usize, bucket + 1); if legacy_bucket_iter + 1 < 8 { - assert_eq!(LEGACY_TO_BUCKET_RANGE[legacy_bucket_iter + 1].0 as usize, bucket + 1); + assert_eq!( + LEGACY_TO_BUCKET_RANGE[legacy_bucket_iter + 1].0 as usize, + bucket + 1 + ); } legacy_bucket_iter += 1; } @@ -1948,14 +2184,16 @@ mod bucketed_history { fn amount_to_pos(amount_msat: u64, capacity_msat: u64) -> u16 { let pos = if amount_msat < u64::max_value() / (POSITION_TICKS as u64) { (amount_msat * (POSITION_TICKS as u64) / capacity_msat.saturating_add(1)) - .try_into().unwrap_or(POSITION_TICKS) + .try_into() + .unwrap_or(POSITION_TICKS) } else { // Only use 128-bit arithmetic when multiplication will overflow to avoid 128-bit // division. This branch should only be hit in fuzz testing since the amount would // need to be over 2.88 million BTC in practice. ((amount_msat as u128) * (POSITION_TICKS as u128) - / (capacity_msat as u128).saturating_add(1)) - .try_into().unwrap_or(POSITION_TICKS) + / (capacity_msat as u128).saturating_add(1)) + .try_into() + .unwrap_or(POSITION_TICKS) }; // If we are running in a client that doesn't validate gossip, its possible for a channel's // capacity to change due to a `channel_update` message which, if received while a payment @@ -1999,7 +2237,9 @@ mod bucketed_history { pub const BUCKET_FIXED_POINT_ONE: u16 = 32; impl HistoricalBucketRangeTracker { - pub(super) fn new() -> Self { Self { buckets: [0; 32] } } + pub(super) fn new() -> Self { + Self { buckets: [0; 32] } + } fn track_datapoint(&mut self, liquidity_offset_msat: u64, capacity_msat: u64) { // We have 32 leaky buckets for min and max liquidity. Each bucket tracks the amount of time // we spend in each bucket as a 16-bit fixed-point number with a 5 bit fractional part. @@ -2052,7 +2292,7 @@ mod bucketed_history { impl_writeable_tlv_based!(LegacyHistoricalBucketRangeTracker, { (0, buckets, required) }); #[derive(Clone, Copy)] - #[repr(C)]// Force the fields in memory to be in the order we specify. + #[repr(C)] // Force the fields in memory to be in the order we specify. pub(super) struct HistoricalLiquidityTracker { // This struct sits inside a `(u64, ChannelLiquidity)` in memory, and we first read the // liquidity offsets in `ChannelLiquidity` when calculating the non-historical score. This @@ -2095,8 +2335,8 @@ mod bucketed_history { } pub(super) fn has_datapoints(&self) -> bool { - self.min_liquidity_offset_history.buckets != [0; 32] || - self.max_liquidity_offset_history.buckets != [0; 32] + self.min_liquidity_offset_history.buckets != [0; 32] + || self.max_liquidity_offset_history.buckets != [0; 32] } pub(super) fn decay_buckets(&mut self, half_lives: f64) { @@ -2107,8 +2347,12 @@ mod bucketed_history { fn recalculate_valid_point_count(&mut self) { let mut total_valid_points_tracked = 0u128; - for (min_idx, min_bucket) in self.min_liquidity_offset_history.buckets.iter().enumerate() { - for max_bucket in self.max_liquidity_offset_history.buckets.iter().take(32 - min_idx) { + for (min_idx, min_bucket) in + self.min_liquidity_offset_history.buckets.iter().enumerate() + { + for max_bucket in + self.max_liquidity_offset_history.buckets.iter().take(32 - min_idx) + { // In testing, raising the weights of buckets to a high power led to better // scoring results. Thus, we raise the bucket weights to the 4th power here (by // squaring the result of multiplying the weights). This results in @@ -2130,13 +2374,15 @@ mod bucketed_history { &self.max_liquidity_offset_history } - pub(super) fn as_directed<'a>(&'a self, source_less_than_target: bool) - -> DirectedHistoricalLiquidityTracker<&'a HistoricalLiquidityTracker> { + pub(super) fn as_directed<'a>( + &'a self, source_less_than_target: bool, + ) -> DirectedHistoricalLiquidityTracker<&'a HistoricalLiquidityTracker> { DirectedHistoricalLiquidityTracker { source_less_than_target, tracker: self } } - pub(super) fn as_directed_mut<'a>(&'a mut self, source_less_than_target: bool) - -> DirectedHistoricalLiquidityTracker<&'a mut HistoricalLiquidityTracker> { + pub(super) fn as_directed_mut<'a>( + &'a mut self, source_less_than_target: bool, + ) -> DirectedHistoricalLiquidityTracker<&'a mut HistoricalLiquidityTracker> { DirectedHistoricalLiquidityTracker { source_less_than_target, tracker: self } } @@ -2150,7 +2396,9 @@ mod bucketed_history { /// A set of buckets representing the history of where we've seen the minimum- and maximum- /// liquidity bounds for a given channel. - pub(super) struct DirectedHistoricalLiquidityTracker> { + pub(super) struct DirectedHistoricalLiquidityTracker< + D: Deref, + > { source_less_than_target: bool, tracker: D, } @@ -2160,11 +2408,19 @@ mod bucketed_history { &mut self, min_offset_msat: u64, max_offset_msat: u64, capacity_msat: u64, ) { if self.source_less_than_target { - self.tracker.min_liquidity_offset_history.track_datapoint(min_offset_msat, capacity_msat); - self.tracker.max_liquidity_offset_history.track_datapoint(max_offset_msat, capacity_msat); + self.tracker + .min_liquidity_offset_history + .track_datapoint(min_offset_msat, capacity_msat); + self.tracker + .max_liquidity_offset_history + .track_datapoint(max_offset_msat, capacity_msat); } else { - self.tracker.max_liquidity_offset_history.track_datapoint(min_offset_msat, capacity_msat); - self.tracker.min_liquidity_offset_history.track_datapoint(max_offset_msat, capacity_msat); + self.tracker + .max_liquidity_offset_history + .track_datapoint(min_offset_msat, capacity_msat); + self.tracker + .min_liquidity_offset_history + .track_datapoint(max_offset_msat, capacity_msat); } self.tracker.recalculate_valid_point_count(); } @@ -2190,7 +2446,7 @@ mod bucketed_history { #[inline] pub(super) fn calculate_success_probability_times_billion( &self, params: &ProbabilisticScoringFeeParameters, total_inflight_amount_msat: u64, - capacity_msat: u64 + capacity_msat: u64, ) -> Option { // If historical penalties are enabled, we try to calculate a probability of success // given our historical distribution of min- and max-liquidity bounds in a channel. @@ -2200,18 +2456,21 @@ mod bucketed_history { // min- and max- liquidity bounds were our current liquidity bounds and then multiply // that probability by the weight of the selected buckets. let payment_pos = amount_to_pos(total_inflight_amount_msat, capacity_msat); - if payment_pos >= POSITION_TICKS { return None; } + if payment_pos >= POSITION_TICKS { + return None; + } - let min_liquidity_offset_history_buckets = - self.min_liquidity_offset_history_buckets(); - let max_liquidity_offset_history_buckets = - self.max_liquidity_offset_history_buckets(); + let min_liquidity_offset_history_buckets = self.min_liquidity_offset_history_buckets(); + let max_liquidity_offset_history_buckets = self.max_liquidity_offset_history_buckets(); let total_valid_points_tracked = self.tracker.total_valid_points_tracked; - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let mut actual_valid_points_tracked = 0u128; - for (min_idx, min_bucket) in min_liquidity_offset_history_buckets.iter().enumerate() { - for max_bucket in max_liquidity_offset_history_buckets.iter().take(32 - min_idx) { + for (min_idx, min_bucket) in min_liquidity_offset_history_buckets.iter().enumerate() + { + for max_bucket in max_liquidity_offset_history_buckets.iter().take(32 - min_idx) + { let mut bucket_weight = (*min_bucket as u64) * (*max_bucket as u64); bucket_weight *= bucket_weight; actual_valid_points_tracked += bucket_weight as u128; @@ -2222,8 +2481,10 @@ mod bucketed_history { // If the total valid points is smaller than 1.0 (i.e. 32 in our fixed-point scheme), // treat it as if we were fully decayed. - const FULLY_DECAYED: f64 = BUCKET_FIXED_POINT_ONE as f64 * BUCKET_FIXED_POINT_ONE as f64 * - BUCKET_FIXED_POINT_ONE as f64 * BUCKET_FIXED_POINT_ONE as f64; + const FULLY_DECAYED: f64 = BUCKET_FIXED_POINT_ONE as f64 + * BUCKET_FIXED_POINT_ONE as f64 + * BUCKET_FIXED_POINT_ONE as f64 + * BUCKET_FIXED_POINT_ONE as f64; if total_valid_points_tracked < FULLY_DECAYED.into() { return None; } @@ -2242,18 +2503,24 @@ mod bucketed_history { let mut highest_max_bucket_with_points = 0; let mut highest_max_bucket_with_full_points = None; let mut total_weight = 0u128; - for (max_idx, max_bucket) in max_liquidity_offset_history_buckets.iter().enumerate() { + for (max_idx, max_bucket) in max_liquidity_offset_history_buckets.iter().enumerate() + { if *max_bucket >= BUCKET_FIXED_POINT_ONE { - highest_max_bucket_with_full_points = Some(cmp::max(highest_max_bucket_with_full_points.unwrap_or(0), max_idx)); + highest_max_bucket_with_full_points = Some(cmp::max( + highest_max_bucket_with_full_points.unwrap_or(0), + max_idx, + )); } if *max_bucket != 0 { - highest_max_bucket_with_points = cmp::max(highest_max_bucket_with_points, max_idx); + highest_max_bucket_with_points = + cmp::max(highest_max_bucket_with_points, max_idx); } // In testing, raising the weights of buckets to a high power led to better // scoring results. Thus, we raise the bucket weights to the 4th power here (by // squaring the result of multiplying the weights), matching the logic in // `recalculate_valid_point_count`. - let bucket_weight = (*max_bucket as u64) * (min_liquidity_offset_history_buckets[0] as u64); + let bucket_weight = + (*max_bucket as u64) * (min_liquidity_offset_history_buckets[0] as u64); total_weight += (bucket_weight * bucket_weight) as u128; } debug_assert!(total_weight as f64 <= total_valid_points_tracked); @@ -2262,19 +2529,30 @@ mod bucketed_history { // if we have substantially decayed data we don't end up thinking the highest // max-bucket is zero even though we have no points in the 0th max-bucket and do // have points elsewhere. - let selected_max = highest_max_bucket_with_full_points.unwrap_or(highest_max_bucket_with_points); + let selected_max = + highest_max_bucket_with_full_points.unwrap_or(highest_max_bucket_with_points); let max_bucket_end_pos = BUCKET_START_POS[32 - selected_max] - 1; if payment_pos < max_bucket_end_pos { - let (numerator, denominator) = success_probability_float(payment_pos as u64, 0, - max_bucket_end_pos as u64, POSITION_TICKS as u64 - 1, params, true); + let (numerator, denominator) = success_probability_float( + payment_pos as u64, + 0, + max_bucket_end_pos as u64, + POSITION_TICKS as u64 - 1, + params, + true, + ); let bucket_prob = total_weight as f64 / total_valid_points_tracked; cumulative_success_prob += bucket_prob * numerator / denominator; } } - for (min_idx, min_bucket) in min_liquidity_offset_history_buckets.iter().enumerate().skip(1) { + for (min_idx, min_bucket) in + min_liquidity_offset_history_buckets.iter().enumerate().skip(1) + { let min_bucket_start_pos = BUCKET_START_POS[min_idx]; - for (max_idx, max_bucket) in max_liquidity_offset_history_buckets.iter().enumerate().take(32 - min_idx) { + for (max_idx, max_bucket) in + max_liquidity_offset_history_buckets.iter().enumerate().take(32 - min_idx) + { let max_bucket_end_pos = BUCKET_START_POS[32 - max_idx] - 1; if payment_pos >= max_bucket_end_pos { // Success probability 0, the payment amount may be above the max liquidity @@ -2293,9 +2571,14 @@ mod bucketed_history { if payment_pos < min_bucket_start_pos { cumulative_success_prob += bucket_prob; } else { - let (numerator, denominator) = success_probability_float(payment_pos as u64, - min_bucket_start_pos as u64, max_bucket_end_pos as u64, - POSITION_TICKS as u64 - 1, params, true); + let (numerator, denominator) = success_probability_float( + payment_pos as u64, + min_bucket_start_pos as u64, + max_bucket_end_pos as u64, + POSITION_TICKS as u64 - 1, + params, + true, + ); cumulative_success_prob += bucket_prob * numerator / denominator; } } @@ -2414,7 +2697,10 @@ mod bucketed_history { } } -impl>, L: Deref> Writeable for ProbabilisticScorer where L::Target: Logger { +impl>, L: Deref> Writeable for ProbabilisticScorer +where + L::Target: Logger, +{ #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { self.channel_liquidities.write(w) @@ -2422,10 +2708,13 @@ impl>, L: Deref> Writeable for ProbabilisticSc } impl>, L: Deref> -ReadableArgs<(ProbabilisticScoringDecayParameters, G, L)> for ProbabilisticScorer where L::Target: Logger { + ReadableArgs<(ProbabilisticScoringDecayParameters, G, L)> for ProbabilisticScorer +where + L::Target: Logger, +{ #[inline] fn read( - r: &mut R, args: (ProbabilisticScoringDecayParameters, G, L) + r: &mut R, args: (ProbabilisticScoringDecayParameters, G, L), ) -> Result { let (decay_params, network_graph, logger) = args; let channel_liquidities = ChannelLiquidities::read(r)?; @@ -2433,13 +2722,7 @@ ReadableArgs<(ProbabilisticScoringDecayParameters, G, L)> for ProbabilisticScore for (_, liq) in channel_liquidities.0.iter() { last_update_time = cmp::max(last_update_time, liq.last_updated); } - Ok(Self { - decay_params, - network_graph, - logger, - channel_liquidities, - last_update_time, - }) + Ok(Self { decay_params, network_graph, logger, channel_liquidities, last_update_time }) } } @@ -2503,7 +2786,8 @@ impl Readable for ChannelLiquidity { min_liquidity_offset_msat, max_liquidity_offset_msat, liquidity_history: HistoricalLiquidityTracker::from_min_max( - min_liquidity_offset_history.unwrap(), max_liquidity_offset_history.unwrap() + min_liquidity_offset_history.unwrap(), + max_liquidity_offset_history.unwrap(), ), last_updated, offset_history_last_updated: offset_history_last_updated.unwrap_or(last_updated), @@ -2514,26 +2798,35 @@ impl Readable for ChannelLiquidity { #[cfg(test)] mod tests { - use super::{ChannelLiquidity, HistoricalLiquidityTracker, ProbabilisticScorer, ProbabilisticScoringDecayParameters, ProbabilisticScoringFeeParameters}; + use super::{ + ChannelLiquidity, HistoricalLiquidityTracker, ProbabilisticScorer, + ProbabilisticScoringDecayParameters, ProbabilisticScoringFeeParameters, + }; use crate::blinded_path::BlindedHop; use crate::util::config::UserConfig; use crate::ln::channelmanager; - use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, UnsignedChannelAnnouncement, UnsignedChannelUpdate}; + use crate::ln::msgs::{ + ChannelAnnouncement, ChannelUpdate, UnsignedChannelAnnouncement, UnsignedChannelUpdate, + }; use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId}; - use crate::routing::router::{BlindedTail, Path, RouteHop, CandidateRouteHop, PublicHopCandidate}; - use crate::routing::scoring::{ChannelLiquidities, ChannelUsage, CombinedScorer, ScoreLookUp, ScoreUpdate}; + use crate::routing::router::{ + BlindedTail, CandidateRouteHop, Path, PublicHopCandidate, RouteHop, + }; + use crate::routing::scoring::{ + ChannelLiquidities, ChannelUsage, CombinedScorer, ScoreLookUp, ScoreUpdate, + }; use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_utils::{self, TestLogger}; + use crate::io; use bitcoin::constants::ChainHash; - use bitcoin::hashes::Hash; use bitcoin::hashes::sha256d::Hash as Sha256dHash; + use bitcoin::hashes::Hash; use bitcoin::network::Network; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use core::time::Duration; use std::rc::Rc; - use crate::io; fn source_privkey() -> SecretKey { SecretKey::from_slice(&[42; 32]).unwrap() @@ -2594,8 +2887,8 @@ mod tests { } fn add_channel( - network_graph: &mut NetworkGraph<&TestLogger>, short_channel_id: u64, node_1_key: SecretKey, - node_2_key: SecretKey + network_graph: &mut NetworkGraph<&TestLogger>, short_channel_id: u64, + node_1_key: SecretKey, node_2_key: SecretKey, ) { let genesis_hash = ChainHash::using_genesis_block(Network::Testnet); let node_1_secret = &SecretKey::from_slice(&[39; 32]).unwrap(); @@ -2607,8 +2900,14 @@ mod tests { short_channel_id, node_id_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_1_key)), node_id_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_2_key)), - bitcoin_key_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_1_secret)), - bitcoin_key_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, &node_2_secret)), + bitcoin_key_1: NodeId::from_pubkey(&PublicKey::from_secret_key( + &secp_ctx, + &node_1_secret, + )), + bitcoin_key_2: NodeId::from_pubkey(&PublicKey::from_secret_key( + &secp_ctx, + &node_2_secret, + )), excess_data: Vec::new(), }; let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); @@ -2620,8 +2919,9 @@ mod tests { contents: unsigned_announcement, }; let chain_source: Option<&crate::util::test_utils::TestChainSource> = None; - network_graph.update_channel_from_announcement( - &signed_announcement, &chain_source).unwrap(); + network_graph + .update_channel_from_announcement(&signed_announcement, &chain_source) + .unwrap(); update_channel(network_graph, short_channel_id, node_1_key, 0, 1_000, 100); update_channel(network_graph, short_channel_id, node_2_key, 1, 0, 100); } @@ -2672,7 +2972,8 @@ mod tests { path_hop(source_pubkey(), 41, 1), path_hop(target_pubkey(), 42, 2), path_hop(recipient_pubkey(), 43, amount_msat), - ], blinded_tail: None, + ], + blinded_tail: None, } } @@ -2685,18 +2986,28 @@ mod tests { let network_graph = network_graph(&logger); let decay_params = ProbabilisticScoringDecayParameters::default(); let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger) - .with_channel(42, + .with_channel( + 42, ChannelLiquidity { - min_liquidity_offset_msat: 700, max_liquidity_offset_msat: 100, - last_updated, offset_history_last_updated, last_datapoint_time, + min_liquidity_offset_msat: 700, + max_liquidity_offset_msat: 100, + last_updated, + offset_history_last_updated, + last_datapoint_time, liquidity_history: HistoricalLiquidityTracker::new(), - }) - .with_channel(43, + }, + ) + .with_channel( + 43, ChannelLiquidity { - min_liquidity_offset_msat: 700, max_liquidity_offset_msat: 100, - last_updated, offset_history_last_updated, last_datapoint_time, + min_liquidity_offset_msat: 700, + max_liquidity_offset_msat: 100, + last_updated, + offset_history_last_updated, + last_datapoint_time, liquidity_history: HistoricalLiquidityTracker::new(), - }); + }, + ); let source = source_node_id(); let target = target_node_id(); let recipient = recipient_node_id(); @@ -2705,53 +3016,59 @@ mod tests { // Update minimum liquidity. - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 100); assert_eq!(liquidity.max_liquidity_msat(), 300); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 700); assert_eq!(liquidity.max_liquidity_msat(), 900); - scorer.channel_liquidities.get_mut(&42).unwrap() + scorer + .channel_liquidities + .get_mut(&42) + .unwrap() .as_directed_mut(&source, &target, 1_000) .set_min_liquidity_msat(200, Duration::ZERO); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 200); assert_eq!(liquidity.max_liquidity_msat(), 300); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 700); assert_eq!(liquidity.max_liquidity_msat(), 800); // Update maximum liquidity. - let liquidity = scorer.channel_liquidities.get(&43).unwrap() - .as_directed(&target, &recipient, 1_000); + let liquidity = + scorer.channel_liquidities.get(&43).unwrap().as_directed(&target, &recipient, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 700); assert_eq!(liquidity.max_liquidity_msat(), 900); - let liquidity = scorer.channel_liquidities.get(&43).unwrap() - .as_directed(&recipient, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&43).unwrap().as_directed(&recipient, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 100); assert_eq!(liquidity.max_liquidity_msat(), 300); - scorer.channel_liquidities.get_mut(&43).unwrap() + scorer + .channel_liquidities + .get_mut(&43) + .unwrap() .as_directed_mut(&target, &recipient, 1_000) .set_max_liquidity_msat(200, Duration::ZERO); - let liquidity = scorer.channel_liquidities.get(&43).unwrap() - .as_directed(&target, &recipient, 1_000); + let liquidity = + scorer.channel_liquidities.get(&43).unwrap().as_directed(&target, &recipient, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 0); assert_eq!(liquidity.max_liquidity_msat(), 200); - let liquidity = scorer.channel_liquidities.get(&43).unwrap() - .as_directed(&recipient, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&43).unwrap().as_directed(&recipient, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 800); assert_eq!(liquidity.max_liquidity_msat(), 1000); } @@ -2765,54 +3082,65 @@ mod tests { let network_graph = network_graph(&logger); let decay_params = ProbabilisticScoringDecayParameters::default(); let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger) - .with_channel(42, + .with_channel( + 42, ChannelLiquidity { - min_liquidity_offset_msat: 200, max_liquidity_offset_msat: 400, - last_updated, offset_history_last_updated, last_datapoint_time, + min_liquidity_offset_msat: 200, + max_liquidity_offset_msat: 400, + last_updated, + offset_history_last_updated, + last_datapoint_time, liquidity_history: HistoricalLiquidityTracker::new(), - }); + }, + ); let source = source_node_id(); let target = target_node_id(); assert!(source > target); // Check initial bounds. - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 400); assert_eq!(liquidity.max_liquidity_msat(), 800); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 200); assert_eq!(liquidity.max_liquidity_msat(), 600); // Reset from source to target. - scorer.channel_liquidities.get_mut(&42).unwrap() + scorer + .channel_liquidities + .get_mut(&42) + .unwrap() .as_directed_mut(&source, &target, 1_000) .set_min_liquidity_msat(900, Duration::ZERO); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 900); assert_eq!(liquidity.max_liquidity_msat(), 1_000); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 0); assert_eq!(liquidity.max_liquidity_msat(), 100); // Reset from target to source. - scorer.channel_liquidities.get_mut(&42).unwrap() + scorer + .channel_liquidities + .get_mut(&42) + .unwrap() .as_directed_mut(&target, &source, 1_000) .set_min_liquidity_msat(400, Duration::ZERO); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 0); assert_eq!(liquidity.max_liquidity_msat(), 600); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 400); assert_eq!(liquidity.max_liquidity_msat(), 1_000); } @@ -2826,54 +3154,65 @@ mod tests { let network_graph = network_graph(&logger); let decay_params = ProbabilisticScoringDecayParameters::default(); let mut scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger) - .with_channel(42, + .with_channel( + 42, ChannelLiquidity { - min_liquidity_offset_msat: 200, max_liquidity_offset_msat: 400, - last_updated, offset_history_last_updated, last_datapoint_time, + min_liquidity_offset_msat: 200, + max_liquidity_offset_msat: 400, + last_updated, + offset_history_last_updated, + last_datapoint_time, liquidity_history: HistoricalLiquidityTracker::new(), - }); + }, + ); let source = source_node_id(); let target = target_node_id(); assert!(source > target); // Check initial bounds. - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 400); assert_eq!(liquidity.max_liquidity_msat(), 800); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 200); assert_eq!(liquidity.max_liquidity_msat(), 600); // Reset from source to target. - scorer.channel_liquidities.get_mut(&42).unwrap() + scorer + .channel_liquidities + .get_mut(&42) + .unwrap() .as_directed_mut(&source, &target, 1_000) .set_max_liquidity_msat(300, Duration::ZERO); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 0); assert_eq!(liquidity.max_liquidity_msat(), 300); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 700); assert_eq!(liquidity.max_liquidity_msat(), 1_000); // Reset from target to source. - scorer.channel_liquidities.get_mut(&42).unwrap() + scorer + .channel_liquidities + .get_mut(&42) + .unwrap() .as_directed_mut(&target, &source, 1_000) .set_max_liquidity_msat(600, Duration::ZERO); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 400); assert_eq!(liquidity.max_liquidity_msat(), 1_000); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&target, &source, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&target, &source, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 0); assert_eq!(liquidity.max_liquidity_msat(), 600); } @@ -2893,15 +3232,16 @@ mod tests { let usage = ChannelUsage { amount_msat: 1_024, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024_000, + htlc_maximum_msat: 1_000, + }, }; let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); let usage = ChannelUsage { amount_msat: 10_240, ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); @@ -2913,7 +3253,10 @@ mod tests { let usage = ChannelUsage { amount_msat: 128, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_000, + }, }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 58); let usage = ChannelUsage { amount_msat: 256, ..usage }; @@ -2945,26 +3288,31 @@ mod tests { let decay_params = ProbabilisticScoringDecayParameters { ..ProbabilisticScoringDecayParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger) - .with_channel(42, - ChannelLiquidity { - min_liquidity_offset_msat: 40, max_liquidity_offset_msat: 40, - last_updated, offset_history_last_updated, last_datapoint_time, - liquidity_history: HistoricalLiquidityTracker::new(), - }); + let scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger).with_channel( + 42, + ChannelLiquidity { + min_liquidity_offset_msat: 40, + max_liquidity_offset_msat: 40, + last_updated, + offset_history_last_updated, + last_datapoint_time, + liquidity_history: HistoricalLiquidityTracker::new(), + }, + ); let source = source_node_id(); let usage = ChannelUsage { amount_msat: 39, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 100, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 100, + htlc_maximum_msat: 1_000, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); let usage = ChannelUsage { amount_msat: 50, ..usage }; assert_ne!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); @@ -2981,21 +3329,26 @@ mod tests { liquidity_penalty_multiplier_msat: 1_000, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let usage = ChannelUsage { amount_msat: 500, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; let failed_path = payment_path_for_amount(500); let successful_path = payment_path_for_amount(200); let channel = &network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 41, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 41 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 301); @@ -3014,21 +3367,26 @@ mod tests { liquidity_penalty_multiplier_msat: 1_000, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let path = payment_path_for_amount(500); let usage = ChannelUsage { amount_msat: 250, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); let usage = ChannelUsage { amount_msat: 500, ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 301); @@ -3054,21 +3412,26 @@ mod tests { considered_impossible_penalty_msat: u64::max_value(), ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let path = payment_path_for_amount(500); let usage = ChannelUsage { amount_msat: 250, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); let usage = ChannelUsage { amount_msat: 500, ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 301); @@ -3108,11 +3471,7 @@ mod tests { let pub_c = PublicKey::from_secret_key(&secp_ctx, &secret_c); let pub_d = PublicKey::from_secret_key(&secp_ctx, &secret_d); - let path = vec![ - path_hop(pub_b, 42, 1), - path_hop(pub_c, 43, 2), - path_hop(pub_d, 44, 100), - ]; + let path = vec![path_hop(pub_b, 42, 1), path_hop(pub_c, 43, 2), path_hop(pub_d, 44, 100)]; let node_a = NodeId::from_pubkey(&pub_a); let node_b = NodeId::from_pubkey(&pub_b); @@ -3122,59 +3481,54 @@ mod tests { liquidity_penalty_multiplier_msat: 1_000, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let usage = ChannelUsage { amount_msat: 250, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&node_a).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); // Note that a default liquidity bound is used for B -> C as no channel exists let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&node_b).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 43, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 43 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); let channel = network_graph.read_only().channel(44).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&node_c).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 44, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 44 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); scorer.payment_path_failed(&Path { hops: path, blinded_tail: None }, 43, Duration::ZERO); let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&node_a).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 80); // Note that a default liquidity bound is used for B -> C as no channel exists let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&node_b).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 43, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 43 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); let channel = network_graph.read_only().channel(44).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&node_c).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 44, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 44 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 128); } @@ -3186,31 +3540,32 @@ mod tests { liquidity_penalty_multiplier_msat: 1_000, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let usage = ChannelUsage { amount_msat: 250, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; let network_graph = network_graph.read_only().channels().clone(); let channel_42 = network_graph.get(&42).unwrap(); let channel_43 = network_graph.get(&43).unwrap(); let (info, _) = channel_42.as_directed_from(&source).unwrap(); - let candidate_41 = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 41, - }); + let candidate_41 = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 41 }); let (info, target) = channel_42.as_directed_from(&source).unwrap(); - let candidate_42 = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate_42 = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); let (info, _) = channel_43.as_directed_from(&target).unwrap(); - let candidate_43 = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 43, - }); + let candidate_43 = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 43 }); assert_eq!(scorer.channel_penalty_msat(&candidate_41, usage, ¶ms), 128); assert_eq!(scorer.channel_penalty_msat(&candidate_42, usage, ¶ms), 128); assert_eq!(scorer.channel_penalty_msat(&candidate_43, usage, ¶ms), 128); @@ -3241,14 +3596,15 @@ mod tests { let usage = ChannelUsage { amount_msat: 0, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_024, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); let usage = ChannelUsage { amount_msat: 1_023, ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2_000); @@ -3330,14 +3686,15 @@ mod tests { let usage = ChannelUsage { amount_msat: 512, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_000, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); @@ -3383,16 +3740,17 @@ mod tests { let usage = ChannelUsage { amount_msat: 500, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; scorer.payment_path_failed(&payment_path_for_amount(500), 42, Duration::ZERO); let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value()); scorer.time_passed(Duration::from_secs(10)); @@ -3405,8 +3763,11 @@ mod tests { scorer.write(&mut serialized_scorer).unwrap(); let mut serialized_scorer = io::Cursor::new(&serialized_scorer); - let deserialized_scorer = - >::read(&mut serialized_scorer, (decay_params, &network_graph, &logger)).unwrap(); + let deserialized_scorer = >::read( + &mut serialized_scorer, + (decay_params, &network_graph, &logger), + ) + .unwrap(); assert_eq!(deserialized_scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); } @@ -3427,16 +3788,17 @@ mod tests { let usage = ChannelUsage { amount_msat: 500, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; scorer.payment_path_failed(&payment_path_for_amount(500), 42, Duration::ZERO); let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value()); if decay_before_reload { @@ -3447,8 +3809,11 @@ mod tests { scorer.write(&mut serialized_scorer).unwrap(); let mut serialized_scorer = io::Cursor::new(&serialized_scorer); - let mut deserialized_scorer = - >::read(&mut serialized_scorer, (decay_params, &network_graph, &logger)).unwrap(); + let mut deserialized_scorer = >::read( + &mut serialized_scorer, + (decay_params, &network_graph, &logger), + ) + .unwrap(); if !decay_before_reload { scorer.time_passed(Duration::from_secs(10)); deserialized_scorer.time_passed(Duration::from_secs(10)); @@ -3475,59 +3840,104 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters::default(); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let usage = ChannelUsage { amount_msat: 100_000_000, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 950_000_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 950_000_000, + htlc_maximum_msat: 1_000, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 42_252); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 36_005); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 2_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 2_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 32_851); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 3_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 3_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 30_832); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 4_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 4_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 29_886); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 5_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 5_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 28_939); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 6_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 6_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 28_435); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 7_450_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 7_450_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 27_993); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 7_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 7_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 27_993); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 8_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 8_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 27_488); let usage = ChannelUsage { - effective_capacity: EffectiveCapacity::Total { capacity_msat: 9_950_000_000, htlc_maximum_msat: 1_000 }, ..usage + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 9_950_000_000, + htlc_maximum_msat: 1_000, + }, + ..usage }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 27_047); } @@ -3540,36 +3950,53 @@ mod tests { let usage = ChannelUsage { amount_msat: 128, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_000, + }, }; let params = ProbabilisticScoringFeeParameters { liquidity_penalty_multiplier_msat: 1_000, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 58); let params = ProbabilisticScoringFeeParameters { - base_penalty_msat: 500, liquidity_penalty_multiplier_msat: 1_000, - anti_probing_penalty_msat: 0, ..ProbabilisticScoringFeeParameters::zero_penalty() + base_penalty_msat: 500, + liquidity_penalty_multiplier_msat: 1_000, + anti_probing_penalty_msat: 0, + ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 558); let params = ProbabilisticScoringFeeParameters { - base_penalty_msat: 500, liquidity_penalty_multiplier_msat: 1_000, + base_penalty_msat: 500, + liquidity_penalty_multiplier_msat: 1_000, base_penalty_amount_multiplier_msat: (1 << 30), - anti_probing_penalty_msat: 0, ..ProbabilisticScoringFeeParameters::zero_penalty() + anti_probing_penalty_msat: 0, + ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 558 + 128); } @@ -3581,7 +4008,10 @@ mod tests { let usage = ChannelUsage { amount_msat: 512_000, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024_000, + htlc_maximum_msat: 1_000, + }, }; let params = ProbabilisticScoringFeeParameters { @@ -3589,13 +4019,15 @@ mod tests { liquidity_penalty_amount_multiplier_msat: 0, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); let params = ProbabilisticScoringFeeParameters { @@ -3603,7 +4035,11 @@ mod tests { liquidity_penalty_amount_multiplier_msat: 256, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 337); } @@ -3624,10 +4060,8 @@ mod tests { let decay_params = ProbabilisticScoringDecayParameters::zero_penalty(); let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); let scorer = ProbabilisticScorer::new(decay_params, &network_graph, &logger); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 80_000); } @@ -3640,21 +4074,26 @@ mod tests { considered_impossible_penalty_msat: u64::max_value(), ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let usage = ChannelUsage { amount_msat: 750, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_ne!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), u64::max_value()); let usage = ChannelUsage { inflight_htlc_msat: 251, ..usage }; @@ -3666,7 +4105,11 @@ mod tests { let logger = TestLogger::new(); let network_graph = network_graph(&logger); let params = ProbabilisticScoringFeeParameters::default(); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let base_penalty_msat = params.base_penalty_msat; @@ -3678,10 +4121,8 @@ mod tests { let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), base_penalty_msat); let usage = ChannelUsage { amount_msat: 1_000, ..usage }; @@ -3711,53 +4152,73 @@ mod tests { let usage = ChannelUsage { amount_msat: 100, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_024, + }, }; let usage_1 = ChannelUsage { amount_msat: 1, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_024, + }, }; { let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); // With no historical data the normal liquidity penalty calculation is used. assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 135); } - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - None); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms, false), - None); + assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); + assert_eq!( + scorer + .historical_estimated_payment_success_probability(42, &target, 42, ¶ms, false), + None + ); scorer.payment_path_failed(&payment_path_for_amount(1), 42, Duration::ZERO); { let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2048); assert_eq!(scorer.channel_penalty_msat(&candidate, usage_1, ¶ms), 220); } // The "it failed" increment is 32, where the probability should lie several buckets into // the first octile. - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - Some(([32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))); - assert!(scorer.historical_estimated_payment_success_probability(42, &target, 1, ¶ms, false) - .unwrap() > 0.35); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 500, ¶ms, false), - Some(0.0)); + assert_eq!( + scorer.historical_estimated_channel_liquidity_probabilities(42, &target), + Some(( + [ + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + [ + 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ] + )) + ); + assert!( + scorer + .historical_estimated_payment_success_probability(42, &target, 1, ¶ms, false) + .unwrap() > 0.35 + ); + assert_eq!( + scorer + .historical_estimated_payment_success_probability(42, &target, 500, ¶ms, false), + Some(0.0) + ); // Even after we tell the scorer we definitely have enough available liquidity, it will // still remember that there was some failure in the past, and assign a non-0 penalty. @@ -3766,26 +4227,36 @@ mod tests { let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 83); } // The first points should be decayed just slightly and the last bucket has a new point. - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - Some(([31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32]))); + assert_eq!( + scorer.historical_estimated_channel_liquidity_probabilities(42, &target), + Some(( + [ + 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 0, 0, 0, 0, 0 + ], + [ + 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32 + ] + )) + ); // The exact success probability is a bit complicated and involves integer rounding, so we // simply check bounds here. - let five_hundred_prob = - scorer.historical_estimated_payment_success_probability(42, &target, 500, ¶ms, false).unwrap(); + let five_hundred_prob = scorer + .historical_estimated_payment_success_probability(42, &target, 500, ¶ms, false) + .unwrap(); assert!(five_hundred_prob > 0.61, "{}", five_hundred_prob); assert!(five_hundred_prob < 0.62, "{}", five_hundred_prob); - let one_prob = - scorer.historical_estimated_payment_success_probability(42, &target, 1, ¶ms, false).unwrap(); + let one_prob = scorer + .historical_estimated_payment_success_probability(42, &target, 1, ¶ms, false) + .unwrap(); assert!(one_prob < 0.89, "{}", one_prob); assert!(one_prob > 0.88, "{}", one_prob); @@ -3796,33 +4267,37 @@ mod tests { let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 135); } // Once fully decayed we still have data, but its all-0s. In the future we may remove the // data entirely instead. - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - Some(([0; 32], [0; 32]))); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 1, ¶ms, false), None); + assert_eq!( + scorer.historical_estimated_channel_liquidity_probabilities(42, &target), + Some(([0; 32], [0; 32])) + ); + assert_eq!( + scorer.historical_estimated_payment_success_probability(42, &target, 1, ¶ms, false), + None + ); let usage = ChannelUsage { amount_msat: 100, inflight_htlc_msat: 1024, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_024, + }, }; scorer.payment_path_failed(&payment_path_for_amount(1), 42, Duration::from_secs(10 * 16)); { let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 2048); @@ -3839,8 +4314,7 @@ mod tests { // Once even the bounds have decayed information about the channel should be removed // entirely. - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - None); + assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); // Use a path in the opposite direction, which have zero for htlc_maximum_msat. This will // ensure that the effective capacity is zero to test division-by-zero edge cases. @@ -3849,7 +4323,11 @@ mod tests { path_hop(source_pubkey(), 42, 1), path_hop(sender_pubkey(), 41, 0), ]; - scorer.payment_path_failed(&Path { hops: path, blinded_tail: None }, 42, Duration::from_secs(10 * (16 + 60 * 60))); + scorer.payment_path_failed( + &Path { hops: path, blinded_tail: None }, + 42, + Duration::from_secs(10 * (16 + 60 * 60)), + ); } #[test] @@ -3861,28 +4339,36 @@ mod tests { anti_probing_penalty_msat: 500, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); // Check we receive no penalty for a low htlc_maximum_msat. let usage = ChannelUsage { amount_msat: 512_000, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024_000, + htlc_maximum_msat: 1_000, + }, }; let network_graph = network_graph.read_only(); let channel = network_graph.channel(42).unwrap(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); // Check we receive anti-probing penalty for htlc_maximum_msat == channel_capacity. let usage = ChannelUsage { amount_msat: 512_000, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_024_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024_000, + htlc_maximum_msat: 1_024_000, + }, }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 500); @@ -3890,7 +4376,10 @@ mod tests { let usage = ChannelUsage { amount_msat: 512_000, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 512_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024_000, + htlc_maximum_msat: 512_000, + }, }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 500); @@ -3898,7 +4387,10 @@ mod tests { let usage = ChannelUsage { amount_msat: 512_000, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 511_999 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024_000, + htlc_maximum_msat: 511_999, + }, }; assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 0); } @@ -3918,21 +4410,25 @@ mod tests { let usage = ChannelUsage { amount_msat: 512, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_000, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, target) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 300); let mut path = payment_path_for_amount(768); let recipient_hop = path.hops.pop().unwrap(); path.blinded_tail = Some(BlindedTail { trampoline_hops: vec![], - hops: vec![BlindedHop { blinded_node_id: test_utils::pubkey(44), encrypted_payload: Vec::new() }], + hops: vec![BlindedHop { + blinded_node_id: test_utils::pubkey(44), + encrypted_payload: Vec::new(), + }], blinding_point: test_utils::pubkey(42), excess_final_cltv_expiry_delta: recipient_hop.cltv_expiry_delta, final_value_msat: recipient_hop.fee_msat, @@ -3946,8 +4442,8 @@ mod tests { path.blinded_tail.as_mut().unwrap().final_value_msat = 256; scorer.payment_path_failed(&path, 43, Duration::ZERO); - let liquidity = scorer.channel_liquidities.get(&42).unwrap() - .as_directed(&source, &target, 1_000); + let liquidity = + scorer.channel_liquidities.get(&42).unwrap().as_directed(&source, &target, 1_000); assert_eq!(liquidity.min_liquidity_msat(), 256); assert_eq!(liquidity.max_liquidity_msat(), 768); } @@ -3981,53 +4477,102 @@ mod tests { let usage = ChannelUsage { amount_msat, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: capacity_msat }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat, + htlc_maximum_msat: capacity_msat, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, target) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); // With no historical data the normal liquidity penalty calculation is used, which results // in a success probability of ~82%. assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 910); - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - None); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms, false), - None); + assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); + assert_eq!( + scorer + .historical_estimated_payment_success_probability(42, &target, 42, ¶ms, false), + None + ); // Fail to pay once, and then check the buckets and penalty. scorer.payment_path_failed(&payment_path_for_amount(amount_msat), 42, Duration::ZERO); // The penalty should be the maximum penalty, as the payment we're scoring is now in the // same bucket which is the only maximum datapoint. - assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), - 2048 + 2048 * amount_msat / super::AMOUNT_PENALTY_DIVISOR); + assert_eq!( + scorer.channel_penalty_msat(&candidate, usage, ¶ms), + 2048 + 2048 * amount_msat / super::AMOUNT_PENALTY_DIVISOR + ); // The "it failed" increment is 32, which we should apply to the first upper-bound (between // 6k sats and 12k sats). - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - Some(([32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))); + assert_eq!( + scorer.historical_estimated_channel_liquidity_probabilities(42, &target), + Some(( + [ + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + [ + 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ] + )) + ); // The success probability estimate itself should be zero. - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, amount_msat, ¶ms, false), - Some(0.0)); + assert_eq!( + scorer.historical_estimated_payment_success_probability( + 42, + &target, + amount_msat, + ¶ms, + false + ), + Some(0.0) + ); // Now test again with the amount in the bottom bucket. amount_msat /= 2; // The new amount is entirely within the only minimum bucket with score, so the probability // we assign is 1/2. - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, amount_msat, ¶ms, false), - Some(0.5)); + assert_eq!( + scorer.historical_estimated_payment_success_probability( + 42, + &target, + amount_msat, + ¶ms, + false + ), + Some(0.5) + ); // ...but once we see a failure, we consider the payment to be substantially less likely, // even though not a probability of zero as we still look at the second max bucket which // now shows 31. scorer.payment_path_failed(&payment_path_for_amount(amount_msat), 42, Duration::ZERO); - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - Some(([63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [32, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, amount_msat, ¶ms, false), - Some(0.0)); + assert_eq!( + scorer.historical_estimated_channel_liquidity_probabilities(42, &target), + Some(( + [ + 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + [ + 32, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ] + )) + ); + assert_eq!( + scorer.historical_estimated_payment_success_probability( + 42, + &target, + amount_msat, + ¶ms, + false + ), + Some(0.0) + ); } #[test] @@ -4038,20 +4583,25 @@ mod tests { liquidity_penalty_multiplier_msat: 1_000, ..ProbabilisticScoringFeeParameters::zero_penalty() }; - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); let source = source_node_id(); let usage = ChannelUsage { amount_msat: 500, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_000, htlc_maximum_msat: 1_000 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_000, + htlc_maximum_msat: 1_000, + }, }; let successful_path = payment_path_for_amount(200); let channel = &network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 41, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 41 }); scorer.payment_path_successful(&successful_path, Duration::ZERO); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 301); @@ -4153,14 +4703,15 @@ mod tests { let usage = ChannelUsage { amount_msat: 512, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024, htlc_maximum_msat: 1_024 }, + effective_capacity: EffectiveCapacity::Total { + capacity_msat: 1_024, + htlc_maximum_msat: 1_024, + }, }; let channel = network_graph.read_only().channel(42).unwrap().to_owned(); let (info, _) = channel.as_directed_from(&source).unwrap(); - let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { - info, - short_channel_id: 42, - }); + let candidate = + CandidateRouteHop::PublicHop(PublicHopCandidate { info, short_channel_id: 42 }); // Initialize the state for channel 42 scorer.payment_path_failed(&payment_path_for_amount(500), 42, Duration::ZERO); @@ -4179,7 +4730,7 @@ mod tests { assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 999_953); // Once we've gotten halfway through the day our penalty is 1/4 the configured value. - scorer.time_passed(Duration::from_secs(86400/2 + 1)); + scorer.time_passed(Duration::from_secs(86400 / 2 + 1)); assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 250_000); } } @@ -4187,19 +4738,21 @@ mod tests { #[cfg(ldk_bench)] pub mod benches { use super::*; - use criterion::Criterion; use crate::routing::router::bench_utils; use crate::util::test_utils::TestLogger; + use criterion::Criterion; pub fn decay_100k_channel_bounds(bench: &mut Criterion) { let logger = TestLogger::new(); let (_, mut scorer) = bench_utils::read_graph_scorer(&logger).unwrap(); let mut cur_time = Duration::ZERO; - cur_time += Duration::from_millis(1); - scorer.time_passed(cur_time); - bench.bench_function("decay_100k_channel_bounds", |b| b.iter(|| { - cur_time += Duration::from_millis(1); - scorer.time_passed(cur_time); - })); + cur_time += Duration::from_millis(1); + scorer.time_passed(cur_time); + bench.bench_function("decay_100k_channel_bounds", |b| { + b.iter(|| { + cur_time += Duration::from_millis(1); + scorer.time_passed(cur_time); + }) + }); } } diff --git a/lightning/src/routing/test_utils.rs b/lightning/src/routing/test_utils.rs index 258652b575d..d2b6fcea430 100644 --- a/lightning/src/routing/test_utils.rs +++ b/lightning/src/routing/test_utils.rs @@ -7,19 +7,22 @@ // You may not use this file except in accordance with one or both of these // licenses. +use crate::ln::msgs::{ + ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, RoutingMessageHandler, SocketAddress, + UnsignedChannelAnnouncement, UnsignedChannelUpdate, UnsignedNodeAnnouncement, MAX_VALUE_MSAT, +}; use crate::routing::gossip::{NetworkGraph, NodeAlias, P2PGossipSync}; use crate::types::features::{ChannelFeatures, NodeFeatures}; -use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, MAX_VALUE_MSAT, NodeAnnouncement, RoutingMessageHandler, SocketAddress, UnsignedChannelAnnouncement, UnsignedChannelUpdate, UnsignedNodeAnnouncement}; -use crate::util::test_utils; use crate::util::ser::Writeable; +use crate::util::test_utils; use bitcoin::constants::ChainHash; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hashes::Hash; use bitcoin::hex::FromHex; use bitcoin::network::Network; -use bitcoin::secp256k1::{PublicKey,SecretKey}; -use bitcoin::secp256k1::{Secp256k1, All}; +use bitcoin::secp256k1::{All, Secp256k1}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; #[allow(unused)] use crate::prelude::*; @@ -57,21 +60,30 @@ pub(crate) fn channel_announcement( // Using the same keys for LN and BTC ids pub(crate) fn add_channel( - gossip_sync: &P2PGossipSync>>, Arc, Arc>, - secp_ctx: &Secp256k1, node_1_privkey: &SecretKey, node_2_privkey: &SecretKey, features: ChannelFeatures, short_channel_id: u64 + gossip_sync: &P2PGossipSync< + Arc>>, + Arc, + Arc, + >, + secp_ctx: &Secp256k1, node_1_privkey: &SecretKey, node_2_privkey: &SecretKey, + features: ChannelFeatures, short_channel_id: u64, ) { let valid_announcement = channel_announcement(node_1_privkey, node_2_privkey, features, short_channel_id, secp_ctx); let node_1_pubkey = PublicKey::from_secret_key(&secp_ctx, node_1_privkey); match gossip_sync.handle_channel_announcement(Some(node_1_pubkey), &valid_announcement) { Ok(res) => assert!(res), - _ => panic!() + _ => panic!(), }; } pub(crate) fn add_or_update_node( - gossip_sync: &P2PGossipSync>>, Arc, Arc>, - secp_ctx: &Secp256k1, node_privkey: &SecretKey, features: NodeFeatures, timestamp: u32 + gossip_sync: &P2PGossipSync< + Arc>>, + Arc, + Arc, + >, + secp_ctx: &Secp256k1, node_privkey: &SecretKey, features: NodeFeatures, timestamp: u32, ) { let node_pubkey = PublicKey::from_secret_key(&secp_ctx, node_privkey); let node_id = NodeId::from_pubkey(&node_pubkey); @@ -88,40 +100,47 @@ pub(crate) fn add_or_update_node( let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); let valid_announcement = NodeAnnouncement { signature: secp_ctx.sign_ecdsa(&msghash, node_privkey), - contents: unsigned_announcement.clone() + contents: unsigned_announcement.clone(), }; match gossip_sync.handle_node_announcement(Some(node_pubkey), &valid_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; } pub(crate) fn update_channel( - gossip_sync: &P2PGossipSync>>, Arc, Arc>, - secp_ctx: &Secp256k1, node_privkey: &SecretKey, update: UnsignedChannelUpdate + gossip_sync: &P2PGossipSync< + Arc>>, + Arc, + Arc, + >, + secp_ctx: &Secp256k1, node_privkey: &SecretKey, update: UnsignedChannelUpdate, ) { let node_pubkey = PublicKey::from_secret_key(&secp_ctx, node_privkey); let msghash = hash_to_message!(&Sha256dHash::hash(&update.encode()[..])[..]); let valid_channel_update = ChannelUpdate { signature: secp_ctx.sign_ecdsa(&msghash, node_privkey), - contents: update.clone() + contents: update.clone(), }; match gossip_sync.handle_channel_update(Some(node_pubkey), &valid_channel_update) { Ok(res) => assert!(res), - Err(_) => panic!() + Err(_) => panic!(), }; } -pub(super) fn get_nodes(secp_ctx: &Secp256k1) -> (SecretKey, PublicKey, Vec, Vec) { - let privkeys: Vec = (2..22).map(|i| { - SecretKey::from_slice(&[i; 32]).unwrap() - }).collect(); +pub(super) fn get_nodes( + secp_ctx: &Secp256k1, +) -> (SecretKey, PublicKey, Vec, Vec) { + let privkeys: Vec = + (2..22).map(|i| SecretKey::from_slice(&[i; 32]).unwrap()).collect(); - let pubkeys = privkeys.iter().map(|secret| PublicKey::from_secret_key(&secp_ctx, secret)).collect(); + let pubkeys = + privkeys.iter().map(|secret| PublicKey::from_secret_key(&secp_ctx, secret)).collect(); - let our_privkey = SecretKey::from_slice(&>::from_hex(&"01".repeat(32)).unwrap()[..]).unwrap(); + let our_privkey = + SecretKey::from_slice(&>::from_hex(&"01".repeat(32)).unwrap()[..]).unwrap(); let our_id = PublicKey::from_secret_key(&secp_ctx, &our_privkey); (our_privkey, our_id, privkeys, pubkeys) @@ -131,21 +150,27 @@ pub(super) fn id_to_feature_flags(id: u8) -> Vec { // Set the feature flags to the id'th odd (ie non-required) feature bit so that we can // test for it later. let idx = (id - 1) * 2 + 1; - if idx > 8*3 { - vec![1 << (idx - 8*3), 0, 0, 0] - } else if idx > 8*2 { - vec![1 << (idx - 8*2), 0, 0] - } else if idx > 8*1 { - vec![1 << (idx - 8*1), 0] + if idx > 8 * 3 { + vec![1 << (idx - 8 * 3), 0, 0, 0] + } else if idx > 8 * 2 { + vec![1 << (idx - 8 * 2), 0, 0] + } else if idx > 8 * 1 { + vec![1 << (idx - 8 * 1), 0] } else { vec![1 << idx] } } pub(super) fn build_line_graph() -> ( - Secp256k1, sync::Arc>>, - P2PGossipSync>>, sync::Arc, sync::Arc>, - sync::Arc, sync::Arc, + Secp256k1, + sync::Arc>>, + P2PGossipSync< + sync::Arc>>, + sync::Arc, + sync::Arc, + >, + sync::Arc, + sync::Arc, ) { let secp_ctx = Secp256k1::new(); let logger = Arc::new(test_utils::TestLogger::new()); @@ -157,12 +182,23 @@ pub(super) fn build_line_graph() -> ( // our_id -1(1)2- node0 -1(2)2- node1 - ... - node19 let (our_privkey, _, privkeys, _) = get_nodes(&secp_ctx); - for (idx, (cur_privkey, next_privkey)) in core::iter::once(&our_privkey) - .chain(privkeys.iter()).zip(privkeys.iter()).enumerate() { - let cur_short_channel_id = (idx as u64) + 1; - add_channel(&gossip_sync, &secp_ctx, &cur_privkey, &next_privkey, - ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), cur_short_channel_id); - update_channel(&gossip_sync, &secp_ctx, &cur_privkey, UnsignedChannelUpdate { + for (idx, (cur_privkey, next_privkey)) in + core::iter::once(&our_privkey).chain(privkeys.iter()).zip(privkeys.iter()).enumerate() + { + let cur_short_channel_id = (idx as u64) + 1; + add_channel( + &gossip_sync, + &secp_ctx, + &cur_privkey, + &next_privkey, + ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), + cur_short_channel_id, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &cur_privkey, + UnsignedChannelUpdate { chain_hash: ChainHash::using_genesis_block(Network::Testnet), short_channel_id: cur_short_channel_id, timestamp: idx as u32, @@ -173,12 +209,17 @@ pub(super) fn build_line_graph() -> ( htlc_maximum_msat: MAX_VALUE_MSAT, fee_base_msat: 0, fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &next_privkey, UnsignedChannelUpdate { + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &next_privkey, + UnsignedChannelUpdate { chain_hash: ChainHash::using_genesis_block(Network::Testnet), short_channel_id: cur_short_channel_id, - timestamp: (idx as u32)+1, + timestamp: (idx as u32) + 1, message_flags: 1, // Only must_be_one channel_flags: 1, cltv_expiry_delta: 0, @@ -186,11 +227,17 @@ pub(super) fn build_line_graph() -> ( htlc_maximum_msat: MAX_VALUE_MSAT, fee_base_msat: 0, fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - add_or_update_node(&gossip_sync, &secp_ctx, &next_privkey, - NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0); - } + excess_data: Vec::new(), + }, + ); + add_or_update_node( + &gossip_sync, + &secp_ctx, + &next_privkey, + NodeFeatures::from_le_bytes(id_to_feature_flags(1)), + 0, + ); + } (secp_ctx, network_graph, gossip_sync, chain_monitor, logger) } @@ -198,7 +245,11 @@ pub(super) fn build_line_graph() -> ( pub(super) fn build_graph() -> ( Secp256k1, sync::Arc>>, - P2PGossipSync>>, sync::Arc, sync::Arc>, + P2PGossipSync< + sync::Arc>>, + sync::Arc, + sync::Arc, + >, sync::Arc, sync::Arc, ) { @@ -268,258 +319,448 @@ pub(super) fn build_graph() -> ( let (our_privkey, _, privkeys, _) = get_nodes(&secp_ctx); - add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[0], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0); - - add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (5 << 4) | 3, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: u32::max_value(), - fee_proportional_millionths: u32::max_value(), - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0); - - add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[7], ChannelFeatures::from_le_bytes(id_to_feature_flags(12)), 12); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (5 << 4) | 3, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: u32::max_value(), - fee_proportional_millionths: u32::max_value(), - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 12, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: 0, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], NodeFeatures::from_le_bytes(id_to_feature_flags(8)), 0); - - add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3); - update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (3 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: (3 << 4) | 2, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 100, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (4 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 1000000, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: (4 << 4) | 2, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_channel(&gossip_sync, &secp_ctx, &privkeys[7], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(13)), 13); - update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (13 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 2000000, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: (13 << 4) | 2, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0); - - add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (6 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: (6 << 4) | 2, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new(), - }); - - add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(11)), 11); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 11, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (11 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 11, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: (11 << 4) | 2, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(5)), 0); - - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0); - - add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[5], ChannelFeatures::from_le_bytes(id_to_feature_flags(7)), 7); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 0, - cltv_expiry_delta: (7 << 4) | 1, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 1000000, - excess_data: Vec::new() - }); - update_channel(&gossip_sync, &secp_ctx, &privkeys[5], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 7, - timestamp: 1, - message_flags: 1, // Only must_be_one - channel_flags: 1, - cltv_expiry_delta: (7 << 4) | 2, - htlc_minimum_msat: 0, - htlc_maximum_msat: MAX_VALUE_MSAT, - fee_base_msat: 0, - fee_proportional_millionths: 0, - excess_data: Vec::new() - }); - - add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[5], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0); + add_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + &privkeys[0], + ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), + 1, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[0], + NodeFeatures::from_le_bytes(id_to_feature_flags(1)), + 0, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + &privkeys[1], + ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), + 2, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (5 << 4) | 3, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: u32::max_value(), + fee_proportional_millionths: u32::max_value(), + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[1], + NodeFeatures::from_le_bytes(id_to_feature_flags(2)), + 0, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + &privkeys[7], + ChannelFeatures::from_le_bytes(id_to_feature_flags(12)), + 12, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (5 << 4) | 3, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: u32::max_value(), + fee_proportional_millionths: u32::max_value(), + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: 0, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[7], + NodeFeatures::from_le_bytes(id_to_feature_flags(8)), + 0, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + &privkeys[2], + ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), + 3, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (3 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: (3 << 4) | 2, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 100, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + &privkeys[2], + ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), + 4, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (4 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 1000000, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: (4 << 4) | 2, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + &privkeys[2], + ChannelFeatures::from_le_bytes(id_to_feature_flags(13)), + 13, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (13 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 2000000, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: (13 << 4) | 2, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[2], + NodeFeatures::from_le_bytes(id_to_feature_flags(3)), + 0, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + &privkeys[4], + ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), + 6, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (6 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: (6 << 4) | 2, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + &privkeys[3], + ChannelFeatures::from_le_bytes(id_to_feature_flags(11)), + 11, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 11, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (11 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[3], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 11, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: (11 << 4) | 2, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[4], + NodeFeatures::from_le_bytes(id_to_feature_flags(5)), + 0, + ); + + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[3], + NodeFeatures::from_le_bytes(id_to_feature_flags(4)), + 0, + ); + + add_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + &privkeys[5], + ChannelFeatures::from_le_bytes(id_to_feature_flags(7)), + 7, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 0, + cltv_expiry_delta: (7 << 4) | 1, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 1000000, + excess_data: Vec::new(), + }, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[5], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 7, + timestamp: 1, + message_flags: 1, // Only must_be_one + channel_flags: 1, + cltv_expiry_delta: (7 << 4) | 2, + htlc_minimum_msat: 0, + htlc_maximum_msat: MAX_VALUE_MSAT, + fee_base_msat: 0, + fee_proportional_millionths: 0, + excess_data: Vec::new(), + }, + ); + + add_or_update_node( + &gossip_sync, + &secp_ctx, + &privkeys[5], + NodeFeatures::from_le_bytes(id_to_feature_flags(6)), + 0, + ); (secp_ctx, network_graph, gossip_sync, chain_monitor, logger) } diff --git a/lightning/src/routing/utxo.rs b/lightning/src/routing/utxo.rs index bb7ec79a8c0..252a5ad393f 100644 --- a/lightning/src/routing/utxo.rs +++ b/lightning/src/routing/utxo.rs @@ -13,21 +13,21 @@ //! channel matches a UTXO on-chain, requiring at least some marginal on-chain transacting in //! order to announce a channel. This module handles that checking. -use bitcoin::TxOut; use bitcoin::amount::Amount; use bitcoin::constants::ChainHash; +use bitcoin::TxOut; use bitcoin::hex::DisplayHex; use crate::ln::chan_utils::make_funding_redeemscript_from_slices; -use crate::ln::msgs::{self, LightningError, ErrorAction, MessageSendEvent}; +use crate::ln::msgs::{self, ErrorAction, LightningError, MessageSendEvent}; use crate::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync}; use crate::util::logger::{Level, Logger}; use crate::prelude::*; +use crate::sync::{LockTestExt, Mutex}; use alloc::sync::{Arc, Weak}; -use crate::sync::{Mutex, LockTestExt}; use core::ops::Deref; /// An error when accessing the chain via [`UtxoLookup`]. @@ -136,14 +136,16 @@ impl UtxoLookup for UtxoResolver { impl UtxoFuture { /// Builds a new future for later resolution. pub fn new() -> Self { - Self { state: Arc::new(Mutex::new(UtxoMessages { - complete: None, - channel_announce: None, - latest_node_announce_a: None, - latest_node_announce_b: None, - latest_channel_update_a: None, - latest_channel_update_b: None, - }))} + Self { + state: Arc::new(Mutex::new(UtxoMessages { + complete: None, + channel_announce: None, + latest_node_announce_a: None, + latest_node_announce_b: None, + latest_channel_update_a: None, + latest_channel_update_b: None, + })), + } } /// Resolves this future against the given `graph` and with the given `result`. @@ -157,9 +159,11 @@ impl UtxoFuture { /// /// [`processing_queue_high`]: crate::ln::msgs::RoutingMessageHandler::processing_queue_high /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events - pub fn resolve_without_forwarding(&self, - graph: &NetworkGraph, result: Result) - where L::Target: Logger { + pub fn resolve_without_forwarding( + &self, graph: &NetworkGraph, result: Result, + ) where + L::Target: Logger, + { self.do_resolve(graph, result); } @@ -174,9 +178,17 @@ impl UtxoFuture { /// /// [`processing_queue_high`]: crate::ln::msgs::RoutingMessageHandler::processing_queue_high /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events - pub fn resolve>, U: Deref, GS: Deref>>(&self, - graph: &NetworkGraph, gossip: GS, result: Result - ) where L::Target: Logger, U::Target: UtxoLookup { + pub fn resolve< + L: Deref, + G: Deref>, + U: Deref, + GS: Deref>, + >( + &self, graph: &NetworkGraph, gossip: GS, result: Result, + ) where + L::Target: Logger, + U::Target: UtxoLookup, + { let mut res = self.do_resolve(graph, result); for msg_opt in res.iter_mut() { if let Some(msg) = msg_opt.take() { @@ -185,8 +197,12 @@ impl UtxoFuture { } } - fn do_resolve(&self, graph: &NetworkGraph, result: Result) - -> [Option; 5] where L::Target: Logger { + fn do_resolve( + &self, graph: &NetworkGraph, result: Result, + ) -> [Option; 5] + where + L::Target: Logger, + { let (announcement, node_a, node_b, update_a, update_b) = { let mut pending_checks = graph.pending_checks.internal.lock().unwrap(); let mut async_messages = self.state.lock().unwrap(); @@ -206,11 +222,13 @@ impl UtxoFuture { pending_checks.lookup_completed(announcement_msg, &Arc::downgrade(&self.state)); - (async_messages.channel_announce.take().unwrap(), + ( + async_messages.channel_announce.take().unwrap(), async_messages.latest_node_announce_a.take(), async_messages.latest_node_announce_b.take(), async_messages.latest_channel_update_a.take(), - async_messages.latest_channel_update_b.take()) + async_messages.latest_channel_update_b.take(), + ) }; let mut res = [None, None, None, None, None]; @@ -225,7 +243,8 @@ impl UtxoFuture { ChannelAnnouncement::Full(signed_msg) => { if graph.update_channel_from_announcement(&signed_msg, &Some(&resolver)).is_ok() { res[res_idx] = Some(MessageSendEvent::BroadcastChannelAnnouncement { - msg: signed_msg, update_msg: None, + msg: signed_msg, + update_msg: None, }); res_idx += 1; } @@ -239,9 +258,8 @@ impl UtxoFuture { match announce { Some(NodeAnnouncement::Full(signed_msg)) => { if graph.update_node_from_announcement(&signed_msg).is_ok() { - res[res_idx] = Some(MessageSendEvent::BroadcastNodeAnnouncement { - msg: signed_msg, - }); + res[res_idx] = + Some(MessageSendEvent::BroadcastNodeAnnouncement { msg: signed_msg }); res_idx += 1; } }, @@ -256,9 +274,8 @@ impl UtxoFuture { match update { Some(ChannelUpdate::Full(signed_msg)) => { if graph.update_channel(&signed_msg).is_ok() { - res[res_idx] = Some(MessageSendEvent::BroadcastChannelUpdate { - msg: signed_msg, - }); + res[res_idx] = + Some(MessageSendEvent::BroadcastChannelUpdate { msg: signed_msg }); res_idx += 1; } }, @@ -279,8 +296,9 @@ struct PendingChecksContext { } impl PendingChecksContext { - fn lookup_completed(&mut self, - msg: &msgs::UnsignedChannelAnnouncement, completed_state: &Weak> + fn lookup_completed( + &mut self, msg: &msgs::UnsignedChannelAnnouncement, + completed_state: &Weak>, ) { if let hash_map::Entry::Occupied(e) = self.channels.entry(msg.short_channel_id) { if Weak::ptr_eq(e.get(), &completed_state) { @@ -290,11 +308,15 @@ impl PendingChecksContext { if let hash_map::Entry::Occupied(mut e) = self.nodes.entry(msg.node_id_1) { e.get_mut().retain(|elem| !Weak::ptr_eq(&elem, &completed_state)); - if e.get().is_empty() { e.remove(); } + if e.get().is_empty() { + e.remove(); + } } if let hash_map::Entry::Occupied(mut e) = self.nodes.entry(msg.node_id_2) { e.get_mut().retain(|elem| !Weak::ptr_eq(&elem, &completed_state)); - if e.get().is_empty() { e.remove(); } + if e.get().is_empty() { + e.remove(); + } } } } @@ -306,15 +328,18 @@ pub(super) struct PendingChecks { impl PendingChecks { pub(super) fn new() -> Self { - PendingChecks { internal: Mutex::new(PendingChecksContext { - channels: new_hash_map(), nodes: new_hash_map(), - }) } + PendingChecks { + internal: Mutex::new(PendingChecksContext { + channels: new_hash_map(), + nodes: new_hash_map(), + }), + } } /// Checks if there is a pending `channel_update` UTXO validation for the given channel, /// and, if so, stores the channel message for handling later and returns an `Err`. pub(super) fn check_hold_pending_channel_update( - &self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate> + &self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate>, ) -> Result<(), LightningError> { let mut pending_checks = self.internal.lock().unwrap(); if let hash_map::Entry::Occupied(e) = pending_checks.channels.entry(msg.short_channel_id) { @@ -323,25 +348,32 @@ impl PendingChecks { Some(msgs_ref) => { let mut messages = msgs_ref.lock().unwrap(); let latest_update = if is_from_a { - &mut messages.latest_channel_update_a - } else { - &mut messages.latest_channel_update_b - }; - if latest_update.is_none() || latest_update.as_ref().unwrap().timestamp() < msg.timestamp { + &mut messages.latest_channel_update_a + } else { + &mut messages.latest_channel_update_b + }; + if latest_update.is_none() + || latest_update.as_ref().unwrap().timestamp() < msg.timestamp + { // If the messages we got has a higher timestamp, just blindly assume the // signatures on the new message are correct and drop the old message. This // may cause us to end up dropping valid `channel_update`s if a peer is // malicious, but we should get the correct ones when the node updates them. - *latest_update = Some( - if let Some(msg) = full_msg { ChannelUpdate::Full(msg.clone()) } - else { ChannelUpdate::Unsigned(msg.clone()) }); + *latest_update = Some(if let Some(msg) = full_msg { + ChannelUpdate::Full(msg.clone()) + } else { + ChannelUpdate::Unsigned(msg.clone()) + }); } return Err(LightningError { - err: "Awaiting channel_announcement validation to accept channel_update".to_owned(), + err: "Awaiting channel_announcement validation to accept channel_update" + .to_owned(), action: ErrorAction::IgnoreAndLog(Level::Gossip), }); }, - None => { e.remove(); }, + None => { + e.remove(); + }, } } Ok(()) @@ -350,43 +382,48 @@ impl PendingChecks { /// Checks if there is a pending `node_announcement` UTXO validation for a channel with the /// given node and, if so, stores the channel message for handling later and returns an `Err`. pub(super) fn check_hold_pending_node_announcement( - &self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement> + &self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement>, ) -> Result<(), LightningError> { let mut pending_checks = self.internal.lock().unwrap(); if let hash_map::Entry::Occupied(mut e) = pending_checks.nodes.entry(msg.node_id) { let mut found_at_least_one_chan = false; - e.get_mut().retain(|node_msgs| { - match Weak::upgrade(&node_msgs) { - Some(chan_mtx) => { - let mut chan_msgs = chan_mtx.lock().unwrap(); - if let Some(chan_announce) = &chan_msgs.channel_announce { - let latest_announce = - if *chan_announce.node_id_1() == msg.node_id { - &mut chan_msgs.latest_node_announce_a - } else { - &mut chan_msgs.latest_node_announce_b - }; - if latest_announce.is_none() || - latest_announce.as_ref().unwrap().timestamp() < msg.timestamp - { - *latest_announce = Some( - if let Some(msg) = full_msg { NodeAnnouncement::Full(msg.clone()) } - else { NodeAnnouncement::Unsigned(msg.clone()) }); - } - found_at_least_one_chan = true; - true + e.get_mut().retain(|node_msgs| match Weak::upgrade(&node_msgs) { + Some(chan_mtx) => { + let mut chan_msgs = chan_mtx.lock().unwrap(); + if let Some(chan_announce) = &chan_msgs.channel_announce { + let latest_announce = if *chan_announce.node_id_1() == msg.node_id { + &mut chan_msgs.latest_node_announce_a } else { - debug_assert!(false, "channel_announce is set before struct is added to node map"); - false + &mut chan_msgs.latest_node_announce_b + }; + if latest_announce.is_none() + || latest_announce.as_ref().unwrap().timestamp() < msg.timestamp + { + *latest_announce = Some(if let Some(msg) = full_msg { + NodeAnnouncement::Full(msg.clone()) + } else { + NodeAnnouncement::Unsigned(msg.clone()) + }); } - }, - None => false, - } + found_at_least_one_chan = true; + true + } else { + debug_assert!( + false, + "channel_announce is set before struct is added to node map" + ); + false + } + }, + None => false, }); - if e.get().is_empty() { e.remove(); } + if e.get().is_empty() { + e.remove(); + } if found_at_least_one_chan { return Err(LightningError { - err: "Awaiting channel_announcement validation to accept node_announcement".to_owned(), + err: "Awaiting channel_announcement validation to accept node_announcement" + .to_owned(), action: ErrorAction::IgnoreAndLog(Level::Gossip), }); } @@ -394,9 +431,10 @@ impl PendingChecks { Ok(()) } - fn check_replace_previous_entry(msg: &msgs::UnsignedChannelAnnouncement, - full_msg: Option<&msgs::ChannelAnnouncement>, replacement: Option>>, - pending_channels: &mut HashMap>> + fn check_replace_previous_entry( + msg: &msgs::UnsignedChannelAnnouncement, full_msg: Option<&msgs::ChannelAnnouncement>, + replacement: Option>>, + pending_channels: &mut HashMap>>, ) -> Result<(), msgs::LightningError> { match pending_channels.entry(msg.short_channel_id) { hash_map::Entry::Occupied(mut e) => { @@ -408,8 +446,13 @@ impl PendingChecks { // This may be called with the mutex held on a different UtxoMessages // struct, however in that case we have a global lockorder of new messages // -> old messages, which makes this safe. - let pending_matches = match &pending_msgs.unsafe_well_ordered_double_lock_self().channel_announce { - Some(ChannelAnnouncement::Full(pending_msg)) => Some(pending_msg) == full_msg, + let pending_matches = match &pending_msgs + .unsafe_well_ordered_double_lock_self() + .channel_announce + { + Some(ChannelAnnouncement::Full(pending_msg)) => { + Some(pending_msg) == full_msg + }, Some(ChannelAnnouncement::Unsigned(pending_msg)) => pending_msg == msg, None => { // This shouldn't actually be reachable. We set the @@ -441,53 +484,66 @@ impl PendingChecks { // so just remove/replace it and move on. if let Some(item) = replacement { *e.get_mut() = item; - } else { e.remove(); } + } else { + e.remove(); + } }, } }, hash_map::Entry::Vacant(v) => { - if let Some(item) = replacement { v.insert(item); } + if let Some(item) = replacement { + v.insert(item); + } }, } Ok(()) } - pub(super) fn check_channel_announcement(&self, - utxo_lookup: &Option, msg: &msgs::UnsignedChannelAnnouncement, - full_msg: Option<&msgs::ChannelAnnouncement> - ) -> Result, msgs::LightningError> where U::Target: UtxoLookup { - let handle_result = |res| { - match res { - Ok(TxOut { value, script_pubkey }) => { - let expected_script = - make_funding_redeemscript_from_slices(msg.bitcoin_key_1.as_array(), msg.bitcoin_key_2.as_array()).to_p2wsh(); - if script_pubkey != expected_script { - return Err(LightningError{ - err: format!("Channel announcement key ({}) didn't match on-chain script ({})", - expected_script.to_hex_string(), script_pubkey.to_hex_string()), - action: ErrorAction::IgnoreError - }); - } - Ok(Some(value)) - }, - Err(UtxoLookupError::UnknownChain) => { - Err(LightningError { - err: format!("Channel announced on an unknown chain ({})", - msg.chain_hash.to_bytes().as_hex()), - action: ErrorAction::IgnoreError - }) - }, - Err(UtxoLookupError::UnknownTx) => { - Err(LightningError { - err: "Channel announced without corresponding UTXO entry".to_owned(), - action: ErrorAction::IgnoreError - }) - }, - } + pub(super) fn check_channel_announcement( + &self, utxo_lookup: &Option, msg: &msgs::UnsignedChannelAnnouncement, + full_msg: Option<&msgs::ChannelAnnouncement>, + ) -> Result, msgs::LightningError> + where + U::Target: UtxoLookup, + { + let handle_result = |res| match res { + Ok(TxOut { value, script_pubkey }) => { + let expected_script = make_funding_redeemscript_from_slices( + msg.bitcoin_key_1.as_array(), + msg.bitcoin_key_2.as_array(), + ) + .to_p2wsh(); + if script_pubkey != expected_script { + return Err(LightningError { + err: format!( + "Channel announcement key ({}) didn't match on-chain script ({})", + expected_script.to_hex_string(), + script_pubkey.to_hex_string() + ), + action: ErrorAction::IgnoreError, + }); + } + Ok(Some(value)) + }, + Err(UtxoLookupError::UnknownChain) => Err(LightningError { + err: format!( + "Channel announced on an unknown chain ({})", + msg.chain_hash.to_bytes().as_hex() + ), + action: ErrorAction::IgnoreError, + }), + Err(UtxoLookupError::UnknownTx) => Err(LightningError { + err: "Channel announced without corresponding UTXO entry".to_owned(), + action: ErrorAction::IgnoreError, + }), }; - Self::check_replace_previous_entry(msg, full_msg, None, - &mut self.internal.lock().unwrap().channels)?; + Self::check_replace_previous_entry( + msg, + full_msg, + None, + &mut self.internal.lock().unwrap().channels, + )?; match utxo_lookup { &None => { @@ -505,15 +561,27 @@ impl PendingChecks { // handle the result in-line. handle_result(res) } else { - Self::check_replace_previous_entry(msg, full_msg, - Some(Arc::downgrade(&future.state)), &mut pending_checks.channels)?; - async_messages.channel_announce = Some( - if let Some(msg) = full_msg { ChannelAnnouncement::Full(msg.clone()) } - else { ChannelAnnouncement::Unsigned(msg.clone()) }); - pending_checks.nodes.entry(msg.node_id_1) - .or_default().push(Arc::downgrade(&future.state)); - pending_checks.nodes.entry(msg.node_id_2) - .or_default().push(Arc::downgrade(&future.state)); + Self::check_replace_previous_entry( + msg, + full_msg, + Some(Arc::downgrade(&future.state)), + &mut pending_checks.channels, + )?; + async_messages.channel_announce = Some(if let Some(msg) = full_msg { + ChannelAnnouncement::Full(msg.clone()) + } else { + ChannelAnnouncement::Unsigned(msg.clone()) + }); + pending_checks + .nodes + .entry(msg.node_id_1) + .or_default() + .push(Arc::downgrade(&future.state)); + pending_checks + .nodes + .entry(msg.node_id_2) + .or_default() + .push(Arc::downgrade(&future.state)); Err(LightningError { err: "Channel being checked async".to_owned(), action: ErrorAction::IgnoreAndLog(Level::Gossip), @@ -521,7 +589,7 @@ impl PendingChecks { } }, } - } + }, } } @@ -544,9 +612,7 @@ impl PendingChecks { // If we have many channel checks pending, ensure we don't have any dangling checks // (i.e. checks where the user told us they'd call back but drop'd the `UtxoFuture` // instead) before we commit to applying backpressure. - pending_checks.channels.retain(|_, chan| { - Weak::upgrade(&chan).is_some() - }); + pending_checks.channels.retain(|_, chan| Weak::upgrade(&chan).is_some()); pending_checks.nodes.retain(|_, channels| { channels.retain(|chan| Weak::upgrade(&chan).is_some()); !channels.is_empty() @@ -577,10 +643,17 @@ mod tests { (chain_source, network_graph) } - fn get_test_objects() -> (msgs::ChannelAnnouncement, TestChainSource, - NetworkGraph>, bitcoin::ScriptBuf, msgs::NodeAnnouncement, - msgs::NodeAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, msgs::ChannelUpdate) - { + fn get_test_objects() -> ( + msgs::ChannelAnnouncement, + TestChainSource, + NetworkGraph>, + bitcoin::ScriptBuf, + msgs::NodeAnnouncement, + msgs::NodeAnnouncement, + msgs::ChannelUpdate, + msgs::ChannelUpdate, + msgs::ChannelUpdate, + ) { let secp_ctx = Secp256k1::new(); let (chain_source, network_graph) = get_network(); @@ -588,19 +661,37 @@ mod tests { let good_script = get_channel_script(&secp_ctx); let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap(); let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap(); - let valid_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); let node_a_announce = get_signed_node_announcement(|_| {}, node_1_privkey, &secp_ctx); let node_b_announce = get_signed_node_announcement(|_| {}, node_2_privkey, &secp_ctx); // Note that we have to set the "direction" flag correctly on both messages - let chan_update_a = get_signed_channel_update(|msg| msg.channel_flags = 0, node_1_privkey, &secp_ctx); - let chan_update_b = get_signed_channel_update(|msg| msg.channel_flags = 1, node_2_privkey, &secp_ctx); - let chan_update_c = get_signed_channel_update(|msg| { - msg.channel_flags = 1; msg.timestamp += 1; }, node_2_privkey, &secp_ctx); - - (valid_announcement, chain_source, network_graph, good_script, node_a_announce, - node_b_announce, chan_update_a, chan_update_b, chan_update_c) + let chan_update_a = + get_signed_channel_update(|msg| msg.channel_flags = 0, node_1_privkey, &secp_ctx); + let chan_update_b = + get_signed_channel_update(|msg| msg.channel_flags = 1, node_2_privkey, &secp_ctx); + let chan_update_c = get_signed_channel_update( + |msg| { + msg.channel_flags = 1; + msg.timestamp += 1; + }, + node_2_privkey, + &secp_ctx, + ); + + ( + valid_announcement, + chain_source, + network_graph, + good_script, + node_a_announce, + node_b_announce, + chan_update_a, + chan_update_b, + chan_update_c, + ) } #[test] @@ -610,41 +701,84 @@ mod tests { let (valid_announcement, chain_source, network_graph, good_script, ..) = get_test_objects(); let future = UtxoFuture::new(); - future.resolve_without_forwarding(&network_graph, - Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script })); + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }), + ); *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone()); - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap(); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_some()); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap(); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_some()); } #[test] fn test_async_lookup() { // Test a simple async lookup - let (valid_announcement, chain_source, network_graph, good_script, - node_a_announce, node_b_announce, ..) = get_test_objects(); + let ( + valid_announcement, + chain_source, + network_graph, + good_script, + node_a_announce, + node_b_announce, + .., + ) = get_test_objects(); let future = UtxoFuture::new(); *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone()); assert_eq!( - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel being checked async"); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); - - future.resolve_without_forwarding(&network_graph, - Ok(TxOut { value: Amount::ZERO, script_pubkey: good_script })); - network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).unwrap(); - network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).unwrap(); - - assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_1) - .unwrap().announcement_info.is_none()); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel being checked async" + ); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_none()); + + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { value: Amount::ZERO, script_pubkey: good_script }), + ); + network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .unwrap(); + network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .unwrap(); + + assert!(network_graph + .read_only() + .nodes() + .get(&valid_announcement.contents.node_id_1) + .unwrap() + .announcement_info + .is_none()); network_graph.update_node_from_announcement(&node_a_announce).unwrap(); network_graph.update_node_from_announcement(&node_b_announce).unwrap(); - assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_1) - .unwrap().announcement_info.is_some()); + assert!(network_graph + .read_only() + .nodes() + .get(&valid_announcement.contents.node_id_1) + .unwrap() + .announcement_info + .is_some()); } #[test] @@ -656,13 +790,30 @@ mod tests { *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone()); assert_eq!( - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel being checked async"); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); - - future.resolve_without_forwarding(&network_graph, - Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: bitcoin::ScriptBuf::new() })); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel being checked async" + ); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_none()); + + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { + value: Amount::from_sat(1_000_000), + script_pubkey: bitcoin::ScriptBuf::new(), + }), + ); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_none()); } #[test] @@ -674,88 +825,184 @@ mod tests { *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone()); assert_eq!( - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel being checked async"); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel being checked async" + ); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_none()); future.resolve_without_forwarding(&network_graph, Err(UtxoLookupError::UnknownTx)); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_none()); } #[test] fn test_updates_async_lookup() { // Test async lookups will process pending channel_update/node_announcements once they // complete. - let (valid_announcement, chain_source, network_graph, good_script, node_a_announce, - node_b_announce, chan_update_a, chan_update_b, ..) = get_test_objects(); + let ( + valid_announcement, + chain_source, + network_graph, + good_script, + node_a_announce, + node_b_announce, + chan_update_a, + chan_update_b, + .., + ) = get_test_objects(); let future = UtxoFuture::new(); *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone()); assert_eq!( - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel being checked async"); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel being checked async" + ); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_none()); assert_eq!( network_graph.update_node_from_announcement(&node_a_announce).unwrap_err().err, - "Awaiting channel_announcement validation to accept node_announcement"); + "Awaiting channel_announcement validation to accept node_announcement" + ); assert_eq!( network_graph.update_node_from_announcement(&node_b_announce).unwrap_err().err, - "Awaiting channel_announcement validation to accept node_announcement"); - - assert_eq!(network_graph.update_channel(&chan_update_a).unwrap_err().err, - "Awaiting channel_announcement validation to accept channel_update"); - assert_eq!(network_graph.update_channel(&chan_update_b).unwrap_err().err, - "Awaiting channel_announcement validation to accept channel_update"); + "Awaiting channel_announcement validation to accept node_announcement" + ); - future.resolve_without_forwarding(&network_graph, - Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script })); - - assert!(network_graph.read_only().channels() - .get(&valid_announcement.contents.short_channel_id).unwrap().one_to_two.is_some()); - assert!(network_graph.read_only().channels() - .get(&valid_announcement.contents.short_channel_id).unwrap().two_to_one.is_some()); - - assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_1) - .unwrap().announcement_info.is_some()); - assert!(network_graph.read_only().nodes().get(&valid_announcement.contents.node_id_2) - .unwrap().announcement_info.is_some()); + assert_eq!( + network_graph.update_channel(&chan_update_a).unwrap_err().err, + "Awaiting channel_announcement validation to accept channel_update" + ); + assert_eq!( + network_graph.update_channel(&chan_update_b).unwrap_err().err, + "Awaiting channel_announcement validation to accept channel_update" + ); + + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }), + ); + + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .unwrap() + .one_to_two + .is_some()); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .unwrap() + .two_to_one + .is_some()); + + assert!(network_graph + .read_only() + .nodes() + .get(&valid_announcement.contents.node_id_1) + .unwrap() + .announcement_info + .is_some()); + assert!(network_graph + .read_only() + .nodes() + .get(&valid_announcement.contents.node_id_2) + .unwrap() + .announcement_info + .is_some()); } #[test] fn test_latest_update_async_lookup() { // Test async lookups will process the latest channel_update if two are received while // awaiting an async UTXO lookup. - let (valid_announcement, chain_source, network_graph, good_script, _, - _, chan_update_a, chan_update_b, chan_update_c, ..) = get_test_objects(); + let ( + valid_announcement, + chain_source, + network_graph, + good_script, + _, + _, + chan_update_a, + chan_update_b, + chan_update_c, + .., + ) = get_test_objects(); let future = UtxoFuture::new(); *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone()); assert_eq!( - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel being checked async"); - assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel being checked async" + ); + assert!(network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .is_none()); - assert_eq!(network_graph.update_channel(&chan_update_a).unwrap_err().err, - "Awaiting channel_announcement validation to accept channel_update"); - assert_eq!(network_graph.update_channel(&chan_update_b).unwrap_err().err, - "Awaiting channel_announcement validation to accept channel_update"); - assert_eq!(network_graph.update_channel(&chan_update_c).unwrap_err().err, - "Awaiting channel_announcement validation to accept channel_update"); + assert_eq!( + network_graph.update_channel(&chan_update_a).unwrap_err().err, + "Awaiting channel_announcement validation to accept channel_update" + ); + assert_eq!( + network_graph.update_channel(&chan_update_b).unwrap_err().err, + "Awaiting channel_announcement validation to accept channel_update" + ); + assert_eq!( + network_graph.update_channel(&chan_update_c).unwrap_err().err, + "Awaiting channel_announcement validation to accept channel_update" + ); - future.resolve_without_forwarding(&network_graph, - Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script })); + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }), + ); assert_eq!(chan_update_a.contents.timestamp, chan_update_b.contents.timestamp); let graph_lock = network_graph.read_only(); - assert!(graph_lock.channels() - .get(&valid_announcement.contents.short_channel_id).as_ref().unwrap() - .one_to_two.as_ref().unwrap().last_update != - graph_lock.channels() - .get(&valid_announcement.contents.short_channel_id).as_ref().unwrap() - .two_to_one.as_ref().unwrap().last_update); + assert!( + graph_lock + .channels() + .get(&valid_announcement.contents.short_channel_id) + .as_ref() + .unwrap() + .one_to_two + .as_ref() + .unwrap() + .last_update != graph_lock + .channels() + .get(&valid_announcement.contents.short_channel_id) + .as_ref() + .unwrap() + .two_to_one + .as_ref() + .unwrap() + .last_update + ); } #[test] @@ -768,16 +1015,24 @@ mod tests { *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future.clone()); assert_eq!( - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel being checked async"); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel being checked async" + ); assert_eq!(chain_source.get_utxo_call_count.load(Ordering::Relaxed), 1); // If we make a second request with the same message, the call count doesn't increase... let future_b = UtxoFuture::new(); *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Async(future_b.clone()); assert_eq!( - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel announcement is already being checked"); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel announcement is already being checked" + ); assert_eq!(chain_source.get_utxo_call_count.load(Ordering::Relaxed), 1); // But if we make a third request with a tweaked message, we should get a second call @@ -785,19 +1040,33 @@ mod tests { let secp_ctx = Secp256k1::new(); let replacement_pk_1 = &SecretKey::from_slice(&[99; 32]).unwrap(); let replacement_pk_2 = &SecretKey::from_slice(&[98; 32]).unwrap(); - let invalid_announcement = get_signed_channel_announcement(|_| {}, replacement_pk_1, replacement_pk_2, &secp_ctx); + let invalid_announcement = + get_signed_channel_announcement(|_| {}, replacement_pk_1, replacement_pk_2, &secp_ctx); assert_eq!( - network_graph.update_channel_from_announcement(&invalid_announcement, &Some(&chain_source)).unwrap_err().err, - "Channel being checked async"); + network_graph + .update_channel_from_announcement(&invalid_announcement, &Some(&chain_source)) + .unwrap_err() + .err, + "Channel being checked async" + ); assert_eq!(chain_source.get_utxo_call_count.load(Ordering::Relaxed), 2); // Still, if we resolve the original future, the original channel will be accepted. - future.resolve_without_forwarding(&network_graph, - Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script })); - assert!(!network_graph.read_only().channels() - .get(&valid_announcement.contents.short_channel_id).unwrap() - .announcement_message.as_ref().unwrap() - .contents.features.supports_unknown_test_feature()); + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { value: Amount::from_sat(1_000_000), script_pubkey: good_script }), + ); + assert!(!network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + .unwrap() + .announcement_message + .as_ref() + .unwrap() + .contents + .features + .supports_unknown_test_feature()); } #[test] @@ -816,14 +1085,22 @@ mod tests { for i in 0..PendingChecks::MAX_PENDING_LOOKUPS { let valid_announcement = get_signed_channel_announcement( - |msg| msg.short_channel_id += 1 + i as u64, node_1_privkey, node_2_privkey, &secp_ctx); - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err(); + |msg| msg.short_channel_id += 1 + i as u64, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err(); assert!(!network_graph.pending_checks.too_many_checks_pending()); } - let valid_announcement = get_signed_channel_announcement( - |_| {}, node_1_privkey, node_2_privkey, &secp_ctx); - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err(); + let valid_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err(); assert!(network_graph.pending_checks.too_many_checks_pending()); // Once the future completes the "too many checks" flag should reset. @@ -846,14 +1123,22 @@ mod tests { for i in 0..PendingChecks::MAX_PENDING_LOOKUPS { let valid_announcement = get_signed_channel_announcement( - |msg| msg.short_channel_id += 1 + i as u64, node_1_privkey, node_2_privkey, &secp_ctx); - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err(); + |msg| msg.short_channel_id += 1 + i as u64, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err(); assert!(!network_graph.pending_checks.too_many_checks_pending()); } - let valid_announcement = get_signed_channel_announcement( - |_| {}, node_1_privkey, node_2_privkey, &secp_ctx); - network_graph.update_channel_from_announcement(&valid_announcement, &Some(&chain_source)).unwrap_err(); + let valid_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + network_graph + .update_channel_from_announcement(&valid_announcement, &Some(&chain_source)) + .unwrap_err(); assert!(network_graph.pending_checks.too_many_checks_pending()); // Once the future is drop'd (by resetting the `utxo_ret` value) the "too many checks" flag diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files deleted file mode 100644 index de717db86ae..00000000000 --- a/rustfmt_excluded_files +++ /dev/null @@ -1,40 +0,0 @@ -lightning/src/chain/chaininterface.rs -lightning/src/chain/chainmonitor.rs -lightning/src/chain/channelmonitor.rs -lightning/src/chain/mod.rs -lightning/src/chain/onchaintx.rs -lightning/src/chain/package.rs -lightning/src/chain/transaction.rs -lightning/src/events/bump_transaction.rs -lightning/src/events/mod.rs -lightning/src/lib.rs -lightning/src/ln/async_signer_tests.rs -lightning/src/ln/blinded_payment_tests.rs -lightning/src/ln/chan_utils.rs -lightning/src/ln/chanmon_update_fail_tests.rs -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/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 -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 -lightning/src/ln/reorg_tests.rs -lightning/src/ln/shutdown_tests.rs -lightning/src/routing/mod.rs -lightning/src/routing/router.rs -lightning/src/routing/scoring.rs -lightning/src/routing/test_utils.rs -lightning/src/routing/utxo.rs