diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index fb6baabfac1..50fcbe12b82 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -4,12 +4,9 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] #![cfg_attr(not(feature = "futures"), deny(unsafe_code))] - #![cfg_attr(docsrs, feature(doc_auto_cfg))] - #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] #[cfg(any(test, feature = "std"))] @@ -18,26 +15,27 @@ extern crate core; #[cfg(not(feature = "std"))] extern crate alloc; -#[macro_use] extern crate lightning; +#[macro_use] +extern crate lightning; extern crate lightning_rapid_gossip_sync; use lightning::chain; use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use lightning::chain::chainmonitor::{ChainMonitor, Persist}; -use lightning::sign::{EntropySource, NodeSigner, SignerProvider}; -use lightning::events::{Event, PathFailure}; #[cfg(feature = "std")] use lightning::events::EventHandler; #[cfg(any(feature = "std", feature = "futures"))] use lightning::events::EventsProvider; +use lightning::events::{Event, PathFailure}; +use lightning::sign::{EntropySource, NodeSigner, SignerProvider}; use lightning::ln::channelmanager::ChannelManager; use lightning::ln::msgs::OnionMessageHandler; use lightning::ln::peer_handler::APeerManager; use lightning::routing::gossip::{NetworkGraph, P2PGossipSync}; -use lightning::routing::utxo::UtxoLookup; use lightning::routing::router::Router; use lightning::routing::scoring::{ScoreUpdate, WriteableScore}; +use lightning::routing::utxo::UtxoLookup; use lightning::util::logger::Logger; use lightning::util::persist::Persister; #[cfg(feature = "std")] @@ -47,11 +45,11 @@ use lightning_rapid_gossip_sync::RapidGossipSync; use core::ops::Deref; use core::time::Duration; -#[cfg(feature = "std")] -use std::sync::Arc; #[cfg(feature = "std")] use core::sync::atomic::{AtomicBool, Ordering}; #[cfg(feature = "std")] +use std::sync::Arc; +#[cfg(feature = "std")] use std::thread::{self, JoinHandle}; #[cfg(feature = "std")] use std::time::Instant; @@ -132,10 +130,18 @@ const REBROADCAST_TIMER: u64 = 1; #[cfg(feature = "futures")] /// core::cmp::min is not currently const, so we define a trivial (and equivalent) replacement -const fn min_u64(a: u64, b: u64) -> u64 { if a < b { a } else { b } } +const fn min_u64(a: u64, b: u64) -> u64 { + if a < b { + a + } else { + b + } +} #[cfg(feature = "futures")] -const FASTEST_TIMER: u64 = min_u64(min_u64(FRESHNESS_TIMER, PING_TIMER), - min_u64(SCORER_PERSIST_TIMER, min_u64(FIRST_NETWORK_PRUNE_TIMER, REBROADCAST_TIMER))); +const FASTEST_TIMER: u64 = min_u64( + min_u64(FRESHNESS_TIMER, PING_TIMER), + min_u64(SCORER_PERSIST_TIMER, min_u64(FIRST_NETWORK_PRUNE_TIMER, REBROADCAST_TIMER)), +); /// Either [`P2PGossipSync`] or [`RapidGossipSync`]. pub enum GossipSync< @@ -144,8 +150,10 @@ pub enum GossipSync< G: Deref>, U: Deref, L: Deref, -> -where U::Target: UtxoLookup, L::Target: Logger { +> where + U::Target: UtxoLookup, + L::Target: Logger, +{ /// Gossip sync via the lightning peer-to-peer network as defined by BOLT 7. P2P(P), /// Rapid gossip sync from a trusted server. @@ -155,13 +163,16 @@ where U::Target: UtxoLookup, L::Target: Logger { } impl< - P: Deref>, - R: Deref>, - G: Deref>, - U: Deref, - L: Deref, -> GossipSync -where U::Target: UtxoLookup, L::Target: Logger { + P: Deref>, + R: Deref>, + G: Deref>, + U: Deref, + L: Deref, + > GossipSync +where + U::Target: UtxoLookup, + L::Target: Logger, +{ fn network_graph(&self) -> Option<&G> { match self { GossipSync::P2P(gossip_sync) => Some(gossip_sync.network_graph()), @@ -186,8 +197,12 @@ where U::Target: UtxoLookup, L::Target: Logger { } /// This is not exported to bindings users as the bindings concretize everything and have constructors for us -impl>, G: Deref>, U: Deref, L: Deref> - GossipSync, G, U, L> +impl< + P: Deref>, + G: Deref>, + U: Deref, + L: Deref, + > GossipSync, G, U, L> where U::Target: UtxoLookup, L::Target: Logger, @@ -199,15 +214,19 @@ where } /// This is not exported to bindings users as the bindings concretize everything and have constructors for us -impl<'a, R: Deref>, G: Deref>, L: Deref> +impl< + 'a, + R: Deref>, + G: Deref>, + L: Deref, + > GossipSync< &P2PGossipSync, R, G, &'a (dyn UtxoLookup + Send + Sync), L, - > -where + > where L::Target: Logger, { /// Initializes a new [`GossipSync::Rapid`] variant. @@ -224,8 +243,7 @@ impl<'a, L: Deref> &'a NetworkGraph, &'a (dyn UtxoLookup + Send + Sync), L, - > -where + > where L::Target: Logger, { /// Initializes a new [`GossipSync::None`] variant. @@ -234,11 +252,14 @@ where } } -fn handle_network_graph_update( - network_graph: &NetworkGraph, event: &Event -) where L::Target: Logger { +fn handle_network_graph_update(network_graph: &NetworkGraph, event: &Event) +where + L::Target: Logger, +{ if let Event::PaymentPathFailed { - failure: PathFailure::OnPath { network_update: Some(ref upd) }, .. } = event + failure: PathFailure::OnPath { network_update: Some(ref upd) }, + .. + } = event { network_graph.handle_network_update(upd); } @@ -459,35 +480,50 @@ macro_rules! define_run_body { #[cfg(feature = "futures")] pub(crate) mod futures_util { use core::future::Future; - use core::task::{Poll, Waker, RawWaker, RawWakerVTable}; - use core::pin::Pin; use core::marker::Unpin; + use core::pin::Pin; + use core::task::{Poll, RawWaker, RawWakerVTable, Waker}; pub(crate) struct Selector< - A: Future + Unpin, B: Future + Unpin, C: Future + Unpin + A: Future + Unpin, + B: Future + Unpin, + C: Future + Unpin, > { pub a: A, pub b: B, pub c: C, } pub(crate) enum SelectorOutput { - A, B, C(bool), + A, + B, + C(bool), } impl< - A: Future + Unpin, B: Future + Unpin, C: Future + Unpin - > Future for Selector { + A: Future + Unpin, + B: Future + Unpin, + C: Future + Unpin, + > Future for Selector + { type Output = SelectorOutput; - fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll { + fn poll( + mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>, + ) -> Poll { match Pin::new(&mut self.a).poll(ctx) { - Poll::Ready(()) => { return Poll::Ready(SelectorOutput::A); }, + Poll::Ready(()) => { + return Poll::Ready(SelectorOutput::A); + }, Poll::Pending => {}, } match Pin::new(&mut self.b).poll(ctx) { - Poll::Ready(()) => { return Poll::Ready(SelectorOutput::B); }, + Poll::Ready(()) => { + return Poll::Ready(SelectorOutput::B); + }, Poll::Pending => {}, } match Pin::new(&mut self.c).poll(ctx) { - Poll::Ready(res) => { return Poll::Ready(SelectorOutput::C(res)); }, + Poll::Ready(res) => { + return Poll::Ready(SelectorOutput::C(res)); + }, Poll::Pending => {}, } Poll::Pending @@ -497,17 +533,25 @@ pub(crate) mod futures_util { // If we want to poll a future without an async context to figure out if it has completed or // not without awaiting, we need a Waker, which needs a vtable...we fill it with dummy values // but sadly there's a good bit of boilerplate here. - fn dummy_waker_clone(_: *const ()) -> RawWaker { RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE) } - fn dummy_waker_action(_: *const ()) { } + fn dummy_waker_clone(_: *const ()) -> RawWaker { + RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE) + } + fn dummy_waker_action(_: *const ()) {} const DUMMY_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( - dummy_waker_clone, dummy_waker_action, dummy_waker_action, dummy_waker_action); - pub(crate) fn dummy_waker() -> Waker { unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)) } } + dummy_waker_clone, + dummy_waker_action, + dummy_waker_action, + dummy_waker_action, + ); + pub(crate) fn dummy_waker() -> Waker { + unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)) } + } } #[cfg(feature = "futures")] -use futures_util::{Selector, SelectorOutput, dummy_waker}; -#[cfg(feature = "futures")] use core::task; +#[cfg(feature = "futures")] +use futures_util::{dummy_waker, Selector, SelectorOutput}; /// Processes background events in a future. /// @@ -635,7 +679,10 @@ pub async fn process_events_async< EventHandlerFuture: core::future::Future, EventHandler: Fn(Event) -> EventHandlerFuture, PS: 'static + Deref + Send, - M: 'static + Deref::EcdsaSigner, CF, T, F, L, P>> + Send + Sync, + M: 'static + + Deref::EcdsaSigner, CF, T, F, L, P>> + + Send + + Sync, CM: 'static + Deref> + Send + Sync, PGS: 'static + Deref> + Send + Sync, RGS: 'static + Deref> + Send, @@ -691,31 +738,48 @@ where } }; define_run_body!( - persister, chain_monitor, + persister, + chain_monitor, chain_monitor.process_pending_events_async(async_event_handler).await, - channel_manager, channel_manager.process_pending_events_async(async_event_handler).await, - peer_manager, process_onion_message_handler_events_async(&peer_manager, async_event_handler).await, - gossip_sync, logger, scorer, should_break, { + channel_manager, + channel_manager.process_pending_events_async(async_event_handler).await, + peer_manager, + process_onion_message_handler_events_async(&peer_manager, async_event_handler).await, + gossip_sync, + logger, + scorer, + should_break, + { let fut = Selector { a: channel_manager.get_event_or_persistence_needed_future(), b: chain_monitor.get_update_future(), - c: sleeper(if mobile_interruptable_platform { Duration::from_millis(100) } else { Duration::from_secs(FASTEST_TIMER) }), + c: sleeper(if mobile_interruptable_platform { + Duration::from_millis(100) + } else { + Duration::from_secs(FASTEST_TIMER) + }), }; match fut.await { - SelectorOutput::A|SelectorOutput::B => {}, + SelectorOutput::A | SelectorOutput::B => {}, SelectorOutput::C(exit) => { should_break = exit; - } + }, } - }, |t| sleeper(Duration::from_secs(t)), + }, + |t| sleeper(Duration::from_secs(t)), |fut: &mut SleepFuture, _| { let mut waker = dummy_waker(); let mut ctx = task::Context::from_waker(&mut waker); match core::pin::Pin::new(fut).poll(&mut ctx) { - task::Poll::Ready(exit) => { should_break = exit; true }, + task::Poll::Ready(exit) => { + should_break = exit; + true + }, task::Poll::Pending => false, } - }, mobile_interruptable_platform, fetch_time, + }, + mobile_interruptable_platform, + fetch_time, ) } @@ -725,9 +789,8 @@ async fn process_onion_message_handler_events_async< EventHandler: Fn(Event) -> EventHandlerFuture, PM: 'static + Deref + Send + Sync, >( - peer_manager: &PM, handler: EventHandler -) -where + peer_manager: &PM, handler: EventHandler, +) where PM::Target: APeerManager + Send + Sync, { let events = core::cell::RefCell::new(Vec::new()); @@ -800,16 +863,22 @@ impl BackgroundProcessor { P: 'static + Deref + Send + Sync, EH: 'static + EventHandler + Send, PS: 'static + Deref + Send, - M: 'static + Deref::EcdsaSigner, CF, T, F, L, P>> + Send + Sync, + M: 'static + + Deref< + Target = ChainMonitor<::EcdsaSigner, CF, T, F, L, P>, + > + + Send + + Sync, CM: 'static + Deref> + Send + Sync, PGS: 'static + Deref> + Send + Sync, RGS: 'static + Deref> + Send, PM: 'static + Deref + Send + Sync, S: 'static + Deref + Send + Sync, - SC: for <'b> WriteableScore<'b>, + SC: for<'b> WriteableScore<'b>, >( persister: PS, event_handler: EH, chain_monitor: M, channel_manager: CM, - gossip_sync: GossipSync, peer_manager: PM, logger: L, scorer: Option, + gossip_sync: GossipSync, peer_manager: PM, logger: L, + scorer: Option, ) -> Self where UL::Target: 'static + UtxoLookup, @@ -836,7 +905,8 @@ impl BackgroundProcessor { } if let Some(ref scorer) = scorer { use std::time::SystemTime; - let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + let duration_since_epoch = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) .expect("Time should be sometime after 1970"); if update_scorer(scorer, &event, duration_since_epoch) { log_trace!(logger, "Persisting scorer after update"); @@ -848,20 +918,34 @@ impl BackgroundProcessor { event_handler.handle_event(event); }; define_run_body!( - persister, chain_monitor, chain_monitor.process_pending_events(&event_handler), - channel_manager, channel_manager.process_pending_events(&event_handler), + persister, + chain_monitor, + chain_monitor.process_pending_events(&event_handler), + channel_manager, + channel_manager.process_pending_events(&event_handler), peer_manager, peer_manager.onion_message_handler().process_pending_events(&event_handler), - gossip_sync, logger, scorer, stop_thread.load(Ordering::Acquire), - { Sleeper::from_two_futures( - channel_manager.get_event_or_persistence_needed_future(), - chain_monitor.get_update_future() - ).wait_timeout(Duration::from_millis(100)); }, - |_| Instant::now(), |time: &Instant, dur| time.elapsed().as_secs() > dur, false, + gossip_sync, + logger, + scorer, + stop_thread.load(Ordering::Acquire), + { + Sleeper::from_two_futures( + channel_manager.get_event_or_persistence_needed_future(), + chain_monitor.get_update_future(), + ) + .wait_timeout(Duration::from_millis(100)); + }, + |_| Instant::now(), + |time: &Instant, dur| time.elapsed().as_secs() > dur, + false, || { use std::time::SystemTime; - Some(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) - .expect("Time should be sometime after 1970")) + Some( + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("Time should be sometime after 1970"), + ) }, ) }); @@ -918,48 +1002,55 @@ impl Drop for BackgroundProcessor { #[cfg(all(feature = "std", test))] mod tests { + use super::{BackgroundProcessor, GossipSync, FRESHNESS_TIMER}; use bitcoin::blockdata::constants::{genesis_block, ChainHash}; use bitcoin::blockdata::locktime::absolute::LockTime; use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::network::constants::Network; - use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1}; - use lightning::chain::{BestBlock, Confirm, chainmonitor}; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use lightning::chain::channelmonitor::ANTI_REORG_DELAY; - use lightning::sign::{InMemorySigner, KeysManager}; use lightning::chain::transaction::OutPoint; - use lightning::events::{Event, PathFailure, MessageSendEventsProvider, MessageSendEvent}; - use lightning::{get_event_msg, get_event}; - use lightning::ln::{PaymentHash, ChannelId}; + use lightning::chain::{chainmonitor, BestBlock, Confirm}; + use lightning::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure}; use lightning::ln::channelmanager; - use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, MIN_CLTV_EXPIRY_DELTA, PaymentId}; + use lightning::ln::channelmanager::{ + ChainParameters, PaymentId, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, + }; use lightning::ln::features::{ChannelFeatures, NodeFeatures}; use lightning::ln::functional_test_utils::*; use lightning::ln::msgs::{ChannelMessageHandler, Init}; - use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler}; + use lightning::ln::peer_handler::{ + IgnoringMessageHandler, MessageHandler, PeerManager, SocketDescriptor, + }; + use lightning::ln::{ChannelId, PaymentHash}; use lightning::routing::gossip::{NetworkGraph, P2PGossipSync}; - use lightning::routing::scoring::{ChannelUsage, ScoreUpdate, ScoreLookUp, LockableScore}; - use lightning::routing::router::{DefaultRouter, Path, RouteHop, CandidateRouteHop}; + use lightning::routing::router::{CandidateRouteHop, DefaultRouter, Path, RouteHop}; + use lightning::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp, ScoreUpdate}; + use lightning::sign::{InMemorySigner, KeysManager}; use lightning::util::config::UserConfig; + use lightning::util::persist::{ + KVStore, CHANNEL_MANAGER_PERSISTENCE_KEY, CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE, + CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_KEY, + NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE, + SCORER_PERSISTENCE_KEY, SCORER_PERSISTENCE_PRIMARY_NAMESPACE, + SCORER_PERSISTENCE_SECONDARY_NAMESPACE, + }; use lightning::util::ser::Writeable; use lightning::util::test_utils; - use lightning::util::persist::{KVStore, - CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_KEY, - NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_KEY, - SCORER_PERSISTENCE_PRIMARY_NAMESPACE, SCORER_PERSISTENCE_SECONDARY_NAMESPACE, SCORER_PERSISTENCE_KEY}; + use lightning::{get_event, get_event_msg}; use lightning_persister::fs_store::FilesystemStore; + use lightning_rapid_gossip_sync::RapidGossipSync; use std::collections::VecDeque; - use std::{fs, env}; use std::path::PathBuf; - use std::sync::{Arc, Mutex}; use std::sync::mpsc::SyncSender; + use std::sync::{Arc, Mutex}; use std::time::Duration; - use lightning_rapid_gossip_sync::RapidGossipSync; - use super::{BackgroundProcessor, GossipSync, FRESHNESS_TIMER}; + use std::{env, fs}; const EVENT_DEADLINE: u64 = 5 * FRESHNESS_TIMER; #[derive(Clone, Hash, PartialEq, Eq)] - struct TestDescriptor{} + struct TestDescriptor {} impl SocketDescriptor for TestDescriptor { fn send_data(&mut self, _data: &[u8], _resume_read: bool) -> usize { 0 @@ -973,33 +1064,63 @@ mod tests { #[cfg(not(c_bindings))] type LockingWrapper = Mutex; - type ChannelManager = - channelmanager::ChannelManager< - Arc, - Arc, - Arc, - Arc, - Arc, - Arc, - Arc, + Arc, + Arc, + Arc, + Arc, + Arc, + Arc< + DefaultRouter< Arc>>, Arc, Arc>, (), - TestScorer> + TestScorer, >, - Arc>; - - type ChainMonitor = chainmonitor::ChainMonitor, Arc, Arc, Arc, Arc>; - - type PGS = Arc>>, Arc, Arc>>; - type RGS = Arc>>, Arc>>; + >, + Arc, + >; + + type ChainMonitor = chainmonitor::ChainMonitor< + InMemorySigner, + Arc, + Arc, + Arc, + Arc, + Arc, + >; + + type PGS = Arc< + P2PGossipSync< + Arc>>, + Arc, + Arc, + >, + >; + type RGS = Arc< + RapidGossipSync< + Arc>>, + Arc, + >, + >; struct Node { node: Arc, p2p_gossip_sync: PGS, rapid_gossip_sync: RGS, - peer_manager: Arc, Arc, IgnoringMessageHandler, Arc, IgnoringMessageHandler, Arc>>, + peer_manager: Arc< + PeerManager< + TestDescriptor, + Arc, + Arc, + IgnoringMessageHandler, + Arc, + IgnoringMessageHandler, + Arc, + >, + >, chain_monitor: Arc, kv_store: Arc, tx_broadcaster: Arc, @@ -1010,15 +1131,39 @@ mod tests { } impl Node { - fn p2p_gossip_sync(&self) -> GossipSync>>, Arc, Arc> { + fn p2p_gossip_sync( + &self, + ) -> GossipSync< + PGS, + RGS, + Arc>>, + Arc, + Arc, + > { GossipSync::P2P(self.p2p_gossip_sync.clone()) } - fn rapid_gossip_sync(&self) -> GossipSync>>, Arc, Arc> { + fn rapid_gossip_sync( + &self, + ) -> GossipSync< + PGS, + RGS, + Arc>>, + Arc, + Arc, + > { GossipSync::Rapid(self.rapid_gossip_sync.clone()) } - fn no_gossip_sync(&self) -> GossipSync>>, Arc, Arc> { + fn no_gossip_sync( + &self, + ) -> GossipSync< + PGS, + RGS, + Arc>>, + Arc, + Arc, + > { GossipSync::None } } @@ -1027,8 +1172,10 @@ mod tests { fn drop(&mut self) { let data_dir = self.kv_store.get_data_dir(); match fs::remove_dir_all(data_dir.clone()) { - Err(e) => println!("Failed to remove test store directory {}: {}", data_dir.display(), e), - _ => {} + Err(e) => { + println!("Failed to remove test store directory {}: {}", data_dir.display(), e) + }, + _ => {}, } } } @@ -1044,7 +1191,13 @@ mod tests { impl Persister { fn new(data_dir: PathBuf) -> Self { let kv_store = FilesystemStore::new(data_dir); - Self { graph_error: None, graph_persistence_notifier: None, manager_error: None, scorer_error: None, kv_store } + Self { + graph_error: None, + graph_persistence_notifier: None, + manager_error: None, + scorer_error: None, + kv_store, + } } fn with_graph_error(self, error: std::io::ErrorKind, message: &'static str) -> Self { @@ -1065,53 +1218,63 @@ mod tests { } impl KVStore for Persister { - fn read(&self, primary_namespace: &str, secondary_namespace: &str, key: &str) -> lightning::io::Result> { + fn read( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, + ) -> lightning::io::Result> { self.kv_store.read(primary_namespace, secondary_namespace, key) } - fn write(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8]) -> lightning::io::Result<()> { - if primary_namespace == CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE && - secondary_namespace == CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE && - key == CHANNEL_MANAGER_PERSISTENCE_KEY + fn write( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8], + ) -> lightning::io::Result<()> { + if primary_namespace == CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE + && secondary_namespace == CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE + && key == CHANNEL_MANAGER_PERSISTENCE_KEY { if let Some((error, message)) = self.manager_error { - return Err(std::io::Error::new(error, message)) + return Err(std::io::Error::new(error, message)); } } - if primary_namespace == NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE && - secondary_namespace == NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE && - key == NETWORK_GRAPH_PERSISTENCE_KEY + if primary_namespace == NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE + && secondary_namespace == NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE + && key == NETWORK_GRAPH_PERSISTENCE_KEY { if let Some(sender) = &self.graph_persistence_notifier { match sender.send(()) { Ok(()) => {}, - Err(std::sync::mpsc::SendError(())) => println!("Persister failed to notify as receiver went away."), + Err(std::sync::mpsc::SendError(())) => { + println!("Persister failed to notify as receiver went away.") + }, } }; if let Some((error, message)) = self.graph_error { - return Err(std::io::Error::new(error, message)) + return Err(std::io::Error::new(error, message)); } } - if primary_namespace == SCORER_PERSISTENCE_PRIMARY_NAMESPACE && - secondary_namespace == SCORER_PERSISTENCE_SECONDARY_NAMESPACE && - key == SCORER_PERSISTENCE_KEY + if primary_namespace == SCORER_PERSISTENCE_PRIMARY_NAMESPACE + && secondary_namespace == SCORER_PERSISTENCE_SECONDARY_NAMESPACE + && key == SCORER_PERSISTENCE_KEY { if let Some((error, message)) = self.scorer_error { - return Err(std::io::Error::new(error, message)) + return Err(std::io::Error::new(error, message)); } } self.kv_store.write(primary_namespace, secondary_namespace, key, buf) } - fn remove(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool) -> lightning::io::Result<()> { + fn remove( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool, + ) -> lightning::io::Result<()> { self.kv_store.remove(primary_namespace, secondary_namespace, key, lazy) } - fn list(&self, primary_namespace: &str, secondary_namespace: &str) -> lightning::io::Result> { + fn list( + &self, primary_namespace: &str, secondary_namespace: &str, + ) -> lightning::io::Result> { self.kv_store.list(primary_namespace, secondary_namespace) } } @@ -1139,18 +1302,27 @@ mod tests { } impl lightning::util::ser::Writeable for TestScorer { - fn write(&self, _: &mut W) -> Result<(), lightning::io::Error> { Ok(()) } + fn write( + &self, _: &mut W, + ) -> Result<(), lightning::io::Error> { + Ok(()) + } } impl ScoreLookUp for TestScorer { type ScoreParams = (); fn channel_penalty_msat( - &self, _candidate: &CandidateRouteHop, _usage: ChannelUsage, _score_params: &Self::ScoreParams - ) -> u64 { unimplemented!(); } + &self, _candidate: &CandidateRouteHop, _usage: ChannelUsage, + _score_params: &Self::ScoreParams, + ) -> u64 { + unimplemented!(); + } } impl ScoreUpdate for TestScorer { - fn payment_path_failed(&mut self, actual_path: &Path, actual_short_channel_id: u64, _: Duration) { + fn payment_path_failed( + &mut self, actual_path: &Path, actual_short_channel_id: u64, _: Duration, + ) { if let Some(expectations) = &mut self.event_expectations { match expectations.pop_front().unwrap() { TestResult::PaymentFailure { path, short_channel_id } => { @@ -1165,7 +1337,7 @@ mod tests { }, TestResult::ProbeSuccess { path } => { panic!("Unexpected probe success: {:?}", path) - } + }, } } } @@ -1184,7 +1356,7 @@ mod tests { }, TestResult::ProbeSuccess { path } => { panic!("Unexpected probe success: {:?}", path) - } + }, } } } @@ -1203,7 +1375,7 @@ mod tests { }, TestResult::ProbeSuccess { path } => { panic!("Unexpected probe success: {:?}", path) - } + }, } } } @@ -1221,7 +1393,7 @@ mod tests { }, TestResult::ProbeSuccess { path } => { assert_eq!(actual_path, &path); - } + }, } } } @@ -1258,41 +1430,111 @@ mod tests { let mut nodes = Vec::new(); for i in 0..num_nodes { let tx_broadcaster = Arc::new(test_utils::TestBroadcaster::new(network)); - let fee_estimator = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }); + let fee_estimator = + Arc::new(test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }); let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i))); let genesis_block = genesis_block(network); let network_graph = Arc::new(NetworkGraph::new(network, logger.clone())); let scorer = Arc::new(LockingWrapper::new(TestScorer::new())); let seed = [i as u8; 32]; - let router = Arc::new(DefaultRouter::new(network_graph.clone(), logger.clone(), seed, scorer.clone(), Default::default())); + let router = Arc::new(DefaultRouter::new( + network_graph.clone(), + logger.clone(), + seed, + scorer.clone(), + Default::default(), + )); let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Bitcoin)); - let kv_store = Arc::new(FilesystemStore::new(format!("{}_persister_{}", &persist_dir, i).into())); + let kv_store = + Arc::new(FilesystemStore::new(format!("{}_persister_{}", &persist_dir, i).into())); let now = Duration::from_secs(genesis_block.header.time as u64); let keys_manager = Arc::new(KeysManager::new(&seed, now.as_secs(), now.subsec_nanos())); - let chain_monitor = Arc::new(chainmonitor::ChainMonitor::new(Some(chain_source.clone()), tx_broadcaster.clone(), logger.clone(), fee_estimator.clone(), kv_store.clone())); + let chain_monitor = Arc::new(chainmonitor::ChainMonitor::new( + Some(chain_source.clone()), + tx_broadcaster.clone(), + logger.clone(), + fee_estimator.clone(), + kv_store.clone(), + )); let best_block = BestBlock::from_network(network); let params = ChainParameters { network, best_block }; - let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster.clone(), router.clone(), logger.clone(), keys_manager.clone(), keys_manager.clone(), keys_manager.clone(), UserConfig::default(), params, genesis_block.header.time)); - let p2p_gossip_sync = Arc::new(P2PGossipSync::new(network_graph.clone(), Some(chain_source.clone()), logger.clone())); - let rapid_gossip_sync = Arc::new(RapidGossipSync::new(network_graph.clone(), logger.clone())); + let manager = Arc::new(ChannelManager::new( + fee_estimator.clone(), + chain_monitor.clone(), + tx_broadcaster.clone(), + router.clone(), + logger.clone(), + keys_manager.clone(), + keys_manager.clone(), + keys_manager.clone(), + UserConfig::default(), + params, + genesis_block.header.time, + )); + let p2p_gossip_sync = Arc::new(P2PGossipSync::new( + network_graph.clone(), + Some(chain_source.clone()), + logger.clone(), + )); + let rapid_gossip_sync = + Arc::new(RapidGossipSync::new(network_graph.clone(), logger.clone())); let msg_handler = MessageHandler { - chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet))), + chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new( + ChainHash::using_genesis_block(Network::Testnet), + )), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()), - onion_message_handler: IgnoringMessageHandler{}, custom_message_handler: IgnoringMessageHandler{} + onion_message_handler: IgnoringMessageHandler {}, + custom_message_handler: IgnoringMessageHandler {}, + }; + let peer_manager = Arc::new(PeerManager::new( + msg_handler, + 0, + &seed, + logger.clone(), + keys_manager.clone(), + )); + let node = Node { + node: manager, + p2p_gossip_sync, + rapid_gossip_sync, + peer_manager, + chain_monitor, + kv_store, + tx_broadcaster, + network_graph, + logger, + best_block, + scorer, }; - let peer_manager = Arc::new(PeerManager::new(msg_handler, 0, &seed, logger.clone(), keys_manager.clone())); - let node = Node { node: manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, kv_store, tx_broadcaster, network_graph, logger, best_block, scorer }; nodes.push(node); } for i in 0..num_nodes { - for j in (i+1)..num_nodes { - nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &Init { - features: nodes[j].node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); - nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &Init { - features: nodes[i].node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + for j in (i + 1)..num_nodes { + nodes[i] + .node + .peer_connected( + &nodes[j].node.get_our_node_id(), + &Init { + features: nodes[j].node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); + nodes[j] + .node + .peer_connected( + &nodes[i].node.get_our_node_id(), + &Init { + features: nodes[i].node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); } } @@ -1304,39 +1546,90 @@ mod tests { begin_open_channel!($node_a, $node_b, $channel_value); let events = $node_a.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); - let (temporary_channel_id, tx) = handle_funding_generation_ready!(events[0], $channel_value); - $node_a.node.funding_transaction_generated(&temporary_channel_id, &$node_b.node.get_our_node_id(), tx.clone()).unwrap(); - $node_b.node.handle_funding_created(&$node_a.node.get_our_node_id(), &get_event_msg!($node_a, MessageSendEvent::SendFundingCreated, $node_b.node.get_our_node_id())); + let (temporary_channel_id, tx) = + handle_funding_generation_ready!(events[0], $channel_value); + $node_a + .node + .funding_transaction_generated( + &temporary_channel_id, + &$node_b.node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); + $node_b.node.handle_funding_created( + &$node_a.node.get_our_node_id(), + &get_event_msg!( + $node_a, + MessageSendEvent::SendFundingCreated, + $node_b.node.get_our_node_id() + ), + ); get_event!($node_b, Event::ChannelPending); - $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() + ), + ); get_event!($node_a, Event::ChannelPending); tx - }} + }}; } macro_rules! begin_open_channel { ($node_a: expr, $node_b: expr, $channel_value: expr) => {{ - $node_a.node.create_channel($node_b.node.get_our_node_id(), $channel_value, 100, 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 + .create_channel($node_b.node.get_our_node_id(), $channel_value, 100, 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() + ), + ); + }}; } macro_rules! handle_funding_generation_ready { ($event: expr, $channel_value: expr) => {{ match $event { - Event::FundingGenerationReady { temporary_channel_id, channel_value_satoshis, ref output_script, user_channel_id, .. } => { + Event::FundingGenerationReady { + temporary_channel_id, + channel_value_satoshis, + ref output_script, + user_channel_id, + .. + } => { assert_eq!(channel_value_satoshis, $channel_value); assert_eq!(user_channel_id, 42); - let tx = Transaction { version: 1 as i32, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: channel_value_satoshis, script_pubkey: output_script.clone(), - }]}; + let tx = Transaction { + version: 1 as i32, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { + value: channel_value_satoshis, + script_pubkey: output_script.clone(), + }], + }; (temporary_channel_id, tx) }, _ => panic!("Unexpected event"), } - }} + }}; } fn confirm_transaction_depth(node: &mut Node, tx: &Transaction, depth: u32) { @@ -1379,7 +1672,16 @@ mod tests { let data_dir = nodes[0].kv_store.get_data_dir(); let persister = Arc::new(Persister::new(data_dir)); let event_handler = |_: _| {}; - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].p2p_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].p2p_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); macro_rules! check_persisted_data { ($node: expr, $filepath: expr) => { @@ -1387,47 +1689,58 @@ mod tests { loop { expected_bytes.clear(); match $node.write(&mut expected_bytes) { - Ok(()) => { - match std::fs::read($filepath) { - Ok(bytes) => { - if bytes == expected_bytes { - break - } else { - continue - } - }, - Err(_) => continue - } + Ok(()) => match std::fs::read($filepath) { + Ok(bytes) => { + if bytes == expected_bytes { + break; + } else { + continue; + } + }, + Err(_) => continue, }, - Err(e) => panic!("Unexpected error: {}", e) + Err(e) => panic!("Unexpected error: {}", e), } } - } + }; } // Check that the initial channel manager data is persisted as expected. - let filepath = get_full_filepath(format!("{}_persister_0", &persist_dir), "manager".to_string()); + let filepath = + get_full_filepath(format!("{}_persister_0", &persist_dir), "manager".to_string()); check_persisted_data!(nodes[0].node, filepath.clone()); loop { - if !nodes[0].node.get_event_or_persist_condvar_value() { break } + if !nodes[0].node.get_event_or_persist_condvar_value() { + break; + } } // Force-close the channel. - nodes[0].node.force_close_broadcasting_latest_txn(&ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.txid(), index: 0 }), &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.txid(), index: 0 }), + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); // Check that the force-close updates are persisted. check_persisted_data!(nodes[0].node, filepath.clone()); loop { - if !nodes[0].node.get_event_or_persist_condvar_value() { break } + if !nodes[0].node.get_event_or_persist_condvar_value() { + break; + } } // Check network graph is persisted - let filepath = get_full_filepath(format!("{}_persister_0", &persist_dir), "network_graph".to_string()); + let filepath = + get_full_filepath(format!("{}_persister_0", &persist_dir), "network_graph".to_string()); check_persisted_data!(nodes[0].network_graph, filepath.clone()); // Check scorer is persisted - let filepath = get_full_filepath(format!("{}_persister_0", &persist_dir), "scorer".to_string()); + let filepath = + get_full_filepath(format!("{}_persister_0", &persist_dir), "scorer".to_string()); check_persisted_data!(nodes[0].scorer, filepath.clone()); if !std::thread::panicking() { @@ -1446,18 +1759,28 @@ mod tests { let data_dir = nodes[0].kv_store.get_data_dir(); let persister = Arc::new(Persister::new(data_dir)); let event_handler = |_: _| {}; - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); loop { let log_entries = nodes[0].logger.lines.lock().unwrap(); let desired_log_1 = "Calling ChannelManager's timer_tick_occurred".to_string(); let desired_log_2 = "Calling PeerManager's timer_tick_occurred".to_string(); let desired_log_3 = "Rebroadcasting monitor's pending claims".to_string(); let desired_log_4 = "Calling OnionMessageHandler's timer_tick_occurred".to_string(); - if log_entries.get(&("lightning_background_processor", desired_log_1)).is_some() && - log_entries.get(&("lightning_background_processor", desired_log_2)).is_some() && - log_entries.get(&("lightning_background_processor", desired_log_3)).is_some() && - log_entries.get(&("lightning_background_processor", desired_log_4)).is_some() { - break + if log_entries.get(&("lightning_background_processor", desired_log_1)).is_some() + && log_entries.get(&("lightning_background_processor", desired_log_2)).is_some() + && log_entries.get(&("lightning_background_processor", desired_log_3)).is_some() + && log_entries.get(&("lightning_background_processor", desired_log_4)).is_some() + { + break; } } @@ -1473,9 +1796,20 @@ mod tests { open_channel!(nodes[0], nodes[1], 100000); let data_dir = nodes[0].kv_store.get_data_dir(); - let persister = Arc::new(Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test")); + let persister = Arc::new( + Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test"), + ); let event_handler = |_: _| {}; - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); match bg_processor.join() { Ok(_) => panic!("Expected error persisting manager"), Err(e) => { @@ -1493,17 +1827,27 @@ mod tests { open_channel!(nodes[0], nodes[1], 100000); let data_dir = nodes[0].kv_store.get_data_dir(); - let persister = Arc::new(Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test")); + let persister = Arc::new( + Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test"), + ); let bp_future = super::process_events_async( - persister, |_: _| {async {}}, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), - nodes[0].rapid_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), - Some(nodes[0].scorer.clone()), move |dur: Duration| { + persister, + |_: _| async {}, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].rapid_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + move |dur: Duration| { Box::pin(async move { tokio::time::sleep(dur).await; false // Never exit }) - }, false, || Some(Duration::ZERO), + }, + false, + || Some(Duration::ZERO), ); match bp_future.await { Ok(_) => panic!("Expected error persisting manager"), @@ -1519,9 +1863,19 @@ mod tests { // Test that if we encounter an error during network graph persistence, an error gets returned. let (_, nodes) = create_nodes(2, "test_persist_network_graph_error"); let data_dir = nodes[0].kv_store.get_data_dir(); - let persister = Arc::new(Persister::new(data_dir).with_graph_error(std::io::ErrorKind::Other, "test")); + let persister = + Arc::new(Persister::new(data_dir).with_graph_error(std::io::ErrorKind::Other, "test")); let event_handler = |_: _| {}; - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].p2p_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].p2p_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); match bg_processor.stop() { Ok(_) => panic!("Expected error persisting network graph"), @@ -1537,9 +1891,19 @@ mod tests { // Test that if we encounter an error during scorer persistence, an error gets returned. let (_, nodes) = create_nodes(2, "test_persist_scorer_error"); let data_dir = nodes[0].kv_store.get_data_dir(); - let persister = Arc::new(Persister::new(data_dir).with_scorer_error(std::io::ErrorKind::Other, "test")); + let persister = + Arc::new(Persister::new(data_dir).with_scorer_error(std::io::ErrorKind::Other, "test")); let event_handler = |_: _| {}; - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); match bg_processor.stop() { Ok(_) => panic!("Expected error persisting scorer"), @@ -1561,35 +1925,84 @@ mod tests { let (funding_generation_send, funding_generation_recv) = std::sync::mpsc::sync_channel(1); let (channel_pending_send, channel_pending_recv) = std::sync::mpsc::sync_channel(1); let event_handler = move |event: Event| match event { - Event::FundingGenerationReady { .. } => funding_generation_send.send(handle_funding_generation_ready!(event, channel_value)).unwrap(), + Event::FundingGenerationReady { .. } => funding_generation_send + .send(handle_funding_generation_ready!(event, channel_value)) + .unwrap(), Event::ChannelPending { .. } => channel_pending_send.send(()).unwrap(), Event::ChannelReady { .. } => {}, _ => panic!("Unexpected event: {:?}", event), }; - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); // Open a channel and check that the FundingGenerationReady event was handled. begin_open_channel!(nodes[0], nodes[1], channel_value); let (temporary_channel_id, funding_tx) = funding_generation_recv .recv_timeout(Duration::from_secs(EVENT_DEADLINE)) .expect("FundingGenerationReady not handled within deadline"); - nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), funding_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(), + funding_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() + ), + ); get_event!(nodes[1], Event::ChannelPending); - 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())); - let _ = channel_pending_recv.recv_timeout(Duration::from_secs(EVENT_DEADLINE)) + 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() + ), + ); + let _ = channel_pending_recv + .recv_timeout(Duration::from_secs(EVENT_DEADLINE)) .expect("ChannelPending not handled within deadline"); // Confirm the funding transaction. confirm_transaction(&mut nodes[0], &funding_tx); - let as_funding = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); + let as_funding = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ); confirm_transaction(&mut nodes[1], &funding_tx); - let bs_funding = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id()); + let bs_funding = 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(), &bs_funding); - 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() + ); nodes[1].node.handle_channel_ready(&nodes[0].node.get_our_node_id(), &as_funding); - 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() + ); if !std::thread::panicking() { bg_processor.stop().unwrap(); @@ -1604,10 +2017,25 @@ mod tests { _ => panic!("Unexpected event: {:?}", event), }; let persister = Arc::new(Persister::new(data_dir)); - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); // Force close the channel and check that the SpendableOutputs event was handled. - nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); let commitment_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().pop().unwrap(); confirm_transaction_depth(&mut nodes[0], &commitment_tx, BREAKDOWN_TIMEOUT as u32); @@ -1630,13 +2058,22 @@ mod tests { let data_dir = nodes[0].kv_store.get_data_dir(); let persister = Arc::new(Persister::new(data_dir)); let event_handler = |_: _| {}; - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); loop { let log_entries = nodes[0].logger.lines.lock().unwrap(); let expected_log = "Calling time_passed and persisting scorer".to_string(); if log_entries.get(&("lightning_background_processor", expected_log)).is_some() { - break + break; } } @@ -1648,9 +2085,16 @@ mod tests { macro_rules! do_test_not_pruning_network_graph_until_graph_sync_completion { ($nodes: expr, $receive: expr, $sleep: expr) => { let features = ChannelFeatures::empty(); - $nodes[0].network_graph.add_channel_from_partial_announcement( - 42, 53, features, $nodes[0].node.get_our_node_id(), $nodes[1].node.get_our_node_id() - ).expect("Failed to update channel from partial announcement"); + $nodes[0] + .network_graph + .add_channel_from_partial_announcement( + 42, + 53, + features, + $nodes[0].node.get_our_node_id(), + $nodes[1].node.get_our_node_id(), + ) + .expect("Failed to update channel from partial announcement"); let original_graph_description = $nodes[0].network_graph.to_string(); assert!(original_graph_description.contains("42: features: 0000, node_one:")); assert_eq!($nodes[0].network_graph.read_only().channels().len(), 1); @@ -1659,30 +2103,34 @@ mod tests { $sleep; let log_entries = $nodes[0].logger.lines.lock().unwrap(); let loop_counter = "Calling ChannelManager's timer_tick_occurred".to_string(); - if *log_entries.get(&("lightning_background_processor", loop_counter)) - .unwrap_or(&0) > 1 + if *log_entries.get(&("lightning_background_processor", loop_counter)).unwrap_or(&0) + > 1 { // Wait until the loop has gone around at least twice. - break + break; } } let initialization_input = vec![ - 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, - 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218, - 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251, - 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125, - 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136, - 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106, - 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138, - 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175, - 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128, - 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68, - 226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 2, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232, - 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 25, 0, 0, - 0, 1, 0, 0, 0, 125, 255, 2, 68, 226, 0, 6, 11, 0, 1, 5, 0, 0, 0, 0, 29, 129, 25, 192, + 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, + 247, 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, + 98, 218, 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, + 250, 251, 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, + 67, 2, 36, 125, 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, + 115, 172, 63, 136, 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, + 1, 242, 121, 152, 106, 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, + 65, 3, 83, 185, 58, 138, 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, + 149, 185, 226, 156, 137, 175, 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, + 175, 168, 77, 4, 143, 38, 128, 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, + 27, 0, 0, 0, 1, 0, 0, 255, 2, 68, 226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 2, 0, 40, 0, + 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232, 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, + 8, 153, 192, 0, 2, 27, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 125, 255, 2, 68, 226, 0, 6, + 11, 0, 1, 5, 0, 0, 0, 0, 29, 129, 25, 192, ]; - $nodes[0].rapid_gossip_sync.update_network_graph_no_std(&initialization_input[..], Some(1642291930)).unwrap(); + $nodes[0] + .rapid_gossip_sync + .update_network_graph_no_std(&initialization_input[..], Some(1642291930)) + .unwrap(); // this should have added two channels and pruned the previous one. assert_eq!($nodes[0].network_graph.read_only().channels().len(), 2); @@ -1691,23 +2139,35 @@ mod tests { // all channels should now be pruned assert_eq!($nodes[0].network_graph.read_only().channels().len(), 0); - } + }; } #[test] fn test_not_pruning_network_graph_until_graph_sync_completion() { let (sender, receiver) = std::sync::mpsc::sync_channel(1); - let (_, nodes) = create_nodes(2, "test_not_pruning_network_graph_until_graph_sync_completion"); + let (_, nodes) = + create_nodes(2, "test_not_pruning_network_graph_until_graph_sync_completion"); let data_dir = nodes[0].kv_store.get_data_dir(); let persister = Arc::new(Persister::new(data_dir).with_graph_persistence_notifier(sender)); let event_handler = |_: _| {}; - let background_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].rapid_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let background_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].rapid_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); - do_test_not_pruning_network_graph_until_graph_sync_completion!(nodes, + do_test_not_pruning_network_graph_until_graph_sync_completion!( + nodes, receiver.recv_timeout(Duration::from_secs(super::FIRST_NETWORK_PRUNE_TIMER * 5)), - std::thread::sleep(Duration::from_millis(1))); + std::thread::sleep(Duration::from_millis(1)) + ); background_processor.stop().unwrap(); } @@ -1717,15 +2177,22 @@ mod tests { async fn test_not_pruning_network_graph_until_graph_sync_completion_async() { let (sender, receiver) = std::sync::mpsc::sync_channel(1); - let (_, nodes) = create_nodes(2, "test_not_pruning_network_graph_until_graph_sync_completion_async"); + let (_, nodes) = + create_nodes(2, "test_not_pruning_network_graph_until_graph_sync_completion_async"); let data_dir = nodes[0].kv_store.get_data_dir(); let persister = Arc::new(Persister::new(data_dir).with_graph_persistence_notifier(sender)); let (exit_sender, exit_receiver) = tokio::sync::watch::channel(()); let bp_future = super::process_events_async( - persister, |_: _| {async {}}, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), - nodes[0].rapid_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), - Some(nodes[0].scorer.clone()), move |dur: Duration| { + persister, + |_: _| async {}, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].rapid_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + move |dur: Duration| { let mut exit_receiver = exit_receiver.clone(); Box::pin(async move { tokio::select! { @@ -1733,20 +2200,29 @@ mod tests { _ = exit_receiver.changed() => true, } }) - }, false, || Some(Duration::from_secs(1696300000)), + }, + false, + || Some(Duration::from_secs(1696300000)), ); let t1 = tokio::spawn(bp_future); let t2 = tokio::spawn(async move { - do_test_not_pruning_network_graph_until_graph_sync_completion!(nodes, { - let mut i = 0; - loop { - tokio::time::sleep(Duration::from_secs(super::FIRST_NETWORK_PRUNE_TIMER)).await; - if let Ok(()) = receiver.try_recv() { break Ok::<(), ()>(()); } - assert!(i < 5); - i += 1; - } - }, tokio::time::sleep(Duration::from_millis(1)).await); + do_test_not_pruning_network_graph_until_graph_sync_completion!( + nodes, + { + let mut i = 0; + loop { + tokio::time::sleep(Duration::from_secs(super::FIRST_NETWORK_PRUNE_TIMER)) + .await; + if let Ok(()) = receiver.try_recv() { + break Ok::<(), ()>(()); + } + assert!(i < 5); + i += 1; + } + }, + tokio::time::sleep(Duration::from_millis(1)).await + ); exit_sender.send(()).unwrap(); }); let (r1, r2) = tokio::join!(t1, t2); @@ -1861,9 +2337,21 @@ mod tests { let (_, nodes) = create_nodes(1, "test_payment_path_scoring"); let data_dir = nodes[0].kv_store.get_data_dir(); let persister = Arc::new(Persister::new(data_dir)); - let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), Some(nodes[0].scorer.clone())); + let bg_processor = BackgroundProcessor::start( + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + ); - do_test_payment_path_scoring!(nodes, receiver.recv_timeout(Duration::from_secs(EVENT_DEADLINE))); + do_test_payment_path_scoring!( + nodes, + receiver.recv_timeout(Duration::from_secs(EVENT_DEADLINE)) + ); if !std::thread::panicking() { bg_processor.stop().unwrap(); @@ -1882,10 +2370,10 @@ mod tests { let sender_ref = sender.clone(); async move { match event { - Event::PaymentPathFailed { .. } => { sender_ref.send(event).await.unwrap() }, - Event::PaymentPathSuccessful { .. } => { sender_ref.send(event).await.unwrap() }, - Event::ProbeSuccessful { .. } => { sender_ref.send(event).await.unwrap() }, - Event::ProbeFailed { .. } => { sender_ref.send(event).await.unwrap() }, + Event::PaymentPathFailed { .. } => sender_ref.send(event).await.unwrap(), + Event::PaymentPathSuccessful { .. } => sender_ref.send(event).await.unwrap(), + Event::ProbeSuccessful { .. } => sender_ref.send(event).await.unwrap(), + Event::ProbeFailed { .. } => sender_ref.send(event).await.unwrap(), _ => panic!("Unexpected event: {:?}", event), } } @@ -1898,9 +2386,15 @@ mod tests { let (exit_sender, exit_receiver) = tokio::sync::watch::channel(()); let bp_future = super::process_events_async( - persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), - nodes[0].no_gossip_sync(), nodes[0].peer_manager.clone(), nodes[0].logger.clone(), - Some(nodes[0].scorer.clone()), move |dur: Duration| { + persister, + event_handler, + nodes[0].chain_monitor.clone(), + nodes[0].node.clone(), + nodes[0].no_gossip_sync(), + nodes[0].peer_manager.clone(), + nodes[0].logger.clone(), + Some(nodes[0].scorer.clone()), + move |dur: Duration| { let mut exit_receiver = exit_receiver.clone(); Box::pin(async move { tokio::select! { @@ -1908,7 +2402,9 @@ mod tests { _ = exit_receiver.changed() => true, } }) - }, false, || Some(Duration::ZERO), + }, + false, + || Some(Duration::ZERO), ); let t1 = tokio::spawn(bp_future); let t2 = tokio::spawn(async move { @@ -1917,7 +2413,10 @@ mod tests { let log_entries = nodes[0].logger.lines.lock().unwrap(); let expected_log = "Persisting scorer after update".to_string(); - assert_eq!(*log_entries.get(&("lightning_background_processor", expected_log)).unwrap(), 5); + assert_eq!( + *log_entries.get(&("lightning_background_processor", expected_log)).unwrap(), + 5 + ); }); let (r1, r2) = tokio::join!(t1, t2); diff --git a/lightning-block-sync/src/convert.rs b/lightning-block-sync/src/convert.rs index ed811d2cc0c..a59ccbd768d 100644 --- a/lightning-block-sync/src/convert.rs +++ b/lightning-block-sync/src/convert.rs @@ -10,15 +10,17 @@ use bitcoin::Transaction; use serde_json; +use bitcoin::hashes::Hash; use std::convert::From; use std::convert::TryFrom; use std::convert::TryInto; use std::str::FromStr; -use bitcoin::hashes::Hash; impl TryInto for JsonResponse { type Error = std::io::Error; - fn try_into(self) -> Result { Ok(self.0) } + fn try_into(self) -> Result { + Ok(self.0) + } } /// Conversion from `std::io::Error` into `BlockSourceError`. @@ -38,7 +40,12 @@ impl TryInto for BinaryResponse { fn try_into(self) -> std::io::Result { match encode::deserialize(&self.0) { - Err(_) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid block data")), + Err(_) => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid block data", + )) + }, Ok(block) => Ok(block), } } @@ -49,9 +56,9 @@ impl TryInto for BinaryResponse { type Error = std::io::Error; fn try_into(self) -> std::io::Result { - BlockHash::from_slice(&self.0).map_err(|_| + BlockHash::from_slice(&self.0).map_err(|_| { std::io::Error::new(std::io::ErrorKind::InvalidData, "bad block hash length") - ) + }) } } @@ -62,18 +69,30 @@ impl TryInto for JsonResponse { fn try_into(self) -> std::io::Result { let header = match self.0 { - serde_json::Value::Array(mut array) if !array.is_empty() => array.drain(..).next().unwrap(), + serde_json::Value::Array(mut array) if !array.is_empty() => { + array.drain(..).next().unwrap() + }, serde_json::Value::Object(_) => self.0, - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "unexpected JSON type")), + _ => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "unexpected JSON type", + )) + }, }; if !header.is_object() { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON object")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected JSON object", + )); } // Add an empty previousblockhash for the genesis block. match header.try_into() { - Err(_) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid header data")), + Err(_) => { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid header data")) + }, Ok(header) => Ok(header), } } @@ -83,23 +102,28 @@ impl TryFrom for BlockHeaderData { type Error = (); fn try_from(response: serde_json::Value) -> Result { - macro_rules! get_field { ($name: expr, $ty_access: tt) => { - response.get($name).ok_or(())?.$ty_access().ok_or(())? - } } + macro_rules! get_field { + ($name: expr, $ty_access: tt) => { + response.get($name).ok_or(())?.$ty_access().ok_or(())? + }; + } Ok(BlockHeaderData { header: Header { version: bitcoin::blockdata::block::Version::from_consensus( - get_field!("version", as_i64).try_into().map_err(|_| ())? + get_field!("version", as_i64).try_into().map_err(|_| ())?, ), prev_blockhash: if let Some(hash_str) = response.get("previousblockhash") { - BlockHash::from_str(hash_str.as_str().ok_or(())?).map_err(|_| ())? - } else { BlockHash::all_zeros() }, - merkle_root: TxMerkleNode::from_str(get_field!("merkleroot", as_str)).map_err(|_| ())?, + BlockHash::from_str(hash_str.as_str().ok_or(())?).map_err(|_| ())? + } else { + BlockHash::all_zeros() + }, + merkle_root: TxMerkleNode::from_str(get_field!("merkleroot", as_str)) + .map_err(|_| ())?, time: get_field!("time", as_u64).try_into().map_err(|_| ())?, - bits: bitcoin::CompactTarget::from_consensus( - u32::from_be_bytes(<[u8; 4]>::from_hex(get_field!("bits", as_str)).map_err(|_| ())?) - ), + bits: bitcoin::CompactTarget::from_consensus(u32::from_be_bytes( + <[u8; 4]>::from_hex(get_field!("bits", as_str)).map_err(|_| ())?, + )), nonce: get_field!("nonce", as_u64).try_into().map_err(|_| ())?, }, chainwork: hex_to_work(get_field!("chainwork", as_str)).map_err(|_| ())?, @@ -114,11 +138,18 @@ impl TryInto for JsonResponse { fn try_into(self) -> std::io::Result { match self.0.as_str() { - None => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")), + None => { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")) + }, Some(hex_data) => match Vec::::from_hex(hex_data) { - Err(_) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")), + Err(_) => { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")) + }, Ok(block_data) => match encode::deserialize(&block_data) { - Err(_) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid block data")), + Err(_) => Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid block data", + )), Ok(block) => Ok(block), }, }, @@ -132,27 +163,55 @@ impl TryInto<(BlockHash, Option)> for JsonResponse { fn try_into(self) -> std::io::Result<(BlockHash, Option)> { if !self.0.is_object() { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON object")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected JSON object", + )); } let hash = match &self.0["bestblockhash"] { serde_json::Value::String(hex_data) => match BlockHash::from_str(&hex_data) { - Err(_) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")), + Err(_) => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid hex data", + )) + }, Ok(block_hash) => block_hash, }, - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")), + _ => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected JSON string", + )) + }, }; let height = match &self.0["blocks"] { serde_json::Value::Null => None, serde_json::Value::Number(height) => match height.as_u64() { - None => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid height")), + None => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid height", + )) + }, Some(height) => match height.try_into() { - Err(_) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid height")), + Err(_) => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid height", + )) + }, Ok(height) => Some(height), - } + }, + }, + _ => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected JSON number", + )) }, - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON number")), }; Ok((hash, height)) @@ -162,8 +221,12 @@ impl TryInto<(BlockHash, Option)> for JsonResponse { impl TryInto for JsonResponse { type Error = std::io::Error; fn try_into(self) -> std::io::Result { - let hex_data = self.0.as_str().ok_or(Self::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string" ))?; - Txid::from_str(hex_data).map_err(|err|Self::Error::new(std::io::ErrorKind::InvalidData, err.to_string() )) + let hex_data = self + .0 + .as_str() + .ok_or(Self::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string"))?; + Txid::from_str(hex_data) + .map_err(|err| Self::Error::new(std::io::ErrorKind::InvalidData, err.to_string())) } } @@ -192,14 +255,16 @@ impl TryInto for JsonResponse { } else { hex_data } - } + }, // result is a complete transaction (e.g. getrawtranaction verbose) _ => hex_data, }, - _ => return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "expected JSON string", - )), + _ => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected JSON string", + )) + }, } } else { // result is plain text (e.g. getrawtransaction no verbose) @@ -210,20 +275,16 @@ impl TryInto for JsonResponse { std::io::ErrorKind::InvalidData, "expected JSON string", )) - } + }, } }; match Vec::::from_hex(hex_tx) { - Err(_) => Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "invalid hex data", - )), + Err(_) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")), Ok(tx_data) => match encode::deserialize(&tx_data) { - Err(_) => Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "invalid transaction", - )), + Err(_) => { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid transaction")) + }, Ok(tx) => Ok(tx), }, } @@ -235,11 +296,15 @@ impl TryInto for JsonResponse { fn try_into(self) -> std::io::Result { match self.0.as_str() { - None => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")), - Some(hex_data) if hex_data.len() != 64 => - Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hash length")), - Some(hex_data) => BlockHash::from_str(hex_data) - .map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data")), + None => { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON string")) + }, + Some(hex_data) if hex_data.len() != 64 => { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hash length")) + }, + Some(hex_data) => BlockHash::from_str(hex_data).map_err(|_| { + std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid hex data") + }), } } } @@ -249,7 +314,7 @@ impl TryInto for JsonResponse { /// that. #[cfg(feature = "rest-client")] pub(crate) struct GetUtxosResponse { - pub(crate) hit_bitmap_nonempty: bool + pub(crate) hit_bitmap_nonempty: bool, } #[cfg(feature = "rest-client")] @@ -257,18 +322,27 @@ impl TryInto for JsonResponse { type Error = std::io::Error; fn try_into(self) -> std::io::Result { - let bitmap_str = - self.0.as_object().ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected an object"))? - .get("bitmap").ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "missing bitmap field"))? - .as_str().ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "bitmap should be an str"))?; - let mut hit_bitmap_nonempty = false; - for c in bitmap_str.chars() { - if c < '0' || c > '9' { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid byte")); - } - if c > '0' { hit_bitmap_nonempty = true; } + let bitmap_str = self + .0 + .as_object() + .ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected an object"))? + .get("bitmap") + .ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "missing bitmap field"))? + .as_str() + .ok_or(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "bitmap should be an str", + ))?; + let mut hit_bitmap_nonempty = false; + for c in bitmap_str.chars() { + if c < '0' || c > '9' { + return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid byte")); } - Ok(GetUtxosResponse { hit_bitmap_nonempty }) + if c > '0' { + hit_bitmap_nonempty = true; + } + } + Ok(GetUtxosResponse { hit_bitmap_nonempty }) } } @@ -326,11 +400,10 @@ pub(crate) mod tests { #[test] fn into_block_header_from_json_response_with_invalid_header_response() { let block = genesis_block(Network::Bitcoin); - let mut response = JsonResponse(BlockHeaderData { - chainwork: block.header.work(), - height: 0, - header: block.header - }.into()); + let mut response = JsonResponse( + BlockHeaderData { chainwork: block.header.work(), height: 0, header: block.header } + .into(), + ); response.0["chainwork"].take(); match TryInto::::try_into(response) { @@ -345,11 +418,10 @@ pub(crate) mod tests { #[test] fn into_block_header_from_json_response_with_invalid_header_data() { let block = genesis_block(Network::Bitcoin); - let mut response = JsonResponse(BlockHeaderData { - chainwork: block.header.work(), - height: 0, - header: block.header - }.into()); + let mut response = JsonResponse( + BlockHeaderData { chainwork: block.header.work(), height: 0, header: block.header } + .into(), + ); response.0["chainwork"] = serde_json::json!("foobar"); match TryInto::::try_into(response) { @@ -364,11 +436,10 @@ pub(crate) mod tests { #[test] fn into_block_header_from_json_response_with_valid_header() { let block = genesis_block(Network::Bitcoin); - let response = JsonResponse(BlockHeaderData { - chainwork: block.header.work(), - height: 0, - header: block.header - }.into()); + let response = JsonResponse( + BlockHeaderData { chainwork: block.header.work(), height: 0, header: block.header } + .into(), + ); match TryInto::::try_into(response) { Err(e) => panic!("Unexpected error: {:?}", e), @@ -383,18 +454,20 @@ pub(crate) mod tests { #[test] fn into_block_header_from_json_response_with_valid_header_array() { let genesis_block = genesis_block(Network::Bitcoin); - let best_block_header = Header { - prev_blockhash: genesis_block.block_hash(), - ..genesis_block.header - }; + let best_block_header = + Header { prev_blockhash: genesis_block.block_hash(), ..genesis_block.header }; let chainwork = genesis_block.header.work() + best_block_header.work(); let response = JsonResponse(serde_json::json!([ - serde_json::Value::from(BlockHeaderData { - chainwork, height: 1, header: best_block_header, - }), - serde_json::Value::from(BlockHeaderData { - chainwork: genesis_block.header.work(), height: 0, header: genesis_block.header, - }), + serde_json::Value::from(BlockHeaderData { + chainwork, + height: 1, + header: best_block_header, + }), + serde_json::Value::from(BlockHeaderData { + chainwork: genesis_block.header.work(), + height: 0, + header: genesis_block.header, + }), ])); match TryInto::::try_into(response) { @@ -410,11 +483,10 @@ pub(crate) mod tests { #[test] fn into_block_header_from_json_response_without_previous_block_hash() { let block = genesis_block(Network::Bitcoin); - let mut response = JsonResponse(BlockHeaderData { - chainwork: block.header.work(), - height: 0, - header: block.header - }.into()); + let mut response = JsonResponse( + BlockHeaderData { chainwork: block.header.work(), height: 0, header: block.header } + .into(), + ); response.0.as_object_mut().unwrap().remove("previousblockhash"); match TryInto::::try_into(response) { @@ -596,7 +668,7 @@ pub(crate) mod tests { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON string"); - } + }, Ok(_) => panic!("Expected error"), } } @@ -607,8 +679,11 @@ pub(crate) mod tests { match TryInto::::try_into(response) { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); - assert_eq!(e.get_ref().unwrap().to_string(), "bad hex string length 6 (expected 64)"); - } + assert_eq!( + e.get_ref().unwrap().to_string(), + "bad hex string length 6 (expected 64)" + ); + }, Ok(_) => panic!("Expected error"), } } @@ -619,8 +694,11 @@ pub(crate) mod tests { match TryInto::::try_into(response) { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); - assert_eq!(e.get_ref().unwrap().to_string(), "bad hex string length 4 (expected 64)"); - } + assert_eq!( + e.get_ref().unwrap().to_string(), + "bad hex string length 4 (expected 64)" + ); + }, Ok(_) => panic!("Expected error"), } } @@ -638,15 +716,15 @@ pub(crate) mod tests { #[test] fn into_txid_from_bitcoind_rpc_json_response() { let mut rpc_response = serde_json::json!( - {"error": "", "id": "770", "result": "7934f775149929a8b742487129a7c3a535dfb612f0b726cc67bc10bc2628f906"} + {"error": "", "id": "770", "result": "7934f775149929a8b742487129a7c3a535dfb612f0b726cc67bc10bc2628f906"} - ); - let r: std::io::Result = JsonResponse(rpc_response.get_mut("result").unwrap().take()) - .try_into(); - assert_eq!( - r.unwrap().to_string(), - "7934f775149929a8b742487129a7c3a535dfb612f0b726cc67bc10bc2628f906" - ); + ); + let r: std::io::Result = + JsonResponse(rpc_response.get_mut("result").unwrap().take()).try_into(); + assert_eq!( + r.unwrap().to_string(), + "7934f775149929a8b742487129a7c3a535dfb612f0b726cc67bc10bc2628f906" + ); } // TryInto can be used in two ways, first with plain hex response where data is @@ -663,7 +741,7 @@ pub(crate) mod tests { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid hex data"); - } + }, Ok(_) => panic!("Expected error"), } } @@ -675,7 +753,7 @@ pub(crate) mod tests { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON string"); - } + }, Ok(_) => panic!("Expected error"), } } @@ -687,7 +765,7 @@ pub(crate) mod tests { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); assert_eq!(e.get_ref().unwrap().to_string(), "invalid transaction"); - } + }, Ok(_) => panic!("Expected error"), } } @@ -722,11 +800,8 @@ pub(crate) mod tests { match TryInto::::try_into(response) { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); - assert_eq!( - e.get_ref().unwrap().to_string(), - "expected JSON string" - ); - } + assert_eq!(e.get_ref().unwrap().to_string(), "expected JSON string"); + }, Ok(_) => panic!("Expected error"), } } @@ -737,11 +812,12 @@ pub(crate) mod tests { match TryInto::::try_into(response) { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); - assert!( - e.get_ref().unwrap().to_string().contains( - "transaction couldn't be signed") - ); - } + assert!(e + .get_ref() + .unwrap() + .to_string() + .contains("transaction couldn't be signed")); + }, Ok(_) => panic!("Expected error"), } } diff --git a/lightning-block-sync/src/gossip.rs b/lightning-block-sync/src/gossip.rs index 9cd4049679c..67cb3959bc3 100644 --- a/lightning-block-sync/src/gossip.rs +++ b/lightning-block-sync/src/gossip.rs @@ -6,21 +6,21 @@ use crate::{AsyncBlockSourceResult, BlockData, BlockSource, BlockSourceError}; use bitcoin::blockdata::block::Block; use bitcoin::blockdata::constants::ChainHash; -use bitcoin::blockdata::transaction::{TxOut, OutPoint}; +use bitcoin::blockdata::transaction::{OutPoint, TxOut}; use bitcoin::hash_types::BlockHash; use lightning::ln::peer_handler::APeerManager; use lightning::routing::gossip::{NetworkGraph, P2PGossipSync}; -use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoResult, UtxoLookupError}; +use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResult}; use lightning::util::logger::Logger; -use std::sync::{Arc, Mutex}; use std::collections::VecDeque; use std::future::Future; use std::ops::Deref; use std::pin::Pin; +use std::sync::{Arc, Mutex}; use std::task::Poll; /// A trait which extends [`BlockSource`] and can be queried to fetch the block at a given height @@ -29,12 +29,14 @@ use std::task::Poll; /// Note that while this is implementable for a [`BlockSource`] which returns filtered block data /// (i.e. [`BlockData::HeaderOnly`] for [`BlockSource::get_block`] requests), such an /// implementation will reject all gossip as it is not fully able to verify the UTXOs referenced. -pub trait UtxoSource : BlockSource + 'static { +pub trait UtxoSource: BlockSource + 'static { /// Fetches the block hash of the block at the given height. /// /// This will, in turn, be passed to to [`BlockSource::get_block`] to fetch the block needed /// for gossip validation. - fn get_block_hash_by_height<'a>(&'a self, block_height: u32) -> AsyncBlockSourceResult<'a, BlockHash>; + fn get_block_hash_by_height<'a>( + &'a self, block_height: u32, + ) -> AsyncBlockSourceResult<'a, BlockHash>; /// Returns true if the given output has *not* been spent, i.e. is a member of the current UTXO /// set. @@ -45,7 +47,7 @@ pub trait UtxoSource : BlockSource + 'static { /// /// If the `tokio` feature is enabled, this is implemented on `TokioSpawner` struct which /// delegates to `tokio::spawn()`. -pub trait FutureSpawner : Send + Sync + 'static { +pub trait FutureSpawner: Send + Sync + 'static { /// Spawns the given future as a background task. /// /// This method MUST NOT block on the given future immediately. @@ -65,8 +67,8 @@ impl FutureSpawner for TokioSpawner { /// A trivial future which joins two other futures and polls them at the same time, returning only /// once both complete. pub(crate) struct Joiner< - A: Future), BlockSourceError>> + Unpin, - B: Future> + Unpin, + A: Future), BlockSourceError>> + Unpin, + B: Future> + Unpin, > { pub a: A, pub b: B, @@ -75,16 +77,20 @@ pub(crate) struct Joiner< } impl< - A: Future), BlockSourceError>> + Unpin, - B: Future> + Unpin, -> Joiner { - fn new(a: A, b: B) -> Self { Self { a, b, a_res: None, b_res: None } } + A: Future), BlockSourceError>> + Unpin, + B: Future> + Unpin, + > Joiner +{ + fn new(a: A, b: B) -> Self { + Self { a, b, a_res: None, b_res: None } + } } impl< - A: Future), BlockSourceError>> + Unpin, - B: Future> + Unpin, -> Future for Joiner { + A: Future), BlockSourceError>> + Unpin, + B: Future> + Unpin, + > Future for Joiner +{ type Output = Result<((BlockHash, Option), BlockHash), BlockSourceError>; fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll { if self.a_res.is_none() { @@ -107,14 +113,13 @@ impl< } else { return Poll::Ready(Err(res.unwrap_err())); } - }, Poll::Pending => {}, } } if let Some(b_res) = self.b_res { if let Some(a_res) = self.a_res { - return Poll::Ready(Ok((a_res, b_res))) + return Poll::Ready(Ok((a_res, b_res))); } } Poll::Pending @@ -129,7 +134,8 @@ impl< /// value of 1024 should more than suffice), and ensure you have sufficient file descriptors /// available on both Bitcoin Core and your LDK application for each request to hold its own /// connection. -pub struct GossipVerifier where @@ -145,10 +151,9 @@ pub struct GossipVerifier GossipVerifier where +impl + GossipVerifier +where Blocks::Target: UtxoSource, L::Target: Logger, { @@ -157,17 +162,24 @@ impl( - source: Blocks, spawn: S, gossiper: Arc>, Self, L>>, peer_manager: APM - ) -> Self where APM::Target: APeerManager { + source: Blocks, spawn: S, gossiper: Arc>, Self, L>>, + peer_manager: APM, + ) -> Self + where + APM::Target: APeerManager, + { let peer_manager_wake = Arc::new(move || peer_manager.as_ref().process_events()); Self { - source, spawn, gossiper, peer_manager_wake, + source, + spawn, + gossiper, + peer_manager_wake, block_cache: Arc::new(Mutex::new(VecDeque::with_capacity(BLOCK_CACHE_SIZE))), } } async fn retrieve_utxo( - source: Blocks, block_cache: Arc>>, short_channel_id: u64 + source: Blocks, block_cache: Arc>>, short_channel_id: u64, ) -> Result { let block_height = (short_channel_id >> 5 * 8) as u32; // block height is most significant three bytes let transaction_index = ((short_channel_id >> 2 * 8) & 0xffffff) as u32; @@ -175,9 +187,10 @@ impl { { + ($block: expr) => {{ if transaction_index as usize >= $block.txdata.len() { return Err(UtxoLookupError::UnknownTx); } @@ -188,7 +201,7 @@ impl return Err(UtxoLookupError::UnknownTx), BlockData::FullBlock(block) => block, @@ -237,7 +250,7 @@ impl Deref for GossipVerifier where +impl Deref + for GossipVerifier +where Blocks::Target: UtxoSource, L::Target: Logger, { type Target = Self; - fn deref(&self) -> &Self { self } + fn deref(&self) -> &Self { + self + } } - -impl UtxoLookup for GossipVerifier where +impl UtxoLookup + for GossipVerifier +where Blocks::Target: UtxoSource, L::Target: Logger, { diff --git a/lightning-block-sync/src/http.rs b/lightning-block-sync/src/http.rs index aa0d840adb0..c230b253f65 100644 --- a/lightning-block-sync/src/http.rs +++ b/lightning-block-sync/src/http.rs @@ -50,11 +50,7 @@ pub struct HttpEndpoint { impl HttpEndpoint { /// Creates an endpoint for the given host and default HTTP port. pub fn for_host(host: String) -> Self { - Self { - host, - port: None, - path: String::from("/"), - } + Self { host, port: None, path: String::from("/") } } /// Specifies a port to use with the endpoint. @@ -107,7 +103,10 @@ impl HttpClient { pub fn connect(endpoint: E) -> std::io::Result { let address = match endpoint.to_socket_addrs()?.next() { None => { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "could not resolve to any addresses")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "could not resolve to any addresses", + )); }, Some(address) => address, }; @@ -129,12 +128,16 @@ impl HttpClient { /// Returns the response body in `F` format. #[allow(dead_code)] pub async fn get(&mut self, uri: &str, host: &str) -> std::io::Result - where F: TryFrom, Error = std::io::Error> { + where + F: TryFrom, Error = std::io::Error>, + { let request = format!( "GET {} HTTP/1.1\r\n\ Host: {}\r\n\ Connection: keep-alive\r\n\ - \r\n", uri, host); + \r\n", + uri, host + ); let response_body = self.send_request_with_retry(&request).await?; F::try_from(response_body) } @@ -145,8 +148,12 @@ impl HttpClient { /// The request body consists of the provided JSON `content`. Returns the response body in `F` /// format. #[allow(dead_code)] - pub async fn post(&mut self, uri: &str, host: &str, auth: &str, content: serde_json::Value) -> std::io::Result - where F: TryFrom, Error = std::io::Error> { + pub async fn post( + &mut self, uri: &str, host: &str, auth: &str, content: serde_json::Value, + ) -> std::io::Result + where + F: TryFrom, Error = std::io::Error>, + { let content = content.to_string(); let request = format!( "POST {} HTTP/1.1\r\n\ @@ -156,7 +163,13 @@ impl HttpClient { Content-Type: application/json\r\n\ Content-Length: {}\r\n\ \r\n\ - {}", uri, host, auth, content.len(), content); + {}", + uri, + host, + auth, + content.len(), + content + ); let response_body = self.send_request_with_retry(&request).await?; F::try_from(response_body) } @@ -218,8 +231,10 @@ impl HttpClient { let mut reader = std::io::BufReader::new(limited_stream); macro_rules! read_line { - () => { read_line!(0) }; - ($retry_count: expr) => { { + () => { + read_line!(0) + }; + ($retry_count: expr) => {{ let mut line = String::new(); let mut timeout_count: u64 = 0; let bytes_read = loop { @@ -236,7 +251,7 @@ impl HttpClient { } else { continue; } - } + }, Err(e) => return Err(e), } }; @@ -245,17 +260,23 @@ impl HttpClient { 0 => None, _ => { // Remove trailing CRLF - if line.ends_with('\n') { line.pop(); if line.ends_with('\r') { line.pop(); } } + if line.ends_with('\n') { + line.pop(); + if line.ends_with('\r') { + line.pop(); + } + } Some(line) }, } - } } + }}; } // Read and parse status line // Note that we allow retrying a few times to reach TCP_STREAM_RESPONSE_TIMEOUT. - let status_line = read_line!(TCP_STREAM_RESPONSE_TIMEOUT.as_secs() / TCP_STREAM_TIMEOUT.as_secs()) - .ok_or(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "no status line"))?; + let status_line = + read_line!(TCP_STREAM_RESPONSE_TIMEOUT.as_secs() / TCP_STREAM_TIMEOUT.as_secs()) + .ok_or(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "no status line"))?; let status = HttpStatus::parse(&status_line)?; // Read and parse relevant headers @@ -263,11 +284,15 @@ impl HttpClient { loop { let line = read_line!() .ok_or(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "no headers"))?; - if line.is_empty() { break; } + if line.is_empty() { + break; + } let header = HttpHeader::parse(&line)?; if header.has_name("Content-Length") { - let length = header.value.parse() + let length = header + .value + .parse() .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; if let HttpMessageLength::Empty = message_length { message_length = HttpMessageLength::ContentLength(length); @@ -285,10 +310,13 @@ impl HttpClient { let read_limit = MAX_HTTP_MESSAGE_BODY_SIZE - reader.buffer().len(); reader.get_mut().set_limit(read_limit as u64); let contents = match message_length { - HttpMessageLength::Empty => { Vec::new() }, + HttpMessageLength::Empty => Vec::new(), HttpMessageLength::ContentLength(length) => { if length == 0 || length > MAX_HTTP_MESSAGE_BODY_SIZE { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, format!("invalid response length: {} bytes", length))); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("invalid response length: {} bytes", length), + )); } else { let mut content = vec![0; length]; #[cfg(feature = "tokio")] @@ -301,7 +329,9 @@ impl HttpClient { HttpMessageLength::TransferEncoding(coding) => { if !coding.eq_ignore_ascii_case("chunked") { return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, "unsupported transfer coding")) + std::io::ErrorKind::InvalidInput, + "unsupported transfer coding", + )); } else { let mut content = Vec::new(); #[cfg(feature = "tokio")] @@ -323,7 +353,8 @@ impl HttpClient { // Decode the chunk header to obtain the chunk size. let mut buffer = Vec::new(); - let mut decoder = chunked_transfer::Decoder::new(chunk_header.as_bytes()); + let mut decoder = + chunked_transfer::Decoder::new(chunk_header.as_bytes()); decoder.read_to_end(&mut buffer)?; // Read the chunk body. @@ -350,10 +381,7 @@ impl HttpClient { if !status.is_ok() { // TODO: Handle 3xx redirection responses. - let error = HttpError { - status_code: status.code.to_string(), - contents, - }; + let error = HttpError { status_code: status.code.to_string(), contents }; return Err(std::io::Error::new(std::io::ErrorKind::Other, error)); } @@ -391,20 +419,30 @@ impl<'a> HttpStatus<'a> { fn parse(line: &'a String) -> std::io::Result> { let mut tokens = line.splitn(3, ' '); - let http_version = tokens.next() + let http_version = tokens + .next() .ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "no HTTP-Version"))?; - if !http_version.eq_ignore_ascii_case("HTTP/1.1") && - !http_version.eq_ignore_ascii_case("HTTP/1.0") { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid HTTP-Version")); + if !http_version.eq_ignore_ascii_case("HTTP/1.1") + && !http_version.eq_ignore_ascii_case("HTTP/1.0") + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid HTTP-Version", + )); } - let code = tokens.next() + let code = tokens + .next() .ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "no Status-Code"))?; if code.len() != 3 || !code.chars().all(|c| c.is_ascii_digit()) { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid Status-Code")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid Status-Code", + )); } - let _reason = tokens.next() + let _reason = tokens + .next() .ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "no Reason-Phrase"))?; Ok(Self { code }) @@ -430,9 +468,11 @@ impl<'a> HttpHeader<'a> { /// [RFC 7230]: https://tools.ietf.org/html/rfc7230#section-3.2 fn parse(line: &'a String) -> std::io::Result> { let mut tokens = line.splitn(2, ':'); - let name = tokens.next() + let name = tokens + .next() .ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "no header name"))?; - let value = tokens.next() + let value = tokens + .next() .ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "no header value"))? .trim_start(); Ok(Self { name, value }) @@ -524,7 +564,7 @@ mod endpoint_tests { assert_eq!(addr, std_addrs.next().unwrap()); } assert!(std_addrs.next().is_none()); - } + }, } } } @@ -559,7 +599,11 @@ pub(crate) mod client_tests { "{}\r\n\ Content-Length: {}\r\n\ \r\n\ - {}", status, body.len(), body) + {}", + status, + body.len(), + body + ) }, MessageBody::ChunkedContent(body) => { let mut chuncked_body = Vec::new(); @@ -572,7 +616,10 @@ pub(crate) mod client_tests { "{}\r\n\ Transfer-Encoding: chunked\r\n\ \r\n\ - {}", status, String::from_utf8(chuncked_body).unwrap()) + {}", + status, + String::from_utf8(chuncked_body).unwrap() + ) }, }; HttpServer::responding_with(response) @@ -606,14 +653,20 @@ pub(crate) mod client_tests { .lines() .take_while(|line| !line.as_ref().unwrap().is_empty()) .count(); - if lines_read == 0 { continue; } + if lines_read == 0 { + continue; + } for chunk in response.as_bytes().chunks(16) { if shutdown_signaled.load(std::sync::atomic::Ordering::SeqCst) { return; } else { - if let Err(_) = stream.write(chunk) { break; } - if let Err(_) = stream.flush() { break; } + if let Err(_) = stream.write(chunk) { + break; + } + if let Err(_) = stream.flush() { + break; + } } } } @@ -636,8 +689,12 @@ pub(crate) mod client_tests { fn connect_to_unresolvable_host() { match HttpClient::connect(("example.invalid", 80)) { Err(e) => { - assert!(e.to_string().contains("failed to lookup address information") || - e.to_string().contains("No such host"), "{:?}", e); + assert!( + e.to_string().contains("failed to lookup address information") + || e.to_string().contains("No such host"), + "{:?}", + e + ); }, Ok(_) => panic!("Expected error"), } @@ -705,7 +762,9 @@ pub(crate) mod client_tests { let response = format!( "HTTP/1.1 302 Found\r\n\ Location: {}\r\n\ - \r\n", "Z".repeat(MAX_HTTP_MESSAGE_HEADER_SIZE)); + \r\n", + "Z".repeat(MAX_HTTP_MESSAGE_HEADER_SIZE) + ); let server = HttpServer::responding_with(response); let mut client = HttpClient::connect(&server.endpoint()).unwrap(); @@ -727,7 +786,10 @@ pub(crate) mod client_tests { match client.get::("/foo", "foo.com").await { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::InvalidData); - assert_eq!(e.get_ref().unwrap().to_string(), "invalid response length: 8032001 bytes"); + assert_eq!( + e.get_ref().unwrap().to_string(), + "invalid response length: 8032001 bytes" + ); }, Ok(_) => panic!("Expected error"), } @@ -740,7 +802,8 @@ pub(crate) mod client_tests { "HTTP/1.1 200 OK\r\n\ Transfer-Encoding: gzip\r\n\ \r\n\ - foobar"); + foobar", + ); let server = HttpServer::responding_with(response); let mut client = HttpClient::connect(&server.endpoint()).unwrap(); diff --git a/lightning-block-sync/src/init.rs b/lightning-block-sync/src/init.rs index 8cb0ff70a2e..14c78889995 100644 --- a/lightning-block-sync/src/init.rs +++ b/lightning-block-sync/src/init.rs @@ -1,8 +1,8 @@ //! Utilities to assist in the initial sync required to initialize or reload Rust-Lightning objects //! from disk. -use crate::{BlockSource, BlockSourceResult, Cache, ChainNotifier}; use crate::poll::{ChainPoller, Validate, ValidatedBlockHeader}; +use crate::{BlockSource, BlockSourceResult, Cache, ChainNotifier}; use bitcoin::blockdata::block::Header; use bitcoin::hash_types::BlockHash; @@ -18,12 +18,14 @@ use std::ops::Deref; /// start when there are no chain listeners to sync yet. /// /// [`SpvClient`]: crate::SpvClient -pub async fn validate_best_block_header(block_source: B) -> -BlockSourceResult where B::Target: BlockSource { +pub async fn validate_best_block_header( + block_source: B, +) -> BlockSourceResult +where + B::Target: BlockSource, +{ let (best_block_hash, best_block_height) = block_source.get_best_block().await?; - block_source - .get_header(&best_block_hash, best_block_height).await? - .validate(best_block_hash) + block_source.get_header(&best_block_hash, best_block_height).await?.validate(best_block_hash) } /// Performs a one-time sync of chain listeners using a single *trusted* block source, bringing each @@ -131,12 +133,17 @@ BlockSourceResult where B::Target: BlockSource { /// [`SpvClient`]: crate::SpvClient /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager /// [`ChannelMonitor`]: lightning::chain::channelmonitor::ChannelMonitor -pub async fn synchronize_listeners( - block_source: B, - network: Network, - header_cache: &mut C, +pub async fn synchronize_listeners< + B: Deref + Sized + Send + Sync, + C: Cache, + L: chain::Listen + ?Sized, +>( + block_source: B, network: Network, header_cache: &mut C, mut chain_listeners: Vec<(BlockHash, &L)>, -) -> BlockSourceResult where B::Target: BlockSource { +) -> BlockSourceResult +where + B::Target: BlockSource, +{ let best_header = validate_best_block_header(&*block_source).await?; // Fetch the header for the block hash paired with each listener. @@ -144,9 +151,9 @@ pub async fn synchronize_listeners *header, - None => block_source - .get_header(&old_block_hash, None).await? - .validate(old_block_hash)? + None => { + block_source.get_header(&old_block_hash, None).await?.validate(old_block_hash)? + }, }; chain_listeners_with_old_headers.push((old_header, chain_listener)) } @@ -180,8 +187,10 @@ pub async fn synchronize_listeners Cache for ReadOnlyCache<'a, C> { struct DynamicChainListener<'a, L: chain::Listen + ?Sized>(&'a L); impl<'a, L: chain::Listen + ?Sized> chain::Listen for DynamicChainListener<'a, L> { - fn filtered_block_connected(&self, _header: &Header, _txdata: &chain::transaction::TransactionData, _height: u32) { + fn filtered_block_connected( + &self, _header: &Header, _txdata: &chain::transaction::TransactionData, _height: u32, + ) { unreachable!() } @@ -234,7 +245,9 @@ impl<'a, L: chain::Listen + ?Sized> chain::Listen for ChainListenerSet<'a, L> { } } - fn filtered_block_connected(&self, header: &Header, txdata: &chain::transaction::TransactionData, height: u32) { + fn filtered_block_connected( + &self, header: &Header, txdata: &chain::transaction::TransactionData, height: u32, + ) { for (starting_height, chain_listener) in self.0.iter() { if height > *starting_height { chain_listener.filtered_block_connected(header, txdata, height); @@ -249,8 +262,8 @@ impl<'a, L: chain::Listen + ?Sized> chain::Listen for ChainListenerSet<'a, L> { #[cfg(test)] mod tests { - use crate::test_utils::{Blockchain, MockChainListener}; use super::*; + use crate::test_utils::{Blockchain, MockChainListener}; use bitcoin::network::constants::Network; @@ -265,8 +278,7 @@ mod tests { let listener_2 = MockChainListener::new() .expect_block_connected(*chain.at_height(3)) .expect_block_connected(*chain.at_height(4)); - let listener_3 = MockChainListener::new() - .expect_block_connected(*chain.at_height(4)); + let listener_3 = MockChainListener::new().expect_block_connected(*chain.at_height(4)); let listeners = vec![ (chain.at_height(1).block_hash, &listener_1 as &dyn chain::Listen), diff --git a/lightning-block-sync/src/lib.rs b/lightning-block-sync/src/lib.rs index 4a01d4673b3..15ea696a53b 100644 --- a/lightning-block-sync/src/lib.rs +++ b/lightning-block-sync/src/lib.rs @@ -15,10 +15,8 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] #![deny(unsafe_code)] - #![cfg_attr(docsrs, feature(doc_auto_cfg))] #[cfg(any(feature = "rest-client", feature = "rpc-client"))] @@ -58,18 +56,21 @@ use std::ops::Deref; use std::pin::Pin; /// Abstract type for retrieving block headers and data. -pub trait BlockSource : Sync + Send { +pub trait BlockSource: Sync + Send { /// Returns the header for a given hash. A height hint may be provided in case a block source /// cannot easily find headers based on a hash. This is merely a hint and thus the returned /// header must have the same hash as was requested. Otherwise, an error must be returned. /// /// Implementations that cannot find headers based on the hash should return a `Transient` error /// when `height_hint` is `None`. - fn get_header<'a>(&'a self, header_hash: &'a BlockHash, height_hint: Option) -> AsyncBlockSourceResult<'a, BlockHeaderData>; + fn get_header<'a>( + &'a self, header_hash: &'a BlockHash, height_hint: Option, + ) -> AsyncBlockSourceResult<'a, BlockHeaderData>; /// Returns the block for a given hash. A headers-only block source should return a `Transient` /// error. - fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData>; + fn get_block<'a>(&'a self, header_hash: &'a BlockHash) + -> AsyncBlockSourceResult<'a, BlockData>; /// Returns the hash of the best block and, optionally, its height. /// @@ -86,7 +87,8 @@ pub type BlockSourceResult = Result; // TODO: Replace with BlockSourceResult once `async` trait functions are supported. For details, // see: https://areweasyncyet.rs. /// Result type for asynchronous `BlockSource` requests. -pub type AsyncBlockSourceResult<'a, T> = Pin> + 'a + Send>>; +pub type AsyncBlockSourceResult<'a, T> = + Pin> + 'a + Send>>; /// Error type for `BlockSource` requests. /// @@ -111,20 +113,18 @@ pub enum BlockSourceErrorKind { impl BlockSourceError { /// Creates a new persistent error originated from the given error. pub fn persistent(error: E) -> Self - where E: Into> { - Self { - kind: BlockSourceErrorKind::Persistent, - error: error.into(), - } + where + E: Into>, + { + Self { kind: BlockSourceErrorKind::Persistent, error: error.into() } } /// Creates a new transient error originated from the given error. pub fn transient(error: E) -> Self - where E: Into> { - Self { - kind: BlockSourceErrorKind::Transient, - error: error.into(), - } + where + E: Into>, + { + Self { kind: BlockSourceErrorKind::Transient, error: error.into() } } /// Returns the kind of error. @@ -180,7 +180,9 @@ pub enum BlockData { /// Hence, there is a trade-off between a lower memory footprint and potentially increased network /// I/O as headers are re-fetched during fork detection. pub struct SpvClient<'a, P: Poll, C: Cache, L: Deref> -where L::Target: chain::Listen { +where + L::Target: chain::Listen, +{ chain_tip: ValidatedBlockHeader, chain_poller: P, chain_notifier: ChainNotifier<'a, C, L>, @@ -226,7 +228,10 @@ impl Cache for UnboundedCache { } } -impl<'a, P: Poll, C: Cache, L: Deref> SpvClient<'a, P, C, L> where L::Target: chain::Listen { +impl<'a, P: Poll, C: Cache, L: Deref> SpvClient<'a, P, C, L> +where + L::Target: chain::Listen, +{ /// Creates a new SPV client using `chain_tip` as the best known chain tip. /// /// Subsequent calls to [`poll_best_tip`] will poll for the best chain tip using the given chain @@ -238,9 +243,7 @@ impl<'a, P: Poll, C: Cache, L: Deref> SpvClient<'a, P, C, L> where L::Target: ch /// /// [`poll_best_tip`]: SpvClient::poll_best_tip pub fn new( - chain_tip: ValidatedBlockHeader, - chain_poller: P, - header_cache: &'a mut C, + chain_tip: ValidatedBlockHeader, chain_poller: P, header_cache: &'a mut C, chain_listener: L, ) -> Self { let chain_notifier = ChainNotifier { header_cache, chain_listener }; @@ -273,8 +276,10 @@ impl<'a, P: Poll, C: Cache, L: Deref> SpvClient<'a, P, C, L> where L::Target: ch /// Updates the chain tip, syncing the chain listener with any connected or disconnected /// blocks. Returns whether there were any such blocks. async fn update_chain_tip(&mut self, best_chain_tip: ValidatedBlockHeader) -> bool { - match self.chain_notifier.synchronize_listener( - best_chain_tip, &self.chain_tip, &mut self.chain_poller).await + match self + .chain_notifier + .synchronize_listener(best_chain_tip, &self.chain_tip, &mut self.chain_poller) + .await { Ok(_) => { self.chain_tip = best_chain_tip; @@ -292,7 +297,10 @@ impl<'a, P: Poll, C: Cache, L: Deref> SpvClient<'a, P, C, L> where L::Target: ch /// Notifies [listeners] of blocks that have been connected or disconnected from the chain. /// /// [listeners]: lightning::chain::Listen -pub struct ChainNotifier<'a, C: Cache, L: Deref> where L::Target: chain::Listen { +pub struct ChainNotifier<'a, C: Cache, L: Deref> +where + L::Target: chain::Listen, +{ /// Cache for looking up headers before fetching from a block source. header_cache: &'a mut C, @@ -318,7 +326,10 @@ struct ChainDifference { connected_blocks: Vec, } -impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> where L::Target: chain::Listen { +impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> +where + L::Target: chain::Listen, +{ /// Finds the first common ancestor between `new_header` and `old_header`, disconnecting blocks /// from `old_header` to get to that point and then connecting blocks until `new_header`. /// @@ -327,19 +338,16 @@ impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> where L::Target: chain::Lis /// ended up which may not be `new_header`. Note that the returned `Err` contains `Some` header /// if and only if the transition from `old_header` to `new_header` is valid. async fn synchronize_listener( - &mut self, - new_header: ValidatedBlockHeader, - old_header: &ValidatedBlockHeader, + &mut self, new_header: ValidatedBlockHeader, old_header: &ValidatedBlockHeader, chain_poller: &mut P, ) -> Result<(), (BlockSourceError, Option)> { - let difference = self.find_difference(new_header, old_header, chain_poller).await + let difference = self + .find_difference(new_header, old_header, chain_poller) + .await .map_err(|e| (e, None))?; self.disconnect_blocks(difference.disconnected_blocks); - self.connect_blocks( - difference.common_ancestor, - difference.connected_blocks, - chain_poller, - ).await + self.connect_blocks(difference.common_ancestor, difference.connected_blocks, chain_poller) + .await } /// Returns the changes needed to produce the chain with `current_header` as its tip from the @@ -347,9 +355,7 @@ impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> where L::Target: chain::Lis /// /// Walks backwards from `current_header` and `prev_header`, finding the common ancestor. async fn find_difference( - &self, - current_header: ValidatedBlockHeader, - prev_header: &ValidatedBlockHeader, + &self, current_header: ValidatedBlockHeader, prev_header: &ValidatedBlockHeader, chain_poller: &mut P, ) -> BlockSourceResult { let mut disconnected_blocks = Vec::new(); @@ -383,9 +389,7 @@ impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> where L::Target: chain::Lis /// Returns the previous header for the given header, either by looking it up in the cache or /// fetching it if not found. async fn look_up_previous_header( - &self, - chain_poller: &mut P, - header: &ValidatedBlockHeader, + &self, chain_poller: &mut P, header: &ValidatedBlockHeader, ) -> BlockSourceResult { match self.header_cache.look_up(&header.header.prev_blockhash) { Some(prev_header) => Ok(*prev_header), @@ -405,16 +409,13 @@ impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> where L::Target: chain::Lis /// Notifies the chain listeners of connected blocks. async fn connect_blocks( - &mut self, - mut new_tip: ValidatedBlockHeader, - mut connected_blocks: Vec, - chain_poller: &mut P, + &mut self, mut new_tip: ValidatedBlockHeader, + mut connected_blocks: Vec, chain_poller: &mut P, ) -> Result<(), (BlockSourceError, Option)> { for header in connected_blocks.drain(..).rev() { let height = header.height; - let block_data = chain_poller - .fetch_block(&header).await - .map_err(|e| (e, Some(new_tip)))?; + let block_data = + chain_poller.fetch_block(&header).await.map_err(|e| (e, Some(new_tip)))?; debug_assert_eq!(block_data.block_hash, header.block_hash); match block_data.deref() { @@ -436,8 +437,8 @@ impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> where L::Target: chain::Lis #[cfg(test)] mod spv_client_tests { - use crate::test_utils::{Blockchain, NullChainListener}; use super::*; + use crate::test_utils::{Blockchain, NullChainListener}; use bitcoin::network::constants::Network; @@ -563,8 +564,8 @@ mod spv_client_tests { #[cfg(test)] mod chain_notifier_tests { - use crate::test_utils::{Blockchain, MockChainListener}; use super::*; + use crate::test_utils::{Blockchain, MockChainListener}; use bitcoin::network::constants::Network; @@ -577,10 +578,8 @@ mod chain_notifier_tests { let chain_listener = &MockChainListener::new() .expect_block_connected(*chain.at_height(2)) .expect_block_connected(*new_tip); - let mut notifier = ChainNotifier { - header_cache: &mut chain.header_cache(0..=1), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut chain.header_cache(0..=1), chain_listener }; let mut poller = poll::ChainPoller::new(&mut chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((e, _)) => panic!("Unexpected error: {:?}", e), @@ -596,10 +595,8 @@ mod chain_notifier_tests { let new_tip = test_chain.tip(); let old_tip = main_chain.tip(); let chain_listener = &MockChainListener::new(); - let mut notifier = ChainNotifier { - header_cache: &mut main_chain.header_cache(0..=1), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut main_chain.header_cache(0..=1), chain_listener }; let mut poller = poll::ChainPoller::new(&mut test_chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((e, _)) => { @@ -620,10 +617,8 @@ mod chain_notifier_tests { let chain_listener = &MockChainListener::new() .expect_block_disconnected(*old_tip) .expect_block_connected(*new_tip); - let mut notifier = ChainNotifier { - header_cache: &mut main_chain.header_cache(0..=2), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut main_chain.header_cache(0..=2), chain_listener }; let mut poller = poll::ChainPoller::new(&mut fork_chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((e, _)) => panic!("Unexpected error: {:?}", e), @@ -643,10 +638,8 @@ mod chain_notifier_tests { .expect_block_disconnected(*old_tip) .expect_block_disconnected(*main_chain.at_height(2)) .expect_block_connected(*new_tip); - let mut notifier = ChainNotifier { - header_cache: &mut main_chain.header_cache(0..=3), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut main_chain.header_cache(0..=3), chain_listener }; let mut poller = poll::ChainPoller::new(&mut fork_chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((e, _)) => panic!("Unexpected error: {:?}", e), @@ -666,10 +659,8 @@ mod chain_notifier_tests { .expect_block_disconnected(*old_tip) .expect_block_connected(*fork_chain.at_height(2)) .expect_block_connected(*new_tip); - let mut notifier = ChainNotifier { - header_cache: &mut main_chain.header_cache(0..=2), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut main_chain.header_cache(0..=2), chain_listener }; let mut poller = poll::ChainPoller::new(&mut fork_chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((e, _)) => panic!("Unexpected error: {:?}", e), @@ -684,10 +675,8 @@ mod chain_notifier_tests { let new_tip = chain.tip(); let old_tip = chain.at_height(1); let chain_listener = &MockChainListener::new(); - let mut notifier = ChainNotifier { - header_cache: &mut chain.header_cache(0..=1), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut chain.header_cache(0..=1), chain_listener }; let mut poller = poll::ChainPoller::new(&mut chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((_, tip)) => assert_eq!(tip, None), @@ -702,10 +691,8 @@ mod chain_notifier_tests { let new_tip = chain.tip(); let old_tip = chain.at_height(1); let chain_listener = &MockChainListener::new(); - let mut notifier = ChainNotifier { - header_cache: &mut chain.header_cache(0..=3), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut chain.header_cache(0..=3), chain_listener }; let mut poller = poll::ChainPoller::new(&mut chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((_, tip)) => assert_eq!(tip, Some(old_tip)), @@ -719,12 +706,9 @@ mod chain_notifier_tests { let new_tip = chain.tip(); let old_tip = chain.at_height(1); - let chain_listener = &MockChainListener::new() - .expect_block_connected(*chain.at_height(2)); - let mut notifier = ChainNotifier { - header_cache: &mut chain.header_cache(0..=3), - chain_listener, - }; + let chain_listener = &MockChainListener::new().expect_block_connected(*chain.at_height(2)); + let mut notifier = + ChainNotifier { header_cache: &mut chain.header_cache(0..=3), chain_listener }; let mut poller = poll::ChainPoller::new(&mut chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((_, tip)) => assert_eq!(tip, Some(chain.at_height(2))), @@ -741,15 +725,12 @@ mod chain_notifier_tests { let chain_listener = &MockChainListener::new() .expect_filtered_block_connected(*chain.at_height(2)) .expect_filtered_block_connected(*new_tip); - let mut notifier = ChainNotifier { - header_cache: &mut chain.header_cache(0..=1), - chain_listener, - }; + let mut notifier = + ChainNotifier { header_cache: &mut chain.header_cache(0..=1), chain_listener }; let mut poller = poll::ChainPoller::new(&mut chain, Network::Testnet); match notifier.synchronize_listener(new_tip, &old_tip, &mut poller).await { Err((e, _)) => panic!("Unexpected error: {:?}", e), Ok(_) => {}, } } - } diff --git a/lightning-block-sync/src/poll.rs b/lightning-block-sync/src/poll.rs index dcc19a4969d..f59d87489c8 100644 --- a/lightning-block-sync/src/poll.rs +++ b/lightning-block-sync/src/poll.rs @@ -1,6 +1,9 @@ //! Adapters that make one or more [`BlockSource`]s simpler to poll for new chain tip transitions. -use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, BlockSourceResult}; +use crate::{ + AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, + BlockSourceResult, +}; use bitcoin::hash_types::BlockHash; use bitcoin::network::constants::Network; @@ -17,16 +20,19 @@ use std::ops::Deref; /// [`ChainPoller`]: ../struct.ChainPoller.html pub trait Poll { /// Returns a chain tip in terms of its relationship to the provided chain tip. - fn poll_chain_tip<'a>(&'a self, best_known_chain_tip: ValidatedBlockHeader) -> - AsyncBlockSourceResult<'a, ChainTip>; + fn poll_chain_tip<'a>( + &'a self, best_known_chain_tip: ValidatedBlockHeader, + ) -> AsyncBlockSourceResult<'a, ChainTip>; /// Returns the header that preceded the given header in the chain. - fn look_up_previous_header<'a>(&'a self, header: &'a ValidatedBlockHeader) -> - AsyncBlockSourceResult<'a, ValidatedBlockHeader>; + fn look_up_previous_header<'a>( + &'a self, header: &'a ValidatedBlockHeader, + ) -> AsyncBlockSourceResult<'a, ValidatedBlockHeader>; /// Returns the block associated with the given header. - fn fetch_block<'a>(&'a self, header: &'a ValidatedBlockHeader) -> - AsyncBlockSourceResult<'a, ValidatedBlock>; + fn fetch_block<'a>( + &'a self, header: &'a ValidatedBlockHeader, + ) -> AsyncBlockSourceResult<'a, ValidatedBlock>; } /// A chain tip relative to another chain tip in terms of block hash and chainwork. @@ -59,9 +65,8 @@ impl Validate for BlockHeaderData { type T = ValidatedBlockHeader; fn validate(self, block_hash: BlockHash) -> BlockSourceResult { - let pow_valid_block_hash = self.header - .validate_pow(self.header.target()) - .map_err(BlockSourceError::persistent)?; + let pow_valid_block_hash = + self.header.validate_pow(self.header.target()).map_err(BlockSourceError::persistent)?; if pow_valid_block_hash != block_hash { return Err(BlockSourceError::persistent("invalid block hash")); @@ -80,9 +85,8 @@ impl Validate for BlockData { BlockData::HeaderOnly(header) => header, }; - let pow_valid_block_hash = header - .validate_pow(header.target()) - .map_err(BlockSourceError::persistent)?; + let pow_valid_block_hash = + header.validate_pow(header.target()).map_err(BlockSourceError::persistent)?; if pow_valid_block_hash != block_hash { return Err(BlockSourceError::persistent("invalid block hash")); @@ -120,7 +124,9 @@ impl std::ops::Deref for ValidatedBlockHeader { impl ValidatedBlockHeader { /// Checks that the header correctly builds on previous_header: the claimed work differential /// matches the actual PoW and the difficulty transition is possible, i.e., within 4x. - fn check_builds_on(&self, previous_header: &ValidatedBlockHeader, network: Network) -> BlockSourceResult<()> { + fn check_builds_on( + &self, previous_header: &ValidatedBlockHeader, network: Network, + ) -> BlockSourceResult<()> { if self.header.prev_blockhash != previous_header.block_hash { return Err(BlockSourceError::persistent("invalid previous block hash")); } @@ -141,28 +147,28 @@ impl ValidatedBlockHeader { let min_target = previous_target.min_difficulty_transition_threshold(); let max_target = previous_target.max_difficulty_transition_threshold(); if target > max_target || target < min_target { - return Err(BlockSourceError::persistent("invalid difficulty transition")) + return Err(BlockSourceError::persistent("invalid difficulty transition")); } } else if self.header.bits != previous_header.header.bits { - return Err(BlockSourceError::persistent("invalid difficulty")) + return Err(BlockSourceError::persistent("invalid difficulty")); } } Ok(()) } - /// Returns the [`BestBlock`] corresponding to this validated block header, which can be passed - /// into [`ChannelManager::new`] as part of its [`ChainParameters`]. Useful for ensuring that - /// the [`SpvClient`] and [`ChannelManager`] are initialized to the same block during a fresh - /// start. - /// - /// [`SpvClient`]: crate::SpvClient - /// [`ChainParameters`]: lightning::ln::channelmanager::ChainParameters - /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager - /// [`ChannelManager::new`]: lightning::ln::channelmanager::ChannelManager::new - pub fn to_best_block(&self) -> BestBlock { - BestBlock::new(self.block_hash, self.inner.height) - } + /// Returns the [`BestBlock`] corresponding to this validated block header, which can be passed + /// into [`ChannelManager::new`] as part of its [`ChainParameters`]. Useful for ensuring that + /// the [`SpvClient`] and [`ChannelManager`] are initialized to the same block during a fresh + /// start. + /// + /// [`SpvClient`]: crate::SpvClient + /// [`ChainParameters`]: lightning::ln::channelmanager::ChainParameters + /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager + /// [`ChannelManager::new`]: lightning::ln::channelmanager::ChannelManager::new + pub fn to_best_block(&self) -> BestBlock { + BestBlock::new(self.block_hash, self.inner.height) + } } /// A block with validated data against its transaction list and corresponding block hash. @@ -191,12 +197,12 @@ mod sealed { /// /// Other `Poll` implementations should be built using `ChainPoller` as it provides the simplest way /// of validating chain data and checking consistency. -pub struct ChainPoller + Sized + Send + Sync, T: BlockSource + ?Sized> { +pub struct ChainPoller + Sized + Send + Sync, T: BlockSource + ?Sized> { block_source: B, network: Network, } -impl + Sized + Send + Sync, T: BlockSource + ?Sized> ChainPoller { +impl + Sized + Send + Sync, T: BlockSource + ?Sized> ChainPoller { /// Creates a new poller for the given block source. /// /// If the `network` parameter is mainnet, then the difficulty between blocks is checked for @@ -206,19 +212,20 @@ impl + Sized + Send + Sync, T: BlockSource + ?Sized> ChainPol } } -impl + Sized + Send + Sync, T: BlockSource + ?Sized> Poll for ChainPoller { - fn poll_chain_tip<'a>(&'a self, best_known_chain_tip: ValidatedBlockHeader) -> - AsyncBlockSourceResult<'a, ChainTip> - { +impl + Sized + Send + Sync, T: BlockSource + ?Sized> Poll + for ChainPoller +{ + fn poll_chain_tip<'a>( + &'a self, best_known_chain_tip: ValidatedBlockHeader, + ) -> AsyncBlockSourceResult<'a, ChainTip> { Box::pin(async move { let (block_hash, height) = self.block_source.get_best_block().await?; if block_hash == best_known_chain_tip.header.block_hash() { return Ok(ChainTip::Common); } - let chain_tip = self.block_source - .get_header(&block_hash, height).await? - .validate(block_hash)?; + let chain_tip = + self.block_source.get_header(&block_hash, height).await?.validate(block_hash)?; if chain_tip.chainwork > best_known_chain_tip.chainwork { Ok(ChainTip::Better(chain_tip)) } else { @@ -227,9 +234,9 @@ impl + Sized + Send + Sync, T: BlockSource + ?Sized> Poll for }) } - fn look_up_previous_header<'a>(&'a self, header: &'a ValidatedBlockHeader) -> - AsyncBlockSourceResult<'a, ValidatedBlockHeader> - { + fn look_up_previous_header<'a>( + &'a self, header: &'a ValidatedBlockHeader, + ) -> AsyncBlockSourceResult<'a, ValidatedBlockHeader> { Box::pin(async move { if header.height == 0 { return Err(BlockSourceError::persistent("genesis block reached")); @@ -237,8 +244,10 @@ impl + Sized + Send + Sync, T: BlockSource + ?Sized> Poll for let previous_hash = &header.header.prev_blockhash; let height = header.height - 1; - let previous_header = self.block_source - .get_header(previous_hash, Some(height)).await? + let previous_header = self + .block_source + .get_header(previous_hash, Some(height)) + .await? .validate(*previous_hash)?; header.check_builds_on(&previous_header, self.network)?; @@ -246,22 +255,20 @@ impl + Sized + Send + Sync, T: BlockSource + ?Sized> Poll for }) } - fn fetch_block<'a>(&'a self, header: &'a ValidatedBlockHeader) -> - AsyncBlockSourceResult<'a, ValidatedBlock> - { + fn fetch_block<'a>( + &'a self, header: &'a ValidatedBlockHeader, + ) -> AsyncBlockSourceResult<'a, ValidatedBlock> { Box::pin(async move { - self.block_source - .get_block(&header.block_hash).await? - .validate(header.block_hash) + self.block_source.get_block(&header.block_hash).await?.validate(header.block_hash) }) } } #[cfg(test)] mod tests { - use crate::*; - use crate::test_utils::Blockchain; use super::*; + use crate::test_utils::Blockchain; + use crate::*; #[tokio::test] async fn poll_empty_chain() { @@ -307,7 +314,10 @@ mod tests { match poller.poll_chain_tip(best_known_chain_tip).await { Err(e) => { assert_eq!(e.kind(), BlockSourceErrorKind::Persistent); - assert_eq!(e.into_inner().as_ref().to_string(), "block target correct but not attained"); + assert_eq!( + e.into_inner().as_ref().to_string(), + "block target correct but not attained" + ); }, Ok(_) => panic!("Expected error"), } diff --git a/lightning-block-sync/src/rest.rs b/lightning-block-sync/src/rest.rs index 74a460a7ab5..9473f7b1b6a 100644 --- a/lightning-block-sync/src/rest.rs +++ b/lightning-block-sync/src/rest.rs @@ -1,13 +1,13 @@ //! Simple REST client implementation which implements [`BlockSource`] against a Bitcoin Core REST //! endpoint. -use crate::{BlockData, BlockHeaderData, BlockSource, AsyncBlockSourceResult}; -use crate::http::{BinaryResponse, HttpEndpoint, HttpClient, JsonResponse}; -use crate::gossip::UtxoSource; use crate::convert::GetUtxosResponse; +use crate::gossip::UtxoSource; +use crate::http::{BinaryResponse, HttpClient, HttpEndpoint, JsonResponse}; +use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource}; -use bitcoin::OutPoint; use bitcoin::hash_types::BlockHash; +use bitcoin::OutPoint; use std::convert::TryFrom; use std::convert::TryInto; @@ -29,11 +29,16 @@ impl RestClient { /// Requests a resource encoded in `F` format and interpreted as type `T`. pub async fn request_resource(&self, resource_path: &str) -> std::io::Result - where F: TryFrom, Error = std::io::Error> + TryInto { + where + F: TryFrom, Error = std::io::Error> + TryInto, + { let host = format!("{}:{}", self.endpoint.host(), self.endpoint.port()); let uri = format!("{}/{}", self.endpoint.path().trim_end_matches("/"), resource_path); - let mut client = if let Some(client) = self.client.lock().unwrap().take() { client } - else { HttpClient::connect(&self.endpoint)? }; + let mut client = if let Some(client) = self.client.lock().unwrap().take() { + client + } else { + HttpClient::connect(&self.endpoint)? + }; let res = client.get::(&uri, &host).await?.try_into(); *self.client.lock().unwrap() = Some(client); res @@ -41,29 +46,37 @@ impl RestClient { } impl BlockSource for RestClient { - fn get_header<'a>(&'a self, header_hash: &'a BlockHash, _height: Option) -> AsyncBlockSourceResult<'a, BlockHeaderData> { + fn get_header<'a>( + &'a self, header_hash: &'a BlockHash, _height: Option, + ) -> AsyncBlockSourceResult<'a, BlockHeaderData> { Box::pin(async move { let resource_path = format!("headers/1/{}.json", header_hash.to_string()); Ok(self.request_resource::(&resource_path).await?) }) } - fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData> { + fn get_block<'a>( + &'a self, header_hash: &'a BlockHash, + ) -> AsyncBlockSourceResult<'a, BlockData> { Box::pin(async move { let resource_path = format!("block/{}.bin", header_hash.to_string()); - Ok(BlockData::FullBlock(self.request_resource::(&resource_path).await?)) + Ok(BlockData::FullBlock( + self.request_resource::(&resource_path).await?, + )) }) } fn get_best_block<'a>(&'a self) -> AsyncBlockSourceResult<'a, (BlockHash, Option)> { - Box::pin(async move { - Ok(self.request_resource::("chaininfo.json").await?) - }) + Box::pin( + async move { Ok(self.request_resource::("chaininfo.json").await?) }, + ) } } impl UtxoSource for RestClient { - fn get_block_hash_by_height<'a>(&'a self, block_height: u32) -> AsyncBlockSourceResult<'a, BlockHash> { + fn get_block_hash_by_height<'a>( + &'a self, block_height: u32, + ) -> AsyncBlockSourceResult<'a, BlockHash> { Box::pin(async move { let resource_path = format!("blockhashbyheight/{}.bin", block_height); Ok(self.request_resource::(&resource_path).await?) @@ -72,7 +85,8 @@ impl UtxoSource for RestClient { fn is_output_unspent<'a>(&'a self, outpoint: OutPoint) -> AsyncBlockSourceResult<'a, bool> { Box::pin(async move { - let resource_path = format!("getutxos/{}-{}.json", outpoint.txid.to_string(), outpoint.vout); + let resource_path = + format!("getutxos/{}-{}.json", outpoint.txid.to_string(), outpoint.vout); let utxo_result = self.request_resource::(&resource_path).await?; Ok(utxo_result.hit_bitmap_nonempty) @@ -83,8 +97,8 @@ impl UtxoSource for RestClient { #[cfg(test)] mod tests { use super::*; - use crate::http::BinaryResponse; use crate::http::client_tests::{HttpServer, MessageBody}; + use crate::http::BinaryResponse; use bitcoin::hashes::Hash; /// Parses binary data as a string-encoded `u32`. @@ -97,7 +111,7 @@ mod tests { Ok(s) => match u32::from_str_radix(s, 10) { Err(e) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e)), Ok(n) => Ok(n), - } + }, } } } @@ -140,7 +154,7 @@ mod tests { let server = HttpServer::responding_with_ok(MessageBody::Content( // A real response contains a few more fields, but we actually only look at the // "bitmap" field, so this should suffice for testing - "{\"chainHeight\": 1, \"bitmap\":\"0\",\"utxos\":[]}" + "{\"chainHeight\": 1, \"bitmap\":\"0\",\"utxos\":[]}", )); let client = RestClient::new(server.endpoint()).unwrap(); @@ -154,7 +168,7 @@ mod tests { let server = HttpServer::responding_with_ok(MessageBody::Content( // A real response contains lots more data, but we actually only look at the "bitmap" // field, so this should suffice for testing - "{\"chainHeight\": 1, \"bitmap\":\"1\",\"utxos\":[]}" + "{\"chainHeight\": 1, \"bitmap\":\"1\",\"utxos\":[]}", )); let client = RestClient::new(server.endpoint()).unwrap(); diff --git a/lightning-block-sync/src/rpc.rs b/lightning-block-sync/src/rpc.rs index d296088ae7e..8032d3fccec 100644 --- a/lightning-block-sync/src/rpc.rs +++ b/lightning-block-sync/src/rpc.rs @@ -1,9 +1,9 @@ //! Simple RPC client implementation which implements [`BlockSource`] against a Bitcoin Core RPC //! endpoint. -use crate::{BlockData, BlockHeaderData, BlockSource, AsyncBlockSourceResult}; -use crate::http::{HttpClient, HttpEndpoint, HttpError, JsonResponse}; use crate::gossip::UtxoSource; +use crate::http::{HttpClient, HttpEndpoint, HttpError, JsonResponse}; +use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource}; use bitcoin::hash_types::BlockHash; use bitcoin::OutPoint; @@ -28,9 +28,9 @@ pub struct RpcError { } impl fmt::Display for RpcError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "RPC error {}: {}", self.code, self.message) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "RPC error {}: {}", self.code, self.message) + } } impl Error for RpcError {} @@ -63,8 +63,12 @@ impl RpcClient { /// /// When an `Err` is returned, [`std::io::Error::into_inner`] may contain an [`RpcError`] if /// [`std::io::Error::kind`] is [`std::io::ErrorKind::Other`]. - pub async fn call_method(&self, method: &str, params: &[serde_json::Value]) -> std::io::Result - where JsonResponse: TryFrom, Error = std::io::Error> + TryInto { + pub async fn call_method( + &self, method: &str, params: &[serde_json::Value], + ) -> std::io::Result + where + JsonResponse: TryFrom, Error = std::io::Error> + TryInto, + { let host = format!("{}:{}", self.endpoint.host(), self.endpoint.port()); let uri = self.endpoint.path(); let content = serde_json::json!({ @@ -73,9 +77,13 @@ impl RpcClient { "id": &self.id.fetch_add(1, Ordering::AcqRel).to_string() }); - let mut client = if let Some(client) = self.client.lock().unwrap().take() { client } - else { HttpClient::connect(&self.endpoint)? }; - let http_response = client.post::(&uri, &host, &self.basic_auth, content).await; + let mut client = if let Some(client) = self.client.lock().unwrap().take() { + client + } else { + HttpClient::connect(&self.endpoint)? + }; + let http_response = + client.post::(&uri, &host, &self.basic_auth, content).await; *self.client.lock().unwrap() = Some(client); let mut response = match http_response { @@ -93,23 +101,30 @@ impl RpcClient { }; if !response.is_object() { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON object")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected JSON object", + )); } let error = &response["error"]; if !error.is_null() { // TODO: Examine error code for a more precise std::io::ErrorKind. - let rpc_error = RpcError { - code: error["code"].as_i64().unwrap_or(-1), - message: error["message"].as_str().unwrap_or("unknown error").to_string() + let rpc_error = RpcError { + code: error["code"].as_i64().unwrap_or(-1), + message: error["message"].as_str().unwrap_or("unknown error").to_string(), }; return Err(std::io::Error::new(std::io::ErrorKind::Other, rpc_error)); } let result = match response.get_mut("result") { Some(result) => result.take(), - None => - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON result")), + None => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected JSON result", + )) + }, }; JsonResponse(result).try_into() @@ -117,14 +132,18 @@ impl RpcClient { } impl BlockSource for RpcClient { - fn get_header<'a>(&'a self, header_hash: &'a BlockHash, _height: Option) -> AsyncBlockSourceResult<'a, BlockHeaderData> { + fn get_header<'a>( + &'a self, header_hash: &'a BlockHash, _height: Option, + ) -> AsyncBlockSourceResult<'a, BlockHeaderData> { Box::pin(async move { let header_hash = serde_json::json!(header_hash.to_string()); Ok(self.call_method("getblockheader", &[header_hash]).await?) }) } - fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData> { + fn get_block<'a>( + &'a self, header_hash: &'a BlockHash, + ) -> AsyncBlockSourceResult<'a, BlockData> { Box::pin(async move { let header_hash = serde_json::json!(header_hash.to_string()); let verbosity = serde_json::json!(0); @@ -133,14 +152,14 @@ impl BlockSource for RpcClient { } fn get_best_block<'a>(&'a self) -> AsyncBlockSourceResult<'a, (BlockHash, Option)> { - Box::pin(async move { - Ok(self.call_method("getblockchaininfo", &[]).await?) - }) + Box::pin(async move { Ok(self.call_method("getblockchaininfo", &[]).await?) }) } } impl UtxoSource for RpcClient { - fn get_block_hash_by_height<'a>(&'a self, block_height: u32) -> AsyncBlockSourceResult<'a, BlockHash> { + fn get_block_hash_by_height<'a>( + &'a self, block_height: u32, + ) -> AsyncBlockSourceResult<'a, BlockHash> { Box::pin(async move { let height_param = serde_json::json!(block_height); Ok(self.call_method("getblockhash", &[height_param]).await?) @@ -152,8 +171,8 @@ impl UtxoSource for RpcClient { let txid_param = serde_json::json!(outpoint.txid.to_string()); let vout_param = serde_json::json!(outpoint.vout); let include_mempool = serde_json::json!(false); - let utxo_opt: serde_json::Value = self.call_method( - "gettxout", &[txid_param, vout_param, include_mempool]).await?; + let utxo_opt: serde_json::Value = + self.call_method("gettxout", &[txid_param, vout_param, include_mempool]).await?; Ok(!utxo_opt.is_null()) }) } @@ -229,7 +248,7 @@ mod tests { #[tokio::test] async fn call_method_returning_missing_result() { - let response = serde_json::json!({ }); + let response = serde_json::json!({}); let server = HttpServer::responding_with_ok(MessageBody::Content(response)); let client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap(); diff --git a/lightning-block-sync/src/test_utils.rs b/lightning-block-sync/src/test_utils.rs index b6fa6617c84..73b627f2e94 100644 --- a/lightning-block-sync/src/test_utils.rs +++ b/lightning-block-sync/src/test_utils.rs @@ -1,5 +1,8 @@ -use crate::{AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, UnboundedCache}; use crate::poll::{Validate, ValidatedBlockHeader}; +use crate::{ + AsyncBlockSourceResult, BlockData, BlockHeaderData, BlockSource, BlockSourceError, + UnboundedCache, +}; use bitcoin::blockdata::block::{Block, Header, Version}; use bitcoin::blockdata::constants::genesis_block; @@ -47,7 +50,7 @@ impl Blockchain { version: 0, lock_time: LockTime::ZERO, input: vec![], - output: vec![] + output: vec![], }; let merkle_root = TxMerkleNode::from_raw_hash(coinbase.txid().to_raw_hash()); self.blocks.push(Block { @@ -134,7 +137,9 @@ impl Blockchain { } impl BlockSource for Blockchain { - fn get_header<'a>(&'a self, header_hash: &'a BlockHash, _height_hint: Option) -> AsyncBlockSourceResult<'a, BlockHeaderData> { + fn get_header<'a>( + &'a self, header_hash: &'a BlockHash, _height_hint: Option, + ) -> AsyncBlockSourceResult<'a, BlockHeaderData> { Box::pin(async move { if self.without_headers { return Err(BlockSourceError::persistent("header not found")); @@ -154,7 +159,9 @@ impl BlockSource for Blockchain { }) } - fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, BlockData> { + fn get_block<'a>( + &'a self, header_hash: &'a BlockHash, + ) -> AsyncBlockSourceResult<'a, BlockData> { Box::pin(async move { for (height, block) in self.blocks.iter().enumerate() { if block.header.block_hash() == *header_hash { @@ -191,7 +198,10 @@ impl BlockSource for Blockchain { pub struct NullChainListener; impl chain::Listen for NullChainListener { - fn filtered_block_connected(&self, _header: &Header, _txdata: &chain::transaction::TransactionData, _height: u32) {} + fn filtered_block_connected( + &self, _header: &Header, _txdata: &chain::transaction::TransactionData, _height: u32, + ) { + } fn block_disconnected(&self, _header: &Header, _height: u32) {} } @@ -239,7 +249,9 @@ impl chain::Listen for MockChainListener { } } - fn filtered_block_connected(&self, header: &Header, _txdata: &chain::transaction::TransactionData, height: u32) { + fn filtered_block_connected( + &self, header: &Header, _txdata: &chain::transaction::TransactionData, height: u32, + ) { match self.expected_filtered_blocks_connected.borrow_mut().pop_front() { None => { panic!("Unexpected filtered block connected: {:?}", header.block_hash()); diff --git a/lightning-invoice/src/de.rs b/lightning-invoice/src/de.rs index c75373ea9da..cc39e21f365 100644 --- a/lightning-invoice/src/de.rs +++ b/lightning-invoice/src/de.rs @@ -1,31 +1,34 @@ -#[cfg(feature = "std")] -use std::error; use core::convert::TryFrom; use core::fmt; use core::fmt::{Display, Formatter}; use core::num::ParseIntError; use core::str; use core::str::FromStr; +#[cfg(feature = "std")] +use std::error; use bech32::{u5, FromBase32}; -use bitcoin::{PubkeyHash, ScriptHash}; +use crate::prelude::*; use bitcoin::address::WitnessVersion; -use bitcoin::hashes::Hash; use bitcoin::hashes::sha256; -use crate::prelude::*; +use bitcoin::hashes::Hash; +use bitcoin::{PubkeyHash, ScriptHash}; use lightning::ln::PaymentSecret; use lightning::routing::gossip::RoutingFees; use lightning::routing::router::{RouteHint, RouteHintHop}; use num_traits::{CheckedAdd, CheckedMul}; -use secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; +use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; use secp256k1::PublicKey; -use super::{Bolt11Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, Bolt11InvoiceSignature, PositiveTimestamp, - Bolt11SemanticError, PrivateRoute, Bolt11ParseError, ParseOrSemanticError, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawBolt11Invoice, - constants, SignedRawBolt11Invoice, RawDataPart, Bolt11InvoiceFeatures}; +use super::{ + constants, Bolt11Invoice, Bolt11InvoiceFeatures, Bolt11InvoiceSignature, Bolt11ParseError, + Bolt11SemanticError, Currency, Description, ExpiryTime, Fallback, MinFinalCltvExpiryDelta, + ParseOrSemanticError, PayeePubKey, PositiveTimestamp, PrivateRoute, RawBolt11Invoice, + RawDataPart, RawHrp, RawTaggedField, Sha256, SiPrefix, SignedRawBolt11Invoice, TaggedField, +}; use self::hrp_sm::parse_hrp; @@ -52,7 +55,7 @@ mod hrp_sm { } else { Err(super::Bolt11ParseError::MalformedHRP) } - } + }, States::ParseL => { if read_symbol == 'n' { Ok(States::ParseN) @@ -92,7 +95,6 @@ mod hrp_sm { } } - struct StateMachine { state: States, position: usize, @@ -114,8 +116,8 @@ mod hrp_sm { fn update_range(range: &mut Option>, position: usize) { let new_range = match *range { - None => Range {start: position, end: position + 1}, - Some(ref r) => Range {start: r.start, end: r.end + 1}, + None => Range { start: position, end: position + 1 }, + Some(ref r) => Range { start: r.start, end: r.end + 1 }, }; *range = Some(new_range); } @@ -125,14 +127,14 @@ mod hrp_sm { match next_state { States::ParseCurrencyPrefix => { StateMachine::update_range(&mut self.currency_prefix, self.position) - } + }, States::ParseAmountNumber => { StateMachine::update_range(&mut self.amount_number, self.position) }, States::ParseAmountSiPrefix => { StateMachine::update_range(&mut self.amount_si_prefix, self.position) }, - _ => {} + _ => {}, } self.position += 1; @@ -167,18 +169,14 @@ mod hrp_sm { return Err(super::Bolt11ParseError::MalformedHRP); } - let currency = sm.currency_prefix().clone() - .map(|r| &input[r]).unwrap_or(""); - let amount = sm.amount_number().clone() - .map(|r| &input[r]).unwrap_or(""); - let si = sm.amount_si_prefix().clone() - .map(|r| &input[r]).unwrap_or(""); + let currency = sm.currency_prefix().clone().map(|r| &input[r]).unwrap_or(""); + let amount = sm.amount_number().clone().map(|r| &input[r]).unwrap_or(""); + let si = sm.amount_si_prefix().clone().map(|r| &input[r]).unwrap_or(""); Ok((currency, amount, si)) } } - impl FromStr for super::Currency { type Err = Bolt11ParseError; @@ -189,7 +187,7 @@ impl FromStr for super::Currency { "bcrt" => Ok(Currency::Regtest), "sb" => Ok(Currency::Simnet), "tbs" => Ok(Currency::Signet), - _ => Err(Bolt11ParseError::UnknownCurrency) + _ => Err(Bolt11ParseError::UnknownCurrency), } } } @@ -204,7 +202,7 @@ impl FromStr for SiPrefix { "u" => Ok(Micro), "n" => Ok(Nano), "p" => Ok(Pico), - _ => Err(Bolt11ParseError::UnknownSiPrefix) + _ => Err(Bolt11ParseError::UnknownSiPrefix), } } } @@ -281,18 +279,12 @@ impl FromStr for SignedRawBolt11Invoice { } let raw_hrp: RawHrp = hrp.parse()?; - let data_part = RawDataPart::from_base32(&data[..data.len()-104])?; + let data_part = RawDataPart::from_base32(&data[..data.len() - 104])?; Ok(SignedRawBolt11Invoice { - raw_invoice: RawBolt11Invoice { - hrp: raw_hrp, - data: data_part, - }, - hash: RawBolt11Invoice::hash_from_parts( - hrp.as_bytes(), - &data[..data.len()-104] - ), - signature: Bolt11InvoiceSignature::from_base32(&data[data.len()-104..])?, + raw_invoice: RawBolt11Invoice { hrp: raw_hrp, data: data_part }, + hash: RawBolt11Invoice::hash_from_parts(hrp.as_bytes(), &data[..data.len() - 104]), + signature: Bolt11InvoiceSignature::from_base32(&data[data.len() - 104..])?, }) } } @@ -305,11 +297,7 @@ impl FromStr for RawHrp { let currency = parts.0.parse::()?; - let amount = if !parts.1.is_empty() { - Some(parts.1.parse::()?) - } else { - None - }; + let amount = if !parts.1.is_empty() { Some(parts.1.parse::()?) } else { None }; let si_prefix: Option = if parts.2.is_empty() { None @@ -323,11 +311,7 @@ impl FromStr for RawHrp { Some(si) }; - Ok(RawHrp { - currency, - raw_amount: amount, - si_prefix, - }) + Ok(RawHrp { currency, raw_amount: amount, si_prefix }) } } @@ -335,17 +319,15 @@ impl FromBase32 for RawDataPart { type Err = Bolt11ParseError; fn from_base32(data: &[u5]) -> Result { - if data.len() < 7 { // timestamp length + if data.len() < 7 { + // timestamp length return Err(Bolt11ParseError::TooShortDataPart); } let timestamp = PositiveTimestamp::from_base32(&data[0..7])?; let tagged = parse_tagged_parts(&data[7..])?; - Ok(RawDataPart { - timestamp, - tagged_fields: tagged, - }) + Ok(RawDataPart { timestamp, tagged_fields: tagged }) } } @@ -354,10 +336,11 @@ impl FromBase32 for PositiveTimestamp { fn from_base32(b32: &[u5]) -> Result { if b32.len() != 7 { - return Err(Bolt11ParseError::InvalidSliceLength("PositiveTimestamp::from_base32()".into())); + return Err(Bolt11ParseError::InvalidSliceLength( + "PositiveTimestamp::from_base32()".into(), + )); } - let timestamp: u64 = parse_int_be(b32, 32) - .expect("7*5bit < 64bit, no overflow possible"); + let timestamp: u64 = parse_int_be(b32, 32).expect("7*5bit < 64bit, no overflow possible"); match PositiveTimestamp::from_unix_timestamp(timestamp) { Ok(t) => Ok(t), Err(_) => unreachable!(), @@ -369,28 +352,27 @@ impl FromBase32 for Bolt11InvoiceSignature { type Err = Bolt11ParseError; fn from_base32(signature: &[u5]) -> Result { if signature.len() != 104 { - return Err(Bolt11ParseError::InvalidSliceLength("Bolt11InvoiceSignature::from_base32()".into())); + return Err(Bolt11ParseError::InvalidSliceLength( + "Bolt11InvoiceSignature::from_base32()".into(), + )); } let recoverable_signature_bytes = Vec::::from_base32(signature)?; let signature = &recoverable_signature_bytes[0..64]; let recovery_id = RecoveryId::from_i32(recoverable_signature_bytes[64] as i32)?; - Ok(Bolt11InvoiceSignature(RecoverableSignature::from_compact( - signature, - recovery_id - )?)) + Ok(Bolt11InvoiceSignature(RecoverableSignature::from_compact(signature, recovery_id)?)) } } pub(crate) fn parse_int_be(digits: &[U], base: T) -> Option - where T: CheckedAdd + CheckedMul + From + Default, - U: Into + Copy +where + T: CheckedAdd + CheckedMul + From + Default, + U: Into + Copy, { - digits.iter().fold(Some(Default::default()), |acc, b| - acc - .and_then(|x| x.checked_mul(&base)) + digits.iter().fold(Some(Default::default()), |acc, b| { + acc.and_then(|x| x.checked_mul(&base)) .and_then(|x| x.checked_add(&(Into::::into(*b)).into())) - ) + }) } fn parse_tagged_parts(data: &[u5]) -> Result, Bolt11ParseError> { @@ -418,13 +400,12 @@ fn parse_tagged_parts(data: &[u5]) -> Result, Bolt11ParseErr data = &data[last_element..]; match TaggedField::from_base32(field) { - Ok(field) => { - parts.push(RawTaggedField::KnownSemantics(field)) - }, - Err(Bolt11ParseError::Skip)|Err(Bolt11ParseError::Bech32Error(bech32::Error::InvalidLength)) => { + Ok(field) => parts.push(RawTaggedField::KnownSemantics(field)), + Err(Bolt11ParseError::Skip) + | Err(Bolt11ParseError::Bech32Error(bech32::Error::InvalidLength)) => { parts.push(RawTaggedField::UnknownSemantics(field.into())) }, - Err(e) => {return Err(e)} + Err(e) => return Err(e), } } Ok(parts) @@ -439,35 +420,46 @@ impl FromBase32 for TaggedField { } let tag = field[0]; - let field_data = &field[3..]; + let field_data = &field[3..]; match tag.to_u8() { - constants::TAG_PAYMENT_HASH => - Ok(TaggedField::PaymentHash(Sha256::from_base32(field_data)?)), - constants::TAG_DESCRIPTION => - Ok(TaggedField::Description(Description::from_base32(field_data)?)), - constants::TAG_PAYEE_PUB_KEY => - Ok(TaggedField::PayeePubKey(PayeePubKey::from_base32(field_data)?)), - constants::TAG_DESCRIPTION_HASH => - Ok(TaggedField::DescriptionHash(Sha256::from_base32(field_data)?)), - constants::TAG_EXPIRY_TIME => - Ok(TaggedField::ExpiryTime(ExpiryTime::from_base32(field_data)?)), - constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA => - Ok(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta::from_base32(field_data)?)), - constants::TAG_FALLBACK => - Ok(TaggedField::Fallback(Fallback::from_base32(field_data)?)), - constants::TAG_PRIVATE_ROUTE => - Ok(TaggedField::PrivateRoute(PrivateRoute::from_base32(field_data)?)), - constants::TAG_PAYMENT_SECRET => - Ok(TaggedField::PaymentSecret(PaymentSecret::from_base32(field_data)?)), - constants::TAG_PAYMENT_METADATA => - Ok(TaggedField::PaymentMetadata(Vec::::from_base32(field_data)?)), - constants::TAG_FEATURES => - Ok(TaggedField::Features(Bolt11InvoiceFeatures::from_base32(field_data)?)), + constants::TAG_PAYMENT_HASH => { + Ok(TaggedField::PaymentHash(Sha256::from_base32(field_data)?)) + }, + constants::TAG_DESCRIPTION => { + Ok(TaggedField::Description(Description::from_base32(field_data)?)) + }, + constants::TAG_PAYEE_PUB_KEY => { + Ok(TaggedField::PayeePubKey(PayeePubKey::from_base32(field_data)?)) + }, + constants::TAG_DESCRIPTION_HASH => { + Ok(TaggedField::DescriptionHash(Sha256::from_base32(field_data)?)) + }, + constants::TAG_EXPIRY_TIME => { + Ok(TaggedField::ExpiryTime(ExpiryTime::from_base32(field_data)?)) + }, + constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA => Ok(TaggedField::MinFinalCltvExpiryDelta( + MinFinalCltvExpiryDelta::from_base32(field_data)?, + )), + constants::TAG_FALLBACK => { + Ok(TaggedField::Fallback(Fallback::from_base32(field_data)?)) + }, + constants::TAG_PRIVATE_ROUTE => { + Ok(TaggedField::PrivateRoute(PrivateRoute::from_base32(field_data)?)) + }, + constants::TAG_PAYMENT_SECRET => { + Ok(TaggedField::PaymentSecret(PaymentSecret::from_base32(field_data)?)) + }, + constants::TAG_PAYMENT_METADATA => { + Ok(TaggedField::PaymentMetadata(Vec::::from_base32(field_data)?)) + }, + constants::TAG_FEATURES => { + Ok(TaggedField::Features(Bolt11InvoiceFeatures::from_base32(field_data)?)) + }, _ => { // "A reader MUST skip over unknown fields" Err(Bolt11ParseError::Skip) - } + }, } } } @@ -480,8 +472,10 @@ impl FromBase32 for Sha256 { // "A reader MUST skip over […] a p, [or] h […] field that does not have data_length 52 […]." Err(Bolt11ParseError::Skip) } else { - Ok(Sha256(sha256::Hash::from_slice(&Vec::::from_base32(field_data)?) - .expect("length was checked before (52 u5 -> 32 u8)"))) + Ok(Sha256( + sha256::Hash::from_slice(&Vec::::from_base32(field_data)?) + .expect("length was checked before (52 u5 -> 32 u8)"), + )) } } } @@ -492,9 +486,8 @@ impl FromBase32 for Description { fn from_base32(field_data: &[u5]) -> Result { let bytes = Vec::::from_base32(field_data)?; let description = String::from(str::from_utf8(&bytes)?); - Ok(Description::new(description).expect( - "Max len is 639=floor(1023*5/8) since the len field is only 10bits long" - )) + Ok(Description::new(description) + .expect("Max len is 639=floor(1023*5/8) since the len field is only 10bits long")) } } @@ -517,9 +510,7 @@ impl FromBase32 for ExpiryTime { type Err = Bolt11ParseError; fn from_base32(field_data: &[u5]) -> Result { - match parse_int_be::(field_data, 32) - .map(ExpiryTime::from_seconds) - { + match parse_int_be::(field_data, 32).map(ExpiryTime::from_seconds) { Some(t) => Ok(t), None => Err(Bolt11ParseError::IntegerOverflowError), } @@ -555,27 +546,29 @@ impl FromBase32 for Fallback { if bytes.len() < 2 || bytes.len() > 40 { return Err(Bolt11ParseError::InvalidSegWitProgramLength); } - let version = WitnessVersion::try_from(version).expect("0 through 16 are valid SegWit versions"); - Ok(Fallback::SegWitProgram { - version, - program: bytes - }) + let version = WitnessVersion::try_from(version) + .expect("0 through 16 are valid SegWit versions"); + Ok(Fallback::SegWitProgram { version, program: bytes }) }, 17 => { let pkh = match PubkeyHash::from_slice(&bytes) { Ok(pkh) => pkh, - Err(bitcoin::hashes::Error::InvalidLength(_, _)) => return Err(Bolt11ParseError::InvalidPubKeyHashLength), + Err(bitcoin::hashes::Error::InvalidLength(_, _)) => { + return Err(Bolt11ParseError::InvalidPubKeyHashLength) + }, }; Ok(Fallback::PubKeyHash(pkh)) - } + }, 18 => { let sh = match ScriptHash::from_slice(&bytes) { Ok(sh) => sh, - Err(bitcoin::hashes::Error::InvalidLength(_, _)) => return Err(Bolt11ParseError::InvalidScriptHashLength), + Err(bitcoin::hashes::Error::InvalidLength(_, _)) => { + return Err(Bolt11ParseError::InvalidScriptHashLength) + }, }; Ok(Fallback::ScriptHash(sh)) - } - _ => Err(Bolt11ParseError::Skip) + }, + _ => Err(Bolt11ParseError::Skip), } } } @@ -602,10 +595,12 @@ impl FromBase32 for PrivateRoute { let hop = RouteHintHop { src_node_id: PublicKey::from_slice(&hop_bytes[0..33])?, - short_channel_id: parse_int_be(&channel_id, 256).expect("short chan ID slice too big?"), + short_channel_id: parse_int_be(&channel_id, 256) + .expect("short chan ID slice too big?"), fees: RoutingFees { base_msat: parse_int_be(&hop_bytes[41..45], 256).expect("slice too big?"), - proportional_millionths: parse_int_be(&hop_bytes[45..49], 256).expect("slice too big?"), + proportional_millionths: parse_int_be(&hop_bytes[45..49], 256) + .expect("slice too big?"), }, cltv_expiry_delta: parse_int_be(&hop_bytes[49..51], 256).expect("slice too big?"), htlc_minimum_msat: None, @@ -625,19 +620,19 @@ impl Display for Bolt11ParseError { // TODO: find a way to combine the first three arms (e as error::Error?) Bolt11ParseError::Bech32Error(ref e) => { write!(f, "Invalid bech32: {}", e) - } + }, Bolt11ParseError::ParseAmountError(ref e) => { write!(f, "Invalid amount in hrp ({})", e) - } + }, Bolt11ParseError::MalformedSignature(ref e) => { write!(f, "Invalid secp256k1 signature: {}", e) - } + }, Bolt11ParseError::DescriptionDecodeError(ref e) => { write!(f, "Description is not a valid utf-8 string: {}", e) - } + }, Bolt11ParseError::InvalidSliceLength(ref function) => { write!(f, "Slice in function {} had the wrong length", function) - } + }, Bolt11ParseError::BadPrefix => f.write_str("did not begin with 'ln'"), Bolt11ParseError::UnknownCurrency => f.write_str("currency code unknown"), Bolt11ParseError::UnknownSiPrefix => f.write_str("unknown SI prefix"), @@ -664,9 +659,9 @@ impl Display for Bolt11ParseError { Bolt11ParseError::InvalidRecoveryId => { f.write_str("recovery id is out of range (should be in [0,3])") }, - Bolt11ParseError::Skip => { - f.write_str("the tagged field has to be skipped because of an unexpected, but allowed property") - }, + Bolt11ParseError::Skip => f.write_str( + "the tagged field has to be skipped because of an unexpected, but allowed property", + ), } } } @@ -687,13 +682,13 @@ impl error::Error for Bolt11ParseError {} impl error::Error for ParseOrSemanticError {} macro_rules! from_error { - ($my_error:expr, $extern_error:ty) => { - impl From<$extern_error> for Bolt11ParseError { - fn from(e: $extern_error) -> Self { - $my_error(e) - } - } - } + ($my_error:expr, $extern_error:ty) => { + impl From<$extern_error> for Bolt11ParseError { + fn from(e: $extern_error) -> Self { + $my_error(e) + } + } + }; } from_error!(Bolt11ParseError::MalformedSignature, secp256k1::Error); @@ -704,7 +699,7 @@ impl From for Bolt11ParseError { fn from(e: bech32::Error) -> Self { match e { bech32::Error::InvalidPadding => Bolt11ParseError::PaddingError, - _ => Bolt11ParseError::Bech32Error(e) + _ => Bolt11ParseError::Bech32Error(e), } } } @@ -724,27 +719,22 @@ impl From for ParseOrSemanticError { #[cfg(test)] mod test { use crate::de::Bolt11ParseError; - use secp256k1::PublicKey; use bech32::u5; use bitcoin::hashes::sha256; + use secp256k1::PublicKey; use std::str::FromStr; const CHARSET_REV: [i8; 128] = [ - -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, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, - -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, - 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, + 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, + -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, + 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, ]; fn from_bech32(bytes_5b: &[u8]) -> Vec { - bytes_5b - .iter() - .map(|c| u5::try_from_u8(CHARSET_REV[*c as usize] as u8).unwrap()) - .collect() + bytes_5b.iter().map(|c| u5::try_from_u8(CHARSET_REV[*c as usize] as u8).unwrap()).collect() } #[test] @@ -774,21 +764,19 @@ mod test { use crate::Sha256; use bech32::FromBase32; - let input = from_bech32( - "qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq".as_bytes() - ); + let input = from_bech32("qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq".as_bytes()); let hash = sha256::Hash::from_str( - "0001020304050607080900010203040506070809000102030405060708090102" - ).unwrap(); + "0001020304050607080900010203040506070809000102030405060708090102", + ) + .unwrap(); let expected = Ok(Sha256(hash)); assert_eq!(Sha256::from_base32(&input), expected); // make sure hashes of unknown length get skipped - let input_unexpected_length = from_bech32( - "qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypyq".as_bytes() - ); + let input_unexpected_length = + from_bech32("qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypyq".as_bytes()); assert_eq!(Sha256::from_base32(&input_unexpected_length), Err(Bolt11ParseError::Skip)); } @@ -811,18 +799,15 @@ mod test { let pk_bytes = [ 0x03, 0xe7, 0x15, 0x6a, 0xe3, 0x3b, 0x0a, 0x20, 0x8d, 0x07, 0x44, 0x19, 0x91, 0x63, 0x17, 0x7e, 0x90, 0x9e, 0x80, 0x17, 0x6e, 0x55, 0xd9, 0x7a, 0x2f, 0x22, 0x1e, 0xde, - 0x0f, 0x93, 0x4d, 0xd9, 0xad + 0x0f, 0x93, 0x4d, 0xd9, 0xad, ]; - let expected = Ok(PayeePubKey( - PublicKey::from_slice(&pk_bytes[..]).unwrap() - )); + let expected = Ok(PayeePubKey(PublicKey::from_slice(&pk_bytes[..]).unwrap())); assert_eq!(PayeePubKey::from_base32(&input), expected); // expects 33 bytes - let input_unexpected_length = from_bech32( - "q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhvq".as_bytes() - ); + let input_unexpected_length = + from_bech32("q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhvq".as_bytes()); assert_eq!(PayeePubKey::from_base32(&input_unexpected_length), Err(Bolt11ParseError::Skip)); } @@ -836,7 +821,10 @@ mod test { assert_eq!(ExpiryTime::from_base32(&input), expected); let input_too_large = from_bech32("sqqqqqqqqqqqq".as_bytes()); - assert_eq!(ExpiryTime::from_base32(&input_too_large), Err(Bolt11ParseError::IntegerOverflowError)); + assert_eq!( + ExpiryTime::from_base32(&input_too_large), + Err(Bolt11ParseError::IntegerOverflowError) + ); } #[test] @@ -854,55 +842,51 @@ mod test { fn test_parse_fallback() { use crate::Fallback; use bech32::FromBase32; - use bitcoin::{PubkeyHash, ScriptHash}; use bitcoin::address::WitnessVersion; use bitcoin::hashes::Hash; + use bitcoin::{PubkeyHash, ScriptHash}; let cases = vec![ ( from_bech32("3x9et2e20v6pu37c5d9vax37wxq72un98".as_bytes()), - Ok(Fallback::PubKeyHash(PubkeyHash::from_slice(&[ - 0x31, 0x72, 0xb5, 0x65, 0x4f, 0x66, 0x83, 0xc8, 0xfb, 0x14, 0x69, 0x59, 0xd3, - 0x47, 0xce, 0x30, 0x3c, 0xae, 0x4c, 0xa7 - ]).unwrap())) + Ok(Fallback::PubKeyHash( + PubkeyHash::from_slice(&[ + 0x31, 0x72, 0xb5, 0x65, 0x4f, 0x66, 0x83, 0xc8, 0xfb, 0x14, 0x69, 0x59, + 0xd3, 0x47, 0xce, 0x30, 0x3c, 0xae, 0x4c, 0xa7, + ]) + .unwrap(), + )), ), ( from_bech32("j3a24vwu6r8ejrss3axul8rxldph2q7z9".as_bytes()), - Ok(Fallback::ScriptHash(ScriptHash::from_slice(&[ - 0x8f, 0x55, 0x56, 0x3b, 0x9a, 0x19, 0xf3, 0x21, 0xc2, 0x11, 0xe9, 0xb9, 0xf3, - 0x8c, 0xdf, 0x68, 0x6e, 0xa0, 0x78, 0x45 - ]).unwrap())) + Ok(Fallback::ScriptHash( + ScriptHash::from_slice(&[ + 0x8f, 0x55, 0x56, 0x3b, 0x9a, 0x19, 0xf3, 0x21, 0xc2, 0x11, 0xe9, 0xb9, + 0xf3, 0x8c, 0xdf, 0x68, 0x6e, 0xa0, 0x78, 0x45, + ]) + .unwrap(), + )), ), ( from_bech32("qw508d6qejxtdg4y5r3zarvary0c5xw7k".as_bytes()), Ok(Fallback::SegWitProgram { version: WitnessVersion::V0, - program: Vec::from(&[ - 0x75u8, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, 0x45, - 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6 - ][..]) - }) - ), - ( - vec![u5::try_from_u8(21).unwrap(); 41], - Err(Bolt11ParseError::Skip) - ), - ( - vec![], - Err(Bolt11ParseError::UnexpectedEndOfTaggedFields) + program: Vec::from( + &[ + 0x75u8, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, + 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6, + ][..], + ), + }), ), + (vec![u5::try_from_u8(21).unwrap(); 41], Err(Bolt11ParseError::Skip)), + (vec![], Err(Bolt11ParseError::UnexpectedEndOfTaggedFields)), ( vec![u5::try_from_u8(1).unwrap(); 81], - Err(Bolt11ParseError::InvalidSegWitProgramLength) + Err(Bolt11ParseError::InvalidSegWitProgramLength), ), - ( - vec![u5::try_from_u8(17).unwrap(); 1], - Err(Bolt11ParseError::InvalidPubKeyHashLength) - ), - ( - vec![u5::try_from_u8(18).unwrap(); 1], - Err(Bolt11ParseError::InvalidScriptHashLength) - ) + (vec![u5::try_from_u8(17).unwrap(); 1], Err(Bolt11ParseError::InvalidPubKeyHashLength)), + (vec![u5::try_from_u8(18).unwrap(); 1], Err(Bolt11ParseError::InvalidScriptHashLength)), ]; for (input, expected) in cases.into_iter() { @@ -912,11 +896,11 @@ mod test { #[test] fn test_parse_route() { - use lightning::routing::gossip::RoutingFees; - use lightning::routing::router::{RouteHint, RouteHintHop}; + use crate::de::parse_int_be; use crate::PrivateRoute; use bech32::FromBase32; - use crate::de::parse_int_be; + use lightning::routing::gossip::RoutingFees; + use lightning::routing::router::{RouteHint, RouteHintHop}; let input = from_bech32( "q20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqa\ @@ -929,34 +913,32 @@ mod test { &[ 0x02u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3, - 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55 - ][..] - ).unwrap(), - short_channel_id: parse_int_be(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08], 256).expect("short chan ID slice too big?"), - fees: RoutingFees { - base_msat: 1, - proportional_millionths: 20, - }, + 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55, + ][..], + ) + .unwrap(), + short_channel_id: parse_int_be(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08], 256) + .expect("short chan ID slice too big?"), + fees: RoutingFees { base_msat: 1, proportional_millionths: 20 }, cltv_expiry_delta: 3, htlc_minimum_msat: None, - htlc_maximum_msat: None + htlc_maximum_msat: None, }); expected.push(RouteHintHop { src_node_id: PublicKey::from_slice( &[ 0x03u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3, - 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55 - ][..] - ).unwrap(), - short_channel_id: parse_int_be(&[0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a], 256).expect("short chan ID slice too big?"), - fees: RoutingFees { - base_msat: 2, - proportional_millionths: 30, - }, + 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55, + ][..], + ) + .unwrap(), + short_channel_id: parse_int_be(&[0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a], 256) + .expect("short chan ID slice too big?"), + fees: RoutingFees { base_msat: 2, proportional_millionths: 30 }, cltv_expiry_delta: 4, htlc_minimum_msat: None, - htlc_maximum_msat: None + htlc_maximum_msat: None, }); assert_eq!(PrivateRoute::from_base32(&input), Ok(PrivateRoute(RouteHint(expected)))); @@ -969,57 +951,69 @@ mod test { #[test] fn test_payment_secret_and_features_de_and_ser() { - use lightning::ln::features::Bolt11InvoiceFeatures; - use secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; use crate::TaggedField::*; - use crate::{SiPrefix, SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, - Currency, Sha256, PositiveTimestamp}; + use crate::{ + Bolt11InvoiceSignature, Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, + RawHrp, Sha256, SiPrefix, SignedRawBolt11Invoice, + }; + use lightning::ln::features::Bolt11InvoiceFeatures; + use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; // Feature bits 9, 15, and 99 are set. - let expected_features = Bolt11InvoiceFeatures::from_le_bytes(vec![0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8]); + let expected_features = + Bolt11InvoiceFeatures::from_le_bytes(vec![0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8]); let invoice_str = "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqpqsq67gye39hfg3zd8rgc80k32tvy9xk2xunwm5lzexnvpx6fd77en8qaq424dxgt56cag2dpt359k3ssyhetktkpqh24jqnjyw6uqd08sgptq44qu"; - let invoice = SignedRawBolt11Invoice { - raw_invoice: RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: Some(25), - si_prefix: Some(SiPrefix::Milli) - }, - data: RawDataPart { - timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), - tagged_fields: vec ! [ + let invoice = + SignedRawBolt11Invoice { + raw_invoice: RawBolt11Invoice { + hrp: RawHrp { + currency: Currency::Bitcoin, + raw_amount: Some(25), + si_prefix: Some(SiPrefix::Milli), + }, + data: RawDataPart { + timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), + tagged_fields: vec ! [ PaymentHash(Sha256(sha256::Hash::from_str( "0001020304050607080900010203040506070809000102030405060708090102" ).unwrap())).into(), Description(crate::Description::new("coffee beans".to_owned()).unwrap()).into(), PaymentSecret(crate::PaymentSecret([17; 32])).into(), - Features(expected_features).into()]} - }, - hash: [0xb1, 0x96, 0x46, 0xc3, 0xbc, 0x56, 0x76, 0x1d, 0x20, 0x65, 0x6e, 0x0e, 0x32, - 0xec, 0xd2, 0x69, 0x27, 0xb7, 0x62, 0x6e, 0x2a, 0x8b, 0xe6, 0x97, 0x71, 0x9f, - 0xf8, 0x7e, 0x44, 0x54, 0x55, 0xb9], - signature: Bolt11InvoiceSignature(RecoverableSignature::from_compact( - &[0xd7, 0x90, 0x4c, 0xc4, 0xb7, 0x4a, 0x22, 0x26, 0x9c, 0x68, 0xc1, 0xdf, 0x68, - 0xa9, 0x6c, 0x21, 0x4d, 0x65, 0x1b, 0x93, 0x76, 0xe9, 0xf1, 0x64, 0xd3, 0x60, - 0x4d, 0xa4, 0xb7, 0xde, 0xcc, 0xce, 0x0e, 0x82, 0xaa, 0xab, 0x4c, 0x85, 0xd3, - 0x58, 0xea, 0x14, 0xd0, 0xae, 0x34, 0x2d, 0xa3, 0x08, 0x12, 0xf9, 0x5d, 0x97, - 0x60, 0x82, 0xea, 0xac, 0x81, 0x39, 0x11, 0xda, 0xe0, 0x1a, 0xf3, 0xc1], - RecoveryId::from_i32(1).unwrap() - ).unwrap()), + Features(expected_features).into()], + }, + }, + hash: [ + 0xb1, 0x96, 0x46, 0xc3, 0xbc, 0x56, 0x76, 0x1d, 0x20, 0x65, 0x6e, 0x0e, 0x32, + 0xec, 0xd2, 0x69, 0x27, 0xb7, 0x62, 0x6e, 0x2a, 0x8b, 0xe6, 0x97, 0x71, 0x9f, + 0xf8, 0x7e, 0x44, 0x54, 0x55, 0xb9, + ], + signature: Bolt11InvoiceSignature( + RecoverableSignature::from_compact( + &[ + 0xd7, 0x90, 0x4c, 0xc4, 0xb7, 0x4a, 0x22, 0x26, 0x9c, 0x68, 0xc1, 0xdf, + 0x68, 0xa9, 0x6c, 0x21, 0x4d, 0x65, 0x1b, 0x93, 0x76, 0xe9, 0xf1, 0x64, + 0xd3, 0x60, 0x4d, 0xa4, 0xb7, 0xde, 0xcc, 0xce, 0x0e, 0x82, 0xaa, 0xab, + 0x4c, 0x85, 0xd3, 0x58, 0xea, 0x14, 0xd0, 0xae, 0x34, 0x2d, 0xa3, 0x08, + 0x12, 0xf9, 0x5d, 0x97, 0x60, 0x82, 0xea, 0xac, 0x81, 0x39, 0x11, 0xda, + 0xe0, 0x1a, 0xf3, 0xc1, + ], + RecoveryId::from_i32(1).unwrap(), + ) + .unwrap(), + ), }; assert_eq!(invoice_str, invoice.to_string()); - assert_eq!( - invoice_str.parse(), - Ok(invoice) - ); + assert_eq!(invoice_str.parse(), Ok(invoice)); } #[test] fn test_raw_signed_invoice_deserialization() { use crate::TaggedField::*; - use secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; - use crate::{SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, - PositiveTimestamp}; + use crate::{ + Bolt11InvoiceSignature, Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, + RawHrp, Sha256, SignedRawBolt11Invoice, + }; + use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; assert_eq!( "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmw\ diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index df0412bfc5d..1c51494cba6 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -1,14 +1,11 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] #![deny(non_upper_case_globals)] #![deny(non_camel_case_types)] #![deny(non_snake_case)] #![deny(unused_mut)] - #![cfg_attr(docsrs, feature(doc_auto_cfg))] - #![cfg_attr(feature = "strict", deny(warnings))] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] @@ -30,12 +27,13 @@ pub mod payment; pub mod utils; extern crate bech32; -#[macro_use] extern crate lightning; -extern crate num_traits; -extern crate secp256k1; +#[macro_use] +extern crate lightning; extern crate alloc; #[cfg(any(test, feature = "std"))] extern crate core; +extern crate num_traits; +extern crate secp256k1; #[cfg(feature = "serde")] extern crate serde; @@ -43,34 +41,34 @@ extern crate serde; use std::time::SystemTime; use bech32::u5; -use bitcoin::{Address, Network, PubkeyHash, ScriptHash}; use bitcoin::address::{Payload, WitnessProgram, WitnessVersion}; -use bitcoin::hashes::{Hash, sha256}; +use bitcoin::hashes::{sha256, Hash}; +use bitcoin::{Address, Network, PubkeyHash, ScriptHash}; use lightning::ln::features::Bolt11InvoiceFeatures; use lightning::util::invoice::construct_invoice_preimage; +use secp256k1::ecdsa::RecoverableSignature; use secp256k1::PublicKey; use secp256k1::{Message, Secp256k1}; -use secp256k1::ecdsa::RecoverableSignature; use core::cmp::Ordering; -use core::fmt::{Display, Formatter, self}; +use core::fmt::{self, Display, Formatter}; use core::iter::FilterMap; use core::num::ParseIntError; use core::ops::Deref; use core::slice::Iter; -use core::time::Duration; use core::str; +use core::time::Duration; #[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer,Serialize, Serializer, de::Error}; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; #[doc(no_inline)] pub use lightning::ln::PaymentSecret; #[doc(no_inline)] -pub use lightning::routing::router::{RouteHint, RouteHintHop}; -#[doc(no_inline)] pub use lightning::routing::gossip::RoutingFees; +#[doc(no_inline)] +pub use lightning::routing::router::{RouteHint, RouteHintHop}; use lightning::util::string::UntrustedString; mod de; @@ -82,11 +80,11 @@ mod prelude { #[cfg(feature = "hashbrown")] extern crate hashbrown; - pub use alloc::{vec, vec::Vec, string::String}; - #[cfg(not(feature = "hashbrown"))] - pub use std::collections::{HashMap, hash_map}; #[cfg(feature = "hashbrown")] - pub use self::hashbrown::{HashMap, HashSet, hash_map}; + pub use self::hashbrown::{hash_map, HashMap, HashSet}; + pub use alloc::{string::String, vec, vec::Vec}; + #[cfg(not(feature = "hashbrown"))] + pub use std::collections::{hash_map, HashMap}; pub use alloc::string::ToString; } @@ -216,7 +214,14 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18; /// /// This is not exported to bindings users as we likely need to manually select one set of boolean type parameters. #[derive(Eq, PartialEq, Debug, Clone)] -pub struct InvoiceBuilder { +pub struct InvoiceBuilder< + D: tb::Bool, + H: tb::Bool, + T: tb::Bool, + C: tb::Bool, + S: tb::Bool, + M: tb::Bool, +> { currency: Currency, amount: Option, si_prefix: Option, @@ -457,8 +462,10 @@ pub enum TaggedField { /// SHA-256 hash #[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] -pub struct Sha256(/// This is not exported to bindings users as the native hash types are not currently mapped - pub sha256::Hash); +pub struct Sha256( + /// This is not exported to bindings users as the native hash types are not currently mapped + pub sha256::Hash, +); impl Sha256 { /// Constructs a new [`Sha256`] from the given bytes, which are assumed to be the output of a @@ -493,10 +500,7 @@ pub struct MinFinalCltvExpiryDelta(pub u64); #[allow(missing_docs)] #[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] pub enum Fallback { - SegWitProgram { - version: WitnessVersion, - program: Vec, - }, + SegWitProgram { version: WitnessVersion, program: Vec }, PubKeyHash(PubkeyHash), ScriptHash(ScriptHash), } @@ -563,9 +567,20 @@ impl InvoiceBuilder InvoiceBuilder { +impl + InvoiceBuilder +{ /// Helper function to set the completeness flags. - fn set_flags(self) -> InvoiceBuilder { + fn set_flags< + DN: tb::Bool, + HN: tb::Bool, + TN: tb::Bool, + CN: tb::Bool, + SN: tb::Bool, + MN: tb::Bool, + >( + self, + ) -> InvoiceBuilder { InvoiceBuilder:: { currency: self.currency, amount: self.amount, @@ -624,41 +639,37 @@ impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Builds a [`RawBolt11Invoice`] if no [`CreationError`] occurred while construction any of the /// fields. pub fn build_raw(self) -> Result { - // If an error occurred at any time before, return it now if let Some(e) = self.error { return Err(e); } - let hrp = RawHrp { - currency: self.currency, - raw_amount: self.amount, - si_prefix: self.si_prefix, - }; + let hrp = + RawHrp { currency: self.currency, raw_amount: self.amount, si_prefix: self.si_prefix }; let timestamp = self.timestamp.expect("ensured to be Some(t) by type T"); - let tagged_fields = self.tagged_fields.into_iter().map(|tf| { - RawTaggedField::KnownSemantics(tf) - }).collect::>(); + let tagged_fields = self + .tagged_fields + .into_iter() + .map(|tf| RawTaggedField::KnownSemantics(tf)) + .collect::>(); - let data = RawDataPart { - timestamp, - tagged_fields, - }; + let data = RawDataPart { timestamp, tagged_fields }; - Ok(RawBolt11Invoice { - hrp, - data, - }) + Ok(RawBolt11Invoice { hrp, data }) } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Set the description. This function is only available if no description (hash) was set. pub fn description(mut self, description: String) -> InvoiceBuilder { match Description::new(description) { @@ -669,25 +680,27 @@ impl InvoiceBui } /// Set the description hash. This function is only available if no description (hash) was set. - pub fn description_hash(mut self, description_hash: sha256::Hash) -> InvoiceBuilder { + pub fn description_hash( + mut self, description_hash: sha256::Hash, + ) -> InvoiceBuilder { self.tagged_fields.push(TaggedField::DescriptionHash(Sha256(description_hash))); self.set_flags() } /// Set the description or description hash. This function is only available if no description (hash) was set. - pub fn invoice_description(self, description: Bolt11InvoiceDescription) -> InvoiceBuilder { + pub fn invoice_description( + self, description: Bolt11InvoiceDescription, + ) -> InvoiceBuilder { match description { - Bolt11InvoiceDescription::Direct(desc) => { - self.description(desc.clone().into_inner().0) - } - Bolt11InvoiceDescription::Hash(hash) => { - self.description_hash(hash.0) - } + Bolt11InvoiceDescription::Direct(desc) => self.description(desc.clone().into_inner().0), + Bolt11InvoiceDescription::Hash(hash) => self.description_hash(hash.0), } } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Set the payment hash. This function is only available if no payment hash was set. pub fn payment_hash(mut self, hash: sha256::Hash) -> InvoiceBuilder { self.tagged_fields.push(TaggedField::PaymentHash(Sha256(hash))); @@ -695,7 +708,9 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the timestamp to a specific [`SystemTime`]. #[cfg(feature = "std")] pub fn timestamp(mut self, time: SystemTime) -> InvoiceBuilder { @@ -709,7 +724,9 @@ impl InvoiceBui /// Sets the timestamp to a duration since the Unix epoch, dropping the subsecond part (which /// is not representable in BOLT 11 invoices). - pub fn duration_since_epoch(mut self, time: Duration) -> InvoiceBuilder { + pub fn duration_since_epoch( + mut self, time: Duration, + ) -> InvoiceBuilder { match PositiveTimestamp::from_duration_since_epoch(time) { Ok(t) => self.timestamp = Some(t), Err(e) => self.error = Some(e), @@ -727,17 +744,27 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets `min_final_cltv_expiry_delta`. - pub fn min_final_cltv_expiry_delta(mut self, min_final_cltv_expiry_delta: u64) -> InvoiceBuilder { - self.tagged_fields.push(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta(min_final_cltv_expiry_delta))); + pub fn min_final_cltv_expiry_delta( + mut self, min_final_cltv_expiry_delta: u64, + ) -> InvoiceBuilder { + self.tagged_fields.push(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta( + min_final_cltv_expiry_delta, + ))); self.set_flags() } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the payment secret and relevant features. - pub fn payment_secret(mut self, payment_secret: PaymentSecret) -> InvoiceBuilder { + pub fn payment_secret( + mut self, payment_secret: PaymentSecret, + ) -> InvoiceBuilder { let mut found_features = false; for field in self.tagged_fields.iter_mut() { if let TaggedField::Features(f) = field { @@ -757,14 +784,18 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the payment metadata. /// /// By default features are set to *optionally* allow the sender to include the payment metadata. /// If you wish to require that the sender include the metadata (and fail to parse the invoice if /// they don't support payment metadata fields), you need to call /// [`InvoiceBuilder::require_payment_metadata`] after this. - pub fn payment_metadata(mut self, payment_metadata: Vec) -> InvoiceBuilder { + pub fn payment_metadata( + mut self, payment_metadata: Vec, + ) -> InvoiceBuilder { self.tagged_fields.push(TaggedField::PaymentMetadata(payment_metadata)); let mut found_features = false; for field in self.tagged_fields.iter_mut() { @@ -782,7 +813,9 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets forwarding of payment metadata as required. A reader of the invoice which does not /// support sending payment metadata will fail to read the invoice. pub fn require_payment_metadata(mut self) -> InvoiceBuilder { @@ -795,7 +828,9 @@ impl InvoiceBui } } -impl InvoiceBuilder { +impl + InvoiceBuilder +{ /// Sets the `basic_mpp` feature as optional. pub fn basic_mpp(mut self) -> Self { for field in self.tagged_fields.iter_mut() { @@ -812,11 +847,10 @@ impl InvoiceBuilder(self, sign_function: F) -> Result - where F: FnOnce(&Message) -> RecoverableSignature + where + F: FnOnce(&Message) -> RecoverableSignature, { - let invoice = self.try_build_signed::<_, ()>(|hash| { - Ok(sign_function(hash)) - }); + let invoice = self.try_build_signed::<_, ()>(|hash| Ok(sign_function(hash))); match invoice { Ok(i) => Ok(i), @@ -828,8 +862,11 @@ impl InvoiceBuilder(self, sign_function: F) -> Result> - where F: FnOnce(&Message) -> Result + pub fn try_build_signed( + self, sign_function: F, + ) -> Result> + where + F: FnOnce(&Message) -> Result, { let raw = match self.build_raw() { Ok(r) => r, @@ -841,9 +878,7 @@ impl InvoiceBuilder return Err(SignOrCreationError::SignError(e)), }; - let invoice = Bolt11Invoice { - signed_invoice: signed, - }; + let invoice = Bolt11Invoice { signed_invoice: signed }; invoice.check_field_counts().expect("should be ensured by type signature of builder"); invoice.check_feature_bits().expect("should be ensured by type signature of builder"); @@ -853,7 +888,6 @@ impl InvoiceBuilder true, @@ -985,10 +1013,7 @@ impl RawBolt11Invoice { pub fn signable_hash(&self) -> [u8; 32] { use bech32::ToBase32; - RawBolt11Invoice::hash_from_parts( - self.hrp.to_string().as_bytes(), - &self.data.to_base32() - ) + RawBolt11Invoice::hash_from_parts(self.hrp.to_string().as_bytes(), &self.data.to_base32()) } /// Signs the invoice using the supplied `sign_method`. This function MAY fail with an error of @@ -998,7 +1023,8 @@ impl RawBolt11Invoice { /// This is not exported to bindings users as we don't currently support passing function pointers into methods /// explicitly. pub fn sign(self, sign_method: F) -> Result - where F: FnOnce(&Message) -> Result + where + F: FnOnce(&Message) -> Result, { let raw_hash = self.signable_hash(); let hash = Message::from_slice(&raw_hash[..]) @@ -1015,9 +1041,9 @@ impl RawBolt11Invoice { /// Returns an iterator over all tagged fields with known semantics. /// /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap - pub fn known_tagged_fields(&self) - -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> - { + pub fn known_tagged_fields( + &self, + ) -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> { // For 1.14.0 compatibility: closures' types can't be written an fn()->() in the // function's type signature. // TODO: refactor once impl Trait is available @@ -1028,7 +1054,7 @@ impl RawBolt11Invoice { } } - self.data.tagged_fields.iter().filter_map(match_raw ) + self.data.tagged_fields.iter().filter_map(match_raw) } pub fn payment_hash(&self) -> Option<&Sha256> { @@ -1078,7 +1104,7 @@ impl RawBolt11Invoice { pub fn amount_pico_btc(&self) -> Option { self.hrp.raw_amount.map(|v| { - v * self.hrp.si_prefix.as_ref().map_or(1_000_000_000_000, |si| { si.multiplier() }) + v * self.hrp.si_prefix.as_ref().map_or(1_000_000_000_000, |si| si.multiplier()) }) } @@ -1166,10 +1192,13 @@ impl Bolt11Invoice { /// Check that all mandatory fields are present fn check_field_counts(&self) -> Result<(), Bolt11SemanticError> { // "A writer MUST include exactly one p field […]." - let payment_hash_cnt = self.tagged_fields().filter(|&tf| match *tf { - TaggedField::PaymentHash(_) => true, - _ => false, - }).count(); + let payment_hash_cnt = self + .tagged_fields() + .filter(|&tf| match *tf { + TaggedField::PaymentHash(_) => true, + _ => false, + }) + .count(); if payment_hash_cnt < 1 { return Err(Bolt11SemanticError::NoPaymentHash); } else if payment_hash_cnt > 1 { @@ -1177,14 +1206,17 @@ impl Bolt11Invoice { } // "A writer MUST include either exactly one d or exactly one h field." - let description_cnt = self.tagged_fields().filter(|&tf| match *tf { - TaggedField::Description(_) | TaggedField::DescriptionHash(_) => true, - _ => false, - }).count(); - if description_cnt < 1 { + let description_cnt = self + .tagged_fields() + .filter(|&tf| match *tf { + TaggedField::Description(_) | TaggedField::DescriptionHash(_) => true, + _ => false, + }) + .count(); + if description_cnt < 1 { return Err(Bolt11SemanticError::NoDescription); } else if description_cnt > 1 { - return Err(Bolt11SemanticError::MultipleDescriptions); + return Err(Bolt11SemanticError::MultipleDescriptions); } self.check_payment_secret()?; @@ -1195,10 +1227,13 @@ impl Bolt11Invoice { /// Checks that there is exactly one payment secret field fn check_payment_secret(&self) -> Result<(), Bolt11SemanticError> { // "A writer MUST include exactly one `s` field." - let payment_secret_count = self.tagged_fields().filter(|&tf| match *tf { - TaggedField::PaymentSecret(_) => true, - _ => false, - }).count(); + let payment_secret_count = self + .tagged_fields() + .filter(|&tf| match *tf { + TaggedField::PaymentSecret(_) => true, + _ => false, + }) + .count(); if payment_secret_count < 1 { return Err(Bolt11SemanticError::NoPaymentSecret); } else if payment_secret_count > 1 { @@ -1247,10 +1282,12 @@ impl Bolt11Invoice { /// Check that the invoice is signed correctly and that key recovery works pub fn check_signature(&self) -> Result<(), Bolt11SemanticError> { match self.signed_invoice.recover_payee_pub_key() { - Err(secp256k1::Error::InvalidRecoveryId) => - return Err(Bolt11SemanticError::InvalidRecoveryId), - Err(secp256k1::Error::InvalidSignature) => - return Err(Bolt11SemanticError::InvalidSignature), + Err(secp256k1::Error::InvalidRecoveryId) => { + return Err(Bolt11SemanticError::InvalidRecoveryId) + }, + Err(secp256k1::Error::InvalidSignature) => { + return Err(Bolt11SemanticError::InvalidSignature) + }, Err(e) => panic!("no other error may occur, got {:?}", e), Ok(_) => {}, } @@ -1282,10 +1319,10 @@ impl Bolt11Invoice { /// /// assert!(Bolt11Invoice::from_signed(signed).is_ok()); /// ``` - pub fn from_signed(signed_invoice: SignedRawBolt11Invoice) -> Result { - let invoice = Bolt11Invoice { - signed_invoice, - }; + pub fn from_signed( + signed_invoice: SignedRawBolt11Invoice, + ) -> Result { + let invoice = Bolt11Invoice { signed_invoice }; invoice.check_field_counts()?; invoice.check_feature_bits()?; invoice.check_signature()?; @@ -1308,8 +1345,9 @@ impl Bolt11Invoice { /// Returns an iterator over all tagged fields of this `Bolt11Invoice`. /// /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap - pub fn tagged_fields(&self) - -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> { + pub fn tagged_fields( + &self, + ) -> FilterMap, fn(&RawTaggedField) -> Option<&TaggedField>> { self.signed_invoice.raw_invoice().known_tagged_fields() } @@ -1363,7 +1401,8 @@ impl Bolt11Invoice { /// Returns the invoice's expiry time, if present, otherwise [`DEFAULT_EXPIRY_TIME`]. pub fn expiry_time(&self) -> Duration { - self.signed_invoice.expiry_time() + self.signed_invoice + .expiry_time() .map(|x| x.0) .unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME)) } @@ -1386,7 +1425,8 @@ impl Bolt11Invoice { /// Returns the Duration remaining until the invoice expires. #[cfg(feature = "std")] pub fn duration_until_expiry(&self) -> Duration { - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) .map(|now| self.expiration_remaining_from_epoch(now)) .unwrap_or(Duration::from_nanos(0)) } @@ -1402,13 +1442,15 @@ impl Bolt11Invoice { pub fn would_expire(&self, at_time: Duration) -> bool { self.duration_since_epoch() .checked_add(self.expiry_time()) - .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) < at_time + .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) + < at_time } /// Returns the invoice's `min_final_cltv_expiry_delta` time, if present, otherwise /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA`]. pub fn min_final_cltv_expiry_delta(&self) -> u64 { - self.signed_invoice.min_final_cltv_expiry_delta() + self.signed_invoice + .min_final_cltv_expiry_delta() .map(|x| x.0) .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA) } @@ -1422,24 +1464,23 @@ impl Bolt11Invoice { /// Returns a list of all fallback addresses as [`Address`]es pub fn fallback_addresses(&self) -> Vec
{ - self.fallbacks().iter().filter_map(|fallback| { - let payload = match fallback { - Fallback::SegWitProgram { version, program } => { - match WitnessProgram::new(*version, program.clone()) { - Ok(witness_program) => Payload::WitnessProgram(witness_program), - Err(_) => return None, - } - } - Fallback::PubKeyHash(pkh) => { - Payload::PubkeyHash(*pkh) - } - Fallback::ScriptHash(sh) => { - Payload::ScriptHash(*sh) - } - }; - - Some(Address::new(self.network(), payload)) - }).collect() + self.fallbacks() + .iter() + .filter_map(|fallback| { + let payload = match fallback { + Fallback::SegWitProgram { version, program } => { + match WitnessProgram::new(*version, program.clone()) { + Ok(witness_program) => Payload::WitnessProgram(witness_program), + Err(_) => return None, + } + }, + Fallback::PubKeyHash(pkh) => Payload::PubkeyHash(*pkh), + Fallback::ScriptHash(sh) => Payload::ScriptHash(*sh), + }; + + Some(Address::new(self.network(), payload)) + }) + .collect() } /// Returns a list of all routes included in the invoice @@ -1450,8 +1491,12 @@ impl Bolt11Invoice { /// Returns a list of all routes included in the invoice as the underlying hints pub fn route_hints(&self) -> Vec { find_all_extract!( - self.signed_invoice.known_tagged_fields(), TaggedField::PrivateRoute(ref x), x - ).map(|route| (**route).clone()).collect() + self.signed_invoice.known_tagged_fields(), + TaggedField::PrivateRoute(ref x), + x + ) + .map(|route| (**route).clone()) + .collect() } /// Returns the currency for which the invoice was issued @@ -1505,7 +1550,6 @@ impl TaggedField { } impl Description { - /// Creates a new `Description` if `description` is at most 1023 __bytes__ long, /// returns [`CreationError::DescriptionTooLong`] otherwise /// @@ -1654,7 +1698,7 @@ impl Display for CreationError { } #[cfg(feature = "std")] -impl std::error::Error for CreationError { } +impl std::error::Error for CreationError {} /// Errors that may occur when converting a [`RawBolt11Invoice`] to a [`Bolt11Invoice`]. They relate to /// the requirements sections in BOLT #11 @@ -1710,7 +1754,7 @@ impl Display for Bolt11SemanticError { } #[cfg(feature = "std")] -impl std::error::Error for Bolt11SemanticError { } +impl std::error::Error for Bolt11SemanticError {} /// When signing using a fallible method either an user-supplied `SignError` or a [`CreationError`] /// may occur. @@ -1734,13 +1778,19 @@ impl Display for SignOrCreationError { #[cfg(feature = "serde")] impl Serialize for Bolt11Invoice { - fn serialize(&self, serializer: S) -> Result where S: Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { serializer.serialize_str(self.to_string().as_str()) } } #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for Bolt11Invoice { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { let bolt11 = String::deserialize(deserializer)? .parse::() .map_err(|e| D::Error::custom(format_args!("{:?}", e)))?; @@ -1751,8 +1801,8 @@ impl<'de> Deserialize<'de> for Bolt11Invoice { #[cfg(test)] mod test { - use bitcoin::ScriptBuf; use bitcoin::hashes::sha256; + use bitcoin::ScriptBuf; use std::str::FromStr; #[test] @@ -1765,24 +1815,28 @@ mod test { #[test] fn test_calc_invoice_hash() { - use crate::{RawBolt11Invoice, RawHrp, RawDataPart, Currency, PositiveTimestamp}; use crate::TaggedField::*; + use crate::{Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, RawHrp}; let invoice = RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: None, - si_prefix: None, - }, + hrp: RawHrp { currency: Currency::Bitcoin, raw_amount: None, si_prefix: None }, data: RawDataPart { timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), tagged_fields: vec![ - PaymentHash(crate::Sha256(sha256::Hash::from_str( - "0001020304050607080900010203040506070809000102030405060708090102" - ).unwrap())).into(), - Description(crate::Description::new( - "Please consider supporting this project".to_owned() - ).unwrap()).into(), + PaymentHash(crate::Sha256( + sha256::Hash::from_str( + "0001020304050607080900010203040506070809000102030405060708090102", + ) + .unwrap(), + )) + .into(), + Description( + crate::Description::new( + "Please consider supporting this project".to_owned(), + ) + .unwrap(), + ) + .into(), ], }, }; @@ -1790,7 +1844,7 @@ mod test { let expected_hash = [ 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, 0xb2, 0xec, - 0xd5, 0x18, 0xe1, 0xc9 + 0xd5, 0x18, 0xe1, 0xc9, ]; assert_eq!(invoice.signable_hash(), expected_hash) @@ -1799,22 +1853,21 @@ mod test { #[test] fn test_check_signature() { use crate::TaggedField::*; + use crate::{ + Bolt11InvoiceSignature, Currency, PositiveTimestamp, RawBolt11Invoice, RawDataPart, + RawHrp, Sha256, SignedRawBolt11Invoice, + }; + use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; use secp256k1::Secp256k1; - use secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; - use secp256k1::{SecretKey, PublicKey}; - use crate::{SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, - PositiveTimestamp}; - - let invoice = SignedRawBolt11Invoice { - raw_invoice: RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: None, - si_prefix: None, - }, - data: RawDataPart { - timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), - tagged_fields: vec ! [ + use secp256k1::{PublicKey, SecretKey}; + + let invoice = + SignedRawBolt11Invoice { + raw_invoice: RawBolt11Invoice { + hrp: RawHrp { currency: Currency::Bitcoin, raw_amount: None, si_prefix: None }, + data: RawDataPart { + timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), + tagged_fields: vec ! [ PaymentHash(Sha256(sha256::Hash::from_str( "0001020304050607080900010203040506070809000102030405060708090102" ).unwrap())).into(), @@ -1824,25 +1877,28 @@ mod test { ).unwrap() ).into(), ], + }, }, - }, - hash: [ - 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, - 0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, - 0x83, 0x5d, 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9 - ], - signature: Bolt11InvoiceSignature(RecoverableSignature::from_compact( - & [ - 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a, - 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43, - 0x4e, 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f, - 0x42, 0x5f, 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad, - 0x0d, 0x6e, 0x35, 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9, - 0xaa, 0xb1, 0x5e, 0x57, 0x38, 0xb1, 0x1f, 0x12, 0x7f + hash: [ + 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, + 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, + 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9, ], - RecoveryId::from_i32(0).unwrap() - ).unwrap()), - }; + signature: Bolt11InvoiceSignature( + RecoverableSignature::from_compact( + &[ + 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a, + 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43, 0x4e, + 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f, 0x42, 0x5f, + 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad, 0x0d, 0x6e, 0x35, + 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9, 0xaa, 0xb1, 0x5e, 0x57, + 0x38, 0xb1, 0x1f, 0x12, 0x7f, + ], + RecoveryId::from_i32(0).unwrap(), + ) + .unwrap(), + ), + }; assert!(invoice.check_signature()); @@ -1850,17 +1906,18 @@ mod test { &[ 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2, 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca, - 0x3b, 0x2d, 0xb7, 0x34 - ][..] - ).unwrap(); + 0x3b, 0x2d, 0xb7, 0x34, + ][..], + ) + .unwrap(); let public_key = PublicKey::from_secret_key(&Secp256k1::new(), &private_key); assert_eq!(invoice.recover_payee_pub_key(), Ok(crate::PayeePubKey(public_key))); let (raw_invoice, _, _) = invoice.into_parts(); - let new_signed = raw_invoice.sign::<_, ()>(|hash| { - Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) - }).unwrap(); + let new_signed = raw_invoice + .sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) + .unwrap(); assert!(new_signed.check_signature()); } @@ -1868,31 +1925,35 @@ mod test { #[test] fn test_check_feature_bits() { use crate::TaggedField::*; + use crate::{ + Bolt11Invoice, Bolt11SemanticError, Currency, PositiveTimestamp, RawBolt11Invoice, + RawDataPart, RawHrp, Sha256, + }; use lightning::ln::features::Bolt11InvoiceFeatures; use secp256k1::Secp256k1; use secp256k1::SecretKey; - use crate::{Bolt11Invoice, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, PositiveTimestamp, - Bolt11SemanticError}; let private_key = SecretKey::from_slice(&[42; 32]).unwrap(); let payment_secret = lightning::ln::PaymentSecret([21; 32]); let invoice_template = RawBolt11Invoice { - hrp: RawHrp { - currency: Currency::Bitcoin, - raw_amount: None, - si_prefix: None, - }, + hrp: RawHrp { currency: Currency::Bitcoin, raw_amount: None, si_prefix: None }, data: RawDataPart { timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), - tagged_fields: vec ! [ - PaymentHash(Sha256(sha256::Hash::from_str( - "0001020304050607080900010203040506070809000102030405060708090102" - ).unwrap())).into(), + tagged_fields: vec![ + PaymentHash(Sha256( + sha256::Hash::from_str( + "0001020304050607080900010203040506070809000102030405060708090102", + ) + .unwrap(), + )) + .into(), Description( crate::Description::new( - "Please consider supporting this project".to_owned() - ).unwrap() - ).into(), + "Please consider supporting this project".to_owned(), + ) + .unwrap(), + ) + .into(), ], }, }; @@ -1901,8 +1962,11 @@ mod test { let invoice = { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::InvalidFeatures)); // Missing feature bits @@ -1910,8 +1974,11 @@ mod test { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); invoice.data.tagged_fields.push(Features(Bolt11InvoiceFeatures::empty()).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::InvalidFeatures)); let mut payment_secret_features = Bolt11InvoiceFeatures::empty(); @@ -1922,31 +1989,43 @@ mod test { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); invoice.data.tagged_fields.push(Features(payment_secret_features.clone()).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert!(Bolt11Invoice::from_signed(invoice).is_ok()); // No payment secret or features let invoice = { let invoice = invoice_template.clone(); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::NoPaymentSecret)); // No payment secret or feature bits let invoice = { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(Features(Bolt11InvoiceFeatures::empty()).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::NoPaymentSecret)); // Missing payment secret let invoice = { let mut invoice = invoice_template.clone(); invoice.data.tagged_fields.push(Features(payment_secret_features).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::NoPaymentSecret)); // Multiple payment secrets @@ -1954,9 +2033,15 @@ mod test { let mut invoice = invoice_template; invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into()); - invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))) - }.unwrap(); - assert_eq!(Bolt11Invoice::from_signed(invoice), Err(Bolt11SemanticError::MultiplePaymentSecrets)); + invoice.sign::<_, ()>(|hash| { + Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)) + }) + } + .unwrap(); + assert_eq!( + Bolt11Invoice::from_signed(invoice), + Err(Bolt11SemanticError::MultiplePaymentSecrets) + ); } #[test] @@ -1965,22 +2050,15 @@ mod test { let builder = InvoiceBuilder::new(Currency::Bitcoin) .description("Test".into()) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .duration_since_epoch(Duration::from_secs(1234567)); - let invoice = builder.clone() - .amount_milli_satoshis(1500) - .build_raw() - .unwrap(); + let invoice = builder.clone().amount_milli_satoshis(1500).build_raw().unwrap(); assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Nano)); assert_eq!(invoice.hrp.raw_amount, Some(15)); - - let invoice = builder - .amount_milli_satoshis(150) - .build_raw() - .unwrap(); + let invoice = builder.amount_milli_satoshis(150).build_raw().unwrap(); assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Pico)); assert_eq!(invoice.hrp.raw_amount, Some(1500)); @@ -1990,53 +2068,43 @@ mod test { fn test_builder_fail() { use crate::*; use lightning::routing::router::RouteHintHop; - use std::iter::FromIterator; use secp256k1::PublicKey; + use std::iter::FromIterator; let builder = InvoiceBuilder::new(Currency::Bitcoin) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .duration_since_epoch(Duration::from_secs(1234567)) .min_final_cltv_expiry_delta(144); - let too_long_string = String::from_iter( - (0..1024).map(|_| '?') - ); + let too_long_string = String::from_iter((0..1024).map(|_| '?')); - let long_desc_res = builder.clone() - .description(too_long_string) - .build_raw(); + let long_desc_res = builder.clone().description(too_long_string).build_raw(); assert_eq!(long_desc_res, Err(CreationError::DescriptionTooLong)); let route_hop = RouteHintHop { src_node_id: PublicKey::from_slice( - &[ - 0x03, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, - 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, - 0x95, 0xc3, 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55 - ][..] - ).unwrap(), + &[ + 0x03, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c, + 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3, + 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55, + ][..], + ) + .unwrap(), short_channel_id: 0, - fees: RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, cltv_expiry_delta: 0, htlc_minimum_msat: None, htlc_maximum_msat: None, }; let too_long_route = RouteHint(vec![route_hop; 13]); - let long_route_res = builder.clone() - .description("Test".into()) - .private_route(too_long_route) - .build_raw(); + let long_route_res = + builder.clone().description("Test".into()).private_route(too_long_route).build_raw(); assert_eq!(long_route_res, Err(CreationError::RouteTooLong)); let sign_error_res = builder .description("Test".into()) .payment_secret(PaymentSecret([0; 32])) - .try_build_signed(|_| { - Err("ImaginaryError") - }); + .try_build_signed(|_| Err("ImaginaryError")); assert_eq!(sign_error_res, Err(SignOrCreationError::SignError("ImaginaryError"))); } @@ -2045,7 +2113,7 @@ mod test { use crate::*; use lightning::routing::router::RouteHintHop; use secp256k1::Secp256k1; - use secp256k1::{SecretKey, PublicKey}; + use secp256k1::{PublicKey, SecretKey}; use std::time::Duration; let secp_ctx = Secp256k1::new(); @@ -2054,59 +2122,51 @@ mod test { &[ 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2, 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca, - 0x3b, 0x2d, 0xb7, 0x34 - ][..] - ).unwrap(); + 0x3b, 0x2d, 0xb7, 0x34, + ][..], + ) + .unwrap(); let public_key = PublicKey::from_secret_key(&secp_ctx, &private_key); let route_1 = RouteHint(vec![ RouteHintHop { src_node_id: public_key, - short_channel_id: de::parse_int_be(&[123; 8], 256).expect("short chan ID slice too big?"), - fees: RoutingFees { - base_msat: 2, - proportional_millionths: 1, - }, + short_channel_id: de::parse_int_be(&[123; 8], 256) + .expect("short chan ID slice too big?"), + fees: RoutingFees { base_msat: 2, proportional_millionths: 1 }, cltv_expiry_delta: 145, htlc_minimum_msat: None, htlc_maximum_msat: None, }, RouteHintHop { src_node_id: public_key, - short_channel_id: de::parse_int_be(&[42; 8], 256).expect("short chan ID slice too big?"), - fees: RoutingFees { - base_msat: 3, - proportional_millionths: 2, - }, + short_channel_id: de::parse_int_be(&[42; 8], 256) + .expect("short chan ID slice too big?"), + fees: RoutingFees { base_msat: 3, proportional_millionths: 2 }, cltv_expiry_delta: 146, htlc_minimum_msat: None, htlc_maximum_msat: None, - } + }, ]); let route_2 = RouteHint(vec![ RouteHintHop { src_node_id: public_key, short_channel_id: 0, - fees: RoutingFees { - base_msat: 4, - proportional_millionths: 3, - }, + fees: RoutingFees { base_msat: 4, proportional_millionths: 3 }, cltv_expiry_delta: 147, htlc_minimum_msat: None, htlc_maximum_msat: None, }, RouteHintHop { src_node_id: public_key, - short_channel_id: de::parse_int_be(&[1; 8], 256).expect("short chan ID slice too big?"), - fees: RoutingFees { - base_msat: 5, - proportional_millionths: 4, - }, + short_channel_id: de::parse_int_be(&[1; 8], 256) + .expect("short chan ID slice too big?"), + fees: RoutingFees { base_msat: 5, proportional_millionths: 4 }, cltv_expiry_delta: 148, htlc_minimum_msat: None, htlc_maximum_msat: None, - } + }, ]); let builder = InvoiceBuilder::new(Currency::BitcoinTestnet) @@ -2115,17 +2175,18 @@ mod test { .payee_pub_key(public_key) .expiry_time(Duration::from_secs(54321)) .min_final_cltv_expiry_delta(144) - .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap())) + .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[0; 20]).unwrap())) .private_route(route_1.clone()) .private_route(route_2.clone()) - .description_hash(sha256::Hash::from_slice(&[3;32][..]).unwrap()) - .payment_hash(sha256::Hash::from_slice(&[21;32][..]).unwrap()) + .description_hash(sha256::Hash::from_slice(&[3; 32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[21; 32][..]).unwrap()) .payment_secret(PaymentSecret([42; 32])) .basic_mpp(); - let invoice = builder.clone().build_signed(|hash| { - secp_ctx.sign_ecdsa_recoverable(hash, &private_key) - }).unwrap(); + let invoice = builder + .clone() + .build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &private_key)) + .unwrap(); assert!(invoice.check_signature().is_ok()); assert_eq!(invoice.tagged_fields().count(), 10); @@ -2141,15 +2202,24 @@ mod test { assert_eq!(invoice.payee_pub_key(), Some(&public_key)); assert_eq!(invoice.expiry_time(), Duration::from_secs(54321)); assert_eq!(invoice.min_final_cltv_expiry_delta(), 144); - assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap())]); - let address = Address::from_script(&ScriptBuf::new_p2pkh(&PubkeyHash::from_slice(&[0;20]).unwrap()), Network::Testnet).unwrap(); + assert_eq!( + invoice.fallbacks(), + vec![&Fallback::PubKeyHash(PubkeyHash::from_slice(&[0; 20]).unwrap())] + ); + let address = Address::from_script( + &ScriptBuf::new_p2pkh(&PubkeyHash::from_slice(&[0; 20]).unwrap()), + Network::Testnet, + ) + .unwrap(); assert_eq!(invoice.fallback_addresses(), vec![address]); assert_eq!(invoice.private_routes(), vec![&PrivateRoute(route_1), &PrivateRoute(route_2)]); assert_eq!( invoice.description(), - Bolt11InvoiceDescription::Hash(&Sha256(sha256::Hash::from_slice(&[3;32][..]).unwrap())) + Bolt11InvoiceDescription::Hash(&Sha256( + sha256::Hash::from_slice(&[3; 32][..]).unwrap() + )) ); - assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&[21;32][..]).unwrap()); + assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&[21; 32][..]).unwrap()); assert_eq!(invoice.payment_secret(), &PaymentSecret([42; 32])); let mut expected_features = Bolt11InvoiceFeatures::empty(); @@ -2170,7 +2240,7 @@ mod test { let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin) .description("Test".into()) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .payment_secret(PaymentSecret([0; 32])) .duration_since_epoch(Duration::from_secs(1234567)) .build_raw() @@ -2196,7 +2266,7 @@ mod test { let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin) .description("Test".into()) - .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap()) + .payment_hash(sha256::Hash::from_slice(&[0; 32][..]).unwrap()) .payment_secret(PaymentSecret([0; 32])) .duration_since_epoch(Duration::from_secs(1234567)) .build_raw() @@ -2228,7 +2298,8 @@ mod test { j5r6drg6k6zcqj0fcwg"; let invoice = invoice_str.parse::().unwrap(); let serialized_invoice = serde_json::to_string(&invoice).unwrap(); - let deserialized_invoice: super::Bolt11Invoice = serde_json::from_str(serialized_invoice.as_str()).unwrap(); + let deserialized_invoice: super::Bolt11Invoice = + serde_json::from_str(serialized_invoice.as_str()).unwrap(); assert_eq!(invoice, deserialized_invoice); assert_eq!(invoice_str, deserialized_invoice.to_string().as_str()); assert_eq!(invoice_str, serialized_invoice.as_str().trim_matches('\"')); diff --git a/lightning-invoice/src/payment.rs b/lightning-invoice/src/payment.rs index 8196fa9eb89..9a847b1b004 100644 --- a/lightning-invoice/src/payment.rs +++ b/lightning-invoice/src/payment.rs @@ -12,8 +12,8 @@ use crate::Bolt11Invoice; use bitcoin::hashes::Hash; -use lightning::ln::PaymentHash; use lightning::ln::channelmanager::RecipientOnionFields; +use lightning::ln::PaymentHash; use lightning::routing::router::{PaymentParameters, RouteParameters}; /// Builds the necessary parameters to pay or pre-flight probe the given zero-amount @@ -28,8 +28,9 @@ use lightning::routing::router::{PaymentParameters, RouteParameters}; /// /// [`ChannelManager::send_payment`]: lightning::ln::channelmanager::ChannelManager::send_payment /// [`ChannelManager::send_preflight_probes`]: lightning::ln::channelmanager::ChannelManager::send_preflight_probes -pub fn payment_parameters_from_zero_amount_invoice(invoice: &Bolt11Invoice, amount_msat: u64) --> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> { +pub fn payment_parameters_from_zero_amount_invoice( + invoice: &Bolt11Invoice, amount_msat: u64, +) -> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> { if invoice.amount_milli_satoshis().is_some() { Err(()) } else { @@ -48,8 +49,9 @@ pub fn payment_parameters_from_zero_amount_invoice(invoice: &Bolt11Invoice, amou /// /// [`ChannelManager::send_payment`]: lightning::ln::channelmanager::ChannelManager::send_payment /// [`ChannelManager::send_preflight_probes`]: lightning::ln::channelmanager::ChannelManager::send_preflight_probes -pub fn payment_parameters_from_invoice(invoice: &Bolt11Invoice) --> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> { +pub fn payment_parameters_from_invoice( + invoice: &Bolt11Invoice, +) -> Result<(PaymentHash, RecipientOnionFields, RouteParameters), ()> { if let Some(amount_msat) = invoice.amount_milli_satoshis() { Ok(params_from_invoice(invoice, amount_msat)) } else { @@ -57,18 +59,20 @@ pub fn payment_parameters_from_invoice(invoice: &Bolt11Invoice) } } -fn params_from_invoice(invoice: &Bolt11Invoice, amount_msat: u64) --> (PaymentHash, RecipientOnionFields, RouteParameters) { +fn params_from_invoice( + invoice: &Bolt11Invoice, amount_msat: u64, +) -> (PaymentHash, RecipientOnionFields, RouteParameters) { let payment_hash = PaymentHash((*invoice.payment_hash()).to_byte_array()); let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret()); recipient_onion.payment_metadata = invoice.payment_metadata().map(|v| v.clone()); let mut payment_params = PaymentParameters::from_node_id( - invoice.recover_payee_pub_key(), - invoice.min_final_cltv_expiry_delta() as u32 - ) - .with_route_hints(invoice.route_hints()).unwrap(); + invoice.recover_payee_pub_key(), + invoice.min_final_cltv_expiry_delta() as u32, + ) + .with_route_hints(invoice.route_hints()) + .unwrap(); if let Some(expiry) = invoice.expires_at() { payment_params = payment_params.with_expiry_time(expiry.as_secs()); } @@ -83,19 +87,18 @@ fn params_from_invoice(invoice: &Bolt11Invoice, amount_msat: u64) #[cfg(test)] mod tests { use super::*; - use crate::{InvoiceBuilder, Currency}; + use crate::{Currency, InvoiceBuilder}; use bitcoin::hashes::sha256::Hash as Sha256; + use core::time::Duration; use lightning::ln::PaymentSecret; use lightning::routing::router::Payee; - use secp256k1::{SecretKey, PublicKey, Secp256k1}; - use core::time::Duration; + use secp256k1::{PublicKey, Secp256k1, SecretKey}; #[cfg(feature = "std")] use std::time::SystemTime; fn duration_since_epoch() -> Duration { #[cfg(feature = "std")] - let duration_since_epoch = - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); #[cfg(not(feature = "std"))] let duration_since_epoch = Duration::from_secs(1234567); duration_since_epoch @@ -115,9 +118,7 @@ mod tests { .duration_since_epoch(duration_since_epoch()) .min_final_cltv_expiry_delta(144) .amount_milli_satoshis(128) - .build_signed(|hash| { - secp_ctx.sign_ecdsa_recoverable(hash, &private_key) - }) + .build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &private_key)) .unwrap(); assert!(payment_parameters_from_zero_amount_invoice(&invoice, 42).is_err()); @@ -147,14 +148,13 @@ mod tests { .payment_secret(PaymentSecret([0; 32])) .duration_since_epoch(duration_since_epoch()) .min_final_cltv_expiry_delta(144) - .build_signed(|hash| { - secp_ctx.sign_ecdsa_recoverable(hash, &private_key) - }) - .unwrap(); + .build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &private_key)) + .unwrap(); assert!(payment_parameters_from_invoice(&invoice).is_err()); - let (hash, onion, params) = payment_parameters_from_zero_amount_invoice(&invoice, 42).unwrap(); + let (hash, onion, params) = + payment_parameters_from_zero_amount_invoice(&invoice, 42).unwrap(); assert_eq!(&hash.0[..], &payment_hash[..]); assert_eq!(onion.payment_secret, Some(PaymentSecret([0; 32]))); assert_eq!(params.final_value_msat, 42); @@ -170,9 +170,9 @@ mod tests { #[cfg(feature = "std")] fn payment_metadata_end_to_end() { use lightning::events::Event; - use lightning::ln::channelmanager::{Retry, PaymentId}; - use lightning::ln::msgs::ChannelMessageHandler; + use lightning::ln::channelmanager::{PaymentId, Retry}; use lightning::ln::functional_test_utils::*; + use lightning::ln::msgs::ChannelMessageHandler; // Test that a payment metadata read from an invoice passed to `pay_invoice` makes it all // the way out through the `PaymentClaimable` event. let chanmon_cfgs = create_chanmon_cfgs(2); @@ -195,13 +195,18 @@ mod tests { .amount_milli_satoshis(50_000) .payment_metadata(payment_metadata.clone()) .build_signed(|hash| { - Secp256k1::new().sign_ecdsa_recoverable(hash, - &nodes[1].keys_manager.backing.get_node_secret_key()) + Secp256k1::new().sign_ecdsa_recoverable( + hash, + &nodes[1].keys_manager.backing.get_node_secret_key(), + ) }) .unwrap(); let (hash, onion, params) = payment_parameters_from_invoice(&invoice).unwrap(); - nodes[0].node.send_payment(hash, onion, PaymentId(hash.0), params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment(hash, onion, PaymentId(hash.0), params, Retry::Attempts(0)) + .unwrap(); check_added_monitors(&nodes[0], 1); let send_event = SendEvent::from_node(&nodes[0]); nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]); @@ -215,7 +220,7 @@ mod tests { Event::PaymentClaimable { onion_fields, .. } => { assert_eq!(Some(payment_metadata), onion_fields.unwrap().payment_metadata); }, - _ => panic!("Unexpected event") + _ => panic!("Unexpected event"), } } } diff --git a/lightning-invoice/src/ser.rs b/lightning-invoice/src/ser.rs index dc63783bfa3..680a256e125 100644 --- a/lightning-invoice/src/ser.rs +++ b/lightning-invoice/src/ser.rs @@ -1,10 +1,13 @@ +use crate::prelude::*; +use bech32::{u5, Base32Len, ToBase32, WriteBase32}; use core::fmt; use core::fmt::{Display, Formatter}; -use bech32::{ToBase32, u5, WriteBase32, Base32Len}; -use crate::prelude::*; -use super::{Bolt11Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, Bolt11InvoiceSignature, PositiveTimestamp, - PrivateRoute, Description, RawTaggedField, Currency, RawHrp, SiPrefix, constants, SignedRawBolt11Invoice, RawDataPart}; +use super::{ + constants, Bolt11Invoice, Bolt11InvoiceSignature, Currency, Description, ExpiryTime, Fallback, + MinFinalCltvExpiryDelta, PayeePubKey, PositiveTimestamp, PrivateRoute, RawDataPart, RawHrp, + RawTaggedField, Sha256, SiPrefix, SignedRawBolt11Invoice, TaggedField, +}; /// Converts a stream of bytes written to it to base32. On finalization the according padding will /// be applied. That means the results of writing two data blocks with one or two `BytesToBase32` @@ -24,11 +27,7 @@ impl<'a, W: WriteBase32> BytesToBase32<'a, W> { /// Create a new bytes-to-base32 converter with `writer` as a sink for the resulting base32 /// data. pub fn new(writer: &'a mut W) -> BytesToBase32<'a, W> { - BytesToBase32 { - writer, - buffer: 0, - buffer_bits: 0, - } + BytesToBase32 { writer, buffer: 0, buffer_bits: 0 } } /// Add more bytes to the current conversion unit @@ -44,9 +43,7 @@ impl<'a, W: WriteBase32> BytesToBase32<'a, W> { // buffer holds too many bits, so we don't have to combine buffer bits with new bits // from this rounds byte. if self.buffer_bits >= 5 { - self.writer.write_u5( - u5::try_from_u8((self.buffer & 0b11111000) >> 3 ).expect("<32") - )?; + self.writer.write_u5(u5::try_from_u8((self.buffer & 0b11111000) >> 3).expect("<32"))?; self.buffer <<= 5; self.buffer_bits -= 5; } @@ -63,18 +60,16 @@ impl<'a, W: WriteBase32> BytesToBase32<'a, W> { Ok(()) } - pub fn finalize(mut self) -> Result<(), W::Err> { + pub fn finalize(mut self) -> Result<(), W::Err> { self.inner_finalize()?; core::mem::forget(self); Ok(()) } - fn inner_finalize(&mut self) -> Result<(), W::Err>{ + fn inner_finalize(&mut self) -> Result<(), W::Err> { // There can be at most two u5s left in the buffer after processing all bytes, write them. if self.buffer_bits >= 5 { - self.writer.write_u5( - u5::try_from_u8((self.buffer & 0b11111000) >> 3).expect("<32") - )?; + self.writer.write_u5(u5::try_from_u8((self.buffer & 0b11111000) >> 3).expect("<32"))?; self.buffer <<= 5; self.buffer_bits -= 5; } @@ -115,7 +110,7 @@ impl Display for Bolt11Invoice { impl Display for SignedRawBolt11Invoice { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { let hrp = self.raw_invoice.hrp.to_string(); - let mut data = self.raw_invoice.data.to_base32(); + let mut data = self.raw_invoice.data.to_base32(); data.extend_from_slice(&self.signature.to_base32()); bech32::encode_to_fmt(f, &hrp, data, bech32::Variant::Bech32).expect("HRP is valid")?; @@ -137,13 +132,7 @@ impl Display for RawHrp { None => String::new(), }; - write!( - f, - "ln{}{}{}", - self.currency, - amount, - si_prefix - ) + write!(f, "ln{}{}{}", self.currency, amount, si_prefix) } } @@ -162,7 +151,9 @@ impl Display for Currency { impl Display for SiPrefix { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { - write!(f, "{}", + write!( + f, + "{}", match *self { SiPrefix::Milli => "m", SiPrefix::Micro => "u", @@ -215,7 +206,8 @@ fn encode_int_be_base256>(int: T) -> Vec { /// Appends the default value of `T` to the front of the `in_vec` till it reaches the length /// `target_length`. If `in_vec` already is too lang `None` is returned. fn try_stretch(mut in_vec: Vec, target_len: usize) -> Option> - where T: Default + Copy +where + T: Default + Copy, { if in_vec.len() > target_len { None @@ -248,7 +240,7 @@ impl ToBase32 for PositiveTimestamp { // FIXME: use writer for int encoding writer.write( &try_stretch(encode_int_be_base32(self.as_unix_timestamp()), 7) - .expect("Can't be longer due than 7 u5s due to timestamp bounds") + .expect("Can't be longer due than 7 u5s due to timestamp bounds"), ) } } @@ -256,12 +248,8 @@ impl ToBase32 for PositiveTimestamp { impl ToBase32 for RawTaggedField { fn write_base32(&self, writer: &mut W) -> Result<(), ::Err> { match *self { - RawTaggedField::UnknownSemantics(ref content) => { - writer.write(content) - }, - RawTaggedField::KnownSemantics(ref tagged_field) => { - tagged_field.write_base32(writer) - } + RawTaggedField::UnknownSemantics(ref content) => writer.write(content), + RawTaggedField::KnownSemantics(ref tagged_field) => tagged_field.write_base32(writer), } } } @@ -279,13 +267,13 @@ impl Base32Len for Sha256 { impl ToBase32 for Description { fn write_base32(&self, writer: &mut W) -> Result<(), ::Err> { - self.0.0.as_bytes().write_base32(writer) + self.0 .0.as_bytes().write_base32(writer) } } impl Base32Len for Description { fn base32_len(&self) -> usize { - self.0.0.as_bytes().base32_len() + self.0 .0.as_bytes().base32_len() } } @@ -328,7 +316,7 @@ impl Base32Len for MinFinalCltvExpiryDelta { impl ToBase32 for Fallback { fn write_base32(&self, writer: &mut W) -> Result<(), ::Err> { match *self { - Fallback::SegWitProgram {version: v, program: ref p} => { + Fallback::SegWitProgram { version: v, program: ref p } => { writer.write_u5(Into::::into(v))?; p.write_base32(writer) }, @@ -339,7 +327,7 @@ impl ToBase32 for Fallback { Fallback::ScriptHash(ref hash) => { writer.write_u5(u5::try_from_u8(18).expect("18 < 32"))?; (&hash[..]).write_base32(writer) - } + }, } } } @@ -347,12 +335,10 @@ impl ToBase32 for Fallback { impl Base32Len for Fallback { fn base32_len(&self) -> usize { match *self { - Fallback::SegWitProgram {program: ref p, ..} => { + Fallback::SegWitProgram { program: ref p, .. } => { bytes_size_to_base32_size(p.len()) + 1 }, - Fallback::PubKeyHash(_) | Fallback::ScriptHash(_) => { - 33 - }, + Fallback::PubKeyHash(_) | Fallback::ScriptHash(_) => 33, } } } @@ -363,28 +349,21 @@ impl ToBase32 for PrivateRoute { for hop in (self.0).0.iter() { converter.append(&hop.src_node_id.serialize()[..])?; - let short_channel_id = try_stretch( - encode_int_be_base256(hop.short_channel_id), - 8 - ).expect("sizeof(u64) == 8"); + let short_channel_id = try_stretch(encode_int_be_base256(hop.short_channel_id), 8) + .expect("sizeof(u64) == 8"); converter.append(&short_channel_id)?; - let fee_base_msat = try_stretch( - encode_int_be_base256(hop.fees.base_msat), - 4 - ).expect("sizeof(u32) == 4"); + let fee_base_msat = try_stretch(encode_int_be_base256(hop.fees.base_msat), 4) + .expect("sizeof(u32) == 4"); converter.append(&fee_base_msat)?; - let fee_proportional_millionths = try_stretch( - encode_int_be_base256(hop.fees.proportional_millionths), - 4 - ).expect("sizeof(u32) == 4"); + let fee_proportional_millionths = + try_stretch(encode_int_be_base256(hop.fees.proportional_millionths), 4) + .expect("sizeof(u32) == 4"); converter.append(&fee_proportional_millionths)?; - let cltv_expiry_delta = try_stretch( - encode_int_be_base256(hop.cltv_expiry_delta), - 2 - ).expect("sizeof(u16) == 2"); + let cltv_expiry_delta = try_stretch(encode_int_be_base256(hop.cltv_expiry_delta), 2) + .expect("sizeof(u16) == 2"); converter.append(&cltv_expiry_delta)?; } @@ -404,17 +383,18 @@ impl ToBase32 for TaggedField { /// Writes a tagged field: tag, length and data. `tag` should be in `0..32` otherwise the /// function will panic. fn write_tagged_field(writer: &mut W, tag: u8, payload: &P) -> Result<(), W::Err> - where W: WriteBase32, - P: ToBase32 + Base32Len, + where + W: WriteBase32, + P: ToBase32 + Base32Len, { let len = payload.base32_len(); assert!(len < 1024, "Every tagged field data can be at most 1023 bytes long."); writer.write_u5(u5::try_from_u8(tag).expect("invalid tag, not in 0..32"))?; - writer.write(&try_stretch( - encode_int_be_base32(len as u64), - 2 - ).expect("Can't be longer than 2, see assert above."))?; + writer.write( + &try_stretch(encode_int_be_base32(len as u64), 2) + .expect("Can't be longer than 2, see assert above."), + )?; payload.write_base32(writer) } @@ -444,10 +424,10 @@ impl ToBase32 for TaggedField { write_tagged_field(writer, constants::TAG_PRIVATE_ROUTE, route_hops) }, TaggedField::PaymentSecret(ref payment_secret) => { - write_tagged_field(writer, constants::TAG_PAYMENT_SECRET, payment_secret) + write_tagged_field(writer, constants::TAG_PAYMENT_SECRET, payment_secret) }, TaggedField::PaymentMetadata(ref payment_metadata) => { - write_tagged_field(writer, constants::TAG_PAYMENT_METADATA, payment_metadata) + write_tagged_field(writer, constants::TAG_PAYMENT_METADATA, payment_metadata) }, TaggedField::Features(ref features) => { write_tagged_field(writer, constants::TAG_FEATURES, features) diff --git a/lightning-invoice/src/tb.rs b/lightning-invoice/src/tb.rs index dde8a53f99c..9f8a5135906 100644 --- a/lightning-invoice/src/tb.rs +++ b/lightning-invoice/src/tb.rs @@ -7,4 +7,4 @@ pub struct True {} pub struct False {} impl Bool for True {} -impl Bool for False {} \ No newline at end of file +impl Bool for False {} diff --git a/lightning-invoice/src/utils.rs b/lightning-invoice/src/utils.rs index 5e8b72467e5..4860c58b006 100644 --- a/lightning-invoice/src/utils.rs +++ b/lightning-invoice/src/utils.rs @@ -2,23 +2,23 @@ use crate::{Bolt11Invoice, CreationError, Currency, InvoiceBuilder, SignOrCreationError}; -use crate::{prelude::*, Description, Bolt11InvoiceDescription, Sha256}; +use crate::{prelude::*, Bolt11InvoiceDescription, Description, Sha256}; use bech32::ToBase32; use bitcoin::hashes::Hash; +use core::iter::Iterator; +use core::ops::Deref; +use core::time::Duration; use lightning::chain; use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use lightning::sign::{Recipient, NodeSigner, SignerProvider, EntropySource}; -use lightning::ln::{PaymentHash, PaymentSecret}; use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, MIN_FINAL_CLTV_EXPIRY_DELTA}; use lightning::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA}; use lightning::ln::inbound_payment::{create, create_from_hash, ExpandedKey}; +use lightning::ln::{PaymentHash, PaymentSecret}; use lightning::routing::gossip::RoutingFees; use lightning::routing::router::{RouteHint, RouteHintHop, Router}; +use lightning::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; use lightning::util::logger::{Logger, Record}; use secp256k1::PublicKey; -use core::ops::Deref; -use core::time::Duration; -use core::iter::Iterator; /// 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,8 +62,9 @@ use core::iter::Iterator; /// 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, @@ -71,10 +72,19 @@ where L::Target: Logger, { let description = Description::new(description).map_err(SignOrCreationError::CreationError)?; - let description = Bolt11InvoiceDescription::Direct(&description,); + 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, ) } @@ -119,7 +129,8 @@ where 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, @@ -127,40 +138,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.0.0.clone()) - } - Bolt11InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0), + InvoiceBuilder::new(network).description(description.0 .0.clone()) + }, + Bolt11InvoiceDescription::Hash(hash) => { + InvoiceBuilder::new(network).description_hash(hash.0) + }, }; // If we ever see performance here being too slow then we should probably take this ExpandedKey as a parameter instead. @@ -171,8 +194,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))?; @@ -183,15 +205,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) @@ -199,28 +224,35 @@ 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 hrp_str = raw_invoice.hrp.to_string(); let hrp_bytes = hrp_str.as_bytes(); let data_without_signature = raw_invoice.data.to_base32(); - let signed_raw_invoice = raw_invoice.sign(|_| node_signer.sign_invoice(hrp_bytes, &data_without_signature, Recipient::PhantomNode)); + let signed_raw_invoice = raw_invoice.sign(|_| { + node_signer.sign_invoice(hrp_bytes, &data_without_signature, Recipient::PhantomNode) + }); match signed_raw_invoice { Ok(inv) => Ok(Bolt11Invoice::from_signed(inv).unwrap()), - Err(e) => Err(SignOrCreationError::SignError(e)) + Err(e) => Err(SignOrCreationError::SignError(e)), } } @@ -232,16 +264,20 @@ where /// * Select one hint from each node, up to three hints or until we run out of hints. /// /// [`PhantomKeysManager`]: lightning::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 @@ -265,10 +301,7 @@ where hint.0.push(RouteHintHop { src_node_id: real_node_pubkey, short_channel_id: phantom_scid, - fees: RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA, htlc_minimum_msat: None, htlc_maximum_msat: None, @@ -329,7 +362,16 @@ fn rotate_through_iterators>(mut vecs: Vec) -> impl /// confirmations during routing. /// /// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::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, + L: Deref, +>( channelmanager: &ChannelManager, node_signer: NS, logger: L, network: Currency, amt_msat: Option, description: String, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, @@ -345,11 +387,19 @@ where L::Target: Logger, { use std::time::SystemTime; - let duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + let duration = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) .expect("for the foreseeable future this shouldn't happen"); create_invoice_from_channelmanager_and_duration_since_epoch( - channelmanager, node_signer, logger, network, amt_msat, - description, duration, invoice_expiry_delta_secs, min_final_cltv_expiry_delta, + channelmanager, + node_signer, + logger, + network, + amt_msat, + description, + duration, + invoice_expiry_delta_secs, + min_final_cltv_expiry_delta, ) } @@ -370,7 +420,16 @@ where /// confirmations during routing. /// /// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: lightning::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, + L: Deref, +>( channelmanager: &ChannelManager, node_signer: NS, logger: L, network: Currency, amt_msat: Option, description_hash: Sha256, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, @@ -392,80 +451,132 @@ where .expect("for the foreseeable future this shouldn't happen"); create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch( - channelmanager, node_signer, logger, network, amt_msat, - description_hash, duration, invoice_expiry_delta_secs, min_final_cltv_expiry_delta, + channelmanager, + node_signer, + logger, + network, + amt_msat, + description_hash, + duration, + invoice_expiry_delta_secs, + min_final_cltv_expiry_delta, ) } /// See [`create_invoice_from_channelmanager_with_description_hash`] /// 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_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch( +pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, +>( channelmanager: &ChannelManager, node_signer: NS, logger: L, network: Currency, amt_msat: Option, description_hash: Sha256, - duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, + duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, + min_final_cltv_expiry_delta: Option, ) -> Result> - where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - L::Target: Logger, +where + M::Target: chain::Watch<::EcdsaSigner>, + T::Target: BroadcasterInterface, + ES::Target: EntropySource, + NS::Target: NodeSigner, + SP::Target: SignerProvider, + F::Target: FeeEstimator, + R::Target: Router, + L::Target: Logger, { _create_invoice_from_channelmanager_and_duration_since_epoch( - channelmanager, node_signer, logger, network, amt_msat, + channelmanager, + node_signer, + logger, + network, + amt_msat, Bolt11InvoiceDescription::Hash(&description_hash), - duration_since_epoch, invoice_expiry_delta_secs, min_final_cltv_expiry_delta, + duration_since_epoch, + invoice_expiry_delta_secs, + min_final_cltv_expiry_delta, ) } /// See [`create_invoice_from_channelmanager`] /// 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_invoice_from_channelmanager_and_duration_since_epoch( +pub fn create_invoice_from_channelmanager_and_duration_since_epoch< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, +>( channelmanager: &ChannelManager, node_signer: NS, logger: L, network: Currency, amt_msat: Option, description: String, duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, ) -> Result> - where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - L::Target: Logger, +where + M::Target: chain::Watch<::EcdsaSigner>, + T::Target: BroadcasterInterface, + ES::Target: EntropySource, + NS::Target: NodeSigner, + SP::Target: SignerProvider, + F::Target: FeeEstimator, + R::Target: Router, + L::Target: Logger, { _create_invoice_from_channelmanager_and_duration_since_epoch( - channelmanager, node_signer, logger, network, amt_msat, + channelmanager, + node_signer, + logger, + network, + amt_msat, Bolt11InvoiceDescription::Direct( &Description::new(description).map_err(SignOrCreationError::CreationError)?, ), - duration_since_epoch, invoice_expiry_delta_secs, min_final_cltv_expiry_delta, + duration_since_epoch, + invoice_expiry_delta_secs, + min_final_cltv_expiry_delta, ) } -fn _create_invoice_from_channelmanager_and_duration_since_epoch( +fn _create_invoice_from_channelmanager_and_duration_since_epoch< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, +>( channelmanager: &ChannelManager, node_signer: NS, logger: L, network: Currency, amt_msat: Option, description: Bolt11InvoiceDescription, - duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, + duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, + min_final_cltv_expiry_delta: Option, ) -> Result> - where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - L::Target: Logger, +where + M::Target: chain::Watch<::EcdsaSigner>, + T::Target: BroadcasterInterface, + ES::Target: EntropySource, + NS::Target: NodeSigner, + SP::Target: SignerProvider, + F::Target: FeeEstimator, + R::Target: Router, + L::Target: Logger, { - 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, + )); } // `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin @@ -474,73 +585,119 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch( +pub fn create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, +>( channelmanager: &ChannelManager, node_signer: NS, logger: L, network: Currency, amt_msat: Option, description: String, duration_since_epoch: Duration, - invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, min_final_cltv_expiry_delta: Option, + invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, + min_final_cltv_expiry_delta: Option, ) -> Result> - where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - L::Target: Logger, +where + M::Target: chain::Watch<::EcdsaSigner>, + T::Target: BroadcasterInterface, + ES::Target: EntropySource, + NS::Target: NodeSigner, + SP::Target: SignerProvider, + F::Target: FeeEstimator, + R::Target: Router, + L::Target: Logger, { let payment_secret = channelmanager - .create_inbound_payment_for_hash(payment_hash, amt_msat, invoice_expiry_delta_secs, - min_final_cltv_expiry_delta) + .create_inbound_payment_for_hash( + payment_hash, + amt_msat, + invoice_expiry_delta_secs, + min_final_cltv_expiry_delta, + ) .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?; _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash( - channelmanager, node_signer, logger, network, amt_msat, + channelmanager, + node_signer, + logger, + network, + amt_msat, Bolt11InvoiceDescription::Direct( &Description::new(description).map_err(SignOrCreationError::CreationError)?, ), - duration_since_epoch, invoice_expiry_delta_secs, payment_hash, payment_secret, + duration_since_epoch, + invoice_expiry_delta_secs, + payment_hash, + payment_secret, min_final_cltv_expiry_delta, ) } -fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash( +fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_hash< + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, +>( channelmanager: &ChannelManager, node_signer: NS, logger: L, network: Currency, amt_msat: Option, description: Bolt11InvoiceDescription, duration_since_epoch: Duration, invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, payment_secret: PaymentSecret, min_final_cltv_expiry_delta: Option, ) -> Result> - where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - L::Target: Logger, +where + M::Target: chain::Watch<::EcdsaSigner>, + T::Target: BroadcasterInterface, + ES::Target: EntropySource, + NS::Target: NodeSigner, + SP::Target: SignerProvider, + F::Target: FeeEstimator, + R::Target: Router, + L::Target: Logger, { let our_node_pubkey = channelmanager.get_our_node_id(); let channels = channelmanager.list_channels(); - 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, + )); } log_trace!(logger, "Creating invoice with payment hash {}", &payment_hash); let invoice = match description { Bolt11InvoiceDescription::Direct(description) => { - InvoiceBuilder::new(network).description(description.0.0.clone()) - } - Bolt11InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0), + InvoiceBuilder::new(network).description(description.0 .0.clone()) + }, + Bolt11InvoiceDescription::Hash(hash) => { + InvoiceBuilder::new(network).description_hash(hash.0) + }, }; let mut invoice = invoice @@ -551,7 +708,11 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has .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(), + ) .expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into())); if let Some(amt) = amt_msat { invoice = invoice.amount_milli_satoshis(amt); @@ -564,15 +725,16 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has 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 hrp_str = raw_invoice.hrp.to_string(); let hrp_bytes = hrp_str.as_bytes(); let data_without_signature = raw_invoice.data.to_base32(); - let signed_raw_invoice = raw_invoice.sign(|_| node_signer.sign_invoice(hrp_bytes, &data_without_signature, Recipient::Node)); + let signed_raw_invoice = raw_invoice + .sign(|_| node_signer.sign_invoice(hrp_bytes, &data_without_signature, Recipient::Node)); match signed_raw_invoice { Ok(inv) => Ok(Bolt11Invoice::from_signed(inv).unwrap()), - Err(e) => Err(SignOrCreationError::SignError(e)) + Err(e) => Err(SignOrCreationError::SignError(e)), } } @@ -596,9 +758,7 @@ fn _create_invoice_from_channelmanager_and_duration_since_epoch_with_payment_has /// * 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. 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, @@ -621,13 +781,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; } @@ -641,15 +804,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; } @@ -671,12 +840,16 @@ where let new_now_public = channel.is_public && !entry.get().is_public; // 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_public == entry.get().is_public && !prefer_current; + let new_channel_preferable = + channel.is_public == entry.get().is_public && !prefer_current; if new_now_public || new_channel_preferable { log_trace!(logger, @@ -696,10 +869,10 @@ where &channel.channel_id, channel.short_channel_id, channel.inbound_capacity_msat); } - } + }, hash_map::Entry::Vacant(entry) => { entry.insert(channel); - } + }, } } @@ -729,32 +902,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_public)); - 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 @@ -768,13 +953,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; @@ -782,25 +967,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); @@ -808,7 +999,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 } } @@ -816,24 +1010,30 @@ impl<'a, 'b, L: Deref> WithChannelDetails<'a, 'b, L> where L::Target: Logger { #[cfg(test)] mod test { - use core::time::Duration; - use crate::{Currency, Description, Bolt11InvoiceDescription, SignOrCreationError, CreationError}; - use bitcoin::hashes::{Hash, sha256}; + use crate::utils::{ + create_invoice_from_channelmanager_and_duration_since_epoch, rotate_through_iterators, + }; + use crate::{ + Bolt11InvoiceDescription, CreationError, Currency, Description, SignOrCreationError, + }; use bitcoin::hashes::sha256::Hash as Sha256; - use lightning::sign::PhantomKeysManager; + use bitcoin::hashes::{sha256, Hash}; + use core::time::Duration; use lightning::events::{MessageSendEvent, MessageSendEventsProvider}; + use lightning::ln::channelmanager::{ + PaymentId, PhantomRouteHints, RecipientOnionFields, Retry, MIN_FINAL_CLTV_EXPIRY_DELTA, + }; + use lightning::ln::functional_test_utils::*; + use lightning::ln::msgs::ChannelMessageHandler; use lightning::ln::PaymentHash; #[cfg(feature = "std")] use lightning::ln::PaymentPreimage; - use lightning::ln::channelmanager::{PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields, Retry}; - use lightning::ln::functional_test_utils::*; - use lightning::ln::msgs::ChannelMessageHandler; use lightning::routing::router::{PaymentParameters, RouteParameters}; - use lightning::util::test_utils; + use lightning::sign::PhantomKeysManager; use lightning::util::config::UserConfig; - use crate::utils::{create_invoice_from_channelmanager_and_duration_since_epoch, rotate_through_iterators}; - use std::collections::HashSet; use lightning::util::string::UntrustedString; + use lightning::util::test_utils; + use std::collections::HashSet; #[test] fn test_prefer_current_channel() { @@ -862,7 +1062,6 @@ mod test { assert_eq!(crate::utils::prefer_current_channel(Some(200), 100, 150), false); } - #[test] fn test_from_channelmanager() { let chanmon_cfgs = create_chanmon_cfgs(2); @@ -872,36 +1071,66 @@ mod test { create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); let non_default_invoice_expiry_secs = 4200; let invoice = create_invoice_from_channelmanager_and_duration_since_epoch( - nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet, - Some(10_000), "test".to_string(), Duration::from_secs(1234567), - non_default_invoice_expiry_secs, None).unwrap(); + nodes[1].node, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + Some(10_000), + "test".to_string(), + Duration::from_secs(1234567), + non_default_invoice_expiry_secs, + None, + ) + .unwrap(); assert_eq!(invoice.amount_pico_btc(), Some(100_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(), Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string())))); - assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into())); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string()))) + ); + 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_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 route_params = RouteParameters::from_payment_params_and_value( - payment_params, invoice.amount_milli_satoshis().unwrap()); + payment_params, + invoice.amount_milli_satoshis().unwrap(), + ); let payment_event = { 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), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(*invoice.payment_secret()), + PaymentId(payment_hash.0), + route_params, + Retry::Attempts(0), + ) + .unwrap(); let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); assert_eq!(added_monitors.len(), 1); added_monitors.clear(); @@ -909,10 +1138,14 @@ mod test { 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(&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( + &nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); assert_eq!(added_monitors.len(), 1); added_monitors.clear(); @@ -928,12 +1161,25 @@ mod test { let custom_min_final_cltv_expiry_delta = Some(50); let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch( - nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet, - Some(10_000), "".into(), Duration::from_secs(1234567), 3600, + nodes[1].node, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + Some(10_000), + "".into(), + Duration::from_secs(1234567), + 3600, if with_custom_delta { custom_min_final_cltv_expiry_delta } else { None }, - ).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); + ) + .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 + ); } #[test] @@ -951,10 +1197,17 @@ mod test { let custom_min_final_cltv_expiry_delta = Some(21); let invoice = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch( - nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet, - Some(10_000), "".into(), Duration::from_secs(1234567), 3600, + nodes[1].node, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + Some(10_000), + "".into(), + Duration::from_secs(1234567), + 3600, custom_min_final_cltv_expiry_delta, - ).unwrap(); + ) + .unwrap(); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); } @@ -971,7 +1224,12 @@ mod test { ).unwrap(); assert_eq!(invoice.amount_pico_btc(), Some(100_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.description(), Bolt11InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Testing description_hash".as_bytes())))); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescription::Hash(&crate::Sha256(Sha256::hash( + "Testing description_hash".as_bytes() + ))) + ); } #[test] @@ -988,7 +1246,10 @@ mod test { ).unwrap(); assert_eq!(invoice.amount_pico_btc(), Some(100_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string())))); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string()))) + ); assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&payment_hash.0[..]).unwrap()); } @@ -1003,7 +1264,8 @@ mod test { // 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. @@ -1015,20 +1277,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()); @@ -1045,7 +1324,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()); } @@ -1056,8 +1339,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()); @@ -1073,9 +1358,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()); @@ -1159,31 +1447,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.announced_channel = 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()); @@ -1201,7 +1528,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); @@ -1269,21 +1597,32 @@ 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 invoice = create_invoice_from_channelmanager_and_duration_since_epoch( - invoice_node.node, invoice_node.keys_manager, invoice_node.logger, - Currency::BitcoinTestnet, invoice_amt, "test".to_string(), Duration::from_secs(1234567), - 3600, None).unwrap(); + invoice_node.node, + invoice_node.keys_manager, + invoice_node.logger, + Currency::BitcoinTestnet, + invoice_amt, + "test".to_string(), + Duration::from_secs(1234567), + 3600, + None, + ) + .unwrap(); let hints = invoice.private_routes(); for hint in hints { let hint_short_chan_id = (hint.0).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] @@ -1295,15 +1634,17 @@ mod test { #[cfg(feature = "std")] fn do_test_multi_node_receive(user_generated_pmt_hash: bool) { - use lightning::events::{Event, EventsProvider}; use core::cell::RefCell; + use lightning::events::{Event, EventsProvider}; let mut chanmon_cfgs = create_chanmon_cfgs(3); let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); 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); @@ -1315,10 +1656,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 { @@ -1326,16 +1665,31 @@ mod test { } else { None }; - let genesis_timestamp = bitcoin::blockdata::constants::genesis_block(bitcoin::Network::Testnet).header.time as u64; + let genesis_timestamp = + bitcoin::blockdata::constants::genesis_block(bitcoin::Network::Testnet).header.time + as u64; let non_default_invoice_expiry_secs = 4200; - let invoice = - crate::utils::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 = crate::utils::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 { @@ -1343,22 +1697,41 @@ mod test { }; assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.description(), Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string())))); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescription::Direct(&Description(UntrustedString("test".to_string()))) + ); 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(); let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); assert_eq!(added_monitors.len(), 1); added_monitors.clear(); @@ -1369,14 +1742,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 @@ -1392,10 +1775,23 @@ 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(&nodes[0], &[&vec!(&nodes[fwd_idx])[..]], false, 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( + &nodes[0], + &[&vec![&nodes[fwd_idx]][..]], + false, + payment_preimage, + ); expect_payment_sent(&nodes[0], payment_preimage, None, true, true); } @@ -1406,8 +1802,10 @@ mod test { let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); 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); @@ -1416,24 +1814,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 = crate::utils::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 = crate::utils::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] @@ -1445,25 +1868,42 @@ 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 = crate::Sha256(Hash::hash("Description hash phantom invoice".as_bytes())); + let description_hash = + crate::Sha256(Hash::hash("Description hash phantom invoice".as_bytes())); let non_default_invoice_expiry_secs = 4200; let invoice = crate::utils::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_pico_btc(), Some(200_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(), Bolt11InvoiceDescription::Hash(&crate::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(), + Bolt11InvoiceDescription::Hash(&crate::Sha256(Sha256::hash( + "Description hash phantom invoice".as_bytes() + ))) + ); } #[test] @@ -1475,22 +1915,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 = crate::utils::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 = crate::utils::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_pico_btc(), Some(200_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] @@ -1500,14 +1959,18 @@ mod test { let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); 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_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()); @@ -1516,28 +1979,34 @@ 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] #[cfg(feature = "std")] - 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]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[3].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[3].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); 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()); @@ -1547,9 +2016,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, ); } @@ -1560,38 +2029,80 @@ mod test { let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[3].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[3].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); 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.announced_channel = 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()); @@ -1605,9 +2116,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, ); } @@ -1618,13 +2129,16 @@ mod test { let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); 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_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); @@ -1638,9 +2152,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, ); } @@ -1651,8 +2165,10 @@ mod test { let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); @@ -1660,9 +2176,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. @@ -1672,9 +2190,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, ); } @@ -1685,16 +2203,22 @@ mod test { let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); 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_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()); @@ -1703,9 +2227,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, ); } @@ -1716,8 +2240,10 @@ mod test { let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; let cross_node_seed = [44u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); @@ -1734,9 +2260,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. @@ -1748,9 +2274,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 @@ -1763,9 +2289,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. @@ -1777,9 +2303,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, ); } @@ -1791,12 +2317,17 @@ mod test { let seed_3 = [44 as u8; 32]; let seed_4 = [45 as u8; 32]; let cross_node_seed = [44 as u8; 32]; - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[3].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); - chanmon_cfgs[4].keys_manager.backing = PhantomKeysManager::new(&seed_3, 43, 44, &cross_node_seed); - chanmon_cfgs[5].keys_manager.backing = PhantomKeysManager::new(&seed_4, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[3].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[4].keys_manager.backing = + PhantomKeysManager::new(&seed_3, 43, 44, &cross_node_seed); + chanmon_cfgs[5].keys_manager.backing = + PhantomKeysManager::new(&seed_4, 43, 44, &cross_node_seed); 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. @@ -1848,8 +2379,10 @@ mod test { let seed_1 = [42 as u8; 32]; let seed_2 = [43 as u8; 32]; let cross_node_seed = [44 as u8; 32]; - chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); - chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); + chanmon_cfgs[1].keys_manager.backing = + PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed); + chanmon_cfgs[2].keys_manager.backing = + PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed); let node_cfgs = create_node_cfgs(5, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, None, None, None, None]); let nodes = create_network(5, &node_cfgs, &node_chanmgrs); @@ -1869,30 +2402,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 = crate::utils::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 = crate::utils::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(); @@ -1910,10 +2457,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] @@ -1923,11 +2474,20 @@ mod test { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let result = crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch( - nodes[1].node, nodes[1].keys_manager, nodes[1].logger, Currency::BitcoinTestnet, - Some(10_000), "Some description".into(), Duration::from_secs(1234567), 3600, Some(MIN_FINAL_CLTV_EXPIRY_DELTA - 4), + nodes[1].node, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + Some(10_000), + "Some description".into(), + Duration::from_secs(1234567), + 3600, + Some(MIN_FINAL_CLTV_EXPIRY_DELTA - 4), ); match result { - Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort)) => {}, + Err(SignOrCreationError::CreationError( + CreationError::MinFinalCltvExpiryDeltaTooShort, + )) => {}, _ => panic!(), } } @@ -1956,7 +2516,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"]; @@ -1970,24 +2534,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-invoice/tests/ser_de.rs b/lightning-invoice/tests/ser_de.rs index 92bc87bef63..9283cc3dd83 100644 --- a/lightning-invoice/tests/ser_de.rs +++ b/lightning-invoice/tests/ser_de.rs @@ -1,22 +1,22 @@ extern crate bech32; +extern crate hex; extern crate lightning; extern crate lightning_invoice; extern crate secp256k1; -extern crate hex; use bitcoin::address::WitnessVersion; -use bitcoin::{PubkeyHash, ScriptHash}; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{sha256, Hash}; +use bitcoin::{PubkeyHash, ScriptHash}; use lightning::ln::PaymentSecret; use lightning::routing::gossip::RoutingFees; use lightning::routing::router::{RouteHint, RouteHintHop}; use lightning_invoice::*; -use secp256k1::PublicKey; use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; +use secp256k1::PublicKey; use std::collections::HashSet; -use std::time::Duration; use std::str::FromStr; +use std::time::Duration; fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { vec![ @@ -386,7 +386,8 @@ fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> { #[test] fn invoice_deserialize() { - for (serialized, deserialized, ignore_feature_diff, ignore_unknown_fields) in get_test_tuples() { + for (serialized, deserialized, ignore_feature_diff, ignore_unknown_fields) in get_test_tuples() + { eprintln!("Testing invoice {}...", serialized); let parsed = serialized.parse::().unwrap(); @@ -397,17 +398,33 @@ fn invoice_deserialize() { assert_eq!(deserialized_invoice.hrp, parsed_invoice.hrp); assert_eq!(deserialized_invoice.data.timestamp, parsed_invoice.data.timestamp); - let mut deserialized_hunks: HashSet<_> = deserialized_invoice.data.tagged_fields.iter().collect(); + let mut deserialized_hunks: HashSet<_> = + deserialized_invoice.data.tagged_fields.iter().collect(); let mut parsed_hunks: HashSet<_> = parsed_invoice.data.tagged_fields.iter().collect(); if ignore_feature_diff { - deserialized_hunks.retain(|h| - if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true }); - parsed_hunks.retain(|h| - if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true }); + deserialized_hunks.retain(|h| { + if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { + false + } else { + true + } + }); + parsed_hunks.retain(|h| { + if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { + false + } else { + true + } + }); } if ignore_unknown_fields { - parsed_hunks.retain(|h| - if let RawTaggedField::UnknownSemantics(_) = h { false } else { true }); + parsed_hunks.retain(|h| { + if let RawTaggedField::UnknownSemantics(_) = h { + false + } else { + true + } + }); } assert_eq!(deserialized_hunks, parsed_hunks); diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index be41a240124..6d5e20bf9da 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -24,31 +24,30 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] use bitcoin::secp256k1::PublicKey; use tokio::net::TcpStream; -use tokio::time; use tokio::sync::mpsc; +use tokio::time; +use lightning::ln::msgs::SocketAddress; use lightning::ln::peer_handler; -use lightning::ln::peer_handler::SocketDescriptor as LnSocketTrait; use lightning::ln::peer_handler::APeerManager; -use lightning::ln::msgs::SocketAddress; +use lightning::ln::peer_handler::SocketDescriptor as LnSocketTrait; -use std::ops::Deref; -use std::task::{self, Poll}; use std::future::Future; +use std::hash::Hash; use std::net::SocketAddr; use std::net::TcpStream as StdTcpStream; -use std::sync::{Arc, Mutex}; +use std::ops::Deref; +use std::pin::Pin; use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Arc, Mutex}; +use std::task::{self, Poll}; use std::time::Duration; -use std::pin::Pin; -use std::hash::Hash; static ID_COUNTER: AtomicU64 = AtomicU64::new(0); @@ -57,27 +56,34 @@ static ID_COUNTER: AtomicU64 = AtomicU64::new(0); // define a trivial two- and three- select macro with the specific types we need and just use that. pub(crate) enum SelectorOutput { - A(Option<()>), B(Option<()>), C(tokio::io::Result<()>), + A(Option<()>), + B(Option<()>), + C(tokio::io::Result<()>), } pub(crate) struct TwoSelector< - A: Future> + Unpin, B: Future> + Unpin + A: Future> + Unpin, + B: Future> + Unpin, > { pub a: A, pub b: B, } -impl< - A: Future> + Unpin, B: Future> + Unpin -> Future for TwoSelector { +impl> + Unpin, B: Future> + Unpin> Future + for TwoSelector +{ type Output = SelectorOutput; fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> Poll { match Pin::new(&mut self.a).poll(ctx) { - Poll::Ready(res) => { return Poll::Ready(SelectorOutput::A(res)); }, + Poll::Ready(res) => { + return Poll::Ready(SelectorOutput::A(res)); + }, Poll::Pending => {}, } match Pin::new(&mut self.b).poll(ctx) { - Poll::Ready(res) => { return Poll::Ready(SelectorOutput::B(res)); }, + Poll::Ready(res) => { + return Poll::Ready(SelectorOutput::B(res)); + }, Poll::Pending => {}, } Poll::Pending @@ -85,7 +91,9 @@ impl< } pub(crate) struct ThreeSelector< - A: Future> + Unpin, B: Future> + Unpin, C: Future> + Unpin + A: Future> + Unpin, + B: Future> + Unpin, + C: Future> + Unpin, > { pub a: A, pub b: B, @@ -93,20 +101,29 @@ pub(crate) struct ThreeSelector< } impl< - A: Future> + Unpin, B: Future> + Unpin, C: Future> + Unpin -> Future for ThreeSelector { + A: Future> + Unpin, + B: Future> + Unpin, + C: Future> + Unpin, + > Future for ThreeSelector +{ type Output = SelectorOutput; fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> Poll { match Pin::new(&mut self.a).poll(ctx) { - Poll::Ready(res) => { return Poll::Ready(SelectorOutput::A(res)); }, + Poll::Ready(res) => { + return Poll::Ready(SelectorOutput::A(res)); + }, Poll::Pending => {}, } match Pin::new(&mut self.b).poll(ctx) { - Poll::Ready(res) => { return Poll::Ready(SelectorOutput::B(res)); }, + Poll::Ready(res) => { + return Poll::Ready(SelectorOutput::B(res)); + }, Poll::Pending => {}, } match Pin::new(&mut self.c).poll(ctx) { - Poll::Ready(res) => { return Poll::Ready(SelectorOutput::C(res)); }, + Poll::Ready(res) => { + return Poll::Ready(SelectorOutput::C(res)); + }, Poll::Pending => {}, } Poll::Pending @@ -140,9 +157,10 @@ struct Connection { } impl Connection { async fn poll_event_process( - peer_manager: PM, - mut event_receiver: mpsc::Receiver<()>, - ) where PM::Target: APeerManager { + peer_manager: PM, mut event_receiver: mpsc::Receiver<()>, + ) where + PM::Target: APeerManager, + { loop { if event_receiver.recv().await.is_none() { return; @@ -152,12 +170,11 @@ impl Connection { } async fn schedule_read( - peer_manager: PM, - us: Arc>, - reader: Arc, - mut read_wake_receiver: mpsc::Receiver<()>, - mut write_avail_receiver: mpsc::Receiver<()>, - ) where PM::Target: APeerManager { + peer_manager: PM, us: Arc>, reader: Arc, + mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>, + ) where + PM::Target: APeerManager, + { // Create a waker to wake up poll_event_process, above let (event_waker, event_receiver) = mpsc::channel(1); tokio::spawn(Self::poll_event_process(peer_manager.clone(), event_receiver)); @@ -178,7 +195,7 @@ impl Connection { // closed. // In this case, we do need to call peer_manager.socket_disconnected() to inform // Rust-Lightning that the socket is gone. - PeerDisconnected + PeerDisconnected, } let disconnect_type = loop { let read_paused = { @@ -193,28 +210,34 @@ impl Connection { TwoSelector { a: Box::pin(write_avail_receiver.recv()), b: Box::pin(read_wake_receiver.recv()), - }.await + } + .await } else { ThreeSelector { a: Box::pin(write_avail_receiver.recv()), b: Box::pin(read_wake_receiver.recv()), c: Box::pin(reader.readable()), - }.await + } + .await }; match select_result { SelectorOutput::A(v) => { assert!(v.is_some()); // We can't have dropped the sending end, its in the us Arc! - if peer_manager.as_ref().write_buffer_space_avail(&mut our_descriptor).is_err() { + if peer_manager.as_ref().write_buffer_space_avail(&mut our_descriptor).is_err() + { break Disconnect::CloseConnection; } }, SelectorOutput::B(_) => {}, SelectorOutput::C(res) => { - if res.is_err() { break Disconnect::PeerDisconnected; } + if res.is_err() { + break Disconnect::PeerDisconnected; + } match reader.try_read(&mut buf) { Ok(0) => break Disconnect::PeerDisconnected, Ok(len) => { - let read_res = peer_manager.as_ref().read_event(&mut our_descriptor, &buf[0..len]); + let read_res = + peer_manager.as_ref().read_event(&mut our_descriptor, &buf[0..len]); let mut us_lock = us.lock().unwrap(); match read_res { Ok(pause_read) => { @@ -249,7 +272,9 @@ impl Connection { } } - fn new(stream: StdTcpStream) -> (Arc, mpsc::Receiver<()>, mpsc::Receiver<()>, Arc>) { + fn new( + stream: StdTcpStream, + ) -> (Arc, mpsc::Receiver<()>, mpsc::Receiver<()>, Arc>) { // We only ever need a channel of depth 1 here: if we returned a non-full write to the // PeerManager, we will eventually get notified that there is room in the socket to write // new bytes, which will generate an event. That event will be popped off the queue before @@ -263,25 +288,30 @@ impl Connection { stream.set_nonblocking(true).unwrap(); let tokio_stream = Arc::new(TcpStream::from_std(stream).unwrap()); - (Arc::clone(&tokio_stream), write_receiver, read_receiver, - Arc::new(Mutex::new(Self { - writer: Some(tokio_stream), write_avail, read_waker, read_paused: false, - rl_requested_disconnect: false, - id: ID_COUNTER.fetch_add(1, Ordering::AcqRel) - }))) + ( + Arc::clone(&tokio_stream), + write_receiver, + read_receiver, + Arc::new(Mutex::new(Self { + writer: Some(tokio_stream), + write_avail, + read_waker, + read_paused: false, + rl_requested_disconnect: false, + id: ID_COUNTER.fetch_add(1, Ordering::AcqRel), + })), + ) } } fn get_addr_from_stream(stream: &StdTcpStream) -> Option { match stream.peer_addr() { - Ok(SocketAddr::V4(sockaddr)) => Some(SocketAddress::TcpIpV4 { - addr: sockaddr.ip().octets(), - port: sockaddr.port(), - }), - Ok(SocketAddr::V6(sockaddr)) => Some(SocketAddress::TcpIpV6 { - addr: sockaddr.ip().octets(), - port: sockaddr.port(), - }), + Ok(SocketAddr::V4(sockaddr)) => { + Some(SocketAddress::TcpIpV4 { addr: sockaddr.ip().octets(), port: sockaddr.port() }) + }, + Ok(SocketAddr::V6(sockaddr)) => { + Some(SocketAddress::TcpIpV6 { addr: sockaddr.ip().octets(), port: sockaddr.port() }) + }, Err(_) => None, } } @@ -293,17 +323,28 @@ fn get_addr_from_stream(stream: &StdTcpStream) -> Option { /// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do /// not need to poll the provided future in order to make progress. pub fn setup_inbound( - peer_manager: PM, - stream: StdTcpStream, -) -> impl std::future::Future -where PM::Target: APeerManager { + peer_manager: PM, stream: StdTcpStream, +) -> impl std::future::Future +where + PM::Target: APeerManager, +{ let remote_addr = get_addr_from_stream(&stream); let (reader, write_receiver, read_receiver, us) = Connection::new(stream); #[cfg(test)] let last_us = Arc::clone(&us); - let handle_opt = if peer_manager.as_ref().new_inbound_connection(SocketDescriptor::new(us.clone()), remote_addr).is_ok() { - Some(tokio::spawn(Connection::schedule_read(peer_manager, us, reader, read_receiver, write_receiver))) + let handle_opt = if peer_manager + .as_ref() + .new_inbound_connection(SocketDescriptor::new(us.clone()), remote_addr) + .is_ok() + { + Some(tokio::spawn(Connection::schedule_read( + peer_manager, + us, + reader, + read_receiver, + write_receiver, + ))) } else { // Note that we will skip socket_disconnected here, in accordance with the PeerManager // requirements. @@ -335,16 +376,20 @@ where PM::Target: APeerManager { /// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do /// not need to poll the provided future in order to make progress. pub fn setup_outbound( - peer_manager: PM, - their_node_id: PublicKey, - stream: StdTcpStream, -) -> impl std::future::Future -where PM::Target: APeerManager { + peer_manager: PM, their_node_id: PublicKey, stream: StdTcpStream, +) -> impl std::future::Future +where + PM::Target: APeerManager, +{ let remote_addr = get_addr_from_stream(&stream); let (reader, mut write_receiver, read_receiver, us) = Connection::new(stream); #[cfg(test)] let last_us = Arc::clone(&us); - let handle_opt = if let Ok(initial_send) = peer_manager.as_ref().new_outbound_connection(their_node_id, SocketDescriptor::new(us.clone()), remote_addr) { + let handle_opt = if let Ok(initial_send) = peer_manager.as_ref().new_outbound_connection( + their_node_id, + SocketDescriptor::new(us.clone()), + remote_addr, + ) { Some(tokio::spawn(async move { // We should essentially always have enough room in a TCP socket buffer to send the // initial 10s of bytes. However, tokio running in single-threaded mode will always @@ -363,13 +408,18 @@ where PM::Target: APeerManager { }, _ => { eprintln!("Failed to write first full message to socket!"); - peer_manager.as_ref().socket_disconnected(&SocketDescriptor::new(Arc::clone(&us))); + peer_manager + .as_ref() + .socket_disconnected(&SocketDescriptor::new(Arc::clone(&us))); break Err(()); - } + }, } } - }).await { - Connection::schedule_read(peer_manager, us, reader, read_receiver, write_receiver).await; + }) + .await + { + Connection::schedule_read(peer_manager, us, reader, read_receiver, write_receiver) + .await; } })) } else { @@ -407,18 +457,28 @@ where PM::Target: APeerManager { /// futures are spawned with tokio::spawn, you do not need to poll the second future in order to /// make progress. pub async fn connect_outbound( - peer_manager: PM, - their_node_id: PublicKey, - addr: SocketAddr, -) -> Option> -where PM::Target: APeerManager { - if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(10), async { TcpStream::connect(&addr).await.map(|s| s.into_std().unwrap()) }).await { + peer_manager: PM, their_node_id: PublicKey, addr: SocketAddr, +) -> Option> +where + PM::Target: APeerManager, +{ + if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(10), async { + TcpStream::connect(&addr).await.map(|s| s.into_std().unwrap()) + }) + .await + { Some(setup_outbound(peer_manager, their_node_id, stream)) - } else { None } + } else { + None + } } -const SOCK_WAKER_VTABLE: task::RawWakerVTable = - task::RawWakerVTable::new(clone_socket_waker, wake_socket_waker, wake_socket_waker_by_ref, drop_socket_waker); +const SOCK_WAKER_VTABLE: task::RawWakerVTable = task::RawWakerVTable::new( + clone_socket_waker, + wake_socket_waker, + wake_socket_waker_by_ref, + drop_socket_waker, +); fn clone_socket_waker(orig_ptr: *const ()) -> task::RawWaker { let new_waker = unsafe { Arc::from_raw(orig_ptr as *const mpsc::Sender<()>) }; @@ -489,8 +549,11 @@ impl peer_handler::SocketDescriptor for SocketDescriptor { us.read_paused = false; let _ = us.read_waker.try_send(()); } - if data.is_empty() { return 0; } - let waker = unsafe { task::Waker::from_raw(write_avail_to_waker(&self.write_avail_sender)) }; + if data.is_empty() { + return 0; + } + let waker = + unsafe { task::Waker::from_raw(write_avail_to_waker(&self.write_avail_sender)) }; let mut ctx = task::Context::from_waker(&waker); let mut written_len = 0; loop { @@ -500,11 +563,13 @@ impl peer_handler::SocketDescriptor for SocketDescriptor { Ok(res) => { debug_assert_ne!(res, 0); written_len += res; - if written_len == data.len() { return written_len; } + if written_len == data.len() { + return written_len; + } }, Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { continue; - } + }, Err(_) => return written_len, } }, @@ -553,16 +618,16 @@ impl Hash for SocketDescriptor { #[cfg(test)] mod tests { + use bitcoin::blockdata::constants::ChainHash; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; + use bitcoin::Network; + use lightning::events::*; + use lightning::ln::features::NodeFeatures; use lightning::ln::features::*; use lightning::ln::msgs::*; use lightning::ln::peer_handler::{MessageHandler, PeerManager}; - use lightning::ln::features::NodeFeatures; use lightning::routing::gossip::NodeId; - use lightning::events::*; use lightning::util::test_utils::TestNodeSigner; - use bitcoin::Network; - use bitcoin::blockdata::constants::ChainHash; - use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey}; use tokio::sync::mpsc; @@ -574,11 +639,18 @@ mod tests { pub struct TestLogger(); impl lightning::util::logger::Logger for TestLogger { fn log(&self, record: lightning::util::logger::Record) { - println!("{:<5} [{} : {}, {}] {}", record.level.to_string(), record.module_path, record.file, record.line, record.args); + println!( + "{:<5} [{} : {}, {}] {}", + record.level.to_string(), + record.module_path, + record.file, + record.line, + record.args + ); } } - struct MsgHandler{ + struct MsgHandler { expected_pubkey: PublicKey, pubkey_connected: mpsc::Sender<()>, pubkey_disconnected: mpsc::Sender<()>, @@ -586,19 +658,63 @@ mod tests { msg_events: Mutex>, } impl RoutingMessageHandler for MsgHandler { - fn handle_node_announcement(&self, _msg: &NodeAnnouncement) -> Result { Ok(false) } - fn handle_channel_announcement(&self, _msg: &ChannelAnnouncement) -> Result { Ok(false) } - fn handle_channel_update(&self, _msg: &ChannelUpdate) -> Result { Ok(false) } - fn get_next_channel_announcement(&self, _starting_point: u64) -> Option<(ChannelAnnouncement, Option, Option)> { None } - fn get_next_node_announcement(&self, _starting_point: Option<&NodeId>) -> Option { None } - fn peer_connected(&self, _their_node_id: &PublicKey, _init_msg: &Init, _inbound: bool) -> Result<(), ()> { Ok(()) } - fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: ReplyChannelRange) -> Result<(), LightningError> { Ok(()) } - fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) } - fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: QueryChannelRange) -> Result<(), LightningError> { Ok(()) } - fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: QueryShortChannelIds) -> Result<(), LightningError> { Ok(()) } - fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } - fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::empty() } - fn processing_queue_high(&self) -> bool { false } + fn handle_node_announcement( + &self, _msg: &NodeAnnouncement, + ) -> Result { + Ok(false) + } + fn handle_channel_announcement( + &self, _msg: &ChannelAnnouncement, + ) -> Result { + Ok(false) + } + fn handle_channel_update(&self, _msg: &ChannelUpdate) -> Result { + Ok(false) + } + fn get_next_channel_announcement( + &self, _starting_point: u64, + ) -> Option<(ChannelAnnouncement, Option, Option)> { + None + } + fn get_next_node_announcement( + &self, _starting_point: Option<&NodeId>, + ) -> Option { + None + } + fn peer_connected( + &self, _their_node_id: &PublicKey, _init_msg: &Init, _inbound: bool, + ) -> Result<(), ()> { + Ok(()) + } + fn handle_reply_channel_range( + &self, _their_node_id: &PublicKey, _msg: ReplyChannelRange, + ) -> Result<(), LightningError> { + Ok(()) + } + fn handle_reply_short_channel_ids_end( + &self, _their_node_id: &PublicKey, _msg: ReplyShortChannelIdsEnd, + ) -> Result<(), LightningError> { + Ok(()) + } + fn handle_query_channel_range( + &self, _their_node_id: &PublicKey, _msg: QueryChannelRange, + ) -> Result<(), LightningError> { + Ok(()) + } + fn handle_query_short_channel_ids( + &self, _their_node_id: &PublicKey, _msg: QueryShortChannelIds, + ) -> Result<(), LightningError> { + Ok(()) + } + fn provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } + fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { + InitFeatures::empty() + } + fn processing_queue_high(&self) -> bool { + false + } } impl ChannelMessageHandler for MsgHandler { fn handle_open_channel(&self, _their_node_id: &PublicKey, _msg: &OpenChannel) {} @@ -609,13 +725,20 @@ mod tests { fn handle_shutdown(&self, _their_node_id: &PublicKey, _msg: &Shutdown) {} fn handle_closing_signed(&self, _their_node_id: &PublicKey, _msg: &ClosingSigned) {} fn handle_update_add_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateAddHTLC) {} - fn handle_update_fulfill_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFulfillHTLC) {} + fn handle_update_fulfill_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFulfillHTLC) { + } fn handle_update_fail_htlc(&self, _their_node_id: &PublicKey, _msg: &UpdateFailHTLC) {} - 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, + ) { + } fn handle_commitment_signed(&self, _their_node_id: &PublicKey, _msg: &CommitmentSigned) {} fn handle_revoke_and_ack(&self, _their_node_id: &PublicKey, _msg: &RevokeAndACK) {} fn handle_update_fee(&self, _their_node_id: &PublicKey, _msg: &UpdateFee) {} - fn handle_announcement_signatures(&self, _their_node_id: &PublicKey, _msg: &AnnouncementSignatures) {} + fn handle_announcement_signatures( + &self, _their_node_id: &PublicKey, _msg: &AnnouncementSignatures, + ) { + } fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &ChannelUpdate) {} fn handle_open_channel_v2(&self, _their_node_id: &PublicKey, _msg: &OpenChannelV2) {} fn handle_accept_channel_v2(&self, _their_node_id: &PublicKey, _msg: &AcceptChannelV2) {} @@ -638,16 +761,25 @@ mod tests { self.pubkey_disconnected.clone().try_send(()).unwrap(); } } - fn peer_connected(&self, their_node_id: &PublicKey, _init_msg: &Init, _inbound: bool) -> Result<(), ()> { + fn peer_connected( + &self, their_node_id: &PublicKey, _init_msg: &Init, _inbound: bool, + ) -> Result<(), ()> { if *their_node_id == self.expected_pubkey { self.pubkey_connected.clone().try_send(()).unwrap(); } Ok(()) } - fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, _msg: &ChannelReestablish) {} + fn handle_channel_reestablish( + &self, _their_node_id: &PublicKey, _msg: &ChannelReestablish, + ) { + } fn handle_error(&self, _their_node_id: &PublicKey, _msg: &ErrorMessage) {} - fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } - fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::empty() } + fn provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } + fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { + InitFeatures::empty() + } fn get_chain_hashes(&self) -> Option> { Some(vec![ChainHash::using_genesis_block(Network::Testnet)]) } @@ -673,7 +805,9 @@ mod tests { (std::net::TcpStream::connect("127.0.0.1:9999").unwrap(), listener.accept().unwrap().0) } else if let Ok(listener) = std::net::TcpListener::bind("127.0.0.1:46926") { (std::net::TcpStream::connect("127.0.0.1:46926").unwrap(), listener.accept().unwrap().0) - } else { panic!("Failed to bind to v4 localhost on common ports"); } + } else { + panic!("Failed to bind to v4 localhost on common ports"); + } } async fn do_basic_connection_test() { @@ -692,12 +826,22 @@ mod tests { disconnected_flag: AtomicBool::new(false), msg_events: Mutex::new(Vec::new()), }); - let a_manager = Arc::new(PeerManager::new(MessageHandler { - chan_handler: Arc::clone(&a_handler), - route_handler: Arc::clone(&a_handler), - onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - custom_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - }, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(TestNodeSigner::new(a_key)))); + let a_manager = Arc::new(PeerManager::new( + MessageHandler { + chan_handler: Arc::clone(&a_handler), + route_handler: Arc::clone(&a_handler), + onion_message_handler: Arc::new( + lightning::ln::peer_handler::IgnoringMessageHandler {}, + ), + custom_message_handler: Arc::new( + lightning::ln::peer_handler::IgnoringMessageHandler {}, + ), + }, + 0, + &[1; 32], + Arc::new(TestLogger()), + Arc::new(TestNodeSigner::new(a_key)), + )); let (b_connected_sender, mut b_connected) = mpsc::channel(1); let (b_disconnected_sender, mut b_disconnected) = mpsc::channel(1); @@ -708,12 +852,22 @@ mod tests { disconnected_flag: AtomicBool::new(false), msg_events: Mutex::new(Vec::new()), }); - let b_manager = Arc::new(PeerManager::new(MessageHandler { - chan_handler: Arc::clone(&b_handler), - route_handler: Arc::clone(&b_handler), - onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - custom_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - }, 0, &[2; 32], Arc::new(TestLogger()), Arc::new(TestNodeSigner::new(b_key)))); + let b_manager = Arc::new(PeerManager::new( + MessageHandler { + chan_handler: Arc::clone(&b_handler), + route_handler: Arc::clone(&b_handler), + onion_message_handler: Arc::new( + lightning::ln::peer_handler::IgnoringMessageHandler {}, + ), + custom_message_handler: Arc::new( + lightning::ln::peer_handler::IgnoringMessageHandler {}, + ), + }, + 0, + &[2; 32], + Arc::new(TestLogger()), + Arc::new(TestNodeSigner::new(b_key)), + )); // We bind on localhost, hoping the environment is properly configured with a local // address. This may not always be the case in containers and the like, so if this test is @@ -728,7 +882,8 @@ mod tests { tokio::time::timeout(Duration::from_secs(1), b_connected.recv()).await.unwrap(); a_handler.msg_events.lock().unwrap().push(MessageSendEvent::HandleError { - node_id: b_pub, action: ErrorAction::DisconnectPeer { msg: None } + node_id: b_pub, + action: ErrorAction::DisconnectPeer { msg: None }, }); assert!(!a_handler.disconnected_flag.load(Ordering::SeqCst)); assert!(!b_handler.disconnected_flag.load(Ordering::SeqCst)); @@ -762,12 +917,22 @@ mod tests { let b_key = SecretKey::from_slice(&[2; 32]).unwrap(); let b_pub = PublicKey::from_secret_key(&secp_ctx, &b_key); - let a_manager = Arc::new(PeerManager::new(MessageHandler { - chan_handler: Arc::new(lightning::ln::peer_handler::ErroringMessageHandler::new()), - onion_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - route_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - custom_message_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}), - }, 0, &[1; 32], Arc::new(TestLogger()), Arc::new(TestNodeSigner::new(a_key)))); + let a_manager = Arc::new(PeerManager::new( + MessageHandler { + chan_handler: Arc::new(lightning::ln::peer_handler::ErroringMessageHandler::new()), + onion_message_handler: Arc::new( + lightning::ln::peer_handler::IgnoringMessageHandler {}, + ), + route_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler {}), + custom_message_handler: Arc::new( + lightning::ln::peer_handler::IgnoringMessageHandler {}, + ), + }, + 0, + &[1; 32], + Arc::new(TestLogger()), + Arc::new(TestNodeSigner::new(a_key)), + )); // Make two connections, one for an inbound and one for an outbound connection let conn_a = { @@ -781,12 +946,8 @@ mod tests { // Call connection setup inside new tokio tasks. let manager_reference = Arc::clone(&a_manager); - tokio::spawn(async move { - super::setup_inbound(manager_reference, conn_a).await - }); - tokio::spawn(async move { - super::setup_outbound(a_manager, b_pub, conn_b).await - }); + tokio::spawn(async move { super::setup_inbound(manager_reference, conn_a).await }); + tokio::spawn(async move { super::setup_outbound(a_manager, b_pub, conn_b).await }); } #[tokio::test(flavor = "multi_thread")] diff --git a/lightning-persister/src/fs_store.rs b/lightning-persister/src/fs_store.rs index 350b1cdd195..1be84570fe4 100644 --- a/lightning-persister/src/fs_store.rs +++ b/lightning-persister/src/fs_store.rs @@ -67,7 +67,9 @@ impl FilesystemStore { } } - fn get_dest_dir_path(&self, primary_namespace: &str, secondary_namespace: &str) -> std::io::Result { + fn get_dest_dir_path( + &self, primary_namespace: &str, secondary_namespace: &str, + ) -> std::io::Result { let mut dest_dir_path = { #[cfg(target_os = "windows")] { @@ -91,7 +93,9 @@ impl FilesystemStore { } impl KVStore for FilesystemStore { - fn read(&self, primary_namespace: &str, secondary_namespace: &str, key: &str) -> std::io::Result> { + fn read( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, + ) -> std::io::Result> { check_namespace_key_validity(primary_namespace, secondary_namespace, Some(key), "read")?; let mut dest_file_path = self.get_dest_dir_path(primary_namespace, secondary_namespace)?; @@ -114,19 +118,19 @@ impl KVStore for FilesystemStore { Ok(buf) } - fn write(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8]) -> std::io::Result<()> { + fn write( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8], + ) -> std::io::Result<()> { check_namespace_key_validity(primary_namespace, secondary_namespace, Some(key), "write")?; let mut dest_file_path = self.get_dest_dir_path(primary_namespace, secondary_namespace)?; dest_file_path.push(key); - let parent_directory = dest_file_path - .parent() - .ok_or_else(|| { - let msg = - format!("Could not retrieve parent directory of {}.", dest_file_path.display()); - std::io::Error::new(std::io::ErrorKind::InvalidInput, msg) - })?; + let parent_directory = dest_file_path.parent().ok_or_else(|| { + let msg = + format!("Could not retrieve parent directory of {}.", dest_file_path.display()); + std::io::Error::new(std::io::ErrorKind::InvalidInput, msg) + })?; fs::create_dir_all(&parent_directory)?; // Do a crazy dance with lots of fsync()s to be overly cautious here... @@ -186,11 +190,11 @@ impl KVStore for FilesystemStore { match res { Ok(()) => { // We fsync the dest file in hopes this will also flush the metadata to disk. - let dest_file = fs::OpenOptions::new().read(true).write(true) - .open(&dest_file_path)?; + let dest_file = + fs::OpenOptions::new().read(true).write(true).open(&dest_file_path)?; dest_file.sync_all()?; Ok(()) - } + }, Err(e) => Err(e), } } @@ -201,7 +205,9 @@ impl KVStore for FilesystemStore { res } - fn remove(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool) -> std::io::Result<()> { + fn remove( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool, + ) -> std::io::Result<()> { check_namespace_key_validity(primary_namespace, secondary_namespace, Some(key), "remove")?; let mut dest_file_path = self.get_dest_dir_path(primary_namespace, secondary_namespace)?; @@ -229,8 +235,10 @@ impl KVStore for FilesystemStore { fs::remove_file(&dest_file_path)?; let parent_directory = dest_file_path.parent().ok_or_else(|| { - let msg = - format!("Could not retrieve parent directory of {}.", dest_file_path.display()); + let msg = format!( + "Could not retrieve parent directory of {}.", + dest_file_path.display() + ); std::io::Error::new(std::io::ErrorKind::InvalidInput, msg) })?; let dir_file = fs::OpenOptions::new().read(true).open(parent_directory)?; @@ -257,8 +265,8 @@ impl KVStore for FilesystemStore { // However, all this is partially based on assumptions and local experiments, as // Windows API is horribly underdocumented. let mut trash_file_path = dest_file_path.clone(); - let trash_file_ext = format!("{}.trash", - self.tmp_file_counter.fetch_add(1, Ordering::AcqRel)); + let trash_file_ext = + format!("{}.trash", self.tmp_file_counter.fetch_add(1, Ordering::AcqRel)); trash_file_path.set_extension(trash_file_ext); call!(unsafe { @@ -273,7 +281,9 @@ impl KVStore for FilesystemStore { { // We fsync the trash file in hopes this will also flush the original's file // metadata to disk. - let trash_file = fs::OpenOptions::new().read(true).write(true) + let trash_file = fs::OpenOptions::new() + .read(true) + .write(true) .open(&trash_file_path.clone())?; trash_file.sync_all()?; } @@ -290,7 +300,9 @@ impl KVStore for FilesystemStore { Ok(()) } - fn list(&self, primary_namespace: &str, secondary_namespace: &str) -> std::io::Result> { + fn list( + &self, primary_namespace: &str, secondary_namespace: &str, + ) -> std::io::Result> { check_namespace_key_validity(primary_namespace, secondary_namespace, None, "list")?; let prefixed_dest = self.get_dest_dir_path(primary_namespace, secondary_namespace)?; @@ -327,10 +339,17 @@ impl KVStore for FilesystemStore { // If we otherwise don't find a file at the given path something went wrong. if !metadata.is_file() { - debug_assert!(false, "Failed to list keys of {}/{}: file couldn't be accessed.", - PrintableString(primary_namespace), PrintableString(secondary_namespace)); - let msg = format!("Failed to list keys of {}/{}: file couldn't be accessed.", - PrintableString(primary_namespace), PrintableString(secondary_namespace)); + debug_assert!( + false, + "Failed to list keys of {}/{}: file couldn't be accessed.", + PrintableString(primary_namespace), + PrintableString(secondary_namespace) + ); + let msg = format!( + "Failed to list keys of {}/{}: file couldn't be accessed.", + PrintableString(primary_namespace), + PrintableString(secondary_namespace) + ); return Err(std::io::Error::new(std::io::ErrorKind::Other, msg)); } @@ -341,20 +360,36 @@ impl KVStore for FilesystemStore { keys.push(relative_path.to_string()) } } else { - debug_assert!(false, "Failed to list keys of {}/{}: file path is not valid UTF-8", - PrintableString(primary_namespace), PrintableString(secondary_namespace)); - let msg = format!("Failed to list keys of {}/{}: file path is not valid UTF-8", - PrintableString(primary_namespace), PrintableString(secondary_namespace)); + debug_assert!( + false, + "Failed to list keys of {}/{}: file path is not valid UTF-8", + PrintableString(primary_namespace), + PrintableString(secondary_namespace) + ); + let msg = format!( + "Failed to list keys of {}/{}: file path is not valid UTF-8", + PrintableString(primary_namespace), + PrintableString(secondary_namespace) + ); return Err(std::io::Error::new(std::io::ErrorKind::Other, msg)); } - } + }, Err(e) => { - debug_assert!(false, "Failed to list keys of {}/{}: {}", - PrintableString(primary_namespace), PrintableString(secondary_namespace), e); - let msg = format!("Failed to list keys of {}/{}: {}", - PrintableString(primary_namespace), PrintableString(secondary_namespace), e); + debug_assert!( + false, + "Failed to list keys of {}/{}: {}", + PrintableString(primary_namespace), + PrintableString(secondary_namespace), + e + ); + let msg = format!( + "Failed to list keys of {}/{}: {}", + PrintableString(primary_namespace), + PrintableString(secondary_namespace), + e + ); return Err(std::io::Error::new(std::io::ErrorKind::Other, msg)); - } + }, } } @@ -371,14 +406,14 @@ mod tests { use bitcoin::Txid; - use lightning::chain::ChannelMonitorUpdateStatus; use lightning::chain::chainmonitor::Persist; use lightning::chain::transaction::OutPoint; + use lightning::chain::ChannelMonitorUpdateStatus; use lightning::check_closed_event; use lightning::events::{ClosureReason, MessageSendEventsProvider}; use lightning::ln::functional_test_utils::*; - use lightning::util::test_utils; use lightning::util::persist::read_channel_monitors; + use lightning::util::test_utils; use std::fs; use std::str::FromStr; @@ -388,7 +423,7 @@ mod tests { // fails. match fs::remove_dir_all(&self.data_dir) { Err(e) => println!("Failed to remove test persister directory: {}", e), - _ => {} + _ => {}, } } } @@ -412,14 +447,23 @@ mod tests { let chanmon_cfgs = create_chanmon_cfgs(1); let mut node_cfgs = create_node_cfgs(1, &chanmon_cfgs); - let chain_mon_0 = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, &store, node_cfgs[0].keys_manager); + let chain_mon_0 = test_utils::TestChainMonitor::new( + Some(&chanmon_cfgs[0].chain_source), + &chanmon_cfgs[0].tx_broadcaster, + &chanmon_cfgs[0].logger, + &chanmon_cfgs[0].fee_estimator, + &store, + node_cfgs[0].keys_manager, + ); node_cfgs[0].chain_monitor = chain_mon_0; let node_chanmgrs = create_node_chanmgrs(1, &node_cfgs, &[None]); let nodes = create_network(1, &node_cfgs, &node_chanmgrs); // Check that read_channel_monitors() returns error if monitors/ is not a // directory. - assert!(read_channel_monitors(&store, nodes[0].keys_manager, nodes[0].keys_manager).is_err()); + assert!( + read_channel_monitors(&store, nodes[0].keys_manager, nodes[0].keys_manager).is_err() + ); } #[test] @@ -446,8 +490,17 @@ mod tests { 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); - nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap(); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()) + .unwrap(); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap(); let update_id = update_map.get(&added_monitors[0].1.channel_id()).unwrap(); @@ -461,12 +514,15 @@ mod tests { fs::set_permissions(path, perms).unwrap(); let test_txo = OutPoint { - txid: Txid::from_str("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), - index: 0 + txid: Txid::from_str( + "8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be", + ) + .unwrap(), + index: 0, }; match store.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) { ChannelMonitorUpdateStatus::UnrecoverableError => {}, - _ => panic!("unexpected result from persisting new channel") + _ => panic!("unexpected result from persisting new channel"), } nodes[1].node.get_and_clear_pending_msg_events(); @@ -485,8 +541,17 @@ mod tests { 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); - nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap(); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()) + .unwrap(); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [nodes[0].node.get_our_node_id()], + 100000 + ); let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap(); let update_id = update_map.get(&added_monitors[0].1.channel_id()).unwrap(); @@ -498,12 +563,15 @@ mod tests { let store = FilesystemStore::new(":<>/".into()); let test_txo = OutPoint { - txid: Txid::from_str("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), - index: 0 + txid: Txid::from_str( + "8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be", + ) + .unwrap(), + index: 0, }; match store.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) { ChannelMonitorUpdateStatus::UnrecoverableError => {}, - _ => panic!("unexpected result from persisting new channel") + _ => panic!("unexpected result from persisting new channel"), } nodes[1].node.get_and_clear_pending_msg_events(); @@ -521,6 +589,10 @@ pub mod bench { let store_a = super::FilesystemStore::new("bench_filesystem_store_a".into()); let store_b = super::FilesystemStore::new("bench_filesystem_store_b".into()); lightning::ln::channelmanager::bench::bench_two_sends( - bench, "bench_filesystem_persisted_sends", store_a, store_b); + bench, + "bench_filesystem_persisted_sends", + store_a, + store_b, + ); } } diff --git a/lightning-persister/src/lib.rs b/lightning-persister/src/lib.rs index 8e7d9055a6a..9d4df264d24 100644 --- a/lightning-persister/src/lib.rs +++ b/lightning-persister/src/lib.rs @@ -2,12 +2,11 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] - #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#[cfg(ldk_bench)] extern crate criterion; +#[cfg(ldk_bench)] +extern crate criterion; pub mod fs_store; diff --git a/lightning-persister/src/test_utils.rs b/lightning-persister/src/test_utils.rs index 360fa3492bf..c45159a89fa 100644 --- a/lightning-persister/src/test_utils.rs +++ b/lightning-persister/src/test_utils.rs @@ -1,11 +1,12 @@ -use lightning::util::persist::{KVStore, KVSTORE_NAMESPACE_KEY_MAX_LEN, read_channel_monitors}; -use lightning::ln::functional_test_utils::{connect_block, create_announced_chan_between_nodes, - create_chanmon_cfgs, create_dummy_block, create_network, create_node_cfgs, create_node_chanmgrs, - send_payment}; use lightning::chain::channelmonitor::CLOSED_CHANNEL_UPDATE_ID; -use lightning::util::test_utils; -use lightning::{check_closed_broadcast, check_closed_event, check_added_monitors}; use lightning::events::ClosureReason; +use lightning::ln::functional_test_utils::{ + connect_block, create_announced_chan_between_nodes, create_chanmon_cfgs, create_dummy_block, + create_network, create_node_cfgs, create_node_chanmgrs, send_payment, +}; +use lightning::util::persist::{read_channel_monitors, KVStore, KVSTORE_NAMESPACE_KEY_MAX_LEN}; +use lightning::util::test_utils; +use lightning::{check_added_monitors, check_closed_broadcast, check_closed_event}; use std::panic::RefUnwindSafe; @@ -24,7 +25,9 @@ pub(crate) fn do_read_write_remove_list_persist(kv_s kv_store.write("", "", key, &data).unwrap(); let res = std::panic::catch_unwind(|| kv_store.write("", secondary_namespace, key, &data)); assert!(res.is_err()); - let res = std::panic::catch_unwind(|| kv_store.write(primary_namespace, secondary_namespace, "", &data)); + let res = std::panic::catch_unwind(|| { + kv_store.write(primary_namespace, secondary_namespace, "", &data) + }); assert!(res.is_err()); let listed_keys = kv_store.list(primary_namespace, secondary_namespace).unwrap(); @@ -62,8 +65,22 @@ pub(crate) fn do_read_write_remove_list_persist(kv_s pub(crate) fn do_test_store(store_0: &K, store_1: &K) { let chanmon_cfgs = create_chanmon_cfgs(2); let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let chain_mon_0 = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, store_0, node_cfgs[0].keys_manager); - let chain_mon_1 = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[1].chain_source), &chanmon_cfgs[1].tx_broadcaster, &chanmon_cfgs[1].logger, &chanmon_cfgs[1].fee_estimator, store_1, node_cfgs[1].keys_manager); + let chain_mon_0 = test_utils::TestChainMonitor::new( + Some(&chanmon_cfgs[0].chain_source), + &chanmon_cfgs[0].tx_broadcaster, + &chanmon_cfgs[0].logger, + &chanmon_cfgs[0].fee_estimator, + store_0, + node_cfgs[0].keys_manager, + ); + let chain_mon_1 = test_utils::TestChainMonitor::new( + Some(&chanmon_cfgs[1].chain_source), + &chanmon_cfgs[1].tx_broadcaster, + &chanmon_cfgs[1].logger, + &chanmon_cfgs[1].fee_estimator, + store_1, + node_cfgs[1].keys_manager, + ); node_cfgs[0].chain_monitor = chain_mon_0; node_cfgs[1].chain_monitor = chain_mon_1; let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); @@ -71,25 +88,31 @@ pub(crate) fn do_test_store(store_0: &K, store_1: &K) { // Check that the persisted channel data is empty before any channels are // open. - let mut persisted_chan_data_0 = read_channel_monitors(store_0, nodes[0].keys_manager, nodes[0].keys_manager).unwrap(); + let mut persisted_chan_data_0 = + read_channel_monitors(store_0, nodes[0].keys_manager, nodes[0].keys_manager).unwrap(); assert_eq!(persisted_chan_data_0.len(), 0); - let mut persisted_chan_data_1 = read_channel_monitors(store_1, nodes[1].keys_manager, nodes[1].keys_manager).unwrap(); + let mut persisted_chan_data_1 = + read_channel_monitors(store_1, nodes[1].keys_manager, nodes[1].keys_manager).unwrap(); assert_eq!(persisted_chan_data_1.len(), 0); // Helper to make sure the channel is on the expected update ID. macro_rules! check_persisted_data { ($expected_update_id: expr) => { - persisted_chan_data_0 = read_channel_monitors(store_0, nodes[0].keys_manager, nodes[0].keys_manager).unwrap(); + persisted_chan_data_0 = + read_channel_monitors(store_0, nodes[0].keys_manager, nodes[0].keys_manager) + .unwrap(); assert_eq!(persisted_chan_data_0.len(), 1); for (_, mon) in persisted_chan_data_0.iter() { assert_eq!(mon.get_latest_update_id(), $expected_update_id); } - persisted_chan_data_1 = read_channel_monitors(store_1, nodes[1].keys_manager, nodes[1].keys_manager).unwrap(); + persisted_chan_data_1 = + read_channel_monitors(store_1, nodes[1].keys_manager, nodes[1].keys_manager) + .unwrap(); assert_eq!(persisted_chan_data_1.len(), 1); for (_, mon) in persisted_chan_data_1.iter() { assert_eq!(mon.get_latest_update_id(), $expected_update_id); } - } + }; } // Create some initial channel and check that a channel was persisted. @@ -97,24 +120,49 @@ pub(crate) fn do_test_store(store_0: &K, store_1: &K) { check_persisted_data!(0); // Send a few payments and make sure the monitors are updated to the latest. - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); + send_payment(&nodes[0], &vec![&nodes[1]][..], 8000000); check_persisted_data!(5); - send_payment(&nodes[1], &vec!(&nodes[0])[..], 4000000); + send_payment(&nodes[1], &vec![&nodes[0]][..], 4000000); check_persisted_data!(10); // Force close because cooperative close doesn't result in any persisted // updates. - nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap(); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 1); - connect_block(&nodes[1], &create_dummy_block(nodes[0].best_block_hash(), 42, vec![node_txn[0].clone(), node_txn[0].clone()])); + connect_block( + &nodes[1], + &create_dummy_block( + nodes[0].best_block_hash(), + 42, + vec![node_txn[0].clone(), node_txn[0].clone()], + ), + ); check_closed_broadcast!(nodes[1], true); - 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 + ); check_added_monitors!(nodes[1], 1); // Make sure everything is persisted as expected after close. diff --git a/lightning-persister/src/utils.rs b/lightning-persister/src/utils.rs index 59a615937c9..6a7900856cc 100644 --- a/lightning-persister/src/utils.rs +++ b/lightning-persister/src/utils.rs @@ -1,20 +1,31 @@ use lightning::util::persist::{KVSTORE_NAMESPACE_KEY_ALPHABET, KVSTORE_NAMESPACE_KEY_MAX_LEN}; use lightning::util::string::PrintableString; - pub(crate) fn is_valid_kvstore_str(key: &str) -> bool { - key.len() <= KVSTORE_NAMESPACE_KEY_MAX_LEN && key.chars().all(|c| KVSTORE_NAMESPACE_KEY_ALPHABET.contains(c)) + key.len() <= KVSTORE_NAMESPACE_KEY_MAX_LEN + && key.chars().all(|c| KVSTORE_NAMESPACE_KEY_ALPHABET.contains(c)) } pub(crate) fn check_namespace_key_validity( - primary_namespace: &str, secondary_namespace: &str, key: Option<&str>, operation: &str) --> Result<(), std::io::Error> { + primary_namespace: &str, secondary_namespace: &str, key: Option<&str>, operation: &str, +) -> Result<(), std::io::Error> { if let Some(key) = key { if key.is_empty() { - debug_assert!(false, "Failed to {} {}/{}/{}: key may not be empty.", operation, - PrintableString(primary_namespace), PrintableString(secondary_namespace), PrintableString(key)); - let msg = format!("Failed to {} {}/{}/{}: key may not be empty.", operation, - PrintableString(primary_namespace), PrintableString(secondary_namespace), PrintableString(key)); + debug_assert!( + false, + "Failed to {} {}/{}/{}: key may not be empty.", + operation, + PrintableString(primary_namespace), + PrintableString(secondary_namespace), + PrintableString(key) + ); + let msg = format!( + "Failed to {} {}/{}/{}: key may not be empty.", + operation, + PrintableString(primary_namespace), + PrintableString(secondary_namespace), + PrintableString(key) + ); return Err(std::io::Error::new(std::io::ErrorKind::Other, msg)); } @@ -29,7 +40,10 @@ pub(crate) fn check_namespace_key_validity( return Err(std::io::Error::new(std::io::ErrorKind::Other, msg)); } - if !is_valid_kvstore_str(primary_namespace) || !is_valid_kvstore_str(secondary_namespace) || !is_valid_kvstore_str(key) { + if !is_valid_kvstore_str(primary_namespace) + || !is_valid_kvstore_str(secondary_namespace) + || !is_valid_kvstore_str(key) + { debug_assert!(false, "Failed to {} {}/{}/{}: primary namespace, secondary namespace, and key must be valid.", operation, PrintableString(primary_namespace), PrintableString(secondary_namespace), PrintableString(key)); @@ -49,10 +63,19 @@ pub(crate) fn check_namespace_key_validity( return Err(std::io::Error::new(std::io::ErrorKind::Other, msg)); } if !is_valid_kvstore_str(primary_namespace) || !is_valid_kvstore_str(secondary_namespace) { - debug_assert!(false, "Failed to {} {}/{}: primary namespace and secondary namespace must be valid.", - operation, PrintableString(primary_namespace), PrintableString(secondary_namespace)); - let msg = format!("Failed to {} {}/{}: primary namespace and secondary namespace must be valid.", - operation, PrintableString(primary_namespace), PrintableString(secondary_namespace)); + debug_assert!( + false, + "Failed to {} {}/{}: primary namespace and secondary namespace must be valid.", + operation, + PrintableString(primary_namespace), + PrintableString(secondary_namespace) + ); + let msg = format!( + "Failed to {} {}/{}: primary namespace and secondary namespace must be valid.", + operation, + PrintableString(primary_namespace), + PrintableString(secondary_namespace) + ); return Err(std::io::Error::new(std::io::ErrorKind::Other, msg)); } } diff --git a/lightning-rapid-gossip-sync/src/error.rs b/lightning-rapid-gossip-sync/src/error.rs index ffd6760f8a9..e80ec83253e 100644 --- a/lightning-rapid-gossip-sync/src/error.rs +++ b/lightning-rapid-gossip-sync/src/error.rs @@ -34,7 +34,9 @@ impl Debug for GraphSyncError { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { GraphSyncError::DecodeError(e) => f.write_fmt(format_args!("DecodeError: {:?}", e)), - GraphSyncError::LightningError(e) => f.write_fmt(format_args!("LightningError: {:?}", e)) + GraphSyncError::LightningError(e) => { + f.write_fmt(format_args!("LightningError: {:?}", e)) + }, } } } diff --git a/lightning-rapid-gossip-sync/src/lib.rs b/lightning-rapid-gossip-sync/src/lib.rs index 0561975f821..61fac347f29 100644 --- a/lightning-rapid-gossip-sync/src/lib.rs +++ b/lightning-rapid-gossip-sync/src/lib.rs @@ -1,6 +1,5 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] #![deny(unsafe_code)] #![deny(non_upper_case_globals)] @@ -63,15 +62,16 @@ #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] -#[cfg(ldk_bench)] extern crate criterion; +#[cfg(ldk_bench)] +extern crate criterion; #[cfg(not(feature = "std"))] extern crate alloc; -#[cfg(feature = "std")] -use std::fs::File; use core::ops::Deref; use core::sync::atomic::{AtomicBool, Ordering}; +#[cfg(feature = "std")] +use std::fs::File; use lightning::io; use lightning::routing::gossip::NetworkGraph; @@ -90,21 +90,22 @@ mod processing; /// See [crate-level documentation] for usage. /// /// [crate-level documentation]: crate -pub struct RapidGossipSync>, L: Deref> -where L::Target: Logger { +pub struct RapidGossipSync>, L: Deref> +where + L::Target: Logger, +{ network_graph: NG, logger: L, - is_initial_sync_complete: AtomicBool + is_initial_sync_complete: AtomicBool, } -impl>, L: Deref> RapidGossipSync where L::Target: Logger { +impl>, L: Deref> RapidGossipSync +where + L::Target: Logger, +{ /// Instantiate a new [`RapidGossipSync`] instance. pub fn new(network_graph: NG, logger: L) -> Self { - Self { - network_graph, - logger, - is_initial_sync_complete: AtomicBool::new(false) - } + Self { network_graph, logger, is_initial_sync_complete: AtomicBool::new(false) } } /// Sync gossip data from a file. @@ -116,8 +117,7 @@ impl>, L: Deref> RapidGossipSync where L /// #[cfg(feature = "std")] pub fn sync_network_graph_with_file_path( - &self, - sync_path: &str, + &self, sync_path: &str, ) -> Result { let mut file = File::open(sync_path)?; self.update_network_graph_from_byte_stream(&mut file) @@ -138,7 +138,9 @@ impl>, L: Deref> RapidGossipSync where L /// /// `update_data`: `&[u8]` binary stream that comprises the update data /// `current_time_unix`: `Option` optional current timestamp to verify data age - pub fn update_network_graph_no_std(&self, update_data: &[u8], current_time_unix: Option) -> Result { + pub fn update_network_graph_no_std( + &self, update_data: &[u8], current_time_unix: Option, + ) -> Result { let mut read_cursor = io::Cursor::new(update_data); self.update_network_graph_from_byte_stream_no_std(&mut read_cursor, current_time_unix) } @@ -164,10 +166,10 @@ mod tests { use bitcoin::Network; + use crate::RapidGossipSync; use lightning::ln::msgs::DecodeError; use lightning::routing::gossip::NetworkGraph; use lightning::util::test_utils::TestLogger; - use crate::RapidGossipSync; #[test] fn test_sync_from_file() { @@ -263,9 +265,10 @@ mod tests { let rapid_sync = RapidGossipSync::new(&network_graph, &logger); let start = std::time::Instant::now(); - let sync_result = rapid_sync - .sync_network_graph_with_file_path("./res/full_graph.lngossip"); - if let Err(crate::error::GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result { + let sync_result = rapid_sync.sync_network_graph_with_file_path("./res/full_graph.lngossip"); + if let Err(crate::error::GraphSyncError::DecodeError(DecodeError::Io(io_error))) = + &sync_result + { let error_string = format!("Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-285cb27df79-2022-07-21.bin\n\n{:?}", io_error); #[cfg(not(require_route_graph_test))] { diff --git a/lightning-rapid-gossip-sync/src/processing.rs b/lightning-rapid-gossip-sync/src/processing.rs index d54f1329798..3b521843e4f 100644 --- a/lightning-rapid-gossip-sync/src/processing.rs +++ b/lightning-rapid-gossip-sync/src/processing.rs @@ -5,14 +5,12 @@ use core::sync::atomic::Ordering; use bitcoin::blockdata::constants::ChainHash; use bitcoin::secp256k1::PublicKey; -use lightning::ln::msgs::{ - DecodeError, ErrorAction, LightningError, UnsignedChannelUpdate, -}; +use lightning::io; +use lightning::ln::msgs::{DecodeError, ErrorAction, LightningError, UnsignedChannelUpdate}; use lightning::routing::gossip::NetworkGraph; use lightning::util::logger::Logger; -use lightning::{log_debug, log_warn, log_trace, log_given_level, log_gossip}; use lightning::util::ser::{BigSize, Readable}; -use lightning::io; +use lightning::{log_debug, log_given_level, log_gossip, log_trace, log_warn}; use crate::error::GraphSyncError; use crate::RapidGossipSync; @@ -21,7 +19,7 @@ use crate::RapidGossipSync; use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(not(feature = "std"))] -use alloc::{vec::Vec, borrow::ToOwned}; +use alloc::{borrow::ToOwned, vec::Vec}; /// The purpose of this prefix is to identify the serialization format, should other rapid gossip /// sync formats arise in the future. @@ -37,11 +35,13 @@ const MAX_INITIAL_NODE_ID_VECTOR_CAPACITY: u32 = 50_000; /// suggestion. const STALE_RGS_UPDATE_AGE_LIMIT_SECS: u64 = 60 * 60 * 24 * 14; -impl>, L: Deref> RapidGossipSync where L::Target: Logger { +impl>, L: Deref> RapidGossipSync +where + L::Target: Logger, +{ #[cfg(feature = "std")] pub(crate) fn update_network_graph_from_byte_stream( - &self, - read_cursor: &mut R, + &self, read_cursor: &mut R, ) -> Result { #[allow(unused_mut, unused_assignments)] let mut current_time_unix = None; @@ -49,15 +49,18 @@ impl>, L: Deref> RapidGossipSync where L { // Note that many tests rely on being able to set arbitrarily old timestamps, thus we // disable this check during tests! - current_time_unix = Some(SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs()); + current_time_unix = Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(), + ); } self.update_network_graph_from_byte_stream_no_std(read_cursor, current_time_unix) } pub(crate) fn update_network_graph_from_byte_stream_no_std( - &self, - mut read_cursor: &mut R, - current_time_unix: Option + &self, mut read_cursor: &mut R, current_time_unix: Option, ) -> Result { log_trace!(self.logger, "Processing RGS data..."); let mut prefix = [0u8; 4]; @@ -70,19 +73,24 @@ impl>, L: Deref> RapidGossipSync where L let chain_hash: ChainHash = Readable::read(read_cursor)?; let ng_chain_hash = self.network_graph.get_chain_hash(); if chain_hash != ng_chain_hash { - return Err( - LightningError { - err: "Rapid Gossip Sync data's chain hash does not match the network graph's".to_owned(), - action: ErrorAction::IgnoreError, - }.into() - ); + return Err(LightningError { + err: "Rapid Gossip Sync data's chain hash does not match the network graph's" + .to_owned(), + action: ErrorAction::IgnoreError, + } + .into()); } let latest_seen_timestamp: u32 = Readable::read(read_cursor)?; if let Some(time) = current_time_unix { - if (latest_seen_timestamp as u64) < time.saturating_sub(STALE_RGS_UPDATE_AGE_LIMIT_SECS) { - return Err(LightningError{err: "Rapid Gossip Sync data is more than two weeks old".to_owned(), action: ErrorAction::IgnoreError}.into()); + if (latest_seen_timestamp as u64) < time.saturating_sub(STALE_RGS_UPDATE_AGE_LIMIT_SECS) + { + return Err(LightningError { + err: "Rapid Gossip Sync data is more than two weeks old".to_owned(), + action: ErrorAction::IgnoreError, + } + .into()); } } @@ -108,9 +116,8 @@ impl>, L: Deref> RapidGossipSync where L // handle SCID let scid_delta: BigSize = Readable::read(read_cursor)?; - let short_channel_id = previous_scid - .checked_add(scid_delta.0) - .ok_or(DecodeError::InvalidValue)?; + let short_channel_id = + previous_scid.checked_add(scid_delta.0).ok_or(DecodeError::InvalidValue)?; previous_scid = short_channel_id; let node_id_1_index: BigSize = Readable::read(read_cursor)?; @@ -122,8 +129,12 @@ impl>, L: Deref> RapidGossipSync where L let node_id_1 = node_ids[node_id_1_index.0 as usize]; let node_id_2 = node_ids[node_id_2_index.0 as usize]; - log_gossip!(self.logger, "Adding channel {} from RGS announcement at {}", - short_channel_id, latest_seen_timestamp); + log_gossip!( + self.logger, + "Adding channel {} from RGS announcement at {}", + short_channel_id, + latest_seen_timestamp + ); let announcement_result = network_graph.add_channel_from_partial_announcement( short_channel_id, @@ -136,7 +147,11 @@ impl>, L: Deref> RapidGossipSync where L if let ErrorAction::IgnoreDuplicateGossip = lightning_error.action { // everything is fine, just a duplicate channel announcement } else { - log_warn!(self.logger, "Failed to process channel announcement: {:?}", lightning_error); + log_warn!( + self.logger, + "Failed to process channel announcement: {:?}", + lightning_error + ); return Err(lightning_error.into()); } } @@ -160,9 +175,8 @@ impl>, L: Deref> RapidGossipSync where L for _ in 0..update_count { let scid_delta: BigSize = Readable::read(read_cursor)?; - let short_channel_id = previous_scid - .checked_add(scid_delta.0) - .ok_or(DecodeError::InvalidValue)?; + let short_channel_id = + previous_scid.checked_add(scid_delta.0).ok_or(DecodeError::InvalidValue)?; previous_scid = short_channel_id; let channel_flags: u8 = Readable::read(read_cursor)?; @@ -188,15 +202,17 @@ impl>, L: Deref> RapidGossipSync where L if (channel_flags & 0b_1000_0000) != 0 { // incremental update, field flags will indicate mutated values let read_only_network_graph = network_graph.read_only(); - if let Some(directional_info) = - read_only_network_graph.channels().get(&short_channel_id) + if let Some(directional_info) = read_only_network_graph + .channels() + .get(&short_channel_id) .and_then(|channel| channel.get_directional_info(channel_flags)) { synthetic_update.cltv_expiry_delta = directional_info.cltv_expiry_delta; synthetic_update.htlc_minimum_msat = directional_info.htlc_minimum_msat; synthetic_update.htlc_maximum_msat = directional_info.htlc_maximum_msat; synthetic_update.fee_base_msat = directional_info.fees.base_msat; - synthetic_update.fee_proportional_millionths = directional_info.fees.proportional_millionths; + synthetic_update.fee_proportional_millionths = + directional_info.fees.proportional_millionths; } else { log_trace!(self.logger, "Skipping application of channel update for chan {} with flags {} as original data is missing.", @@ -234,13 +250,23 @@ impl>, L: Deref> RapidGossipSync where L continue; } - log_gossip!(self.logger, "Updating channel {} with flags {} from RGS announcement at {}", - short_channel_id, channel_flags, latest_seen_timestamp); + log_gossip!( + self.logger, + "Updating channel {} with flags {} from RGS announcement at {}", + short_channel_id, + channel_flags, + latest_seen_timestamp + ); match network_graph.update_channel_unsigned(&synthetic_update) { Ok(_) => {}, Err(LightningError { action: ErrorAction::IgnoreDuplicateGossip, .. }) => {}, Err(LightningError { action: ErrorAction::IgnoreAndLog(level), err }) => { - log_given_level!(self.logger, level, "Failed to apply channel update: {:?}", err); + log_given_level!( + self.logger, + level, + "Failed to apply channel update: {:?}", + err + ); }, Err(LightningError { action: ErrorAction::IgnoreError, .. }) => {}, Err(e) => return Err(e.into()), @@ -274,21 +300,20 @@ mod tests { use crate::RapidGossipSync; const VALID_RGS_BINARY: [u8; 300] = [ - 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, - 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218, - 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251, - 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125, - 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136, - 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106, - 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138, - 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175, - 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128, - 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68, - 226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 4, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232, - 0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 2, 224, 0, 0, 0, 0, 58, 85, 116, 216, 0, 29, 0, - 0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1, - 0, 0, 1, + 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, + 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218, 0, 0, 0, + 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251, 187, 172, 38, + 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125, 157, 176, 223, + 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136, 88, 216, 115, 11, + 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106, 204, 131, 186, 35, + 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138, 181, 64, 187, 103, 127, + 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175, 110, 32, 237, 0, 217, 90, + 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128, 76, 97, 0, 0, 0, 2, 0, 0, 255, + 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68, 226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 4, + 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232, 0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, + 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 2, 224, + 0, 0, 0, 0, 58, 85, 116, 216, 0, 29, 0, 0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, + 216, 255, 2, 68, 226, 0, 6, 11, 0, 1, 0, 0, 1, ]; const VALID_BINARY_TIMESTAMP: u64 = 1642291930; @@ -400,10 +425,7 @@ mod tests { let rapid_sync = RapidGossipSync::new(&network_graph, &logger); let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]); if initialization_result.is_err() { - panic!( - "Unexpected initialization result: {:?}", - initialization_result - ) + panic!("Unexpected initialization result: {:?}", initialization_result) } assert_eq!(network_graph.read_only().channels().len(), 2); @@ -466,7 +488,8 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 136, 0, 0, 0, 221, 255, 2, 68, 226, 0, 6, 11, 0, 1, 128, ]; - let update_result = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]); + let update_result = + rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]); if update_result.is_err() { panic!("Unexpected update result: {:?}", update_result) } @@ -526,9 +549,11 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 136, 0, 0, 0, 221, 255, 2, 68, 226, 0, 6, 11, 0, 1, 128, ]; - let update_result_1 = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]); + let update_result_1 = + rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]); // Apply duplicate update - let update_result_2 = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]); + let update_result_2 = + rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]); assert!(update_result_1.is_ok()); assert!(update_result_2.is_ok()); } @@ -591,7 +616,8 @@ mod tests { assert_eq!(network_graph.read_only().channels().len(), 0); let rapid_sync = RapidGossipSync::new(&network_graph, &logger); - let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_nonpruning_time)); + let update_result = rapid_sync + .update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_nonpruning_time)); assert!(update_result.is_ok()); assert_eq!(network_graph.read_only().channels().len(), 2); } @@ -601,7 +627,8 @@ mod tests { assert_eq!(network_graph.read_only().channels().len(), 0); let rapid_sync = RapidGossipSync::new(&network_graph, &logger); - let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_nonpruning_time + 1)); + let update_result = rapid_sync + .update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_nonpruning_time + 1)); assert!(update_result.is_ok()); assert_eq!(network_graph.read_only().channels().len(), 0); } @@ -620,7 +647,8 @@ mod tests { assert_eq!(network_graph.read_only().channels().len(), 0); let rapid_sync = RapidGossipSync::new(&network_graph, &logger); - let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_succeeding_time)); + let update_result = rapid_sync + .update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_succeeding_time)); assert!(update_result.is_ok()); assert_eq!(network_graph.read_only().channels().len(), 0); } @@ -630,7 +658,8 @@ mod tests { assert_eq!(network_graph.read_only().channels().len(), 0); let rapid_sync = RapidGossipSync::new(&network_graph, &logger); - let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(earliest_failing_time)); + let update_result = rapid_sync + .update_network_graph_no_std(&VALID_RGS_BINARY, Some(earliest_failing_time)); assert!(update_result.is_err()); if let Err(GraphSyncError::LightningError(lightning_error)) = update_result { assert_eq!( @@ -690,7 +719,10 @@ mod tests { let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(0)); assert!(update_result.is_err()); if let Err(GraphSyncError::LightningError(err)) = update_result { - assert_eq!(err.err, "Rapid Gossip Sync data's chain hash does not match the network graph's"); + assert_eq!( + err.err, + "Rapid Gossip Sync data's chain hash does not match the network graph's" + ); } else { panic!("Unexpected update result: {:?}", update_result) } diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index 3a5541fa146..b11c70376f3 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -1,14 +1,14 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; -use crate::blinded_path::{BlindedHop, BlindedPath}; use crate::blinded_path::utils; +use crate::blinded_path::{BlindedHop, BlindedPath}; +use crate::crypto::streams::ChaChaPolyReadAdapter; use crate::io; use crate::io::Cursor; use crate::ln::onion_utils; use crate::onion_message::packet::ControlTlvs; use crate::prelude::*; use crate::sign::{NodeSigner, Recipient}; -use crate::crypto::streams::ChaChaPolyReadAdapter; use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer}; use core::mem; @@ -55,9 +55,10 @@ impl Writeable for ReceiveTlvs { /// Construct blinded onion message hops for the given `unblinded_path`. pub(super) fn blinded_hops( - secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], session_priv: &SecretKey + secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], session_priv: &SecretKey, ) -> Result, secp256k1::Error> { - let blinded_tlvs = unblinded_path.iter() + let blinded_tlvs = unblinded_path + .iter() .skip(1) // The first node's TLVs contains the next node's pubkey .map(|pk| { ControlTlvs::Forward(ForwardTlvs { next_node_id: *pk, next_blinding_override: None }) @@ -70,28 +71,33 @@ pub(super) fn blinded_hops( // Advance the blinded onion message path by one hop, so make the second hop into the new // introduction node. pub(crate) fn advance_path_by_one( - path: &mut BlindedPath, node_signer: &NS, secp_ctx: &Secp256k1 -) -> Result<(), ()> where NS::Target: NodeSigner { + path: &mut BlindedPath, node_signer: &NS, secp_ctx: &Secp256k1, +) -> Result<(), ()> +where + NS::Target: NodeSigner, +{ let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?; let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes()); let encrypted_control_tlvs = path.blinded_hops.remove(0).encrypted_payload; let mut s = Cursor::new(&encrypted_control_tlvs); let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64); match ChaChaPolyReadAdapter::read(&mut reader, rho) { - Ok(ChaChaPolyReadAdapter { readable: ControlTlvs::Forward(ForwardTlvs { - mut next_node_id, next_blinding_override, - })}) => { + Ok(ChaChaPolyReadAdapter { + readable: ControlTlvs::Forward(ForwardTlvs { mut next_node_id, next_blinding_override }), + }) => { let mut new_blinding_point = match next_blinding_override { Some(blinding_point) => blinding_point, - None => { - onion_utils::next_hop_pubkey(secp_ctx, path.blinding_point, - control_tlvs_ss.as_ref()).map_err(|_| ())? - } + None => onion_utils::next_hop_pubkey( + secp_ctx, + path.blinding_point, + control_tlvs_ss.as_ref(), + ) + .map_err(|_| ())?, }; mem::swap(&mut path.blinding_point, &mut new_blinding_point); mem::swap(&mut path.introduction_node_id, &mut next_node_id); Ok(()) }, - _ => Err(()) + _ => Err(()), } } diff --git a/lightning/src/blinded_path/mod.rs b/lightning/src/blinded_path/mod.rs index b1fc9e1c0a4..6859f5bbd89 100644 --- a/lightning/src/blinded_path/mod.rs +++ b/lightning/src/blinded_path/mod.rs @@ -9,8 +9,8 @@ //! Creating blinded paths and related utilities live here. -pub mod payment; pub(crate) mod message; +pub mod payment; pub(crate) mod utils; use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; @@ -57,8 +57,11 @@ pub struct BlindedHop { impl BlindedPath { /// Create a one-hop blinded path for a message. - pub fn one_hop_for_message( - recipient_node_id: PublicKey, entropy_source: &ES, secp_ctx: &Secp256k1 + pub fn one_hop_for_message< + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, + >( + recipient_node_id: PublicKey, entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result { Self::new_for_message(&[recipient_node_id], entropy_source, secp_ctx) } @@ -68,31 +71,46 @@ impl BlindedPath { /// /// Errors if no hops are provided or if `node_pk`(s) are invalid. // TODO: make all payloads the same size with padding + add dummy hops - pub fn new_for_message( - node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1 + pub fn new_for_message< + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, + >( + node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result { - if node_pks.is_empty() { return Err(()) } + if node_pks.is_empty() { + return Err(()); + } let blinding_secret_bytes = entropy_source.get_secure_random_bytes(); - let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); + let blinding_secret = + SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); let introduction_node_id = node_pks[0]; Ok(BlindedPath { introduction_node_id, blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), - blinded_hops: message::blinded_hops(secp_ctx, node_pks, &blinding_secret).map_err(|_| ())?, + blinded_hops: message::blinded_hops(secp_ctx, node_pks, &blinding_secret) + .map_err(|_| ())?, }) } /// Create a one-hop blinded path for a payment. - pub fn one_hop_for_payment( + pub fn one_hop_for_payment< + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, + >( payee_node_id: PublicKey, payee_tlvs: payment::ReceiveTlvs, entropy_source: &ES, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result<(BlindedPayInfo, Self), ()> { // This value is not considered in pathfinding for 1-hop blinded paths, because it's intended to // be in relation to a specific channel. let htlc_maximum_msat = u64::max_value(); Self::new_for_payment( - &[], payee_node_id, payee_tlvs, htlc_maximum_msat, entropy_source, secp_ctx + &[], + payee_node_id, + payee_tlvs, + htlc_maximum_msat, + entropy_source, + secp_ctx, ) } @@ -105,22 +123,37 @@ impl BlindedPath { /// /// [`ForwardTlvs`]: crate::blinded_path::payment::ForwardTlvs // TODO: make all payloads the same size with padding + add dummy hops - pub fn new_for_payment( + pub fn new_for_payment< + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, + >( intermediate_nodes: &[payment::ForwardNode], payee_node_id: PublicKey, payee_tlvs: payment::ReceiveTlvs, htlc_maximum_msat: u64, entropy_source: &ES, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result<(BlindedPayInfo, Self), ()> { let blinding_secret_bytes = entropy_source.get_secure_random_bytes(); - let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); - - let blinded_payinfo = payment::compute_payinfo(intermediate_nodes, &payee_tlvs, htlc_maximum_msat)?; - Ok((blinded_payinfo, BlindedPath { - introduction_node_id: intermediate_nodes.first().map_or(payee_node_id, |n| n.node_id), - blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), - blinded_hops: payment::blinded_hops( - secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, &blinding_secret - ).map_err(|_| ())?, - })) + let blinding_secret = + SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted"); + + let blinded_payinfo = + payment::compute_payinfo(intermediate_nodes, &payee_tlvs, htlc_maximum_msat)?; + Ok(( + blinded_payinfo, + BlindedPath { + introduction_node_id: intermediate_nodes + .first() + .map_or(payee_node_id, |n| n.node_id), + blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), + blinded_hops: payment::blinded_hops( + secp_ctx, + intermediate_nodes, + payee_node_id, + payee_tlvs, + &blinding_secret, + ) + .map_err(|_| ())?, + }, + )) } } @@ -141,16 +174,14 @@ impl Readable for BlindedPath { let introduction_node_id = Readable::read(r)?; let blinding_point = Readable::read(r)?; let num_hops: u8 = Readable::read(r)?; - if num_hops == 0 { return Err(DecodeError::InvalidValue) } + if num_hops == 0 { + return Err(DecodeError::InvalidValue); + } let mut blinded_hops: Vec = Vec::with_capacity(num_hops.into()); for _ in 0..num_hops { blinded_hops.push(Readable::read(r)?); } - Ok(BlindedPath { - introduction_node_id, - blinding_point, - blinded_hops, - }) + Ok(BlindedPath { introduction_node_id, blinding_point, blinded_hops }) } } @@ -158,4 +189,3 @@ impl_writeable!(BlindedHop, { blinded_node_id, encrypted_payload }); - diff --git a/lightning/src/blinded_path/payment.rs b/lightning/src/blinded_path/payment.rs index 5d332a76faf..feb65f97edb 100644 --- a/lightning/src/blinded_path/payment.rs +++ b/lightning/src/blinded_path/payment.rs @@ -4,13 +4,13 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; -use crate::blinded_path::BlindedHop; use crate::blinded_path::utils; +use crate::blinded_path::BlindedHop; use crate::io; -use crate::ln::PaymentSecret; use crate::ln::channelmanager::CounterpartyForwardingInfo; use crate::ln::features::BlindedHopFeatures; use crate::ln::msgs::DecodeError; +use crate::ln::PaymentSecret; use crate::offers::invoice::BlindedPayInfo; use crate::prelude::*; use crate::util::ser::{Readable, Writeable, Writer}; @@ -102,7 +102,9 @@ impl TryFrom for PaymentRelay { fn try_from(info: CounterpartyForwardingInfo) -> Result { let CounterpartyForwardingInfo { - fee_base_msat, fee_proportional_millionths, cltv_expiry_delta + fee_base_msat, + fee_proportional_millionths, + cltv_expiry_delta, } = info; // Avoid exposing esoteric CLTV expiry deltas @@ -164,7 +166,9 @@ impl Readable for BlindedPaymentTlvs { let _padding: Option = _padding; if let Some(short_channel_id) = scid { - if payment_secret.is_some() { return Err(DecodeError::InvalidValue) } + if payment_secret.is_some() { + return Err(DecodeError::InvalidValue); + } Ok(BlindedPaymentTlvs::Forward(ForwardTlvs { short_channel_id, payment_relay: payment_relay.ok_or(DecodeError::InvalidValue)?, @@ -172,7 +176,9 @@ impl Readable for BlindedPaymentTlvs { features: features.ok_or(DecodeError::InvalidValue)?, })) } else { - if payment_relay.is_some() || features.is_some() { return Err(DecodeError::InvalidValue) } + if payment_relay.is_some() || features.is_some() { + return Err(DecodeError::InvalidValue); + } Ok(BlindedPaymentTlvs::Receive(ReceiveTlvs { payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?, payment_constraints: payment_constraints.0.unwrap(), @@ -183,18 +189,22 @@ impl Readable for BlindedPaymentTlvs { /// Construct blinded payment hops for the given `intermediate_nodes` and payee info. pub(super) fn blinded_hops( - secp_ctx: &Secp256k1, intermediate_nodes: &[ForwardNode], - payee_node_id: PublicKey, payee_tlvs: ReceiveTlvs, session_priv: &SecretKey + secp_ctx: &Secp256k1, intermediate_nodes: &[ForwardNode], payee_node_id: PublicKey, + payee_tlvs: ReceiveTlvs, session_priv: &SecretKey, ) -> Result, secp256k1::Error> { - let pks = intermediate_nodes.iter().map(|node| &node.node_id) - .chain(core::iter::once(&payee_node_id)); - let tlvs = intermediate_nodes.iter().map(|node| BlindedPaymentTlvsRef::Forward(&node.tlvs)) + let pks = + intermediate_nodes.iter().map(|node| &node.node_id).chain(core::iter::once(&payee_node_id)); + let tlvs = intermediate_nodes + .iter() + .map(|node| BlindedPaymentTlvsRef::Forward(&node.tlvs)) .chain(core::iter::once(BlindedPaymentTlvsRef::Receive(&payee_tlvs))); utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv) } /// `None` if underflow occurs. -pub(crate) fn amt_to_forward_msat(inbound_amt_msat: u64, payment_relay: &PaymentRelay) -> Option { +pub(crate) fn amt_to_forward_msat( + inbound_amt_msat: u64, payment_relay: &PaymentRelay, +) -> Option { let inbound_amt = inbound_amt_msat as u128; let base = payment_relay.fee_base_msat as u128; let prop = payment_relay.fee_proportional_millionths as u128; @@ -215,7 +225,7 @@ pub(crate) fn amt_to_forward_msat(inbound_amt_msat: u64, payment_relay: &Payment } pub(super) fn compute_payinfo( - intermediate_nodes: &[ForwardNode], payee_tlvs: &ReceiveTlvs, payee_htlc_maximum_msat: u64 + intermediate_nodes: &[ForwardNode], payee_tlvs: &ReceiveTlvs, payee_htlc_maximum_msat: u64, ) -> Result { let mut curr_base_fee: u64 = 0; let mut curr_prop_mil: u64 = 0; @@ -223,26 +233,31 @@ pub(super) fn compute_payinfo( for tlvs in intermediate_nodes.iter().rev().map(|n| &n.tlvs) { // In the future, we'll want to take the intersection of all supported features for the // `BlindedPayInfo`, but there are no features in that context right now. - if tlvs.features.requires_unknown_bits_from(&BlindedHopFeatures::empty()) { return Err(()) } + if tlvs.features.requires_unknown_bits_from(&BlindedHopFeatures::empty()) { + return Err(()); + } let next_base_fee = tlvs.payment_relay.fee_base_msat as u64; let next_prop_mil = tlvs.payment_relay.fee_proportional_millionths as u64; // Use integer arithmetic to compute `ceil(a/b)` as `(a+b-1)/b` // ((curr_base_fee * (1_000_000 + next_prop_mil)) / 1_000_000) + next_base_fee - curr_base_fee = curr_base_fee.checked_mul(1_000_000 + next_prop_mil) + curr_base_fee = curr_base_fee + .checked_mul(1_000_000 + next_prop_mil) .and_then(|f| f.checked_add(1_000_000 - 1)) .map(|f| f / 1_000_000) .and_then(|f| f.checked_add(next_base_fee)) .ok_or(())?; // ceil(((curr_prop_mil + 1_000_000) * (next_prop_mil + 1_000_000)) / 1_000_000) - 1_000_000 - curr_prop_mil = curr_prop_mil.checked_add(1_000_000) + curr_prop_mil = curr_prop_mil + .checked_add(1_000_000) .and_then(|f1| next_prop_mil.checked_add(1_000_000).and_then(|f2| f2.checked_mul(f1))) .and_then(|f| f.checked_add(1_000_000 - 1)) .map(|f| f / 1_000_000) .and_then(|f| f.checked_sub(1_000_000)) .ok_or(())?; - cltv_expiry_delta = cltv_expiry_delta.checked_add(tlvs.payment_relay.cltv_expiry_delta).ok_or(())?; + cltv_expiry_delta = + cltv_expiry_delta.checked_add(tlvs.payment_relay.cltv_expiry_delta).ok_or(())?; } let mut htlc_minimum_msat: u64 = 1; @@ -253,18 +268,22 @@ pub(super) fn compute_payinfo( // in the amount that this node receives and contribute towards reaching its min. htlc_minimum_msat = amt_to_forward_msat( core::cmp::max(node.tlvs.payment_constraints.htlc_minimum_msat, htlc_minimum_msat), - &node.tlvs.payment_relay - ).unwrap_or(1); // If underflow occurs, we definitely reached this node's min + &node.tlvs.payment_relay, + ) + .unwrap_or(1); // If underflow occurs, we definitely reached this node's min htlc_maximum_msat = amt_to_forward_msat( - core::cmp::min(node.htlc_maximum_msat, htlc_maximum_msat), &node.tlvs.payment_relay - ).ok_or(())?; // If underflow occurs, we cannot send to this hop without exceeding their max + core::cmp::min(node.htlc_maximum_msat, htlc_maximum_msat), + &node.tlvs.payment_relay, + ) + .ok_or(())?; // If underflow occurs, we cannot send to this hop without exceeding their max } - htlc_minimum_msat = core::cmp::max( - payee_tlvs.payment_constraints.htlc_minimum_msat, htlc_minimum_msat - ); + htlc_minimum_msat = + core::cmp::max(payee_tlvs.payment_constraints.htlc_minimum_msat, htlc_minimum_msat); htlc_maximum_msat = core::cmp::min(payee_htlc_maximum_msat, htlc_maximum_msat); - if htlc_maximum_msat < htlc_minimum_msat { return Err(()) } + if htlc_maximum_msat < htlc_minimum_msat { + return Err(()); + } Ok(BlindedPayInfo { fee_base_msat: u32::try_from(curr_base_fee).map_err(|_| ())?, fee_proportional_millionths: u32::try_from(curr_prop_mil).map_err(|_| ())?, @@ -288,58 +307,61 @@ impl_writeable_msg!(PaymentConstraints, { #[cfg(test)] mod tests { - use bitcoin::secp256k1::PublicKey; - use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, ReceiveTlvs, PaymentConstraints, PaymentRelay}; - use crate::ln::PaymentSecret; + use crate::blinded_path::payment::{ + ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs, + }; use crate::ln::features::BlindedHopFeatures; + use crate::ln::PaymentSecret; + use bitcoin::secp256k1::PublicKey; #[test] fn compute_payinfo() { // Taken from the spec example for aggregating blinded payment info. See // https://github.com/lightning/bolts/blob/master/proposals/route-blinding.md#blinded-payments let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap(); - let intermediate_nodes = vec![ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 144, - fee_proportional_millionths: 500, - fee_base_msat: 100, - }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 100, + let intermediate_nodes = vec![ + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 144, + fee_proportional_millionths: 500, + fee_base_msat: 100, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 100, + }, + features: BlindedHopFeatures::empty(), }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: u64::max_value(), }, - htlc_maximum_msat: u64::max_value(), - }, ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 144, - fee_proportional_millionths: 500, - fee_base_msat: 100, - }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1_000, + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 144, + fee_proportional_millionths: 500, + fee_base_msat: 100, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 1_000, + }, + features: BlindedHopFeatures::empty(), }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: u64::max_value(), }, - htlc_maximum_msat: u64::max_value(), - }]; + ]; let recv_tlvs = ReceiveTlvs { payment_secret: PaymentSecret([0; 32]), - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1, - }, + payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 }, }; let htlc_maximum_msat = 100_000; - let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat).unwrap(); + let blinded_payinfo = + super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat).unwrap(); assert_eq!(blinded_payinfo.fee_base_msat, 201); assert_eq!(blinded_payinfo.fee_proportional_millionths, 1001); assert_eq!(blinded_payinfo.cltv_expiry_delta, 288); @@ -351,10 +373,7 @@ mod tests { fn compute_payinfo_1_hop() { let recv_tlvs = ReceiveTlvs { payment_secret: PaymentSecret([0; 32]), - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1, - }, + payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 }, }; let blinded_payinfo = super::compute_payinfo(&[], &recv_tlvs, 4242).unwrap(); assert_eq!(blinded_payinfo.fee_base_msat, 0); @@ -369,48 +388,49 @@ mod tests { // If no hops charge fees, the htlc_minimum_msat should just be the maximum htlc_minimum_msat // along the path. let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap(); - let intermediate_nodes = vec![ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 0, - fee_proportional_millionths: 0, - fee_base_msat: 0, - }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1, + let intermediate_nodes = vec![ + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 0, + fee_proportional_millionths: 0, + fee_base_msat: 0, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 1, + }, + features: BlindedHopFeatures::empty(), }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: u64::max_value(), }, - htlc_maximum_msat: u64::max_value() - }, ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 0, - fee_proportional_millionths: 0, - fee_base_msat: 0, + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 0, + fee_proportional_millionths: 0, + fee_base_msat: 0, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 2_000, + }, + features: BlindedHopFeatures::empty(), }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 2_000, - }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: u64::max_value(), }, - htlc_maximum_msat: u64::max_value() - }]; + ]; let recv_tlvs = ReceiveTlvs { payment_secret: PaymentSecret([0; 32]), - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 3, - }, + payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 3 }, }; let htlc_maximum_msat = 100_000; - let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat).unwrap(); + let blinded_payinfo = + super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat).unwrap(); assert_eq!(blinded_payinfo.htlc_minimum_msat, 2_000); } @@ -419,51 +439,53 @@ mod tests { // Create a path with varying fees and htlc_mins, and make sure htlc_minimum_msat ends up as the // max (htlc_min - following_fees) along the path. let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap(); - let intermediate_nodes = vec![ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 0, - fee_proportional_millionths: 500, - fee_base_msat: 1_000, - }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 5_000, + let intermediate_nodes = vec![ + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 0, + fee_proportional_millionths: 500, + fee_base_msat: 1_000, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 5_000, + }, + features: BlindedHopFeatures::empty(), }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: u64::max_value(), }, - htlc_maximum_msat: u64::max_value() - }, ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 0, - fee_proportional_millionths: 500, - fee_base_msat: 200, + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 0, + fee_proportional_millionths: 500, + fee_base_msat: 200, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 2_000, + }, + features: BlindedHopFeatures::empty(), }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 2_000, - }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: u64::max_value(), }, - htlc_maximum_msat: u64::max_value() - }]; + ]; let recv_tlvs = ReceiveTlvs { payment_secret: PaymentSecret([0; 32]), - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1, - }, + payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 }, }; let htlc_minimum_msat = 3798; - assert!(super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_minimum_msat - 1).is_err()); + assert!(super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_minimum_msat - 1) + .is_err()); let htlc_maximum_msat = htlc_minimum_msat + 1; - let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat).unwrap(); + let blinded_payinfo = + super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, htlc_maximum_msat).unwrap(); assert_eq!(blinded_payinfo.htlc_minimum_msat, htlc_minimum_msat); assert_eq!(blinded_payinfo.htlc_maximum_msat, htlc_maximum_msat); } @@ -473,48 +495,49 @@ mod tests { // Create a path with varying fees and `htlc_maximum_msat`s, and make sure the aggregated max // htlc ends up as the min (htlc_max - following_fees) along the path. let dummy_pk = PublicKey::from_slice(&[2; 33]).unwrap(); - let intermediate_nodes = vec![ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 0, - fee_proportional_millionths: 500, - fee_base_msat: 1_000, - }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1, + let intermediate_nodes = vec![ + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 0, + fee_proportional_millionths: 500, + fee_base_msat: 1_000, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 1, + }, + features: BlindedHopFeatures::empty(), }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: 5_000, }, - htlc_maximum_msat: 5_000, - }, ForwardNode { - node_id: dummy_pk, - tlvs: ForwardTlvs { - short_channel_id: 0, - payment_relay: PaymentRelay { - cltv_expiry_delta: 0, - fee_proportional_millionths: 500, - fee_base_msat: 1, + ForwardNode { + node_id: dummy_pk, + tlvs: ForwardTlvs { + short_channel_id: 0, + payment_relay: PaymentRelay { + cltv_expiry_delta: 0, + fee_proportional_millionths: 500, + fee_base_msat: 1, + }, + payment_constraints: PaymentConstraints { + max_cltv_expiry: 0, + htlc_minimum_msat: 1, + }, + features: BlindedHopFeatures::empty(), }, - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1, - }, - features: BlindedHopFeatures::empty(), + htlc_maximum_msat: 10_000, }, - htlc_maximum_msat: 10_000 - }]; + ]; let recv_tlvs = ReceiveTlvs { payment_secret: PaymentSecret([0; 32]), - payment_constraints: PaymentConstraints { - max_cltv_expiry: 0, - htlc_minimum_msat: 1, - }, + payment_constraints: PaymentConstraints { max_cltv_expiry: 0, htlc_minimum_msat: 1 }, }; - let blinded_payinfo = super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, 10_000).unwrap(); + let blinded_payinfo = + super::compute_payinfo(&intermediate_nodes[..], &recv_tlvs, 10_000).unwrap(); assert_eq!(blinded_payinfo.htlc_maximum_msat, 3997); } } diff --git a/lightning/src/blinded_path/utils.rs b/lightning/src/blinded_path/utils.rs index d4894a86aa1..e0409201c27 100644 --- a/lightning/src/blinded_path/utils.rs +++ b/lightning/src/blinded_path/utils.rs @@ -9,17 +9,17 @@ //! Onion message utility methods live here. -use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey, Scalar}; +use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::secp256k1::ecdh::SharedSecret; +use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey}; use super::{BlindedHop, BlindedPath}; +use crate::crypto::streams::ChaChaPolyWriteAdapter; use crate::ln::msgs::DecodeError; use crate::ln::onion_utils; use crate::onion_message::messenger::Destination; -use crate::crypto::streams::ChaChaPolyWriteAdapter; use crate::util::ser::{Readable, Writeable}; use crate::io; @@ -29,11 +29,11 @@ use crate::prelude::*; #[inline] pub(crate) fn construct_keys_callback<'a, T, I, F>( secp_ctx: &Secp256k1, unblinded_path: I, destination: Option, - session_priv: &SecretKey, mut callback: F + session_priv: &SecretKey, mut callback: F, ) -> Result<(), secp256k1::Error> where T: secp256k1::Signing + secp256k1::Verification, - I: Iterator, + I: Iterator, F: FnMut(PublicKey, SharedSecret, PublicKey, [u8; 32], Option, Option>), { let mut msg_blinding_point_priv = session_priv.clone(); @@ -45,7 +45,9 @@ where ($pk: expr, $blinded: expr, $encrypted_payload: expr) => {{ let encrypted_data_ss = SharedSecret::new(&$pk, &msg_blinding_point_priv); - let blinded_hop_pk = if $blinded { $pk } else { + let blinded_hop_pk = if $blinded { + $pk + } else { let hop_pk_blinding_factor = { let mut hmac = HmacEngine::::new(b"blinded_node_id"); hmac.input(encrypted_data_ss.as_ref()); @@ -57,14 +59,22 @@ where let rho = onion_utils::gen_rho_from_shared_secret(encrypted_data_ss.as_ref()); let unblinded_pk_opt = if $blinded { None } else { Some($pk) }; - callback(blinded_hop_pk, onion_packet_ss, onion_packet_pubkey, rho, unblinded_pk_opt, $encrypted_payload); + callback( + blinded_hop_pk, + onion_packet_ss, + onion_packet_pubkey, + rho, + unblinded_pk_opt, + $encrypted_payload, + ); (encrypted_data_ss, onion_packet_ss) - }} + }}; } macro_rules! build_keys_in_loop { ($pk: expr, $blinded: expr, $encrypted_payload: expr) => { - let (encrypted_data_ss, onion_packet_ss) = build_keys!($pk, $blinded, $encrypted_payload); + let (encrypted_data_ss, onion_packet_ss) = + build_keys!($pk, $blinded, $encrypted_payload); let msg_blinding_point_blinding_factor = { let mut sha = Sha256::engine(); @@ -73,7 +83,8 @@ where Sha256::from_engine(sha).to_byte_array() }; - msg_blinding_point_priv = msg_blinding_point_priv.mul_tweak(&Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap())?; + msg_blinding_point_priv = msg_blinding_point_priv + .mul_tweak(&Scalar::from_be_bytes(msg_blinding_point_blinding_factor).unwrap())?; msg_blinding_point = PublicKey::from_secret_key(secp_ctx, &msg_blinding_point_priv); let onion_packet_pubkey_blinding_factor = { @@ -82,7 +93,8 @@ where sha.input(onion_packet_ss.as_ref()); Sha256::from_engine(sha).to_byte_array() }; - onion_packet_pubkey_priv = onion_packet_pubkey_priv.mul_tweak(&Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap())?; + onion_packet_pubkey_priv = onion_packet_pubkey_priv + .mul_tweak(&Scalar::from_be_bytes(onion_packet_pubkey_blinding_factor).unwrap())?; onion_packet_pubkey = PublicKey::from_secret_key(secp_ctx, &onion_packet_pubkey_priv); }; } @@ -107,23 +119,30 @@ where // Panics if `unblinded_tlvs` length is less than `unblinded_pks` length pub(super) fn construct_blinded_hops<'a, T, I1, I2>( - secp_ctx: &Secp256k1, unblinded_pks: I1, mut unblinded_tlvs: I2, session_priv: &SecretKey + secp_ctx: &Secp256k1, unblinded_pks: I1, mut unblinded_tlvs: I2, session_priv: &SecretKey, ) -> Result, secp256k1::Error> where T: secp256k1::Signing + secp256k1::Verification, - I1: Iterator, + I1: Iterator, I2: Iterator, - I2::Item: Writeable + I2::Item: Writeable, { let mut blinded_hops = Vec::with_capacity(unblinded_pks.size_hint().0); construct_keys_callback( - secp_ctx, unblinded_pks, None, session_priv, + secp_ctx, + unblinded_pks, + None, + session_priv, |blinded_node_id, _, _, encrypted_payload_rho, _, _| { blinded_hops.push(BlindedHop { blinded_node_id, - encrypted_payload: encrypt_payload(unblinded_tlvs.next().unwrap(), encrypted_payload_rho), + encrypted_payload: encrypt_payload( + unblinded_tlvs.next().unwrap(), + encrypted_payload_rho, + ), }); - })?; + }, + )?; Ok(blinded_hops) } @@ -142,7 +161,9 @@ impl Readable for Padding { fn read(reader: &mut R) -> Result { loop { let mut buf = [0; 8192]; - if reader.read(&mut buf[..])? == 0 { break; } + if reader.read(&mut buf[..])? == 0 { + break; + } } Ok(Self {}) } diff --git a/lightning/src/chain/chaininterface.rs b/lightning/src/chain/chaininterface.rs index 1f42dc2fe42..a7b799f464a 100644 --- a/lightning/src/chain/chaininterface.rs +++ b/lightning/src/chain/chaininterface.rs @@ -13,8 +13,8 @@ //! Includes traits for monitoring and receiving notifications of new blocks and block //! disconnections, transaction broadcasting, and feerate information requests. -use core::{cmp, ops::Deref}; use core::convert::TryInto; +use core::{cmp, ops::Deref}; use bitcoin::blockdata::transaction::Transaction; @@ -159,25 +159,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, @@ -195,7 +199,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] @@ -204,6 +211,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 b71f10f58d4..2154e2c0e51 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -24,29 +24,32 @@ //! servicing [`ChannelMonitor`] updates from the client. use bitcoin::blockdata::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, LATENCY_GRACE_PERIOD_BLOCKS}; +use crate::chain::channelmonitor::{ + Balance, ChannelMonitor, ChannelMonitorUpdate, MonitorEvent, TransactionOutputs, + WithChannelMonitor, LATENCY_GRACE_PERIOD_BLOCKS, +}; use crate::chain::transaction::{OutPoint, TransactionData}; -use crate::ln::ChannelId; -use crate::sign::ecdsa::WriteableEcdsaChannelSigner; +use crate::chain::{ChannelMonitorUpdateStatus, Filter, WatchedOutput}; use crate::events; use crate::events::{Event, EventHandler}; +use crate::ln::channelmanager::ChannelDetails; +use crate::ln::ChannelId; +use crate::sign::ecdsa::WriteableEcdsaChannelSigner; use crate::util::atomic_counter::AtomicCounter; -use crate::util::logger::{Logger, WithContext}; use crate::util::errors::APIError; +use crate::util::logger::{Logger, WithContext}; use crate::util::wakers::{Future, Notifier}; -use crate::ln::channelmanager::ChannelDetails; use crate::prelude::*; -use crate::sync::{RwLock, RwLockReadGuard, Mutex, MutexGuard}; +use crate::sync::{Mutex, MutexGuard, RwLock, RwLockReadGuard}; +use bitcoin::secp256k1::PublicKey; use core::iter::FromIterator; use core::ops::Deref; use core::sync::atomic::{AtomicUsize, Ordering}; -use bitcoin::secp256k1::PublicKey; mod update_origin { #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] @@ -83,7 +86,9 @@ impl MonitorUpdateId { pub(crate) fn from_monitor_update(update: &ChannelMonitorUpdate) -> Self { Self { contents: UpdateOrigin::OffChain(update.update_id) } } - pub(crate) fn from_new_monitor(monitor: &ChannelMonitor) -> Self { + pub(crate) fn from_new_monitor( + monitor: &ChannelMonitor, + ) -> Self { Self { contents: UpdateOrigin::OffChain(monitor.get_latest_update_id()) } } } @@ -159,7 +164,10 @@ pub trait Persist { /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [`Writeable::write`]: crate::util::ser::Writeable::write - fn persist_new_channel(&self, channel_funding_outpoint: OutPoint, data: &ChannelMonitor, update_id: MonitorUpdateId) -> ChannelMonitorUpdateStatus; + fn persist_new_channel( + &self, channel_funding_outpoint: OutPoint, data: &ChannelMonitor, + update_id: MonitorUpdateId, + ) -> ChannelMonitorUpdateStatus; /// Update one channel's data. The provided [`ChannelMonitor`] has already applied the given /// update. @@ -194,7 +202,10 @@ pub trait Persist { /// [`ChannelMonitorUpdateStatus`] for requirements when returning errors. /// /// [`Writeable::write`]: crate::util::ser::Writeable::write - fn update_persisted_channel(&self, channel_funding_outpoint: OutPoint, update: Option<&ChannelMonitorUpdate>, data: &ChannelMonitor, update_id: MonitorUpdateId) -> ChannelMonitorUpdateStatus; + fn update_persisted_channel( + &self, channel_funding_outpoint: OutPoint, update: Option<&ChannelMonitorUpdate>, + data: &ChannelMonitor, update_id: MonitorUpdateId, + ) -> ChannelMonitorUpdateStatus; } struct MonitorHolder { @@ -227,13 +238,27 @@ struct MonitorHolder { } impl MonitorHolder { - fn has_pending_offchain_updates(&self, pending_monitor_updates_lock: &MutexGuard>) -> bool { - pending_monitor_updates_lock.iter().any(|update_id| - if let UpdateOrigin::OffChain(_) = update_id.contents { true } else { false }) + fn has_pending_offchain_updates( + &self, pending_monitor_updates_lock: &MutexGuard>, + ) -> bool { + pending_monitor_updates_lock.iter().any(|update_id| { + if let UpdateOrigin::OffChain(_) = update_id.contents { + true + } else { + false + } + }) } - fn has_pending_chainsync_updates(&self, pending_monitor_updates_lock: &MutexGuard>) -> bool { - pending_monitor_updates_lock.iter().any(|update_id| - if let UpdateOrigin::ChainSync(_) = update_id.contents { true } else { false }) + fn has_pending_chainsync_updates( + &self, pending_monitor_updates_lock: &MutexGuard>, + ) -> bool { + pending_monitor_updates_lock.iter().any(|update_id| { + if let UpdateOrigin::ChainSync(_) = update_id.contents { + true + } else { + false + } + }) } } @@ -269,12 +294,19 @@ impl Deref for LockedChannelMonitor< /// [`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: WriteableEcdsaChannelSigner, + 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>>, /// When we generate a [`MonitorUpdateId`] for a chain-event monitor persistence, we need a @@ -295,12 +327,20 @@ pub struct ChainMonitor ChainMonitor -where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +impl< + ChannelSigner: WriteableEcdsaChannelSigner, + C: Deref, + T: Deref, + F: Deref, + L: Deref, + P: Deref, + > 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 @@ -313,16 +353,28 @@ 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 funding_outpoints: HashSet = HashSet::from_iter(self.monitors.read().unwrap().keys().cloned()); + let funding_outpoints: HashSet = + HashSet::from_iter(self.monitors.read().unwrap().keys().cloned()); for funding_outpoint in funding_outpoints.iter() { let monitor_lock = self.monitors.read().unwrap(); if let Some(monitor_state) = monitor_lock.get(funding_outpoint) { - if self.update_monitor_with_chain_data(header, best_height, txdata, &process, funding_outpoint, &monitor_state).is_err() { + if self + .update_monitor_with_chain_data( + header, + best_height, + txdata, + &process, + funding_outpoint, + &monitor_state, + ) + .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); @@ -337,7 +389,17 @@ where C::Target: chain::Filter, let monitor_states = self.monitors.write().unwrap(); for (funding_outpoint, monitor_state) in monitor_states.iter() { if !funding_outpoints.contains(funding_outpoint) { - if self.update_monitor_with_chain_data(header, best_height, txdata, &process, funding_outpoint, &monitor_state).is_err() { + if self + .update_monitor_with_chain_data( + header, + best_height, + txdata, + &process, + funding_outpoint, + &monitor_state, + ) + .is_err() + { log_error!(self.logger, "{}", err_str); panic!("{}", err_str); } @@ -356,9 +418,12 @@ where C::Target: chain::Filter, } fn update_monitor_with_chain_data( - &self, header: &Header, best_height: Option, txdata: &TransactionData, - process: FN, funding_outpoint: &OutPoint, monitor_state: &MonitorHolder - ) -> Result<(), ()> where FN: Fn(&ChannelMonitor, &TransactionData) -> Vec { + &self, header: &Header, best_height: Option, txdata: &TransactionData, process: FN, + funding_outpoint: &OutPoint, monitor_state: &MonitorHolder, + ) -> Result<(), ()> + where + FN: Fn(&ChannelMonitor, &TransactionData) -> Vec, + { let monitor = &monitor_state.monitor; let logger = WithChannelMonitor::from(&self.logger, &monitor); let mut txn_outputs; @@ -373,14 +438,28 @@ where C::Target: chain::Filter, // If there are not ChainSync persists awaiting completion, go ahead and // set last_chain_persist_height here - we wouldn't want the first // InProgress to always immediately be considered "overly delayed". - monitor_state.last_chain_persist_height.store(height as usize, Ordering::Release); + monitor_state + .last_chain_persist_height + .store(height as usize, Ordering::Release); } } - log_trace!(logger, "Syncing Channel Monitor for channel {}", log_funding_info!(monitor)); - match self.persister.update_persisted_channel(*funding_outpoint, None, monitor, update_id) { - ChannelMonitorUpdateStatus::Completed => - log_trace!(logger, "Finished syncing Channel Monitor for channel {}", log_funding_info!(monitor)), + log_trace!( + logger, + "Syncing Channel Monitor for channel {}", + log_funding_info!(monitor) + ); + match self.persister.update_persisted_channel( + *funding_outpoint, + None, + monitor, + update_id, + ) { + ChannelMonitorUpdateStatus::Completed => log_trace!( + logger, + "Finished syncing Channel Monitor for channel {}", + log_funding_info!(monitor) + ), ChannelMonitorUpdateStatus::InProgress => { log_debug!(logger, "Channel Monitor sync for channel {} in progress, holding events until completion!", log_funding_info!(monitor)); pending_monitor_updates.push(update_id); @@ -403,7 +482,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); } } @@ -418,7 +501,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(HashMap::new()), sync_persistence_id: AtomicCounter::new(), @@ -463,7 +548,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, funding_txo: OutPoint) -> Result, ()> { + pub fn get_monitor( + &self, funding_txo: OutPoint, + ) -> Result, ()> { let lock = self.monitors.read().unwrap(); if lock.get(&funding_txo).is_some() { Ok(LockedChannelMonitor { lock, funding_txo }) @@ -477,29 +564,43 @@ where C::Target: chain::Filter, /// Note that [`ChannelMonitor`]s are not removed when a channel is closed as they are always /// monitoring for on-chain state resolutions. pub fn list_monitors(&self) -> Vec<(OutPoint, ChannelId)> { - self.monitors.read().unwrap().iter().map(|(outpoint, monitor_holder)| { - let channel_id = monitor_holder.monitor.channel_id(); - (*outpoint, channel_id) - }).collect() + self.monitors + .read() + .unwrap() + .iter() + .map(|(outpoint, monitor_holder)| { + let channel_id = monitor_holder.monitor.channel_id(); + (*outpoint, channel_id) + }) + .collect() } #[cfg(not(c_bindings))] /// Lists the pending updates for each [`ChannelMonitor`] (by `OutPoint` being monitored). pub fn list_pending_monitor_updates(&self) -> HashMap> { - self.monitors.read().unwrap().iter().map(|(outpoint, holder)| { - (*outpoint, holder.pending_monitor_updates.lock().unwrap().clone()) - }).collect() + self.monitors + .read() + .unwrap() + .iter() + .map(|(outpoint, holder)| { + (*outpoint, holder.pending_monitor_updates.lock().unwrap().clone()) + }) + .collect() } #[cfg(c_bindings)] /// Lists the pending updates for each [`ChannelMonitor`] (by `OutPoint` being monitored). pub fn list_pending_monitor_updates(&self) -> Vec<(OutPoint, Vec)> { - self.monitors.read().unwrap().iter().map(|(outpoint, holder)| { - (*outpoint, holder.pending_monitor_updates.lock().unwrap().clone()) - }).collect() + self.monitors + .read() + .unwrap() + .iter() + .map(|(outpoint, holder)| { + (*outpoint, holder.pending_monitor_updates.lock().unwrap().clone()) + }) + .collect() } - #[cfg(test)] pub fn remove_monitor(&self, funding_txo: &OutPoint) -> ChannelMonitor { self.monitors.write().unwrap().remove(funding_txo).unwrap().monitor @@ -521,10 +622,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, funding_txo: OutPoint, completed_update_id: MonitorUpdateId) -> Result<(), APIError> { + pub fn channel_monitor_updated( + &self, funding_txo: OutPoint, completed_update_id: MonitorUpdateId, + ) -> Result<(), APIError> { let monitors = self.monitors.read().unwrap(); - let monitor_data = if let Some(mon) = monitors.get(&funding_txo) { mon } else { - return Err(APIError::APIMisuseError { err: format!("No ChannelMonitor matching funding outpoint {:?} found", funding_txo) }); + let monitor_data = if let Some(mon) = monitors.get(&funding_txo) { + mon + } else { + return Err(APIError::APIMisuseError { + err: format!("No ChannelMonitor matching funding outpoint {:?} found", funding_txo), + }); }; let mut pending_monitor_updates = monitor_data.pending_monitor_updates.lock().unwrap(); pending_monitor_updates.retain(|update_id| *update_id != completed_update_id); @@ -540,21 +647,31 @@ where C::Target: chain::Filter, // - we can still update our channel state, just as long as we don't return // `MonitorEvent`s from the monitor back to the `ChannelManager` until they // complete. - let monitor_is_pending_updates = monitor_data.has_pending_offchain_updates(&pending_monitor_updates); + let monitor_is_pending_updates = + monitor_data.has_pending_offchain_updates(&pending_monitor_updates); if monitor_is_pending_updates { // If there are still monitor updates pending, we cannot yet construct a // Completed event. return Ok(()); } let channel_id = monitor_data.monitor.channel_id(); - self.pending_monitor_events.lock().unwrap().push((funding_txo, channel_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.pending_monitor_events.lock().unwrap().push(( + funding_txo, + channel_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(), + )); }, MonitorUpdateId { contents: UpdateOrigin::ChainSync(_) } => { if !monitor_data.has_pending_chainsync_updates(&pending_monitor_updates) { - monitor_data.last_chain_persist_height.store(self.highest_chain_height.load(Ordering::Acquire), Ordering::Release); + monitor_data.last_chain_persist_height.store( + self.highest_chain_height.load(Ordering::Acquire), + Ordering::Release, + ); // The next time release_pending_monitor_events is called, any events for this // ChannelMonitor will be returned. } @@ -575,11 +692,12 @@ where C::Target: chain::Filter, } else { (None, ChannelId::v1_from_funding_outpoint(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(); } @@ -598,8 +716,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 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. @@ -607,7 +728,10 @@ where C::Target: chain::Filter, for funding_txo in mons_to_process { let mut ev; super::channelmonitor::process_events_body!( - self.monitors.read().unwrap().get(&funding_txo).map(|m| &m.monitor), ev, handler(ev).await); + self.monitors.read().unwrap().get(&funding_txo).map(|m| &m.monitor), + ev, + handler(ev).await + ); } } @@ -632,14 +756,22 @@ 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, ) } } } -impl -chain::Listen for ChainMonitor +impl< + ChannelSigner: WriteableEcdsaChannelSigner, + C: Deref, + T: Deref, + F: Deref, + L: Deref, + P: Deref, + > chain::Listen for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, @@ -648,25 +780,52 @@ 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, + ) }); } 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 +impl< + ChannelSigner: WriteableEcdsaChannelSigner, + C: Deref, + T: Deref, + F: Deref, + L: Deref, + P: Deref, + > chain::Confirm for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, @@ -675,10 +834,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, + ) }); } @@ -686,18 +857,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, ) }); } @@ -715,15 +900,24 @@ where } } -impl -chain::Watch for ChainMonitor -where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +impl< + ChannelSigner: WriteableEcdsaChannelSigner, + C: Deref, + T: Deref, + F: Deref, + L: Deref, + P: Deref, + > 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, funding_outpoint: OutPoint, monitor: ChannelMonitor) -> Result { + fn watch_channel( + &self, funding_outpoint: OutPoint, monitor: ChannelMonitor, + ) -> Result { let logger = WithChannelMonitor::from(&self.logger, &monitor); let mut monitors = self.monitors.write().unwrap(); let entry = match monitors.entry(funding_outpoint) { @@ -739,11 +933,19 @@ where C::Target: chain::Filter, let persist_res = self.persister.persist_new_channel(funding_outpoint, &monitor, update_id); 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."; @@ -752,25 +954,31 @@ 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, pending_monitor_updates: Mutex::new(pending_monitor_updates), - last_chain_persist_height: AtomicUsize::new(self.highest_chain_height.load(Ordering::Acquire)), + last_chain_persist_height: AtomicUsize::new( + self.highest_chain_height.load(Ordering::Acquire), + ), }); Ok(persist_res) } - fn update_channel(&self, funding_txo: OutPoint, update: &ChannelMonitorUpdate) -> ChannelMonitorUpdateStatus { + fn update_channel( + &self, funding_txo: OutPoint, 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`. - let channel_id = update.channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(funding_txo)); + let channel_id = + update.channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(funding_txo)); // Update the monitor that watches the channel referred to by the given outpoint. let monitors = self.monitors.read().unwrap(); match monitors.get(&funding_txo) { None => { - let logger = WithContext::from(&self.logger, update.counterparty_node_id, Some(channel_id)); + let logger = + WithContext::from(&self.logger, update.counterparty_node_id, Some(channel_id)); log_error!(logger, "Failed to update channel monitor: no such monitor registered"); // We should never ever trigger this from within ChannelManager. Technically a @@ -784,11 +992,21 @@ where C::Target: chain::Filter, Some(monitor_state) => { let monitor = &monitor_state.monitor; let logger = WithChannelMonitor::from(&self.logger, &monitor); - log_trace!(logger, "Updating ChannelMonitor for channel {}", log_funding_info!(monitor)); - let update_res = monitor.update_monitor(update, &self.broadcaster, &self.fee_estimator, &self.logger); + log_trace!( + logger, + "Updating ChannelMonitor for channel {}", + log_funding_info!(monitor) + ); + let update_res = monitor.update_monitor( + update, + &self.broadcaster, + &self.fee_estimator, + &self.logger, + ); let update_id = MonitorUpdateId::from_monitor_update(update); - let mut pending_monitor_updates = monitor_state.pending_monitor_updates.lock().unwrap(); + let mut pending_monitor_updates = + monitor_state.pending_monitor_updates.lock().unwrap(); let persist_res = if update_res.is_err() { // Even if updating the monitor returns an error, the monitor's state will // still be changed. Therefore, we should persist the updated monitor despite the error. @@ -798,15 +1016,28 @@ where C::Target: chain::Filter, 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(funding_txo, None, monitor, update_id) } else { - self.persister.update_persisted_channel(funding_txo, Some(update), monitor, update_id) + self.persister.update_persisted_channel( + funding_txo, + Some(update), + monitor, + update_id, + ) }; match persist_res { ChannelMonitorUpdateStatus::InProgress => { pending_monitor_updates.push(update_id); - log_debug!(logger, "Persistence of ChannelMonitorUpdate for channel {} in progress", log_funding_info!(monitor)); + log_debug!( + logger, + "Persistence of ChannelMonitorUpdate for channel {} in progress", + log_funding_info!(monitor) + ); }, ChannelMonitorUpdateStatus::Completed => { - log_debug!(logger, "Persistence of ChannelMonitorUpdate for channel {} completed", log_funding_info!(monitor)); + log_debug!( + logger, + "Persistence of ChannelMonitorUpdate for channel {} completed", + log_funding_info!(monitor) + ); }, ChannelMonitorUpdateStatus::UnrecoverableError => { // Take the monitors lock for writing so that we poison it and any future @@ -824,27 +1055,50 @@ where C::Target: chain::Filter, } else { persist_res } - } + }, } } - fn release_pending_monitor_events(&self) -> Vec<(OutPoint, ChannelId, Vec, Option)> { + fn release_pending_monitor_events( + &self, + ) -> Vec<(OutPoint, ChannelId, Vec, Option)> { let mut pending_monitor_events = self.pending_monitor_events.lock().unwrap().split_off(0); for monitor_state in self.monitors.read().unwrap().values() { let logger = WithChannelMonitor::from(&self.logger, &monitor_state.monitor); - let is_pending_monitor_update = monitor_state.has_pending_chainsync_updates(&monitor_state.pending_monitor_updates.lock().unwrap()); - if !is_pending_monitor_update || monitor_state.last_chain_persist_height.load(Ordering::Acquire) + LATENCY_GRACE_PERIOD_BLOCKS as usize <= self.highest_chain_height.load(Ordering::Acquire) { + let is_pending_monitor_update = monitor_state.has_pending_chainsync_updates( + &monitor_state.pending_monitor_updates.lock().unwrap(), + ); + if !is_pending_monitor_update + || monitor_state.last_chain_persist_height.load(Ordering::Acquire) + + LATENCY_GRACE_PERIOD_BLOCKS as usize + <= self.highest_chain_height.load(Ordering::Acquire) + { if is_pending_monitor_update { - log_error!(logger, "A ChannelMonitor sync took longer than {} blocks to complete.", LATENCY_GRACE_PERIOD_BLOCKS); - log_error!(logger, " To avoid funds-loss, we are allowing monitor updates to be released."); - log_error!(logger, " This may cause duplicate payment events to be generated."); + log_error!( + logger, + "A ChannelMonitor sync took longer than {} blocks to complete.", + LATENCY_GRACE_PERIOD_BLOCKS + ); + log_error!( + logger, + " To avoid funds-loss, we are allowing monitor updates to be released." + ); + log_error!( + logger, + " This may cause duplicate payment events to be generated." + ); } let monitor_events = monitor_state.monitor.get_and_clear_pending_monitor_events(); if monitor_events.len() > 0 { let monitor_outpoint = monitor_state.monitor.get_funding_txo().0; 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_outpoint, monitor_channel_id, monitor_events, counterparty_node_id)); + pending_monitor_events.push(( + monitor_outpoint, + monitor_channel_id, + monitor_events, + counterparty_node_id, + )); } } } @@ -852,12 +1106,20 @@ where C::Target: chain::Filter, } } -impl events::EventsProvider for ChainMonitor - where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +impl< + ChannelSigner: WriteableEcdsaChannelSigner, + C: Deref, + T: Deref, + F: Deref, + L: Deref, + P: Deref, + > 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. /// @@ -872,7 +1134,10 @@ 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() { monitor_state.monitor.process_pending_events(&handler); } @@ -881,16 +1146,19 @@ 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); @@ -288,14 +307,16 @@ impl_writeable_tlv_based!(HolderSignedTx, { impl HolderSignedTx { fn non_dust_htlcs(&self) -> Vec { - self.htlc_outputs.iter().filter_map(|(htlc, _, _)| { - if let Some(_) = htlc.transaction_output_index { - Some(htlc.clone()) - } else { - None - } - }) - .collect() + self.htlc_outputs + .iter() + .filter_map(|(htlc, _, _)| { + if let Some(_) = htlc.transaction_output_index { + Some(htlc.clone()) + } else { + None + } + }) + .collect() } } @@ -325,7 +346,7 @@ impl Readable for CounterpartyCommitmentParameters { // Versions prior to 0.0.100 had some per-HTLC state stored here, which is no longer // used. Read it for compatibility. let per_htlc_len: u64 = Readable::read(r)?; - for _ in 0..per_htlc_len { + for _ in 0..per_htlc_len { let _txid: Txid = Readable::read(r)?; let htlcs_count: u64 = Readable::read(r)?; for _ in 0..htlcs_count { @@ -342,7 +363,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, } @@ -369,14 +392,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); @@ -416,9 +440,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 { @@ -481,7 +503,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), + })) } } @@ -549,8 +577,12 @@ pub(crate) enum ChannelMonitorUpdateStep { impl ChannelMonitorUpdateStep { fn variant_name(&self) -> &'static str { match self { - ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } => "LatestHolderCommitmentTXInfo", - ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } => "LatestCounterpartyCommitmentTXInfo", + ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } => { + "LatestHolderCommitmentTXInfo" + }, + ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } => { + "LatestCounterpartyCommitmentTXInfo" + }, ChannelMonitorUpdateStep::PaymentPreimage { .. } => "PaymentPreimage", ChannelMonitorUpdateStep::CommitmentSecret { .. } => "CommitmentSecret", ChannelMonitorUpdateStep::ChannelForceClosed { .. } => "ChannelForceClosed", @@ -683,14 +715,12 @@ 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 { .. }| - Balance::MaybePreimageClaimableHTLC { .. } - => 0, + Balance::ClaimableOnChannelClose { amount_satoshis, .. } + | Balance::ClaimableAwaitingConfirmations { amount_satoshis, .. } + | Balance::ContentiousClaimable { amount_satoshis, .. } + | Balance::CounterpartyRevokedOutputClaimable { amount_satoshis, .. } => *amount_satoshis, + Balance::MaybeTimeoutClaimableHTLC { .. } + | Balance::MaybePreimageClaimableHTLC { .. } => 0, } } } @@ -714,7 +744,8 @@ struct IrrevocablyResolvedHTLC { // using `u32::max_value()` as a sentinal to indicate the HTLC was dust. impl Writeable for IrrevocablyResolvedHTLC { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let mapped_commitment_tx_output_idx = self.commitment_tx_output_idx.unwrap_or(u32::max_value()); + let mapped_commitment_tx_output_idx = + self.commitment_tx_output_idx.unwrap_or(u32::max_value()); write_tlv_fields!(writer, { (0, mapped_commitment_tx_output_idx, required), (1, self.resolving_txid, option), @@ -738,7 +769,11 @@ impl Readable for IrrevocablyResolvedHTLC { (3, resolving_tx, option), }); Ok(Self { - commitment_tx_output_idx: if mapped_commitment_tx_output_idx == u32::max_value() { None } else { Some(mapped_commitment_tx_output_idx) }, + commitment_tx_output_idx: if mapped_commitment_tx_output_idx == u32::max_value() { + None + } else { + Some(mapped_commitment_tx_output_idx) + }, resolving_txid, payment_preimage, resolving_tx, @@ -764,7 +799,10 @@ pub struct ChannelMonitor { pub(super) 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) @@ -800,7 +838,8 @@ pub(crate) struct ChannelMonitorImpl { /// The set of outpoints in each counterparty commitment transaction. We always need at least /// the payment hash from `HTLCOutputInCommitment` to claim even a revoked commitment /// transaction broadcast as we need to be able to construct the witness script in all cases. - counterparty_claimable_outpoints: HashMap>)>>, + counterparty_claimable_outpoints: + HashMap>)>>, /// We cannot identify HTLC-Success or HTLC-Timeout transactions by themselves on the chain. /// Nor can we figure out their commitment numbers without the commitment transaction they are /// spending. Thus, in order to claim them via revocation key, we track all the counterparty @@ -923,14 +962,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) } } @@ -955,7 +1005,9 @@ impl Writeable for ChannelMonitorImpl Writeable for ChannelMonitorImpl Writeable for ChannelMonitorImpl Writeable for ChannelMonitorImpl Writeable for ChannelMonitorImpl true, - MonitorEvent::HolderForceClosed(_) => 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, + _ => false, + }) + .count() as u64) + .to_be_bytes(), + )?; for event in self.pending_monitor_events.iter() { match event { MonitorEvent::HTLCEvent(upd) => { @@ -1080,7 +1145,8 @@ impl Writeable for ChannelMonitorImpl where L::Target: Logger { +pub(crate) struct WithChannelMonitor<'a, L: Deref> +where + L::Target: Logger, +{ logger: &'a L, peer_id: Option, channel_id: 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; @@ -1166,17 +1240,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) -> Self { +impl<'a, L: Deref> WithChannelMonitor<'a, L> +where + L::Target: Logger, +{ + pub(crate) fn from( + logger: &'a L, monitor: &ChannelMonitor, + ) -> Self { Self::from_impl(logger, &*monitor.inner.lock().unwrap()) } - pub(crate) fn from_impl(logger: &'a L, monitor_impl: &ChannelMonitorImpl) -> Self { + pub(crate) fn from_impl( + logger: &'a L, monitor_impl: &ChannelMonitorImpl, + ) -> Self { let peer_id = monitor_impl.counterparty_node_id; let channel_id = Some(monitor_impl.channel_id()); - WithChannelMonitor { - logger, peer_id, channel_id, - } + WithChannelMonitor { logger, peer_id, channel_id } } } @@ -1188,24 +1267,31 @@ impl ChannelMonitor { ChannelMonitor { inner: Mutex::new(imp) } } - pub(crate) fn new(secp_ctx: Secp256k1, keys: Signer, shutdown_script: Option, - on_counterparty_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, ScriptBuf), - channel_parameters: &ChannelTransactionParameters, - funding_redeemscript: ScriptBuf, channel_value_satoshis: u64, - commitment_transaction_number_obscure_factor: u64, - initial_holder_commitment_tx: HolderCommitmentTransaction, - best_block: BestBlock, counterparty_node_id: PublicKey, channel_id: ChannelId, + pub(crate) fn new( + secp_ctx: Secp256k1, keys: Signer, shutdown_script: Option, + on_counterparty_tx_csv: u16, destination_script: &Script, + funding_info: (OutPoint, ScriptBuf), channel_parameters: &ChannelTransactionParameters, + funding_redeemscript: ScriptBuf, channel_value_satoshis: u64, + commitment_transaction_number_obscure_factor: u64, + 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 counterparty_payment_script = chan_utils::get_counterparty_payment_script( - &channel_parameters.channel_type_features, &keys.pubkeys().payment_point + &channel_parameters.channel_type_features, + &keys.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 = keys.pubkeys().revocation_basepoint; @@ -1231,12 +1317,20 @@ impl ChannelMonitor { }; let onchain_tx_handler = OnchainTxHandler::new( - channel_value_satoshis, channel_keys_id, destination_script.into(), keys, - channel_parameters.clone(), initial_holder_commitment_tx, secp_ctx + channel_value_satoshis, + channel_keys_id, + destination_script.into(), + keys, + channel_parameters.clone(), + initial_holder_commitment_tx, + secp_ctx, ); let mut outputs_to_watch = HashMap::new(); - outputs_to_watch.insert(funding_info.0.txid, vec![(funding_info.0.index as u32, funding_info.1.clone())]); + outputs_to_watch.insert( + funding_info.0.txid, + vec![(funding_info.0.index as u32, funding_info.1.clone())], + ); Self::from_impl(ChannelMonitorImpl { latest_update_id: 0, @@ -1312,14 +1406,21 @@ impl ChannelMonitor { &self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, commitment_number: u64, their_cur_per_commitment_point: PublicKey, feerate_per_kw: u32, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, logger: &L, - ) - where L::Target: Logger + ) where + L::Target: Logger, { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner); - inner.provide_initial_counterparty_commitment_tx(txid, - htlc_outputs, commitment_number, their_cur_per_commitment_point, feerate_per_kw, - to_broadcaster_value_sat, to_countersignatory_value_sat, &logger); + inner.provide_initial_counterparty_commitment_tx( + txid, + htlc_outputs, + commitment_number, + their_cur_per_commitment_point, + feerate_per_kw, + to_broadcaster_value_sat, + to_countersignatory_value_sat, + &logger, + ); } /// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction. @@ -1328,17 +1429,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); 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)] @@ -1346,18 +1450,23 @@ impl ChannelMonitor { &self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, ) -> Result<(), ()> { - self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs, &Vec::new(), Vec::new()).map_err(|_| ()) + self.inner + .lock() + .unwrap() + .provide_latest_holder_commitment_tx( + holder_commitment_tx, + htlc_outputs, + &Vec::new(), + Vec::new(), + ) + .map_err(|_| ()) } /// This is used to provide payment preimage(s) out-of-band during startup without updating the /// off-chain state with a new commitment transaction. pub(crate) fn provide_payment_preimage( - &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, @@ -1366,7 +1475,12 @@ impl ChannelMonitor { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner); inner.provide_payment_preimage( - payment_hash, payment_preimage, broadcaster, fee_estimator, &logger) + payment_hash, + payment_preimage, + broadcaster, + fee_estimator, + &logger, + ) } /// Updates a ChannelMonitor on the basis of some new information provided by the Channel @@ -1374,11 +1488,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, @@ -1409,16 +1519,22 @@ 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 /// calling `chain::Filter::register_output` and `chain::Filter::register_tx` until all outputs /// have been registered. - pub fn load_outputs_to_watch(&self, filter: &F, logger: &L) - where - F::Target: chain::Filter, L::Target: Logger, + pub fn load_outputs_to_watch(&self, filter: &F, logger: &L) + where + F::Target: chain::Filter, + L::Target: Logger, { let lock = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*lock); @@ -1428,7 +1544,11 @@ impl ChannelMonitor { for (index, script_pubkey) in outputs.iter() { assert!(*index <= u16::max_value() 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, @@ -1457,7 +1577,10 @@ impl ChannelMonitor { /// /// [`SpendableOutputs`]: crate::events::Event::SpendableOutputs /// [`BumpTransaction`]: crate::events::Event::BumpTransaction - pub fn process_pending_events(&self, handler: &H) where H::Target: EventHandler { + pub fn process_pending_events(&self, handler: &H) + where + H::Target: EventHandler, + { let mut ev; process_events_body!(Some(self), ev, handler.handle_event(ev)); } @@ -1465,8 +1588,11 @@ impl ChannelMonitor { /// Processes any events asynchronously. /// /// See [`Self::process_pending_events`] for more information. - pub async fn process_pending_events_async 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!(Some(self), ev, { handler(ev).await }); @@ -1517,7 +1643,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) } @@ -1538,8 +1666,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 { @@ -1577,7 +1712,9 @@ impl ChannelMonitor { /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager pub fn 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); inner.get_latest_holder_commitment_txn(&logger) @@ -1588,7 +1725,9 @@ impl ChannelMonitor { /// revoked commitment transaction. #[cfg(any(test, 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); inner.unsafe_get_latest_holder_commitment_txn(&logger) @@ -1606,13 +1745,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, @@ -1621,19 +1755,13 @@ impl ChannelMonitor { { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner); - 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, @@ -1641,8 +1769,7 @@ impl ChannelMonitor { { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner); - 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 @@ -1653,13 +1780,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, @@ -1670,7 +1792,13 @@ impl ChannelMonitor { let mut inner = self.inner.lock().unwrap(); let logger = WithChannelMonitor::from_impl(logger, &*inner); 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. @@ -1680,11 +1808,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, @@ -1693,9 +1817,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); - 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 @@ -1706,12 +1828,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, @@ -1721,15 +1838,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); - 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()) @@ -1752,8 +1868,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, @@ -1763,7 +1878,10 @@ impl ChannelMonitor { let logger = WithChannelMonitor::from_impl(logger, &*inner); let current_height = inner.best_block.height; inner.onchain_tx_handler.rebroadcast_pending_claims( - current_height, &broadcaster, &fee_estimator, &logger, + current_height, + &broadcaster, + &fee_estimator, + &logger, ); } @@ -1785,15 +1903,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 }); @@ -1814,11 +1936,15 @@ 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, holder_commitment: bool, - counterparty_revoked_commitment: bool, confirmed_txid: Option) - -> Option { - let htlc_commitment_tx_output_idx = - if let Some(v) = htlc.transaction_output_index { v } else { return None; }; + fn get_htlc_balance( + &self, htlc: &HTLCOutputInCommitment, holder_commitment: bool, + counterparty_revoked_commitment: bool, confirmed_txid: Option, + ) -> Option { + let htlc_commitment_tx_output_idx = if let Some(v) = htlc.transaction_output_index { + v + } else { + return None; + }; let mut htlc_spend_txid_opt = None; let mut htlc_spend_tx_opt = None; @@ -1827,8 +1953,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()); @@ -1837,8 +1964,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()); @@ -1847,10 +1975,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 @@ -1858,46 +1989,62 @@ 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() - .find(|v| if v.commitment_tx_output_idx == Some(htlc_commitment_tx_output_idx) { + let htlc_resolved = self.htlcs_resolved_on_chain.iter().find(|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.is_some() 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.onchain_tx_handler.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.is_some() 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 + .onchain_tx_handler + .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); @@ -1913,30 +2060,47 @@ 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().find_map(|event| { - if let OnchainEvent::MaturingOutput { - descriptor: SpendableOutputDescriptor::StaticOutput { .. } - } = &event.event { - if event.transaction.as_ref().map(|tx| tx.input.iter().any(|inp| { - if let Some(htlc_spend_txid) = htlc_spend_txid_opt { - tx.txid() == *htlc_spend_txid || inp.previous_output.txid == *htlc_spend_txid + let htlc_output_claim_pending = + self.onchain_events_awaiting_threshold_conf.iter().find_map(|event| { + if let OnchainEvent::MaturingOutput { + descriptor: SpendableOutputDescriptor::StaticOutput { .. }, + } = &event.event + { + if event + .transaction + .as_ref() + .map(|tx| { + tx.input.iter().any(|inp| { + if let Some(htlc_spend_txid) = htlc_spend_txid_opt { + tx.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) + { + Some(()) } else { - Some(inp.previous_output.txid) == confirmed_txid && - inp.previous_output.vout == htlc_commitment_tx_output_idx + None } - })).unwrap_or(false) { - Some(()) - } else { None } - } else { None } - }); + } else { + None + } + }); if htlc_output_claim_pending.is_some() { // 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 { @@ -2012,14 +2176,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!"); @@ -2031,13 +2200,17 @@ impl ChannelMonitor { ($holder_commitment: expr, $counterparty_revoked_commitment: expr, $htlc_iter: expr) => { for htlc in $htlc_iter { if htlc.transaction_output_index.is_some() { - - if let Some(bal) = us.get_htlc_balance(htlc, $holder_commitment, $counterparty_revoked_commitment, confirmed_txid) { + if let Some(bal) = us.get_htlc_balance( + htlc, + $holder_commitment, + $counterparty_revoked_commitment, + confirmed_txid, + ) { res.push(bal); } } } - } + }; } if let Some(txid) = confirmed_txid { @@ -2045,13 +2218,18 @@ impl ChannelMonitor { if let Some(counterparty_tx_htlcs) = us.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, confirmation_height: conf_thresh, @@ -2062,7 +2240,9 @@ impl ChannelMonitor { // confirmation with the same height or have never met our dust amount. } } - if Some(txid) == us.current_counterparty_commitment_txid || Some(txid) == us.prev_counterparty_commitment_txid { + if Some(txid) == us.current_counterparty_commitment_txid + || Some(txid) == us.prev_counterparty_commitment_txid + { walk_htlcs!(false, false, counterparty_tx_htlcs.iter().map(|(a, _)| a)); } else { walk_htlcs!(false, true, counterparty_tx_htlcs.iter().map(|(a, _)| a)); @@ -2073,16 +2253,26 @@ 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, confirmation_height: event.confirmation_threshold(), }); - 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; } } @@ -2090,9 +2280,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, @@ -2105,7 +2297,11 @@ impl ChannelMonitor { } found_commitment_tx = true; } else if txid == us.current_holder_commitment_tx.txid { - walk_htlcs!(true, false, us.current_holder_commitment_tx.htlc_outputs.iter().map(|(a, _, _)| a)); + walk_htlcs!( + true, + false, + us.current_holder_commitment_tx.htlc_outputs.iter().map(|(a, _, _)| a) + ); if let Some(conf_thresh) = pending_commitment_tx_conf_thresh { res.push(Balance::ClaimableAwaitingConfirmations { amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat, @@ -2115,7 +2311,11 @@ impl ChannelMonitor { found_commitment_tx = true; } else if let Some(prev_commitment) = &us.prev_holder_signed_commitment_tx { if txid == prev_commitment.txid { - walk_htlcs!(true, false, prev_commitment.htlc_outputs.iter().map(|(a, _, _)| a)); + walk_htlcs!( + true, + false, + prev_commitment.htlc_outputs.iter().map(|(a, _, _)| a) + ); if let Some(conf_thresh) = pending_commitment_tx_conf_thresh { res.push(Balance::ClaimableAwaitingConfirmations { amount_satoshis: prev_commitment.to_self_value_sat, @@ -2139,7 +2339,9 @@ impl ChannelMonitor { } else { let mut claimable_inbound_htlc_value_sat = 0; for (htlc, _, _) in us.current_holder_commitment_tx.htlc_outputs.iter() { - if htlc.transaction_output_index.is_none() { continue; } + if htlc.transaction_output_index.is_none() { + continue; + } if htlc.offered { res.push(Balance::MaybeTimeoutClaimableHTLC { amount_satoshis: htlc.amount_msat / 1000, @@ -2159,7 +2361,8 @@ impl ChannelMonitor { } } res.push(Balance::ClaimableOnChannelClose { - amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat + claimable_inbound_htlc_value_sat, + amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat + + claimable_inbound_htlc_value_sat, }); } @@ -2173,7 +2376,9 @@ 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 = HashMap::new(); // Just examine the available counterparty commitment transactions. See docs on // `fail_unbroadcast_htlcs`, below, for justification. @@ -2183,12 +2388,19 @@ impl ChannelMonitor { if let Some(ref latest_outpoints) = us.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.current_counterparty_commitment_txid { walk_counterparty_commitment!(txid); @@ -2206,7 +2418,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, @@ -2215,7 +2429,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 + } }) }); @@ -2230,7 +2446,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. @@ -2240,46 +2460,86 @@ 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 counterparty_resolved_preimage_opt = - us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).cloned(); + 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 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), + ); } } } - } + }; } let txid = confirmed_txid.unwrap(); - if Some(txid) == us.current_counterparty_commitment_txid || Some(txid) == us.prev_counterparty_commitment_txid { - walk_htlcs!(false, us.counterparty_claimable_outpoints.get(&txid).unwrap().iter().filter_map(|(a, b)| { - if let &Some(ref source) = b { - Some((a, &**source)) - } else { None } - })); + if Some(txid) == us.current_counterparty_commitment_txid + || Some(txid) == us.prev_counterparty_commitment_txid + { + walk_htlcs!( + false, + us.counterparty_claimable_outpoints.get(&txid).unwrap().iter().filter_map( + |(a, b)| { + if let &Some(ref source) = b { + Some((a, &**source)) + } else { + None + } + } + ) + ); } else if txid == us.current_holder_commitment_tx.txid { - walk_htlcs!(true, us.current_holder_commitment_tx.htlc_outputs.iter().filter_map(|(a, _, c)| { - if let Some(source) = c { Some((a, source)) } else { None } - })); + walk_htlcs!( + true, + us.current_holder_commitment_tx.htlc_outputs.iter().filter_map(|(a, _, c)| { + if let Some(source) = c { + Some((a, source)) + } else { + None + } + }) + ); } else if let Some(prev_commitment) = &us.prev_holder_signed_commitment_tx { if txid == prev_commitment.txid { - walk_htlcs!(true, prev_commitment.htlc_outputs.iter().filter_map(|(a, _, c)| { - if let Some(source) = c { Some((a, source)) } else { None } - })); + walk_htlcs!( + true, + prev_commitment.htlc_outputs.iter().filter_map(|(a, _, c)| { + if let Some(source) = c { + Some((a, source)) + } else { + None + } + }) + ); } } @@ -2399,7 +2659,14 @@ pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec { #[cfg(test)] 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 { @@ -2415,22 +2682,32 @@ impl ChannelMonitorImpl { // events for now-revoked/fulfilled HTLCs. if let Some(txid) = self.prev_counterparty_commitment_txid.take() { if self.current_counterparty_commitment_txid.unwrap() != txid { - let cur_claimables = self.counterparty_claimable_outpoints.get( - &self.current_counterparty_commitment_txid.unwrap()).unwrap(); - for (_, ref source_opt) in self.counterparty_claimable_outpoints.get(&txid).unwrap() { + let cur_claimables = self + .counterparty_claimable_outpoints + .get(&self.current_counterparty_commitment_txid.unwrap()) + .unwrap(); + for (_, ref source_opt) in self.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.counterparty_claimable_outpoints.get_mut(&txid).unwrap() { + for &mut (_, ref mut source_opt) in + self.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" + ); } } @@ -2443,22 +2720,24 @@ impl ChannelMonitorImpl { self.payment_preimages.retain(|&k, _| { for &(ref htlc, _, _) in cur_holder_signed_commitment_tx.htlc_outputs.iter() { if k == htlc.payment_hash { - return true + return true; } } if let Some(prev_holder_commitment_tx) = prev_holder_signed_commitment_tx { for &(ref htlc, _, _) in prev_holder_commitment_tx.htlc_outputs.iter() { 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); } @@ -2470,27 +2749,43 @@ impl ChannelMonitorImpl { } fn provide_initial_counterparty_commitment_tx( - &mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, + &mut self, txid: Txid, + htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, commitment_number: u64, their_per_commitment_point: PublicKey, feerate_per_kw: u32, to_broadcaster_value: u64, to_countersignatory_value: u64, logger: &WithChannelMonitor, - ) where L::Target: Logger { - self.initial_counterparty_commitment_info = Some((their_per_commitment_point.clone(), - feerate_per_kw, to_broadcaster_value, to_countersignatory_value)); + ) where + L::Target: Logger, + { + self.initial_counterparty_commitment_info = Some(( + their_per_commitment_point.clone(), + feerate_per_kw, + to_broadcaster_value, + to_countersignatory_value, + )); - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let rebuilt_commitment_tx = self.initial_counterparty_commitment_tx().unwrap(); debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), txid); } - self.provide_latest_counterparty_commitment_tx(txid, htlc_outputs, commitment_number, - their_per_commitment_point, logger); + self.provide_latest_counterparty_commitment_tx( + txid, + htlc_outputs, + commitment_number, + their_per_commitment_point, + logger, + ); } 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 @@ -2508,20 +2803,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)); + }, } let mut htlcs = Vec::with_capacity(htlc_outputs.len()); for htlc in htlc_outputs { @@ -2536,17 +2839,36 @@ impl ChannelMonitorImpl { /// is important that any clones of this channel monitor (including remote clones) by kept /// up-to-date as our holder commitment transaction is updated. /// Panics if set_on_holder_tx_csv has never been called. - fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, mut htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, claimed_htlcs: &[(SentHTLCId, PaymentPreimage)], nondust_htlc_sources: Vec) -> Result<(), &'static str> { + fn provide_latest_holder_commitment_tx( + &mut self, holder_commitment_tx: HolderCommitmentTransaction, + mut htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, + claimed_htlcs: &[(SentHTLCId, PaymentPreimage)], nondust_htlc_sources: Vec, + ) -> Result<(), &'static str> { if htlc_outputs.iter().any(|(_, s, _)| s.is_some()) { // 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().htlcs().len()); - for (a, b) in htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).map(|(h, _, _)| h).zip(holder_commitment_tx.trust().htlcs().iter()) { + debug_assert_eq!( + htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).count(), + holder_commitment_tx.trust().htlcs().len() + ); + for (a, b) in htlc_outputs + .iter() + .filter(|(_, s, _)| s.is_some()) + .map(|(h, _, _)| h) + .zip(holder_commitment_tx.trust().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); } debug_assert!(nondust_htlc_sources.is_empty()); @@ -2554,25 +2876,37 @@ impl ChannelMonitorImpl { // If we don't have any non-dust HTLCs in htlc_outputs, assume they were all passed via // `nondust_htlc_sources`, building up the final htlc_outputs by combining // `nondust_htlc_sources` and the `holder_commitment_tx` - #[cfg(debug_assertions)] { + #[cfg(debug_assertions)] + { let mut prev = -1; for htlc in holder_commitment_tx.trust().htlcs().iter() { assert!(htlc.transaction_output_index.unwrap() as i32 > prev); prev = htlc.transaction_output_index.unwrap() as i32; } } - 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().htlcs().len(), holder_commitment_tx.counterparty_htlc_sigs.len()); + debug_assert_eq!( + holder_commitment_tx.trust().htlcs().len(), + holder_commitment_tx.counterparty_htlc_sigs.len() + ); let mut sources_iter = nondust_htlc_sources.into_iter(); - for (htlc, counterparty_sig) in holder_commitment_tx.trust().htlcs().iter() + for (htlc, counterparty_sig) in holder_commitment_tx + .trust() + .htlcs() + .iter() .zip(holder_commitment_tx.counterparty_htlc_sigs.iter()) { if htlc.offered { - let source = sources_iter.next().expect("Non-dust HTLC sources didn't match commitment tx"); - #[cfg(debug_assertions)] { + let source = sources_iter + .next() + .expect("Non-dust HTLC sources didn't match commitment tx"); + #[cfg(debug_assertions)] + { assert!(source.possibly_matches_output(htlc)); } htlc_outputs.push((htlc.clone(), Some(counterparty_sig.clone()), Some(source))); @@ -2602,19 +2936,26 @@ impl ChannelMonitorImpl { mem::swap(&mut new_holder_commitment_tx, &mut self.current_holder_commitment_tx); self.prev_holder_signed_commitment_tx = Some(new_holder_commitment_tx); for (claimed_htlc_id, claimed_preimage) in claimed_htlcs { - #[cfg(debug_assertions)] { - let cur_counterparty_htlcs = self.counterparty_claimable_outpoints.get( - &self.current_counterparty_commitment_txid.unwrap()).unwrap(); + #[cfg(debug_assertions)] + { + let cur_counterparty_htlcs = self + .counterparty_claimable_outpoints + .get(&self.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); } if self.holder_tx_signed { - return Err("Latest holder commitment signed has already been signed, update is rejected"); + return Err( + "Latest holder commitment signed has already been signed, update is rejected", + ); } Ok(()) } @@ -2623,10 +2964,11 @@ impl ChannelMonitorImpl { /// commitment_tx_infos which contain the payment hash have been revoked. fn provide_payment_preimage( &mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, 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.insert(payment_hash.clone(), payment_preimage.clone()); @@ -2646,13 +2988,23 @@ impl ChannelMonitorImpl { // First check if a counterparty commitment transaction has been broadcasted: macro_rules! claim_htlcs { ($commitment_number: expr, $txid: expr) => { - let (htlc_claim_reqs, _) = self.get_counterparty_output_claim_info($commitment_number, $txid, None); - self.onchain_tx_handler.update_claims_view_from_requests(htlc_claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger); - } + let (htlc_claim_reqs, _) = + self.get_counterparty_output_claim_info($commitment_number, $txid, None); + self.onchain_tx_handler.update_claims_view_from_requests( + htlc_claim_reqs, + self.best_block.height(), + self.best_block.height(), + broadcaster, + fee_estimator, + logger, + ); + }; } if let Some(txid) = self.current_counterparty_commitment_txid { if txid == confirmed_spend_txid { - if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { + if let Some(commitment_number) = + self.counterparty_commitment_txn_on_chain.get(&txid) + { claim_htlcs!(*commitment_number, txid); } else { debug_assert!(false); @@ -2663,7 +3015,9 @@ impl ChannelMonitorImpl { } if let Some(txid) = self.prev_counterparty_commitment_txid { if txid == confirmed_spend_txid { - if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { + if let Some(commitment_number) = + self.counterparty_commitment_txn_on_chain.get(&txid) + { claim_htlcs!(*commitment_number, txid); } else { debug_assert!(false); @@ -2679,7 +3033,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_tx = if self.current_holder_commitment_tx.txid == confirmed_spend_txid { + let holder_commitment_tx = if self.current_holder_commitment_tx.txid + == confirmed_spend_txid + { Some(&self.current_holder_commitment_tx) } else if let Some(prev_holder_commitment_tx) = &self.prev_holder_signed_commitment_tx { if prev_holder_commitment_tx.txid == confirmed_spend_txid { @@ -2694,22 +3050,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()); - self.onchain_tx_handler.update_claims_view_from_requests(claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger); + let (claim_reqs, _) = self + .get_broadcasted_holder_claims(&holder_commitment_tx, self.best_block.height()); + self.onchain_tx_handler.update_claims_view_from_requests( + claim_reqs, + self.best_block.height(), + self.best_block.height(), + broadcaster, + fee_estimator, + logger, + ); } } } - fn generate_claimable_outpoints_and_watch_outputs(&mut self) -> (Vec, Vec) { + fn generate_claimable_outpoints_and_watch_outputs( + &mut self, + ) -> (Vec, Vec) { let funding_outp = HolderFundingOutput::build( self.funding_redeemscript.clone(), self.channel_value_satoshis, - self.onchain_tx_handler.channel_type_features().clone() + self.onchain_tx_handler.channel_type_features().clone(), ); let commitment_package = PackageTemplate::build_package( - self.funding_info.0.txid.clone(), self.funding_info.0.index as u32, + self.funding_info.0.txid.clone(), + self.funding_info.0.index as u32, PackageSolvingData::HolderFundingOutput(funding_outp), - self.best_block.height(), self.best_block.height() + self.best_block.height(), + self.best_block.height(), ); let mut claimable_outpoints = vec![commitment_package]; self.pending_monitor_events.push(MonitorEvent::HolderForceClosed(self.funding_info.0)); @@ -2726,11 +3094,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.current_holder_commitment_tx, self.best_block.height() + &self.current_holder_commitment_tx, + self.best_block.height(), ); - let unsigned_commitment_tx = self.onchain_tx_handler.get_unsigned_holder_commitment_tx(); + let unsigned_commitment_tx = + self.onchain_tx_handler.get_unsigned_holder_commitment_tx(); let new_outputs = self.get_broadcasted_holder_watch_outputs( - &self.current_holder_commitment_tx, &unsigned_commitment_tx + &self.current_holder_commitment_tx, + &unsigned_commitment_tx, ); if !new_outputs.is_empty() { watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs)); @@ -2741,33 +3112,49 @@ 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(); self.onchain_tx_handler.update_claims_view_from_requests( - claimable_outpoints, self.best_block.height(), self.best_block.height(), broadcaster, - fee_estimator, logger + claimable_outpoints, + self.best_block.height(), + self.best_block.height(), + broadcaster, + 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 == CLOSED_CHANNEL_UPDATE_ID && updates.update_id == CLOSED_CHANNEL_UPDATE_ID { - log_info!(logger, "Applying post-force-closed update to monitor {} with {} change(s).", - log_funding_info!(self), updates.updates.len()); + if self.latest_update_id == CLOSED_CHANNEL_UPDATE_ID + && updates.update_id == CLOSED_CHANNEL_UPDATE_ID + { + log_info!( + logger, + "Applying post-force-closed update to monitor {} with {} change(s).", + log_funding_info!(self), + updates.updates.len() + ); } else if updates.update_id == CLOSED_CHANNEL_UPDATE_ID { - log_info!(logger, "Applying force close update to monitor {} with {} change(s).", - log_funding_info!(self), updates.updates.len()); + log_info!( + logger, + "Applying 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()); @@ -2795,10 +3182,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_eq!(self.latest_update_id, CLOSED_CHANNEL_UPDATE_ID), + ChannelMonitorUpdateStep::PaymentPreimage { .. } => { + debug_assert_eq!(self.latest_update_id, CLOSED_CHANNEL_UPDATE_ID) + }, _ => { - 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"); }, } @@ -2809,52 +3201,107 @@ 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!(); } - if let Err(e) = self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs, nondust_htlc_sources.clone()) { - log_error!(logger, "Providing latest holder commitment transaction failed/was refused:"); + 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!(); + } + if let Err(e) = self.provide_latest_holder_commitment_tx( + commitment_tx.clone(), + htlc_outputs.clone(), + &claimed_htlcs, + nondust_htlc_sources.clone(), + ) { + log_error!( + logger, + "Providing latest holder commitment transaction failed/was refused:" + ); log_error!(logger, " {}", e); ret = Err(()); } - } - 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::PaymentPreimage { payment_preimage } => { log_trace!(logger, "Updating ChannelMonitor with payment preimage"); - self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()), &payment_preimage, broadcaster, &bounded_fee_estimator, logger) + self.provide_payment_preimage( + &PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()), + &payment_preimage, + 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().find(|event| match event.event { - OnchainEvent::FundingSpendConfirmation { .. } => true, - _ => false, - }).is_some(); + let detected_funding_spend = 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 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::get_latest_holder_commitment_txn and take manual action!"); } else { // If we generated a MonitorEvent::HolderForceClosed, the ChannelManager @@ -2865,20 +3312,29 @@ 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); } // If the updates succeeded and we were in an already closed channel state, then there's no // need to refuse any updates we expect to receive afer seeing a confirmed commitment. - if ret.is_ok() && updates.update_id == CLOSED_CHANNEL_UPDATE_ID && self.latest_update_id == updates.update_id { + if ret.is_ok() + && updates.update_id == CLOSED_CHANNEL_UPDATE_ID + && self.latest_update_id == updates.update_id + { return Ok(()); } @@ -2886,10 +3342,15 @@ impl ChannelMonitorImpl { // Refuse updates after we've detected a spend onchain, but only if we haven't processed a // force closed monitor update yet. - if ret.is_ok() && self.funding_spend_seen && self.latest_update_id != CLOSED_CHANNEL_UPDATE_ID { + if ret.is_ok() + && self.funding_spend_seen + && self.latest_update_id != CLOSED_CHANNEL_UPDATE_ID + { log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent"); Err(()) - } else { ret } + } else { + ret + } } fn get_latest_update_id(&self) -> u64 { @@ -2929,13 +3390,15 @@ 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, anchor_output_idx, + package_target_feerate_sat_per_1000_weight, + commitment_tx, + anchor_output_idx, } => { let commitment_txid = commitment_tx.txid(); debug_assert_eq!(self.current_holder_commitment_tx.txid, commitment_txid); let pending_htlcs = self.current_holder_commitment_tx.non_dust_htlcs(); - let commitment_tx_fee_satoshis = self.channel_value_satoshis - - commitment_tx.output.iter().fold(0u64, |sum, output| sum + output.value); + let commitment_tx_fee_satoshis = self.channel_value_satoshis + - commitment_tx.output.iter().fold(0u64, |sum, output| sum + output.value); ret.push(Event::BumpTransaction(BumpTransactionEvent::ChannelClose { claim_id, package_target_feerate_sat_per_1000_weight, @@ -2945,7 +3408,10 @@ impl ChannelMonitorImpl { channel_derivation_parameters: ChannelDerivationParameters { keys_id: self.channel_keys_id, value_satoshis: self.channel_value_satoshis, - transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(), + transaction_parameters: self + .onchain_tx_handler + .channel_transaction_parameters + .clone(), }, outpoint: BitcoinOutPoint { txid: commitment_txid, @@ -2956,7 +3422,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 mut htlc_descriptors = Vec::with_capacity(htlcs.len()); for htlc in htlcs { @@ -2964,13 +3432,20 @@ impl ChannelMonitorImpl { channel_derivation_parameters: ChannelDerivationParameters { keys_id: self.channel_keys_id, value_satoshis: self.channel_value_satoshis, - transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(), + transaction_parameters: self + .onchain_tx_handler + .channel_transaction_parameters + .clone(), }, commitment_txid: htlc.commitment_txid, per_commitment_number: htlc.per_commitment_number, - per_commitment_point: self.onchain_tx_handler.signer.get_per_commitment_point( - htlc.per_commitment_number, &self.onchain_tx_handler.secp_ctx, - ), + per_commitment_point: self + .onchain_tx_handler + .signer + .get_per_commitment_point( + htlc.per_commitment_number, + &self.onchain_tx_handler.secp_ctx, + ), feerate_per_kw: 0, htlc: htlc.htlc, preimage: htlc.preimage, @@ -2983,90 +3458,146 @@ impl ChannelMonitorImpl { htlc_descriptors, tx_lock_time, })); - } + }, } } ret } fn initial_counterparty_commitment_tx(&mut self) -> Option { - let (their_per_commitment_point, feerate_per_kw, to_broadcaster_value, - to_countersignatory_value) = self.initial_counterparty_commitment_info?; + let ( + their_per_commitment_point, + feerate_per_kw, + to_broadcaster_value, + to_countersignatory_value, + ) = self.initial_counterparty_commitment_info?; let htlc_outputs = vec![]; - let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER, - &their_per_commitment_point, to_broadcaster_value, to_countersignatory_value, - feerate_per_kw, htlc_outputs); + let commitment_tx = self.build_counterparty_commitment_tx( + INITIAL_COMMITMENT_NUMBER, + &their_per_commitment_point, + to_broadcaster_value, + to_countersignatory_value, + feerate_per_kw, + htlc_outputs, + ); Some(commitment_tx) } 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, - mut nondust_htlcs: Vec<(HTLCOutputInCommitment, Option>)> + mut nondust_htlcs: Vec<(HTLCOutputInCommitment, Option>)>, ) -> CommitmentTransaction { - let broadcaster_keys = &self.onchain_tx_handler.channel_transaction_parameters - .counterparty_parameters.as_ref().unwrap().pubkeys; + let broadcaster_keys = &self + .onchain_tx_handler + .channel_transaction_parameters + .counterparty_parameters + .as_ref() + .unwrap() + .pubkeys; let countersignatory_keys = &self.onchain_tx_handler.channel_transaction_parameters.holder_pubkeys; let broadcaster_funding_key = broadcaster_keys.funding_pubkey; let countersignatory_funding_key = countersignatory_keys.funding_pubkey; - let keys = TxCreationKeys::from_channel_static_keys(&their_per_commitment_point, - &broadcaster_keys, &countersignatory_keys, &self.onchain_tx_handler.secp_ctx); + let keys = TxCreationKeys::from_channel_static_keys( + &their_per_commitment_point, + &broadcaster_keys, + &countersignatory_keys, + &self.onchain_tx_handler.secp_ctx, + ); let channel_parameters = &self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable(); - CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, - to_broadcaster_value, to_countersignatory_value, broadcaster_funding_key, - countersignatory_funding_key, keys, feerate_per_kw, &mut nondust_htlcs, - channel_parameters) + CommitmentTransaction::new_with_auxiliary_htlc_data( + commitment_number, + to_broadcaster_value, + to_countersignatory_value, + broadcaster_funding_key, + countersignatory_funding_key, + keys, + feerate_per_kw, + &mut nondust_htlcs, + channel_parameters, + ) } - fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec { - update.updates.iter().filter_map(|update| { - match update { - &ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, - ref htlc_outputs, commitment_number, their_per_commitment_point, + fn counterparty_commitment_txs_from_update( + &self, update: &ChannelMonitorUpdate, + ) -> Vec { + update + .updates + .iter() + .filter_map(|update| 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.clone(), None)) - }).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); + to_countersignatory_value_sat: Some(to_countersignatory_value), + } => { + let nondust_htlcs = htlc_outputs + .iter() + .filter_map(|(htlc, _)| { + htlc.transaction_output_index.map(|_| (htlc.clone(), None)) + }) + .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); Some(commitment_tx) }, _ => None, - } - }).collect() + }) + .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 sig = self.onchain_tx_handler.signer.sign_justice_revoked_output( - &justice_tx, input_idx, value, &per_commitment_key, &self.onchain_tx_handler.secp_ctx)?; - justice_tx.input[input_idx].witness.push_bitcoin_signature(&sig.serialize_der(), EcdsaSighashType::All); + &justice_tx, + input_idx, + value, + &per_commitment_key, + &self.onchain_tx_handler.secp_ctx, + )?; + justice_tx.input[input_idx] + .witness + .push_bitcoin_signature(&sig.serialize_der(), EcdsaSighashType::All); justice_tx.input[input_idx].witness.push(&[1u8]); justice_tx.input[input_idx].witness.push(revokeable_redeemscript.as_bytes()); Ok(justice_tx) @@ -3097,9 +3628,12 @@ impl ChannelMonitorImpl { /// Returns packages to claim the revoked output(s), as well as additional outputs to watch 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, TransactionOutputs, CommitmentTxCounterpartyOutputInfo) - where L::Target: Logger { + fn check_spend_counterparty_transaction( + &mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L, + ) -> (Vec, TransactionOutputs, 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(); @@ -3113,30 +3647,70 @@ impl ChannelMonitorImpl { ( $thing : expr ) => { match $thing { Ok(a) => a, - Err(_) => return (claimable_outpoints, (commitment_txid, watch_outputs), to_counterparty_output_info) + Err(_) => { + return ( + claimable_outpoints, + (commitment_txid, watch_outputs), + 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_v0_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, self.counterparty_commitment_params.counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, per_commitment_key, outp.value, self.counterparty_commitment_params.on_counterparty_tx_csv, self.onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx()); - let justice_package = PackageTemplate::build_package(commitment_txid, idx as u32, PackageSolvingData::RevokedOutput(revk_outp), height + self.counterparty_commitment_params.on_counterparty_tx_csv as u32, height); + let revk_outp = RevokedOutput::build( + per_commitment_point, + self.counterparty_commitment_params.counterparty_delayed_payment_base_key, + self.counterparty_commitment_params.counterparty_htlc_base_key, + per_commitment_key, + outp.value, + self.counterparty_commitment_params.on_counterparty_tx_csv, + self.onchain_tx_handler + .channel_type_features() + .supports_anchors_zero_fee_htlc_tx(), + ); + let justice_package = PackageTemplate::build_package( + commitment_txid, + idx as u32, + PackageSolvingData::RevokedOutput(revk_outp), + height + self.counterparty_commitment_params.on_counterparty_tx_csv as u32, + height, + ); 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, + )); } } @@ -3144,37 +3718,79 @@ impl ChannelMonitorImpl { if let Some(ref per_commitment_data) = per_commitment_option { for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() { 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.amount_msat / 1000 { + if transaction_output_index as usize >= tx.output.len() + || tx.output[transaction_output_index as usize].value + != htlc.amount_msat / 1000 + { // per_commitment_data is corrupt or our commitment signing key leaked! - return (claimable_outpoints, (commitment_txid, watch_outputs), - to_counterparty_output_info); + return ( + claimable_outpoints, + (commitment_txid, watch_outputs), + to_counterparty_output_info, + ); } - let revk_htlc_outp = RevokedHTLCOutput::build(per_commitment_point, self.counterparty_commitment_params.counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, per_commitment_key, htlc.amount_msat / 1000, htlc.clone(), &self.onchain_tx_handler.channel_transaction_parameters.channel_type_features); - let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedHTLCOutput(revk_htlc_outp), htlc.cltv_expiry, height); + let revk_htlc_outp = RevokedHTLCOutput::build( + per_commitment_point, + self.counterparty_commitment_params + .counterparty_delayed_payment_base_key, + self.counterparty_commitment_params.counterparty_htlc_base_key, + per_commitment_key, + htlc.amount_msat / 1000, + htlc.clone(), + &self + .onchain_tx_handler + .channel_transaction_parameters + .channel_type_features, + ); + let justice_package = PackageTemplate::build_package( + commitment_txid, + transaction_output_index, + PackageSolvingData::RevokedHTLCOutput(revk_htlc_outp), + htlc.cltv_expiry, + height, + ); claimable_outpoints.push(justice_package); } } } // 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()); for (idx, outp) in tx.output.iter().enumerate() { watch_outputs.push((idx as u32, outp.clone())); } - 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_data) = per_commitment_option { - fail_unbroadcast_htlcs!(self, "revoked_counterparty", commitment_txid, tx, height, - block_hash, per_commitment_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_data.iter().map(|(htlc, htlc_source)| ( + htlc, + htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()) + )), + logger + ); } else { debug_assert!(false, "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_data) = per_commitment_option { @@ -3190,26 +3806,39 @@ impl ChannelMonitorImpl { } 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_data.iter().map(|(htlc, htlc_source)| - (htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref())) - ), logger); + 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_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)); + let (htlc_claim_reqs, counterparty_output_info) = self + .get_counterparty_output_claim_info(commitment_number, commitment_txid, Some(tx)); to_counterparty_output_info = counterparty_output_info; for req in htlc_claim_reqs { claimable_outpoints.push(req); } - } (claimable_outpoints, (commitment_txid, watch_outputs), 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>) - -> (Vec, CommitmentTxCounterpartyOutputInfo) { + fn get_counterparty_output_claim_info( + &self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>, + ) -> (Vec, CommitmentTxCounterpartyOutputInfo) { let mut claimable_outpoints = Vec::new(); let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None; @@ -3237,13 +3866,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_v0_p2wsh(); + &delayed_key, + ) + .to_v0_p2wsh(); for (idx, outp) in transaction.output.iter().enumerate() { if outp.script_pubkey == revokeable_p2wsh { to_counterparty_output_info = @@ -3255,28 +3894,55 @@ impl ChannelMonitorImpl { for (_, &(ref htlc, _)) in htlc_outputs.iter().enumerate() { 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.amount_msat / 1000 { - // 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.amount_msat / 1000 + { + // 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, - self.counterparty_commitment_params.counterparty_delayed_payment_base_key, + CounterpartyOfferedHTLCOutput::build( + *per_commitment_point, + self.counterparty_commitment_params + .counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, - preimage.unwrap(), htlc.clone(), self.onchain_tx_handler.channel_type_features().clone())) + preimage.unwrap(), + htlc.clone(), + self.onchain_tx_handler.channel_type_features().clone(), + ), + ) } else { PackageSolvingData::CounterpartyReceivedHTLCOutput( - CounterpartyReceivedHTLCOutput::build(*per_commitment_point, - self.counterparty_commitment_params.counterparty_delayed_payment_base_key, + CounterpartyReceivedHTLCOutput::build( + *per_commitment_point, + self.counterparty_commitment_params + .counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, - htlc.clone(), self.onchain_tx_handler.channel_type_features().clone())) + htlc.clone(), + self.onchain_tx_handler.channel_type_features().clone(), + ), + ) }; - let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, counterparty_htlc_outp, htlc.cltv_expiry, 0); + let counterparty_package = PackageTemplate::build_package( + commitment_txid, + transaction_output_index, + counterparty_htlc_outp, + htlc.cltv_expiry, + 0, + ); claimable_outpoints.push(counterparty_package); } } @@ -3287,14 +3953,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.txid(); let mut claimable_outpoints = vec![]; @@ -3310,17 +3985,31 @@ 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, self.counterparty_commitment_params.counterparty_delayed_payment_base_key, - self.counterparty_commitment_params.counterparty_htlc_base_key, per_commitment_key, - tx.output[idx].value, self.counterparty_commitment_params.on_counterparty_tx_csv, - false + per_commitment_point, + self.counterparty_commitment_params.counterparty_delayed_payment_base_key, + self.counterparty_commitment_params.counterparty_htlc_base_key, + per_commitment_key, + tx.output[idx].value, + self.counterparty_commitment_params.on_counterparty_tx_csv, + false, ); let justice_package = PackageTemplate::build_package( - htlc_txid, idx as u32, PackageSolvingData::RevokedOutput(revk_outp), - height + self.counterparty_commitment_params.on_counterparty_tx_csv as u32, height + htlc_txid, + idx as u32, + PackageSolvingData::RevokedOutput(revk_outp), + height + self.counterparty_commitment_params.on_counterparty_tx_csv as u32, + height, ); claimable_outpoints.push(justice_package); if outputs_to_watch.is_none() { @@ -3335,35 +4024,52 @@ impl ChannelMonitorImpl { // Returns (1) `PackageTemplate`s that can be given to the OnchainTxHandler, so that the handler can // broadcast transactions claiming holder HTLC commitment outputs and (2) a holder revokable // script so we can detect whether a holder transaction has been seen on-chain. - fn get_broadcasted_holder_claims(&self, holder_tx: &HolderSignedTx, conf_height: u32) -> (Vec, Option<(ScriptBuf, PublicKey, RevocationKey)>) { + fn get_broadcasted_holder_claims( + &self, holder_tx: &HolderSignedTx, conf_height: u32, + ) -> (Vec, Option<(ScriptBuf, PublicKey, RevocationKey)>) { let mut claim_requests = Vec::with_capacity(holder_tx.htlc_outputs.len()); - let redeemscript = chan_utils::get_revokeable_redeemscript(&holder_tx.revocation_key, self.on_holder_tx_csv, &holder_tx.delayed_payment_key); - let broadcasted_holder_revokable_script = Some((redeemscript.to_v0_p2wsh(), holder_tx.per_commitment_point.clone(), holder_tx.revocation_key.clone())); + let redeemscript = chan_utils::get_revokeable_redeemscript( + &holder_tx.revocation_key, + self.on_holder_tx_csv, + &holder_tx.delayed_payment_key, + ); + let broadcasted_holder_revokable_script = Some(( + redeemscript.to_v0_p2wsh(), + holder_tx.per_commitment_point.clone(), + holder_tx.revocation_key.clone(), + )); for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() { if let Some(transaction_output_index) = htlc.transaction_output_index { let htlc_output = if htlc.offered { let htlc_output = HolderHTLCOutput::build_offered( - htlc.amount_msat, htlc.cltv_expiry, self.onchain_tx_handler.channel_type_features().clone() + htlc.amount_msat, + htlc.cltv_expiry, + self.onchain_tx_handler.channel_type_features().clone(), ); htlc_output } else { - let payment_preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) { - preimage.clone() - } else { - // We can't build an HTLC-Success transaction without the preimage - continue; - }; + let payment_preimage = + if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) { + preimage.clone() + } else { + // We can't build an HTLC-Success transaction without the preimage + continue; + }; let htlc_output = HolderHTLCOutput::build_accepted( - payment_preimage, htlc.amount_msat, self.onchain_tx_handler.channel_type_features().clone() + payment_preimage, + htlc.amount_msat, + self.onchain_tx_handler.channel_type_features().clone(), ); htlc_output }; let htlc_package = PackageTemplate::build_package( - holder_tx.txid, transaction_output_index, + holder_tx.txid, + transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), - htlc.cltv_expiry, conf_height + htlc.cltv_expiry, + conf_height, ); claim_requests.push(htlc_package); } @@ -3373,11 +4079,16 @@ impl ChannelMonitorImpl { } // Returns holder HTLC outputs to watch and react to in case of spending. - fn get_broadcasted_holder_watch_outputs(&self, holder_tx: &HolderSignedTx, commitment_tx: &Transaction) -> Vec<(u32, TxOut)> { + fn get_broadcasted_holder_watch_outputs( + &self, holder_tx: &HolderSignedTx, commitment_tx: &Transaction, + ) -> Vec<(u32, TxOut)> { let mut watch_outputs = Vec::with_capacity(holder_tx.htlc_outputs.len()); for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() { if let Some(transaction_output_index) = htlc.transaction_output_index { - watch_outputs.push((transaction_output_index, commitment_tx.output[transaction_output_index as usize].clone())); + watch_outputs.push(( + transaction_output_index, + commitment_tx.output[transaction_output_index as usize].clone(), + )); } } watch_outputs @@ -3387,7 +4098,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.txid(); let mut claim_requests = Vec::new(); let mut watch_outputs = Vec::new(); @@ -3397,7 +4113,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 @@ -3406,12 +4122,24 @@ impl ChannelMonitorImpl { if self.current_holder_commitment_tx.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.current_holder_commitment_tx, height); - let mut to_watch = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, tx); + let res = + self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, height); + let mut to_watch = + self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, tx); append_onchain_update!(res, to_watch); - fail_unbroadcast_htlcs!(self, "latest holder", commitment_txid, tx, height, - block_hash, self.current_holder_commitment_tx.htlc_outputs.iter() - .map(|(htlc, _, htlc_source)| (htlc, htlc_source.as_ref())), logger); + fail_unbroadcast_htlcs!( + self, + "latest holder", + commitment_txid, + tx, + height, + block_hash, + self.current_holder_commitment_tx + .htlc_outputs + .iter() + .map(|(htlc, _, htlc_source)| (htlc, htlc_source.as_ref())), + logger + ); } else if let &Some(ref holder_tx) = &self.prev_holder_signed_commitment_tx { if holder_tx.txid == commitment_txid { is_holder_tx = true; @@ -3419,9 +4147,19 @@ impl ChannelMonitorImpl { let res = self.get_broadcasted_holder_claims(holder_tx, height); let mut to_watch = self.get_broadcasted_holder_watch_outputs(holder_tx, tx); append_onchain_update!(res, to_watch); - fail_unbroadcast_htlcs!(self, "previous holder", commitment_txid, tx, height, block_hash, - holder_tx.htlc_outputs.iter().map(|(htlc, _, htlc_source)| (htlc, htlc_source.as_ref())), - logger); + fail_unbroadcast_htlcs!( + self, + "previous holder", + commitment_txid, + tx, + height, + block_hash, + holder_tx + .htlc_outputs + .iter() + .map(|(htlc, _, htlc_source)| (htlc, htlc_source.as_ref())), + logger + ); } } @@ -3435,16 +4173,25 @@ 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 { continue; } - for (htlc, _) in self.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 + .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; @@ -3456,9 +4203,13 @@ impl ChannelMonitorImpl { // If we've signed, we may have broadcast either commitment (prev or current), and // attempted to claim from it immediately without waiting for a confirmation. if self.current_holder_commitment_tx.txid != *confirmed_commitment_txid { - log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}", - self.current_holder_commitment_tx.txid); - let mut outpoint = BitcoinOutPoint { txid: self.current_holder_commitment_tx.txid, vout: 0 }; + log_trace!( + logger, + "Canceling claims for previously broadcast holder commitment {}", + self.current_holder_commitment_tx.txid + ); + let mut outpoint = + BitcoinOutPoint { txid: self.current_holder_commitment_tx.txid, vout: 0 }; for (htlc, _, _) in &self.current_holder_commitment_tx.htlc_outputs { if let Some(vout) = htlc.transaction_output_index { outpoint.vout = vout; @@ -3468,9 +4219,13 @@ impl ChannelMonitorImpl { } if let Some(prev_holder_commitment_tx) = &self.prev_holder_signed_commitment_tx { if prev_holder_commitment_tx.txid != *confirmed_commitment_txid { - log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}", - prev_holder_commitment_tx.txid); - let mut outpoint = BitcoinOutPoint { txid: prev_holder_commitment_tx.txid, vout: 0 }; + log_trace!( + logger, + "Canceling claims for previously broadcast holder commitment {}", + prev_holder_commitment_tx.txid + ); + let mut outpoint = + BitcoinOutPoint { txid: prev_holder_commitment_tx.txid, vout: 0 }; for (htlc, _, _) in &prev_holder_commitment_tx.htlc_outputs { if let Some(vout) = htlc.transaction_output_index { outpoint.vout = vout; @@ -3486,10 +4241,14 @@ impl ChannelMonitorImpl { fn get_latest_holder_commitment_txn( &mut self, logger: &WithChannelMonitor, - ) -> Vec where L::Target: Logger { + ) -> Vec + where + L::Target: Logger, + { log_debug!(logger, "Getting signed latest holder commitment transaction!"); self.holder_tx_signed = true; - let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript); + let commitment_tx = + self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript); let txid = commitment_tx.txid(); let mut holder_transactions = vec![commitment_tx]; // When anchor outputs are present, the HTLC transactions are only valid once the commitment @@ -3500,7 +4259,9 @@ impl ChannelMonitorImpl { for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() { if let Some(vout) = htlc.0.transaction_output_index { let preimage = if !htlc.0.offered { - if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(preimage.clone()) } else { + if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { + Some(preimage.clone()) + } else { // We can't build an HTLC-Success transaction without the preimage continue; } @@ -3511,9 +4272,13 @@ impl ChannelMonitorImpl { // Note that we add + 1 as transactions are broadcastable when they can be // confirmed in the next block. continue; - } else { None }; - if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx( - &::bitcoin::OutPoint { txid, vout }, &preimage) { + } else { + None + }; + if let Some(htlc_tx) = self + .onchain_tx_handler + .get_fully_signed_htlc_tx(&::bitcoin::OutPoint { txid, vout }, &preimage) + { holder_transactions.push(htlc_tx); } } @@ -3523,13 +4288,17 @@ impl ChannelMonitorImpl { holder_transactions } - #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] + #[cfg(any(test, 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 = self.onchain_tx_handler.get_fully_signed_copy_holder_tx(&self.funding_redeemscript); + let commitment_tx = + self.onchain_tx_handler.get_fully_signed_copy_holder_tx(&self.funding_redeemscript); let txid = commitment_tx.txid(); let mut holder_transactions = vec![commitment_tx]; // When anchor outputs are present, the HTLC transactions are only final once the commitment @@ -3540,13 +4309,19 @@ impl ChannelMonitorImpl { for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() { if let Some(vout) = htlc.0.transaction_output_index { let preimage = if !htlc.0.offered { - if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(preimage.clone()) } else { + if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { + Some(preimage.clone()) + } else { // We can't build an HTLC-Success transaction without the preimage continue; } - } else { None }; - if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx( - &::bitcoin::OutPoint { txid, vout }, &preimage) { + } else { + None + }; + if let Some(htlc_tx) = self + .onchain_tx_handler + .get_fully_signed_htlc_tx(&::bitcoin::OutPoint { txid, vout }, &preimage) + { holder_transactions.push(htlc_tx); } } @@ -3558,24 +4333,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, @@ -3587,24 +4366,40 @@ 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); - self.onchain_tx_handler.block_disconnected(height + 1, broadcaster, fee_estimator, logger); + self.onchain_tx_handler.block_disconnected( + height + 1, + broadcaster, + 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, @@ -3615,9 +4410,13 @@ impl ChannelMonitorImpl { for tx in &txn_matched { let mut output_val = 0; for out in tx.output.iter() { - if out.value > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); } + if out.value > 21_000_000_0000_0000 { + panic!("Value-overflowing transaction provided to block connected"); + } output_val += out.value; - if output_val > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); } + if output_val > 21_000_000_0000_0000 { + panic!("Value-overflowing transaction provided to block connected"); + } } } @@ -3627,7 +4426,7 @@ impl ChannelMonitorImpl { let mut claimable_outpoints = Vec::new(); 'tx_iter: for tx in &txn_matched { let txid = tx.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); @@ -3663,22 +4462,37 @@ impl ChannelMonitorImpl { // (except for HTLC transactions for channels with anchor outputs), which is an easy // way to filter out any potential non-matching txn for lazy filters. let prevout = &tx.input[0].previous_output; - if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 { + if prevout.txid == self.funding_info.0.txid + && prevout.vout == self.funding_info.0.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 { - let (mut new_outpoints, new_outputs, counterparty_output_idx_sats) = - self.check_spend_counterparty_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 + { + let (mut new_outpoints, new_outputs, counterparty_output_idx_sats) = self + .check_spend_counterparty_transaction( + &tx, + height, + &block_hash, + &logger, + ); commitment_tx_to_counterparty_output = counterparty_output_idx_sats; if !new_outputs.1.is_empty() { watch_outputs.push(new_outputs); } claimable_outpoints.append(&mut new_outpoints); if new_outpoints.is_empty() { - if let Some((mut new_outpoints, new_outputs)) = self.check_spend_holder_transaction(&tx, height, &block_hash, &logger) { + if let Some((mut new_outpoints, new_outputs)) = self + .check_spend_holder_transaction(&tx, height, &block_hash, &logger) + { debug_assert!(commitment_tx_to_counterparty_output.is_none(), "A commitment transaction matched as both a counterparty and local commitment tx?"); if !new_outputs.1.is_empty() { @@ -3711,10 +4525,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); @@ -3736,7 +4557,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 @@ -3748,14 +4578,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 @@ -3763,12 +4588,18 @@ 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(); + let (mut new_outpoints, mut new_outputs) = + self.generate_claimable_outpoints_and_watch_outputs(); claimable_outpoints.append(&mut new_outpoints); watch_outputs.append(&mut new_outputs); } @@ -3787,7 +4618,8 @@ impl ChannelMonitorImpl { // 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), @@ -3800,7 +4632,12 @@ impl ChannelMonitorImpl { // Produce actionable events from on-chain events having reached their threshold. for entry in onchain_events_reaching_threshold_conf.drain(..) { match entry.event { - OnchainEvent::HTLCUpdate { ref source, payment_hash, htlc_value_satoshis, commitment_tx_output_idx } => { + OnchainEvent::HTLCUpdate { + ref source, + payment_hash, + htlc_value_satoshis, + commitment_tx_output_idx, + } => { // Check for duplicate HTLC resolutions. #[cfg(debug_assertions)] { @@ -3813,7 +4650,8 @@ impl ChannelMonitorImpl { matured_htlcs.iter().find(|&htlc| htlc == source).is_none(), "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()); } @@ -3833,14 +4671,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), @@ -3848,15 +4692,34 @@ 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; }, } } - self.onchain_tx_handler.update_claims_view_from_requests(claimable_outpoints, conf_height, self.best_block.height(), broadcaster, fee_estimator, logger); - self.onchain_tx_handler.update_claims_view_from_matched_txn(&txn_matched, conf_height, conf_hash, self.best_block.height(), broadcaster, fee_estimator, logger); + self.onchain_tx_handler.update_claims_view_from_requests( + claimable_outpoints, + conf_height, + self.best_block.height(), + broadcaster, + fee_estimator, + logger, + ); + self.onchain_tx_handler.update_claims_view_from_matched_txn( + &txn_matched, + conf_height, + conf_hash, + self.best_block.height(), + broadcaster, + fee_estimator, + logger, + ); // Determine new outputs to watch by comparing against previously known outputs to watch, // updating the latter in the process. @@ -3866,14 +4729,17 @@ impl ChannelMonitorImpl { }); #[cfg(test)] { - // If we see a transaction for which we registered outputs previously, + // If we see a transaction for which we registered outputs previously, // make sure the registered scriptpubkey at the expected index match // the actual transaction output one. We failed this case before #653. for tx in &txn_matched { if let Some(outputs) = self.get_outputs_to_watch().get(&tx.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 + ); } } } @@ -3882,8 +4748,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, { @@ -3895,16 +4763,18 @@ impl ChannelMonitorImpl { self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.height < height); let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); - self.onchain_tx_handler.block_disconnected(height, broadcaster, &bounded_fee_estimator, logger); + self.onchain_tx_handler.block_disconnected( + height, + broadcaster, + &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, @@ -3920,14 +4790,26 @@ 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)); self.onchain_tx_handler.transaction_unconfirmed(txid, broadcaster, fee_estimator, logger); } @@ -3936,19 +4818,25 @@ impl ChannelMonitorImpl { /// transactions thereof. fn filter_block<'a>(&self, txdata: &TransactionData<'a>) -> Vec<&'a Transaction> { let mut matched_txn = HashSet::new(); - 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.txid()); - } - matches - }).map(|(_, tx)| *tx).collect() + if matches { + matched_txn.insert(tx.txid()); + } + matches + }) + .map(|(_, tx)| *tx) + .collect() } /// Checks if a given transaction spends any watched outputs. @@ -3963,17 +4851,39 @@ 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_v0_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_v0_p2wpkh() { - assert_eq!(&bitcoin::Address::p2wpkh(&bitcoin::PublicKey::from_slice(&input.witness.last().unwrap()).unwrap(), bitcoin::Network::Bitcoin).unwrap().script_pubkey(), _script_pubkey); - } else { panic!(); } + assert_eq!( + &bitcoin::Address::p2wpkh( + &bitcoin::PublicKey::from_slice( + &input.witness.last().unwrap() + ) + .unwrap(), + bitcoin::Network::Bitcoin + ) + .unwrap() + .script_pubkey(), + _script_pubkey + ); + } else { + panic!(); + } } return true; } @@ -3985,15 +4895,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; } @@ -4044,7 +4961,10 @@ impl ChannelMonitorImpl { } } - scan_commitment!(self.current_holder_commitment_tx.htlc_outputs.iter().map(|&(ref a, _, _)| a), true); + scan_commitment!( + self.current_holder_commitment_tx.htlc_outputs.iter().map(|&(ref a, _, _)| a), + true + ); if let Some(ref txid) = self.current_counterparty_commitment_txid { if let Some(ref htlc_outputs) = self.counterparty_claimable_outpoints.get(txid) { @@ -4063,8 +4983,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); @@ -4114,23 +5037,37 @@ impl ChannelMonitorImpl { macro_rules! check_htlc_valid_counterparty { ($counterparty_txid: expr, $htlc_output: expr) => { if let Some(txid) = $counterparty_txid { - for &(ref pending_htlc, ref pending_source) in self.counterparty_claimable_outpoints.get(&txid).unwrap() { - if pending_htlc.payment_hash == $htlc_output.payment_hash && pending_htlc.amount_msat == $htlc_output.amount_msat { + for &(ref pending_htlc, ref pending_source) in + self.counterparty_claimable_outpoints.get(&txid).unwrap() + { + 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)); + 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 @@ -4138,58 +5075,109 @@ 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 { - check_htlc_valid_counterparty!(self.current_counterparty_commitment_txid, htlc_output); + check_htlc_valid_counterparty!( + self.current_counterparty_commitment_txid, + htlc_output + ); if payment_data.is_none() { - check_htlc_valid_counterparty!(self.prev_counterparty_commitment_txid, htlc_output); + check_htlc_valid_counterparty!( + self.prev_counterparty_commitment_txid, + htlc_output + ); } } 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.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.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.current_holder_commitment_tx.txid { - scan_commitment!(self.current_holder_commitment_tx.htlc_outputs.iter().map(|&(ref a, _, ref b)| (a, b.as_ref())), - "our latest holder commitment tx", true); + scan_commitment!( + self.current_holder_commitment_tx + .htlc_outputs + .iter() + .map(|&(ref a, _, ref b)| (a, b.as_ref())), + "our latest holder commitment tx", + true + ); } - if let Some(ref prev_holder_signed_commitment_tx) = self.prev_holder_signed_commitment_tx { + if let Some(ref prev_holder_signed_commitment_tx) = + self.prev_holder_signed_commitment_tx + { if input.previous_output.txid == prev_holder_signed_commitment_tx.txid { - scan_commitment!(prev_holder_signed_commitment_tx.htlc_outputs.iter().map(|&(ref a, _, ref b)| (a, b.as_ref())), - "our previous holder commitment tx", true); + scan_commitment!( + prev_holder_signed_commitment_tx + .htlc_outputs + .iter() + .map(|&(ref a, _, ref b)| (a, b.as_ref())), + "our previous holder commitment tx", + true + ); } } - if let Some(ref htlc_outputs) = self.counterparty_claimable_outpoints.get(&input.previous_output.txid) { - scan_commitment!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, (b.as_ref().clone()).map(|boxed| &**boxed))), - "counterparty commitment tx", false); + if let Some(ref htlc_outputs) = + self.counterparty_claimable_outpoints.get(&input.previous_output.txid) + { + scan_commitment!( + htlc_outputs + .iter() + .map(|&(ref a, ref b)| (a, (b.as_ref().clone()).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.txid(), height, @@ -4209,10 +5197,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.txid(), transaction: Some(tx.clone()), @@ -4233,7 +5224,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 @@ -4247,7 +5240,8 @@ impl ChannelMonitorImpl { height, block_hash: Some(*block_hash), event: OnchainEvent::HTLCUpdate { - source, payment_hash, + source, + payment_hash, htlc_value_satoshis: Some(amount_msat / 1000), commitment_tx_output_idx: Some(input.previous_output.vout), }, @@ -4269,27 +5263,35 @@ 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 { + spendable_outputs.push(SpendableOutputDescriptor::DelayedPaymentOutput( + DelayedPaymentOutputDescriptor { + outpoint: OutPoint { txid: tx.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.channel_value_satoshis, + }, + )); + } + } + if self.counterparty_payment_script == outp.script_pubkey { + spendable_outputs.push(SpendableOutputDescriptor::StaticPaymentOutput( + StaticPaymentOutputDescriptor { outpoint: OutPoint { txid: tx.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.channel_value_satoshis, - })); - } - } - if self.counterparty_payment_script == outp.script_pubkey { - spendable_outputs.push(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor { - outpoint: OutPoint { txid: tx.txid(), index: i as u16 }, - output: outp.clone(), - channel_keys_id: self.channel_keys_id, - channel_value_satoshis: self.channel_value_satoshis, - channel_transaction_parameters: Some(self.onchain_tx_handler.channel_transaction_parameters.clone()), - })); + channel_transaction_parameters: Some( + self.onchain_tx_handler.channel_transaction_parameters.clone(), + ), + }, + )); } if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) { spendable_outputs.push(SpendableOutputDescriptor::StaticOutput { @@ -4305,8 +5307,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.txid(), @@ -4315,13 +5320,19 @@ 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); } } } -impl chain::Listen for (ChannelMonitor, T, F, L) +impl chain::Listen + for (ChannelMonitor, T, F, L) where T::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -4336,7 +5347,8 @@ where } } -impl chain::Confirm for (M, T, F, L) +impl chain::Confirm + for (M, T, F, L) where M: Deref>, T::Target: BroadcasterInterface, @@ -4360,10 +5372,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) => { @@ -4371,7 +5384,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; @@ -4389,23 +5402,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_info = (outpoint, Readable::read(reader)?); let current_counterparty_commitment_txid = Readable::read(reader)?; let prev_counterparty_commitment_txid = Readable::read(reader)?; @@ -4424,7 +5438,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))), + )) } } }; @@ -4434,29 +5452,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 = HashMap::with_capacity(cmp::min(counterparty_claimable_outpoints_len as usize, MAX_ALLOC_SIZE / 64)); + let mut counterparty_claimable_outpoints = HashMap::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 let Some(_) = counterparty_claimable_outpoints.insert(txid, htlcs) { return Err(DecodeError::InvalidValue); @@ -4464,7 +5491,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 = HashMap::with_capacity(cmp::min(counterparty_commitment_txn_on_chain_len as usize, MAX_ALLOC_SIZE / 32)); + let mut counterparty_commitment_txn_on_chain = HashMap::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; @@ -4474,11 +5504,16 @@ 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 = HashMap::with_capacity(cmp::min(counterparty_hash_commitment_number_len as usize, MAX_ALLOC_SIZE / 32)); + let mut counterparty_hash_commitment_number = HashMap::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 let Some(_) = counterparty_hash_commitment_number.insert(payment_hash, commitment_number) { + if let Some(_) = + counterparty_hash_commitment_number.insert(payment_hash, commitment_number) + { return Err(DecodeError::InvalidValue); } } @@ -4486,9 +5521,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let mut prev_holder_signed_commitment_tx: Option = match ::read(reader)? { 0 => None, - 1 => { - Some(Readable::read(reader)?) - }, + 1 => Some(Readable::read(reader)?), _ => return Err(DecodeError::InvalidValue), }; let mut current_holder_commitment_tx: HolderSignedTx = Readable::read(reader)?; @@ -4497,7 +5530,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let current_holder_commitment_number = ::read(reader)?.0; let payment_preimages_len: u64 = Readable::read(reader)?; - let mut payment_preimages = HashMap::with_capacity(cmp::min(payment_preimages_len as usize, MAX_ALLOC_SIZE / 32)); + let mut payment_preimages = + HashMap::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()); @@ -4507,19 +5541,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(funding_info.0), - _ => 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); @@ -4529,7 +5568,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); @@ -4537,11 +5577,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 = HashMap::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 = HashMap::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)?)); } @@ -4550,7 +5599,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)?; @@ -4558,7 +5608,9 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP if let Some(prev_commitment_tx) = prev_holder_signed_commitment_tx.as_mut() { let prev_holder_value = onchain_tx_handler.get_prev_holder_commitment_to_self_value(); - if prev_holder_value.is_none() { return Err(DecodeError::InvalidValue); } + if prev_holder_value.is_none() { + return Err(DecodeError::InvalidValue); + } if prev_commitment_tx.to_self_value_sat == u64::max_value() { prev_commitment_tx.to_self_value_sat = prev_holder_value.unwrap(); } else if prev_commitment_tx.to_self_value_sat != prev_holder_value.unwrap() { @@ -4598,114 +5650,132 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP // 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 onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx() && - counterparty_payment_script.is_v0_p2wpkh() + if onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx() + && counterparty_payment_script.is_v0_p2wpkh() { - let payment_point = onchain_tx_handler.channel_transaction_parameters.holder_pubkeys.payment_point; + let payment_point = + onchain_tx_handler.channel_transaction_parameters.holder_pubkeys.payment_point; counterparty_payment_script = - chan_utils::get_to_countersignatory_with_anchors_redeemscript(&payment_point).to_v0_p2wsh(); + chan_utils::get_to_countersignatory_with_anchors_redeemscript(&payment_point) + .to_v0_p2wsh(); } - Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl { - 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: channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(outpoint)), - funding_info, - current_counterparty_commitment_txid, - prev_counterparty_commitment_txid, - - counterparty_commitment_params, - funding_redeemscript, - channel_value_satoshis, - their_cur_per_commitment_points, - - on_holder_tx_csv, - - commitment_secrets, - counterparty_claimable_outpoints, - counterparty_commitment_txn_on_chain, - counterparty_hash_commitment_number, - counterparty_fulfilled_htlcs: counterparty_fulfilled_htlcs.unwrap(), - - prev_holder_signed_commitment_tx, - current_holder_commitment_tx, - 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, - 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, - initial_counterparty_commitment_info, - }))) + Ok(( + best_block.block_hash(), + ChannelMonitor::from_impl(ChannelMonitorImpl { + 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: channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(outpoint)), + funding_info, + current_counterparty_commitment_txid, + prev_counterparty_commitment_txid, + + counterparty_commitment_params, + funding_redeemscript, + channel_value_satoshis, + their_cur_per_commitment_points, + + on_holder_tx_csv, + + commitment_secrets, + counterparty_claimable_outpoints, + counterparty_commitment_txn_on_chain, + counterparty_hash_commitment_number, + counterparty_fulfilled_htlcs: counterparty_fulfilled_htlcs.unwrap(), + + prev_holder_signed_commitment_tx, + current_holder_commitment_tx, + 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, + 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, + initial_counterparty_commitment_info, + }), + )) } } #[cfg(test)] mod tests { use bitcoin::blockdata::locktime::absolute::LockTime; - use bitcoin::blockdata::script::{ScriptBuf, Builder}; use bitcoin::blockdata::opcodes; - use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; + use bitcoin::blockdata::script::{Builder, ScriptBuf}; use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; - use bitcoin::sighash; - use bitcoin::sighash::EcdsaSighashType; - use bitcoin::hashes::Hash; - use bitcoin::hashes::sha256::Hash as Sha256; - use bitcoin::hashes::hex::FromHex; + use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; use bitcoin::hash_types::{BlockHash, Txid}; + use bitcoin::hashes::hex::FromHex; + use bitcoin::hashes::sha256::Hash as Sha256; + use bitcoin::hashes::Hash; use bitcoin::network::constants::Network; - use bitcoin::secp256k1::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + use bitcoin::sighash; + use bitcoin::sighash::EcdsaSighashType; 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, unwrap_send_err}; - 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::{PaymentPreimage, PaymentHash, ChannelId}; - use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, RevocationBasepoint, RevocationKey}; - use crate::ln::chan_utils::{self,HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; - use crate::ln::channelmanager::{PaymentSendFailure, PaymentId, RecipientOnionFields}; + 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::{PaymentId, PaymentSendFailure, RecipientOnionFields}; + use crate::ln::features::ChannelTypeFeatures; use crate::ln::functional_test_utils::*; use crate::ln::script::ShutdownScript; + use crate::ln::{ChannelId, PaymentHash, PaymentPreimage}; + use crate::prelude::*; + use crate::sign::InMemorySigner; + use crate::sync::{Arc, Mutex}; use crate::util::errors::APIError; - use crate::util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator}; - use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::logger::Logger; - use crate::sync::{Arc, Mutex}; - use crate::io; - use crate::ln::features::ChannelTypeFeatures; - use crate::prelude::*; + 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, unwrap_send_err, + }; use std::str::FromStr; @@ -4747,44 +5817,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); - unwrap_send_err!(nodes[1].node.send_payment_with_route(&route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ), false, APIError::MonitorUpdateInProgress, {}); + let (route, payment_hash, _, payment_secret) = + get_route_and_payment_hash!(nodes[1], nodes[0], 100_000); + unwrap_send_err!( + nodes[1].node.send_payment_with_route( + &route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0) + ), + false, + APIError::MonitorUpdateInProgress, + {} + ); 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!(); } - replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage: payment_preimage_1 }); - replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage: payment_preimage_2 }); + if let ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } = + replay_update.updates[0] + { + } else { + panic!(); + } + replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { + payment_preimage: payment_preimage_1, + }); + replay_update.updates.push(ChannelMonitorUpdateStep::PaymentPreimage { + payment_preimage: payment_preimage_2, + }); 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.txid() - }).collect::>(); + let htlc_txn = txn_broadcasted + .iter() + .filter(|tx| { + assert_eq!(tx.input.len(), 1); + tx.input[0].previous_output.txid == broadcast_tx.txid() + }) + .collect::>(); assert_eq!(htlc_txn.len(), 2); check_spends!(htlc_txn[0], broadcast_tx); check_spends!(htlc_txn[1], broadcast_tx); @@ -4802,7 +5903,8 @@ mod tests { let broadcaster = Arc::new(TestBroadcaster::new(Network::Testnet)); let fee_estimator = TestFeeEstimator { sat_per_kw: Mutex::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(); { @@ -4814,37 +5916,48 @@ mod tests { } 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 { + ($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 + }, + (), + )); } - } + 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_slice(&[42; 32]).unwrap(), - &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( @@ -4861,11 +5974,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_value() }; let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint); @@ -4878,60 +6006,121 @@ mod tests { selected_contest_delay: 67, }), funding_outpoint: Some(funding_outpoint), - channel_type_features: ChannelTypeFeatures::only_static_remote_key() + channel_type_features: ChannelTypeFeatures::only_static_remote_key(), }; // 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 best_block = BestBlock::from_network(Network::Testnet); - let monitor = ChannelMonitor::new(Secp256k1::new(), keys, - Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &ScriptBuf::new(), + let monitor = ChannelMonitor::new( + Secp256k1::new(), + keys, + Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), + 0, + &ScriptBuf::new(), (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, ScriptBuf::new()), - &channel_parameters, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()), - best_block, dummy_key, channel_id); + &channel_parameters, + ScriptBuf::new(), + 46, + 0, + HolderCommitmentTransaction::dummy(&mut Vec::new()), + best_block, + dummy_key, + channel_id, + ); let mut htlcs = preimages_slice_to_htlcs!(preimages[0..10]); let dummy_commitment_tx = HolderCommitmentTransaction::dummy(&mut htlcs); - monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(), - htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap(); - 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(), + htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect(), + ) + .unwrap(); + 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(hash, preimage, &broadcaster, &bounded_fee_estimator, &logger); + monitor.provide_payment_preimage( + 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 let mut htlcs = preimages_slice_to_htlcs!(preimages[0..5]); let dummy_commitment_tx = HolderCommitmentTransaction::dummy(&mut htlcs); - monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(), - htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap(); - secret[0..32].clone_from_slice(&>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor + .provide_latest_holder_commitment_tx( + dummy_commitment_tx.clone(), + htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect(), + ) + .unwrap(); + 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); @@ -4940,9 +6129,18 @@ mod tests { // But if we do it again, we'll prune 5-10 let mut htlcs = preimages_slice_to_htlcs!(preimages[0..3]); let dummy_commitment_tx = HolderCommitmentTransaction::dummy(&mut htlcs); - monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx, - htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap(); - secret[0..32].clone_from_slice(&>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + monitor + .provide_latest_holder_commitment_tx( + dummy_commitment_tx, + htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect(), + ) + .unwrap(); + 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); @@ -4954,21 +6152,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.segwit_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 + .segwit_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); @@ -4976,8 +6216,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]); @@ -4989,33 +6231,44 @@ 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: 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: 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: 0, - }); + claim_tx.output.push(TxOut { script_pubkey: script_pubkey.clone(), value: 0 }); 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); @@ -5024,30 +6277,42 @@ mod tests { 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: 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: 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: 0, - }); + claim_tx.output.push(TxOut { script_pubkey: script_pubkey.clone(), value: 0 }); 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); @@ -5056,26 +6321,33 @@ mod tests { 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: 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: 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: 0, - }); + claim_tx.output.push(TxOut { script_pubkey: script_pubkey.clone(), value: 0 }); let base_weight = claim_tx.weight().to_wu(); let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT]; let mut inputs_total_weight = 2; // count segwit flags @@ -5086,7 +6358,10 @@ mod tests { 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) + ); } } @@ -5095,7 +6370,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, @@ -5111,11 +6387,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_value() }; let channel_id = ChannelId::v1_from_funding_outpoint(funding_outpoint); @@ -5128,15 +6419,27 @@ mod tests { selected_contest_delay: 67, }), funding_outpoint: Some(funding_outpoint), - channel_type_features: ChannelTypeFeatures::only_static_remote_key() + channel_type_features: ChannelTypeFeatures::only_static_remote_key(), }; - 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 best_block = BestBlock::from_network(Network::Testnet); - let monitor = ChannelMonitor::new(Secp256k1::new(), keys, - Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &ScriptBuf::new(), + let monitor = ChannelMonitor::new( + Secp256k1::new(), + keys, + Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), + 0, + &ScriptBuf::new(), (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, ScriptBuf::new()), - &channel_parameters, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()), - best_block, dummy_key, channel_id); + &channel_parameters, + ScriptBuf::new(), + 46, + 0, + HolderCommitmentTransaction::dummy(&mut Vec::new()), + best_block, + dummy_key, + channel_id, + ); let chan_id = monitor.inner.lock().unwrap().channel_id(); let context_logger = WithChannelMonitor::from(&logger, &monitor); @@ -5146,7 +6449,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 368dd8497b0..64fb11821af 100644 --- a/lightning/src/chain/mod.rs +++ b/lightning/src/chain/mod.rs @@ -17,18 +17,18 @@ use bitcoin::network::constants::Network; use bitcoin::secp256k1::PublicKey; use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, MonitorEvent}; +use crate::chain::transaction::{OutPoint, TransactionData}; use crate::ln::ChannelId; use crate::sign::ecdsa::WriteableEcdsaChannelSigner; -use crate::chain::transaction::{OutPoint, TransactionData}; 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, PartialEq, Eq)] @@ -41,10 +41,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. @@ -53,13 +50,16 @@ impl BestBlock { } /// Returns the best block hash. - pub fn block_hash(&self) -> BlockHash { self.block_hash } + pub fn block_hash(&self) -> BlockHash { + self.block_hash + } /// Returns the best block height. - pub fn height(&self) -> u32 { self.height } + pub fn height(&self) -> u32 { + self.height + } } - /// The `Listen` trait is used to notify when blocks have been connected or disconnected from the /// chain. /// @@ -270,7 +270,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, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result; + fn watch_channel( + &self, funding_txo: OutPoint, monitor: ChannelMonitor, + ) -> Result; /// Updates a channel identified by `funding_txo` by applying `update` to its monitor. /// @@ -287,7 +289,9 @@ pub trait Watch { /// [`ChannelMonitorUpdateStatus::UnrecoverableError`], see its documentation for more info. /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager - fn update_channel(&self, funding_txo: OutPoint, update: &ChannelMonitorUpdate) -> ChannelMonitorUpdateStatus; + fn update_channel( + &self, funding_txo: OutPoint, update: &ChannelMonitorUpdate, + ) -> ChannelMonitorUpdateStatus; /// Returns any monitor events since the last call. Subsequent calls must only return new /// events. @@ -298,7 +302,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, Option)>; + fn release_pending_monitor_events( + &self, + ) -> Vec<(OutPoint, ChannelId, Vec, Option)>; } /// 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 59c98f05ebc..f0c9ea5ea2e 100644 --- a/lightning/src/chain/onchaintx.rs +++ b/lightning/src/chain/onchaintx.rs @@ -13,37 +13,46 @@ //! building, tracking, bumping and notifications functions. use bitcoin::blockdata::locktime::absolute::LockTime; -use bitcoin::blockdata::transaction::Transaction; -use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; use bitcoin::blockdata::script::{Script, ScriptBuf}; -use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; +use bitcoin::blockdata::transaction::Transaction; +use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hash_types::{Txid, BlockHash}; -use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; +use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::secp256k1; +use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1}; use crate::chain::chaininterface::compute_feerate_sat_per_1000_weight; -use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ChannelSigner, EntropySource, SignerProvider, ecdsa::WriteableEcdsaChannelSigner}; -use crate::ln::msgs::DecodeError; -use crate::ln::PaymentPreimage; -use crate::ln::chan_utils::{self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction}; -use crate::chain::ClaimId; -use crate::chain::chaininterface::{ConfirmationTarget, FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator}; +use crate::chain::chaininterface::{ + BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator, +}; use crate::chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER}; use crate::chain::package::{PackageSolvingData, PackageTemplate}; +use crate::chain::ClaimId; +use crate::ln::chan_utils::{ + self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction, +}; +use crate::ln::msgs::DecodeError; +use crate::ln::PaymentPreimage; +use crate::sign::{ + ecdsa::WriteableEcdsaChannelSigner, ChannelDerivationParameters, ChannelSigner, EntropySource, + HTLCDescriptor, SignerProvider, +}; use crate::util::logger::Logger; -use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, UpgradableRequired, Writer, Writeable, VecWriter}; +use crate::util::ser::{ + MaybeReadable, Readable, ReadableArgs, UpgradableRequired, VecWriter, Writeable, Writer, +}; use crate::io; +use crate::ln::features::ChannelTypeFeatures; use crate::prelude::*; use alloc::collections::BTreeMap; use core::cmp; -use core::ops::Deref; use core::mem::replace; use core::mem::swap; -use crate::ln::features::ChannelTypeFeatures; +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 +84,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 +118,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 +142,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)) @@ -272,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 } } @@ -329,7 +346,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)?; } @@ -339,8 +357,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; @@ -353,7 +375,8 @@ 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 = Readable::read(reader)?; @@ -370,17 +393,24 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP bytes_read += bytes_to_read; } - let mut signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); + let mut signer = + signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); signer.provide_channel_parameters(&channel_parameters); let pending_claim_requests_len: u64 = Readable::read(reader)?; - let mut pending_claim_requests = HashMap::with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); + let mut pending_claim_requests = HashMap::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 = HashMap::with_capacity(cmp::min(pending_claim_requests_len as usize, MAX_ALLOC_SIZE / 128)); + let mut claimable_outpoints = HashMap::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)?; @@ -393,7 +423,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)?); } @@ -401,7 +434,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); @@ -435,7 +469,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, @@ -474,48 +508,70 @@ impl OnchainTxHandler /// invoking this every 30 seconds, or lower if running in an environment with spotty /// connections, like on mobile. pub(super) fn rebroadcast_pending_claims( - &mut self, current_height: u32, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, - logger: &L, - ) - where + &mut self, current_height: u32, broadcaster: &B, + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, + ) 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, false /* force_feerate_bump */, fee_estimator, logger) - .map(|(_, new_feerate, claim)| { - let mut bumped_feerate = false; - if let Some(mut_request) = self.pending_claim_requests.get_mut(&claim_id) { - bumped_feerate = request.previous_feerate() > new_feerate; - mut_request.set_feerate(new_feerate); - } - match claim { - OnchainClaim::Tx(tx) => { - let log_start = if bumped_feerate { "Broadcasting RBF-bumped" } else { "Rebroadcasting" }; - log_info!(logger, "{} onchain {}", log_start, log_tx!(tx)); - broadcaster.broadcast_transactions(&[&tx]); - }, - OnchainClaim::Event(event) => { - let log_start = if bumped_feerate { "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)); + self.generate_claim( + current_height, + &request, + false, /* force_feerate_bump */ + fee_estimator, + logger, + ) + .map(|(_, new_feerate, claim)| { + let mut bumped_feerate = false; + if let Some(mut_request) = self.pending_claim_requests.get_mut(&claim_id) { + bumped_feerate = request.previous_feerate() > new_feerate; + mut_request.set_feerate(new_feerate); + } + match claim { + OnchainClaim::Tx(tx) => { + let log_start = if bumped_feerate { + "Broadcasting RBF-bumped" + } else { + "Rebroadcasting" + }; + log_info!(logger, "{} onchain {}", log_start, log_tx!(tx)); + broadcaster.broadcast_transactions(&[&tx]); + }, + OnchainClaim::Event(event) => { + let log_start = + if bumped_feerate { "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)); + }, + } + }); } } @@ -531,7 +587,8 @@ impl OnchainTxHandler &mut self, cur_height: u32, cached_request: &PackageTemplate, force_feerate_bump: bool, 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() { @@ -550,14 +607,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; @@ -577,16 +634,22 @@ 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, ConfirmationTarget::OnChainSweep, force_feerate_bump + fee_estimator, + ConfirmationTarget::OnChainSweep, + force_feerate_bump, ); - if let Some(htlcs) = cached_request.construct_malleable_package_with_external_funding(self) { + if let Some(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), + ), }), )); } else { @@ -596,14 +659,23 @@ impl OnchainTxHandler let predicted_weight = cached_request.package_weight(&self.destination_script); if let Some((output_value, new_feerate)) = cached_request.compute_package_output( - predicted_weight, self.destination_script.dust_value().to_sat(), - force_feerate_bump, fee_estimator, logger, + predicted_weight, + self.destination_script.dust_value().to_sat(), + force_feerate_bump, + fee_estimator, + logger, ) { assert!(new_feerate != 0); - let transaction = cached_request.finalize_malleable_package( - cur_height, self, output_value, self.destination_script.clone(), logger - ).unwrap(); + let transaction = cached_request + .finalize_malleable_package( + cur_height, + self, + output_value, + self.destination_script.clone(), + logger, + ) + .unwrap(); log_trace!(logger, "...with timer {} and feerate {}", new_timer, new_feerate); assert!(predicted_weight >= transaction.weight().to_wu()); return Some((new_timer, new_feerate, OnchainClaim::Tx(transaction))); @@ -671,16 +743,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 { @@ -690,8 +765,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) + }) + }); } } @@ -706,12 +784,17 @@ impl OnchainTxHandler /// `cur_height`, however it must never be higher than `cur_height`. pub(super) fn update_claims_view_from_requests( &mut self, requests: Vec, conf_height: u32, cur_height: u32, - broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, { - 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() + ); let mut preprocessed_requests = Vec::with_capacity(requests.len()); let mut aggregated_request = None; @@ -722,7 +805,11 @@ impl OnchainTxHandler if let Some(_) = self.claimable_outpoints.get(req.outpoints()[0]) { log_info!(logger, "Ignoring second claim for outpoint {}:{}, already registered its claiming request", req.outpoints()[0].txid, req.outpoints()[0].vout); } else { - let timelocked_equivalent_package = self.locktimed_packages.iter().map(|v| v.1.iter()).flatten() + let timelocked_equivalent_package = self + .locktimed_packages + .iter() + .map(|v| v.1.iter()) + .flatten() .find(|locked_package| locked_package.outpoints() == req.outpoints()); if let Some(package) = timelocked_equivalent_package { log_info!(logger, "Ignoring second claim for outpoint {}:{}, we already have one which we're waiting on a timelock at {} for.", @@ -740,7 +827,12 @@ impl OnchainTxHandler continue; } - log_trace!(logger, "Test if outpoint can be aggregated with expiration {} against {}", req.timelock(), cur_height + CLTV_SHARED_CLAIM_BUFFER); + log_trace!( + logger, + "Test if outpoint can be aggregated with expiration {} against {}", + req.timelock(), + cur_height + CLTV_SHARED_CLAIM_BUFFER + ); if req.timelock() <= cur_height + CLTV_SHARED_CLAIM_BUFFER || !req.aggregable() { // Don't aggregate if outpoint package timelock is soon or marked as non-aggregable preprocessed_requests.push(req); @@ -758,7 +850,11 @@ impl OnchainTxHandler // Claim everything up to and including `cur_height` let remaining_locked_packages = self.locktimed_packages.split_off(&(cur_height + 1)); 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; @@ -767,7 +863,11 @@ 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, true /* force_feerate_bump */, &*fee_estimator, &*logger, + cur_height, + &req, + true, /* force_feerate_bump */ + &*fee_estimator, + &*logger, ) { req.set_timer(new_timer); req.set_feerate(new_feerate); @@ -781,12 +881,18 @@ impl OnchainTxHandler ClaimId(tx.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.txid().to_byte_array()), + // For commitment claims, we can just use their txid as it should + // already be unique. + { + ClaimId(commitment_tx.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 @@ -795,13 +901,21 @@ 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 }, @@ -826,12 +940,18 @@ impl OnchainTxHandler /// provided via `cur_height`, however it must never be higher than `cur_height`. 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, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + cur_height: u32, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, { - 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 + ); let mut bump_candidates = HashMap::new(); for tx in txn_matched { // Scan all input to verify is one of the outpoint spent is of interest for us @@ -844,7 +964,8 @@ impl OnchainTxHandler // outpoints to know if transaction is the original claim or a bumped one issued // by us. let mut are_sets_equal = 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() { @@ -859,12 +980,12 @@ impl OnchainTxHandler txid: tx.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 @@ -872,10 +993,12 @@ impl OnchainTxHandler // ANTI_REORG_DELAY and clean the RBF tracking map. if are_sets_equal { 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; } @@ -893,9 +1016,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); @@ -935,19 +1062,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); @@ -965,7 +1099,11 @@ impl OnchainTxHandler log_trace!(logger, "Bumping {} candidates", bump_candidates.len()); for (claim_id, request) in bump_candidates.iter() { if let Some((new_timer, new_feerate, bump_claim)) = self.generate_claim( - cur_height, &request, true /* force_feerate_bump */, &*fee_estimator, &*logger, + cur_height, + &request, + true, /* force_feerate_bump */ + &*fee_estimator, + &*logger, ) { match bump_claim { OnchainClaim::Tx(bump_tx) => { @@ -973,10 +1111,18 @@ impl OnchainTxHandler broadcaster.broadcast_transactions(&[&bump_tx]); }, 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); @@ -992,10 +1138,7 @@ impl OnchainTxHandler } pub(super) fn transaction_unconfirmed( - &mut self, - txid: &Txid, - broadcaster: B, - fee_estimator: &LowerBoundedFeeEstimator, + &mut self, txid: &Txid, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, @@ -1014,9 +1157,12 @@ impl OnchainTxHandler } } - pub(super) fn block_disconnected(&mut self, height: u32, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator, logger: &L) - where B::Target: BroadcasterInterface, - F::Target: FeeEstimator, + pub(super) fn block_disconnected( + &mut self, height: u32, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator, + logger: &L, + ) where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, { let mut bump_candidates = HashMap::new(); let onchain_events_awaiting_threshold_conf = @@ -1027,8 +1173,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) + { request.merge_package(package); // Using a HashMap guarantee us than if we have multiple outpoints getting // resurrected only one bump claim tx is going to be broadcast @@ -1046,7 +1196,11 @@ 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, true /* force_feerate_bump */, fee_estimator, logger + current_height, + &request, + true, /* force_feerate_bump */ + fee_estimator, + logger, ) { request.set_timer(new_timer); request.set_feerate(new_feerate); @@ -1056,10 +1210,18 @@ impl OnchainTxHandler broadcaster.broadcast_transactions(&[&bump_tx]); }, 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); @@ -1074,11 +1236,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); } @@ -1089,7 +1254,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(); @@ -1110,29 +1276,46 @@ impl OnchainTxHandler // have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after OutboundV1Channel::get_funding_created, // before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing // to monitor before. - pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction { - let sig = self.signer.sign_holder_commitment(&self.holder_commitment, &self.secp_ctx).expect("signing holder commitment"); + pub(crate) fn get_fully_signed_holder_tx( + &mut self, funding_redeemscript: &Script, + ) -> Transaction { + let sig = self + .signer + .sign_holder_commitment(&self.holder_commitment, &self.secp_ctx) + .expect("signing holder commitment"); self.holder_commitment.add_holder_sig(funding_redeemscript, sig) } - #[cfg(any(test, feature="unsafe_revoked_tx_signing"))] - pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction { - let sig = self.signer.unsafe_sign_holder_commitment(&self.holder_commitment, &self.secp_ctx).expect("sign holder commitment"); + #[cfg(any(test, feature = "unsafe_revoked_tx_signing"))] + pub(crate) fn get_fully_signed_copy_holder_tx( + &mut self, funding_redeemscript: &Script, + ) -> Transaction { + let sig = self + .signer + .unsafe_sign_holder_commitment(&self.holder_commitment, &self.secp_ctx) + .expect("sign holder commitment"); self.holder_commitment.add_holder_sig(funding_redeemscript, sig) } - pub(crate) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option) -> Option { + pub(crate) fn get_fully_signed_htlc_tx( + &mut self, outp: &::bitcoin::OutPoint, preimage: &Option, + ) -> Option { let get_signed_htlc_tx = |holder_commitment: &HolderCommitmentTransaction| { let trusted_tx = holder_commitment.trust(); if trusted_tx.txid() != outp.txid { return None; } - let (htlc_idx, htlc) = trusted_tx.htlcs().iter().enumerate() + let (htlc_idx, htlc) = trusted_tx + .htlcs() + .iter() + .enumerate() .find(|(_, htlc)| htlc.transaction_output_index.unwrap() == outp.vout) .unwrap(); let counterparty_htlc_sig = holder_commitment.counterparty_htlc_sigs[htlc_idx]; let mut htlc_tx = trusted_tx.build_unsigned_htlc_tx( - &self.channel_transaction_parameters.as_holder_broadcastable(), htlc_idx, preimage, + &self.channel_transaction_parameters.as_holder_broadcastable(), + htlc_idx, + preimage, ); let htlc_descriptor = HTLCDescriptor { @@ -1149,43 +1332,59 @@ impl OnchainTxHandler preimage: preimage.clone(), counterparty_sig: counterparty_htlc_sig.clone(), }; - let htlc_sig = self.signer.sign_holder_htlc_transaction(&htlc_tx, 0, &htlc_descriptor, &self.secp_ctx).unwrap(); + let htlc_sig = self + .signer + .sign_holder_htlc_transaction(&htlc_tx, 0, &htlc_descriptor, &self.secp_ctx) + .unwrap(); htlc_tx.input[0].witness = trusted_tx.build_htlc_input_witness( - htlc_idx, &counterparty_htlc_sig, &htlc_sig, preimage, + htlc_idx, + &counterparty_htlc_sig, + &htlc_sig, + preimage, ); Some(htlc_tx) }; // Check if the HTLC spends from the current holder commitment first, or the previous. - get_signed_htlc_tx(&self.holder_commitment) - .or_else(|| self.prev_holder_commitment.as_ref().and_then(|prev_holder_commitment| get_signed_htlc_tx(prev_holder_commitment))) + get_signed_htlc_tx(&self.holder_commitment).or_else(|| { + self.prev_holder_commitment + .as_ref() + .and_then(|prev_holder_commitment| get_signed_htlc_tx(prev_holder_commitment)) + }) } pub(crate) fn generate_external_htlc_claim( - &self, outp: &::bitcoin::OutPoint, preimage: &Option + &self, outp: &::bitcoin::OutPoint, preimage: &Option, ) -> Option { - let find_htlc = |holder_commitment: &HolderCommitmentTransaction| -> Option { - let trusted_tx = holder_commitment.trust(); - if outp.txid != trusted_tx.txid() { - return None; - } - trusted_tx.htlcs().iter().enumerate() - .find(|(_, htlc)| if let Some(output_index) = htlc.transaction_output_index { - output_index == outp.vout - } else { - false - }) - .map(|(htlc_idx, htlc)| { - let counterparty_htlc_sig = holder_commitment.counterparty_htlc_sigs[htlc_idx]; - ExternalHTLCClaim { - commitment_txid: trusted_tx.txid(), - per_commitment_number: trusted_tx.commitment_number(), - htlc: htlc.clone(), - preimage: *preimage, - counterparty_sig: counterparty_htlc_sig, - } - }) - }; + let find_htlc = + |holder_commitment: &HolderCommitmentTransaction| -> Option { + let trusted_tx = holder_commitment.trust(); + if outp.txid != trusted_tx.txid() { + return None; + } + trusted_tx + .htlcs() + .iter() + .enumerate() + .find(|(_, htlc)| { + if let Some(output_index) = htlc.transaction_output_index { + output_index == outp.vout + } else { + false + } + }) + .map(|(htlc_idx, htlc)| { + let counterparty_htlc_sig = + holder_commitment.counterparty_htlc_sigs[htlc_idx]; + ExternalHTLCClaim { + commitment_txid: trusted_tx.txid(), + per_commitment_number: trusted_tx.commitment_number(), + htlc: htlc.clone(), + preimage: *preimage, + counterparty_sig: counterparty_htlc_sig, + } + }) + }; // Check if the HTLC spends from the current holder commitment or the previous one otherwise. find_htlc(&self.holder_commitment) .or_else(|| self.prev_holder_commitment.as_ref().map(|c| find_htlc(c)).flatten()) diff --git a/lightning/src/chain/package.rs b/lightning/src/chain/package.rs index efc32bf7d40..70bc8e18ce0 100644 --- a/lightning/src/chain/package.rs +++ b/lightning/src/chain/package.rs @@ -11,27 +11,29 @@ //! 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::blockdata::constants::WITNESS_SCALE_FACTOR; use bitcoin::blockdata::locktime::absolute::LockTime; -use bitcoin::blockdata::transaction::{TxOut,TxIn, Transaction}; -use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; use bitcoin::blockdata::script::{Script, ScriptBuf}; +use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; +use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; use bitcoin::hash_types::Txid; -use bitcoin::secp256k1::{SecretKey,PublicKey}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::sighash::EcdsaSighashType; +use bitcoin::{Sequence, Witness}; -use crate::ln::PaymentPreimage; -use crate::ln::chan_utils::{self, TxCreationKeys, HTLCOutputInCommitment}; -use crate::ln::features::ChannelTypeFeatures; +use crate::chain::chaininterface::{ + compute_feerate_sat_per_1000_weight, ConfirmationTarget, FeeEstimator, + FEERATE_FLOOR_SATS_PER_KW, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT, +}; +use crate::chain::onchaintx::{ExternalHTLCClaim, OnchainTxHandler}; +use crate::ln::chan_utils::{self, HTLCOutputInCommitment, TxCreationKeys}; use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint}; +use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs::DecodeError; -use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT, compute_feerate_sat_per_1000_weight, FEERATE_FLOOR_SATS_PER_KW}; +use crate::ln::PaymentPreimage; use crate::sign::ecdsa::WriteableEcdsaChannelSigner; -use crate::chain::onchaintx::{ExternalHTLCClaim, OnchainTxHandler}; use crate::util::logger::Logger; -use crate::util::ser::{Readable, Writer, Writeable, RequiredWrapper}; +use crate::util::ser::{Readable, RequiredWrapper, Writeable, Writer}; use crate::io; use crate::prelude::*; @@ -42,45 +44,64 @@ use core::ops::Deref; 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(); @@ -125,7 +146,12 @@ pub(crate) struct RevokedOutput { } impl RevokedOutput { - pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: u64, on_counterparty_tx_csv: u16, is_counterparty_balance_on_anchors: bool) -> Self { + pub(crate) fn build( + per_commitment_point: PublicKey, + counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, + counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: u64, + on_counterparty_tx_csv: u16, is_counterparty_balance_on_anchors: bool, + ) -> Self { RevokedOutput { per_commitment_point, counterparty_delayed_payment_base_key, @@ -134,7 +160,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 + }, } } } @@ -170,8 +200,17 @@ pub(crate) struct RevokedHTLCOutput { } impl RevokedHTLCOutput { - pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: u64, htlc: HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures) -> Self { - let weight = if htlc.offered { weight_revoked_offered_htlc(channel_type_features) } else { weight_revoked_received_htlc(channel_type_features) }; + pub(crate) fn build( + per_commitment_point: PublicKey, + counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, + counterparty_htlc_base_key: HtlcBasepoint, per_commitment_key: SecretKey, amount: u64, + htlc: HTLCOutputInCommitment, channel_type_features: &ChannelTypeFeatures, + ) -> Self { + let weight = if htlc.offered { + weight_revoked_offered_htlc(channel_type_features) + } else { + weight_revoked_received_htlc(channel_type_features) + }; RevokedHTLCOutput { per_commitment_point, counterparty_delayed_payment_base_key, @@ -179,7 +218,7 @@ impl RevokedHTLCOutput { per_commitment_key, weight, amount, - htlc + htlc, } } } @@ -213,7 +252,12 @@ pub(crate) struct CounterpartyOfferedHTLCOutput { } impl CounterpartyOfferedHTLCOutput { - pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, preimage: PaymentPreimage, htlc: HTLCOutputInCommitment, channel_type_features: ChannelTypeFeatures) -> Self { + pub(crate) fn build( + per_commitment_point: PublicKey, + counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, + counterparty_htlc_base_key: HtlcBasepoint, preimage: PaymentPreimage, + htlc: HTLCOutputInCommitment, channel_type_features: ChannelTypeFeatures, + ) -> Self { CounterpartyOfferedHTLCOutput { per_commitment_point, counterparty_delayed_payment_base_key, @@ -227,7 +271,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), @@ -269,7 +316,8 @@ impl Readable for CounterpartyOfferedHTLCOutput { counterparty_htlc_base_key: counterparty_htlc_base_key.0.unwrap(), preimage: preimage.0.unwrap(), htlc: htlc.0.unwrap(), - 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()), }) } } @@ -290,20 +338,28 @@ pub(crate) struct CounterpartyReceivedHTLCOutput { } impl CounterpartyReceivedHTLCOutput { - pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, counterparty_htlc_base_key: HtlcBasepoint, htlc: HTLCOutputInCommitment, channel_type_features: ChannelTypeFeatures) -> Self { + pub(crate) fn build( + per_commitment_point: PublicKey, + counterparty_delayed_payment_base_key: DelayedPaymentBasepoint, + counterparty_htlc_base_key: HtlcBasepoint, htlc: HTLCOutputInCommitment, + channel_type_features: ChannelTypeFeatures, + ) -> Self { CounterpartyReceivedHTLCOutput { per_commitment_point, counterparty_delayed_payment_base_key, counterparty_htlc_base_key, htlc, - channel_type_features + channel_type_features, } } } 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), @@ -341,7 +397,8 @@ impl Readable for CounterpartyReceivedHTLCOutput { counterparty_delayed_payment_base_key: counterparty_delayed_payment_base_key.0.unwrap(), counterparty_htlc_base_key: counterparty_htlc_base_key.0.unwrap(), htlc: htlc.0.unwrap(), - 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()), }) } } @@ -362,16 +419,15 @@ pub(crate) struct HolderHTLCOutput { } impl HolderHTLCOutput { - pub(crate) fn build_offered(amount_msat: u64, cltv_expiry: u32, channel_type_features: ChannelTypeFeatures) -> Self { - HolderHTLCOutput { - preimage: None, - amount_msat, - cltv_expiry, - channel_type_features, - } + pub(crate) fn build_offered( + amount_msat: u64, cltv_expiry: u32, channel_type_features: ChannelTypeFeatures, + ) -> Self { + HolderHTLCOutput { preimage: None, amount_msat, cltv_expiry, channel_type_features } } - pub(crate) fn build_accepted(preimage: PaymentPreimage, amount_msat: u64, channel_type_features: ChannelTypeFeatures) -> Self { + pub(crate) fn build_accepted( + preimage: PaymentPreimage, amount_msat: u64, channel_type_features: ChannelTypeFeatures, + ) -> Self { HolderHTLCOutput { preimage: Some(preimage), amount_msat, @@ -383,7 +439,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), @@ -417,7 +476,8 @@ impl Readable for HolderHTLCOutput { amount_msat: amount_msat.0.unwrap(), cltv_expiry: cltv_expiry.0.unwrap(), preimage, - 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()), }) } } @@ -434,9 +494,11 @@ pub(crate) struct HolderFundingOutput { channel_type_features: ChannelTypeFeatures, } - impl HolderFundingOutput { - pub(crate) fn build(funding_redeemscript: ScriptBuf, funding_amount: u64, channel_type_features: ChannelTypeFeatures) -> Self { + pub(crate) fn build( + funding_redeemscript: ScriptBuf, funding_amount: u64, + channel_type_features: ChannelTypeFeatures, + ) -> Self { HolderFundingOutput { funding_redeemscript, funding_amount: Some(funding_amount), @@ -447,7 +509,10 @@ impl HolderFundingOutput { 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), @@ -476,8 +541,9 @@ impl Readable for HolderFundingOutput { Ok(Self { funding_redeemscript: funding_redeemscript.0.unwrap(), - channel_type_features: channel_type_features.unwrap_or(ChannelTypeFeatures::only_static_remote_key()), - funding_amount + channel_type_features: channel_type_features + .unwrap_or(ChannelTypeFeatures::only_static_remote_key()), + funding_amount, }) } } @@ -501,8 +567,12 @@ impl PackageSolvingData { let amt = match self { PackageSolvingData::RevokedOutput(ref outp) => outp.amount, 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 @@ -510,7 +580,7 @@ impl PackageSolvingData { PackageSolvingData::HolderFundingOutput(ref outp) => { debug_assert!(outp.channel_type_features.supports_anchors_zero_fee_htlc_tx()); outp.funding_amount.unwrap() - } + }, }; amt } @@ -518,8 +588,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() { @@ -535,80 +609,141 @@ impl PackageSolvingData { } fn is_compatible(&self, input: &PackageSolvingData) -> bool { match self { - PackageSolvingData::RevokedOutput(..) => { - match input { - PackageSolvingData::RevokedHTLCOutput(..) => { true }, - PackageSolvingData::RevokedOutput(..) => { true }, - _ => { false } - } + PackageSolvingData::RevokedOutput(..) => match input { + PackageSolvingData::RevokedHTLCOutput(..) => true, + PackageSolvingData::RevokedOutput(..) => true, + _ => false, }, - PackageSolvingData::RevokedHTLCOutput(..) => { - match input { - PackageSolvingData::RevokedOutput(..) => { true }, - PackageSolvingData::RevokedHTLCOutput(..) => { true }, - _ => { false } - } + PackageSolvingData::RevokedHTLCOutput(..) => match input { + PackageSolvingData::RevokedOutput(..) => true, + PackageSolvingData::RevokedHTLCOutput(..) => true, + _ => false, }, - _ => { mem::discriminant(self) == mem::discriminant(&input) } + _ => mem::discriminant(self) == mem::discriminant(&input), } } fn as_tx_input(&self, previous_output: BitcoinOutPoint) -> TxIn { 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 { match self { PackageSolvingData::RevokedOutput(ref outp) => { - let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint); - let witness_script = chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, outp.on_counterparty_tx_csv, &chan_keys.broadcaster_delayed_payment_key); + let chan_keys = TxCreationKeys::derive_new( + &onchain_handler.secp_ctx, + &outp.per_commitment_point, + &outp.counterparty_delayed_payment_base_key, + &outp.counterparty_htlc_base_key, + &onchain_handler.signer.pubkeys().revocation_basepoint, + &onchain_handler.signer.pubkeys().htlc_basepoint, + ); + 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(&bumped_tx, i, outp.amount, &outp.per_commitment_key, &onchain_handler.secp_ctx) { + if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output( + &bumped_tx, + i, + outp.amount, + &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 chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint); - let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &onchain_handler.channel_type_features(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key); + let chan_keys = TxCreationKeys::derive_new( + &onchain_handler.secp_ctx, + &outp.per_commitment_point, + &outp.counterparty_delayed_payment_base_key, + &outp.counterparty_htlc_base_key, + &onchain_handler.signer.pubkeys().revocation_basepoint, + &onchain_handler.signer.pubkeys().htlc_basepoint, + ); + let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys( + &outp.htlc, + &onchain_handler.channel_type_features(), + &chan_keys.broadcaster_htlc_key, + &chan_keys.countersignatory_htlc_key, + &chan_keys.revocation_key, + ); //TODO: should we panic on signer failure ? - if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_htlc(&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( + &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 chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint); - let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &onchain_handler.channel_type_features(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key); - - if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(&bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) { + let chan_keys = TxCreationKeys::derive_new( + &onchain_handler.secp_ctx, + &outp.per_commitment_point, + &outp.counterparty_delayed_payment_base_key, + &outp.counterparty_htlc_base_key, + &onchain_handler.signer.pubkeys().revocation_basepoint, + &onchain_handler.signer.pubkeys().htlc_basepoint, + ); + let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys( + &outp.htlc, + &onchain_handler.channel_type_features(), + &chan_keys.broadcaster_htlc_key, + &chan_keys.countersignatory_htlc_key, + &chan_keys.revocation_key, + ); + + if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction( + &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); @@ -617,10 +752,30 @@ impl PackageSolvingData { } }, PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { - let chan_keys = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint); - let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &onchain_handler.channel_type_features(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key); - - if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(&bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) { + let chan_keys = TxCreationKeys::derive_new( + &onchain_handler.secp_ctx, + &outp.per_commitment_point, + &outp.counterparty_delayed_payment_base_key, + &outp.counterparty_htlc_base_key, + &onchain_handler.signer.pubkeys().revocation_basepoint, + &onchain_handler.signer.pubkeys().htlc_basepoint, + ); + let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys( + &outp.htlc, + &onchain_handler.channel_type_features(), + &chan_keys.broadcaster_htlc_key, + &chan_keys.countersignatory_htlc_key, + &chan_keys.revocation_key, + ); + + if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction( + &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); @@ -629,20 +784,28 @@ impl PackageSolvingData { bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); } }, - _ => { panic!("API Error!"); } + _ => { + panic!("API Error!"); + }, } true } - fn get_finalized_tx(&self, outpoint: &BitcoinOutPoint, onchain_handler: &mut OnchainTxHandler) -> Option { + fn get_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()); return onchain_handler.get_fully_signed_htlc_tx(outpoint, &outp.preimage); - } + }, PackageSolvingData::HolderFundingOutput(ref outp) => { - return Some(onchain_handler.get_fully_signed_holder_tx(&outp.funding_redeemscript)); - } - _ => { panic!("API Error!"); } + return Some( + onchain_handler.get_fully_signed_holder_tx(&outp.funding_redeemscript), + ); + }, + _ => { + panic!("API Error!"); + }, } } fn absolute_tx_timelock(&self, current_height: u32) -> u32 { @@ -652,7 +815,9 @@ impl PackageSolvingData { PackageSolvingData::RevokedOutput(_) => current_height, PackageSolvingData::RevokedHTLCOutput(_) => current_height, PackageSolvingData::CounterpartyOfferedHTLCOutput(_) => current_height, - PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => cmp::max(outp.htlc.cltv_expiry, current_height), + PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { + cmp::max(outp.htlc.cltv_expiry, current_height) + }, // HTLC timeout/success transactions rely on a fixed timelock due to the counterparty's // signature. PackageSolvingData::HolderHTLCOutput(ref outp) => { @@ -669,17 +834,31 @@ impl PackageSolvingData { fn map_output_type_flags(&self) -> (PackageMalleability, bool) { // Post-anchor, aggregation of outputs of different types is unsafe. See https://github.com/lightning/bolts/pull/803. let (malleability, aggregable) = match self { - PackageSolvingData::RevokedOutput(RevokedOutput { is_counterparty_balance_on_anchors: Some(()), .. }) => { (PackageMalleability::Malleable, false) }, - PackageSolvingData::RevokedOutput(RevokedOutput { is_counterparty_balance_on_anchors: None, .. }) => { (PackageMalleability::Malleable, true) }, - PackageSolvingData::RevokedHTLCOutput(..) => { (PackageMalleability::Malleable, true) }, - PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => { (PackageMalleability::Malleable, true) }, - PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => { (PackageMalleability::Malleable, false) }, - PackageSolvingData::HolderHTLCOutput(ref outp) => if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { - (PackageMalleability::Malleable, outp.preimage.is_some()) - } else { + PackageSolvingData::RevokedOutput(RevokedOutput { + is_counterparty_balance_on_anchors: Some(()), + .. + }) => (PackageMalleability::Malleable, false), + PackageSolvingData::RevokedOutput(RevokedOutput { + is_counterparty_balance_on_anchors: None, + .. + }) => (PackageMalleability::Malleable, true), + PackageSolvingData::RevokedHTLCOutput(..) => (PackageMalleability::Malleable, true), + PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => { + (PackageMalleability::Malleable, true) + }, + PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => { + (PackageMalleability::Malleable, false) + }, + PackageSolvingData::HolderHTLCOutput(ref outp) => { + if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { + (PackageMalleability::Malleable, outp.preimage.is_some()) + } else { + (PackageMalleability::Untractable, false) + } + }, + PackageSolvingData::HolderFundingOutput(..) => { (PackageMalleability::Untractable, false) }, - PackageSolvingData::HolderFundingOutput(..) => { (PackageMalleability::Untractable, false) }, }; (malleability, aggregable) } @@ -775,7 +954,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 => { let mut split_package = None; @@ -808,12 +989,14 @@ 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) { assert_eq!(self.height_original, merge_from.height_original); - if self.malleability == PackageMalleability::Untractable || merge_from.malleability == PackageMalleability::Untractable { + if self.malleability == PackageMalleability::Untractable + || merge_from.malleability == PackageMalleability::Untractable + { panic!("Merging template on untractable packages"); } if !self.aggregable || !merge_from.aggregable { @@ -821,9 +1004,13 @@ impl PackageTemplate { } if let Some((_, lead_input)) = self.inputs.first() { for (_, v) in merge_from.inputs.iter() { - if !lead_input.is_compatible(v) { panic!("Merging outputs from differing types !"); } + if !lead_input.is_compatible(v) { + panic!("Merging outputs from differing types !"); + } } - } else { panic!("Merging template on an empty package"); } + } else { + panic!("Merging template on an empty package"); + } for (k, v) in merge_from.inputs.drain(..) { self.inputs.push((k, v)); } @@ -846,30 +1033,39 @@ impl PackageTemplate { amounts } pub(crate) fn package_locktime(&self, current_height: u32) -> u32 { - let locktime = self.inputs.iter().map(|(_, outp)| outp.absolute_tx_timelock(current_height)) - .max().expect("There must always be at least one output to spend in a PackageTemplate"); + let locktime = self + .inputs + .iter() + .map(|(_, outp)| outp.absolute_tx_timelock(current_height)) + .max() + .expect("There must always be at least one output to spend in a PackageTemplate"); // If we ever try to aggregate a `HolderHTLCOutput`s with another output type, we'll likely // end up with an incorrect transaction locktime since the counterparty has included it in // its HTLC signature. This should never happen unless we decide to aggregate outputs across // different channel commitments. - #[cfg(debug_assertions)] { - if self.inputs.iter().any(|(_, outp)| + #[cfg(debug_assertions)] + { + if self.inputs.iter().any(|(_, outp)| { if let PackageSolvingData::HolderHTLCOutput(outp) = outp { outp.preimage.is_some() } else { false } - ) { + }) { debug_assert_eq!(locktime, 0); }; - for timeout_htlc_expiry in self.inputs.iter().filter_map(|(_, outp)| + for timeout_htlc_expiry in self.inputs.iter().filter_map(|(_, outp)| { if let PackageSolvingData::HolderHTLCOutput(outp) = outp { if outp.preimage.is_none() { Some(outp.cltv_expiry) - } else { None } - } else { None } - ) { + } else { + None + } + } else { + None + } + }) { debug_assert_eq!(locktime, timeout_htlc_expiry); } } @@ -890,7 +1086,9 @@ impl PackageTemplate { let output_weight = (8 + 1 + destination_script.len()) * WITNESS_SCALE_FACTOR; (inputs_weight + witnesses_weight + transaction_weight + output_weight) as u64 } - pub(crate) fn construct_malleable_package_with_external_funding( + pub(crate) fn construct_malleable_package_with_external_funding< + Signer: WriteableEcdsaChannelSigner, + >( &self, onchain_handler: &mut OnchainTxHandler, ) -> Option> { debug_assert!(self.requires_external_funding()); @@ -899,35 +1097,46 @@ impl PackageTemplate { match input { PackageSolvingData::HolderHTLCOutput(ref outp) => { debug_assert!(outp.channel_type_features.supports_anchors_zero_fee_htlc_tx()); - onchain_handler.generate_external_htlc_claim(&previous_output, &outp.preimage).map(|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"), + onchain_handler + .generate_external_htlc_claim(&previous_output, &outp.preimage) + .map(|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" + ), } } htlcs } pub(crate) fn finalize_malleable_package( &self, current_height: u32, onchain_handler: &mut OnchainTxHandler, value: u64, - destination_script: ScriptBuf, logger: &L + destination_script: ScriptBuf, logger: &L, ) -> Option { debug_assert!(self.is_malleable()); let mut bumped_tx = Transaction { version: 2, 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) { return None; } + log_debug!( + logger, + "Adding claiming input for outpoint {}:{}", + outpoint.txid, + outpoint.vout + ); + if !out.finalize_input(&mut bumped_tx, i, onchain_handler) { + return None; + } } log_debug!(logger, "Finalized transaction {} ready to broadcast", bumped_tx.txid()); Some(bumped_tx) @@ -938,12 +1147,19 @@ impl PackageTemplate { debug_assert!(!self.is_malleable()); if let Some((outpoint, outp)) = self.inputs.first() { if let Some(final_tx) = outp.get_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 + ); log_debug!(logger, "Finalized transaction {} ready to broadcast", final_tx.txid()); 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"); + } } /// In LN, output claimed are time-sensitive, which means we have to spend them before reaching some timelock expiration. At in-channel /// output detection, we generate a first version of a claim tx and associate to it a height timer. A height timer is an absolute block @@ -952,9 +1168,9 @@ impl PackageTemplate { /// frequency of the bump and so increase our bets of success. pub(crate) fn get_height_timer(&self, current_height: u32) -> u32 { if self.soonest_conf_deadline <= current_height + MIDDLE_FREQUENCY_BUMP_INTERVAL { - return current_height + HIGH_FREQUENCY_BUMP_INTERVAL + return current_height + HIGH_FREQUENCY_BUMP_INTERVAL; } else if self.soonest_conf_deadline - current_height <= LOW_FREQUENCY_BUMP_INTERVAL { - return current_height + MIDDLE_FREQUENCY_BUMP_INTERVAL + return current_height + MIDDLE_FREQUENCY_BUMP_INTERVAL; } current_height + LOW_FREQUENCY_BUMP_INTERVAL } @@ -966,22 +1182,44 @@ impl PackageTemplate { &self, predicted_weight: u64, dust_limit_sats: u64, force_feerate_bump: bool, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Option<(u64, u64)> - where F::Target: FeeEstimator, + where + F::Target: FeeEstimator, { - debug_assert!(self.malleability == PackageMalleability::Malleable, "The package output is fixed for non-malleable packages"); + debug_assert!( + 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, self.feerate_previous, force_feerate_bump, - fee_estimator, logger, + predicted_weight, + input_amounts, + self.feerate_previous, + force_feerate_bump, + fee_estimator, + logger, ) { - return Some((cmp::max(input_amounts as i64 - new_fee as i64, dust_limit_sats as i64) as u64, feerate)); + return Some(( + cmp::max(input_amounts as i64 - new_fee as i64, dust_limit_sats as i64) as u64, + feerate, + )); } } else { - if let Some((new_fee, feerate)) = compute_fee_from_spent_amounts(input_amounts, predicted_weight, 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, + fee_estimator, + logger, + ) { + return Some(( + cmp::max(input_amounts as i64 - new_fee as i64, dust_limit_sats as i64) as u64, + feerate, + )); } } None @@ -993,7 +1231,10 @@ impl PackageTemplate { pub(crate) fn compute_package_feerate( &self, fee_estimator: &LowerBoundedFeeEstimator, conf_target: ConfirmationTarget, force_feerate_bump: bool, - ) -> 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 { // Use the new fee estimate if it's higher than the one previously used. @@ -1022,15 +1263,26 @@ 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() - } - - pub (crate) fn build_package(txid: Txid, vout: u32, input_solving_data: PackageSolvingData, soonest_conf_deadline: u32, height_original: u32) -> Self { - let (malleability, aggregable) = PackageSolvingData::map_output_type_flags(&input_solving_data); + 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, soonest_conf_deadline: u32, + height_original: u32, + ) -> Self { + let (malleability, aggregable) = + PackageSolvingData::map_output_type_flags(&input_solving_data); let mut inputs = Vec::with_capacity(1); inputs.push((BitcoinOutPoint { txid, vout }, input_solving_data)); PackageTemplate { @@ -1065,7 +1317,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)?; @@ -1073,7 +1326,9 @@ impl Readable for PackageTemplate { } let (malleability, aggregable) = 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 soonest_conf_deadline = 0; let mut feerate_previous = 0; let mut height_timer = None; @@ -1109,11 +1364,18 @@ impl Readable for PackageTemplate { /// /// [`OnChainSweep`]: crate::chain::chaininterface::ConfirmationTarget::OnChainSweep /// [`FEERATE_FLOOR_SATS_PER_KW`]: crate::chain::chaininterface::MIN_RELAY_FEE_SAT_PER_1000_WEIGHT -fn compute_fee_from_spent_amounts(input_amounts: u64, predicted_weight: u64, fee_estimator: &LowerBoundedFeeEstimator, logger: &L) -> Option<(u64, u64)> - where F::Target: FeeEstimator, +fn compute_fee_from_spent_amounts( + input_amounts: u64, predicted_weight: u64, fee_estimator: &LowerBoundedFeeEstimator, + logger: &L, +) -> Option<(u64, u64)> +where + F::Target: FeeEstimator, { let sweep_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::OnChainSweep); - 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 @@ -1140,7 +1402,9 @@ where F::Target: FeeEstimator, { // 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, fee_estimator, logger) { + let (new_fee, new_feerate) = if let Some((new_fee, new_feerate)) = + compute_fee_from_spent_amounts(input_amounts, predicted_weight, fee_estimator, logger) + { if new_feerate > previous_feerate { (new_fee, new_feerate) } else if !force_feerate_bump { @@ -1151,13 +1415,21 @@ where let bumped_feerate = previous_feerate + (previous_feerate / 4); let bumped_fee = bumped_feerate * predicted_weight / 1000; if input_amounts <= bumped_fee { - log_warn!(logger, "Can't 25% bump new claiming tx, amount {} is too small", input_amounts); + log_warn!( + logger, + "Can't 25% bump new claiming tx, amount {} is too small", + input_amounts + ); return None; } (bumped_fee, bumped_feerate) } } else { - log_warn!(logger, "Can't new-estimation bump new claiming tx, amount {} is too small", input_amounts); + log_warn!( + logger, + "Can't new-estimation bump new claiming tx, amount {} is too small", + input_amounts + ); return None; }; @@ -1183,11 +1455,15 @@ where #[cfg(test)] mod tests { - use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderHTLCOutput, PackageTemplate, PackageSolvingData, RevokedOutput, WEIGHT_REVOKED_OUTPUT, weight_offered_htlc, weight_received_htlc}; + use crate::chain::package::{ + weight_offered_htlc, weight_received_htlc, CounterpartyOfferedHTLCOutput, + CounterpartyReceivedHTLCOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, + RevokedOutput, WEIGHT_REVOKED_OUTPUT, + }; use crate::chain::Txid; use crate::ln::chan_utils::HTLCOutputInCommitment; - use crate::ln::{PaymentPreimage, PaymentHash}; use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint}; + use crate::ln::{PaymentHash, PaymentPreimage}; use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR; use bitcoin::blockdata::script::ScriptBuf; @@ -1195,128 +1471,210 @@ mod tests { use bitcoin::hashes::hex::FromHex; - use bitcoin::secp256k1::{PublicKey,SecretKey}; - use bitcoin::secp256k1::Secp256k1; use crate::ln::features::ChannelTypeFeatures; + use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; use std::str::FromStr; macro_rules! dumb_revk_output { - ($secp_ctx: expr, $is_counterparty_balance_on_anchors: expr) => { - { - let dumb_scalar = SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap(); - let dumb_point = PublicKey::from_secret_key(&$secp_ctx, &dumb_scalar); - PackageSolvingData::RevokedOutput(RevokedOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), dumb_scalar, 0, 0, $is_counterparty_balance_on_anchors)) - } - } + ($secp_ctx: expr, $is_counterparty_balance_on_anchors: expr) => {{ + let dumb_scalar = SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap()[..], + ) + .unwrap(); + let dumb_point = PublicKey::from_secret_key(&$secp_ctx, &dumb_scalar); + PackageSolvingData::RevokedOutput(RevokedOutput::build( + dumb_point, + DelayedPaymentBasepoint::from(dumb_point), + HtlcBasepoint::from(dumb_point), + dumb_scalar, + 0, + 0, + $is_counterparty_balance_on_anchors, + )) + }}; } macro_rules! dumb_counterparty_output { - ($secp_ctx: expr, $amt: expr, $opt_anchors: expr) => { - { - 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: 0, payment_hash: hash, transaction_output_index: None }; - PackageSolvingData::CounterpartyReceivedHTLCOutput(CounterpartyReceivedHTLCOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), htlc, $opt_anchors)) - } - } + ($secp_ctx: expr, $amt: expr, $opt_anchors: expr) => {{ + 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: 0, + payment_hash: hash, + transaction_output_index: None, + }; + PackageSolvingData::CounterpartyReceivedHTLCOutput( + CounterpartyReceivedHTLCOutput::build( + dumb_point, + DelayedPaymentBasepoint::from(dumb_point), + HtlcBasepoint::from(dumb_point), + htlc, + $opt_anchors, + ), + ) + }}; } macro_rules! dumb_counterparty_offered_output { - ($secp_ctx: expr, $amt: expr, $opt_anchors: expr) => { - { - 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: 1000, payment_hash: hash, transaction_output_index: None }; - PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build(dumb_point, DelayedPaymentBasepoint::from(dumb_point), HtlcBasepoint::from(dumb_point), preimage, htlc, $opt_anchors)) - } - } + ($secp_ctx: expr, $amt: expr, $opt_anchors: expr) => {{ + 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: 1000, + payment_hash: hash, + transaction_output_index: None, + }; + PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build( + dumb_point, + DelayedPaymentBasepoint::from(dumb_point), + HtlcBasepoint::from(dumb_point), + preimage, + htlc, + $opt_anchors, + )) + }}; } macro_rules! dumb_htlc_output { - () => { - { - let preimage = PaymentPreimage([2;32]); - PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build_accepted(preimage, 0, ChannelTypeFeatures::only_static_remote_key())) - } - } + () => {{ + let preimage = PaymentPreimage([2; 32]); + PackageSolvingData::HolderHTLCOutput(HolderHTLCOutput::build_accepted( + preimage, + 0, + ChannelTypeFeatures::only_static_remote_key(), + )) + }}; } #[test] #[should_panic] fn test_package_differing_heights() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp = dumb_revk_output!(secp_ctx, false); - let mut package_one_hundred = PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); - let package_two_hundred = PackageTemplate::build_package(txid, 1, revk_outp.clone(), 1000, 200); + let mut package_one_hundred = + PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); + let package_two_hundred = + PackageTemplate::build_package(txid, 1, revk_outp.clone(), 1000, 200); package_one_hundred.merge_package(package_two_hundred); } #[test] #[should_panic] fn test_package_untractable_merge_to() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp = dumb_revk_output!(secp_ctx, false); let htlc_outp = dumb_htlc_output!(); - let mut untractable_package = PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); - let malleable_package = PackageTemplate::build_package(txid, 1, htlc_outp.clone(), 1000, 100); + let mut untractable_package = + PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); + let malleable_package = + PackageTemplate::build_package(txid, 1, htlc_outp.clone(), 1000, 100); untractable_package.merge_package(malleable_package); } #[test] #[should_panic] fn test_package_untractable_merge_from() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let htlc_outp = dumb_htlc_output!(); let revk_outp = dumb_revk_output!(secp_ctx, false); - let mut malleable_package = PackageTemplate::build_package(txid, 0, htlc_outp.clone(), 1000, 100); - let untractable_package = PackageTemplate::build_package(txid, 1, revk_outp.clone(), 1000, 100); + let mut malleable_package = + PackageTemplate::build_package(txid, 0, htlc_outp.clone(), 1000, 100); + let untractable_package = + PackageTemplate::build_package(txid, 1, revk_outp.clone(), 1000, 100); malleable_package.merge_package(untractable_package); } #[test] #[should_panic] fn test_package_noaggregation_to() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp = dumb_revk_output!(secp_ctx, false); let revk_outp_counterparty_balance = dumb_revk_output!(secp_ctx, true); - let mut noaggregation_package = PackageTemplate::build_package(txid, 0, revk_outp_counterparty_balance.clone(), 1000, 100); - let aggregation_package = PackageTemplate::build_package(txid, 1, revk_outp.clone(), 1000, 100); + let mut noaggregation_package = PackageTemplate::build_package( + txid, + 0, + revk_outp_counterparty_balance.clone(), + 1000, + 100, + ); + let aggregation_package = + PackageTemplate::build_package(txid, 1, revk_outp.clone(), 1000, 100); noaggregation_package.merge_package(aggregation_package); } #[test] #[should_panic] fn test_package_noaggregation_from() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp = dumb_revk_output!(secp_ctx, false); let revk_outp_counterparty_balance = dumb_revk_output!(secp_ctx, true); - let mut aggregation_package = PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); - let noaggregation_package = PackageTemplate::build_package(txid, 1, revk_outp_counterparty_balance.clone(), 1000, 100); + let mut aggregation_package = + PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); + let noaggregation_package = PackageTemplate::build_package( + txid, + 1, + revk_outp_counterparty_balance.clone(), + 1000, + 100, + ); aggregation_package.merge_package(noaggregation_package); } #[test] #[should_panic] fn test_package_empty() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp = dumb_revk_output!(secp_ctx, false); - let mut empty_package = PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); + let mut empty_package = + PackageTemplate::build_package(txid, 0, revk_outp.clone(), 1000, 100); empty_package.inputs = vec![]; let package = PackageTemplate::build_package(txid, 1, revk_outp.clone(), 1000, 100); empty_package.merge_package(package); @@ -1325,19 +1683,25 @@ mod tests { #[test] #[should_panic] fn test_package_differing_categories() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp = dumb_revk_output!(secp_ctx, false); - let counterparty_outp = dumb_counterparty_output!(secp_ctx, 0, ChannelTypeFeatures::only_static_remote_key()); + let counterparty_outp = + dumb_counterparty_output!(secp_ctx, 0, ChannelTypeFeatures::only_static_remote_key()); let mut revoked_package = PackageTemplate::build_package(txid, 0, revk_outp, 1000, 100); - let counterparty_package = PackageTemplate::build_package(txid, 1, counterparty_outp, 1000, 100); + let counterparty_package = + PackageTemplate::build_package(txid, 1, counterparty_outp, 1000, 100); revoked_package.merge_package(counterparty_package); } #[test] fn test_package_split_malleable() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp_one = dumb_revk_output!(secp_ctx, false); let revk_outp_two = dumb_revk_output!(secp_ctx, false); @@ -1359,23 +1723,29 @@ mod tests { assert_eq!(split_package.feerate_previous, package_one.feerate_previous); assert_eq!(split_package.height_timer, package_one.height_timer); assert_eq!(split_package.height_original, package_one.height_original); - } else { panic!(); } + } else { + panic!(); + } assert_eq!(package_one.outpoints().len(), 2); } #[test] fn test_package_split_untractable() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let htlc_outp_one = dumb_htlc_output!(); let mut package_one = PackageTemplate::build_package(txid, 0, htlc_outp_one, 1000, 100); - let ret_split = package_one.split_package(&BitcoinOutPoint { txid, vout: 0}); + let ret_split = package_one.split_package(&BitcoinOutPoint { txid, vout: 0 }); assert!(ret_split.is_none()); } #[test] fn test_package_timer() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); let revk_outp = dumb_revk_output!(secp_ctx, false); @@ -1387,9 +1757,15 @@ mod tests { #[test] fn test_package_amounts() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); - let counterparty_outp = dumb_counterparty_output!(secp_ctx, 1_000_000, ChannelTypeFeatures::only_static_remote_key()); + let counterparty_outp = dumb_counterparty_output!( + secp_ctx, + 1_000_000, + ChannelTypeFeatures::only_static_remote_key() + ); let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, 100); assert_eq!(package.package_amount(), 1000); @@ -1397,31 +1773,58 @@ mod tests { #[test] fn test_package_weight() { - let txid = Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(); + let txid = + Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e") + .unwrap(); let secp_ctx = Secp256k1::new(); // (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!(secp_ctx, false); let package = PackageTemplate::build_package(txid, 0, revk_outp, 0, 100); - 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_output!(secp_ctx, 1_000_000, channel_type_features.clone()); + for channel_type_features in [ + ChannelTypeFeatures::only_static_remote_key(), + ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + ] + .iter() + { + let counterparty_outp = + dumb_counterparty_output!(secp_ctx, 1_000_000, channel_type_features.clone()); let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, 100); - assert_eq!(package.package_weight(&ScriptBuf::new()), weight_sans_output + weight_received_htlc(channel_type_features)); + 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!(secp_ctx, 1_000_000, channel_type_features.clone()); + 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!( + secp_ctx, + 1_000_000, + channel_type_features.clone() + ); let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, 100); - assert_eq!(package.package_weight(&ScriptBuf::new()), weight_sans_output + weight_offered_htlc(channel_type_features)); + assert_eq!( + package.package_weight(&ScriptBuf::new()), + weight_sans_output + weight_offered_htlc(channel_type_features) + ); } } } diff --git a/lightning/src/chain/transaction.rs b/lightning/src/chain/transaction.rs index 17815207a8d..2ef514ed1e9 100644 --- a/lightning/src/chain/transaction.rs +++ b/lightning/src/chain/transaction.rs @@ -9,9 +9,9 @@ //! Types describing on-chain transactions. -use bitcoin::hash_types::Txid; use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; use bitcoin::blockdata::transaction::Transaction; +use bitcoin::hash_types::Txid; /// Transaction data where each item consists of a transaction reference paired with the index of /// the transaction within a block. @@ -58,13 +58,10 @@ pub struct OutPoint { impl OutPoint { /// Converts this OutPoint into the OutPoint field as used by rust-bitcoin /// - /// This is not exported to bindings users as the same type is used universally in the C bindings + /// 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 } } } @@ -88,13 +85,19 @@ mod tests { #[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.txid(), - index: 0 - }).0[..], &>::from_hex("3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25e").unwrap()[..]); - assert_eq!(&ChannelId::v1_from_funding_outpoint(OutPoint { - txid: tx.txid(), - index: 1 - }).0[..], &>::from_hex("3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25f").unwrap()[..]); + assert_eq!( + &ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.txid(), index: 0 }).0[..], + &>::from_hex( + "3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25e" + ) + .unwrap()[..] + ); + assert_eq!( + &ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.txid(), index: 1 }).0[..], + &>::from_hex( + "3e88dd7165faf7be58b3c5bb2c9c452aebef682807ea57080f62e6f6e113c25f" + ) + .unwrap()[..] + ); } } diff --git a/lightning/src/crypto/chacha20.rs b/lightning/src/crypto/chacha20.rs index d6fd3a7dee0..38529baed4a 100644 --- a/lightning/src/crypto/chacha20.rs +++ b/lightning/src/crypto/chacha20.rs @@ -21,20 +21,24 @@ mod real_chacha { type Output = u32x4; #[inline] fn add(self, rhs: u32x4) -> u32x4 { - u32x4(self.0.wrapping_add(rhs.0), - self.1.wrapping_add(rhs.1), - self.2.wrapping_add(rhs.2), - self.3.wrapping_add(rhs.3)) + u32x4( + self.0.wrapping_add(rhs.0), + self.1.wrapping_add(rhs.1), + self.2.wrapping_add(rhs.2), + self.3.wrapping_add(rhs.3), + ) } } impl ::core::ops::Sub for u32x4 { type Output = u32x4; #[inline] fn sub(self, rhs: u32x4) -> u32x4 { - u32x4(self.0.wrapping_sub(rhs.0), - self.1.wrapping_sub(rhs.1), - self.2.wrapping_sub(rhs.2), - self.3.wrapping_sub(rhs.3)) + u32x4( + self.0.wrapping_sub(rhs.0), + self.1.wrapping_sub(rhs.1), + self.2.wrapping_sub(rhs.2), + self.3.wrapping_sub(rhs.3), + ) } } impl ::core::ops::BitXor for u32x4 { @@ -61,44 +65,48 @@ mod real_chacha { impl u32x4 { #[inline] fn from_bytes(bytes: &[u8]) -> Self { - assert_eq!(bytes.len(), 4*4); - Self ( - u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")), - u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")), - u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")), - u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")), + assert_eq!(bytes.len(), 4 * 4); + Self( + u32::from_le_bytes(bytes[0 * 4..1 * 4].try_into().expect("len is 4")), + u32::from_le_bytes(bytes[1 * 4..2 * 4].try_into().expect("len is 4")), + u32::from_le_bytes(bytes[2 * 4..3 * 4].try_into().expect("len is 4")), + u32::from_le_bytes(bytes[3 * 4..4 * 4].try_into().expect("len is 4")), ) } } const BLOCK_SIZE: usize = 64; - #[derive(Clone,Copy)] + #[derive(Clone, Copy)] struct ChaChaState { a: u32x4, b: u32x4, c: u32x4, - d: u32x4 + d: u32x4, } #[derive(Copy)] pub struct ChaCha20 { - state : ChaChaState, - output : [u8; BLOCK_SIZE], - offset : usize, + state: ChaChaState, + output: [u8; BLOCK_SIZE], + offset: usize, } - impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } } + impl Clone for ChaCha20 { + fn clone(&self) -> ChaCha20 { + *self + } + } macro_rules! swizzle { ($b: expr, $c: expr, $d: expr) => {{ let u32x4(b10, b11, b12, b13) = $b; $b = u32x4(b11, b12, b13, b10); let u32x4(c10, c11, c12, c13) = $c; - $c = u32x4(c12, c13,c10, c11); + $c = u32x4(c12, c13, c10, c11); let u32x4(d10, d11, d12, d13) = $d; $d = u32x4(d13, d10, d11, d12); - }} + }}; } macro_rules! state_to_buffer { @@ -107,19 +115,14 @@ mod real_chacha { let u32x4(b1, b2, b3, b4) = $state.b; let u32x4(c1, c2, c3, c4) = $state.c; let u32x4(d1, d2, d3, d4) = $state.d; - let lens = [ - a1,a2,a3,a4, - b1,b2,b3,b4, - c1,c2,c3,c4, - d1,d2,d3,d4 - ]; + let lens = [a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4]; for i in 0..lens.len() { - $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes()); + $output[i * 4..(i + 1) * 4].copy_from_slice(&lens[i].to_le_bytes()); } - }} + }}; } - macro_rules! round{ + macro_rules! round { ($state: expr) => {{ $state.a = $state.a + $state.b; rotate!($state.d, $state.a, 16); @@ -129,7 +132,7 @@ mod real_chacha { rotate!($state.d, $state.a, 8); $state.c = $state.c + $state.d; rotate!($state.b, $state.c, 7); - }} + }}; } macro_rules! rotate { @@ -138,7 +141,7 @@ mod real_chacha { let r = 32 - $rot; let right = v >> r; $a = (v << $rot) ^ right - }} + }}; } impl ChaCha20 { @@ -146,12 +149,16 @@ mod real_chacha { assert!(key.len() == 16 || key.len() == 32); assert!(nonce.len() == 8 || nonce.len() == 12); - ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 } + ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 } } /// Get one block from a ChaCha stream. pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] { - let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }; + let mut chacha = ChaCha20 { + state: ChaCha20::expand(key, nonce), + output: [0u8; BLOCK_SIZE], + offset: 64, + }; let mut chacha_bytes = [0; 32]; chacha.process_in_place(&mut chacha_bytes); chacha_bytes @@ -159,9 +166,7 @@ mod real_chacha { /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as /// `src` in a second call will decrypt it. - pub fn encrypt_single_block( - key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8] - ) { + pub fn encrypt_single_block(key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]) { debug_assert_eq!(dest.len(), src.len()); debug_assert!(dest.len() <= 32); @@ -173,7 +178,7 @@ mod real_chacha { /// Same as `encrypt_single_block` only operates on a fixed-size input in-place. pub fn encrypt_single_block_in_place( - key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32] + key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32], ) { let block = ChaCha20::get_single_block(key, nonce); for i in 0..bytes.len() { @@ -185,7 +190,7 @@ mod real_chacha { let constant = match key.len() { 16 => b"expand 16-byte k", 32 => b"expand 32-byte k", - _ => unreachable!(), + _ => unreachable!(), }; ChaChaState { a: u32x4::from_bytes(&constant[0..16]), @@ -198,14 +203,14 @@ mod real_chacha { d: if nonce.len() == 16 { u32x4::from_bytes(&nonce[0..16]) } else if nonce.len() == 12 { - let mut nonce4 = [0; 4*4]; + let mut nonce4 = [0; 4 * 4]; nonce4[4..].copy_from_slice(nonce); u32x4::from_bytes(&nonce4) } else { - let mut nonce4 = [0; 4*4]; + let mut nonce4 = [0; 4 * 4]; nonce4[8..].copy_from_slice(nonce); u32x4::from_bytes(&nonce4) - } + }, } } @@ -313,15 +318,16 @@ mod fuzzy_chacha { } pub fn encrypt_single_block( - _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8] + _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8], ) { debug_assert_eq!(dest.len(), src.len()); debug_assert!(dest.len() <= 32); } pub fn encrypt_single_block_in_place( - _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32] - ) {} + _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32], + ) { + } pub fn process(&mut self, input: &[u8], output: &mut [u8]) { output.copy_from_slice(input); @@ -336,7 +342,7 @@ pub use self::fuzzy_chacha::ChaCha20; #[cfg(test)] mod test { use alloc::vec; - use alloc::vec::{Vec}; + use alloc::vec::Vec; use core::convert::TryInto; use core::iter::repeat; @@ -345,128 +351,103 @@ mod test { #[test] fn test_chacha20_256_tls_vectors() { struct TestVector { - key: [u8; 32], + key: [u8; 32], nonce: [u8; 8], keystream: Vec, } // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 - let test_vectors = vec!( - TestVector{ + let test_vectors = vec![ + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + keystream: vec![ + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53, + 0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36, + 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, + 0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, 0xb8, 0xf4, + 0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86, ], - nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], - keystream: vec!( - 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, - 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, - 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, - 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, - 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, - 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, - 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, - 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + keystream: vec![ + 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, 0xd7, 0x73, 0x6e, 0x7b, 0x20, + 0x8e, 0x3c, 0x96, 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60, 0x4f, 0x45, + 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41, 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, + 0xd2, 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c, 0x53, 0xd7, 0x92, 0xb1, + 0xc4, 0x3f, 0xea, 0x81, 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63, ], - nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], - keystream: vec!( - 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, - 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96, - 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60, - 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41, - 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2, - 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c, - 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81, - 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], + keystream: vec![ + 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, 0xe7, 0x86, 0xdc, 0x63, 0x97, + 0x3f, 0x65, 0x3a, 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13, 0x4f, 0xcb, + 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31, 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, + 0x45, 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b, 0x52, 0x77, 0x06, 0x2e, + 0xb7, 0xa0, 0x43, 0x3e, 0x44, 0x5f, 0x41, 0xe3, ], - nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ], - keystream: vec!( - 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, - 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a, - 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13, - 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31, - 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45, - 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b, - 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e, - 0x44, 0x5f, 0x41, 0xe3, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + nonce: [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + keystream: vec![ + 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, 0xf5, 0xcf, 0x35, 0xbd, 0x3d, + 0xd3, 0x3b, 0x80, 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, 0x33, 0x96, + 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, + 0x3c, 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, 0x5d, 0xdc, 0x49, 0x7a, + 0x0b, 0x46, 0x6e, 0x7d, 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b, ], - nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], - keystream: vec!( - 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, - 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80, - 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, - 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, - 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c, - 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, - 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d, - 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + ], + nonce: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + keystream: vec![ + 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, 0x82, 0x10, 0x5f, 0xfb, 0x64, + 0x0b, 0xb7, 0x75, 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93, 0xec, 0x01, + 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1, 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, + 0x41, 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69, 0x05, 0xd3, 0xbe, 0x59, + 0xea, 0x1c, 0x53, 0xf1, 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a, 0x38, + 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94, 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, + 0xde, 0x66, 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58, 0x89, 0xfb, 0x60, + 0xe8, 0x46, 0x29, 0xc9, 0xbd, 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56, + 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e, 0x09, 0xa7, 0xe7, 0x78, 0x49, + 0x2b, 0x56, 0x2e, 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7, 0x9d, 0xb9, + 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15, 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, + 0xc3, 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a, 0x97, 0xa5, 0xf5, 0x76, + 0xfe, 0x06, 0x40, 0x25, 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5, 0x07, + 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69, 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, + 0xc9, 0xc4, 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7, 0x0e, 0xaf, 0x46, + 0xf7, 0x6d, 0xad, 0x39, 0x79, 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a, + 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a, 0x94, 0xdf, 0x76, 0x28, 0xfe, + 0x4e, 0xaa, 0xf2, 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a, 0xd0, 0xf9, + 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09, 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, + 0x7a, 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9, ], - nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ], - keystream: vec!( - 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, - 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75, - 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93, - 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1, - 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41, - 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69, - 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1, - 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a, - 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94, - 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66, - 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58, - 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd, - 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56, - 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e, - 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e, - 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7, - 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15, - 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3, - 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a, - 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25, - 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5, - 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69, - 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4, - 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7, - 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79, - 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a, - 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a, - 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2, - 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a, - 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09, - 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a, - 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9, - ), }, - ); + ]; for tv in test_vectors.iter() { let mut c = ChaCha20::new(&tv.key, &tv.nonce); @@ -480,128 +461,103 @@ mod test { #[test] fn test_chacha20_256_tls_vectors_96_nonce() { struct TestVector { - key: [u8; 32], + key: [u8; 32], nonce: [u8; 12], keystream: Vec, } // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 - let test_vectors = vec!( - TestVector{ + let test_vectors = vec![ + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + keystream: vec![ + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53, + 0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36, + 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, + 0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, 0xb8, 0xf4, + 0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86, ], - nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], - keystream: vec!( - 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, - 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, - 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, - 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, - 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, - 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, - 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, - 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + keystream: vec![ + 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, 0xd7, 0x73, 0x6e, 0x7b, 0x20, + 0x8e, 0x3c, 0x96, 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60, 0x4f, 0x45, + 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41, 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, + 0xd2, 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c, 0x53, 0xd7, 0x92, 0xb1, + 0xc4, 0x3f, 0xea, 0x81, 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63, ], - nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], - keystream: vec!( - 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, - 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96, - 0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60, - 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41, - 0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2, - 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c, - 0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81, - 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], + keystream: vec![ + 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, 0xe7, 0x86, 0xdc, 0x63, 0x97, + 0x3f, 0x65, 0x3a, 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13, 0x4f, 0xcb, + 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31, 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, + 0x45, 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b, 0x52, 0x77, 0x06, 0x2e, + 0xb7, 0xa0, 0x43, 0x3e, 0x44, 0x5f, 0x41, 0xe3, ], - nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ], - keystream: vec!( - 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, - 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a, - 0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13, - 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31, - 0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45, - 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b, - 0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e, - 0x44, 0x5f, 0x41, 0xe3, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + keystream: vec![ + 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, 0xf5, 0xcf, 0x35, 0xbd, 0x3d, + 0xd3, 0x3b, 0x80, 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, 0x33, 0x96, + 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, + 0x3c, 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, 0x5d, 0xdc, 0x49, 0x7a, + 0x0b, 0x46, 0x6e, 0x7d, 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b, ], - nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], - keystream: vec!( - 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, - 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80, - 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, - 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, - 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c, - 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, - 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d, - 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b, - ), - }, TestVector{ + }, + TestVector { key: [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + ], + nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + keystream: vec![ + 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, 0x82, 0x10, 0x5f, 0xfb, 0x64, + 0x0b, 0xb7, 0x75, 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93, 0xec, 0x01, + 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1, 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, + 0x41, 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69, 0x05, 0xd3, 0xbe, 0x59, + 0xea, 0x1c, 0x53, 0xf1, 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a, 0x38, + 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94, 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, + 0xde, 0x66, 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58, 0x89, 0xfb, 0x60, + 0xe8, 0x46, 0x29, 0xc9, 0xbd, 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56, + 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e, 0x09, 0xa7, 0xe7, 0x78, 0x49, + 0x2b, 0x56, 0x2e, 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7, 0x9d, 0xb9, + 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15, 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, + 0xc3, 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a, 0x97, 0xa5, 0xf5, 0x76, + 0xfe, 0x06, 0x40, 0x25, 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5, 0x07, + 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69, 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, + 0xc9, 0xc4, 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7, 0x0e, 0xaf, 0x46, + 0xf7, 0x6d, 0xad, 0x39, 0x79, 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a, + 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a, 0x94, 0xdf, 0x76, 0x28, 0xfe, + 0x4e, 0xaa, 0xf2, 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a, 0xd0, 0xf9, + 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09, 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, + 0x7a, 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9, ], - nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ], - keystream: vec!( - 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, - 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75, - 0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93, - 0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1, - 0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41, - 0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69, - 0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1, - 0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a, - 0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94, - 0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66, - 0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58, - 0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd, - 0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56, - 0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e, - 0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e, - 0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7, - 0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15, - 0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3, - 0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a, - 0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25, - 0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5, - 0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69, - 0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4, - 0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7, - 0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79, - 0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a, - 0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a, - 0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2, - 0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a, - 0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09, - 0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a, - 0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9, - ), }, - ); + ]; for tv in test_vectors.iter() { let mut c = ChaCha20::new(&tv.key, &tv.nonce); @@ -618,13 +574,13 @@ mod test { // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4 // bytes. let key = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, ]; let nonce_16bytes = [ - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, ]; let counter_pos = &nonce_16bytes[..4]; let nonce_12bytes = &nonce_16bytes[4..]; @@ -642,14 +598,13 @@ mod test { #[test] fn encrypt_single_block() { let key = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, ]; let nonce = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, ]; let bytes = [1; 32]; @@ -665,14 +620,13 @@ mod test { #[test] fn encrypt_single_block_in_place() { let key = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, ]; let nonce = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, ]; let unencrypted_bytes = [1; 32]; let mut bytes = unencrypted_bytes; diff --git a/lightning/src/crypto/chacha20poly1305rfc.rs b/lightning/src/crypto/chacha20poly1305rfc.rs index 4ca974421c6..c0594b6ee98 100644 --- a/lightning/src/crypto/chacha20poly1305rfc.rs +++ b/lightning/src/crypto/chacha20poly1305rfc.rs @@ -13,8 +13,8 @@ #[cfg(not(fuzzing))] mod real_chachapoly { use super::super::chacha20::ChaCha20; - use super::super::poly1305::Poly1305; use super::super::fixed_time_eq; + use super::super::poly1305::Poly1305; #[derive(Clone, Copy)] pub struct ChaCha20Poly1305RFC { @@ -70,7 +70,9 @@ mod real_chachapoly { self.mac.raw_result(out_tag); } - pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) { + pub fn encrypt_full_message_in_place( + &mut self, input_output: &mut [u8], out_tag: &mut [u8], + ) { self.encrypt_in_place(input_output); self.finish_and_get_tag(out_tag); } @@ -98,7 +100,9 @@ mod real_chachapoly { /// Decrypt the `input`, checking the given `tag` prior to writing the decrypted contents /// into `output`. Note that, because `output` is not touched until the `tag` is checked, /// this decryption is *variable time*. - pub fn variable_time_decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> Result<(), ()> { + pub fn variable_time_decrypt( + &mut self, input: &[u8], output: &mut [u8], tag: &[u8], + ) -> Result<(), ()> { assert!(input.len() == output.len()); assert!(self.finished == false); @@ -111,7 +115,7 @@ mod real_chachapoly { self.mac.input(&self.aad_len.to_le_bytes()); self.mac.input(&(self.data_len as u64).to_le_bytes()); - let mut calc_tag = [0u8; 16]; + let mut calc_tag = [0u8; 16]; self.mac.raw_result(&mut calc_tag); if fixed_time_eq(&calc_tag, tag) { self.cipher.process(input, output); @@ -121,9 +125,15 @@ mod real_chachapoly { } } - pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> { + pub fn check_decrypt_in_place( + &mut self, input_output: &mut [u8], tag: &[u8], + ) -> Result<(), ()> { self.decrypt_in_place(input_output); - if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) } + if self.finish_and_check_tag(tag) { + Ok(()) + } else { + Err(()) + } } /// Decrypt in place, without checking the tag. Use `finish_and_check_tag` to check it @@ -146,7 +156,7 @@ mod real_chachapoly { self.mac.input(&self.aad_len.to_le_bytes()); self.mac.input(&(self.data_len as u64).to_le_bytes()); - let mut calc_tag = [0u8; 16]; + let mut calc_tag = [0u8; 16]; self.mac.raw_result(&mut calc_tag); if fixed_time_eq(&calc_tag, tag) { true @@ -177,10 +187,7 @@ mod fuzzy_chachapoly { let mut tag = [0; 16]; tag.copy_from_slice(&key[0..16]); - ChaCha20Poly1305RFC { - tag, - finished: false, - } + ChaCha20Poly1305RFC { tag, finished: false } } pub fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) { @@ -192,7 +199,9 @@ mod fuzzy_chachapoly { self.finished = true; } - pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) { + pub fn encrypt_full_message_in_place( + &mut self, input_output: &mut [u8], out_tag: &mut [u8], + ) { self.encrypt_in_place(input_output); self.finish_and_get_tag(out_tag); } @@ -207,19 +216,29 @@ mod fuzzy_chachapoly { self.finished = true; } - pub fn variable_time_decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> Result<(), ()> { + pub fn variable_time_decrypt( + &mut self, input: &[u8], output: &mut [u8], tag: &[u8], + ) -> Result<(), ()> { assert!(input.len() == output.len()); assert!(self.finished == false); - if tag[..] != self.tag[..] { return Err(()); } + if tag[..] != self.tag[..] { + return Err(()); + } output.copy_from_slice(input); self.finished = true; Ok(()) } - pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> { + pub fn check_decrypt_in_place( + &mut self, input_output: &mut [u8], tag: &[u8], + ) -> Result<(), ()> { self.decrypt_in_place(input_output); - if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) } + if self.finish_and_check_tag(tag) { + Ok(()) + } else { + Err(()) + } } pub(in super::super) fn decrypt_in_place(&mut self, _input: &mut [u8]) { @@ -227,7 +246,9 @@ mod fuzzy_chachapoly { } pub(in super::super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool { - if tag[..] != self.tag[..] { return false; } + if tag[..] != self.tag[..] { + return false; + } self.finished = true; true } diff --git a/lightning/src/crypto/mod.rs b/lightning/src/crypto/mod.rs index 6efd120667c..b733cb461e7 100644 --- a/lightning/src/crypto/mod.rs +++ b/lightning/src/crypto/mod.rs @@ -1,8 +1,8 @@ use bitcoin::hashes::cmp::fixed_time_eq; pub(crate) mod chacha20; +pub(crate) mod chacha20poly1305rfc; #[cfg(not(fuzzing))] pub(crate) mod poly1305; -pub(crate) mod chacha20poly1305rfc; pub(crate) mod streams; pub(crate) mod utils; diff --git a/lightning/src/crypto/poly1305.rs b/lightning/src/crypto/poly1305.rs index a1b9fbac516..a1908531685 100644 --- a/lightning/src/crypto/poly1305.rs +++ b/lightning/src/crypto/poly1305.rs @@ -12,25 +12,33 @@ use core::convert::TryInto; #[derive(Clone, Copy)] pub struct Poly1305 { - r : [u32; 5], - h : [u32; 5], - pad : [u32; 4], - leftover : usize, - buffer : [u8; 16], - finalized : bool, + r: [u32; 5], + h: [u32; 5], + pad: [u32; 4], + leftover: usize, + buffer: [u8; 16], + finalized: bool, } impl Poly1305 { pub fn new(key: &[u8]) -> Poly1305 { assert!(key.len() == 32); - let mut poly = Poly1305{ r: [0u32; 5], h: [0u32; 5], pad: [0u32; 4], leftover: 0, buffer: [0u8; 16], finalized: false }; + let mut poly = Poly1305 { + r: [0u32; 5], + h: [0u32; 5], + pad: [0u32; 4], + leftover: 0, + buffer: [0u8; 16], + finalized: false, + }; // r &= 0xffffffc0ffffffc0ffffffc0fffffff - poly.r[0] = (u32::from_le_bytes(key[ 0.. 4].try_into().expect("len is 4")) ) & 0x3ffffff; - poly.r[1] = (u32::from_le_bytes(key[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffff03; - poly.r[2] = (u32::from_le_bytes(key[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffc0ff; - poly.r[3] = (u32::from_le_bytes(key[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3f03fff; - poly.r[4] = (u32::from_le_bytes(key[12..16].try_into().expect("len is 4")) >> 8) & 0x00fffff; + poly.r[0] = (u32::from_le_bytes(key[0..4].try_into().expect("len is 4"))) & 0x3ffffff; + poly.r[1] = (u32::from_le_bytes(key[3..7].try_into().expect("len is 4")) >> 2) & 0x3ffff03; + poly.r[2] = (u32::from_le_bytes(key[6..10].try_into().expect("len is 4")) >> 4) & 0x3ffc0ff; + poly.r[3] = (u32::from_le_bytes(key[9..13].try_into().expect("len is 4")) >> 6) & 0x3f03fff; + poly.r[4] = + (u32::from_le_bytes(key[12..16].try_into().expect("len is 4")) >> 8) & 0x00fffff; poly.pad[0] = u32::from_le_bytes(key[16..20].try_into().expect("len is 4")); poly.pad[1] = u32::from_le_bytes(key[20..24].try_into().expect("len is 4")); @@ -41,7 +49,7 @@ impl Poly1305 { } fn block(&mut self, m: &[u8]) { - let hibit : u32 = if self.finalized { 0 } else { 1 << 24 }; + let hibit: u32 = if self.finalized { 0 } else { 1 << 24 }; let r0 = self.r[0]; let r1 = self.r[1]; @@ -61,27 +69,58 @@ impl Poly1305 { let mut h4 = self.h[4]; // h += m - h0 += (u32::from_le_bytes(m[ 0.. 4].try_into().expect("len is 4")) ) & 0x3ffffff; - h1 += (u32::from_le_bytes(m[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffffff; - h2 += (u32::from_le_bytes(m[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffffff; - h3 += (u32::from_le_bytes(m[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3ffffff; + h0 += (u32::from_le_bytes(m[0..4].try_into().expect("len is 4"))) & 0x3ffffff; + h1 += (u32::from_le_bytes(m[3..7].try_into().expect("len is 4")) >> 2) & 0x3ffffff; + h2 += (u32::from_le_bytes(m[6..10].try_into().expect("len is 4")) >> 4) & 0x3ffffff; + h3 += (u32::from_le_bytes(m[9..13].try_into().expect("len is 4")) >> 6) & 0x3ffffff; h4 += (u32::from_le_bytes(m[12..16].try_into().expect("len is 4")) >> 8) | hibit; // h *= r - let d0 = (h0 as u64 * r0 as u64) + (h1 as u64 * s4 as u64) + (h2 as u64 * s3 as u64) + (h3 as u64 * s2 as u64) + (h4 as u64 * s1 as u64); - let mut d1 = (h0 as u64 * r1 as u64) + (h1 as u64 * r0 as u64) + (h2 as u64 * s4 as u64) + (h3 as u64 * s3 as u64) + (h4 as u64 * s2 as u64); - let mut d2 = (h0 as u64 * r2 as u64) + (h1 as u64 * r1 as u64) + (h2 as u64 * r0 as u64) + (h3 as u64 * s4 as u64) + (h4 as u64 * s3 as u64); - let mut d3 = (h0 as u64 * r3 as u64) + (h1 as u64 * r2 as u64) + (h2 as u64 * r1 as u64) + (h3 as u64 * r0 as u64) + (h4 as u64 * s4 as u64); - let mut d4 = (h0 as u64 * r4 as u64) + (h1 as u64 * r3 as u64) + (h2 as u64 * r2 as u64) + (h3 as u64 * r1 as u64) + (h4 as u64 * r0 as u64); + let d0 = (h0 as u64 * r0 as u64) + + (h1 as u64 * s4 as u64) + + (h2 as u64 * s3 as u64) + + (h3 as u64 * s2 as u64) + + (h4 as u64 * s1 as u64); + let mut d1 = (h0 as u64 * r1 as u64) + + (h1 as u64 * r0 as u64) + + (h2 as u64 * s4 as u64) + + (h3 as u64 * s3 as u64) + + (h4 as u64 * s2 as u64); + let mut d2 = (h0 as u64 * r2 as u64) + + (h1 as u64 * r1 as u64) + + (h2 as u64 * r0 as u64) + + (h3 as u64 * s4 as u64) + + (h4 as u64 * s3 as u64); + let mut d3 = (h0 as u64 * r3 as u64) + + (h1 as u64 * r2 as u64) + + (h2 as u64 * r1 as u64) + + (h3 as u64 * r0 as u64) + + (h4 as u64 * s4 as u64); + let mut d4 = (h0 as u64 * r4 as u64) + + (h1 as u64 * r3 as u64) + + (h2 as u64 * r2 as u64) + + (h3 as u64 * r1 as u64) + + (h4 as u64 * r0 as u64); // (partial) h %= p - let mut c : u32; - c = (d0 >> 26) as u32; h0 = d0 as u32 & 0x3ffffff; - d1 += c as u64; c = (d1 >> 26) as u32; h1 = d1 as u32 & 0x3ffffff; - d2 += c as u64; c = (d2 >> 26) as u32; h2 = d2 as u32 & 0x3ffffff; - d3 += c as u64; c = (d3 >> 26) as u32; h3 = d3 as u32 & 0x3ffffff; - d4 += c as u64; c = (d4 >> 26) as u32; h4 = d4 as u32 & 0x3ffffff; - h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; + let mut c: u32; + c = (d0 >> 26) as u32; + h0 = d0 as u32 & 0x3ffffff; + d1 += c as u64; + c = (d1 >> 26) as u32; + h1 = d1 as u32 & 0x3ffffff; + d2 += c as u64; + c = (d2 >> 26) as u32; + h2 = d2 as u32 & 0x3ffffff; + d3 += c as u64; + c = (d3 >> 26) as u32; + h3 = d3 as u32 & 0x3ffffff; + d4 += c as u64; + c = (d4 >> 26) as u32; + h4 = d4 as u32 & 0x3ffffff; + h0 += c * 5; + c = h0 >> 26; + h0 = h0 & 0x3ffffff; h1 += c; self.h[0] = h0; @@ -94,7 +133,7 @@ impl Poly1305 { pub fn finish(&mut self) { if self.leftover > 0 { self.buffer[self.leftover] = 1; - for i in self.leftover+1..16 { + for i in self.leftover + 1..16 { self.buffer[i] = 0; } self.finalized = true; @@ -109,19 +148,36 @@ impl Poly1305 { let mut h3 = self.h[3]; let mut h4 = self.h[4]; - let mut c : u32; - c = h1 >> 26; h1 = h1 & 0x3ffffff; - h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; - h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; - h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; - h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; - h1 += c; + let mut c: u32; + c = h1 >> 26; + h1 = h1 & 0x3ffffff; + h2 += c; + c = h2 >> 26; + h2 = h2 & 0x3ffffff; + h3 += c; + c = h3 >> 26; + h3 = h3 & 0x3ffffff; + h4 += c; + c = h4 >> 26; + h4 = h4 & 0x3ffffff; + h0 += c * 5; + c = h0 >> 26; + h0 = h0 & 0x3ffffff; + h1 += c; // compute h + -p - let mut g0 = h0.wrapping_add(5); c = g0 >> 26; g0 &= 0x3ffffff; - let mut g1 = h1.wrapping_add(c); c = g1 >> 26; g1 &= 0x3ffffff; - let mut g2 = h2.wrapping_add(c); c = g2 >> 26; g2 &= 0x3ffffff; - let mut g3 = h3.wrapping_add(c); c = g3 >> 26; g3 &= 0x3ffffff; + let mut g0 = h0.wrapping_add(5); + c = g0 >> 26; + g0 &= 0x3ffffff; + let mut g1 = h1.wrapping_add(c); + c = g1 >> 26; + g1 &= 0x3ffffff; + let mut g2 = h2.wrapping_add(c); + c = g2 >> 26; + g2 &= 0x3ffffff; + let mut g3 = h3.wrapping_add(c); + c = g3 >> 26; + g3 &= 0x3ffffff; let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26); // select h if h < p, or h + -p if h >= p @@ -139,17 +195,21 @@ impl Poly1305 { h4 = (h4 & mask) | g4; // h = h % (2^128) - h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; - h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; + h0 = ((h0) | (h1 << 26)) & 0xffffffff; + h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; - h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; + h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; // h = mac = (h + pad) % (2^128) - let mut f : u64; - f = h0 as u64 + self.pad[0] as u64 ; h0 = f as u32; - f = h1 as u64 + self.pad[1] as u64 + (f >> 32); h1 = f as u32; - f = h2 as u64 + self.pad[2] as u64 + (f >> 32); h2 = f as u32; - f = h3 as u64 + self.pad[3] as u64 + (f >> 32); h3 = f as u32; + let mut f: u64; + f = h0 as u64 + self.pad[0] as u64; + h0 = f as u32; + f = h1 as u64 + self.pad[1] as u64 + (f >> 32); + h1 = f as u32; + f = h2 as u64 + self.pad[2] as u64 + (f >> 32); + h2 = f as u32; + f = h3 as u64 + self.pad[3] as u64 + (f >> 32); + h3 = f as u32; self.h[0] = h0; self.h[1] = h1; @@ -164,7 +224,7 @@ impl Poly1305 { if self.leftover > 0 { let want = min(16 - self.leftover, m.len()); for i in 0..want { - self.buffer[self.leftover+i] = m[i]; + self.buffer[self.leftover + i] = m[i]; } m = &m[want..]; self.leftover += want; @@ -193,7 +253,7 @@ impl Poly1305 { pub fn raw_result(&mut self, output: &mut [u8]) { assert!(output.len() >= 16); - if !self.finalized{ + if !self.finalized { self.finish(); } output[0..4].copy_from_slice(&self.h[0].to_le_bytes()); @@ -205,8 +265,8 @@ impl Poly1305 { #[cfg(test)] mod test { - use core::iter::repeat; use alloc::vec::Vec; + use core::iter::repeat; use super::Poly1305; @@ -219,35 +279,27 @@ mod test { #[test] fn test_nacl_vector() { let key = [ - 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91, - 0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25, - 0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65, - 0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80, + 0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91, 0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, + 0x3c, 0x25, 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65, 0x2d, 0x65, 0x1f, 0xa4, + 0xc8, 0xcf, 0xf8, 0x80, ]; let msg = [ - 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73, - 0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce, - 0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4, - 0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a, - 0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b, - 0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72, - 0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2, - 0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38, - 0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a, - 0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae, - 0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea, - 0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda, - 0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde, - 0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3, - 0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6, - 0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74, - 0xe3,0x55,0xa5, + 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, + 0x76, 0xce, 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, 0x47, 0x6f, 0xb8, 0xc5, + 0x31, 0xa1, 0x18, 0x6a, 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, 0x4d, 0xa7, + 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72, 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, + 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, + 0xcc, 0x8a, 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae, 0x90, 0x22, 0x43, 0x68, + 0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda, 0x99, 0x83, + 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, + 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6, 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, + 0x5a, 0x74, 0xe3, 0x55, 0xa5, ]; let expected = [ - 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5, - 0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9, + 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, + 0x05, 0xd9, ]; let mut mac = [0u8; 16]; @@ -273,20 +325,19 @@ mod test { #[test] fn donna_self_test() { let wrap_key = [ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, ]; let wrap_msg = [ - 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, ]; let wrap_mac = [ - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, ]; let mut mac = [0u8; 16]; @@ -294,15 +345,14 @@ mod test { assert_eq!(&mac[..], &wrap_mac[..]); let total_key = [ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff, - 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, ]; let total_mac = [ - 0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd, - 0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39, + 0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd, 0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, + 0x3d, 0x39, ]; let mut tpoly = Poly1305::new(&total_key); @@ -323,17 +373,17 @@ mod test { let key = b"this is 32-byte key for Poly1305"; let msg = [0u8; 32]; let expected = [ - 0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, - 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07, + 0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, + 0x03, 0x07, ]; let mut mac = [0u8; 16]; poly1305(key, &msg, &mut mac); assert_eq!(&mac[..], &expected[..]); let msg = b"Hello world!"; - let expected= [ - 0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, - 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0, + let expected = [ + 0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, + 0xb2, 0xf0, ]; poly1305(key, msg, &mut mac); assert_eq!(&mac[..], &expected[..]); diff --git a/lightning/src/crypto/streams.rs b/lightning/src/crypto/streams.rs index 14921a38612..a5b194f48fa 100644 --- a/lightning/src/crypto/streams.rs +++ b/lightning/src/crypto/streams.rs @@ -1,9 +1,11 @@ use crate::crypto::chacha20::ChaCha20; use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC; -use crate::ln::msgs::DecodeError; -use crate::util::ser::{FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer}; use crate::io::{self, Read, Write}; +use crate::ln::msgs::DecodeError; +use crate::util::ser::{ + FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer, +}; pub(crate) struct ChaChaReader<'a, R: io::Read> { pub chacha: &'a mut ChaCha20, @@ -58,7 +60,9 @@ impl LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter { // LengthRead must be used instead of std::io::Read because we need the total length to separate // out the tag at the end. fn read(mut r: &mut R, secret: [u8; 32]) -> Result { - if r.total_bytes() < 16 { return Err(DecodeError::InvalidValue) } + if r.total_bytes() < 16 { + return Err(DecodeError::InvalidValue); + } let mut chacha = ChaCha20Poly1305RFC::new(&secret, &[0; 12], &[]); let decrypted_len = r.total_bytes() - 16; @@ -70,14 +74,13 @@ impl LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter { let mut tag = [0 as u8; 16]; r.read_exact(&mut tag)?; if !chacha.finish_and_check_tag(&tag) { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } Ok(Self { readable }) } } - /// Enables simultaneously reading and decrypting a ChaCha20Poly1305RFC stream from a std::io::Read. struct ChaChaPolyReader<'a, R: Read> { pub chacha: &'a mut ChaCha20Poly1305RFC, @@ -111,7 +114,9 @@ impl<'a, W: Writer> Writer for ChaChaPolyWriter<'a, W> { let mut src_idx = 0; while src_idx < src.len() { let mut write_buffer = [0; 8192]; - let bytes_written = (&mut write_buffer[..]).write(&src[src_idx..]).expect("In-memory writes can't fail"); + let bytes_written = (&mut write_buffer[..]) + .write(&src[src_idx..]) + .expect("In-memory writes can't fail"); self.chacha.encrypt_in_place(&mut write_buffer[..bytes_written]); self.write.write_all(&write_buffer[..bytes_written])?; src_idx += bytes_written; @@ -120,11 +125,10 @@ impl<'a, W: Writer> Writer for ChaChaPolyWriter<'a, W> { } } - #[cfg(test)] mod tests { - use crate::ln::msgs::DecodeError; use super::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter}; + use crate::ln::msgs::DecodeError; use crate::util::ser::{self, FixedLengthReader, LengthReadableArgs, Writeable}; // Used for for testing various lengths of serialization. @@ -155,34 +159,26 @@ mod tests { // Now deserialize the object back and make sure it matches the original. let mut rd = FixedLengthReader::new(encrypted_writeable, writeable_len); - let read_adapter = >::read(&mut rd, rho).unwrap(); + let read_adapter = + >::read(&mut rd, rho).unwrap(); assert_eq!($obj, read_adapter.readable); }; } // Try a big object that will require multiple write buffers. - let big_writeable = TestWriteable { - field1: vec![43], - field2: vec![44; 4192], - field3: vec![45; 4192 + 1], - }; + let big_writeable = + TestWriteable { field1: vec![43], field2: vec![44; 4192], field3: vec![45; 4192 + 1] }; check_object_read_write!(big_writeable); // Try a small object that fits into one write buffer. - let small_writeable = TestWriteable { - field1: vec![43], - field2: vec![44], - field3: vec![45], - }; + let small_writeable = + TestWriteable { field1: vec![43], field2: vec![44], field3: vec![45] }; check_object_read_write!(small_writeable); } fn do_chacha_stream_adapters_ser_macros() -> Result<(), DecodeError> { - let writeable = TestWriteable { - field1: vec![43], - field2: vec![44; 4192], - field3: vec![45; 4192 + 1], - }; + let writeable = + TestWriteable { field1: vec![43], field2: vec![44; 4192], field3: vec![45; 4192 + 1] }; // First, serialize the object into a TLV stream, encrypted with ChaCha20Poly1305. let rho = [42; 32]; diff --git a/lightning/src/crypto/utils.rs b/lightning/src/crypto/utils.rs index 98963c7c2bd..6fb8627c81b 100644 --- a/lightning/src/crypto/utils.rs +++ b/lightning/src/crypto/utils.rs @@ -1,7 +1,7 @@ -use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature, Signing}; +use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::secp256k1::{ecdsa::Signature, Message, Secp256k1, SecretKey, Signing}; use crate::sign::EntropySource; @@ -43,14 +43,16 @@ macro_rules! hkdf_extract_expand { let k5 = Hmac::from_engine(hmac).to_byte_array(); (k1, k2, k3, k4, k5) - }} + }}; } pub fn hkdf_extract_expand_twice(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) { hkdf_extract_expand!(salt, ikm, 2) } -pub fn hkdf_extract_expand_5x(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32]) { +pub fn hkdf_extract_expand_5x( + salt: &[u8], ikm: &[u8], +) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32]) { hkdf_extract_expand!(salt, ikm, 5) } @@ -66,8 +68,11 @@ pub fn sign(ctx: &Secp256k1, msg: &Message, sk: &SecretKey) -> Si #[inline] #[allow(unused_variables)] pub fn sign_with_aux_rand( - ctx: &Secp256k1, msg: &Message, sk: &SecretKey, entropy_source: &ES -) -> Signature where ES::Target: EntropySource { + ctx: &Secp256k1, msg: &Message, sk: &SecretKey, entropy_source: &ES, +) -> Signature +where + ES::Target: EntropySource, +{ #[cfg(feature = "grind_signatures")] let sig = loop { let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes()); diff --git a/lightning/src/events/bump_transaction.rs b/lightning/src/events/bump_transaction.rs index 1b019ba349e..c4788a5c2dc 100644 --- a/lightning/src/events/bump_transaction.rs +++ b/lightning/src/events/bump_transaction.rs @@ -14,31 +14,33 @@ 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::chan_utils; use crate::ln::chan_utils::{ - ANCHOR_INPUT_WITNESS_WEIGHT, HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT, - HTLC_TIMEOUT_INPUT_ANCHOR_WITNESS_WEIGHT, HTLCOutputInCommitment + 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::prelude::*; +use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; use crate::sign::{ - ChannelDerivationParameters, HTLCDescriptor, SignerProvider, P2WPKH_WITNESS_WEIGHT + ChannelDerivationParameters, HTLCDescriptor, SignerProvider, P2WPKH_WITNESS_WEIGHT, }; -use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; use crate::sync::Mutex; use crate::util::logger::Logger; -use bitcoin::{OutPoint, PubkeyHash, Sequence, ScriptBuf, Transaction, TxIn, TxOut, Witness, WPubkeyHash}; use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR; use bitcoin::blockdata::locktime::absolute::LockTime; use bitcoin::consensus::Encodable; use bitcoin::psbt::PartiallySignedTransaction; use bitcoin::secp256k1; -use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::ecdsa::Signature; +use bitcoin::secp256k1::Secp256k1; +use bitcoin::{ + OutPoint, PubkeyHash, ScriptBuf, Sequence, Transaction, TxIn, TxOut, WPubkeyHash, Witness, +}; const EMPTY_SCRIPT_SIG_WEIGHT: u64 = 1 /* empty script_sig */ * WITNESS_SCALE_FACTOR as u64; @@ -79,27 +81,35 @@ impl AnchorDescriptor { /// Returns the witness script of the anchor output in the commitment transaction. pub fn witness_script(&self) -> ScriptBuf { - let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); + let channel_params = + self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); chan_utils::get_anchor_redeemscript(&channel_params.broadcaster_pubkeys().funding_pubkey) } /// Returns the fully signed witness required to spend the anchor output in the commitment /// transaction. pub fn tx_input_witness(&self, signature: &Signature) -> Witness { - let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); - chan_utils::build_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_anchor_input_witness( + &channel_params.broadcaster_pubkeys().funding_pubkey, + signature, + ) } /// Derives the channel signer required to sign the anchor input. - pub fn derive_channel_signer(&self, signer_provider: &SP) -> S + pub fn derive_channel_signer( + &self, signer_provider: &SP, + ) -> S where - SP::Target: SignerProvider + SP::Target: SignerProvider, { let mut signer = signer_provider.derive_channel_signer( self.channel_derivation_parameters.value_satoshis, self.channel_derivation_parameters.keys_id, ); - signer.provide_channel_parameters(&self.channel_derivation_parameters.transaction_parameters); + signer + .provide_channel_parameters(&self.channel_derivation_parameters.transaction_parameters); signer } } @@ -256,11 +266,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 */ } } @@ -274,9 +281,12 @@ impl Utxo { outpoint, output: TxOut { value, - script_pubkey: ScriptBuf::new_p2sh(&ScriptBuf::new_v0_p2wpkh(pubkey_hash).script_hash()), + script_pubkey: ScriptBuf::new_p2sh( + &ScriptBuf::new_v0_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, } } @@ -284,10 +294,7 @@ impl Utxo { pub fn new_v0_p2wpkh(outpoint: OutPoint, value: u64, pubkey_hash: &WPubkeyHash) -> Self { Self { outpoint, - output: TxOut { - value, - script_pubkey: ScriptBuf::new_v0_p2wpkh(pubkey_hash), - }, + output: TxOut { value, script_pubkey: ScriptBuf::new_v0_p2wpkh(pubkey_hash) }, satisfaction_weight: EMPTY_SCRIPT_SIG_WEIGHT + P2WPKH_WITNESS_WEIGHT, } } @@ -373,7 +380,7 @@ pub trait WalletSource { pub struct Wallet where W::Target: WalletSource, - L::Target: Logger + L::Target: Logger, { source: W, logger: L, @@ -386,7 +393,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`]. @@ -408,32 +415,45 @@ where preexisting_tx_weight: u64, input_amount_sat: u64, target_amount_sat: u64, ) -> 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 = 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 = 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 = fee_for_weight(target_feerate_sat_per_1000_weight, preexisting_tx_weight); + let mut total_fees = + 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 { @@ -444,8 +464,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 { @@ -457,8 +480,8 @@ 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 = remaining_amount.saturating_sub(change_output_fee); let change_output = if change_output_amount < change_script.dust_value().to_sat() { @@ -468,17 +491,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], @@ -487,22 +507,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: u64 = 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) @@ -546,13 +576,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. @@ -573,10 +597,7 @@ where // considered standard. We choose to go with an empty OP_RETURN as it is the cheapest // way to include a dummy output. log_debug!(self.logger, "Including dummy OP_RETURN output since an output is needed and a change output was not provided"); - tx.output.push(TxOut { - value: 0, - script_pubkey: ScriptBuf::new_op_return(&[]), - }); + tx.output.push(TxOut { value: 0, script_pubkey: ScriptBuf::new_op_return(&[]) }); } } @@ -585,7 +606,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 tranasction's fee and weight are part of @@ -595,15 +617,20 @@ where let must_spend = vec![Input { outpoint: anchor_descriptor.outpoint, previous_utxo: anchor_utxo, - satisfaction_weight: commitment_tx.weight().to_wu() + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT, + satisfaction_weight: commitment_tx.weight().to_wu() + + ANCHOR_INPUT_WITNESS_WEIGHT + + EMPTY_SCRIPT_SIG_WEIGHT, }]; #[cfg(debug_assertions)] - 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, "Peforming 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 { @@ -614,11 +641,16 @@ where }; #[cfg(debug_assertions)] - 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_satisfaction_weight = ANCHOR_INPUT_WITNESS_WEIGHT + + EMPTY_SCRIPT_SIG_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).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.txid(); @@ -639,7 +671,8 @@ where debug_assert_eq!(anchor_psbt.unsigned_tx.output.len(), 1); #[cfg(debug_assertions)] - 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); log_debug!(self.logger, "Signing anchor transaction {}", anchor_txid); anchor_tx = self.utxo_source.sign_psbt(anchor_psbt)?; @@ -648,27 +681,39 @@ where let anchor_sig = signer.sign_holder_anchor_input(&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 + 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); + assert!( + expected_signed_tx_weight >= signed_tx_weight + && expected_signed_tx_weight - (expected_signed_tx_weight / 100) + <= signed_tx_weight + ); - let expected_package_fee = fee_for_weight(package_target_feerate_sat_per_1000_weight, - signed_tx_weight + commitment_tx.weight().to_wu()); - let package_fee = total_input_amount - - anchor_tx.output.iter().map(|output| output.value).sum::(); + let expected_package_fee = fee_for_weight( + package_target_feerate_sat_per_1000_weight, + signed_tx_weight + commitment_tx.weight().to_wu(), + ); + let package_fee = total_input_amount + - anchor_tx.output.iter().map(|output| output.value).sum::(); // Our fee should be within a 5% error margin of the expected fee based on the // feerate and transaction weight and we should never pay less than required. let fee_error_margin = expected_package_fee * 5 / 100; - assert!(package_fee >= expected_package_fee && - package_fee - fee_error_margin <= expected_package_fee); + assert!( + package_fee >= expected_package_fee + && package_fee - fee_error_margin <= expected_package_fee + ); } - log_info!(self.logger, "Broadcasting anchor transaction {} to bump channel close with txid {}", - anchor_txid, commitment_tx.txid()); + log_info!( + self.logger, + "Broadcasting anchor transaction {} to bump channel close with txid {}", + anchor_txid, + commitment_tx.txid() + ); self.broadcaster.broadcast_transactions(&[&commitment_tx, &anchor_tx]); Ok(()) } @@ -679,48 +724,55 @@ where &self, claim_id: ClaimId, target_feerate_sat_per_1000_weight: u32, htlc_descriptors: &[HTLCDescriptor], tx_lock_time: LockTime, ) -> Result<(), ()> { - let mut htlc_tx = Transaction { - version: 2, - lock_time: tx_lock_time, - input: vec![], - output: vec![], - }; + let mut htlc_tx = + Transaction { version: 2, lock_time: tx_lock_time, input: vec![], output: vec![] }; let mut must_spend = Vec::with_capacity(htlc_descriptors.len()); for htlc_descriptor in htlc_descriptors { let htlc_input = htlc_descriptor.unsigned_tx_input(); 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, "Peforming coin selection for HTLC transaction targeting {} sat/kW", - target_feerate_sat_per_1000_weight); + log_debug!( + self.logger, + "Peforming 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).sum::(); + let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).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).sum::(); + let total_input_amount = must_spend_amount + + coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum::(); self.process_coin_selection(&mut htlc_tx, &coin_selection); @@ -728,7 +780,10 @@ where let mut htlc_psbt = PartiallySignedTransaction::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 @@ -742,36 +797,47 @@ 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.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 signer = signers.entry(htlc_descriptor.channel_derivation_parameters.keys_id) + let signer = signers + .entry(htlc_descriptor.channel_derivation_parameters.keys_id) .or_insert_with(|| htlc_descriptor.derive_channel_signer(&self.signer_provider)); - 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); + 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).sum::(); + 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).sum::(); // Our fee should be within a 5% error margin of the expected fee based on the // feerate and transaction weight and we should never pay less than required. let fee_error_margin = expected_signed_tx_fee * 5 / 100; - assert!(signed_tx_fee >= expected_signed_tx_fee && - signed_tx_fee - fee_error_margin <= expected_signed_tx_fee); + assert!( + signed_tx_fee >= expected_signed_tx_fee + && signed_tx_fee - fee_error_margin <= expected_signed_tx_fee + ); } log_info!(self.logger, "Broadcasting {}", log_tx!(htlc_tx)); @@ -783,31 +849,58 @@ 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.txid()); + log_info!( + self.logger, + "Handling channel close bump (claim_id = {}, commitment_txid = {})", + log_bytes!(claim_id.0), + commitment_tx.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.txid()); + log_error!( + self.logger, + "Failed bumping commitment transaction fee for {}", + commitment_tx.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 + ); } - } + }, } } } diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index 77f6937c545..c0f53e3ba79 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -18,30 +18,33 @@ pub mod bump_transaction; pub use bump_transaction::BumpTransactionEvent; -use crate::sign::SpendableOutputDescriptor; -use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; +use crate::chain::transaction; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; +use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs; -use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret}; -use crate::chain::transaction; +use crate::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use crate::routing::gossip::NetworkUpdate; +use crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters}; +use crate::sign::SpendableOutputDescriptor; 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 crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters}; -use bitcoin::{Transaction, OutPoint}; +use crate::io; +use crate::prelude::*; +use crate::sync::Arc; use bitcoin::blockdata::locktime::absolute::LockTime; use bitcoin::blockdata::script::ScriptBuf; -use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; use bitcoin::secp256k1::PublicKey; -use crate::io; -use crate::prelude::*; -use core::time::Duration; +use bitcoin::{OutPoint, Transaction}; use core::ops::Deref; -use crate::sync::Arc; +use core::time::Duration; /// 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. @@ -229,18 +232,36 @@ impl core::fmt::Display for ClosureReason { ClosureReason::CounterpartyForceClosed { peer_msg } => { f.write_fmt(format_args!("counterparty force-closed with message: {}", peer_msg)) }, - ClosureReason::HolderForceClosed => f.write_str("user manually force-closed the channel"), - ClosureReason::CooperativeClosure => f.write_str("the channel was cooperatively closed"), - 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::HolderForceClosed => { + f.write_str("user manually force-closed the channel") + }, + ClosureReason::CooperativeClosure => { + f.write_str("the channel was cooperatively closed") + }, + 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") + }, } } } @@ -280,7 +301,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, }, /// Failure scenario where an HTLC may have been forwarded to be intended for us, /// but is invalid for some reason, so we reject it. @@ -294,7 +315,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, }, } @@ -319,9 +340,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, @@ -680,9 +699,9 @@ pub enum Event { /// If this is `Some`, then the corresponding channel should be avoided when the payment is /// retried. May be `None` for older [`Event`] serializations. short_channel_id: Option, -#[cfg(test)] + #[cfg(test)] error_code: Option, -#[cfg(test)] + #[cfg(test)] error_data: Option>, }, /// Indicates that a probe payment we sent returned successful, i.e., only failed at the destination. @@ -900,7 +919,7 @@ pub enum Event { /// The channel_id of the channel which has been closed. channel_id: ChannelId, /// The full transaction received from the user - transaction: Transaction + transaction: Transaction, }, /// Indicates a request to open a new channel by a peer. /// @@ -992,24 +1011,37 @@ 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 + &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, } => { 1u8.write(writer)?; let mut payment_secret = None; let payment_preimage; match &purpose { - PaymentPurpose::InvoicePayment { payment_preimage: preimage, payment_secret: secret } => { + PaymentPurpose::InvoicePayment { + payment_preimage: preimage, + payment_secret: secret, + } => { payment_secret = Some(secret); payment_preimage = *preimage; }, 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), @@ -1024,7 +1056,12 @@ impl Writeable for Event { (10, skimmed_fee_opt, option), }); }, - &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => { + &Event::PaymentSent { + ref payment_id, + ref payment_preimage, + ref payment_hash, + ref fee_paid_msat, + } => { 2u8.write(writer)?; write_tlv_fields!(writer, { (0, payment_preimage, required), @@ -1034,8 +1071,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(test)] ref error_code, #[cfg(test)] @@ -1071,7 +1112,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, { @@ -1081,10 +1128,13 @@ impl Writeable for Event { (6, inbound_amount_msat, required), (8, expected_outbound_amount_msat, required), }); - } + }, &Event::PaymentForwarded { - fee_earned_msat, prev_channel_id, claim_from_onchain_tx, - next_channel_id, outbound_amount_forwarded_msat + fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, } => { 7u8.write(writer)?; write_tlv_fields!(writer, { @@ -1095,8 +1145,13 @@ impl Writeable for Event { (5, outbound_amount_forwarded_msat, 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, } => { 9u8.write(writer)?; // `user_channel_id` used to be a single u64 value. In order to remain backwards @@ -1143,7 +1198,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 } => { + &Event::PaymentClaimed { + ref payment_hash, + ref amount_msat, + ref purpose, + ref receiver_node_id, + ref htlcs, + ref sender_intended_total_msat, + } => { 19u8.write(writer)?; write_tlv_fields!(writer, { (0, payment_hash, required), @@ -1163,7 +1225,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), @@ -1180,17 +1247,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), @@ -1199,7 +1271,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 } => { + &Event::ChannelPending { + ref channel_id, + ref user_channel_id, + ref former_temporary_channel_id, + ref counterparty_node_id, + ref funding_txo, + } => { 31u8.write(writer)?; write_tlv_fields!(writer, { (0, channel_id, required), @@ -1260,16 +1338,19 @@ impl MaybeReadable for Event { let purpose = match payment_secret { Some(secret) => PaymentPurpose::InvoicePayment { payment_preimage, - payment_secret: secret + payment_secret: secret, + }, + None if payment_preimage.is_some() => { + PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()) }, - 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, @@ -1292,7 +1373,9 @@ impl MaybeReadable for Event { (5, fee_paid_msat, 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, @@ -1329,7 +1412,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, @@ -1361,7 +1445,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, { @@ -1372,7 +1457,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, @@ -1397,8 +1482,11 @@ impl MaybeReadable for Event { (5, outbound_amount_forwarded_msat, option), }); Ok(Some(Event::PaymentForwarded { - fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, - outbound_amount_forwarded_msat + fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, })) }; f() @@ -1425,23 +1513,34 @@ 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 })) + 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, + })) }; f() }, 11u8 => { let f = || { let mut channel_id = ChannelId::new_zero(); - let mut transaction = Transaction{ version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + let mut transaction = Transaction { + version: 2, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }; read_tlv_fields!(reader, { (0, channel_id, required), (2, transaction, required), }); - Ok(Some(Event::DiscardFunding { channel_id, transaction } )) + Ok(Some(Event::DiscardFunding { channel_id, transaction })) }; f() }, @@ -1471,11 +1570,7 @@ impl MaybeReadable for Event { (1, reason, upgradable_option), (2, payment_hash, required), }); - Ok(Some(Event::PaymentFailed { - payment_id, - payment_hash, - reason, - })) + Ok(Some(Event::PaymentFailed { payment_id, payment_hash, reason })) }; f() }, @@ -1554,7 +1649,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() @@ -1577,7 +1675,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() @@ -1602,7 +1700,7 @@ impl MaybeReadable for Event { user_channel_id, former_temporary_channel_id, counterparty_node_id: counterparty_node_id.0.unwrap(), - funding_txo: funding_txo.0.unwrap() + funding_txo: funding_txo.0.unwrap(), })) }; f() @@ -1612,9 +1710,7 @@ impl MaybeReadable for Event { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), }); - Ok(Some(Event::InvoiceRequestFailed { - payment_id: payment_id.0.unwrap(), - })) + Ok(Some(Event::InvoiceRequestFailed { payment_id: payment_id.0.unwrap() })) }; f() }, @@ -1631,10 +1727,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), } } } @@ -1882,7 +1979,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: msgs::ErrorAction + action: msgs::ErrorAction, }, /// Query a peer for channels with funding transaction UTXOs in a block range. SendChannelRangeQuery { @@ -1964,7 +2061,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; } /// A trait implemented for objects handling events from [`EventsProvider`]. @@ -1979,7 +2078,10 @@ pub trait EventHandler { fn handle_event(&self, event: Event); } -impl EventHandler for F where F: Fn(Event) { +impl EventHandler for F +where + F: Fn(Event), +{ fn handle_event(&self, event: Event) { self(event) } diff --git a/lightning/src/lib.rs b/lightning/src/lib.rs index 160f632415b..34df8a9c76a 100644 --- a/lightning/src/lib.rs +++ b/lightning/src/lib.rs @@ -39,18 +39,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(not(any(feature = "std", feature = "no-std")))] @@ -66,32 +62,36 @@ extern crate bitcoin; extern crate core; extern crate hex; -#[cfg(any(test, feature = "_test_utils"))] extern crate regex; +#[cfg(any(test, feature = "_test_utils"))] +extern crate regex; -#[cfg(not(feature = "std"))] extern crate core2; -#[cfg(not(feature = "std"))] extern crate libm; +#[cfg(not(feature = "std"))] +extern crate core2; +#[cfg(not(feature = "std"))] +extern crate libm; -#[cfg(ldk_bench)] extern crate criterion; +#[cfg(ldk_bench)] +extern crate criterion; #[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; -#[cfg(feature = "std")] -/// Re-export of either `core2::io` or `std::io`, depending on the `std` feature flag. -pub use std::io; #[cfg(not(feature = "std"))] /// Re-export of either `core2::io` or `std::io`, depending on the `std` feature flag. pub use core2::io; +#[cfg(feature = "std")] +/// Re-export of either `core2::io` or `std::io`, depending on the `std` feature flag. +pub use std::io; #[cfg(not(feature = "std"))] mod io_extras { @@ -120,7 +120,7 @@ mod io_extras { } pub fn copy(reader: &mut R, writer: &mut W) -> Result - where + where R: Read, W: Write, { @@ -130,7 +130,10 @@ 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()), }; @@ -168,11 +171,11 @@ mod prelude { #[cfg(feature = "hashbrown")] extern crate hashbrown; - pub use alloc::{vec, vec::Vec, string::String, collections::VecDeque, boxed::Box}; - #[cfg(not(feature = "hashbrown"))] - pub use std::collections::{HashMap, HashSet, hash_map}; #[cfg(feature = "hashbrown")] - pub use self::hashbrown::{HashMap, HashSet, hash_map}; + pub use self::hashbrown::{hash_map, HashMap, HashSet}; + pub use alloc::{boxed::Box, collections::VecDeque, string::String, vec, vec::Vec}; + #[cfg(not(feature = "hashbrown"))] + pub use std::collections::{hash_map, HashMap, HashSet}; 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 0f51bea0d36..ffef593354c 100644 --- a/lightning/src/ln/async_signer_tests.rs +++ b/lightning/src/ln/async_signer_tests.rs @@ -11,9 +11,9 @@ //! properly with a signer implementation that asynchronously derives signatures. use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider}; +use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; use crate::ln::functional_test_utils::*; use crate::ln::msgs::ChannelMessageHandler; -use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; #[test] fn test_async_commitment_signature_for_funding_created() { @@ -23,22 +23,48 @@ fn test_async_commitment_signature_for_funding_created() { 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); - nodes[0].set_channel_signer_available(&nodes[1].node.get_our_node_id(), &temporary_channel_id, false); - 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].set_channel_signer_available( + &nodes[1].node.get_our_node_id(), + &temporary_channel_id, + false, + ); + 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()); @@ -54,13 +80,21 @@ fn test_async_commitment_signature_for_funding_created() { nodes[0].set_channel_signer_available(&nodes[1].node.get_our_node_id(), &chan_id, true); 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()); @@ -74,25 +108,55 @@ fn test_async_commitment_signature_for_funding_signed() { 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`... - nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &temporary_channel_id, false); + nodes[1].set_channel_signer_available( + &nodes[0].node.get_our_node_id(), + &temporary_channel_id, + false, + ); nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors(&nodes[1], 1); @@ -111,7 +175,11 @@ fn test_async_commitment_signature_for_funding_signed() { 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()); @@ -128,9 +196,16 @@ fn test_async_commitment_signature_for_commitment_signed() { // 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. @@ -177,8 +252,15 @@ fn test_async_commitment_signature_for_funding_signed_0conf() { 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); @@ -187,29 +269,54 @@ fn test_async_commitment_signature_for_funding_signed_0conf() { 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) + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ) .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.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`... - nodes[1].set_channel_signer_available(&nodes[0].node.get_our_node_id(), &temporary_channel_id, false); + nodes[1].set_channel_signer_available( + &nodes[0].node.get_our_node_id(), + &temporary_channel_id, + false, + ); nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors(&nodes[1], 1); @@ -232,11 +339,11 @@ fn test_async_commitment_signature_for_funding_signed_0conf() { 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) }; @@ -246,7 +353,11 @@ fn test_async_commitment_signature_for_funding_signed_0conf() { 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()); @@ -254,8 +365,16 @@ fn test_async_commitment_signature_for_funding_signed_0conf() { 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); @@ -275,9 +394,16 @@ fn test_async_commitment_signature_for_peer_disconnect() { // 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. diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index 3232cd0d33e..08e7f8a3f8d 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -7,11 +7,13 @@ // You may not use this file except in accordance with one or both of these // licenses. -use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; +use crate::blinded_path::payment::{ + ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs, +}; use crate::blinded_path::BlindedPath; -use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs}; -use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentFailureReason}; -use crate::ln::PaymentSecret; +use crate::events::{ + Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentFailureReason, +}; use crate::ln::channelmanager; use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; use crate::ln::features::BlindedHopFeatures; @@ -21,15 +23,17 @@ use crate::ln::msgs::ChannelMessageHandler; use crate::ln::onion_utils; use crate::ln::onion_utils::INVALID_ONION_BLINDING; use crate::ln::outbound_payment::Retry; +use crate::ln::PaymentSecret; use crate::offers::invoice::BlindedPayInfo; use crate::prelude::*; use crate::routing::router::{Payee, PaymentParameters, RouteParameters}; use crate::util::config::UserConfig; use crate::util::test_utils; +use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; fn blinded_payment_path( payment_secret: PaymentSecret, node_ids: Vec, - channel_upds: &[&msgs::UnsignedChannelUpdate], keys_manager: &test_utils::TestKeysInterface + channel_upds: &[&msgs::UnsignedChannelUpdate], keys_manager: &test_utils::TestKeysInterface, ) -> (BlindedPayInfo, BlindedPath) { let mut intermediate_nodes = Vec::new(); for (node_id, chan_upd) in node_ids.iter().zip(channel_upds) { @@ -60,19 +64,28 @@ fn blinded_payment_path( }; let mut secp_ctx = Secp256k1::new(); BlindedPath::new_for_payment( - &intermediate_nodes[..], *node_ids.last().unwrap(), payee_tlvs, - channel_upds.last().unwrap().htlc_maximum_msat, keys_manager, &secp_ctx - ).unwrap() + &intermediate_nodes[..], + *node_ids.last().unwrap(), + payee_tlvs, + channel_upds.last().unwrap().htlc_maximum_msat, + keys_manager, + &secp_ctx, + ) + .unwrap() } pub fn get_blinded_route_parameters( amt_msat: u64, payment_secret: PaymentSecret, node_ids: Vec, - channel_upds: &[&msgs::UnsignedChannelUpdate], keys_manager: &test_utils::TestKeysInterface + channel_upds: &[&msgs::UnsignedChannelUpdate], keys_manager: &test_utils::TestKeysInterface, ) -> RouteParameters { RouteParameters::from_payment_params_and_value( - PaymentParameters::blinded(vec![ - blinded_payment_path(payment_secret, node_ids, channel_upds, keys_manager) - ]), amt_msat + PaymentParameters::blinded(vec![blinded_payment_path( + payment_secret, + node_ids, + channel_upds, + keys_manager, + )]), + amt_msat, ) } @@ -87,10 +100,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 = ReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -100,15 +115,27 @@ fn do_one_hop_blinded_path(success: bool) { }; let mut secp_ctx = Secp256k1::new(); let blinded_path = BlindedPath::one_hop_for_payment( - nodes[1].node.get_our_node_id(), payee_tlvs, &chanmon_cfgs[1].keys_manager, &secp_ctx - ).unwrap(); + nodes[1].node.get_our_node_id(), + payee_tlvs, + &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 { @@ -132,7 +159,8 @@ fn mpp_to_one_hop_blinded_path() { create_announced_chan_between_nodes(&nodes, 2, 3).0.contents; 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 = ReceiveTlvs { payment_secret, payment_constraints: PaymentConstraints { @@ -141,16 +169,30 @@ fn mpp_to_one_hop_blinded_path() { }, }; let blinded_path = BlindedPath::one_hop_for_payment( - nodes[3].node.get_our_node_id(), payee_tlvs, &chanmon_cfgs[3].keys_manager, &secp_ctx - ).unwrap(); + nodes[3].node.get_our_node_id(), + payee_tlvs, + &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]]]; @@ -158,12 +200,28 @@ 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); + pass_along_path( + &nodes[0], + expected_route[1], + amt_msat, + payment_hash.clone(), + Some(payment_secret), + ev.clone(), + true, + None, + ); claim_payment_along_route(&nodes[0], expected_route, false, payment_preimage); } @@ -194,17 +252,32 @@ fn do_forward_checks_failure(check: ForwardCheckFail) { // We need the session priv to construct a bogus onion packet later. *nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some([3; 32]); 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, - 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, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_1_2], + &chanmon_cfgs[2].keys_manager, + ); 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); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -219,14 +292,31 @@ fn do_forward_checks_failure(check: ForwardCheckFail) { }, ForwardCheckFail::ForwardPayloadEncodedAsReceive => { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ) + .unwrap(); let cur_height = nodes[0].best_block_info().1; let (mut onion_payloads, ..) = onion_utils::build_onion_payloads( - &route.paths[0], amt_msat, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], + amt_msat, + RecipientOnionFields::spontaneous_empty(), + cur_height, + &None, + ) + .unwrap(); // Remove the receive payload so the blinded forward payload is encoded as a final payload // (i.e. next_hop_hmac == [0; 32]) onion_payloads.pop(); - update_add.onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + update_add.onion_routing_packet = onion_utils::construct_onion_packet( + onion_payloads, + onion_keys, + [0; 32], + &payment_hash, + ) + .unwrap(); }, ForwardCheckFail::OutboundChannelCheck => { // The intro node will see that the next-hop peer is disconnected and fail the HTLC backwards. @@ -238,10 +328,16 @@ fn do_forward_checks_failure(check: ForwardCheckFail) { do_commitment_signed_dance(&nodes[1], &nodes[0], &payment_event.commitment_msg, true, true); 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(INVALID_ONION_BLINDING, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]), + ); } #[test] @@ -253,15 +349,30 @@ 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, - 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, + 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(); @@ -296,14 +407,22 @@ fn failed_backwards_to_intro_node() { // 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(INVALID_ONION_BLINDING, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]), + ); } enum ProcessPendingHTLCsCheck { @@ -330,12 +449,26 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck) }; 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, - 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, + 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(); @@ -353,13 +486,21 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck) // intro node will error backwards. nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id()); expect_pending_htlcs_forwardable!(nodes[1]); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], - vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id + }] + ); }, ProcessPendingHTLCsCheck::FwdChannelClosed => { // Force close the next-hop channel so when we go to forward in process_pending_htlc_forwards, // the intro node will error backwards. - nodes[1].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id()) + .unwrap(); let events = nodes[1].node.get_and_clear_pending_events(); match events[0] { crate::events::Event::PendingHTLCsForwardable { .. } => {}, @@ -371,8 +512,12 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck) } nodes[1].node.process_pending_htlc_forwards(); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(nodes[1], - vec![HTLCDestination::UnknownNextHop { requested_forward_scid: chan_upd_1_2.short_channel_id }]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + nodes[1], + vec![HTLCDestination::UnknownNextHop { + requested_forward_scid: chan_upd_1_2.short_channel_id + }] + ); check_closed_broadcast(&nodes[1], 1, true); check_added_monitors!(nodes[1], 1); nodes[1].node.process_pending_htlc_forwards(); @@ -380,12 +525,18 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck) } 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]); check_added_monitors!(nodes[1], 1); 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(INVALID_ONION_BLINDING, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]), + ); } #[test] @@ -398,7 +549,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) = { @@ -407,16 +559,29 @@ 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, - 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, + 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(); @@ -430,19 +595,25 @@ 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(); let update_fail = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); check_added_monitors!(&nodes[1], 1); @@ -450,12 +621,25 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) { let fail_msg = update_fail.update_fail_htlcs[0].clone(); 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, false, - PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32])); - return + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]), + ); + 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 = { @@ -472,8 +656,20 @@ 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(&nodes[0], &vec!(&vec!(&nodes[1], &nodes[2])[..]), false, 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( + &nodes[0], + &vec![&vec![&nodes[1], &nodes[2]][..]], + false, + payment_preimage, + ); expect_payment_sent(&nodes[0], payment_preimage, Some(Some(1000)), true, true); } @@ -484,15 +680,30 @@ 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, - 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, + 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); @@ -506,18 +717,40 @@ 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; 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, + 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, 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); } @@ -561,9 +794,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) }; @@ -571,17 +803,29 @@ 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, - 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, + nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), + &[&chan_upd_1_2], + &chanmon_cfgs[2].keys_manager, + ); 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 @@ -590,22 +834,39 @@ 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, - 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, + 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].1.clone() - } else { panic!() } + } else { + panic!() + } }; if let Payee::Blinded { ref mut route_hints, .. } = route_params.payment_params.payee { route_hints[0].1 = high_htlc_min_bp; - } 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 = { @@ -614,9 +875,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); @@ -629,80 +898,165 @@ 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).unwrap(); + let mut onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ) + .unwrap(); let cur_height = nodes[0].best_block_info().1; let (mut onion_payloads, ..) = onion_utils::build_onion_payloads( - &route.paths[0], amt_msat, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], + amt_msat, + RecipientOnionFields::spontaneous_empty(), + cur_height, + &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, + ); }, ReceiveCheckFail::ReceiveRequirements => { let update_add = &mut payment_event_1_2.msgs[0]; 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, + ); }, 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(&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( + &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); }, 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); - 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 + ); + 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, + ); + }, } let updates_2_1 = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); @@ -710,28 +1064,40 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { 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, INVALID_ONION_BLINDING); - 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_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 { - MessageSendEvent:: UpdateHTLCs { node_id, updates } => { + events + .into_iter() + .find_map(|ev| match ev { + MessageSendEvent::UpdateHTLCs { node_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(INVALID_ONION_BLINDING, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32]), + ); } #[test] @@ -741,7 +1107,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. @@ -756,26 +1123,40 @@ fn blinded_path_retries() { let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0); 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, - 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, - 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, + 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, + 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); @@ -783,7 +1164,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); @@ -793,18 +1175,40 @@ fn blinded_path_retries() { let update_malformed = &updates.update_fail_malformed_htlcs[0]; assert_eq!(update_malformed.sha256_of_onion, [0; 32]); assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING); - $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); + $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); }, @@ -815,7 +1219,7 @@ fn blinded_path_retries() { _ => panic!("Unexpected event"), } nodes[0].node.process_pending_htlc_forwards(); - } + }; } fail_payment_back!(nodes[1]); @@ -824,7 +1228,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(); @@ -835,6 +1248,6 @@ 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!(), } } diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 18c4d83406c..27a5eb119fb 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::blockdata::script::{Script, ScriptBuf, Builder}; +use bitcoin::address::Payload; use bitcoin::blockdata::opcodes; -use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction}; +use bitcoin::blockdata::script::{Builder, Script, ScriptBuf}; +use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; use bitcoin::sighash; use bitcoin::sighash::EcdsaSighashType; -use bitcoin::address::Payload; -use bitcoin::hashes::{Hash, HashEngine}; -use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hash_types::{PubkeyHash, Txid, WPubkeyHash}; use bitcoin::hashes::ripemd160::Hash as Ripemd160; -use bitcoin::hash_types::{Txid, PubkeyHash, WPubkeyHash}; +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::sign::EntropySource; -use crate::ln::{PaymentHash, PaymentPreimage}; use crate::ln::msgs::DecodeError; +use crate::ln::{PaymentHash, PaymentPreimage}; +use crate::sign::EntropySource; use crate::util::ser::{Readable, RequiredWrapper, Writeable, Writer}; use crate::util::transaction_utils; use bitcoin::blockdata::locktime::absolute::LockTime; -use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar}; -use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message}; -use bitcoin::{secp256k1, Sequence, Witness}; +use bitcoin::secp256k1::{ecdsa::Signature, Message, Secp256k1}; +use bitcoin::secp256k1::{PublicKey, Scalar, SecretKey}; use bitcoin::PublicKey as BitcoinPublicKey; +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::prelude::*; -use core::cmp; use crate::ln::chan_utils; +use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, INITIAL_COMMITMENT_NUMBER}; +use crate::ln::features::ChannelTypeFeatures; +use crate::prelude::*; use crate::util::transaction_utils::sort_outputs; -use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI}; +use core::cmp; use core::ops::Deref; -use crate::chain; -use crate::ln::features::ChannelTypeFeatures; -use crate::crypto::utils::{sign, sign_with_aux_rand}; -use super::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint}; /// Maximum number of one-way in-flight HTLC (protocol-level value). pub const MAX_HTLCS: u16 = 483; @@ -77,7 +80,11 @@ pub const HTLC_SUCCESS_INPUT_ANCHOR_WITNESS_WEIGHT: u64 = 327; 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. @@ -85,7 +92,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. @@ -146,8 +157,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 { // @@ -184,7 +196,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: u64, to_counterparty_value_sat: u64, to_holder_script: ScriptBuf, to_counterparty_script: ScriptBuf, funding_outpoint: OutPoint) -> Transaction { +pub fn build_closing_transaction( + to_holder_value_sat: u64, to_counterparty_value_sat: u64, to_holder_script: ScriptBuf, + to_counterparty_script: ScriptBuf, funding_outpoint: OutPoint, +) -> Transaction { let txins = { let mut ins: Vec = Vec::new(); ins.push(TxIn { @@ -199,32 +214,24 @@ pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value let mut txouts: Vec<(TxOut, ())> = Vec::new(); if to_counterparty_value_sat > 0 { - 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 > 0 { - 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: 2, - lock_time: LockTime::ZERO, - input: txins, - output: outputs, - } + Transaction { version: 2, lock_time: LockTime::ZERO, input: txins, output: outputs } } /// Implements the per-commitment secret storage scheme from @@ -240,9 +247,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 @@ -252,14 +261,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 @@ -313,7 +322,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()); @@ -345,7 +354,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()); @@ -361,10 +372,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 = { @@ -382,9 +395,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.") @@ -460,19 +477,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, @@ -489,29 +531,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_countersignatory_with_anchors_redeemscript(payment_key).to_v0_p2wsh() } else { @@ -549,105 +597,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 @@ -657,14 +725,22 @@ 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 { +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 mut txins: Vec = Vec::new(); txins.push(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 { @@ -675,27 +751,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.amount_msat / 1000 } else { let total_fee = feerate_per_kw as u64 * weight / 1000; @@ -703,7 +792,12 @@ pub(crate) fn build_htlc_output( }; TxOut { - script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_v0_p2wsh(), + script_pubkey: get_revokeable_redeemscript( + revocation_key, + contest_delay, + broadcaster_delayed_payment_key, + ) + .to_v0_p2wsh(), value: output_value, } } @@ -753,7 +847,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(); @@ -784,7 +880,8 @@ pub fn get_to_countersignatory_with_anchors_redeemscript(payment_point: &PublicK /// (empty vector required to satisfy compliance with MINIMALIF-standard rule) #[inline] pub fn get_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) @@ -795,9 +892,14 @@ pub fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> ScriptBuf { } /// Locates the output with an anchor script paying to `funding_pubkey` within `commitment_tx`. -pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> { +pub(crate) fn get_anchor_output<'a>( + commitment_tx: &'a Transaction, funding_pubkey: &PublicKey, +) -> Option<(u32, &'a TxOut)> { let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_v0_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)) } @@ -832,7 +934,7 @@ pub struct ChannelTransactionParameters { pub funding_outpoint: Option, /// This channel's type, as negotiated during channel open. For old objects where this field /// wasn't serialized, it will default to static_remote_key at deserialization. - pub channel_type_features: ChannelTypeFeatures + pub channel_type_features: ChannelTypeFeatures, } /// Late-bound per-channel counterparty data used to build transactions. @@ -855,11 +957,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, @@ -867,11 +969,11 @@ 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 } } } @@ -882,7 +984,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), @@ -918,7 +1023,10 @@ impl Readable 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(), @@ -926,7 +1034,8 @@ impl Readable for ChannelTransactionParameters { is_outbound_from_holder: is_outbound_from_holder.0.unwrap(), counterparty_parameters, funding_outpoint, - 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()), }) } } @@ -966,7 +1075,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. @@ -974,7 +1087,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 @@ -1006,7 +1123,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 {} @@ -1028,67 +1147,121 @@ impl HolderCommitmentTransaction { #[cfg(test)] pub fn dummy(htlcs: &mut Vec<(HTLCOutputInCommitment, ())>) -> 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_slice(&[42; 32]).unwrap(), &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_slice(&[42; 32]).unwrap(), + &SecretKey::from_slice(&[42; 32]).unwrap(), + ); let keys = TxCreationKeys { per_commitment_point: dummy_key.clone(), - revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key), - broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key), - countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key), - broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key), + revocation_key: RevocationKey::from_basepoint( + &secp_ctx, + &RevocationBasepoint::from(dummy_key), + &dummy_key, + ), + broadcaster_htlc_key: HtlcKey::from_basepoint( + &secp_ctx, + &HtlcBasepoint::from(dummy_key), + &dummy_key, + ), + countersignatory_htlc_key: HtlcKey::from_basepoint( + &secp_ctx, + &HtlcBasepoint::from(dummy_key), + &dummy_key, + ), + broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint( + &secp_ctx, + &DelayedPaymentBasepoint::from(dummy_key), + &dummy_key, + ), }; 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, + }), channel_type_features: ChannelTypeFeatures::only_static_remote_key(), }; let mut counterparty_htlc_sigs = Vec::new(); for _ in 0..htlcs.len() { counterparty_htlc_sigs.push(dummy_sig); } - let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, dummy_key.clone(), dummy_key.clone(), keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable()); + let inner = CommitmentTransaction::new_with_auxiliary_htlc_data( + 0, + 0, + 0, + dummy_key.clone(), + dummy_key.clone(), + keys, + 0, + htlcs, + &channel_parameters.as_counterparty_broadcastable(), + ); htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index); 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_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All); - tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All); + tx.input[0] + .witness + .push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All); + tx.input[0].witness.push_bitcoin_signature( + &self.counterparty_sig.serialize_der(), + EcdsaSighashType::All, + ); } else { - tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All); - tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All); + tx.input[0].witness.push_bitcoin_signature( + &self.counterparty_sig.serialize_der(), + EcdsaSighashType::All, + ); + tx.input[0] + .witness + .push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All); } tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec()); @@ -1117,13 +1290,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).segwit_signature_hash(0, funding_redeemscript, 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) + .segwit_signature_hash( + 0, + funding_redeemscript, + 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) } @@ -1131,8 +1316,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) } @@ -1155,23 +1343,22 @@ 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 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, } } @@ -1193,12 +1380,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 }) } @@ -1237,7 +1426,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> { @@ -1249,14 +1440,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).segwit_signature_hash(0, funding_redeemscript, 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) + .segwit_signature_hash( + 0, + funding_redeemscript, + 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) } @@ -1287,13 +1490,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.htlcs == o.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.htlcs == o.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); @@ -1304,7 +1507,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), @@ -1338,7 +1544,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(), @@ -1349,7 +1558,8 @@ impl Readable for CommitmentTransaction { keys: keys.0.unwrap(), built: built.0.unwrap(), 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()), }) } } @@ -1365,12 +1575,29 @@ impl CommitmentTransaction { /// Only include HTLCs that are above the dust limit for the channel. /// /// This is not exported to bindings users due to the generic though we likely should expose a version without - pub fn new_with_auxiliary_htlc_data(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction { + pub fn new_with_auxiliary_htlc_data( + commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, + broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, + keys: TxCreationKeys, feerate_per_kw: u32, + htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, + channel_parameters: &DirectedChannelTransactionParameters, + ) -> CommitmentTransaction { // Sort outputs and populate output indices while keeping track of the auxiliary data - let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, &broadcaster_funding_key, &countersignatory_funding_key).unwrap(); + let (outputs, htlcs) = Self::internal_build_outputs( + &keys, + to_broadcaster_value_sat, + to_countersignatory_value_sat, + htlcs_with_aux, + channel_parameters, + &broadcaster_funding_key, + &countersignatory_funding_key, + ) + .unwrap(); - let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters); - let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); + let (obscured_commitment_transaction_number, txins) = + Self::internal_build_inputs(commitment_number, channel_parameters); + let transaction = + Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); let txid = transaction.txid(); CommitmentTransaction { commitment_number, @@ -1381,10 +1608,7 @@ impl CommitmentTransaction { htlcs, channel_type_features: channel_parameters.channel_type_features().clone(), keys, - built: BuiltCommitmentTransaction { - transaction, - txid - }, + built: BuiltCommitmentTransaction { transaction, txid }, } } @@ -1396,25 +1620,40 @@ impl CommitmentTransaction { self } - fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result { - let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters); + fn internal_rebuild_transaction( + &self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters, + broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey, + ) -> Result { + let (obscured_commitment_transaction_number, txins) = + Self::internal_build_inputs(self.commitment_number, channel_parameters); let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect(); - let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters, broadcaster_funding_key, countersignatory_funding_key)?; - - let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); + let (outputs, _) = Self::internal_build_outputs( + keys, + self.to_broadcaster_value_sat, + self.to_countersignatory_value_sat, + &mut htlcs_with_aux, + channel_parameters, + broadcaster_funding_key, + countersignatory_funding_key, + )?; + + let transaction = + Self::make_transaction(obscured_commitment_transaction_number, txins, outputs); let txid = transaction.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: 2, - 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, } @@ -1424,23 +1663,31 @@ impl CommitmentTransaction { // - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the // caller needs to have sorted together with the HTLCs so it can keep track of the output index // - building of a bitcoin transaction during a verify() call, in which case T is just () - fn internal_build_outputs(keys: &TxCreationKeys, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec, Vec), ()> { + fn internal_build_outputs( + keys: &TxCreationKeys, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, + htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, + channel_parameters: &DirectedChannelTransactionParameters, + broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey, + ) -> Result<(Vec, Vec), ()> { let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys(); let contest_delay = channel_parameters.contest_delay(); let mut txouts: Vec<(TxOut, Option<&mut HTLCOutputInCommitment>)> = Vec::new(); if to_countersignatory_value_sat > 0 { - let script = if channel_parameters.channel_type_features().supports_anchors_zero_fee_htlc_tx() { - get_to_countersignatory_with_anchors_redeemscript(&countersignatory_pubkeys.payment_point).to_v0_p2wsh() - } else { - Payload::p2wpkh(&BitcoinPublicKey::new(countersignatory_pubkeys.payment_point)).unwrap().script_pubkey() - }; + let script = + if channel_parameters.channel_type_features().supports_anchors_zero_fee_htlc_tx() { + get_to_countersignatory_with_anchors_redeemscript( + &countersignatory_pubkeys.payment_point, + ) + .to_v0_p2wsh() + } else { + Payload::p2wpkh(&BitcoinPublicKey::new(countersignatory_pubkeys.payment_point)) + .unwrap() + .script_pubkey() + }; txouts.push(( - TxOut { - script_pubkey: script.clone(), - value: to_countersignatory_value_sat, - }, + TxOut { script_pubkey: script.clone(), value: to_countersignatory_value_sat }, None, )) } @@ -1486,11 +1733,13 @@ impl CommitmentTransaction { let mut htlcs = Vec::with_capacity(htlcs_with_aux.len()); for (htlc, _) in htlcs_with_aux { - let script = chan_utils::get_htlc_redeemscript(&htlc, &channel_parameters.channel_type_features(), &keys); - let txout = TxOut { - script_pubkey: script.to_v0_p2wsh(), - value: htlc.amount_msat / 1000, - }; + let script = chan_utils::get_htlc_redeemscript( + &htlc, + &channel_parameters.channel_type_features(), + &keys, + ); + let txout = + TxOut { script_pubkey: script.to_v0_p2wsh(), value: htlc.amount_msat / 1000 }; txouts.push((txout, Some(htlc))); } @@ -1499,15 +1748,21 @@ impl CommitmentTransaction { sort_outputs(&mut txouts, |a, b| { if let &Some(ref a_htlcout) = a { if let &Some(ref b_htlcout) = b { - a_htlcout.cltv_expiry.cmp(&b_htlcout.cltv_expiry) + a_htlcout + .cltv_expiry + .cmp(&b_htlcout.cltv_expiry) // Note that due to hash collisions, we have to have a fallback comparison // here for fuzzing mode (otherwise at least chanmon_fail_consistency // may fail)! .then(a_htlcout.payment_hash.0.cmp(&b_htlcout.payment_hash.0)) // 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: - } else { cmp::Ordering::Equal } - } else { cmp::Ordering::Equal } + } else { + cmp::Ordering::Equal + } + } else { + cmp::Ordering::Equal + } }); let mut outputs = Vec::with_capacity(txouts.len()); @@ -1521,25 +1776,30 @@ impl CommitmentTransaction { Ok((outputs, htlcs)) } - fn internal_build_inputs(commitment_number: u64, channel_parameters: &DirectedChannelTransactionParameters) -> (u64, Vec) { + fn internal_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 mut ins: Vec = Vec::new(); ins.push(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 @@ -1598,14 +1858,28 @@ impl CommitmentTransaction { /// /// An external validating signer must call this method before signing /// or using the built transaction. - pub fn verify(&self, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1) -> Result { + pub fn verify( + &self, channel_parameters: &DirectedChannelTransactionParameters, + broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, + 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, broadcaster_keys, countersignatory_keys, secp_ctx); + let keys = TxCreationKeys::from_channel_static_keys( + &per_commitment_point, + broadcaster_keys, + countersignatory_keys, + secp_ctx, + ); if keys != self.keys { return Err(()); } - let tx = self.internal_rebuild_transaction(&keys, channel_parameters, &broadcaster_keys.funding_pubkey, &countersignatory_keys.funding_pubkey)?; + let tx = self.internal_rebuild_transaction( + &keys, + channel_parameters, + &broadcaster_keys.funding_pubkey, + &countersignatory_keys.funding_pubkey, + )?; if self.built.transaction != tx.transaction || self.built.txid != tx.txid { return Err(()); } @@ -1626,7 +1900,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> { @@ -1657,22 +1933,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.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.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).segwit_signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, EcdsaSighashType::All).unwrap()[..]); + let sighash = hash_to_message!( + &sighash::SighashCache::new(&htlc_tx) + .segwit_signature_hash( + 0, + &htlc_redeemscript, + this_htlc.amount_msat / 1000, + EcdsaSighashType::All + ) + .unwrap()[..] + ); ret.push(sign_with_aux_rand(secp_ctx, &sighash, &holder_htlc_key, entropy_source)); } Ok(ret) @@ -1687,30 +1991,45 @@ impl<'a> TrustedCommitmentTransaction<'a> { let this_htlc = &self.inner.htlcs[htlc_index]; assert!(this_htlc.transaction_output_index.is_some()); // if we don't have preimage for an HTLC-Success, we can't generate an HTLC transaction. - if !this_htlc.offered && preimage.is_none() { unreachable!(); } + if !this_htlc.offered && preimage.is_none() { + unreachable!(); + } // Further, we should never be provided the preimage for an HTLC-Timeout transaction. - if this_htlc.offered && preimage.is_some() { unreachable!(); } + if this_htlc.offered && preimage.is_some() { + unreachable!(); + } build_htlc_transaction( - &self.inner.built.txid, self.inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, - &self.channel_type_features, &keys.broadcaster_delayed_payment_key, &keys.revocation_key + &self.inner.built.txid, + self.inner.feerate_per_kw, + channel_parameters.contest_delay(), + &this_htlc, + &self.channel_type_features, + &keys.broadcaster_delayed_payment_key, + &keys.revocation_key, ) } - /// Builds the witness required to spend the input for the HTLC with index `htlc_index` in a /// second-level holder HTLC transaction. pub(crate) fn build_htlc_input_witness( &self, htlc_index: usize, counterparty_signature: &Signature, signature: &Signature, - preimage: &Option + preimage: &Option, ) -> Witness { let keys = &self.inner.keys; let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys( - &self.inner.htlcs[htlc_index], &self.channel_type_features, &keys.broadcaster_htlc_key, - &keys.countersignatory_htlc_key, &keys.revocation_key + &self.inner.htlcs[htlc_index], + &self.channel_type_features, + &keys.broadcaster_htlc_key, + &keys.countersignatory_htlc_key, + &keys.revocation_key, ); chan_utils::build_htlc_input_witness( - signature, counterparty_signature, preimage, &htlc_redeemscript, &self.channel_type_features, + signature, + counterparty_signature, + preimage, + &htlc_redeemscript, + &self.channel_type_features, ) } @@ -1731,7 +2050,9 @@ impl<'a> TrustedCommitmentTransaction<'a> { ); let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh(); let outputs = &self.inner.built.transaction.output; - outputs.iter().enumerate() + outputs + .iter() + .enumerate() .find(|(_, out)| out.script_pubkey == revokeable_p2wsh) .map(|(idx, _)| idx) } @@ -1747,35 +2068,24 @@ 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: 2, - lock_time: LockTime::ZERO, - input, - output, - }; + let output = vec![TxOut { script_pubkey: destination_script, value }]; + let mut justice_tx = Transaction { version: 2, lock_time: LockTime::ZERO, input, output }; let weight = justice_tx.weight().to_wu() + WEIGHT_REVOKED_OUTPUT; let fee = 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 @@ -1785,8 +2095,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(); @@ -1810,20 +2119,24 @@ 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_countersignatory_with_anchors_redeemscript, + ChannelTransactionParameters, CommitmentTransaction, + CounterpartyChannelTransactionParameters, HTLCOutputInCommitment, TxCreationKeys, + }; + use crate::ln::features::ChannelTypeFeatures; + use crate::ln::PaymentHash; use crate::prelude::*; - use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment}; - use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1}; - use crate::util::test_utils; use crate::sign::{ChannelSigner, SignerProvider}; - use bitcoin::{Network, Txid, ScriptBuf}; - use bitcoin::hashes::Hash; - use bitcoin::hashes::hex::FromHex; - use crate::ln::PaymentHash; + use crate::util::test_utils; use bitcoin::address::Payload; + use bitcoin::hashes::hex::FromHex; + use bitcoin::hashes::Hash; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use bitcoin::PublicKey as BitcoinPublicKey; - use crate::ln::features::ChannelTypeFeatures; + use bitcoin::{Network, ScriptBuf, Txid}; struct TestCommitmentTxBuilder { commitment_number: u64, @@ -1842,21 +2155,47 @@ 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(3000, keys_provider.generate_channel_keys_id(false, 1_000_000, 0)); - let counterparty_signer = keys_provider.derive_channel_signer(3000, keys_provider.generate_channel_keys_id(true, 1_000_000, 1)); + let signer = keys_provider.derive_channel_signer( + 3000, + keys_provider.generate_channel_keys_id(false, 1_000_000, 0), + ); + let counterparty_signer = keys_provider.derive_channel_signer( + 3000, + keys_provider.generate_channel_keys_id(true, 1_000_000, 1), + ); let delayed_payment_base = &signer.pubkeys().delayed_payment_basepoint; - 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 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 htlc_basepoint = &signer.pubkeys().htlc_basepoint; let holder_pubkeys = signer.pubkeys(); let counterparty_pubkeys = counterparty_signer.pubkeys().clone(); - let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint); + let keys = TxCreationKeys::derive_new( + &secp_ctx, + &per_commitment_point, + delayed_payment_base, + htlc_basepoint, + &counterparty_pubkeys.revocation_basepoint, + &counterparty_pubkeys.htlc_basepoint, + ); 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, + }), channel_type_features: ChannelTypeFeatures::only_static_remote_key(), }; let htlcs_with_aux = Vec::new(); @@ -1873,13 +2212,19 @@ mod tests { } } - fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction { + fn build( + &mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64, + ) -> CommitmentTransaction { CommitmentTransaction::new_with_auxiliary_htlc_data( - self.commitment_number, to_broadcaster_sats, to_countersignatory_sats, + self.commitment_number, + to_broadcaster_sats, + to_countersignatory_sats, self.holder_funding_pubkey.clone(), self.counterparty_funding_pubkey.clone(), - self.keys.clone(), self.feerate_per_kw, - &mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable() + self.keys.clone(), + self.feerate_per_kw, + &mut self.htlcs_with_aux, + &self.channel_parameters.as_holder_broadcastable(), ) } } @@ -1891,13 +2236,25 @@ mod tests { // Generate broadcaster and counterparty outputs let tx = builder.build(1000, 2000); assert_eq!(tx.built.transaction.output.len(), 2); - assert_eq!(tx.built.transaction.output[1].script_pubkey, Payload::p2wpkh(&BitcoinPublicKey::new(builder.counterparty_pubkeys.payment_point)).unwrap().script_pubkey()); + assert_eq!( + tx.built.transaction.output[1].script_pubkey, + Payload::p2wpkh(&BitcoinPublicKey::new(builder.counterparty_pubkeys.payment_point)) + .unwrap() + .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); assert_eq!(tx.built.transaction.output.len(), 4); - assert_eq!(tx.built.transaction.output[3].script_pubkey, get_to_countersignatory_with_anchors_redeemscript(&builder.counterparty_pubkeys.payment_point).to_v0_p2wsh()); + assert_eq!( + tx.built.transaction.output[3].script_pubkey, + get_to_countersignatory_with_anchors_redeemscript( + &builder.counterparty_pubkeys.payment_point + ) + .to_v0_p2wsh() + ); // Generate broadcaster output and anchor let tx = builder.build(3000, 0); @@ -1924,29 +2281,95 @@ 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(); builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())]; let tx = builder.build(3000, 0); let keys = &builder.keys.clone(); 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_v0_p2wsh()); - assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_v0_p2wsh()); - assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_v0_p2wsh().to_hex_string(), - "0020e43a7c068553003fe68fcae424fb7b28ec5ce48cd8b6744b3945631389bad2fb"); - assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_v0_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_v0_p2wsh() + ); + assert_eq!( + tx.built.transaction.output[1].script_pubkey, + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::only_static_remote_key(), + &keys + ) + .to_v0_p2wsh() + ); + assert_eq!( + get_htlc_redeemscript( + &received_htlc, + &ChannelTypeFeatures::only_static_remote_key(), + &keys + ) + .to_v0_p2wsh() + .to_hex_string(), + "0020e43a7c068553003fe68fcae424fb7b28ec5ce48cd8b6744b3945631389bad2fb" + ); + assert_eq!( + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::only_static_remote_key(), + &keys + ) + .to_v0_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(); builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())]; let tx = builder.build(3000, 0); 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_v0_p2wsh()); - assert_eq!(tx.built.transaction.output[3].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_v0_p2wsh()); - assert_eq!(get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_v0_p2wsh().to_hex_string(), - "0020b70d0649c72b38756885c7a30908d912a7898dd5d79457a7280b8e9a20f3f2bc"); - assert_eq!(get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_v0_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_v0_p2wsh() + ); + assert_eq!( + tx.built.transaction.output[3].script_pubkey, + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + &keys + ) + .to_v0_p2wsh() + ); + assert_eq!( + get_htlc_redeemscript( + &received_htlc, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + &keys + ) + .to_v0_p2wsh() + .to_hex_string(), + "0020b70d0649c72b38756885c7a30908d912a7898dd5d79457a7280b8e9a20f3f2bc" + ); + assert_eq!( + get_htlc_redeemscript( + &offered_htlc, + &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), + &keys + ) + .to_v0_p2wsh() + .to_hex_string(), + "002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7" + ); } #[test] @@ -1987,16 +2410,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_v0_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.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); @@ -2028,42 +2461,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!(); } @@ -2074,13 +2547,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()); } { @@ -2089,23 +2574,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()); } { @@ -2114,23 +2621,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()); } { @@ -2139,43 +2668,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()); } { @@ -2184,33 +2755,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()); } { @@ -2219,43 +2822,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()); } { @@ -2264,43 +2909,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()); } { @@ -2309,43 +2996,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()); } } } diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs index 02253a003fb..950b287bf55 100644 --- a/lightning/src/ln/chanmon_update_fail_tests.rs +++ b/lightning/src/ln/chanmon_update_fail_tests.rs @@ -12,30 +12,35 @@ //! 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::blockdata::constants::genesis_block; -use bitcoin::hash_types::BlockHash; -use bitcoin::network::constants::Network; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor}; +use crate::chain::channelmonitor::{ChannelMonitor, ANTI_REORG_DELAY}; use crate::chain::transaction::OutPoint; use crate::chain::{ChannelMonitorUpdateStatus, Listen, Watch}; -use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose, ClosureReason, HTLCDestination}; -use crate::ln::channelmanager::{RAACommitmentOrder, PaymentSendFailure, PaymentId, RecipientOnionFields}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, + PaymentPurpose, +}; use crate::ln::channel::{AnnouncementSigsState, ChannelPhase}; -use crate::ln::{msgs, ChannelId}; +use crate::ln::channelmanager::{ + PaymentId, PaymentSendFailure, RAACommitmentOrder, RecipientOnionFields, +}; use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler}; -use crate::util::test_channel_signer::TestChannelSigner; +use crate::ln::{msgs, ChannelId}; use crate::util::errors::APIError; use crate::util::ser::{ReadableArgs, Writeable}; +use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_utils::TestBroadcaster; +use bitcoin::blockdata::constants::genesis_block; +use bitcoin::hash_types::BlockHash; +use bitcoin::network::constants::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() { @@ -52,7 +57,7 @@ fn test_monitor_and_persister_update_fail() { let outpoint = OutPoint { txid: chan.3.txid(), index: 0 }; // 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); @@ -75,15 +80,31 @@ fn test_monitor_and_persister_update_fail() { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(outpoint).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(outpoint, 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(outpoint, 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); @@ -92,23 +113,48 @@ 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 ChannelPhase::Funded(ref mut channel) = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2) { - if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) { + if let ChannelPhase::Funded(ref mut channel) = get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan.2 + ) { + if let Ok(Some(update)) = + channel.commitment_signed(&updates.commitment_signed, &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(outpoint, &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(outpoint, &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(outpoint, &update), - ChannelMonitorUpdateStatus::Completed); - } else { assert!(false); } + assert_eq!( + nodes[0].chain_monitor.update_channel(outpoint, &update), + ChannelMonitorUpdateStatus::Completed + ); + } else { + assert!(false); + } } else { assert!(false); } @@ -127,14 +173,23 @@ 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); { - unwrap_send_err!(nodes[0].node.send_payment_with_route(&route, payment_hash_1, - RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0) - ), false, APIError::MonitorUpdateInProgress, {}); + unwrap_send_err!( + nodes[0].node.send_payment_with_route( + &route, + payment_hash_1, + RecipientOnionFields::secret_only(payment_secret_1), + PaymentId(payment_hash_1.0) + ), + false, + APIError::MonitorUpdateInProgress, + {} + ); check_added_monitors!(nodes[0], 1); } @@ -151,7 +206,14 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { } chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[0], 0); @@ -167,7 +229,14 @@ 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()); @@ -177,7 +246,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_1, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -186,12 +255,21 @@ 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); - unwrap_send_err!(nodes[0].node.send_payment_with_route(&route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0) - ), false, APIError::MonitorUpdateInProgress, {}); + unwrap_send_err!( + nodes[0].node.send_payment_with_route( + &route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0) + ), + false, + APIError::MonitorUpdateInProgress, + {} + ); check_added_monitors!(nodes[0], 1); } @@ -206,7 +284,10 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { } // ...and make sure we can force-close a frozen channel - nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&channel_id, &nodes[1].node.get_our_node_id()) + .unwrap(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); @@ -214,7 +295,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, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -249,15 +336,25 @@ 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); - unwrap_send_err!(nodes[0].node.send_payment_with_route(&route, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0) - ), false, APIError::MonitorUpdateInProgress, {}); + unwrap_send_err!( + nodes[0].node.send_payment_with_route( + &route, + payment_hash_2, + RecipientOnionFields::secret_only(payment_secret_2), + PaymentId(payment_hash_2.0) + ), + false, + APIError::MonitorUpdateInProgress, + {} + ); check_added_monitors!(nodes[0], 1); } @@ -274,7 +371,18 @@ 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, 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, + 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,9 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { _ => panic!("Unexpected event"), } - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed); + nodes[0] + .node + .handle_commitment_signed(&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 +424,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 (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, 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 +549,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 +563,15 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { _ => panic!("Unexpected event"), } - nodes[0].node.handle_commitment_signed(&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( + &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 +580,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 +591,36 @@ 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(), as_resp.2.unwrap()), as_resp.1.unwrap()) + ( + SendEvent::from_commitment_update(nodes[1].node.get_our_node_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(&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(&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 +637,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 +722,27 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { } } - nodes[0].node.handle_commitment_signed(&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( + &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(&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( + &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); @@ -538,7 +750,9 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 1); - nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_revoke_and_ack); + nodes[0] + .node + .handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_revoke_and_ack); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); expect_payment_path_successful!(nodes[0]); @@ -548,7 +762,14 @@ 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()); @@ -558,7 +779,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_2, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -603,24 +824,42 @@ 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(&nodes[0].node.get_our_node_id(), &send_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[1], 0); let responses = nodes[1].node.get_and_clear_pending_msg_events(); @@ -644,7 +883,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(&nodes[1].node.get_our_node_id(), &updates.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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 +895,22 @@ fn test_monitor_update_fail_cs() { } chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, 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,7 +919,14 @@ 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()); @@ -676,7 +936,7 @@ fn test_monitor_update_fail_cs() { assert!(payment_preimage.is_none()); assert_eq!(our_payment_secret, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -696,16 +956,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 +992,14 @@ fn test_monitor_update_fail_no_rebroadcast() { check_added_monitors!(nodes[1], 1); chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 0); @@ -744,31 +1028,57 @@ 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(&nodes[0].node.get_our_node_id(), &send_event_1.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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(&nodes[1].node.get_our_node_id(), &send_event_2.commitment_msg); + nodes[0] + .node + .handle_commitment_signed(&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 +1087,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 (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[0], 0); @@ -788,11 +1105,21 @@ fn test_monitor_update_raa_while_paused() { nodes[1].node.handle_commitment_signed(&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()); - - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_cs.commitment_signed); + let bs_second_raa = get_event_msg!( + nodes[1], + MessageSendEvent::SendRevokeAndACK, + nodes[0].node.get_our_node_id() + ); + + nodes[0] + .node + .handle_commitment_signed(&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 +1152,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 +1164,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 +1215,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 +1244,52 @@ 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(&nodes[2].node.get_our_node_id(), &send_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2.2).unwrap().clone(); + let (outpoint, 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(outpoint, 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 +1301,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 } => { assert_eq!(node_id, nodes[0].node.get_our_node_id()); @@ -932,12 +1316,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 +1331,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 +1344,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(&nodes[1].node.get_our_node_id(), &send_event_b.commitment_msg); + nodes[2].node.handle_commitment_signed( + &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 +1367,15 @@ 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(&nodes[2].node.get_our_node_id(), &bs_cs.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&nodes[2].node.get_our_node_id(), &bs_cs.commitment_signed); check_added_monitors!(nodes[1], 1); } else { - nodes[2].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &send_event_b.commitment_msg); + nodes[2].node.handle_commitment_signed( + &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 +1400,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(&nodes[2].node.get_our_node_id(), &updates.commitment_signed); + nodes[1].node.handle_commitment_signed( + &nodes[2].node.get_our_node_id(), + &updates.commitment_signed, + ); check_added_monitors!(nodes[1], 1); }, _ => panic!("Unexpected event"), @@ -1012,13 +1415,24 @@ 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()); - - - 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(&nodes[1].node.get_our_node_id(), &as_cs.commitment_signed); + 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(&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 +1442,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(&nodes[2].node.get_our_node_id(), &bs_second_cs.commitment_signed); + nodes[1].node.handle_commitment_signed( + &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 +1462,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 +1489,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 +1518,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 +1534,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 +1576,15 @@ 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.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 + .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 +1592,68 @@ 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.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 + .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.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 + .flags & 2, + 0 + ); // The "disabled" bit should be unset as we just reconnected chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[1], 0); @@ -1168,7 +1663,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 +1683,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 +1696,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, 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); - 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); } @@ -1207,7 +1722,9 @@ 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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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()); @@ -1219,7 +1736,11 @@ fn raa_no_response_awaiting_raa_state() { nodes[0].node.handle_commitment_signed(&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 +1748,9 @@ 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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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 +1759,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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); // nodes[1] should be AwaitingRAA here! check_added_monitors!(nodes[1], 0); @@ -1248,8 +1778,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()); } @@ -1261,12 +1798,22 @@ fn raa_no_response_awaiting_raa_state() { nodes[0].node.handle_commitment_signed(&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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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 +1825,15 @@ 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(&nodes[1].node.get_our_node_id(), &bs_update.commitment_signed); + nodes[0] + .node + .handle_commitment_signed(&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 +1860,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 +1870,78 @@ 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(&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(&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 +1950,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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[1], 0); @@ -1368,12 +1967,22 @@ fn claim_while_disconnected_monitor_update_fail() { match bs_msgs[0] { MessageSendEvent::UpdateHTLCs { ref node_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(&nodes[1].node.get_our_node_id(), &updates.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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 +2001,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(&nodes[1].node.get_our_node_id(), &bs_commitment.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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()); - - nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_commitment.commitment_signed); + let as_raa = get_event_msg!( + nodes[0], + MessageSendEvent::SendRevokeAndACK, + nodes[1].node.get_our_node_id() + ); + + nodes[1].node.handle_commitment_signed( + &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 +2049,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 +2095,9 @@ 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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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,23 +2106,56 @@ 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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[1], 0); let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -1483,7 +2165,11 @@ fn monitor_failed_no_reestablish_response() { nodes[0].node.handle_commitment_signed(&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 +2199,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,7 +2219,9 @@ 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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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()); @@ -1534,13 +2230,25 @@ fn first_message_on_recv_ordering() { nodes[0].node.handle_commitment_signed(&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 +2269,21 @@ 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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[1], 0); @@ -1579,7 +2296,11 @@ fn first_message_on_recv_ordering() { nodes[0].node.handle_commitment_signed(&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 +2328,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); nodes[1].node.claim_funds(payment_preimage_1); @@ -1619,10 +2341,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, 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); } @@ -1640,8 +2370,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(); @@ -1654,13 +2391,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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, 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); @@ -1668,15 +2415,29 @@ 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()); @@ -1687,13 +2448,20 @@ fn test_monitor_update_fail_claim() { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_2, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => 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()); @@ -1703,7 +2471,7 @@ fn test_monitor_update_fail_claim() { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_3, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -1728,18 +2496,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); } @@ -1750,17 +2532,35 @@ 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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone(); + let (outpoint, 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(outpoint, 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(); @@ -1768,7 +2568,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, payment_hash_1); @@ -1776,7 +2578,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(); @@ -1798,13 +2600,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); } @@ -1812,7 +2623,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); @@ -1821,7 +2640,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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000); check_added_monitors!(nodes[1], 0); @@ -1833,7 +2659,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); @@ -1842,7 +2671,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); @@ -1850,28 +2681,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.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), funding_tx.clone()).unwrap(); + 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 + .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_outpoint(OutPoint { txid: funding_created_msg.funding_txid, index: 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_outpoint(OutPoint { + txid: funding_created_msg.funding_txid, + index: 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 (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); check_added_monitors!(nodes[0], 0); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); @@ -1879,11 +2756,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].txid(), funding_output.txid); + assert_eq!( + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0].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 { @@ -1911,25 +2798,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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, 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 { @@ -1937,7 +2853,8 @@ 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 node in nodes.iter() { @@ -1952,11 +2869,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1981,7 +2909,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(); @@ -2001,30 +2930,72 @@ fn test_path_paused_mpp() { // Now check that we get the right return value, indicating that the first path succeeded but // the second got a MonitorUpdateInProgress err. This implies // PaymentSendFailure::PartialFailure as some paths succeeded, preventing retry. - if let Err(PaymentSendFailure::PartialFailure { results, ..}) = nodes[0].node.send_payment_with_route( - &route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) - ) { + if let Err(PaymentSendFailure::PartialFailure { results, .. }) = + nodes[0].node.send_payment_with_route( + &route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) { assert_eq!(results.len(), 2); - if let Ok(()) = results[0] {} else { panic!(); } - if let Err(APIError::MonitorUpdateInProgress) = results[1] {} else { panic!(); } - } else { panic!(); } + if let Ok(()) = results[0] { + } else { + panic!(); + } + if let Err(APIError::MonitorUpdateInProgress) = results[1] { + } else { + panic!(); + } + } else { + panic!(); + } 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 (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2_id).unwrap().clone(); + let (outpoint, 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(outpoint, 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(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, 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( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_preimage, + ); } #[test] @@ -2047,9 +3018,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 +3042,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(&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( + &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 +3093,69 @@ 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(&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( + &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(&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( + &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(&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 +3182,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 +3193,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 }]); - - nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[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_id_2 + }] + ); + + 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 +3250,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 +3268,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 +3302,55 @@ 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(&nodes[0].node.get_our_node_id(), &update_msgs.commitment_signed); + nodes[1].node.handle_commitment_signed( + &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(&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(&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( + &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 +3359,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(&nodes[1].node.get_our_node_id(), &bs_second_cs.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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 +3399,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 +3428,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, 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 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(); @@ -2338,7 +3472,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 +3488,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 +3541,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 +3558,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 (funding_txo, mon_id, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone(); + let (funding_txo, 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(funding_txo, mon_id); expect_payment_claimed!(nodes[0], payment_hash_0, 100_000); @@ -2415,10 +3587,16 @@ 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!"), @@ -2427,7 +3605,11 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) { nodes[1].node.handle_commitment_signed(&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 +3620,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 +3662,32 @@ 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(&nodes[0].node.get_our_node_id(), &send_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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 +3696,21 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f nodes[0].node.handle_commitment_signed(&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 +3731,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 +3756,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 +3776,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 +3821,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 +3838,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 (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, 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 (outpoint, latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (outpoint, 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(outpoint, 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 +3891,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::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -2648,14 +3917,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 (funding_tx, latest_update_1, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + let (funding_tx, 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 +3942,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(funding_tx, latest_update_1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[1], 0); @@ -2677,18 +3962,33 @@ 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, 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, + 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()); @@ -2706,7 +4006,8 @@ fn double_temp_error() { nodes[0].node.handle_commitment_signed(&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); @@ -2718,25 +4019,27 @@ fn double_temp_error() { 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, 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, 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 +4066,79 @@ 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), Some(chan_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(chan_config), 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).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ) + .unwrap(); } else { - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0).unwrap(); + nodes[1] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ) + .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.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), funding_tx.clone()).unwrap(); + 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 + .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 +4151,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 +4176,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 +4214,79 @@ 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), Some(chan_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(chan_config), 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).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ) + .unwrap(); } else { - nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0).unwrap(); + nodes[1] + .node + .accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ) + .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.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), funding_tx.clone()).unwrap(); + 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 + .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 +4294,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 +4310,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 +4328,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); - - check_closed_event!(nodes[1], 1, ClosureReason::DisconnectedPeer, [nodes[0].node.get_our_node_id()], 100000); + 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 + ); assert!(nodes[1].node.list_channels().is_empty()); } @@ -2946,8 +4371,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 +4382,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 +4403,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 +4414,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(&nodes[0].node.get_our_node_id(), &as_htlc_fulfill_updates.commitment_signed); + nodes[1].node.handle_commitment_signed( + &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 +4428,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 +4449,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 +4490,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 +4505,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 +4518,24 @@ 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(&nodes[2].node.get_our_node_id(), &cs_updates.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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(&nodes[1].node.get_our_node_id(), &bs_commitment_signed); + nodes[2] + .node + .handle_commitment_signed(&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 +4551,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 +4593,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 (outpoint, _, 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(outpoint, 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 (outpoint, _, 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(outpoint, 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 +4621,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 +4639,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 (outpoint, _, 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(outpoint, ab_update_id).unwrap(); + let (outpoint, _, 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(outpoint, 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 +4664,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 +4691,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 +4719,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 +4730,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 +4743,9 @@ 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(&nodes[2].node.get_our_node_id(), &cs_updates.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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()); @@ -3225,20 +4754,47 @@ 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()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan_id_bc, &nodes[2].node.get_our_node_id()) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[2].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed, + 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()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[0].node.get_our_node_id()) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed, + 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()); @@ -3253,8 +4809,18 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, } } - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id()).unwrap(); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, 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()) + .unwrap(); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + 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); @@ -3266,7 +4832,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); @@ -3283,7 +4857,14 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, 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, + ); } else { // While we forwarded the payment a while ago, we don't want to process events too early or // we'll run background tasks we wanted to test individually. @@ -3308,7 +4889,14 @@ fn do_test_durable_preimages_on_closed_channel(close_chans_before_reload: bool, reconnect_args.pending_raa.1 = true; reconnect_nodes(reconnect_args); - let (outpoint, ab_update_id, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_ab).unwrap().clone(); + let (outpoint, 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(outpoint, ab_update_id); expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), true, false); if !close_chans_before_reload { @@ -3352,7 +4940,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); @@ -3360,7 +4949,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. @@ -3369,7 +4961,9 @@ 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(&nodes[2].node.get_our_node_id(), &cs_updates.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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()); @@ -3378,7 +4972,11 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) { nodes[2].node.handle_commitment_signed(&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); @@ -3388,23 +4986,49 @@ 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 + ); 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan_id_ab, &nodes[1].node.get_our_node_id()) + .unwrap(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + 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().2; + let bc_update_id = + nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_bc).unwrap().2; 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), close_during_reload, false); + expect_payment_forwarded( + events.pop().unwrap(), + &nodes[1], + &nodes[0], + &nodes[2], + Some(1000), + close_during_reload, + false, + ); if close_during_reload { match events[0] { Event::ChannelClosed { .. } => {}, @@ -3416,7 +5040,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().2; + let post_ev_bc_update_id = + nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id_bc).unwrap().2; 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 @@ -3449,7 +5074,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); @@ -3460,12 +5086,18 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) { // The first update will be on the A <-> B channel, which we 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); } @@ -3484,10 +5116,18 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) { assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - let (route, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(&nodes[1], nodes[2], 1_000_000); - - nodes[1].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_secret_2) = + get_route_and_payment_hash!(&nodes[1], nodes[2], 1_000_000); + + 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()); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 2007a9e772c..9a683064c4d 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -8,53 +8,69 @@ // licenses. use bitcoin::blockdata::constants::ChainHash; -use bitcoin::blockdata::script::{Script, ScriptBuf, Builder}; +use bitcoin::blockdata::script::{Builder, Script, ScriptBuf}; use bitcoin::blockdata::transaction::Transaction; +use bitcoin::consensus::encode; use bitcoin::sighash; use bitcoin::sighash::EcdsaSighashType; -use bitcoin::consensus::encode; -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; - -use crate::ln::{ChannelId, PaymentPreimage, PaymentHash}; +use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE; +use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; + +use crate::chain::chaininterface::{ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator}; +use crate::chain::channelmonitor::{ + ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, CLOSED_CHANNEL_UPDATE_ID, + LATENCY_GRACE_PERIOD_BLOCKS, +}; +use crate::chain::transaction::{OutPoint, TransactionData}; +use crate::chain::BestBlock; +use crate::events::ClosureReason; +use crate::ln::chan_utils; +use crate::ln::chan_utils::{ + get_commitment_transaction_number_obscure_factor, htlc_success_tx_weight, + htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, + ChannelTransactionParameters, ClosingTransaction, CommitmentTransaction, + CounterpartyChannelTransactionParameters, CounterpartyCommitmentSecrets, + HTLCOutputInCommitment, HolderCommitmentTransaction, TxCreationKeys, MAX_HTLCS, +}; +use crate::ln::channelmanager::{ + self, ChannelShutdownState, CounterpartyForwardingInfo, HTLCFailureMsg, HTLCSource, + PendingHTLCInfo, PendingHTLCStatus, RAACommitmentOrder, SentHTLCId, BREAKDOWN_TIMEOUT, + MAX_LOCAL_BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::features::{ChannelTypeFeatures, InitFeatures}; use crate::ln::msgs; use crate::ln::msgs::DecodeError; -use crate::ln::script::{self, ShutdownScript}; -use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT, ChannelShutdownState}; -use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction}; -use crate::ln::chan_utils; use crate::ln::onion_utils::HTLCFailReason; -use crate::chain::BestBlock; -use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator}; -use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS, CLOSED_CHANNEL_UPDATE_ID}; -use crate::chain::transaction::{OutPoint, TransactionData}; -use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; -use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient}; -use crate::events::ClosureReason; +use crate::ln::script::{self, ShutdownScript}; +use crate::ln::{ChannelId, PaymentHash, PaymentPreimage}; use crate::routing::gossip::NodeId; -use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; -use crate::util::logger::{Logger, Record, WithContext}; +use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; +use crate::sign::{ChannelSigner, EntropySource, NodeSigner, Recipient, SignerProvider}; +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, Writeable, Writer}; use crate::io; use crate::prelude::*; -use core::{cmp,mem,fmt}; -use core::convert::TryInto; -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::convert::TryInto; +use core::ops::Deref; +use core::{cmp, fmt, mem}; use super::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint}; @@ -211,7 +227,7 @@ impl From> for OutboundHTLCOutcome { fn from(o: Option) -> Self { match o { None => OutboundHTLCOutcome::Success(None), - Some(r) => OutboundHTLCOutcome::Failure(r) + Some(r) => OutboundHTLCOutcome::Failure(r), } } } @@ -220,7 +236,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), } } } @@ -240,7 +256,8 @@ struct 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, @@ -440,14 +457,19 @@ define_state_flags!( define_state_flags!( "Flags that only apply to [`ChannelState::ChannelReady`].", - FUNDED_STATE, ChannelReadyFlags, [ - ("Indicates that we have sent a `commitment_signed` but are awaiting the responding \ + FUNDED_STATE, + ChannelReadyFlags, + [( + "Indicates that we have sent a `commitment_signed` but are awaiting the responding \ `revoke_and_ack` message. During this period, we can't generate new `commitment_signed` \ messages as we'd be unable to determine which HTLCs they included in their `revoke_and_ack` \ implicit ACK, so instead we have to hold them away temporarily to be sent later.", - AWAITING_REMOTE_REVOKE, state_flags::AWAITING_REMOTE_REVOKE, - is_awaiting_remote_revoke, set_awaiting_remote_revoke, clear_awaiting_remote_revoke) - ] + AWAITING_REMOTE_REVOKE, + state_flags::AWAITING_REMOTE_REVOKE, + is_awaiting_remote_revoke, + set_awaiting_remote_revoke, + clear_awaiting_remote_revoke + )] ); // Note that the order of this enum is implicitly defined by where each variant is placed. Take this @@ -515,7 +537,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 { @@ -534,14 +557,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 { @@ -550,18 +575,23 @@ 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(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(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) + && !flags.is_set(FundedStateFlags::PEER_DISCONNECTED.into()) + }, _ => { debug_assert!(false, "Can only generate new commitment within ChannelReady"); false @@ -569,14 +599,54 @@ 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_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 + ); } pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; @@ -586,7 +656,11 @@ pub const DEFAULT_MAX_HTLCS: u16 = 50; 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 + } } #[cfg(not(test))] @@ -661,13 +735,19 @@ impl fmt::Display for 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, } -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; @@ -676,9 +756,12 @@ 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 { +where + L::Target: Logger, +{ pub(super) fn from(logger: &'a L, context: &'b ChannelContext) -> Self - where S::Target: SignerProvider + where + S::Target: SignerProvider, { WithChannelContext { logger, @@ -753,8 +836,8 @@ struct HTLCStats { /// An enum gathering stats on commitment transaction, either local or remote. struct CommitmentStats<'a> { tx: CommitmentTransaction, // the transaction info - feerate_per_kw: u32, // the feerate included to build the transaction - total_fee_sat: u64, // the total fee included in the transaction + feerate_per_kw: u32, // the feerate included to build the transaction + total_fee_sat: u64, // the total fee included in the transaction num_nondust_htlcs: usize, // the number of HTLC outputs (dust HTLCs *non*-included) htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction local_balance_msat: u64, // local balance before fees *not* considering dust limits @@ -771,10 +854,7 @@ struct HTLCCandidate { impl HTLCCandidate { fn new(amount_msat: u64, origin: HTLCInitiator) -> Self { - Self { - amount_msat, - origin, - } + Self { amount_msat, origin } } } @@ -927,13 +1007,17 @@ impl_writeable_tlv_based!(PendingChannelMonitorUpdate, { /// The `ChannelPhase` enum describes the current phase in life of a lightning channel with each of /// its variants containing an appropriate channel struct. -pub(super) enum ChannelPhase where SP::Target: SignerProvider { +pub(super) enum ChannelPhase +where + SP::Target: SignerProvider, +{ UnfundedOutboundV1(OutboundV1Channel), UnfundedInboundV1(InboundV1Channel), Funded(Channel), } -impl<'a, SP: Deref> ChannelPhase where +impl<'a, SP: Deref> ChannelPhase +where SP::Target: SignerProvider, ::EcdsaSigner: ChannelSigner, { @@ -977,7 +1061,10 @@ impl UnfundedChannelContext { } /// 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 @@ -1020,7 +1107,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_holder_commitment_transaction_number: u64, cur_counterparty_commitment_transaction_number: u64, value_to_self_msat: u64, // Excluding all pending_htlcs, fees, and anchor outputs @@ -1265,7 +1351,10 @@ pub(super) struct ChannelContext where SP::Target: SignerProvider { blocked_monitor_updates: Vec, } -impl ChannelContext where SP::Target: SignerProvider { +impl ChannelContext +where + SP::Target: SignerProvider, +{ /// Allowed in any state (including after shutdown) pub fn get_update_time_counter(&self) -> u32 { self.update_time_counter @@ -1291,31 +1380,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, } @@ -1323,16 +1422,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 @@ -1390,7 +1495,7 @@ impl ChannelContext where SP::Target: SignerProvider { /// Returns the holder signer for this channel. #[cfg(test)] pub fn get_signer(&self) -> &ChannelSignerType { - return &self.holder_signer + return &self.holder_signer; } /// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0, @@ -1441,8 +1546,10 @@ impl ChannelContext where SP::Target: SignerProvider { } 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 { @@ -1471,8 +1578,7 @@ impl ChannelContext where SP::Target: SignerProvider { // 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.channel_value_satoshis * 1000 * 9 / 10, - - self.counterparty_max_htlc_value_in_flight_msat + self.counterparty_max_htlc_value_in_flight_msat, ); } @@ -1491,7 +1597,7 @@ impl ChannelContext where SP::Target: SignerProvider { let holder_reserve = self.holder_selected_channel_reserve_satoshis; cmp::min( (self.channel_value_satoshis - counterparty_reserve - holder_reserve) * 1000, - party_max_htlc_value_in_flight_msat + party_max_htlc_value_in_flight_msat, ) }) } @@ -1508,14 +1614,17 @@ impl ChannelContext where SP::Target: SignerProvider { cmp::max(self.config.options.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA) } - pub fn get_max_dust_htlc_exposure_msat(&self, - fee_estimator: &LowerBoundedFeeEstimator) -> u64 - where F::Target: FeeEstimator + pub fn get_max_dust_htlc_exposure_msat( + &self, fee_estimator: &LowerBoundedFeeEstimator, + ) -> u64 + where + F::Target: FeeEstimator, { match self.config.options.max_dust_htlc_exposure { MaxDustHTLCExposure::FeeRateMultiplier(multiplier) => { - let feerate_per_kw = fee_estimator.bounded_sat_per_1000_weight( - ConfirmationTarget::OnChainSweep) as u64; + let feerate_per_kw = fee_estimator + .bounded_sat_per_1000_weight(ConfirmationTarget::OnChainSweep) + as u64; feerate_per_kw.saturating_mul(multiplier) }, MaxDustHTLCExposure::FixedLimitMsat(limit) => limit, @@ -1574,10 +1683,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 @@ -1591,8 +1700,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)) } /// Transaction nomenclature is somewhat confusing here as there are many different cases - a @@ -1609,14 +1718,24 @@ 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, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, logger: &L) -> CommitmentStats - where L::Target: Logger + fn build_commitment_transaction( + &self, commitment_number: u64, keys: &TxCreationKeys, local: bool, + generated_by_local: bool, logger: &L, + ) -> CommitmentStats + where + L::Target: Logger, { - let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new(); + let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = + Vec::new(); let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len(); - let mut included_non_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs); + let mut included_non_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = + Vec::with_capacity(num_htlcs); - let broadcaster_dust_limit_satoshis = if local { self.holder_dust_limit_satoshis } else { self.counterparty_dust_limit_satoshis }; + let broadcaster_dust_limit_satoshis = if local { + self.holder_dust_limit_satoshis + } else { + self.counterparty_dust_limit_satoshis + }; let mut remote_htlc_total_msat = 0; let mut local_htlc_total_msat = 0; let mut value_to_self_msat_offset = 0; @@ -1626,9 +1745,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!(!self.is_outbound()); !generated_by_local }, - FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { debug_assert!(!self.is_outbound()); !generated_by_local }, - FeeUpdateState::Outbound => { assert!(self.is_outbound()); generated_by_local }, + FeeUpdateState::RemoteAnnounced => { + debug_assert!(!self.is_outbound()); + !generated_by_local + }, + FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { + debug_assert!(!self.is_outbound()); + !generated_by_local + }, + FeeUpdateState::Outbound => { + assert!(self.is_outbound()); + generated_by_local + }, } { feerate_per_kw = feerate; } @@ -1647,9 +1775,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 { @@ -1691,8 +1819,12 @@ impl ChannelContext where SP::Target: SignerProvider { for ref htlc in self.pending_inbound_htlcs.iter() { let (include, state_name) = match htlc.state { InboundHTLCState::RemoteAnnounced(_) => (!generated_by_local, "RemoteAnnounced"), - InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => (!generated_by_local, "AwaitingRemoteRevokeToAnnounce"), - InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => (true, "AwaitingAnnouncedRemoteRevoke"), + InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => { + (!generated_by_local, "AwaitingRemoteRevokeToAnnounce") + }, + InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => { + (true, "AwaitingAnnouncedRemoteRevoke") + }, InboundHTLCState::Committed => (true, "Committed"), InboundHTLCState::LocalRemoved(_) => (!generated_by_local, "LocalRemoved"), }; @@ -1701,7 +1833,14 @@ impl ChannelContext where SP::Target: SignerProvider { add_htlc_output!(htlc, false, None, state_name); remote_htlc_total_msat += htlc.amount_msat; } else { - log_trace!(logger, " ...not including inbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, &htlc.payment_hash, htlc.amount_msat, state_name); + log_trace!( + logger, + " ...not including inbound HTLC {} (hash {}) with value {} due to state ({})", + htlc.htlc_id, + &htlc.payment_hash, + htlc.amount_msat, + state_name + ); match &htlc.state { &InboundHTLCState::LocalRemoved(ref reason) => { if generated_by_local { @@ -1716,7 +1855,6 @@ impl ChannelContext where SP::Target: SignerProvider { } } - let mut outbound_htlc_preimages: Vec = Vec::new(); for ref htlc in self.pending_outbound_htlcs.iter() { @@ -1724,14 +1862,22 @@ impl ChannelContext where SP::Target: SignerProvider { OutboundHTLCState::LocalAnnounced(_) => (generated_by_local, "LocalAnnounced"), OutboundHTLCState::Committed => (true, "Committed"), OutboundHTLCState::RemoteRemoved(_) => (generated_by_local, "RemoteRemoved"), - OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) => (generated_by_local, "AwaitingRemoteRevokeToRemove"), - OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => (false, "AwaitingRemovedRemoteRevoke"), + OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) => { + (generated_by_local, "AwaitingRemoteRevokeToRemove") + }, + OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => { + (false, "AwaitingRemovedRemoteRevoke") + }, }; let preimage_opt = match htlc.state { OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(p)) => p, - OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(p)) => p, - OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(p)) => p, + OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success( + p, + )) => p, + OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(p)) => { + p + }, _ => None, }; @@ -1745,7 +1891,12 @@ 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, state_name); match htlc.state { - OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_))|OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) => { + OutboundHTLCState::AwaitingRemoteRevokeToRemove( + OutboundHTLCOutcome::Success(_), + ) + | OutboundHTLCState::AwaitingRemovedRemoteRevoke( + OutboundHTLCOutcome::Success(_), + ) => { value_to_self_msat_offset -= htlc.amount_msat as i64; }, OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(_)) => { @@ -1758,13 +1909,17 @@ impl ChannelContext where SP::Target: SignerProvider { } } - let value_to_self_msat: i64 = (self.value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset; + let value_to_self_msat: i64 = + (self.value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset; assert!(value_to_self_msat >= 0); // Note that in case they have several just-awaiting-last-RAA fulfills in-progress (ie // AwaitingRemoteRevokeToRemove or AwaitingRemovedRemoteRevoke) we may have allowed them to // "violate" their reserve value by couting those against it. Thus, we have to convert // everything to i64 before subtracting as otherwise we can overflow. - let value_to_remote_msat: i64 = (self.channel_value_satoshis * 1000) as i64 - (self.value_to_self_msat as i64) - (remote_htlc_total_msat as i64) - value_to_self_msat_offset; + let value_to_remote_msat: i64 = (self.channel_value_satoshis * 1000) as i64 + - (self.value_to_self_msat as i64) + - (remote_htlc_total_msat as i64) + - value_to_self_msat_offset; assert!(value_to_remote_msat >= 0); #[cfg(debug_assertions)] @@ -1776,54 +1931,101 @@ impl ChannelContext where SP::Target: SignerProvider { } else { self.counterparty_max_commitment_tx_output.lock().unwrap() }; - debug_assert!(broadcaster_max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.counterparty_selected_channel_reserve_satoshis.unwrap() as i64); - broadcaster_max_commitment_tx_output.0 = cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat as u64); - debug_assert!(broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= self.holder_selected_channel_reserve_satoshis as i64); - broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat as u64); - } - - let total_fee_sat = commit_tx_fee_sat(feerate_per_kw, included_non_dust_htlcs.len(), &self.channel_transaction_parameters.channel_type_features); - let anchors_val = if self.channel_transaction_parameters.channel_type_features.supports_anchors_zero_fee_htlc_tx() { ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 } as i64; + debug_assert!( + broadcaster_max_commitment_tx_output.0 <= value_to_self_msat as u64 + || value_to_self_msat / 1000 + >= self.counterparty_selected_channel_reserve_satoshis.unwrap() as i64 + ); + broadcaster_max_commitment_tx_output.0 = + cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat as u64); + debug_assert!( + broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat as u64 + || value_to_remote_msat / 1000 + >= self.holder_selected_channel_reserve_satoshis as i64 + ); + broadcaster_max_commitment_tx_output.1 = + cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat as u64); + } + + let total_fee_sat = commit_tx_fee_sat( + feerate_per_kw, + included_non_dust_htlcs.len(), + &self.channel_transaction_parameters.channel_type_features, + ); + let anchors_val = if self + .channel_transaction_parameters + .channel_type_features + .supports_anchors_zero_fee_htlc_tx() + { + ANCHOR_OUTPUT_VALUE_SATOSHI * 2 + } else { + 0 + } as i64; let (value_to_self, value_to_remote) = if self.is_outbound() { - (value_to_self_msat / 1000 - anchors_val - total_fee_sat as i64, value_to_remote_msat / 1000) + ( + value_to_self_msat / 1000 - anchors_val - total_fee_sat as i64, + value_to_remote_msat / 1000, + ) } else { - (value_to_self_msat / 1000, value_to_remote_msat / 1000 - anchors_val - total_fee_sat as i64) + ( + value_to_self_msat / 1000, + value_to_remote_msat / 1000 - anchors_val - total_fee_sat as i64, + ) }; let mut value_to_a = if local { value_to_self } else { value_to_remote }; let mut value_to_b = if local { value_to_remote } else { value_to_self }; let (funding_pubkey_a, funding_pubkey_b) = if local { - (self.get_holder_pubkeys().funding_pubkey, self.get_counterparty_pubkeys().funding_pubkey) + ( + self.get_holder_pubkeys().funding_pubkey, + self.get_counterparty_pubkeys().funding_pubkey, + ) } else { - (self.get_counterparty_pubkeys().funding_pubkey, self.get_holder_pubkeys().funding_pubkey) + ( + self.get_counterparty_pubkeys().funding_pubkey, + self.get_holder_pubkeys().funding_pubkey, + ) }; if value_to_a >= (broadcaster_dust_limit_satoshis as i64) { - log_trace!(logger, " ...including {} output with value {}", if local { "to_local" } else { "to_remote" }, value_to_a); + log_trace!( + logger, + " ...including {} output with value {}", + if local { "to_local" } else { "to_remote" }, + value_to_a + ); } else { value_to_a = 0; } if value_to_b >= (broadcaster_dust_limit_satoshis as i64) { - log_trace!(logger, " ...including {} output with value {}", if local { "to_remote" } else { "to_local" }, value_to_b); + log_trace!( + logger, + " ...including {} output with value {}", + if local { "to_remote" } else { "to_local" }, + value_to_b + ); } else { value_to_b = 0; } let num_nondust_htlcs = included_non_dust_htlcs.len(); - let channel_parameters = - if local { self.channel_transaction_parameters.as_holder_broadcastable() } - else { self.channel_transaction_parameters.as_counterparty_broadcastable() }; - let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, - value_to_a as u64, - value_to_b as u64, - funding_pubkey_a, - funding_pubkey_b, - keys.clone(), - feerate_per_kw, - &mut included_non_dust_htlcs, - &channel_parameters + let channel_parameters = if local { + self.channel_transaction_parameters.as_holder_broadcastable() + } else { + self.channel_transaction_parameters.as_counterparty_broadcastable() + }; + let tx = CommitmentTransaction::new_with_auxiliary_htlc_data( + commitment_number, + value_to_a as u64, + value_to_b as u64, + funding_pubkey_a, + funding_pubkey_b, + keys.clone(), + feerate_per_kw, + &mut included_non_dust_htlcs, + &channel_parameters, ); let mut htlcs_included = included_non_dust_htlcs; // The unwrap is safe, because all non-dust HTLCs have been assigned an output index @@ -1850,12 +2052,20 @@ impl ChannelContext where SP::Target: SignerProvider { /// The result is a transaction which we can revoke broadcastership of (ie a "local" transaction) /// TODO Some magic rust shit to compile-time check this? fn build_holder_transaction_keys(&self, commitment_number: u64) -> TxCreationKeys { - let per_commitment_point = self.holder_signer.as_ref().get_per_commitment_point(commitment_number, &self.secp_ctx); + let per_commitment_point = + self.holder_signer.as_ref().get_per_commitment_point(commitment_number, &self.secp_ctx); let delayed_payment_base = &self.get_holder_pubkeys().delayed_payment_basepoint; let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint; let counterparty_pubkeys = self.get_counterparty_pubkeys(); - TxCreationKeys::derive_new(&self.secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint) + TxCreationKeys::derive_new( + &self.secp_ctx, + &per_commitment_point, + delayed_payment_base, + htlc_basepoint, + &counterparty_pubkeys.revocation_basepoint, + &counterparty_pubkeys.htlc_basepoint, + ) } #[inline] @@ -1867,14 +2077,24 @@ impl ChannelContext where SP::Target: SignerProvider { let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint; let counterparty_pubkeys = self.get_counterparty_pubkeys(); - TxCreationKeys::derive_new(&self.secp_ctx, &self.counterparty_cur_commitment_point.unwrap(), &counterparty_pubkeys.delayed_payment_basepoint, &counterparty_pubkeys.htlc_basepoint, revocation_basepoint, htlc_basepoint) + TxCreationKeys::derive_new( + &self.secp_ctx, + &self.counterparty_cur_commitment_point.unwrap(), + &counterparty_pubkeys.delayed_payment_basepoint, + &counterparty_pubkeys.htlc_basepoint, + revocation_basepoint, + htlc_basepoint, + ) } /// Gets the redeemscript for the funding transaction output (ie the funding transaction output /// pays to get_funding_redeemscript().to_v0_p2wsh()). /// Panics if called before accept_channel/InboundV1Channel::new pub fn get_funding_redeemscript(&self) -> ScriptBuf { - make_funding_redeemscript(&self.get_holder_pubkeys().funding_pubkey, self.counterparty_funding_pubkey()) + make_funding_redeemscript( + &self.get_holder_pubkeys().funding_pubkey, + self.counterparty_funding_pubkey(), + ) } fn counterparty_funding_pubkey(&self) -> &PublicKey { @@ -1921,15 +2141,21 @@ impl ChannelContext where SP::Target: SignerProvider { on_holder_tx_holding_cell_htlcs_count: 0, }; - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - (0, 0) - } else { - let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64; - (dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000, - dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000) - }; - 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 (htlc_timeout_dust_limit, htlc_success_dust_limit) = + if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + (0, 0) + } else { + let dust_buffer_feerate = + context.get_dust_buffer_feerate(outbound_feerate_update) as u64; + ( + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000, + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000, + ) + }; + 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() { stats.pending_htlcs_value_msat += htlc.amount_msat; if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat { @@ -1954,15 +2180,21 @@ impl ChannelContext where SP::Target: SignerProvider { on_holder_tx_holding_cell_htlcs_count: 0, }; - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - (0, 0) - } else { - let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64; - (dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000, - dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000) - }; - 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 (htlc_timeout_dust_limit, htlc_success_dust_limit) = + if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + (0, 0) + } else { + let dust_buffer_feerate = + context.get_dust_buffer_feerate(outbound_feerate_update) as u64; + ( + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000, + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000, + ) + }; + 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() { stats.pending_htlcs_value_msat += htlc.amount_msat; if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat { @@ -1995,9 +2227,11 @@ impl ChannelContext where SP::Target: SignerProvider { /// Doesn't bother handling the /// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC /// corner case properly. - pub fn get_available_balances(&self, fee_estimator: &LowerBoundedFeeEstimator) - -> AvailableBalances - where F::Target: FeeEstimator + pub fn get_available_balances( + &self, fee_estimator: &LowerBoundedFeeEstimator, + ) -> AvailableBalances + where + F::Target: FeeEstimator, { let context = &self; // Note that we have to handle overflow due to the above case. @@ -2006,24 +2240,28 @@ impl ChannelContext where SP::Target: SignerProvider { let mut balance_msat = context.value_to_self_msat; for ref htlc in context.pending_inbound_htlcs.iter() { - if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_)) = htlc.state { + if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_)) = htlc.state + { balance_msat += htlc.amount_msat; } } balance_msat -= outbound_stats.pending_htlcs_value_msat; - let outbound_capacity_msat = context.value_to_self_msat - .saturating_sub(outbound_stats.pending_htlcs_value_msat) - .saturating_sub( - context.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) * 1000); + let outbound_capacity_msat = context + .value_to_self_msat + .saturating_sub(outbound_stats.pending_htlcs_value_msat) + .saturating_sub( + context.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) * 1000, + ); let mut available_capacity_msat = outbound_capacity_msat; - let anchor_outputs_value_msat = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 - } else { - 0 - }; + let anchor_outputs_value_msat = + if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 + } else { + 0 + }; if context.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. @@ -2034,13 +2272,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 !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - real_dust_limit_timeout_sat += context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.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(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(htlc_dust, Some(())); + real_dust_limit_timeout_sat += context.feerate_per_kw as u64 + * htlc_timeout_tx_weight(context.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(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(htlc_dust, Some(())); if !context.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; @@ -2049,14 +2295,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; } @@ -2065,20 +2319,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 !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - real_dust_limit_success_sat += context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) / 1000; + real_dust_limit_success_sat += context.feerate_per_kw as u64 + * htlc_success_tx_weight(context.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(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(htlc_above_dust, None); - let holder_selected_chan_reserve_msat = context.holder_selected_channel_reserve_satoshis * 1000; - let remote_balance_msat = (context.channel_value_satoshis * 1000 - context.value_to_self_msat) + let holder_selected_chan_reserve_msat = + context.holder_selected_channel_reserve_satoshis * 1000; + let remote_balance_msat = (context.channel_value_satoshis * 1000 + - context.value_to_self_msat) .saturating_sub(inbound_stats.pending_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); } } @@ -2092,49 +2357,73 @@ impl ChannelContext where SP::Target: SignerProvider { let mut dust_exposure_dust_limit_msat = 0; let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure_msat(fee_estimator); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.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(context.get_channel_type()) / 1000, - context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000) - }; - let on_counterparty_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat; - if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_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(max_dust_htlc_exposure_msat.saturating_sub(on_counterparty_dust_htlc_exposure_msat)); - dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000); + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = + if context.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(context.get_channel_type()) + / 1000, + context.holder_dust_limit_satoshis + + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) + / 1000, + ) + }; + let on_counterparty_dust_htlc_exposure_msat = inbound_stats + .on_counterparty_tx_dust_exposure_msat + + outbound_stats.on_counterparty_tx_dust_exposure_msat; + if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_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( + max_dust_htlc_exposure_msat.saturating_sub(on_counterparty_dust_htlc_exposure_msat), + ); + dust_exposure_dust_limit_msat = + cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000); } - let on_holder_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat; - if on_holder_dust_htlc_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) { + let on_holder_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + + outbound_stats.on_holder_tx_dust_exposure_msat; + if on_holder_dust_htlc_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(on_holder_dust_htlc_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(on_holder_dust_htlc_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 - outbound_stats.pending_htlcs_value_msat); + available_capacity_msat = cmp::min( + available_capacity_msat, + context.counterparty_max_htlc_value_in_flight_msat + - outbound_stats.pending_htlcs_value_msat, + ); if outbound_stats.pending_htlcs + 1 > context.counterparty_max_accepted_htlcs as u32 { available_capacity_msat = 0; } AvailableBalances { - inbound_capacity_msat: cmp::max(context.channel_value_satoshis as i64 * 1000 + inbound_capacity_msat: cmp::max( + context.channel_value_satoshis as i64 * 1000 - context.value_to_self_msat as i64 - context.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64 - context.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, @@ -2144,7 +2433,10 @@ impl ChannelContext where SP::Target: SignerProvider { pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option) { let context = &self; - (context.holder_selected_channel_reserve_satoshis, context.counterparty_selected_channel_reserve_satoshis) + ( + context.holder_selected_channel_reserve_satoshis, + context.counterparty_selected_channel_reserve_satoshis, + ) } /// Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the @@ -2157,21 +2449,34 @@ impl ChannelContext where SP::Target: SignerProvider { /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added. /// /// Dust HTLCs are excluded. - fn next_local_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 { + fn next_local_commit_tx_fee_msat( + &self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>, + ) -> u64 { let context = &self; assert!(context.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context + .get_channel_type() + .supports_anchors_zero_fee_htlc_tx() + { (0, 0) } else { - (context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) / 1000, - context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.get_channel_type()) / 1000) + ( + context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) + / 1000, + context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.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 { @@ -2182,13 +2487,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. @@ -2197,12 +2502,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. @@ -2214,7 +2519,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 }, @@ -2229,9 +2534,14 @@ impl ChannelContext where SP::Target: SignerProvider { { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type); + fee = commit_tx_fee_msat( + context.feerate_per_kw, + num_htlcs - 1, + &context.channel_type, + ); } - 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, @@ -2246,7 +2556,8 @@ impl ChannelContext where SP::Target: SignerProvider { }, feerate: context.feerate_per_kw, }; - *context.next_local_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info); + *context.next_local_commitment_tx_fee_info_cached.lock().unwrap() = + Some(commitment_tx_info); } res } @@ -2261,21 +2572,34 @@ impl ChannelContext where SP::Target: SignerProvider { /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added. /// /// Dust HTLCs are excluded. - fn next_remote_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 { + fn next_remote_commit_tx_fee_msat( + &self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>, + ) -> u64 { let context = &self; assert!(!context.is_outbound()); - let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context + .get_channel_type() + .supports_anchors_zero_fee_htlc_tx() + { (0, 0) } else { - (context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) / 1000, - context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.get_channel_type()) / 1000) + ( + context.feerate_per_kw as u64 * htlc_success_tx_weight(context.get_channel_type()) + / 1000, + context.feerate_per_kw as u64 * htlc_timeout_tx_weight(context.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; + } match htlc.origin { HTLCInitiator::LocalOffered => { if htlc.amount_msat / 1000 >= real_dust_limit_success_sat { @@ -2286,7 +2610,7 @@ impl ChannelContext where SP::Target: SignerProvider { if htlc.amount_msat / 1000 >= real_dust_limit_timeout_sat { addl_htlcs += 1; } - } + }, } // When calculating the set of HTLCs which will be included in their next commitment_signed, all @@ -2295,20 +2619,20 @@ 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, _ => {}, } @@ -2320,9 +2644,14 @@ impl ChannelContext where SP::Target: SignerProvider { { let mut fee = res; if fee_spike_buffer_htlc.is_some() { - fee = commit_tx_fee_msat(context.feerate_per_kw, num_htlcs - 1, &context.channel_type); + fee = commit_tx_fee_msat( + context.feerate_per_kw, + num_htlcs - 1, + &context.channel_type, + ); } - 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, @@ -2336,22 +2665,27 @@ impl ChannelContext where SP::Target: SignerProvider { }, feerate: context.feerate_per_kw, }; - *context.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info); + *context.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, } } @@ -2365,9 +2699,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) -> Option { - self.if_unbroadcasted_funding(|| + self.if_unbroadcasted_funding(|| { self.channel_transaction_parameters.funding_outpoint.map(|txo| txo.txid) - ) + }) } /// Returns whether the channel is funded in a batch. @@ -2386,7 +2720,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, should_broadcast: bool, closure_reason: ClosureReason) -> ShutdownResult { + pub fn force_shutdown( + &mut self, 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 @@ -2400,9 +2736,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) = self.get_funding_txo() { @@ -2415,14 +2756,25 @@ 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 = CLOSED_CHANNEL_UPDATE_ID; - Some((self.get_counterparty_node_id(), funding_txo, self.channel_id(), ChannelMonitorUpdate { - update_id: self.latest_monitor_update_id, - counterparty_node_id: Some(self.counterparty_node_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, + counterparty_node_id: Some(self.counterparty_node_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(); let unbroadcasted_funding_tx = self.unbroadcasted_funding(); @@ -2443,19 +2795,43 @@ impl ChannelContext where SP::Target: SignerProvider { } /// Only allowed after [`Self::channel_transaction_parameters`] is set. - fn get_funding_signed_msg(&mut self, logger: &L) -> (CommitmentTransaction, Option) where L::Target: Logger { + fn get_funding_signed_msg( + &mut self, logger: &L, + ) -> (CommitmentTransaction, Option) + where + L::Target: Logger, + { let counterparty_keys = self.build_remote_transaction_keys(); - let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number + 1, &counterparty_keys, false, false, logger).tx; + let counterparty_initial_commitment_tx = self + .build_commitment_transaction( + self.cur_counterparty_commitment_transaction_number + 1, + &counterparty_keys, + false, + false, + logger, + ) + .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 {}", - &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) + ); match &self.holder_signer { // TODO (arik): move match into calling method for Taproot ChannelSignerType::Ecdsa(ecdsa) => { - let funding_signed = ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.secp_ctx) + let funding_signed = ecdsa + .sign_counterparty_commitment( + &counterparty_initial_commitment_tx, + Vec::new(), + Vec::new(), + &self.secp_ctx, + ) .map(|(signature, _)| msgs::FundingSigned { channel_id: self.channel_id(), signature, @@ -2465,10 +2841,12 @@ impl ChannelContext where SP::Target: SignerProvider { .ok(); if funding_signed.is_none() { - #[cfg(not(async_signing))] { + #[cfg(not(async_signing))] + { panic!("Failed to get signature for funding_signed"); } - #[cfg(async_signing)] { + #[cfg(async_signing)] + { log_trace!(logger, "Counterparty commitment signature not available for funding_signed message; setting signer_pending_funding"); self.signer_pending_funding = true; } @@ -2482,7 +2860,7 @@ impl ChannelContext where SP::Target: SignerProvider { }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), } } } @@ -2496,7 +2874,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 { @@ -2515,8 +2895,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)) } @@ -2524,7 +2908,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)) } @@ -2532,21 +2918,34 @@ pub(crate) fn get_legacy_default_holder_selected_channel_reserve_satoshis(channe // Get the fee cost in SATS of a commitment tx with a given number of HTLC outputs. // Note that num_htlcs should not include dust HTLCs. #[inline] -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 +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 } // Get the fee cost in MSATS 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_msat(feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures) -> u64 { +pub(crate) fn commit_tx_fee_msat( + feerate_per_kw: u32, num_htlcs: usize, channel_type_features: &ChannelTypeFeatures, +) -> u64 { // Note that we need to divide before multiplying to round properly, // since the lowest denomination of bitcoin on-chain is the satoshi. - (commitment_tx_base_weight(channel_type_features) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) * feerate_per_kw as u64 / 1000 * 1000 + (commitment_tx_base_weight(channel_type_features) + + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) + * feerate_per_kw as u64 + / 1000 * 1000 } // 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 Channel where SP::Target: SignerProvider { +pub(super) struct Channel +where + SP::Target: SignerProvider, +{ pub context: ChannelContext, } @@ -2586,7 +2985,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 { @@ -2596,7 +2995,7 @@ impl FailHTLCContents for ([u8; 32], u16) { HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, sha256_of_onion: self.0, - failure_code: self.1 + failure_code: self.1, } } } @@ -2615,14 +3014,18 @@ impl FailHTLCMessageName for msgs::UpdateFailMalformedHTLC { } } -impl Channel where +impl Channel +where SP::Target: SignerProvider, - ::EcdsaSigner: WriteableEcdsaChannelSigner + ::EcdsaSigner: WriteableEcdsaChannelSigner, { 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 @@ -2639,7 +3042,10 @@ impl Channel where return Ok(()); } } - return Err(ChannelError::Close(format!("Peer's feerate much too low. Actual: {}. Our expected lower limit: {}", feerate_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 + ))); } Ok(()) } @@ -2653,9 +3059,10 @@ impl Channel 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) @@ -2667,27 +3074,34 @@ impl Channel where 1 + // witness element count 4 + // 4 element lengths (2 sigs, multisig dummy, and witness script) self.context.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) -> (ClosingTransaction, u64) { + fn build_closing_transaction( + &self, proposed_total_fee_satoshis: u64, skip_remote_output: bool, + ) -> (ClosingTransaction, u64) { 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.context.value_to_self_msat as i64) / 1000 - if self.context.is_outbound() { total_fee_satoshis as i64 } else { 0 }; - let mut value_to_counterparty: i64 = ((self.context.channel_value_satoshis * 1000 - self.context.value_to_self_msat) as i64 / 1000) - if self.context.is_outbound() { 0 } else { total_fee_satoshis as i64 }; + let mut value_to_holder: i64 = (self.context.value_to_self_msat as i64) / 1000 + - if self.context.is_outbound() { total_fee_satoshis as i64 } else { 0 }; + let mut value_to_counterparty: i64 = + ((self.context.channel_value_satoshis * 1000 - self.context.value_to_self_msat) as i64 + / 1000) - if self.context.is_outbound() { 0 } else { total_fee_satoshis as i64 }; if value_to_holder < 0 { assert!(self.context.is_outbound()); @@ -2697,7 +3111,9 @@ impl Channel where total_fee_satoshis += (-value_to_counterparty) as u64; } - 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; } @@ -2707,10 +3123,17 @@ impl Channel 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, + ); (closing_transaction, total_fee_satoshis) } @@ -2726,9 +3149,11 @@ impl Channel 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 - (&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( + &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()); @@ -2740,7 +3165,12 @@ impl Channel where } } - fn get_update_fulfill_htlc(&mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L) -> UpdateFulfillFetch where L::Target: Logger { + fn get_update_fulfill_htlc( + &mut self, htlc_id_arg: u64, payment_preimage_arg: PaymentPreimage, logger: &L, + ) -> 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, @@ -2757,23 +3187,34 @@ impl Channel 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; @@ -2814,27 +3255,42 @@ impl Channel where // Make sure we don't leave latest_monitor_update_id incremented here: self.context.latest_monitor_update_id -= 1; #[cfg(any(test, fuzzing))] - debug_assert!(self.context.historical_inbound_htlc_fulfills.contains(&htlc_id_arg)); + debug_assert!(self + .context + .historical_inbound_htlc_fulfills + .contains(&htlc_id_arg)); 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, }); #[cfg(any(test, fuzzing))] self.context.historical_inbound_htlc_fulfills.insert(htlc_id_arg); @@ -2847,11 +3303,21 @@ impl Channel 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 { @@ -2865,7 +3331,12 @@ impl Channel where } } - pub fn get_update_fulfill_htlc_and_commit(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger { + pub fn get_update_fulfill_htlc_and_commit( + &mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L, + ) -> 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, logger) { UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => { @@ -2881,8 +3352,12 @@ impl Channel 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; @@ -2890,14 +3365,21 @@ impl Channel 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 {}, } @@ -2911,8 +3393,12 @@ impl Channel where /// If we do fail twice, we `debug_assert!(false)` and return `Ok(None)`. Thus, this will always /// return `Ok(_)` if preconditions are met. In any case, `Err`s will only be /// [`ChannelError::Ignore`]. - 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?")) } @@ -2922,8 +3408,11 @@ impl Channel 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?")) } @@ -2937,9 +3426,11 @@ impl Channel where /// return `Ok(_)` if preconditions are met. In any case, `Err`s will only be /// [`ChannelError::Ignore`]. 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"); } @@ -2962,8 +3453,11 @@ impl Channel where }, _ => { 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; } @@ -2988,28 +3482,45 @@ impl Channel where &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { #[cfg(any(test, fuzzing))] - debug_assert!(self.context.historical_inbound_htlc_fulfills.contains(&htlc_id_arg)); + debug_assert!(self + .context + .historical_inbound_htlc_fulfills + .contains(&htlc_id_arg)); return Ok(None); } }, - &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } | - &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => - { + &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } + | &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { debug_assert!(false, "Tried to fail an HTLC that was already failed"); - return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned())); + return Err(ChannelError::Ignore( + "Unable to find a pending HTLC which matched the given HTLC ID" + .to_owned(), + )); } }, - _ => {} + _ => {}, } } - 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(); @@ -3035,9 +3546,7 @@ impl Channel where /// Further, the channel must be immediately shut down after this with a call to /// [`ChannelContext::force_shutdown`]. pub fn unset_funding_info(&mut self, temporary_channel_id: ChannelId) { - debug_assert!(matches!( - self.context.channel_state, ChannelState::AwaitingChannelReady(_) - )); + debug_assert!(matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_))); self.context.channel_transaction_parameters.funding_outpoint = None; self.context.channel_id = temporary_channel_id; } @@ -3047,11 +3556,11 @@ impl Channel 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()); @@ -3073,81 +3582,123 @@ impl Channel 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, mut pending_forward_status: PendingHTLCStatus, - create_pending_htlc_status: F, fee_estimator: &LowerBoundedFeeEstimator, logger: &L + create_pending_htlc_status: F, fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Result<(), ChannelError> - where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus, - FE::Target: FeeEstimator, L::Target: Logger, + where + F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus, + FE::Target: FeeEstimator, + L::Target: Logger, { 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(), + )); } // We can't accept HTLCs sent after we've sent a shutdown. if self.context.channel_state.is_local_shutdown_sent() { - pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x4000|8); + pending_forward_status = + create_pending_htlc_status(self, pending_forward_status, 0x4000 | 8); } // 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.context.channel_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())); @@ -3159,10 +3710,18 @@ impl Channel where let inbound_stats = self.context.get_inbound_pending_htlc_stats(None); let outbound_stats = self.context.get_outbound_pending_htlc_stats(None); if inbound_stats.pending_htlcs + 1 > self.context.holder_max_accepted_htlcs as u32 { - 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 inbound_stats.pending_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 inbound_stats.pending_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 @@ -3179,103 +3738,164 @@ impl Channel 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 max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator); - let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - (0, 0) - } else { - let dust_buffer_feerate = self.context.get_dust_buffer_feerate(None) as u64; - (dust_buffer_feerate * htlc_timeout_tx_weight(self.context.get_channel_type()) / 1000, - dust_buffer_feerate * htlc_success_tx_weight(self.context.get_channel_type()) / 1000) - }; - let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis; + let max_dust_htlc_exposure_msat = + self.context.get_max_dust_htlc_exposure_msat(fee_estimator); + let (htlc_timeout_dust_limit, htlc_success_dust_limit) = + if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + (0, 0) + } else { + let dust_buffer_feerate = self.context.get_dust_buffer_feerate(None) as u64; + ( + dust_buffer_feerate * htlc_timeout_tx_weight(self.context.get_channel_type()) + / 1000, + dust_buffer_feerate * htlc_success_tx_weight(self.context.get_channel_type()) + / 1000, + ) + }; + let exposure_dust_limit_timeout_sats = + htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis; if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats { - let on_counterparty_tx_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat + msg.amount_msat; + let on_counterparty_tx_dust_htlc_exposure_msat = inbound_stats + .on_counterparty_tx_dust_exposure_msat + + outbound_stats.on_counterparty_tx_dust_exposure_msat + + msg.amount_msat; if on_counterparty_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 counterparty commitment tx", on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat); - pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|7); + pending_forward_status = + create_pending_htlc_status(self, pending_forward_status, 0x1000 | 7); } } - let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis; + 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 = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat + msg.amount_msat; + let on_holder_tx_dust_htlc_exposure_msat = inbound_stats + .on_holder_tx_dust_exposure_msat + + outbound_stats.on_holder_tx_dust_exposure_msat + + msg.amount_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); - pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|7); + pending_forward_status = + create_pending_htlc_status(self, pending_forward_status, 0x1000 | 7); } } - let pending_value_to_self_msat = - self.context.value_to_self_msat + inbound_stats.pending_htlcs_value_msat - removed_outbound_total_msat; + let pending_value_to_self_msat = self.context.value_to_self_msat + + inbound_stats.pending_htlcs_value_msat + - removed_outbound_total_msat; let pending_remote_value_msat = self.context.channel_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.context.is_outbound() { 0 } else { - let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); + let remote_commit_tx_fee_msat = if self.context.is_outbound() { + 0 + } else { + let htlc_candidate = + HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); self.context.next_remote_commit_tx_fee_msat(htlc_candidate, None) // Don't include the extra fee spike buffer HTLC in calculations }; - let anchor_outputs_value_msat = if !self.context.is_outbound() && self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + let anchor_outputs_value_msat = if !self.context.is_outbound() + && self.context.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.context.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.context.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.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 - } else { - 0 - }; + let anchor_outputs_value_msat = + if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { + ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000 + } else { + 0 + }; if !self.context.is_outbound() { // `Some(())` is for the fee spike buffer we keep for the remote. This deviates from // the spec because the fee spike buffer requirement doesn't exist on the receiver's // side, only on the sender's. Note that with anchor outputs we are no longer as // sensitive to fee spikes, so we need to account for them. let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered); - let mut remote_fee_cost_incl_stuck_buffer_msat = self.context.next_remote_commit_tx_fee_msat(htlc_candidate, Some(())); + let mut remote_fee_cost_incl_stuck_buffer_msat = + self.context.next_remote_commit_tx_fee_msat(htlc_candidate, Some(())); if !self.context.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(msg.amount_msat).saturating_sub(self.context.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(msg.amount_msat) + .saturating_sub(self.context.holder_selected_channel_reserve_satoshis * 1000) + .saturating_sub(anchor_outputs_value_msat) + < remote_fee_cost_incl_stuck_buffer_msat + { // Note that if the pending_forward_status is not updated here, then it's because we're already failing // the HTLC, i.e. its status is already set to failing. log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", &self.context.channel_id()); - pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|7); + pending_forward_status = + create_pending_htlc_status(self, pending_forward_status, 0x1000 | 7); } } else { // 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(htlc_candidate, None); - if self.context.value_to_self_msat < self.context.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(htlc_candidate, None); + if self.context.value_to_self_msat + < self.context.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(), + )); } if self.context.channel_state.is_local_shutdown_sent() { @@ -3298,19 +3918,29 @@ impl Channel where /// Marks an outbound HTLC which we have received update_fail/fulfill/malformed #[inline] - fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option, fail_reason: Option) -> Result<&OutboundHTLCOutput, ChannelError> { - assert!(!(check_preimage.is_some() && fail_reason.is_some()), "cannot fail while we have a preimage"); + fn mark_outbound_htlc_removed( + &mut self, htlc_id: u64, check_preimage: Option, + fail_reason: Option, + ) -> Result<&OutboundHTLCOutput, ChannelError> { + assert!( + !(check_preimage.is_some() && fail_reason.is_some()), + "cannot fail while we have a preimage" + ); for htlc in self.context.pending_outbound_htlcs.iter_mut() { if htlc.htlc_id == htlc_id { let outcome = match check_preimage { None => fail_reason.into(), Some(payment_preimage) => { - 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 + ))); } OutboundHTLCOutcome::Success(Some(payment_preimage)) - } + }, }; match htlc.state { OutboundHTLCState::LocalAnnounced(_) => @@ -3327,107 +3957,174 @@ impl Channel 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), ChannelError> { + pub fn update_fulfill_htlc( + &mut self, msg: &msgs::UpdateFulfillHTLC, + ) -> Result<(HTLCSource, u64), ChannelError> { 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, Some(msg.payment_preimage), None).map(|htlc| (htlc.source.clone(), htlc.amount_msat)) + self.mark_outbound_htlc_removed(msg.htlc_id, Some(msg.payment_preimage), None) + .map(|htlc| (htlc.source.clone(), htlc.amount_msat)) } - pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> { + pub fn update_fail_htlc( + &mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason, + ) -> Result<(), ChannelError> { 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, None, Some(fail_reason))?; Ok(()) } - pub fn update_fail_malformed_htlc(&mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> { + pub fn update_fail_malformed_htlc( + &mut self, msg: &msgs::UpdateFailMalformedHTLC, fail_reason: HTLCFailReason, + ) -> Result<(), ChannelError> { 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, None, Some(fail_reason))?; Ok(()) } - 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, { 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(), + )); } let funding_script = self.context.get_funding_redeemscript(); - let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); + let keys = self + .context + .build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); - let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger); + let commitment_stats = self.context.build_commitment_transaction( + self.context.cur_holder_commitment_transaction_number, + &keys, + true, + false, + logger, + ); let commitment_txid = { let trusted_tx = commitment_stats.tx.trust(); let bitcoin_tx = trusted_tx.built_transaction(); - let sighash = bitcoin_tx.get_sighash_all(&funding_script, self.context.channel_value_satoshis); + let sighash = + bitcoin_tx.get_sighash_all(&funding_script, self.context.channel_value_satoshis); log_trace!(logger, "Checking commitment tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}", log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(self.context.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction), log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), &self.context.channel_id()); - if let Err(_) = self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.context.counterparty_funding_pubkey()) { - return Err(ChannelError::Close("Invalid commitment tx signature from peer".to_owned())); + if let Err(_) = self.context.secp_ctx.verify_ecdsa( + &sighash, + &msg.signature, + &self.context.counterparty_funding_pubkey(), + ) { + return Err(ChannelError::Close( + "Invalid commitment tx signature from peer".to_owned(), + )); } bitcoin_tx.txid }; - let mut htlcs_cloned: Vec<_> = commitment_stats.htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect(); + let mut htlcs_cloned: Vec<_> = commitment_stats + .htlcs_included + .iter() + .map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))) + .collect(); // If our counterparty updated the channel fee in this commitment transaction, check that // they can actually afford the new fee now. let update_fee = if let Some((_, update_state)) = self.context.pending_update_fee { update_state == FeeUpdateState::RemoteAnnounced - } else { false }; + } else { + false + }; if update_fee { debug_assert!(!self.context.is_outbound()); - let counterparty_reserve_we_require_msat = self.context.holder_selected_channel_reserve_satoshis * 1000; - if commitment_stats.remote_balance_msat < commitment_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 = + self.context.holder_selected_channel_reserve_satoshis * 1000; + if commitment_stats.remote_balance_msat + < commitment_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 self.context.is_outbound() { - let projected_commit_tx_info = self.context.next_local_commitment_tx_fee_info_cached.lock().unwrap().take(); + let projected_commit_tx_info = + self.context.next_local_commitment_tx_fee_info_cached.lock().unwrap().take(); *self.context.next_remote_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() + self.context.holding_cell_htlc_updates.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 { - assert_eq!(commitment_stats.total_fee_sat, info.fee / 1000); - } + && info.feerate == self.context.feerate_per_kw + { + assert_eq!(commitment_stats.total_fee_sat, info.fee / 1000); + } } } } if msg.htlc_signatures.len() != commitment_stats.num_nondust_htlcs { - return Err(ChannelError::Close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs))); + return Err(ChannelError::Close(format!( + "Got wrong number of HTLC signatures ({}) from remote. It must be {}", + msg.htlc_signatures.len(), + commitment_stats.num_nondust_htlcs + ))); } // Up to LDK 0.0.115, HTLC information was required to be duplicated in the @@ -3438,7 +4135,8 @@ impl Channel where // we randomly decide (in test/fuzzing builds) to use the new vec sometimes. #[allow(unused_assignments, unused_mut)] let mut separate_nondust_htlc_sources = false; - #[cfg(all(feature = "std", any(test, fuzzing)))] { + #[cfg(all(feature = "std", any(test, fuzzing)))] + { use core::hash::{BuildHasher, Hasher}; // Get a random value using the only std API to do so - the DefaultHasher let rand_val = std::collections::hash_map::RandomState::new().build_hasher().finish(); @@ -3449,18 +4147,45 @@ impl Channel where let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len()); for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() { if let Some(_) = htlc.transaction_output_index { - let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw, - self.context.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.context.channel_type, - &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + let htlc_tx = chan_utils::build_htlc_transaction( + &commitment_txid, + commitment_stats.feerate_per_kw, + self.context.get_counterparty_selected_contest_delay().unwrap(), + &htlc, + &self.context.channel_type, + &keys.broadcaster_delayed_payment_key, + &keys.revocation_key, + ); - let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys); - let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; - let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]); + let htlc_redeemscript = + chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys); + let htlc_sighashtype = + if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { + EcdsaSighashType::SinglePlusAnyoneCanPay + } else { + EcdsaSighashType::All + }; + let htlc_sighash = hash_to_message!( + &sighash::SighashCache::new(&htlc_tx) + .segwit_signature_hash( + 0, + &htlc_redeemscript, + htlc.amount_msat / 1000, + 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!(keys.countersignatory_htlc_key.to_public_key().serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id()); - if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) { - return Err(ChannelError::Close("Invalid HTLC tx signature from peer".to_owned())); + if let Err(_) = self.context.secp_ctx.verify_ecdsa( + &htlc_sighash, + &msg.htlc_signatures[idx], + &keys.countersignatory_htlc_key.to_public_key(), + ) { + return Err(ChannelError::Close( + "Invalid HTLC tx signature from peer".to_owned(), + )); } if !separate_nondust_htlc_sources { htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source_opt.take())); @@ -3481,10 +4206,16 @@ impl Channel where msg.signature, msg.htlc_signatures.clone(), &self.context.get_holder_pubkeys().funding_pubkey, - self.context.counterparty_funding_pubkey() + self.context.counterparty_funding_pubkey(), ); - self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages) + self.context + .holder_signer + .as_ref() + .validate_holder_commitment( + &holder_commitment_tx, + commitment_stats.outbound_htlc_preimages, + ) .map_err(|_| ChannelError::Close("Failed to validate our commitment".to_owned()))?; // Update state now that we've passed all the can-fail calls... @@ -3497,9 +4228,12 @@ impl Channel where } for htlc in self.context.pending_inbound_htlcs.iter_mut() { - let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state { - Some(forward_info.clone()) - } else { None }; + let new_forward = + if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state { + Some(forward_info.clone()) + } else { + None + }; if let Some(forward_info) = new_forward { log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToAnnounce due to commitment_signed in channel {}.", &htlc.payment_hash, &self.context.channel_id); @@ -3568,21 +4302,31 @@ impl Channel 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 }; + 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()); + 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)); } @@ -3590,26 +4334,45 @@ impl Channel 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!(!self.context.channel_state.is_monitor_update_in_progress()); - 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! @@ -3632,12 +4395,26 @@ impl Channel 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_count += 1, Err(e) => { @@ -3656,7 +4433,7 @@ impl Channel where panic!("Got a non-IgnoreError action trying to send holding cell HTLC"); }, } - } + }, } None }, @@ -3669,19 +4446,27 @@ impl Channel where let mut additional_monitor_update = if let UpdateFulfillFetch::NewClaim { monitor_update, .. } = self.get_update_fulfill_htlc(htlc_id, *payment_preimage, logger) - { monitor_update } else { unreachable!() }; + { + 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 { @@ -3701,7 +4486,11 @@ impl Channel 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() { @@ -3732,25 +4521,43 @@ impl Channel 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 !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())); } } @@ -3774,18 +4581,29 @@ impl Channel 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, @@ -3803,7 +4621,8 @@ impl Channel where // channel based on that, but stepping stuff here should be safe either way. self.context.channel_state.clear_awaiting_remote_revoke(); self.context.sent_message_awaiting_response = 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); self.context.cur_counterparty_commitment_transaction_number -= 1; @@ -3811,7 +4630,11 @@ impl Channel 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 revoked_htlcs = Vec::new(); let mut finalized_claimed_htlcs = Vec::new(); @@ -3824,7 +4647,8 @@ impl Channel 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| { @@ -3835,12 +4659,19 @@ impl Channel where } *expecting_peer_commitment_signed = true; false - } else { true } + } else { + true + } }); 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(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(reason) = outcome.clone() { + // We really want take() here, but, again, non-mut ref :( revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason)); } else { finalized_claimed_htlcs.push(htlc.source.clone()); @@ -3848,14 +4679,19 @@ impl Channel 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); @@ -3864,18 +4700,27 @@ impl Channel where log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to AwaitingAnnouncedRemoteRevoke", &htlc.payment_hash); htlc.state = InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info); require_commitment = true; - } else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info) = state { + } else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info) = + state + { match forward_info { 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.reason.clone())); + htlc.state = InboundHTLCState::LocalRemoved( + InboundHTLCRemovalReason::FailRelay(msg.reason.clone()), + ); 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) }, } @@ -3884,18 +4729,24 @@ impl Channel where log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", &htlc.payment_hash); to_forward_infos.push((forward_info, htlc.htlc_id)); 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); // Grab the preimage, if it exists, instead of cloning let mut reason = OutboundHTLCOutcome::Success(None); @@ -3905,18 +4756,25 @@ impl Channel where } } } - self.context.value_to_self_msat = (self.context.value_to_self_msat as i64 + value_to_self_msat_diff) as u64; + self.context.value_to_self_msat = + (self.context.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.context.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.context.is_outbound()); }, + FeeUpdateState::RemoteAnnounced => { + debug_assert!(!self.context.is_outbound()); + }, FeeUpdateState::AwaitingRemoteRevokeToAnnounce => { debug_assert!(!self.context.is_outbound()); log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce fee update {} to Committed", feerate); @@ -3928,19 +4786,24 @@ impl Channel 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))); } - } + }; } if self.context.channel_state.is_monitor_update_in_progress() { @@ -3975,7 +4838,14 @@ impl Channel 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) => { @@ -3992,25 +4862,41 @@ impl Channel where update_fail_htlcs.len() + update_fail_malformed_htlcs.len(), 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); } 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); } - } + }, } } /// 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?"); @@ -4025,9 +4911,11 @@ impl Channel where /// [`Channel`] 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.context.is_outbound() { panic!("Cannot send fee from inbound channel"); @@ -4042,30 +4930,61 @@ impl Channel where // Before proposing a feerate update, check that we can actually afford the new fee. let inbound_stats = self.context.get_inbound_pending_htlc_stats(Some(feerate_per_kw)); let outbound_stats = self.context.get_outbound_pending_htlc_stats(Some(feerate_per_kw)); - let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); - let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger); - let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + outbound_stats.on_holder_tx_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000; - let holder_balance_msat = commitment_stats.local_balance_msat - outbound_stats.holding_cell_msat; - if holder_balance_msat < buffer_fee_msat + self.context.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 { + let keys = self + .context + .build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); + let commitment_stats = self.context.build_commitment_transaction( + self.context.cur_holder_commitment_transaction_number, + &keys, + true, + true, + logger, + ); + let buffer_fee_msat = commit_tx_fee_sat( + feerate_per_kw, + commitment_stats.num_nondust_htlcs + + outbound_stats.on_holder_tx_holding_cell_htlcs_count as usize + + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, + self.context.get_channel_type(), + ) * 1000; + let holder_balance_msat = + commitment_stats.local_balance_msat - outbound_stats.holding_cell_msat; + if holder_balance_msat + < buffer_fee_msat + + self.context.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 holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat; - let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat; - let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator); + let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + + outbound_stats.on_holder_tx_dust_exposure_msat; + let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + + outbound_stats.on_counterparty_tx_dust_exposure_msat; + let max_dust_htlc_exposure_msat = + self.context.get_max_dust_htlc_exposure_msat(fee_estimator); if holder_tx_dust_exposure > 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 counterparty_tx_dust_exposure > 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 self.context.channel_state.is_awaiting_remote_revoke() || self.context.channel_state.is_monitor_update_in_progress() { + if self.context.channel_state.is_awaiting_remote_revoke() + || self.context.channel_state.is_monitor_update_in_progress() + { force_holding_cell = true; } @@ -4077,10 +4996,7 @@ impl Channel 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 @@ -4089,10 +5005,15 @@ impl Channel 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. - pub fn remove_uncommitted_htlcs_and_mark_paused(&mut self, logger: &L) -> Result<(), ()> where L::Target: Logger { + pub 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(()); } if self.context.channel_state.is_peer_disconnected() { @@ -4101,7 +5022,9 @@ impl Channel 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; } @@ -4121,7 +5044,8 @@ impl Channel 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. @@ -4158,7 +5082,12 @@ impl Channel where self.context.sent_message_awaiting_response = None; 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(()) } @@ -4173,17 +5102,20 @@ impl Channel 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(); } @@ -4191,12 +5123,12 @@ impl Channel 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(); @@ -4204,16 +5136,19 @@ impl Channel where // If we're past (or at) the AwaitingChannelReady stage on an outbound channel, try to // (re-)broadcast the funding transaction as we may have declined to broadcast it when we // first received the funding_signed. - let mut funding_broadcastable = - if self.context.is_outbound() && - (matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) || - matches!(self.context.channel_state, ChannelState::ChannelReady(_))) - { - self.context.funding_transaction.take() - } else { None }; + let mut funding_broadcastable = if self.context.is_outbound() + && (matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) + || matches!(self.context.channel_state, ChannelState::ChannelReady(_))) + { + self.context.funding_transaction.take() + } else { + None + }; // That said, if the funding transaction is already confirmed (ie we're active with a // minimum_depth over 0) don't bother re-broadcasting the confirmed funding tx. - if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) && self.context.minimum_depth != Some(0) { + if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) + && self.context.minimum_depth != Some(0) + { funding_broadcastable = None; } @@ -4227,38 +5162,64 @@ impl Channel where assert!(!self.context.is_outbound() || self.context.minimum_depth == Some(0), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); self.context.monitor_pending_channel_ready = false; - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let next_per_commitment_point = + self.context.holder_signer.as_ref().get_per_commitment_point( + self.context.cur_holder_commitment_transaction_number, + &self.context.secp_ctx, + ); Some(msgs::ChannelReady { channel_id: self.context.channel_id(), next_per_commitment_point, short_channel_id_alias: Some(self.context.outbound_scid_alias), }) - } 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, + ); if self.context.channel_state.is_peer_disconnected() { 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, funding_broadcastable, channel_ready, announcement_sigs + raa: None, + commitment_update: None, + order: RAACommitmentOrder::RevokeAndACKFirst, + accepted_htlcs, + failed_htlcs, + finalized_claimed_htlcs, + funding_broadcastable, + channel_ready, + announcement_sigs, }; } let raa = if self.context.monitor_pending_revoke_and_ack { Some(self.get_last_revoke_and_ack()) - } else { None }; + } else { + None + }; let commitment_update = if self.context.monitor_pending_commitment_signed { self.get_last_commitment_update_for_send(logger).ok() - } else { None }; + } else { + None + }; if commitment_update.is_some() { self.mark_awaiting_response(); } @@ -4271,30 +5232,56 @@ impl Channel 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, funding_broadcastable, channel_ready, announcement_sigs + raa, + commitment_update, + order, + accepted_htlcs, + failed_htlcs, + finalized_claimed_htlcs, + funding_broadcastable, + channel_ready, + announcement_sigs, } } - 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.context.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(), + )); } - Channel::::check_remote_fee(&self.context.channel_type, fee_estimator, msg.feerate_per_kw, Some(self.context.feerate_per_kw), logger)?; + Channel::::check_remote_fee( + &self.context.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. if !self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { let inbound_stats = self.context.get_inbound_pending_htlc_stats(None); let outbound_stats = self.context.get_outbound_pending_htlc_stats(None); - let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat; - let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat; - let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator); + let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + + outbound_stats.on_holder_tx_dust_exposure_msat; + let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + + outbound_stats.on_counterparty_tx_dust_exposure_msat; + let max_dust_htlc_exposure_msat = + self.context.get_max_dust_htlc_exposure_msat(fee_estimator); if holder_tx_dust_exposure > 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, holder_tx_dust_exposure))); @@ -4310,32 +5297,44 @@ impl Channel where /// Indicates that the signer may have some signatures for us, so we should retry if we're /// blocked. #[cfg(async_signing)] - 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, + { let commitment_update = if self.context.signer_pending_commitment_update { self.get_last_commitment_update_for_send(logger).ok() - } else { None }; + } else { + None + }; let funding_signed = if self.context.signer_pending_funding && !self.context.is_outbound() { self.context.get_funding_signed_msg(logger).1 - } else { None }; - let channel_ready = if funding_signed.is_some() { - self.check_get_channel_ready(0) - } else { None }; + } else { + None + }; + let channel_ready = + if funding_signed.is_some() { self.check_get_channel_ready(0) } else { None }; - log_trace!(logger, "Signer unblocked with {} commitment_update, {} funding_signed and {} channel_ready", + log_trace!( + logger, + "Signer unblocked with {} commitment_update, {} funding_signed and {} channel_ready", if commitment_update.is_some() { "a" } else { "no" }, if funding_signed.is_some() { "a" } else { "no" }, - if channel_ready.is_some() { "a" } else { "no" }); + if channel_ready.is_some() { "a" } else { "no" } + ); - SignerResumeUpdates { - commitment_update, - funding_signed, - channel_ready, - } + SignerResumeUpdates { commitment_update, funding_signed, channel_ready } } fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK { - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); - let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.cur_holder_commitment_transaction_number + 2); + let next_per_commitment_point = + self.context.holder_signer.as_ref().get_per_commitment_point( + self.context.cur_holder_commitment_transaction_number, + &self.context.secp_ctx, + ); + let per_commitment_secret = + self.context.holder_signer.as_ref().release_commitment_secret( + self.context.cur_holder_commitment_transaction_number + 2, + ); msgs::RevokeAndACK { channel_id: self.context.channel_id, per_commitment_secret, @@ -4346,7 +5345,12 @@ impl Channel 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(); @@ -4374,10 +5378,13 @@ impl Channel where update_fail_htlcs.push(msgs::UpdateFailHTLC { channel_id: self.context.channel_id(), htlc_id: htlc.htlc_id, - reason: err_packet.clone() + reason: err_packet.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, @@ -4396,36 +5403,49 @@ impl Channel where } } - let update_fee = if self.context.is_outbound() && self.context.pending_update_fee.is_some() { + let update_fee = if self.context.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).map(|(cu, _)| cu) { - 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 { - #[cfg(not(async_signing))] { - panic!("Failed to get signature for new commitment state"); - } - #[cfg(async_signing)] { - 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; + let commitment_signed = + if let Ok(update) = self.send_commitment_no_state_update(logger).map(|(cu, _)| cu) { + 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; } - return Err(()); - } - }; + update + } else { + #[cfg(not(async_signing))] + { + panic!("Failed to get signature for new commitment state"); + } + #[cfg(async_signing)] + { + 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, }) } @@ -4438,7 +5458,9 @@ impl Channel 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) @@ -4450,38 +5472,63 @@ impl Channel 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.context.cur_holder_commitment_transaction_number - 1; + let our_commitment_transaction = + INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_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); + 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, + ); 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\ @@ -4511,35 +5558,50 @@ impl Channel 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! - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let next_per_commitment_point = + self.context.holder_signer.as_ref().get_per_commitment_point( + self.context.cur_holder_commitment_transaction_number, + &self.context.secp_ctx, + ); return Ok(ReestablishResponses { channel_ready: Some(msgs::ChannelReady { channel_id: self.context.channel_id(), next_per_commitment_point, short_channel_id_alias: Some(self.context.outbound_scid_alias), }), - raa: None, commitment_update: None, + raa: None, + commitment_update: None, order: RAACommitmentOrder::CommitmentFirst, - shutdown_msg, announcement_sigs, + shutdown_msg, + announcement_sigs, }); } @@ -4571,48 +5633,82 @@ impl Channel where if is_awaiting_remote_revoke && !self.is_awaiting_monitor_update() { self.mark_awaiting_response(); } - 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.context.cur_holder_commitment_transaction_number == 1 { + let channel_ready = if msg.next_local_commitment_number == 1 + && INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number + == 1 + { // We should never have to worry about MonitorUpdateInProgress resending ChannelReady - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let next_per_commitment_point = + self.context.holder_signer.as_ref().get_per_commitment_point( + self.context.cur_holder_commitment_transaction_number, + &self.context.secp_ctx, + ); Some(msgs::ChannelReady { channel_id: self.context.channel_id(), next_per_commitment_point, short_channel_id_alias: Some(self.context.outbound_scid_alias), }) - } else { None }; + } else { + None + }; if msg.next_local_commitment_number == next_counterparty_commitment_number { if required_revoke.is_some() { - 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() { - 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 { Ok(ReestablishResponses { - channel_ready, shutdown_msg, announcement_sigs, + channel_ready, + shutdown_msg, + announcement_sigs, raa: required_revoke, commitment_update: self.get_last_commitment_update_for_send(logger).ok(), order: self.context.resend_order.clone(), @@ -4636,20 +5732,27 @@ impl Channel 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.context.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.context.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 @@ -4658,7 +5761,11 @@ impl Channel 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.context.is_outbound() { target_feerate } else { cmp::min(self.context.feerate_per_kw, target_feerate) }; + let min_feerate = if self.context.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); } @@ -4670,19 +5777,26 @@ impl Channel 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.context.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.context.channel_value_satoshis - (self.context.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.context.channel_value_satoshis - (self.context.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() } @@ -4700,7 +5814,9 @@ impl Channel 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; } @@ -4709,9 +5825,14 @@ impl Channel 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 @@ -4745,22 +5866,30 @@ impl Channel where ChannelSignerType::Ecdsa(ecdsa) => { let sig = ecdsa .sign_closing_transaction(&closing_tx, &self.context.secp_ctx) - .map_err(|()| ChannelError::Close("Failed to get signature for closing transaction.".to_owned()))?; + .map_err(|()| { + ChannelError::Close( + "Failed to get signature for closing transaction.".to_owned(), + ) + })?; self.context.last_sent_closing_fee = Some((total_fee_satoshis, sig.clone())); - Ok((Some(msgs::ClosingSigned { - channel_id: self.context.channel_id, - fee_satoshis: total_fee_satoshis, - signature: sig, - fee_range: Some(msgs::ClosingSignedFeeRange { - min_fee_satoshis: our_min_fee, - max_fee_satoshis: our_max_fee, + Ok(( + Some(msgs::ClosingSigned { + channel_id: self.context.channel_id, + fee_satoshis: total_fee_satoshis, + signature: sig, + fee_range: Some(msgs::ClosingSignedFeeRange { + min_fee_satoshis: our_min_fee, + max_fee_satoshis: our_max_fee, + }), }), - }), None, None)) + None, + None, + )) }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), } } @@ -4776,38 +5905,50 @@ impl Channel where /// /// This should be called on every [`super::channelmanager::ChannelManager::timer_tick_occurred`]. pub fn should_disconnect_peer_awaiting_response(&mut self) -> bool { - let ticks_elapsed = if let Some(ticks_elapsed) = self.context.sent_message_awaiting_response.as_mut() { - ticks_elapsed - } else { - // Don't disconnect when we're not waiting on a response. - return false; - }; + let ticks_elapsed = + if let Some(ticks_elapsed) = self.context.sent_message_awaiting_response.as_mut() { + ticks_elapsed + } else { + // Don't disconnect when we're not waiting on a response. + return false; + }; *ticks_elapsed += 1; *ticks_elapsed >= DISCONNECT_PEER_AWAITING_RESPONSE_TICKS } 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)); 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() { @@ -4829,10 +5970,17 @@ impl Channel 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 @@ -4856,27 +6004,30 @@ impl Channel 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(); @@ -4885,7 +6036,9 @@ impl Channel 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 @@ -4909,21 +6062,38 @@ impl Channel where } pub fn closing_signed( - &mut self, fee_estimator: &LowerBoundedFeeEstimator, msg: &msgs::ClosingSigned) - -> Result<(Option, Option, Option), ChannelError> - where F::Target: FeeEstimator + &mut self, fee_estimator: &LowerBoundedFeeEstimator, msg: &msgs::ClosingSigned, + ) -> Result< + (Option, Option, Option), + ChannelError, + > + where + F::Target: FeeEstimator, { 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.context.is_outbound() && self.context.last_sent_closing_fee.is_none() { @@ -4936,25 +6106,43 @@ impl Channel where } let funding_redeemscript = self.context.get_funding_redeemscript(); - let (mut closing_tx, used_total_fee) = self.build_closing_transaction(msg.fee_satoshis, false); + let (mut closing_tx, used_total_fee) = + self.build_closing_transaction(msg.fee_satoshis, false); 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.context.channel_value_satoshis); + let sighash = closing_tx + .trust() + .get_sighash_all(&funding_redeemscript, self.context.channel_value_satoshis); - match self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.context.get_counterparty_pubkeys().funding_pubkey) { + match self.context.secp_ctx.verify_ecdsa( + &sighash, + &msg.signature, + &self.context.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. closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0; - let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.context.channel_value_satoshis); - secp_check!(self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, self.context.counterparty_funding_pubkey()), "Invalid closing tx signature from peer".to_owned()); + let sighash = closing_tx + .trust() + .get_sighash_all(&funding_redeemscript, self.context.channel_value_satoshis); + secp_check!( + self.context.secp_ctx.verify_ecdsa( + &sighash, + &msg.signature, + self.context.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 < MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS { + if !outp.script_pubkey.is_witness_program() + && outp.value < 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())); } } @@ -4966,7 +6154,9 @@ impl Channel where closure_reason: ClosureReason::CooperativeClosure, monitor_update: None, dropped_outbound_htlcs: Vec::new(), - unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(), + unbroadcasted_batch_funding_txid: self + .context + .unbroadcasted_batch_funding_txid(), channel_id: self.context.channel_id, user_channel_id: self.context.user_id, channel_capacity_satoshis: self.context.channel_value_satoshis, @@ -4974,7 +6164,8 @@ impl Channel where unbroadcasted_funding_tx: self.context.unbroadcasted_funding(), channel_funding_txo: self.context.get_funding_txo(), }; - 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))); @@ -4995,13 +6186,20 @@ impl Channel where ChannelSignerType::Ecdsa(ecdsa) => { let sig = ecdsa .sign_closing_transaction(&closing_tx, &self.context.secp_ctx) - .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?; + .map_err(|_| { + ChannelError::Close( + "External signer refused to sign closing transaction" + .to_owned(), + ) + })?; let (signed_tx, shutdown_result) = if $new_fee == msg.fee_satoshis { let shutdown_result = ShutdownResult { closure_reason: ClosureReason::CooperativeClosure, monitor_update: None, dropped_outbound_htlcs: Vec::new(), - unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(), + unbroadcasted_batch_funding_txid: self + .context + .unbroadcasted_batch_funding_txid(), channel_id: self.context.channel_id, user_channel_id: self.context.user_id, channel_capacity_satoshis: self.context.channel_value_satoshis, @@ -5011,31 +6209,41 @@ impl Channel where }; self.context.channel_state = ChannelState::ShutdownComplete; self.context.update_time_counter += 1; - let tx = self.build_signed_closing_transaction(&closing_tx, &msg.signature, &sig); + let tx = self.build_signed_closing_transaction( + &closing_tx, + &msg.signature, + &sig, + ); (Some(tx), Some(shutdown_result)) } else { (None, None) }; self.context.last_sent_closing_fee = Some((used_fee, sig.clone())); - Ok((Some(msgs::ClosingSigned { - channel_id: self.context.channel_id, - fee_satoshis: used_fee, - signature: sig, - fee_range: Some(msgs::ClosingSignedFeeRange { - min_fee_satoshis: our_min_fee, - max_fee_satoshis: our_max_fee, + Ok(( + Some(msgs::ClosingSigned { + channel_id: self.context.channel_id, + fee_satoshis: used_fee, + signature: sig, + fee_range: Some(msgs::ClosingSignedFeeRange { + min_fee_satoshis: our_min_fee, + max_fee_satoshis: our_max_fee, + }), }), - }), signed_tx, shutdown_result)) + signed_tx, + shutdown_result, + )) }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), } - } + }; } - 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))); } @@ -5049,7 +6257,11 @@ impl Channel where if !self.context.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.context.channel_value_satoshis - (self.context.value_to_self_msat + 999) / 1000); + debug_assert_eq!( + our_max_fee, + self.context.channel_value_satoshis + - (self.context.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 { @@ -5093,18 +6305,25 @@ impl Channel 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, u16)> { - 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", 0x1000 | 12, // fee_insufficient )); } - 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", 0x1000 | 13, // incorrect_cltv_expiry @@ -5119,14 +6338,24 @@ impl Channel where pub fn htlc_satisfies_config( &self, htlc: &msgs::UpdateAddHTLC, amt_to_forward: u64, outgoing_cltv_value: u32, ) -> Result<(), (&'static str, u16)> { - 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) + } + }) } pub fn get_cur_holder_commitment_transaction_number(&self) -> u64 { @@ -5134,7 +6363,8 @@ impl Channel 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 { @@ -5151,22 +6381,37 @@ impl Channel where ChannelValueStat { value_to_self_msat: self.context.value_to_self_msat, channel_value_msat: self.context.channel_value_satoshis * 1000, - channel_reserve_msat: self.context.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 + .context + .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, } } @@ -5179,27 +6424,32 @@ impl Channel 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) @@ -5215,7 +6465,9 @@ impl Channel 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() @@ -5225,8 +6477,10 @@ impl Channel where debug_assert!(self.context.minimum_depth.unwrap_or(1) > 0); return true; } - if self.context.cur_holder_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 && - self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 { + if self.context.cur_holder_commitment_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 @@ -5239,7 +6493,9 @@ impl Channel 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.context.is_outbound() { assert!(self.context.funding_transaction.is_some()); } + if self.context.is_outbound() { + assert!(self.context.funding_transaction.is_some()); + } assert!(self.context.monitor_pending_channel_ready); assert_eq!(self.context.latest_monitor_update_id, 0); return true; @@ -5249,8 +6505,8 @@ impl Channel 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. @@ -5283,11 +6539,13 @@ impl Channel where // 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; } @@ -5304,28 +6562,35 @@ impl Channel 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 @@ -5335,7 +6600,10 @@ impl Channel where if !self.context.channel_state.is_monitor_update_in_progress() { if !self.context.channel_state.is_peer_disconnected() { let next_per_commitment_point = - self.context.holder_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.context.secp_ctx); + self.context.holder_signer.as_ref().get_per_commitment_point( + INITIAL_COMMITMENT_NUMBER - 1, + &self.context.secp_ctx, + ); return Some(msgs::ChannelReady { channel_id: self.context.channel_id, next_per_commitment_point, @@ -5354,11 +6622,11 @@ impl Channel 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.context.get_funding_txo() { @@ -5368,8 +6636,11 @@ impl Channel where if self.context.funding_tx_confirmation_height == 0 { if tx.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.context.get_funding_redeemscript().to_v0_p2wsh() || - tx.output[txo_idx].value != self.context.channel_value_satoshis { + if txo_idx >= tx.output.len() + || tx.output[txo_idx].script_pubkey + != self.context.get_funding_redeemscript().to_v0_p2wsh() + || tx.output[txo_idx].value != self.context.channel_value_satoshis + { if self.context.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 @@ -5381,7 +6652,9 @@ impl Channel 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.context.is_outbound() { if !tx.is_coin_base() { @@ -5404,9 +6677,10 @@ impl Channel 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_coin_base() && - self.context.minimum_depth.unwrap_or(0) > 0 && - self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY { + if tx.is_coin_base() + && self.context.minimum_depth.unwrap_or(0) > 0 + && self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY + { self.context.minimum_depth = Some(COINBASE_MATURITY); } } @@ -5414,14 +6688,31 @@ impl Channel 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) { - 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.txid(), inp.previous_output.txid, inp.previous_output.vout, &self.context.channel_id()); + log_info!( + logger, + "Detected channel-closing tx {} spending {}:{}, closing channel {}", + tx.txid(), + inp.previous_output.txid, + inp.previous_output.vout, + &self.context.channel_id() + ); return Err(ClosureReason::CommitmentTxConfirmed); } } @@ -5442,54 +6733,88 @@ impl Channel 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) { - 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 @@ -5507,29 +6832,48 @@ impl Channel 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.context.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.context.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. @@ -5538,14 +6882,25 @@ impl Channel 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 @@ -5569,18 +6924,29 @@ impl Channel 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.announced_channel { - 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(); @@ -5590,8 +6956,16 @@ impl Channel 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.context.get_holder_pubkeys().funding_pubkey } else { self.context.counterparty_funding_pubkey() }), - bitcoin_key_2: NodeId::from_pubkey(if were_node_one { self.context.counterparty_funding_pubkey() } else { &self.context.get_holder_pubkeys().funding_pubkey }), + bitcoin_key_1: NodeId::from_pubkey(if were_node_one { + &self.context.get_holder_pubkeys().funding_pubkey + } else { + self.context.counterparty_funding_pubkey() + }), + bitcoin_key_2: NodeId::from_pubkey(if were_node_one { + self.context.counterparty_funding_pubkey() + } else { + &self.context.get_holder_pubkeys().funding_pubkey + }), excess_data: Vec::new(), }; @@ -5600,13 +6974,15 @@ impl Channel 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; } @@ -5615,7 +6991,10 @@ impl Channel 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; } @@ -5623,29 +7002,39 @@ impl Channel 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(&announcement, &self.context.secp_ctx) { + let our_bitcoin_sig = match ecdsa.sign_channel_announcement_with_funding_key( + &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, @@ -5663,37 +7052,63 @@ impl Channel 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(&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( + &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())) @@ -5705,25 +7120,44 @@ impl Channel 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.context.counterparty_funding_pubkey()).is_err() { + if self + .context + .secp_ctx + .verify_ecdsa( + &msghash, + &msg.bitcoin_signature, + self.context.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.context.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())); } @@ -5734,12 +7168,19 @@ impl Channel 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, }; @@ -5751,24 +7192,37 @@ impl Channel where /// May panic if called on a channel that wasn't immediately-previously /// self.remove_uncommitted_htlcs_and_mark_paused()'d - pub fn get_channel_reestablish(&mut self, logger: &L) -> msgs::ChannelReestablish where L::Target: Logger { + pub 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 + ); // 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 // set to a dummy (but valid, as required by the spec) public key. // 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] }; self.mark_awaiting_response(); msgs::ChannelReestablish { @@ -5782,7 +7236,8 @@ impl Channel 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.context.cur_holder_commitment_transaction_number, + next_local_commitment_number: INITIAL_COMMITMENT_NUMBER + - self.context.cur_holder_commitment_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 @@ -5790,7 +7245,9 @@ impl Channel 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, // TODO(dual_funding): If we've sent `commtiment_signed` for an interactive transaction @@ -5800,7 +7257,6 @@ impl Channel where } } - // Send stuff to our remote peers: /// Queues up an outbound HTLC to send by placing it in the holding cell. You should call @@ -5809,21 +7265,34 @@ impl Channel where /// /// `Err`s will only be [`ChannelError::Ignore`]. 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<(), ChannelError> - 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| { - if let ChannelError::Ignore(_) = err { /* fine */ } - else { debug_assert!(false, "Queueing cannot trigger channel failure"); } - 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| { + if let ChannelError::Ignore(_) = err { /* fine */ + } else { + debug_assert!(false, "Queueing cannot trigger channel failure"); + } + err + }) } /// Adds a pending outbound HTLC to this channel, note that you probably want @@ -5843,22 +7312,27 @@ impl Channel where /// /// `Err`s will only be [`ChannelError::Ignore`]. 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, ChannelError> - 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(ChannelError::Ignore("Cannot send HTLC until channel is fully established and we haven't started shutting down".to_owned())); } let channel_total_msat = self.context.channel_value_satoshis * 1000; if amount_msat > channel_total_msat { - return Err(ChannelError::Ignore(format!("Cannot send amount {}, because it is more than the total value of the channel {}", amount_msat, channel_total_msat))); + return Err(ChannelError::Ignore(format!( + "Cannot send amount {}, because it is more than the total value of the channel {}", + amount_msat, channel_total_msat + ))); } if amount_msat == 0 { @@ -5867,13 +7341,17 @@ impl Channel where let available_balances = self.context.get_available_balances(fee_estimator); if amount_msat < available_balances.next_outbound_htlc_minimum_msat { - return Err(ChannelError::Ignore(format!("Cannot send less than our next-HTLC minimum - {} msat", - available_balances.next_outbound_htlc_minimum_msat))); + return Err(ChannelError::Ignore(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(ChannelError::Ignore(format!("Cannot send more than our next-HTLC maximum - {} msat", - available_balances.next_outbound_htlc_limit_msat))); + return Err(ChannelError::Ignore(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() { @@ -5883,15 +7361,25 @@ impl Channel 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(ChannelError::Ignore("Cannot send an HTLC while disconnected from channel counterparty".to_owned())); + return Err(ChannelError::Ignore( + "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; @@ -5937,22 +7425,32 @@ impl Channel where Ok(Some(res)) } - 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); // Grab the preimage, if it exists, instead of cloning let mut reason = OutboundHTLCOutcome::Success(None); @@ -5973,8 +7471,12 @@ impl Channel where let (mut htlcs_ref, counterparty_commitment_tx) = self.build_commitment_no_state_update(logger); let counterparty_commitment_txid = counterparty_commitment_tx.trust().txid(); - let htlcs: Vec<(HTLCOutputInCommitment, Option>)> = - htlcs_ref.drain(..).map(|(htlc, htlc_source)| (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone())))).collect(); + let htlcs: Vec<(HTLCOutputInCommitment, Option>)> = htlcs_ref + .drain(..) + .map(|(htlc, htlc_source)| { + (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone()))) + }) + .collect(); if self.context.announcement_sigs_state == AnnouncementSigsState::MessageSent { self.context.announcement_sigs_state = AnnouncementSigsState::Committed; @@ -5990,8 +7492,12 @@ impl Channel where commitment_number: self.context.cur_counterparty_commitment_transaction_number, 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(), + ), }], channel_id: Some(self.context.channel_id()), }; @@ -5999,28 +7505,43 @@ impl Channel where monitor_update } - fn build_commitment_no_state_update(&self, logger: &L) - -> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction) - where L::Target: Logger + fn build_commitment_no_state_update( + &self, logger: &L, + ) -> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction) + where + L::Target: Logger, { let counterparty_keys = self.context.build_remote_transaction_keys(); - let commitment_stats = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger); + let commitment_stats = self.context.build_commitment_transaction( + self.context.cur_counterparty_commitment_transaction_number, + &counterparty_keys, + false, + true, + logger, + ); let counterparty_commitment_tx = commitment_stats.tx; #[cfg(any(test, fuzzing))] { if !self.context.is_outbound() { - let projected_commit_tx_info = self.context.next_remote_commitment_tx_fee_info_cached.lock().unwrap().take(); + let projected_commit_tx_info = + self.context.next_remote_commitment_tx_fee_info_cached.lock().unwrap().take(); *self.context.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_msat(self.context.feerate_per_kw, commitment_stats.num_nondust_htlcs, self.context.get_channel_type()); - assert_eq!(actual_fee, info.fee); - } + && info.feerate == self.context.feerate_per_kw + { + let actual_fee = commit_tx_fee_msat( + self.context.feerate_per_kw, + commitment_stats.num_nondust_htlcs, + self.context.get_channel_type(), + ); + assert_eq!(actual_fee, info.fee); + } } } } @@ -6030,13 +7551,27 @@ impl Channel where /// Only fails in case of signer rejection. Used for channel_reestablish commitment_signed /// generation when we shouldn't change HTLC/channel state. - fn send_commitment_no_state_update(&self, logger: &L) -> Result<(msgs::CommitmentSigned, (Txid, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> where L::Target: Logger { + fn send_commitment_no_state_update( + &self, logger: &L, + ) -> Result< + (msgs::CommitmentSigned, (Txid, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), + ChannelError, + > + where + L::Target: Logger, + { // Get the fee tests from `build_commitment_no_state_update` #[cfg(any(test, fuzzing))] self.build_commitment_no_state_update(logger); let counterparty_keys = self.context.build_remote_transaction_keys(); - let commitment_stats = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger); + let commitment_stats = self.context.build_commitment_transaction( + self.context.cur_counterparty_commitment_transaction_number, + &counterparty_keys, + false, + true, + logger, + ); let counterparty_commitment_txid = commitment_stats.tx.trust().txid(); match &self.context.holder_signer { @@ -6049,12 +7584,18 @@ impl Channel where htlcs.push(htlc); } - let res = ecdsa.sign_counterparty_commitment( + let res = ecdsa + .sign_counterparty_commitment( &commitment_stats.tx, commitment_stats.inbound_htlc_preimages, commitment_stats.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; @@ -6072,17 +7613,20 @@ impl Channel where } } - Ok((msgs::CommitmentSigned { - channel_id: self.context.channel_id, - signature, - htlc_signatures, - #[cfg(taproot)] - partial_signature_with_nonce: None, - }, (counterparty_commitment_txid, commitment_stats.htlcs_included))) + Ok(( + msgs::CommitmentSigned { + channel_id: self.context.channel_id, + signature, + htlc_signatures, + #[cfg(taproot)] + partial_signature_with_nonce: None, + }, + (counterparty_commitment_txid, commitment_stats.htlcs_included), + )) }, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), } } @@ -6094,20 +7638,44 @@ impl Channel 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); - if let Err(e) = &send_res { if let ChannelError::Ignore(_) = e {} else { debug_assert!(false, "Sending cannot trigger channel failure"); } } + let send_res = self.send_htlc( + amount_msat, + payment_hash, + cltv_expiry, + source, + onion_routing_packet, + false, + skimmed_fee_msat, + None, + fee_estimator, + logger, + ); + if let Err(e) = &send_res { + if let ChannelError::Ignore(_) = e { + } else { + debug_assert!(false, "Sending cannot trigger channel failure"); + } + } match send_res? { 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), } } @@ -6117,7 +7685,7 @@ impl Channel 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 { @@ -6129,26 +7697,40 @@ impl Channel 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, + > { 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()}); } @@ -6162,12 +7744,18 @@ impl Channel 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 @@ -6191,7 +7779,9 @@ impl Channel 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(), @@ -6200,70 +7790,106 @@ impl Channel 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)) } - 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)), + ) } } /// 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 context: ChannelContext, pub unfunded_context: UnfundedChannelContext, } -impl OutboundV1Channel where SP::Target: SignerProvider { +impl OutboundV1Channel +where + SP::Target: SignerProvider, +{ 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 + 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, ) -> Result, APIError> - where ES::Target: EntropySource, - F::Target: FeeEstimator + where + ES::Target: EntropySource, + F::Target: FeeEstimator, { let holder_selected_contest_delay = config.channel_handshake_config.our_to_self_delay; - let channel_keys_id = signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id); - let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); + let channel_keys_id = + signer_provider.generate_channel_keys_id(false, channel_value_satoshis, user_id); + let holder_signer = + signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); let pubkeys = holder_signer.pubkeys().clone(); - 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)}); } - 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` @@ -6271,17 +7897,21 @@ impl OutboundV1Channel where SP::Target: SignerProvider { } let channel_type = Self::get_initial_channel_type(&config, their_features); - debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config))); + debug_assert!( + channel_type.is_subset(&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_msat(commitment_feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type); + let commitment_tx_fee = + commit_tx_fee_msat(commitment_feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type); 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) }); } @@ -6289,25 +7919,39 @@ impl OutboundV1Channel 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 temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source)); + let temporary_channel_id = temporary_channel_id + .unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source)); Ok(Self { context: ChannelContext { @@ -6316,7 +7960,9 @@ impl OutboundV1Channel where SP::Target: SignerProvider { config: LegacyChannelConfig { options: config.channel_config.clone(), announced_channel: config.channel_handshake_config.announced_channel, - 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, @@ -6325,7 +7971,9 @@ impl OutboundV1Channel where SP::Target: SignerProvider { channel_id: temporary_channel_id, temporary_channel_id: Some(temporary_channel_id), - channel_state: ChannelState::NegotiatingFunding(NegotiatingFundingFlags::OUR_INIT_SENT), + channel_state: ChannelState::NegotiatingFunding( + NegotiatingFundingFlags::OUR_INIT_SENT, + ), announcement_sigs_state: AnnouncementSigsState::NotSent, secp_ctx, channel_value_satoshis, @@ -6362,9 +8010,15 @@ impl OutboundV1Channel where SP::Target: SignerProvider { signer_pending_funding: false, #[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, + )), last_sent_closing_fee: None, pending_counterparty_closing_signed: None, @@ -6381,24 +8035,38 @@ impl OutboundV1Channel where SP::Target: SignerProvider { counterparty_dust_limit_satoshis: 0, holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS, counterparty_max_htlc_value_in_flight_msat: 0, - 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_selected_channel_reserve_satoshis: None, // Filled in in accept_channel holder_selected_channel_reserve_satoshis, 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), + holder_max_accepted_htlcs: cmp::min( + config.channel_handshake_config.our_max_accepted_htlcs, + MAX_HTLCS, + ), minimum_depth: None, // Filled in in accept_channel counterparty_forwarding_info: None, channel_transaction_parameters: ChannelTransactionParameters { holder_pubkeys: pubkeys, - holder_selected_contest_delay: config.channel_handshake_config.our_to_self_delay, + holder_selected_contest_delay: config + .channel_handshake_config + .our_to_self_delay, is_outbound_from_holder: true, counterparty_parameters: None, funding_outpoint: None, - channel_type_features: channel_type.clone() + channel_type_features: channel_type.clone(), }, funding_transaction: None, is_batch_funding: None, @@ -6438,23 +8106,40 @@ impl OutboundV1Channel where SP::Target: SignerProvider { blocked_monitor_updates: Vec::new(), }, - unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 } + unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }, }) } /// Only allowed after [`ChannelContext::channel_transaction_parameters`] is set. - fn get_funding_created_msg(&mut self, logger: &L) -> Option where L::Target: Logger { + fn get_funding_created_msg(&mut self, logger: &L) -> Option + where + L::Target: Logger, + { let counterparty_keys = self.context.build_remote_transaction_keys(); - let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx; + let counterparty_initial_commitment_tx = self + .context + .build_commitment_transaction( + self.context.cur_counterparty_commitment_transaction_number, + &counterparty_keys, + false, + false, + logger, + ) + .tx; let signature = match &self.context.holder_signer { // TODO (taproot|arik): move match into calling method for Taproot - ChannelSignerType::Ecdsa(ecdsa) => { - ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), Vec::new(), &self.context.secp_ctx) - .map(|(sig, _)| sig).ok()? - }, + ChannelSignerType::Ecdsa(ecdsa) => ecdsa + .sign_counterparty_commitment( + &counterparty_initial_commitment_tx, + Vec::new(), + Vec::new(), + &self.context.secp_ctx, + ) + .map(|(sig, _)| sig) + .ok()?, // TODO (taproot|arik) #[cfg(taproot)] - _ => todo!() + _ => todo!(), }; if self.context.signer_pending_funding { @@ -6464,8 +8149,20 @@ impl OutboundV1Channel where SP::Target: SignerProvider { Some(msgs::FundingCreated { temporary_channel_id: self.context.temporary_channel_id.unwrap(), - funding_txid: self.context.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().txid, - funding_output_index: self.context.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().index, + funding_txid: self + .context + .channel_transaction_parameters + .funding_outpoint + .as_ref() + .unwrap() + .txid, + funding_output_index: self + .context + .channel_transaction_parameters + .funding_outpoint + .as_ref() + .unwrap() + .index, signature, #[cfg(taproot)] partial_signature_with_nonce: None, @@ -6481,8 +8178,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.context.is_outbound() { panic!("Tried to create outbound funding_created message on an inbound channel!"); } @@ -6492,14 +8194,21 @@ 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)"); } - if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) || - self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || - self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { - panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); + if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) + || self.context.cur_counterparty_commitment_transaction_number + != INITIAL_COMMITMENT_NUMBER + || self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER + { + panic!( + "Should not have advanced channel commitment tx numbers prior to funding_created" + ); } self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo); - self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters); + self.context + .holder_signer + .as_mut() + .provide_channel_parameters(&self.context.channel_transaction_parameters); // Now that we're past error-generating stuff, update our local state: @@ -6508,9 +8217,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_coin_base() && - self.context.minimum_depth.unwrap_or(0) > 0 && - self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY { + if funding_transaction.is_coin_base() + && self.context.minimum_depth.unwrap_or(0) > 0 + && self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY + { self.context.minimum_depth = Some(COINBASE_MATURITY); } @@ -6519,12 +8229,17 @@ impl OutboundV1Channel where SP::Target: SignerProvider { let funding_created = self.get_funding_created_msg(logger); if funding_created.is_none() { - #[cfg(not(async_signing))] { + #[cfg(not(async_signing))] + { panic!("Failed to get signature for new funding creation"); } - #[cfg(async_signing)] { + #[cfg(async_signing)] + { if !self.context.signer_pending_funding { - log_trace!(logger, "funding_created awaiting signer; setting signer_pending_funding"); + log_trace!( + logger, + "funding_created awaiting signer; setting signer_pending_funding" + ); self.context.signer_pending_funding = true; } } @@ -6533,23 +8248,27 @@ impl OutboundV1Channel where SP::Target: SignerProvider { Ok(funding_created) } - 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.announced_channel && - config.channel_handshake_config.negotiate_scid_privacy && - their_features.supports_scid_privacy() { + if !config.channel_handshake_config.announced_channel + && 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(); } @@ -6560,17 +8279,16 @@ 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 + &mut self, chain_hash: ChainHash, fee_estimator: &LowerBoundedFeeEstimator, ) -> Result where - F::Target: FeeEstimator + F::Target: FeeEstimator, { - if !self.context.is_outbound() || - !matches!( + if !self.context.is_outbound() + || !matches!( self.context.channel_state, ChannelState::NegotiatingFunding(flags) if flags == NegotiatingFundingFlags::OUR_INIT_SENT - ) - { + ) { return Err(()); } if self.context.channel_type == ChannelTypeFeatures::only_static_remote_key() { @@ -6588,14 +8306,20 @@ impl OutboundV1Channel where SP::Target: SignerProvider { // whatever reason. if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { self.context.channel_type.clear_anchors_zero_fee_htlc_tx(); - self.context.feerate_per_kw = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); - assert!(!self.context.channel_transaction_parameters.channel_type_features.supports_anchors_nonzero_fee_htlc_tx()); + self.context.feerate_per_kw = + fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee); + assert!(!self + .context + .channel_transaction_parameters + .channel_type_features + .supports_anchors_nonzero_fee_htlc_tx()); } else if self.context.channel_type.supports_scid_privacy() { self.context.channel_type.clear_scid_privacy(); } else { self.context.channel_type = ChannelTypeFeatures::only_static_remote_key(); } - self.context.channel_transaction_parameters.channel_type_features = self.context.channel_type.clone(); + self.context.channel_transaction_parameters.channel_type_features = + self.context.channel_type.clone(); Ok(self.get_open_channel(chain_hash)) } @@ -6611,7 +8335,11 @@ impl OutboundV1Channel where SP::Target: SignerProvider { panic!("Tried to send an open_channel for a channel that has already advanced"); } - let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let first_per_commitment_point = + self.context.holder_signer.as_ref().get_per_commitment_point( + self.context.cur_holder_commitment_transaction_number, + &self.context.secp_ctx, + ); let keys = self.context.get_holder_pubkeys(); msgs::OpenChannel { @@ -6632,7 +8360,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.announced_channel {1} else {0}, + channel_flags: if self.context.config.announced_channel { 1 } else { 0 }, shutdown_scriptpubkey: Some(match &self.context.shutdown_scriptpubkey { Some(script) => script.clone().into_inner(), None => Builder::new().into_script(), @@ -6642,62 +8370,114 @@ impl OutboundV1Channel where SP::Target: SignerProvider { } // Message handlers - pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, default_limits: &ChannelHandshakeLimits, their_features: &InitFeatures) -> Result<(), ChannelError> { - let peer_limits = if let Some(ref limits) = self.context.inbound_handshake_limits_override { limits } else { default_limits }; + pub fn accept_channel( + &mut self, msg: &msgs::AcceptChannel, default_limits: &ChannelHandshakeLimits, + their_features: &InitFeatures, + ) -> Result<(), ChannelError> { + let peer_limits = if let Some(ref limits) = self.context.inbound_handshake_limits_override { + limits + } else { + default_limits + }; // Check sanity of message fields: if !self.context.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.context.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.context.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 msg.dust_limit_satoshis > 21000000 * 100000000 { - return Err(ChannelError::Close(format!("Peer never wants payout outputs? dust_limit_satoshis was {}", msg.dust_limit_satoshis))); + return Err(ChannelError::Close(format!( + "Peer never wants payout outputs? dust_limit_satoshis was {}", + msg.dust_limit_satoshis + ))); } if msg.channel_reserve_satoshis > self.context.channel_value_satoshis { - return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", msg.channel_reserve_satoshis, self.context.channel_value_satoshis))); + return Err(ChannelError::Close(format!( + "Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", + msg.channel_reserve_satoshis, self.context.channel_value_satoshis + ))); } if msg.dust_limit_satoshis > self.context.holder_selected_channel_reserve_satoshis { - return Err(ChannelError::Close(format!("Dust limit ({}) is bigger than our channel reserve ({})", msg.dust_limit_satoshis, self.context.holder_selected_channel_reserve_satoshis))); + return Err(ChannelError::Close(format!( + "Dust limit ({}) is bigger than our channel reserve ({})", + msg.dust_limit_satoshis, self.context.holder_selected_channel_reserve_satoshis + ))); } - if msg.channel_reserve_satoshis > self.context.channel_value_satoshis - self.context.holder_selected_channel_reserve_satoshis { + if msg.channel_reserve_satoshis + > self.context.channel_value_satoshis + - self.context.holder_selected_channel_reserve_satoshis + { return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than channel value minus our reserve ({})", msg.channel_reserve_satoshis, self.context.channel_value_satoshis - self.context.holder_selected_channel_reserve_satoshis))); } - let full_channel_value_msat = (self.context.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000; + let full_channel_value_msat = + (self.context.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000; if msg.htlc_minimum_msat >= full_channel_value_msat { - return Err(ChannelError::Close(format!("Minimum htlc value ({}) is full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat))); + return Err(ChannelError::Close(format!( + "Minimum htlc value ({}) is full channel value ({})", + msg.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 msg.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, msg.to_self_delay))); } if msg.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 msg.max_accepted_htlcs > MAX_HTLCS { - return Err(ChannelError::Close(format!("max_accepted_htlcs was {}. It must not be larger than {}", msg.max_accepted_htlcs, MAX_HTLCS))); + return Err(ChannelError::Close(format!( + "max_accepted_htlcs was {}. It must not be larger than {}", + msg.max_accepted_htlcs, MAX_HTLCS + ))); } // Now check against optional parameters as set by config... if msg.htlc_minimum_msat > peer_limits.max_htlc_minimum_msat { - return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.htlc_minimum_msat, peer_limits.max_htlc_minimum_msat))); + return Err(ChannelError::Close(format!( + "htlc_minimum_msat ({}) is higher than the user specified limit ({})", + msg.htlc_minimum_msat, peer_limits.max_htlc_minimum_msat + ))); } if msg.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 ({})", msg.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 ({})", + msg.max_htlc_value_in_flight_msat, peer_limits.min_max_htlc_value_in_flight_msat + ))); } if msg.channel_reserve_satoshis > peer_limits.max_channel_reserve_satoshis { - return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg.channel_reserve_satoshis, peer_limits.max_channel_reserve_satoshis))); + return Err(ChannelError::Close(format!( + "channel_reserve_satoshis ({}) is higher than the user specified limit ({})", + msg.channel_reserve_satoshis, peer_limits.max_channel_reserve_satoshis + ))); } if msg.max_accepted_htlcs < peer_limits.min_max_accepted_htlcs { - return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, peer_limits.min_max_accepted_htlcs))); + return Err(ChannelError::Close(format!( + "max_accepted_htlcs ({}) is less than the user specified limit ({})", + msg.max_accepted_htlcs, peer_limits.min_max_accepted_htlcs + ))); } if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS))); + return Err(ChannelError::Close(format!( + "dust_limit_satoshis ({}) is less than the implementation limit ({})", + msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS + ))); } if msg.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS))); + return Err(ChannelError::Close(format!( + "dust_limit_satoshis ({}) is greater than the implementation limit ({})", + msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS + ))); } if msg.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, msg.minimum_depth))); @@ -6705,20 +8485,28 @@ impl OutboundV1Channel where SP::Target: SignerProvider { if let Some(ty) = &msg.channel_type { if *ty != self.context.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(), + )); } self.context.channel_type = channel_type.clone(); self.context.channel_transaction_parameters.channel_type_features = channel_type; } - let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { + let counterparty_shutdown_scriptpubkey = if their_features + .supports_upfront_shutdown_script() + { match &msg.shutdown_scriptpubkey { &Some(ref script) => { // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything @@ -6734,13 +8522,17 @@ impl OutboundV1Channel 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.context.counterparty_dust_limit_satoshis = msg.dust_limit_satoshis; - self.context.counterparty_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.context.channel_value_satoshis * 1000); - self.context.counterparty_selected_channel_reserve_satoshis = Some(msg.channel_reserve_satoshis); + self.context.counterparty_max_htlc_value_in_flight_msat = + cmp::min(msg.max_htlc_value_in_flight_msat, self.context.channel_value_satoshis * 1000); + self.context.counterparty_selected_channel_reserve_satoshis = + Some(msg.channel_reserve_satoshis); self.context.counterparty_htlc_minimum_msat = msg.htlc_minimum_msat; self.context.counterparty_max_accepted_htlcs = msg.max_accepted_htlcs; @@ -6755,19 +8547,20 @@ impl OutboundV1Channel where SP::Target: SignerProvider { revocation_basepoint: RevocationBasepoint::from(msg.revocation_basepoint), payment_point: msg.payment_point, delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.delayed_payment_basepoint), - htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint) + htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint), }; - self.context.channel_transaction_parameters.counterparty_parameters = Some(CounterpartyChannelTransactionParameters { - selected_contest_delay: msg.to_self_delay, - pubkeys: counterparty_pubkeys, - }); + self.context.channel_transaction_parameters.counterparty_parameters = + Some(CounterpartyChannelTransactionParameters { + selected_contest_delay: msg.to_self_delay, + pubkeys: counterparty_pubkeys, + }); self.context.counterparty_cur_commitment_point = Some(msg.first_per_commitment_point); self.context.counterparty_shutdown_scriptpubkey = counterparty_shutdown_scriptpubkey; self.context.channel_state = ChannelState::NegotiatingFunding( - NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT + NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT, ); self.context.inbound_handshake_limits_override = None; // We're done enforcing limits on our peer's handshake now. @@ -6777,42 +8570,89 @@ 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<(Channel, ChannelMonitor<::EcdsaSigner>), (OutboundV1Channel, ChannelError)> + mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, + logger: &L, + ) -> Result< + (Channel, ChannelMonitor<::EcdsaSigner>), + (OutboundV1Channel, ChannelError), + > where - L::Target: Logger + L::Target: Logger, { if !self.context.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()), + )); } - if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) || - self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || - self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { - panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); + if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) + || self.context.cur_counterparty_commitment_transaction_number + != INITIAL_COMMITMENT_NUMBER + || self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER + { + panic!( + "Should not have advanced channel commitment tx numbers prior to funding_created" + ); } let funding_script = self.context.get_funding_redeemscript(); let counterparty_keys = self.context.build_remote_transaction_keys(); - let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx; + let counterparty_initial_commitment_tx = self + .context + .build_commitment_transaction( + self.context.cur_counterparty_commitment_transaction_number, + &counterparty_keys, + false, + false, + logger, + ) + .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 {}", - &self.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 {}", + &self.context.channel_id(), + counterparty_initial_bitcoin_tx.txid, + encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction) + ); - let holder_signer = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); - let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &holder_signer, true, false, logger).tx; + let holder_signer = self + .context + .build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); + let initial_commitment_tx = self + .context + .build_commitment_transaction( + self.context.cur_holder_commitment_transaction_number, + &holder_signer, + true, + false, + logger, + ) + .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.context.channel_value_satoshis); + let sighash = initial_commitment_bitcoin_tx + .get_sighash_all(&funding_script, self.context.channel_value_satoshis); // They sign our commitment transaction, allowing us to broadcast the tx if we wish. - if let Err(_) = self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.context.get_counterparty_pubkeys().funding_pubkey) { - return Err((self, ChannelError::Close("Invalid funding_signed signature from peer".to_owned()))); + if let Err(_) = self.context.secp_ctx.verify_ecdsa( + &sighash, + &msg.signature, + &self.context.get_counterparty_pubkeys().funding_pubkey, + ) { + return Err(( + self, + ChannelError::Close("Invalid funding_signed signature from peer".to_owned()), + )); } } @@ -6821,68 +8661,115 @@ impl OutboundV1Channel where SP::Target: SignerProvider { msg.signature, Vec::new(), &self.context.get_holder_pubkeys().funding_pubkey, - self.context.counterparty_funding_pubkey() + self.context.counterparty_funding_pubkey(), ); - let validated = - self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()); + let validated = self + .context + .holder_signer + .as_ref() + .validate_holder_commitment(&holder_commitment_tx, Vec::new()); if validated.is_err() { - return Err((self, ChannelError::Close("Failed to validate our commitment".to_owned()))); + return Err(( + self, + ChannelError::Close("Failed to validate our commitment".to_owned()), + )); } let funding_redeemscript = self.context.get_funding_redeemscript(); let funding_txo = self.context.get_funding_txo().unwrap(); let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); - let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound()); - let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); - let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id); + let obscure_factor = get_commitment_transaction_number_obscure_factor( + &self.context.get_holder_pubkeys().payment_point, + &self.context.get_counterparty_pubkeys().payment_point, + self.context.is_outbound(), + ); + let shutdown_script = + self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); + let mut monitor_signer = signer_provider.derive_channel_signer( + self.context.channel_value_satoshis, + self.context.channel_keys_id, + ); monitor_signer.provide_channel_parameters(&self.context.channel_transaction_parameters); - let channel_monitor = ChannelMonitor::new(self.context.secp_ctx.clone(), monitor_signer, - shutdown_script, self.context.get_holder_selected_contest_delay(), - &self.context.destination_script, (funding_txo, funding_txo_script), - &self.context.channel_transaction_parameters, - funding_redeemscript.clone(), self.context.channel_value_satoshis, - obscure_factor, - holder_commitment_tx, best_block, self.context.counterparty_node_id, self.context.channel_id()); + let channel_monitor = ChannelMonitor::new( + self.context.secp_ctx.clone(), + monitor_signer, + shutdown_script, + self.context.get_holder_selected_contest_delay(), + &self.context.destination_script, + (funding_txo, funding_txo_script), + &self.context.channel_transaction_parameters, + funding_redeemscript.clone(), + self.context.channel_value_satoshis, + obscure_factor, + holder_commitment_tx, + best_block, + self.context.counterparty_node_id, + self.context.channel_id(), + ); channel_monitor.provide_initial_counterparty_commitment_tx( - counterparty_initial_bitcoin_tx.txid, Vec::new(), + counterparty_initial_bitcoin_tx.txid, + Vec::new(), self.context.cur_counterparty_commitment_transaction_number, self.context.counterparty_cur_commitment_point.unwrap(), counterparty_initial_commitment_tx.feerate_per_kw(), counterparty_initial_commitment_tx.to_broadcaster_value_sat(), - counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger); + counterparty_initial_commitment_tx.to_countersignatory_value_sat(), + logger, + ); assert!(!self.context.channel_state.is_monitor_update_in_progress()); // We have no had any monitor(s) yet to fail update! if self.context.is_batch_funding() { - self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH); + self.context.channel_state = + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH); } else { - self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); + self.context.channel_state = + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); } self.context.cur_holder_commitment_transaction_number -= 1; self.context.cur_counterparty_commitment_transaction_number -= 1; - 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 = Channel { context: self.context }; let need_channel_ready = channel.check_get_channel_ready(0).is_some(); - 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. #[cfg(async_signing)] - 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.context.signer_pending_funding && self.context.is_outbound() { log_trace!(logger, "Signer unblocked a funding_created"); self.get_funding_created_msg(logger) - } else { None } + } else { + None + } } } /// 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 context: ChannelContext, pub unfunded_context: UnfundedChannelContext, } @@ -6891,38 +8778,51 @@ pub(super) struct InboundV1Channel where SP::Target: SignerProvider { /// [`msgs::OpenChannel`]. pub(super) fn channel_type_from_open_channel( msg: &msgs::OpenChannel, their_features: &InitFeatures, - our_supported_features: &ChannelTypeFeatures + our_supported_features: &ChannelTypeFeatures, ) -> Result { if let Some(channel_type) = &msg.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.is_subset(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 announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false }; if channel_type.requires_scid_privacy() && announced_channel { - 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( @@ -6931,26 +8831,31 @@ 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.temporary_channel_id)); + let logger = + WithContext::from(logger, Some(counterparty_node_id), Some(msg.temporary_channel_id)); let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false }; // 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, their_features, our_supported_features)?; + let channel_type = + channel_type_from_open_channel(msg, their_features, our_supported_features)?; - let channel_keys_id = signer_provider.generate_channel_keys_id(true, msg.funding_satoshis, user_id); - let holder_signer = signer_provider.derive_channel_signer(msg.funding_satoshis, channel_keys_id); + let channel_keys_id = + signer_provider.generate_channel_keys_id(true, msg.funding_satoshis, user_id); + let holder_signer = + signer_provider.derive_channel_signer(msg.funding_satoshis, channel_keys_id); let pubkeys = holder_signer.pubkeys().clone(); let counterparty_pubkeys = ChannelPublicKeys { funding_pubkey: msg.funding_pubkey, revocation_basepoint: RevocationBasepoint::from(msg.revocation_basepoint), payment_point: msg.payment_point, delayed_payment_basepoint: DelayedPaymentBasepoint::from(msg.delayed_payment_basepoint), - htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint) + htlc_basepoint: HtlcBasepoint::from(msg.htlc_basepoint), }; if config.channel_handshake_config.our_to_self_delay < BREAKDOWN_TIMEOUT { @@ -6959,58 +8864,111 @@ impl InboundV1Channel where SP::Target: SignerProvider { // Check sanity of message fields: if msg.funding_satoshis > config.channel_handshake_limits.max_funding_satoshis { - return Err(ChannelError::Close(format!("Per our config, funding must be at most {}. It was {}", config.channel_handshake_limits.max_funding_satoshis, msg.funding_satoshis))); + return Err(ChannelError::Close(format!( + "Per our config, funding must be at most {}. It was {}", + config.channel_handshake_limits.max_funding_satoshis, msg.funding_satoshis + ))); } if msg.funding_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS { - return Err(ChannelError::Close(format!("Funding must be smaller than the total bitcoin supply. It was {}", msg.funding_satoshis))); + return Err(ChannelError::Close(format!( + "Funding must be smaller than the total bitcoin supply. It was {}", + msg.funding_satoshis + ))); } if msg.channel_reserve_satoshis > msg.funding_satoshis { return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must be not greater than funding_satoshis: {}", msg.channel_reserve_satoshis, msg.funding_satoshis))); } let full_channel_value_msat = (msg.funding_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 msg.dust_limit_satoshis > msg.funding_satoshis { return Err(ChannelError::Close(format!("dust_limit_satoshis {} was larger than funding_satoshis {}. Peer never wants payout outputs?", msg.dust_limit_satoshis, msg.funding_satoshis))); } if msg.htlc_minimum_msat >= full_channel_value_msat { - return Err(ChannelError::Close(format!("Minimum htlc value ({}) was larger than full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat))); + return Err(ChannelError::Close(format!( + "Minimum htlc value ({}) was larger than full channel value ({})", + msg.htlc_minimum_msat, full_channel_value_msat + ))); } - Channel::::check_remote_fee(&channel_type, fee_estimator, msg.feerate_per_kw, None, &&logger)?; + Channel::::check_remote_fee( + &channel_type, + fee_estimator, + msg.feerate_per_kw, + 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 msg.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, msg.to_self_delay))); } if msg.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 msg.max_accepted_htlcs > MAX_HTLCS { - return Err(ChannelError::Close(format!("max_accepted_htlcs was {}. It must not be larger than {}", msg.max_accepted_htlcs, MAX_HTLCS))); + return Err(ChannelError::Close(format!( + "max_accepted_htlcs was {}. It must not be larger than {}", + msg.max_accepted_htlcs, MAX_HTLCS + ))); } // Now check against optional parameters as set by config... if msg.funding_satoshis < config.channel_handshake_limits.min_funding_satoshis { - return Err(ChannelError::Close(format!("Funding satoshis ({}) is less than the user specified limit ({})", msg.funding_satoshis, config.channel_handshake_limits.min_funding_satoshis))); + return Err(ChannelError::Close(format!( + "Funding satoshis ({}) is less than the user specified limit ({})", + msg.funding_satoshis, config.channel_handshake_limits.min_funding_satoshis + ))); } if msg.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 ({})", msg.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 ({})", + msg.htlc_minimum_msat, config.channel_handshake_limits.max_htlc_minimum_msat + ))); } - if msg.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 ({})", msg.max_htlc_value_in_flight_msat, config.channel_handshake_limits.min_max_htlc_value_in_flight_msat))); + if msg.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 ({})", + msg.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 msg.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 ({})", msg.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 ({})", + msg.max_accepted_htlcs, config.channel_handshake_limits.min_max_accepted_htlcs + ))); } if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS))); + return Err(ChannelError::Close(format!( + "dust_limit_satoshis ({}) is less than the implementation limit ({})", + msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS + ))); } - if msg.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS))); + if msg.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!( + "dust_limit_satoshis ({}) is greater than the implementation limit ({})", + msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS + ))); } // Convert things into internal flags and prep our state: @@ -7021,7 +8979,8 @@ impl InboundV1Channel where SP::Target: SignerProvider { } } - let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis, config); + let holder_selected_channel_reserve_satoshis = + get_holder_selected_channel_reserve_satoshis(msg.funding_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` @@ -7046,19 +9005,25 @@ impl InboundV1Channel where SP::Target: SignerProvider { 0 }; let funders_amount_msat = msg.funding_satoshis * 1000 - msg.push_msat; - let commitment_tx_fee = commit_tx_fee_msat(msg.feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) / 1000; + let commitment_tx_fee = + commit_tx_fee_msat(msg.feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT, &channel_type) / 1000; 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 &msg.shutdown_scriptpubkey { &Some(ref script) => { // Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything @@ -7066,7 +9031,7 @@ impl InboundV1Channel 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()) } @@ -7074,26 +9039,40 @@ impl InboundV1Channel 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(); @@ -7112,7 +9091,9 @@ impl InboundV1Channel where SP::Target: SignerProvider { config: LegacyChannelConfig { options: config.channel_config.clone(), announced_channel, - 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, @@ -7122,7 +9103,8 @@ impl InboundV1Channel where SP::Target: SignerProvider { temporary_channel_id: Some(msg.temporary_channel_id), channel_id: msg.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, @@ -7159,9 +9141,15 @@ impl InboundV1Channel where SP::Target: SignerProvider { signer_pending_funding: false, #[cfg(debug_assertions)] - holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), + holder_max_commitment_tx_output: Mutex::new(( + msg.push_msat, + msg.funding_satoshis * 1000 - msg.push_msat, + )), #[cfg(debug_assertions)] - counterparty_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), + counterparty_max_commitment_tx_output: Mutex::new(( + msg.push_msat, + msg.funding_satoshis * 1000 - msg.push_msat, + )), last_sent_closing_fee: None, pending_counterparty_closing_signed: None, @@ -7178,28 +9166,45 @@ impl InboundV1Channel where SP::Target: SignerProvider { channel_value_satoshis: msg.funding_satoshis, counterparty_dust_limit_satoshis: msg.dust_limit_satoshis, holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS, - counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), - holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat(msg.funding_satoshis, &config.channel_handshake_config), + counterparty_max_htlc_value_in_flight_msat: cmp::min( + msg.max_htlc_value_in_flight_msat, + msg.funding_satoshis * 1000, + ), + holder_max_htlc_value_in_flight_msat: get_holder_max_htlc_value_in_flight_msat( + msg.funding_satoshis, + &config.channel_handshake_config, + ), counterparty_selected_channel_reserve_satoshis: Some(msg.channel_reserve_satoshis), holder_selected_channel_reserve_satoshis, counterparty_htlc_minimum_msat: msg.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: msg.max_accepted_htlcs, - holder_max_accepted_htlcs: cmp::min(config.channel_handshake_config.our_max_accepted_htlcs, MAX_HTLCS), + holder_max_accepted_htlcs: cmp::min( + config.channel_handshake_config.our_max_accepted_htlcs, + MAX_HTLCS, + ), minimum_depth, counterparty_forwarding_info: None, channel_transaction_parameters: ChannelTransactionParameters { holder_pubkeys: pubkeys, - holder_selected_contest_delay: config.channel_handshake_config.our_to_self_delay, + holder_selected_contest_delay: config + .channel_handshake_config + .our_to_self_delay, is_outbound_from_holder: false, counterparty_parameters: Some(CounterpartyChannelTransactionParameters { selected_contest_delay: msg.to_self_delay, pubkeys: counterparty_pubkeys, }), funding_outpoint: None, - channel_type_features: channel_type.clone() + channel_type_features: channel_type.clone(), }, funding_transaction: None, is_batch_funding: None, @@ -7239,7 +9244,7 @@ impl InboundV1Channel where SP::Target: SignerProvider { blocked_monitor_updates: Vec::new(), }, - unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 } + unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }, }; Ok(chan) @@ -7272,7 +9277,11 @@ impl InboundV1Channel where SP::Target: SignerProvider { /// /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel fn generate_accept_channel_message(&self) -> msgs::AcceptChannel { - let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + let first_per_commitment_point = + self.context.holder_signer.as_ref().get_per_commitment_point( + self.context.cur_holder_commitment_transaction_number, + &self.context.secp_ctx, + ); let keys = self.context.get_holder_pubkeys(); msgs::AcceptChannel { @@ -7309,32 +9318,67 @@ impl InboundV1Channel where SP::Target: SignerProvider { self.generate_accept_channel_message() } - fn check_funding_created_signature(&mut self, sig: &Signature, logger: &L) -> Result where L::Target: Logger { + fn check_funding_created_signature( + &mut self, sig: &Signature, logger: &L, + ) -> Result + where + L::Target: Logger, + { let funding_script = self.context.get_funding_redeemscript(); - let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); - let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger).tx; + let keys = self + .context + .build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); + let initial_commitment_tx = self + .context + .build_commitment_transaction( + self.context.cur_holder_commitment_transaction_number, + &keys, + true, + false, + logger, + ) + .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.context.channel_value_satoshis); + let sighash = initial_commitment_bitcoin_tx + .get_sighash_all(&funding_script, self.context.channel_value_satoshis); // They sign the holder commitment transaction... log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.", log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.context.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.context.counterparty_funding_pubkey()), "Invalid funding_created signature from peer".to_owned()); + secp_check!( + self.context.secp_ctx.verify_ecdsa( + &sighash, + &sig, + self.context.counterparty_funding_pubkey() + ), + "Invalid funding_created signature from peer".to_owned() + ); Ok(initial_commitment_tx) } pub fn funding_created( - mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L - ) -> Result<(Channel, Option, ChannelMonitor<::EcdsaSigner>), (Self, ChannelError)> + mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, + logger: &L, + ) -> Result< + ( + Channel, + Option, + ChannelMonitor<::EcdsaSigner>, + ), + (Self, ChannelError), + > where - L::Target: Logger + L::Target: Logger, { if self.context.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) @@ -7343,84 +9387,137 @@ 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(), + ), + )); } - if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) || - self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || - self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { - panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); + if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) + || self.context.cur_counterparty_commitment_transaction_number + != INITIAL_COMMITMENT_NUMBER + || self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER + { + panic!( + "Should not have advanced channel commitment tx numbers prior to funding_created" + ); } let funding_txo = OutPoint { txid: msg.funding_txid, index: msg.funding_output_index }; self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo); // This is an externally observable change before we finish all our checks. In particular // check_funding_created_signature may fail. - self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters); - - let initial_commitment_tx = match self.check_funding_created_signature(&msg.signature, logger) { - Ok(res) => res, - Err(ChannelError::Close(e)) => { - self.context.channel_transaction_parameters.funding_outpoint = None; - return Err((self, ChannelError::Close(e))); - }, - 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_funding_created_signature {:?}", e); - } - }; + self.context + .holder_signer + .as_mut() + .provide_channel_parameters(&self.context.channel_transaction_parameters); + + let initial_commitment_tx = + match self.check_funding_created_signature(&msg.signature, logger) { + Ok(res) => res, + Err(ChannelError::Close(e)) => { + self.context.channel_transaction_parameters.funding_outpoint = None; + return Err((self, ChannelError::Close(e))); + }, + 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_funding_created_signature {:?}", e); + }, + }; let holder_commitment_tx = HolderCommitmentTransaction::new( initial_commitment_tx, msg.signature, Vec::new(), &self.context.get_holder_pubkeys().funding_pubkey, - self.context.counterparty_funding_pubkey() + self.context.counterparty_funding_pubkey(), ); - if let Err(_) = self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, Vec::new()) { - return Err((self, ChannelError::Close("Failed to validate our commitment".to_owned()))); + if let Err(_) = self + .context + .holder_signer + .as_ref() + .validate_holder_commitment(&holder_commitment_tx, Vec::new()) + { + return Err(( + self, + ChannelError::Close("Failed to validate our commitment".to_owned()), + )); } // Now that we're past error-generating stuff, update our local state: - self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); + self.context.channel_state = + ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); self.context.channel_id = ChannelId::v1_from_funding_outpoint(funding_txo); self.context.cur_counterparty_commitment_transaction_number -= 1; self.context.cur_holder_commitment_transaction_number -= 1; - let (counterparty_initial_commitment_tx, funding_signed) = self.context.get_funding_signed_msg(logger); + let (counterparty_initial_commitment_tx, funding_signed) = + self.context.get_funding_signed_msg(logger); let funding_redeemscript = self.context.get_funding_redeemscript(); let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); - let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound()); - let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); - let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id); + let obscure_factor = get_commitment_transaction_number_obscure_factor( + &self.context.get_holder_pubkeys().payment_point, + &self.context.get_counterparty_pubkeys().payment_point, + self.context.is_outbound(), + ); + let shutdown_script = + self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); + let mut monitor_signer = signer_provider.derive_channel_signer( + self.context.channel_value_satoshis, + self.context.channel_keys_id, + ); monitor_signer.provide_channel_parameters(&self.context.channel_transaction_parameters); - let channel_monitor = ChannelMonitor::new(self.context.secp_ctx.clone(), monitor_signer, - shutdown_script, self.context.get_holder_selected_contest_delay(), - &self.context.destination_script, (funding_txo, funding_txo_script.clone()), - &self.context.channel_transaction_parameters, - funding_redeemscript.clone(), self.context.channel_value_satoshis, - obscure_factor, - holder_commitment_tx, best_block, self.context.counterparty_node_id, self.context.channel_id()); + let channel_monitor = ChannelMonitor::new( + self.context.secp_ctx.clone(), + monitor_signer, + shutdown_script, + self.context.get_holder_selected_contest_delay(), + &self.context.destination_script, + (funding_txo, funding_txo_script.clone()), + &self.context.channel_transaction_parameters, + funding_redeemscript.clone(), + self.context.channel_value_satoshis, + obscure_factor, + holder_commitment_tx, + best_block, + self.context.counterparty_node_id, + self.context.channel_id(), + ); channel_monitor.provide_initial_counterparty_commitment_tx( - counterparty_initial_commitment_tx.trust().txid(), Vec::new(), + counterparty_initial_commitment_tx.trust().txid(), + Vec::new(), self.context.cur_counterparty_commitment_transaction_number + 1, - self.context.counterparty_cur_commitment_point.unwrap(), self.context.feerate_per_kw, + self.context.counterparty_cur_commitment_point.unwrap(), + self.context.feerate_per_kw, counterparty_initial_commitment_tx.to_broadcaster_value_sat(), - counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger); + counterparty_initial_commitment_tx.to_countersignatory_value_sat(), + logger, + ); - 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`. - let mut channel = Channel { - context: self.context, - }; + let mut channel = Channel { context: self.context }; let need_channel_ready = channel.check_get_channel_ready(0).is_some(); - 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)) } @@ -7483,7 +9580,10 @@ impl Readable for AnnouncementSigsState { } } -impl Writeable for Channel where SP::Target: SignerProvider { +impl Writeable for Channel +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. @@ -7504,7 +9604,10 @@ impl Writeable for Channel where SP::Target: SignerProvider { self.context.channel_id.write(writer)?; { let mut channel_state = self.context.channel_state; - if matches!(channel_state, ChannelState::AwaitingChannelReady(_)|ChannelState::ChannelReady(_)) { + if matches!( + channel_state, + ChannelState::AwaitingChannelReady(_) | ChannelState::ChannelReady(_) + ) { channel_state.set_peer_disconnected(); } else { debug_assert!(false, "Pre-funded/shutdown channels should not be written"); @@ -7517,7 +9620,12 @@ impl Writeable for Channel 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)?, } @@ -7593,7 +9701,7 @@ impl Writeable for Channel 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 { @@ -7601,7 +9709,7 @@ impl Writeable for Channel 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); @@ -7615,8 +9723,13 @@ impl Writeable for Channel where SP::Target: SignerProvider { 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)?; @@ -7637,9 +9750,11 @@ impl Writeable for Channel where SP::Target: SignerProvider { 2u8.write(writer)?; htlc_id.write(writer)?; err_packet.write(writer)?; - } + }, &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. @@ -7649,7 +9764,7 @@ impl Writeable for Channel where SP::Target: SignerProvider { 2u8.write(writer)?; htlc_id.write(writer)?; dummy_err_packet.write(writer)?; - } + }, } } @@ -7669,7 +9784,9 @@ impl Writeable for Channel 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)?; @@ -7677,7 +9794,9 @@ impl Writeable for Channel where SP::Target: SignerProvider { if self.context.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 @@ -7722,7 +9841,7 @@ impl Writeable for Channel 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.context.channel_transaction_parameters.write(writer)?; @@ -7749,22 +9868,40 @@ impl Writeable for Channel 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.context.channel_type != ChannelTypeFeatures::only_static_remote_key() { - Some(&self.context.channel_type) } else { None }; + let chan_type = + if self.context.channel_type != ChannelTypeFeatures::only_static_remote_key() { + Some(&self.context.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.context.holder_selected_channel_reserve_satoshis != get_legacy_default_holder_selected_channel_reserve_satoshis(self.context.channel_value_satoshis) - { Some(self.context.holder_selected_channel_reserve_satoshis) } else { None }; + if self.context.holder_selected_channel_reserve_satoshis + != get_legacy_default_holder_selected_channel_reserve_satoshis( + self.context.channel_value_satoshis, + ) { + Some(self.context.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.context.channel_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.context.channel_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); @@ -7774,7 +9911,12 @@ impl Writeable for Channel where SP::Target: SignerProvider { // 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) + }; write_tlv_fields!(writer, { (0, self.context.announcement_sigs, option), @@ -7817,13 +9959,16 @@ impl Writeable for Channel where SP::Target: SignerProvider { } } -const MAX_ALLOC_SIZE: usize = 64*1024; -impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)> for Channel - where - ES::Target: EntropySource, - SP::Target: SignerProvider +const MAX_ALLOC_SIZE: usize = 64 * 1024; +impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)> + for Channel +where + ES::Target: EntropySource, + SP::Target: SignerProvider, { - fn read(reader: &mut R, args: (&'a ES, &'b SP, u32, &'c ChannelTypeFeatures)) -> Result { + fn read( + reader: &mut R, args: (&'a ES, &'b SP, u32, &'c ChannelTypeFeatures), + ) -> Result { let (entropy_source, signer_provider, serialized_height, our_supported_features) = args; let ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); @@ -7835,7 +9980,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch let mut config = Some(LegacyChannelConfig::default()); if ver == 1 { // Read the old serialization of the ChannelConfig from version 0.0.98. - config.as_mut().unwrap().options.forwarding_fee_proportional_millionths = Readable::read(reader)?; + config.as_mut().unwrap().options.forwarding_fee_proportional_millionths = + Readable::read(reader)?; config.as_mut().unwrap().options.cltv_expiry_delta = Readable::read(reader)?; config.as_mut().unwrap().announced_channel = Readable::read(reader)?; config.as_mut().unwrap().commit_upfront_shutdown_pubkey = Readable::read(reader)?; @@ -7845,7 +9991,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch } let channel_id = 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)?; @@ -7859,7 +10006,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch while keys_data.as_ref().unwrap().len() != keys_len as usize { // Read 1KB at a time to avoid accidentally allocating 4GB on corrupted channel keys let mut data = [0; 1024]; - let read_slice = &mut data[0..cmp::min(1024, keys_len as usize - keys_data.as_ref().unwrap().len())]; + let read_slice = &mut data + [0..cmp::min(1024, keys_len as usize - keys_data.as_ref().unwrap().len())]; reader.read_exact(read_slice)?; keys_data.as_mut().unwrap().extend_from_slice(read_slice); } @@ -7878,7 +10026,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch 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)?, @@ -7896,7 +10047,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch } 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)?, @@ -7927,7 +10081,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch } 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 { @@ -7962,15 +10119,25 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch 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)?; @@ -8058,11 +10225,14 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch } 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 }; @@ -8070,8 +10240,14 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch 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()); @@ -8135,7 +10311,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch }); let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id { - let mut holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); + let mut holder_signer = + signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id); // If we've gotten to the funding stage of the channel, populate the signer with its // required channel parameters. if channel_state >= ChannelState::FundingNegotiated { @@ -8153,13 +10330,25 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch let mut iter = preimages.into_iter(); for htlc in pending_outbound_htlcs.iter_mut() { match &htlc.state { - OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(None)) => { - htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?)); - } - OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(None)) => { - htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?)); - } - _ => {} + OutboundHTLCState::AwaitingRemoteRevokeToRemove( + OutboundHTLCOutcome::Success(None), + ) => { + htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove( + OutboundHTLCOutcome::Success( + iter.next().ok_or(DecodeError::InvalidValue)?, + ), + ); + }, + OutboundHTLCState::AwaitingRemovedRemoteRevoke( + OutboundHTLCOutcome::Success(None), + ) => { + htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke( + OutboundHTLCOutcome::Success( + iter.next().ok_or(DecodeError::InvalidValue)?, + ), + ); + }, + _ => {}, } } // We expect all preimages to be consumed above @@ -8195,7 +10384,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch 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(); @@ -8205,7 +10396,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch } } // 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(); @@ -8213,7 +10406,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch 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(); @@ -8223,22 +10418,34 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch } } // 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(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); } } @@ -8316,7 +10523,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch counterparty_max_htlc_value_in_flight_msat, holder_max_htlc_value_in_flight_msat: holder_max_htlc_value_in_flight_msat.unwrap(), 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(), counterparty_htlc_minimum_msat, holder_htlc_minimum_msat, counterparty_max_accepted_htlcs, @@ -8363,66 +10571,86 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch channel_keys_id, blocked_monitor_updates: blocked_monitor_updates.unwrap(), - } + }, }) } } #[cfg(test)] mod tests { - use std::cmp; - use bitcoin::blockdata::constants::ChainHash; - use bitcoin::blockdata::script::{ScriptBuf, Builder}; - use bitcoin::blockdata::transaction::{Transaction, TxOut}; - use bitcoin::blockdata::opcodes; - use bitcoin::network::constants::Network; - use crate::ln::onion_utils::INVALID_ONION_BLINDING; - use crate::ln::{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, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_msat}; - use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS}; + use crate::ln::channel::{ + commit_tx_fee_msat, AwaitingChannelReadyFlags, Channel, ChannelState, 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::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; use crate::ln::msgs; use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT}; + use crate::ln::onion_utils::INVALID_ONION_BLINDING; 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::ln::{PaymentHash, PaymentPreimage}; + use crate::prelude::*; use crate::routing::router::{Path, RouteHop}; + use crate::sign::{ChannelSigner, EntropySource, InMemorySigner, SignerProvider}; 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::address::{WitnessProgram, WitnessVersion}; + use bitcoin::blockdata::constants::ChainHash; + use bitcoin::blockdata::locktime::absolute::LockTime; + use bitcoin::blockdata::opcodes; + use bitcoin::blockdata::script::{Builder, ScriptBuf}; + use bitcoin::blockdata::transaction::{Transaction, TxOut}; + use bitcoin::hash_types::WPubkeyHash; + use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; - use bitcoin::hashes::hex::FromHex; - use bitcoin::hash_types::WPubkeyHash; - use bitcoin::blockdata::locktime::absolute::LockTime; - use bitcoin::address::{WitnessProgram, WitnessVersion}; - use crate::prelude::*; + use bitcoin::network::constants::Network; + use bitcoin::secp256k1::ffi::Signature as FFISignature; + use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1}; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + 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 { @@ -8433,8 +10661,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 { @@ -8442,7 +10672,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 { @@ -8450,53 +10682,99 @@ mod tests { #[cfg(taproot)] type TaprootSigner = InMemorySigner; - fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { + fn generate_channel_keys_id( + &self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128, + ) -> [u8; 32] { self.signer.channel_keys_id() } - fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::EcdsaSigner { + fn derive_channel_signer( + &self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32], + ) -> Self::EcdsaSigner { self.signer.clone() } - fn read_chan_signer(&self, _data: &[u8]) -> Result { panic!(); } + fn read_chan_signer(&self, _data: &[u8]) -> Result { + panic!(); + } 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(all(feature = "_test_vectors", not(feature = "grind_signatures")))] - fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap()) + fn public_from_secret_hex( + secp_ctx: &Secp256k1, hex: &str, + ) -> PublicKey { + PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(), + ) } #[test] fn upfront_shutdown_script_incompatibility() { - let features = channelmanager::provided_init_features(&UserConfig::default()).clear_shutdown_anysegwit(); + let features = channelmanager::provided_init_features(&UserConfig::default()) + .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 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) { + match OutboundV1Channel::<&TestKeysInterface>::new( + &LowerBoundedFeeEstimator::new(&TestFeeEstimator { fee_est: 253 }), + &&keys_provider, + &&keys_provider, + node_id, + &features, + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + ) { Err(APIError::IncompatibleShutdownScript { script }) => { assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner()); }, @@ -8510,21 +10788,37 @@ 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]; let network = Network::Testnet; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); - 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 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).unwrap(); + let 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, + ) + .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)); + let open_channel_msg = + node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); assert_eq!(open_channel_msg.feerate_per_kw, original_fee); } @@ -8532,7 +10826,7 @@ mod tests { 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; @@ -8544,34 +10838,89 @@ 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).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, + ) + .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)); - 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)); + 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(); accept_channel_msg.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.context.get_funding_redeemscript(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: output_script.clone(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.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: 1, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { value: 10000000, script_pubkey: output_script.clone() }], + }; + let funding_outpoint = OutPoint { txid: tx.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. @@ -8591,7 +10940,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]), }, @@ -8602,16 +10957,26 @@ 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(htlc_candidate, None); - let local_commit_fee_0_htlcs = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.context.get_channel_type()); + let local_commit_tx_fee = + node_a_chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None); + let local_commit_fee_0_htlcs = commit_tx_fee_msat( + node_a_chan.context.feerate_per_kw, + 0, + node_a_chan.context.get_channel_type(), + ); 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.context.channel_transaction_parameters.is_outbound_from_holder = false; - let remote_commit_fee_3_htlcs = commit_tx_fee_msat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.context.get_channel_type()); + let remote_commit_fee_3_htlcs = commit_tx_fee_msat( + node_a_chan.context.feerate_per_kw, + 3, + node_a_chan.context.get_channel_type(), + ); 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(htlc_candidate, None); + let remote_commit_tx_fee = + node_a_chan.context.next_remote_commit_tx_fee_msat(htlc_candidate, None); assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs); } @@ -8621,50 +10986,83 @@ 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 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).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, + ) + .unwrap(); - let commitment_tx_fee_0_htlcs = commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.context.get_channel_type()); - let commitment_tx_fee_1_htlc = commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.context.get_channel_type()); + let commitment_tx_fee_0_htlcs = + commit_tx_fee_msat(chan.context.feerate_per_kw, 0, chan.context.get_channel_type()); + let commitment_tx_fee_1_htlc = + commit_tx_fee_msat(chan.context.feerate_per_kw, 1, chan.context.get_channel_type()); // 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.context.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000; - let htlc_candidate = HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered); + let htlc_amt_above_timeout = ((253 + * htlc_timeout_tx_weight(chan.context.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(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.context.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 dust_htlc_amt_below_success = ((253 + * htlc_success_tx_weight(chan.context.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(htlc_candidate, None); assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs); chan.context.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.context.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 dust_htlc_amt_above_timeout = ((253 + * htlc_timeout_tx_weight(chan.context.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(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.context.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000; - let htlc_candidate = HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered); + let htlc_amt_below_success = ((253 + * htlc_success_tx_weight(chan.context.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(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]; @@ -8676,31 +11074,85 @@ 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).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, + ) + .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); - 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(); - 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.context.get_funding_redeemscript(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: output_script.clone(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.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: 1, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { value: 10000000, script_pubkey: output_script.clone() }], + }; + let funding_outpoint = OutPoint { txid: tx.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. @@ -8721,80 +11173,220 @@ 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 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).unwrap(); + let 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, + ) + .unwrap(); let chan_1_value_msat = chan_1.context.channel_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).unwrap(); + 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, + ) + .unwrap(); let chan_2_value_msat = chan_2.context.channel_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); + 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)); + let chan_1_open_channel_msg = + chan_1.get_open_channel(ChainHash::using_genesis_block(network)); // 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 = 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.context.channel_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); + 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.context.channel_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).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, + ) + .unwrap(); let chan_5_value_msat = chan_5.context.channel_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).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, + ) + .unwrap(); let chan_6_value_msat = chan_6.context.channel_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.context.channel_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.context.channel_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); @@ -8814,45 +11406,113 @@ 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 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).unwrap(); + outbound_node_config + .channel_handshake_config + .their_channel_reserve_proportional_millionths = + (outbound_selected_channel_reserve_perc * 1_000_000.0) as u32; + let 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, + ) + .unwrap(); - let expected_outbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.context.channel_value_satoshis as f64 * outbound_selected_channel_reserve_perc) as u64); - assert_eq!(chan.context.holder_selected_channel_reserve_satoshis, expected_outbound_selected_chan_reserve); + let expected_outbound_selected_chan_reserve = cmp::max( + MIN_THEIR_CHAN_RESERVE_SATOSHIS, + (chan.context.channel_value_satoshis as f64 * outbound_selected_channel_reserve_perc) + as u64, + ); + assert_eq!( + chan.context.holder_selected_channel_reserve_satoshis, + expected_outbound_selected_chan_reserve + ); let chan_open_channel_msg = chan.get_open_channel(ChainHash::using_genesis_block(network)); 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 expected_inbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.context.channel_value_satoshis as f64 * inbound_selected_channel_reserve_perc) as u64); - - assert_eq!(chan_inbound_node.context.holder_selected_channel_reserve_satoshis, expected_inbound_selected_chan_reserve); - assert_eq!(chan_inbound_node.context.counterparty_selected_channel_reserve_satoshis.unwrap(), expected_outbound_selected_chan_reserve); + 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.context.channel_value_satoshis as f64 * inbound_selected_channel_reserve_perc) + as u64, + ); + + assert_eq!( + chan_inbound_node.context.holder_selected_channel_reserve_satoshis, + expected_inbound_selected_chan_reserve + ); + assert_eq!( + chan_inbound_node.context.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]; @@ -8862,34 +11522,89 @@ 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).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, + ) + .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)); - 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)); + 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(); accept_channel_msg.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.context.get_funding_redeemscript(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: output_script.clone(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.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: 1, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { value: 10000000, script_pubkey: output_script.clone() }], + }; + let funding_outpoint = OutPoint { txid: tx.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 { @@ -8905,7 +11620,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()); @@ -8918,7 +11633,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()); @@ -8929,30 +11644,75 @@ 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 - ).unwrap(); + &feeest, + &&keys_provider, + &&keys_provider, + node_b_node_id, + &features, + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + ) + .unwrap(); let 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)), 7, &config, 0, &&logger, false - ).unwrap(); - outbound_chan.accept_channel(&inbound_chan.get_accept_channel_message(), &config.channel_handshake_limits, &features).unwrap(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: outbound_chan.context.get_funding_redeemscript(), - }]}; - let funding_outpoint = OutPoint{ txid: tx.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)), + 7, + &config, + 0, + &&logger, + false, + ) + .unwrap(); + outbound_chan + .accept_channel( + &inbound_chan.get_accept_channel_message(), + &config.channel_handshake_limits, + &features, + ) + .unwrap(); + let tx = Transaction { + version: 1, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { + value: 10000000, + script_pubkey: outbound_chan.context.get_funding_redeemscript(), + }], + }; + let funding_outpoint = OutPoint { txid: tx.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), }; @@ -8960,11 +11720,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, @@ -8999,8 +11763,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, @@ -9010,11 +11774,15 @@ mod tests { htlc_id: 0, }; let dummy_holding_cell_failed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailHTLC { - htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42] } - }; - let dummy_holding_cell_malformed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC { - htlc_id, failure_code: INVALID_ONION_BLINDING, sha256_of_onion: [0; 32], + htlc_id, + err_packet: msgs::OnionErrorPacket { data: vec![42] }, }; + let dummy_holding_cell_malformed_htlc = + |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC { + htlc_id, + failure_code: INVALID_ONION_BLINDING, + sha256_of_onion: [0; 32], + }; let mut holding_cell_htlc_updates = Vec::with_capacity(12); for i in 0..12 { if i % 5 == 0 { @@ -9024,11 +11792,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)); @@ -9041,9 +11814,11 @@ 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 = Channel::read(&mut reader, (&&keys_provider, &&keys_provider, 0, &features)).unwrap(); + let decoded_chan = + Channel::read(&mut reader, (&&keys_provider, &&keys_provider, 0, &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); } @@ -9051,87 +11826,198 @@ mod tests { #[cfg(all(feature = "_test_vectors", not(feature = "grind_signatures")))] #[test] fn outbound_commitment_test() { - use bitcoin::sighash; + use crate::ln::chan_utils::{ + ChannelPublicKeys, CounterpartyChannelTransactionParameters, + HolderCommitmentTransaction, + }; + use crate::ln::channel::{HTLCOutputInCommitment, TxCreationKeys}; + use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint}; + use crate::ln::PaymentPreimage; + use crate::sign::{ecdsa::EcdsaChannelSigner, ChannelDerivationParameters, HTLCDescriptor}; + use crate::sync::Arc; + use crate::util::logger::Logger; use bitcoin::consensus::encode::serialize; - use bitcoin::sighash::EcdsaSighashType; - use bitcoin::hashes::hex::FromHex; use bitcoin::hash_types::Txid; + use bitcoin::hashes::hex::FromHex; use bitcoin::secp256k1::Message; - use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ecdsa::EcdsaChannelSigner}; - use crate::ln::PaymentPreimage; - use crate::ln::channel::{HTLCOutputInCommitment ,TxCreationKeys}; - 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; use hex::DisplayHex; // 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 mut 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, + ], 10_000_000, [0; 32], [0; 32], ); - assert_eq!(signer.pubkeys().funding_pubkey.serialize()[..], - >::from_hex("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]); + assert_eq!( + signer.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.announced_channel = 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).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, + ) + .unwrap(); // Nothing uses their network key in this test chan.context.holder_dust_limit_satoshis = 546; chan.context.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.context.channel_transaction_parameters.counterparty_parameters = Some( - CounterpartyChannelTransactionParameters { + chan.context.channel_transaction_parameters.counterparty_parameters = + Some(CounterpartyChannelTransactionParameters { pubkeys: counterparty_pubkeys.clone(), - selected_contest_delay: 144 + selected_contest_delay: 144, }); chan.context.channel_transaction_parameters.funding_outpoint = Some(funding_info); signer.provide_channel_parameters(&chan.context.channel_transaction_parameters); - 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 delayed_payment_base = &chan.context.holder_signer.as_ref().pubkeys().delayed_payment_basepoint; - let per_commitment_secret = SecretKey::from_slice(&>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); + let delayed_payment_base = + &chan.context.holder_signer.as_ref().pubkeys().delayed_payment_basepoint; + 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 htlc_basepoint = &chan.context.holder_signer.as_ref().pubkeys().htlc_basepoint; - let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint); + let keys = TxCreationKeys::derive_new( + &secp_ctx, + &per_commitment_point, + delayed_payment_base, + htlc_basepoint, + &counterparty_pubkeys.revocation_basepoint, + &counterparty_pubkeys.htlc_basepoint, + ); macro_rules! test_commitment { ( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $($remain:tt)* ) => { @@ -9267,29 +12153,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, @@ -9299,11 +12197,17 @@ mod tests { skimmed_fee_msat: None, blinding_point: 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, @@ -9313,18 +12217,30 @@ mod tests { skimmed_fee_msat: None, blinding_point: 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 }); @@ -9703,19 +12619,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, @@ -9725,11 +12647,17 @@ mod tests { skimmed_fee_msat: None, blinding_point: 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, @@ -9739,7 +12667,13 @@ mod tests { skimmed_fee_msat: None, blinding_point: 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 }); @@ -9786,23 +12720,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] @@ -9810,48 +12774,130 @@ 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 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).unwrap(); + let 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, + ) + .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)); + let mut open_channel_msg = + node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); open_channel_msg.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()); } @@ -9860,13 +12906,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; @@ -9874,10 +12922,20 @@ 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 - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&UserConfig::default()), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + ) + .unwrap(); assert!(!channel_a.context.channel_type.supports_anchors_zero_fee_htlc_tx()); let mut expected_channel_type = ChannelTypeFeatures::empty(); @@ -9885,17 +12943,37 @@ mod tests { expected_channel_type.set_anchors_zero_fee_htlc_tx_required(); let 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 - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + ) + .unwrap(); let open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network)); 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.context.channel_type, expected_channel_type); assert_eq!(channel_b.context.channel_type, expected_channel_type); @@ -9906,13 +12984,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(); @@ -9920,24 +13000,45 @@ 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 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 - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + ) + .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)); + let mut open_channel_msg = + channel_a.get_open_channel(ChainHash::using_genesis_block(network)); open_channel_msg.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()); } @@ -9947,13 +13048,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(); @@ -9961,8 +13064,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()); @@ -9970,18 +13075,38 @@ 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 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 - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &channelmanager::provided_init_features(&config), + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + ) + .unwrap(); - let mut open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network)); + let mut open_channel_msg = + channel_a.get_open_channel(ChainHash::using_genesis_block(network)); open_channel_msg.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()); @@ -9990,30 +13115,53 @@ 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 - ).unwrap(); + &fee_estimator, + &&keys_provider, + &&keys_provider, + node_id_b, + &simple_anchors_init, + 10000000, + 100000, + 42, + &config, + 0, + 42, + None, + ) + .unwrap(); let open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network)); 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(); let mut accept_channel_msg = channel_b.get_accept_channel_message(); accept_channel_msg.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]; @@ -10028,7 +13176,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, @@ -10041,11 +13190,14 @@ mod tests { &config, 0, 42, - None - ).unwrap(); + None, + ) + .unwrap(); - let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); - 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)); + 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, @@ -10058,15 +13210,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(); - 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.context.get_funding_redeemscript(); @@ -10075,23 +13230,19 @@ mod tests { lock_time: LockTime::ZERO, input: Vec::new(), output: vec![ - TxOut { - value: 10000000, script_pubkey: output_script.clone(), - }, - TxOut { - value: 10000000, script_pubkey: Builder::new().into_script(), - }, - ]}; - let funding_outpoint = OutPoint{ txid: tx.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(); + TxOut { value: 10000000, script_pubkey: output_script.clone() }, + TxOut { value: 10000000, script_pubkey: Builder::new().into_script() }, + ], + }; + let funding_outpoint = OutPoint { txid: tx.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, @@ -10103,9 +13254,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, @@ -10117,25 +13275,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).is_some()); } } diff --git a/lightning/src/ln/channel_id.rs b/lightning/src/ln/channel_id.rs index 19003961ff1..5496e0e93cb 100644 --- a/lightning/src/ln/channel_id.rs +++ b/lightning/src/ln/channel_id.rs @@ -49,7 +49,9 @@ impl ChannelId { /// Create a _temporary_ channel ID randomly, based on an entropy source. pub fn temporary_from_entropy_source(entropy_source: &ES) -> Self - where ES::Target: EntropySource { + where + ES::Target: EntropySource, + { Self(entropy_source.get_secure_random_bytes()) } @@ -93,16 +95,19 @@ impl fmt::Display for ChannelId { mod tests { use hex::DisplayHex; + use crate::io; use crate::ln::ChannelId; + use crate::prelude::*; use crate::util::ser::{Readable, Writeable}; use crate::util::test_utils; - use crate::prelude::*; - use crate::io; #[test] fn test_channel_id_v1_from_funding_txid() { let channel_id = ChannelId::v1_from_funding_txid(&[2; 32], 1); - assert_eq!(channel_id.0.as_hex().to_string(), "0202020202020202020202020202020202020202020202020202020202020203"); + assert_eq!( + channel_id.0.as_hex().to_string(), + "0202020202020202020202020202020202020202020202020202020202020203" + ); } #[test] @@ -137,6 +142,9 @@ mod tests { #[test] fn test_channel_id_display() { let channel_id = ChannelId::v1_from_funding_txid(&[2; 32], 1); - assert_eq!(format!("{}", &channel_id), "0202020202020202020202020202020202020202020202020202020202020203"); + assert_eq!( + format!("{}", &channel_id), + "0202020202020202020202020202020202020202020202020202020202020203" + ); } } diff --git a/lightning/src/ln/channel_keys.rs b/lightning/src/ln/channel_keys.rs index b577dc60008..4128f06aab1 100644 --- a/lightning/src/ln/channel_keys.rs +++ b/lightning/src/ln/channel_keys.rs @@ -10,19 +10,19 @@ //! Keys used to generate commitment transactions. //! See: -use bitcoin::hashes::Hash; -use bitcoin::hashes::HashEngine; -use bitcoin::secp256k1::Scalar; -use bitcoin::secp256k1::SecretKey; -use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1; +use crate::io; use crate::ln::msgs::DecodeError; use crate::util::ser::Readable; -use crate::io; -use crate::util::ser::Writer; use crate::util::ser::Writeable; -use bitcoin::secp256k1::PublicKey; +use crate::util::ser::Writer; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; +use bitcoin::hashes::HashEngine; +use bitcoin::secp256k1; +use bitcoin::secp256k1::PublicKey; +use bitcoin::secp256k1::Scalar; +use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::SecretKey; macro_rules! doc_comment { ($x:expr, $($tt:tt)*) => { @@ -44,8 +44,7 @@ macro_rules! basepoint_impl { Self(value) } } - - } + }; } macro_rules! key_impl { ($BasepointT:ty, $KeyName:expr) => { @@ -87,11 +86,9 @@ macro_rules! key_read_write { Ok(Self(key)) } } - } + }; } - - /// Base key used in conjunction with a `per_commitment_point` to generate a [`DelayedPaymentKey`]. /// /// The delayed payment key is used to pay the commitment state broadcaster their @@ -102,7 +99,6 @@ pub struct DelayedPaymentBasepoint(pub PublicKey); basepoint_impl!(DelayedPaymentBasepoint); key_read_write!(DelayedPaymentBasepoint); - /// A derived key built from a [`DelayedPaymentBasepoint`] and `per_commitment_point`. /// /// The delayed payment key is used to pay the commitment state broadcaster their @@ -150,14 +146,19 @@ key_read_write!(HtlcKey); /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key) /// from the base point and the per_commitment_key. This is the public equivalent of /// derive_private_key - using only public keys to derive a public key instead of private keys. -fn derive_public_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey { +fn derive_public_key( + secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_point: &PublicKey, +) -> PublicKey { let mut sha = Sha256::engine(); sha.input(&per_commitment_point.serialize()); sha.input(&base_point.serialize()); let res = Sha256::from_engine(sha).to_byte_array(); - let hashkey = PublicKey::from_secret_key(&secp_ctx, - &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken")); + let hashkey = PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice(&res) + .expect("Hashes should always be valid keys unless SHA-256 is broken"), + ); base_point.combine(&hashkey) .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.") } @@ -169,7 +170,6 @@ pub struct RevocationBasepoint(pub PublicKey); basepoint_impl!(RevocationBasepoint); key_read_write!(RevocationBasepoint); - /// The revocation key is used to allow a channel party to revoke their state - giving their /// counterparty the required material to claim all of their funds if they broadcast that state. /// @@ -192,8 +192,7 @@ impl RevocationKey { /// /// [`chan_utils::derive_private_revocation_key`]: crate::ln::chan_utils::derive_private_revocation_key pub fn from_basepoint( - secp_ctx: &Secp256k1, - countersignatory_basepoint: &RevocationBasepoint, + secp_ctx: &Secp256k1, countersignatory_basepoint: &RevocationBasepoint, per_commitment_point: &PublicKey, ) -> Self { let rev_append_commit_hash_key = { @@ -227,28 +226,56 @@ impl RevocationKey { } key_read_write!(RevocationKey); - #[cfg(test)] mod test { - use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey}; - use bitcoin::hashes::hex::FromHex; use super::derive_public_key; + use bitcoin::hashes::hex::FromHex; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; #[test] fn test_key_derivation() { // 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!(derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..], - >::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]); + assert_eq!( + per_commitment_point.serialize()[..], + >::from_hex( + "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486" + ) + .unwrap()[..] + ); + + assert_eq!( + derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..], + >::from_hex( + "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5" + ) + .unwrap()[..] + ); } } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index b5fc9996e29..d19e2a51469 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -18,66 +18,95 @@ //! imply it needs to fail HTLCs/payments/channels it manages). use bitcoin::blockdata::block::Header; -use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::constants::ChainHash; +use bitcoin::blockdata::transaction::Transaction; use bitcoin::key::constants::SECRET_KEY_SIZE; use bitcoin::network::constants::Network; -use bitcoin::hashes::Hash; -use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hash_types::{BlockHash, Txid}; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; -use bitcoin::secp256k1::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::{secp256k1, Sequence}; -use crate::blinded_path::BlindedPath; use crate::blinded_path::payment::{PaymentConstraints, ReceiveTlvs}; +use crate::blinded_path::BlindedPath; use crate::chain; -use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock}; -use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator}; -use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, WithChannelMonitor, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent, CLOSED_CHANNEL_UPDATE_ID}; +use crate::chain::chaininterface::{ + BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator, +}; +use crate::chain::channelmonitor::{ + ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, MonitorEvent, + WithChannelMonitor, ANTI_REORG_DELAY, CLOSED_CHANNEL_UPDATE_ID, CLTV_CLAIM_BUFFER, + HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, +}; use crate::chain::transaction::{OutPoint, TransactionData}; +use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Watch}; use crate::events; -use crate::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination, PaymentFailureReason}; +use crate::events::{ + ClosureReason, Event, EventHandler, EventsProvider, HTLCDestination, MessageSendEvent, + MessageSendEventsProvider, PaymentFailureReason, +}; // 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, ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; -use crate::ln::channel::{self, Channel, ChannelPhase, ChannelContext, ChannelError, ChannelUpdateStatus, ShutdownResult, UnfundedChannelContext, UpdateFulfillCommitFetch, OutboundV1Channel, InboundV1Channel, WithChannelContext}; -use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; +use crate::ln::channel::{ + self, Channel, ChannelContext, ChannelError, ChannelPhase, ChannelUpdateStatus, + InboundV1Channel, OutboundV1Channel, ShutdownResult, UnfundedChannelContext, + UpdateFulfillCommitFetch, WithChannelContext, +}; #[cfg(any(feature = "_test_utils", test))] use crate::ln::features::Bolt11InvoiceFeatures; -use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteParameters, Router}; -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, InboundHTLCErr, NextPacketDetails}; +use crate::ln::features::{ + Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures, +}; use crate::ln::msgs; +use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; +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, InboundHTLCErr, NextPacketDetails, +}; use crate::ln::onion_utils; use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING}; -use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; #[cfg(test)] use crate::ln::outbound_payment; -use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration}; +use crate::ln::outbound_payment::{ + Bolt12PaymentError, OutboundPayments, PaymentAttempts, PendingOutboundPayment, + SendAlongPathArgs, StaleExpiration, +}; use crate::ln::wire::Encode; -use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, InvoiceBuilder}; +use crate::ln::{inbound_payment, ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; +use crate::offers::invoice::{ + BlindedPayInfo, Bolt12Invoice, DerivedSigningPubkey, InvoiceBuilder, DEFAULT_RELATIVE_EXPIRY, +}; use crate::offers::invoice_error::InvoiceError; use crate::offers::merkle::SignError; use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder}; use crate::offers::parse::Bolt12SemanticError; use crate::offers::refund::{Refund, RefundBuilder}; -use crate::onion_message::messenger::{Destination, MessageRouter, PendingOnionMessage, new_pending_onion_message}; +use crate::onion_message::messenger::{ + new_pending_onion_message, Destination, MessageRouter, PendingOnionMessage, +}; use crate::onion_message::offers::{OffersMessage, OffersMessageHandler}; -use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; +use crate::routing::router::{ + BlindedTail, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteParameters, Router, +}; use crate::sign::ecdsa::WriteableEcdsaChannelSigner; -use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate}; -use crate::util::wakers::{Future, Notifier}; +use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; +use crate::util::config::{ChannelConfig, 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, MaybeReadable, Readable, ReadableArgs, VecWriter, Writeable, Writer, +}; use crate::util::string::UntrustedString; -use crate::util::ser::{BigSize, FixedLengthReader, 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(not(c_bindings))] use { - crate::routing::router::DefaultRouter, crate::routing::gossip::NetworkGraph, + crate::routing::router::DefaultRouter, crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters}, crate::sign::KeysManager, }; @@ -85,17 +114,19 @@ use { 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 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 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::{PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields}; +pub use crate::ln::outbound_payment::{ + PaymentSendFailure, ProbeSendFailure, RecipientOnionFields, Retry, RetryableSendFailure, +}; use crate::ln::script::ShutdownScript; // We hold various information about HTLC relay in the HTLC objects in Channel itself: @@ -212,7 +243,9 @@ impl PendingHTLCRouting { fn blinded_failure(&self) -> Option { match self { Self::Forward { blinded: Some(BlindedForward { failure, .. }), .. } => Some(*failure), - Self::Receive { requires_blinded_error: true, .. } => Some(BlindedFailure::FromBlindedNode), + Self::Receive { requires_blinded_error: true, .. } => { + Some(BlindedFailure::FromBlindedNode) + }, _ => None, } } @@ -296,15 +329,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, @@ -442,8 +468,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() } + }, } } } @@ -457,7 +484,6 @@ impl_writeable_tlv_based_enum!(SentHTLCId, }; ); - /// Tracks the inbound corresponding to an outbound HTLC #[allow(clippy::derive_hash_xor_eq)] // Our Hash is faithful to the data, we just don't have SecretKey::hash #[derive(Clone, Debug, PartialEq, Eq)] @@ -505,7 +531,9 @@ impl HTLCSource { #[cfg(debug_assertions)] /// 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 { @@ -541,7 +569,7 @@ pub enum FailureCode { } impl Into for FailureCode { - fn into(self) -> u16 { + fn into(self) -> u16 { match self { FailureCode::TemporaryNodeFailure => 0x2000 | 2, FailureCode::RequiredNodeFeatureMissing => 0x4000 | 0x2000 | 3, @@ -569,10 +597,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, @@ -584,7 +609,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 @@ -604,27 +632,20 @@ 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::Ignore(msg) => LightningError { - err: msg, - action: msgs::ErrorAction::IgnoreError, + ChannelError::Ignore(msg) => { + LightningError { err: msg, action: msgs::ErrorAction::IgnoreError } }, ChannelError::Close(msg) => LightningError { err: msg.clone(), action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { - channel_id, - data: msg - }, + msg: msgs::ErrorMessage { channel_id, data: msg }, }, }, }, @@ -724,15 +745,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 }, } #[derive(Debug)] @@ -752,7 +770,8 @@ pub(crate) enum MonitorUpdateCompletionAction { /// outbound edge. EmitEventAndFreeOtherChannel { event: events::Event, - downstream_counterparty_and_funding_outpoint: Option<(PublicKey, OutPoint, ChannelId, RAAMonitorUpdateBlockingAction)>, + downstream_counterparty_and_funding_outpoint: + Option<(PublicKey, OutPoint, ChannelId, RAAMonitorUpdateBlockingAction)>, }, /// Indicates we should immediately resume the operation of another channel, unless there is /// some other reason why the channel is blocked. In practice this simply means immediately @@ -843,9 +862,11 @@ impl_writeable_tlv_based_enum!(RAAMonitorUpdateBlockingAction, (0, ForwardedPaymentInboundClaim) => { (0, channel_id, required), (2, htlc_id, required) } ;); - /// State we hold per-peer. -pub(super) struct PeerState where SP::Target: SignerProvider { +pub(super) struct PeerState +where + SP::Target: SignerProvider, +{ /// `channel_id` -> `ChannelPhase` /// /// Holds all channels within corresponding `ChannelPhase`s where the peer is the counterparty. @@ -895,15 +916,21 @@ pub(super) struct PeerState where SP::Target: SignerProvider { is_connected: bool, } -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; } - self.channel_by_id.iter().filter(|(_, phase)| matches!(phase, ChannelPhase::Funded(_))).count() == 0 + self.channel_by_id + .iter() + .filter(|(_, phase)| matches!(phase, ChannelPhase::Funded(_))) + .count() == 0 && self.monitor_update_blocked_actions.is_empty() && self.in_flight_monitor_updates.is_empty() } @@ -915,8 +942,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) } } @@ -972,14 +999,16 @@ pub type SimpleArcChannelManager = ChannelManager< Arc, Arc, Arc, - Arc>>, - Arc, - Arc>>, Arc>>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer>>, Arc>, - >>, - Arc + Arc< + DefaultRouter< + Arc>>, + Arc, + Arc>>, Arc>>>, + ProbabilisticScoringFeeParameters, + ProbabilisticScorer>>, Arc>, + >, + >, + Arc, >; /// [`SimpleRefChannelManager`] is a type alias for a ChannelManager reference, and is the reference @@ -994,23 +1023,22 @@ 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, 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, - &'h RwLock, &'g L>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L> - >, - &'g L - >; +pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 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, + &'h RwLock, &'g L>>, + ProbabilisticScoringFeeParameters, + ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>, + >, + &'g L, +>; /// A trivial trait which describes any [`ChannelManager`]. /// @@ -1036,7 +1064,7 @@ pub trait AChannelManager { /// A type implementing [`WriteableEcdsaChannelSigner`]. type Signer: WriteableEcdsaChannelSigner + 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`]. @@ -1052,11 +1080,13 @@ 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; } -impl AChannelManager -for ChannelManager +impl + AChannelManager for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -1084,7 +1114,9 @@ where type R = R; type Logger = L::Target; type L = L; - fn get_cm(&self) -> &ChannelManager { self } + fn get_cm(&self) -> &ChannelManager { + self + } } /// Manager which keeps track of a number of channels and sends messages to the appropriate @@ -1181,8 +1213,16 @@ 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, + L: Deref, +> where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, ES::Target: EntropySource, @@ -1441,19 +1481,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(); @@ -1467,8 +1511,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, } }, @@ -1479,8 +1527,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 { @@ -1499,8 +1548,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 => {}, } } @@ -1527,7 +1575,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*7; +pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6 * 7; // 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 @@ -1551,12 +1599,17 @@ pub const MIN_FINAL_CLTV_EXPIRY_DELTA: u16 = HTLC_FAIL_BACK_BUFFER as u16 + 3; // failing the corresponding htlc backward, and us now seeing the last block of ANTI_REORG_DELAY before // LATENCY_GRACE_PERIOD_BLOCKS. #[allow(dead_code)] -const CHECK_CLTV_EXPIRY_SANITY: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - CLTV_CLAIM_BUFFER - ANTI_REORG_DELAY - LATENCY_GRACE_PERIOD_BLOCKS; +const CHECK_CLTV_EXPIRY_SANITY: u32 = MIN_CLTV_EXPIRY_DELTA as u32 + - LATENCY_GRACE_PERIOD_BLOCKS + - CLTV_CLAIM_BUFFER + - ANTI_REORG_DELAY + - LATENCY_GRACE_PERIOD_BLOCKS; // Check for ability of an attacker to make us fail on-chain by delaying an HTLC claim. See // ChannelMonitor::should_broadcast_holder_commitment_txn for a description of why this is needed. #[allow(dead_code)] -const CHECK_CLTV_EXPIRY_SANITY_2: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2*CLTV_CLAIM_BUFFER; +const CHECK_CLTV_EXPIRY_SANITY_2: u32 = + MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2 * CLTV_CLAIM_BUFFER; /// The number of ticks of [`ChannelManager::timer_tick_occurred`] until expiry of incomplete MPPs pub(crate) const MPP_TIMEOUT_TICKS: u8 = 3; @@ -1829,11 +1882,11 @@ impl ChannelDetails { fn from_channel_context( context: &ChannelContext, best_block_height: u32, latest_features: InitFeatures, - fee_estimator: &LowerBoundedFeeEstimator + fee_estimator: &LowerBoundedFeeEstimator, ) -> Self where SP::Target: SignerProvider, - F::Target: FeeEstimator + F::Target: FeeEstimator, { let balance = context.get_available_balances(fee_estimator); let (to_remote_reserve_satoshis, to_self_reserve_satoshis) = @@ -1851,15 +1904,26 @@ impl ChannelDetails { // Else `Channel::get_counterparty_htlc_minimum_msat` could return the // default `0` value set by `Channel::new_outbound`. outbound_htlc_minimum_msat: if context.have_received_message() { - Some(context.get_counterparty_htlc_minimum_msat()) } else { None }, + Some(context.get_counterparty_htlc_minimum_msat()) + } else { + None + }, outbound_htlc_maximum_msat: context.get_counterparty_htlc_maximum_msat(), }, funding_txo: context.get_funding_txo(), // Note that accept_channel (or open_channel) is always the first message, so // `have_received_message` indicates that type negotiation has completed. - channel_type: if context.have_received_message() { Some(context.get_channel_type().clone()) } else { None }, + channel_type: if context.have_received_message() { + Some(context.get_channel_type().clone()) + } else { + None + }, short_channel_id: context.get_short_channel_id(), - outbound_scid_alias: if context.is_usable() { Some(context.outbound_scid_alias()) } else { None }, + outbound_scid_alias: if context.is_usable() { + Some(context.outbound_scid_alias()) + } else { + None + }, inbound_scid_alias: context.latest_inbound_scid_alias(), channel_value_satoshis: context.get_value_satoshis(), feerate_sat_per_1000_weight: Some(context.get_feerate_sat_per_1000_weight()), @@ -1967,7 +2031,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); @@ -1982,15 +2046,16 @@ 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), + &$self.logger, + Some(counterparty_node_id), + Some(channel_id), ); log_error!(logger, "Force-closing channel: {}", err.err); $self.finish_close_channel(shutdown_res); if let Some(update) = update_option { - msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + msg_events + .push(events::MessageSendEvent::BroadcastChannelUpdate { msg: update }); } } else { log_error!($self.logger, "Got non-closing error: {}", err.err); @@ -2000,7 +2065,7 @@ macro_rules! handle_error { } else { msg_events.push(events::MessageSendEvent::HandleError { node_id: $counterparty_node_id, - action: err.action.clone() + action: err.action.clone(), }); } @@ -2016,7 +2081,7 @@ macro_rules! handle_error { Err(err) }, } - } }; + }}; } macro_rules! update_maps_on_chan_removal { @@ -2034,37 +2099,54 @@ macro_rules! update_maps_on_chan_removal { // 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_chan_phase_err { ($self: ident, $err: expr, $channel: 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::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::Ignore(msg) => ( + false, + MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), *$channel_id), + ), ChannelError::Close(msg) => { let logger = WithChannelContext::from(&$self.logger, &$channel.context); - 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 + ); update_maps_on_chan_removal!($self, $channel.context); let reason = ClosureReason::ProcessingError { err: msg.clone() }; let shutdown_res = $channel.context.force_shutdown(true, reason); - 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) }, } }; ($self: ident, $err: expr, $channel: expr, $channel_id: expr, FUNDED_CHANNEL) => { - convert_chan_phase_err!($self, $err, $channel, $channel_id, MANUAL_CHANNEL_UPDATE, { $self.get_channel_update_for_broadcast($channel).ok() }) + convert_chan_phase_err!($self, $err, $channel, $channel_id, MANUAL_CHANNEL_UPDATE, { + $self.get_channel_update_for_broadcast($channel).ok() + }) }; ($self: ident, $err: expr, $channel: expr, $channel_id: expr, UNFUNDED_CHANNEL) => { convert_chan_phase_err!($self, $err, $channel, $channel_id, MANUAL_CHANNEL_UPDATE, None) @@ -2095,9 +2177,9 @@ macro_rules! break_chan_phase_entry { $entry.remove_entry(); } break Err(res); - } + }, } - } + }; } macro_rules! try_chan_phase_entry { @@ -2111,19 +2193,17 @@ macro_rules! try_chan_phase_entry { $entry.remove_entry(); } return Err(res); - } + }, } - } + }; } macro_rules! remove_channel_phase { - ($self: expr, $entry: expr) => { - { - let channel = $entry.remove_entry().1; - update_maps_on_chan_removal!($self, &channel.context()); - channel - } - } + ($self: expr, $entry: expr) => {{ + let channel = $entry.remove_entry().1; + update_maps_on_chan_removal!($self, &channel.context()); + channel + }}; } macro_rules! send_channel_ready { @@ -2149,31 +2229,41 @@ macro_rules! send_channel_ready { 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.context.get_funding_txo().unwrap().into_bitcoin_outpoint(), - }, 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 + .context + .get_funding_txo() + .unwrap() + .into_bitcoin_outpoint(), + }, + 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.context.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.context.get_channel_type().clone(), + }, + None, + )); $channel.context.set_channel_ready_event_emitted(); } - } + }; } macro_rules! handle_monitor_update_completion { @@ -2322,7 +2412,11 @@ macro_rules! process_events_body { ($self: expr, $event_to_handle: expr, $handle_event: expr) => { let mut processed_all_events = false; while !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; } @@ -2380,15 +2474,15 @@ 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 + ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -2439,7 +2533,10 @@ where pending_inbound_payments: Mutex::new(HashMap::new()), pending_outbound_payments: OutboundPayments::new(), forward_htlcs: Mutex::new(HashMap::new()), - claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: HashMap::new(), pending_claiming_payments: HashMap::new() }), + claimable_payments: Mutex::new(ClaimablePayments { + claimable_payments: HashMap::new(), + pending_claiming_payments: HashMap::new(), + }), pending_intercepted_htlcs: Mutex::new(HashMap::new()), outpoint_to_peer: Mutex::new(HashMap::new()), short_to_chan_info: FairRwLock::new(HashMap::new()), @@ -2485,16 +2582,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 } @@ -2531,9 +2638,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); @@ -2542,25 +2658,46 @@ 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 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) - { + 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, + ) { Ok(res) => res, Err(e) => { self.outbound_scid_aliases.lock().unwrap().remove(&outbound_scid_alias); @@ -2579,7 +2716,9 @@ where panic!("RNG is bad???"); } }, - hash_map::Entry::Vacant(entry) => { entry.insert(ChannelPhase::UnfundedOutboundV1(channel)); } + hash_map::Entry::Vacant(entry) => { + entry.insert(ChannelPhase::UnfundedOutboundV1(channel)); + }, } peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel { @@ -2589,7 +2728,9 @@ where 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, and the `outpoint_to_peer` shouldn't be used outside @@ -2603,17 +2744,24 @@ 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() - .filter_map(|(chan_id, phase)| match phase { - // Only `Channels` in the `ChannelPhase::Funded` phase can be considered funded. - ChannelPhase::Funded(chan) => Some((chan_id, chan)), - _ => None, - }) - .filter(f) - .map(|(_channel_id, channel)| { - ChannelDetails::from_channel_context(&channel.context, best_block_height, - peer_state.latest_features.clone(), &self.fee_estimator) - }) + res.extend( + peer_state + .channel_by_id + .iter() + .filter_map(|(chan_id, phase)| match phase { + // Only `Channels` in the `ChannelPhase::Funded` phase can be considered funded. + ChannelPhase::Funded(chan) => Some((chan_id, chan)), + _ => None, + }) + .filter(f) + .map(|(_channel_id, channel)| { + ChannelDetails::from_channel_context( + &channel.context, + best_block_height, + peer_state.latest_features.clone(), + &self.fee_estimator, + ) + }), ); } } @@ -2637,8 +2785,12 @@ where let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; for context in peer_state.channel_by_id.iter().map(|(_, phase)| phase.context()) { - let details = ChannelDetails::from_channel_context(context, best_block_height, - peer_state.latest_features.clone(), &self.fee_estimator); + let details = ChannelDetails::from_channel_context( + context, + best_block_height, + peer_state.latest_features.clone(), + &self.fee_estimator, + ); res.push(details); } } @@ -2660,7 +2812,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(); @@ -2669,9 +2823,15 @@ where let peer_state = &mut *peer_state_lock; let features = &peer_state.latest_features; let context_to_details = |context| { - ChannelDetails::from_channel_context(context, best_block_height, features.clone(), &self.fee_estimator) + ChannelDetails::from_channel_context( + context, + best_block_height, + features.clone(), + &self.fee_estimator, + ) }; - return peer_state.channel_by_id + return peer_state + .channel_by_id .iter() .map(|(_, phase)| phase.context()) .map(context_to_details) @@ -2689,7 +2849,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 { .. } => { Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id }) @@ -2706,17 +2870,27 @@ where }) }, PendingOutboundPayment::Abandoned { payment_hash, .. } => { - Some(RecentPaymentDetails::Abandoned { payment_id: *payment_id, payment_hash: *payment_hash }) + Some(RecentPaymentDetails::Abandoned { + payment_id: *payment_id, + payment_hash: *payment_hash, + }) }, PendingOutboundPayment::Fulfilled { payment_hash, .. } => { - Some(RecentPaymentDetails::Fulfilled { payment_id: *payment_id, payment_hash: *payment_hash }) + Some(RecentPaymentDetails::Fulfilled { + payment_id: *payment_id, + payment_hash: *payment_hash, + }) }, - PendingOutboundPayment::Legacy { .. } => None + PendingOutboundPayment::Legacy { .. } => None, }) .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(); @@ -2725,8 +2899,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; @@ -2736,29 +2916,49 @@ where if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() { let funding_txo_opt = chan.context.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` // here as we don't need the monitor update to complete until we send a // `shutdown_signed`, which we'll delay if we're pending a monitor update. - peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown { - node_id: *counterparty_node_id, - msg: shutdown_msg, - }); + peer_state.pending_msg_events.push( + events::MessageSendEvent::SendShutdown { + node_id: *counterparty_node_id, + 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(), *channel_id, monitor_update, - peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo_opt.unwrap(), + *channel_id, + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } } else { let mut chan_phase = remove_channel_phase!(self, chan_phase_entry); - shutdown_result = Some(chan_phase.context_mut().force_shutdown(false, ClosureReason::HolderForceClosed)); + shutdown_result = Some( + chan_phase + .context_mut() + .force_shutdown(false, ClosureReason::HolderForceClosed), + ); } }, hash_map::Entry::Vacant(_) => { @@ -2766,7 +2966,7 @@ where err: format!( "Channel with id {} not found for the passed counterparty node_id {}", channel_id, counterparty_node_id, - ) + ), }); }, } @@ -2774,7 +2974,10 @@ where for htlc_source in failed_htlcs.drain(..) { let reason = HTLCFailReason::from_failure_code(0x4000 | 8); - 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); } @@ -2808,7 +3011,9 @@ where /// [`ChannelCloseMinimum`]: crate::chain::chaininterface::ConfirmationTarget::ChannelCloseMinimum /// [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee /// [`SendShutdown`]: crate::events::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) } @@ -2841,8 +3046,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`]: crate::events::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, + ) } fn finish_close_channel(&self, mut shutdown_res: ShutdownResult) { @@ -2853,15 +3066,22 @@ where } let logger = WithContext::from( - &self.logger, Some(shutdown_res.counterparty_node_id), Some(shutdown_res.channel_id), + &self.logger, + Some(shutdown_res.counterparty_node_id), + Some(shutdown_res.channel_id), ); - 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 reason = HTLCFailReason::from_failure_code(0x4000 | 8); - 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 { @@ -2882,10 +3102,14 @@ where let mut peer_state = peer_state_mutex.lock().unwrap(); if let Some(mut chan) = peer_state.channel_by_id.remove(&channel_id) { update_maps_on_chan_removal!(self, &chan.context()); - shutdown_results.push(chan.context_mut().force_shutdown(false, ClosureReason::FundingBatchClosure)); + shutdown_results.push( + chan.context_mut() + .force_shutdown(false, ClosureReason::FundingBatchClosure), + ); } } - 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), @@ -2895,19 +3119,26 @@ 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, - }, 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, + }, + None, + )); if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx { - pending_events.push_back((events::Event::DiscardFunding { - channel_id: shutdown_res.channel_id, transaction - }, None)); + pending_events.push_back(( + events::Event::DiscardFunding { + channel_id: shutdown_res.channel_id, + transaction, + }, + None, + )); } } for shutdown_result in shutdown_results.drain(..) { @@ -2917,31 +3148,49 @@ 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 }; let logger = WithContext::from(&self.logger, Some(*peer_node_id), Some(*channel_id)); - if let hash_map::Entry::Occupied(chan_phase_entry) = peer_state.channel_by_id.entry(channel_id.clone()) { + if let hash_map::Entry::Occupied(chan_phase_entry) = + peer_state.channel_by_id.entry(channel_id.clone()) + { log_error!(logger, "Force-closing channel {}", channel_id); let mut chan_phase = remove_channel_phase!(self, chan_phase_entry); mem::drop(peer_state); mem::drop(per_peer_state); match chan_phase { ChannelPhase::Funded(mut chan) => { - self.finish_close_channel(chan.context.force_shutdown(broadcast, closure_reason)); - (self.get_channel_update_for_broadcast(&chan).ok(), chan.context.get_counterparty_node_id()) + self.finish_close_channel( + chan.context.force_shutdown(broadcast, closure_reason), + ); + ( + self.get_channel_update_for_broadcast(&chan).ok(), + chan.context.get_counterparty_node_id(), + ) }, ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => { - self.finish_close_channel(chan_phase.context_mut().force_shutdown(false, closure_reason)); + self.finish_close_channel( + chan_phase.context_mut().force_shutdown(false, closure_reason), + ); // Unfunded channel has no update (None, chan_phase.context().get_counterparty_node_id()) }, @@ -2953,45 +3202,54 @@ 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 { // Try to send the `BroadcastChannelUpdate` to the peer we just force-closed on, but if // not try to broadcast it via whatever peer we have. let per_peer_state = self.per_peer_state.read().unwrap(); - let a_peer_state_opt = per_peer_state.get(peer_node_id) - .ok_or(per_peer_state.values().next()); + let a_peer_state_opt = + per_peer_state.get(peer_node_id).ok_or(per_peer_state.values().next()); if let Ok(a_peer_state_mutex) = a_peer_state_opt { let mut a_peer_state = a_peer_state_mutex.lock().unwrap(); - a_peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + a_peer_state + .pending_msg_events + .push(events::MessageSendEvent::BroadcastChannelUpdate { msg: update }); } } Ok(counterparty_node_id) } - fn force_close_sending_error(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool) -> Result<(), APIError> { + fn force_close_sending_error( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, broadcast: bool, + ) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - match self.force_close_channel_with_peer(channel_id, counterparty_node_id, None, broadcast) { + 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( - events::MessageSendEvent::HandleError { - node_id: counterparty_node_id, - action: msgs::ErrorAction::DisconnectPeer { - msg: Some(msgs::ErrorMessage { channel_id: *channel_id, data: "Channel force-closed".to_owned() }) - }, - } - ); + peer_state.pending_msg_events.push(events::MessageSendEvent::HandleError { + node_id: counterparty_node_id, + action: msgs::ErrorAction::DisconnectPeer { + msg: Some(msgs::ErrorMessage { + channel_id: *channel_id, + data: "Channel force-closed".to_owned(), + }), + }, + }); } Ok(()) }, - Err(e) => Err(e) + Err(e) => Err(e), } } @@ -2999,8 +3257,9 @@ where /// rejecting new HTLCs on the given channel. 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) - -> Result<(), APIError> { + pub fn force_close_broadcasting_latest_txn( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, + ) -> Result<(), APIError> { self.force_close_sending_error(channel_id, counterparty_node_id, true) } @@ -3010,8 +3269,9 @@ where /// /// You can always get the latest local transaction(s) to broadcast from /// [`ChannelMonitor::get_latest_holder_commitment_txn`]. - pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey) - -> Result<(), APIError> { + pub fn force_close_without_broadcasting_txn( + &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, + ) -> Result<(), APIError> { self.force_close_sending_error(channel_id, counterparty_node_id, false) } @@ -3019,7 +3279,8 @@ where /// for each to the chain and rejecting new HTLCs on each. pub fn force_close_all_channels_broadcasting_latest_txn(&self) { for chan in self.list_channels() { - let _ = self.force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id); + let _ = self + .force_close_broadcasting_latest_txn(&chan.channel_id, &chan.counterparty.node_id); } } @@ -3027,60 +3288,76 @@ where /// local transaction(s). pub fn force_close_all_channels_without_broadcasting_txn(&self) { for chan in self.list_channels() { - let _ = self.force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id); + let _ = self + .force_close_without_broadcasting_txn(&chan.channel_id, &chan.counterparty.node_id); } } fn decode_update_add_htlc_onion( &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, ) -> Result< - (onion_utils::Hop, [u8; 32], Option>), HTLCFailureMsg + (onion_utils::Hop, [u8; 32], Option>), + HTLCFailureMsg, > { - let (next_hop, shared_secret, next_packet_details_opt) = decode_incoming_update_add_htlc_onion( - msg, &self.node_signer, &self.logger, &self.secp_ctx - )?; + let (next_hop, shared_secret, next_packet_details_opt) = + decode_incoming_update_add_htlc_onion( + msg, + &self.node_signer, + &self.logger, + &self.secp_ctx, + )?; let is_intro_node_forward = match next_hop { onion_utils::Hop::Forward { - next_hop_data: msgs::InboundOnionPayload::BlindedForward { - intro_node_blinding_point: Some(_), .. - }, .. + next_hop_data: + msgs::InboundOnionPayload::BlindedForward { + intro_node_blinding_point: Some(_), .. + }, + .. } => true, _ => false, }; macro_rules! return_err { - ($msg: expr, $err_code: expr, $data: expr) => { - { - log_info!( - WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id)), - "Failed to accept/forward incoming HTLC: {}", $msg - ); - // If `msg.blinding_point` is set, we must always fail with malformed. - if msg.blinding_point.is_some() { - return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - sha256_of_onion: [0; 32], - failure_code: INVALID_ONION_BLINDING, - })); - } - - let (err_code, err_data) = if is_intro_node_forward { - (INVALID_ONION_BLINDING, &[0; 32][..]) - } else { ($err_code, $data) }; - return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { + ($msg: expr, $err_code: expr, $data: expr) => {{ + log_info!( + WithContext::from( + &self.logger, + Some(*counterparty_node_id), + Some(msg.channel_id) + ), + "Failed to accept/forward incoming HTLC: {}", + $msg + ); + // If `msg.blinding_point` is set, we must always fail with malformed. + if msg.blinding_point.is_some() { + return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { channel_id: msg.channel_id, htlc_id: msg.htlc_id, - reason: HTLCFailReason::reason(err_code, err_data.to_vec()) - .get_encrypted_failure_packet(&shared_secret, &None), + sha256_of_onion: [0; 32], + failure_code: INVALID_ONION_BLINDING, })); } - } + + let (err_code, err_data) = if is_intro_node_forward { + (INVALID_ONION_BLINDING, &[0; 32][..]) + } else { + ($err_code, $data) + }; + return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + reason: HTLCFailReason::reason(err_code, err_data.to_vec()) + .get_encrypted_failure_packet(&shared_secret, &None), + })); + }}; } let NextPacketDetails { - next_packet_pubkey, outgoing_amt_msat, outgoing_scid, outgoing_cltv_value + next_packet_pubkey, + outgoing_amt_msat, + outgoing_scid, + outgoing_cltv_value, } = match next_packet_details_opt { Some(next_packet_details) => next_packet_details, // it is a receive, so no need for outbound checks @@ -3092,49 +3369,91 @@ where if let Some((err, mut code, chan_update)) = loop { let id_option = self.short_to_chan_info.read().unwrap().get(&outgoing_scid).cloned(); let forwarding_chan_info_opt = match id_option { - None => { // unknown_next_peer + None => { + // unknown_next_peer // Note that this is likely a timing oracle for detecting whether an scid is a // phantom or an intercept. - 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) - { + 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, + ) { None } else { - break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None)); + break Some(( + "Don't have available channel for forwarding as requested.", + 0x4000 | 10, + None, + )); } }, Some((cp_id, id)) => Some((cp_id.clone(), id.clone())), }; - let chan_update_opt = if let Some((counterparty_node_id, forwarding_id)) = forwarding_chan_info_opt { + let chan_update_opt = if let Some((counterparty_node_id, forwarding_id)) = + forwarding_chan_info_opt + { 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() { - break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None)); + break Some(( + "Don't have available channel for forwarding as requested.", + 0x4000 | 10, + None, + )); } let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; - let chan = match peer_state.channel_by_id.get_mut(&forwarding_id).map( - |chan_phase| if let ChannelPhase::Funded(chan) = chan_phase { Some(chan) } else { None } - ).flatten() { + let chan = match peer_state + .channel_by_id + .get_mut(&forwarding_id) + .map(|chan_phase| { + if let ChannelPhase::Funded(chan) = chan_phase { + Some(chan) + } else { + None + } + }) + .flatten() + { None => { // Channel was removed. The short_to_chan_info and channel_by_id maps // have no consistency guarantees. - break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None)); + break Some(( + "Don't have available channel for forwarding as requested.", + 0x4000 | 10, + None, + )); }, - Some(chan) => chan + Some(chan) => chan, }; - 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. - break Some(("Refusing to forward to a private channel based on our config.", 0x4000 | 10, None)); - } - if chan.context.get_channel_type().supports_scid_privacy() && outgoing_scid != chan.context.outbound_scid_alias() { + break Some(( + "Refusing to forward to a private channel based on our config.", + 0x4000 | 10, + None, + )); + } + if chan.context.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. - break Some(("Refusing to forward over real channel SCID as our counterparty requested.", 0x4000 | 10, None)); + break Some(( + "Refusing to forward over real channel SCID as our counterparty requested.", + 0x4000 | 10, + None, + )); } let chan_update_opt = self.get_channel_update_for_onion(outgoing_scid, chan).ok(); @@ -3143,20 +3462,37 @@ where // around to doing the actual forward, but better to fail early if we can and // hopefully an attacker trying to path-trace payments cannot make this occur // on a small/per-node/per-channel scale. - if !chan.context.is_live() { // channel_disabled + if !chan.context.is_live() { + // channel_disabled // If the channel_update we're going to return is disabled (i.e. the // peer has been disabled for some time), return `channel_disabled`, // otherwise return `temporary_channel_failure`. - if chan_update_opt.as_ref().map(|u| u.contents.flags & 2 == 2).unwrap_or(false) { - break Some(("Forwarding channel has been disconnected for some time.", 0x1000 | 20, chan_update_opt)); + if chan_update_opt.as_ref().map(|u| u.contents.flags & 2 == 2).unwrap_or(false) + { + break Some(( + "Forwarding channel has been disconnected for some time.", + 0x1000 | 20, + chan_update_opt, + )); } else { - break Some(("Forwarding channel is not in a ready state.", 0x1000 | 7, chan_update_opt)); + break Some(( + "Forwarding channel is not in a ready state.", + 0x1000 | 7, + chan_update_opt, + )); } } - if outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { // amount_below_minimum - break Some(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, chan_update_opt)); + if outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { + // amount_below_minimum + break Some(( + "HTLC amount was below the htlc_minimum_msat", + 0x1000 | 11, + chan_update_opt, + )); } - if let Err((err, code)) = chan.htlc_satisfies_config(&msg, outgoing_amt_msat, outgoing_cltv_value) { + if let Err((err, code)) = + chan.htlc_satisfies_config(&msg, outgoing_amt_msat, outgoing_cltv_value) + { break Some((err, code, chan_update_opt)); } chan_update_opt @@ -3166,35 +3502,35 @@ where let cur_height = self.best_block.read().unwrap().height() + 1; - if let Err((err_msg, code)) = check_incoming_htlc_cltv( - cur_height, outgoing_cltv_value, msg.cltv_expiry - ) { + if let Err((err_msg, code)) = + check_incoming_htlc_cltv(cur_height, outgoing_cltv_value, msg.cltv_expiry) + { if code & 0x1000 != 0 && chan_update_opt.is_none() { // We really should set `incorrect_cltv_expiry` here but as we're not // forwarding over a real channel we can't generate a channel_update // for it. Instead we just return a generic temporary_node_failure. - break Some((err_msg, 0x2000 | 2, None)) + break Some((err_msg, 0x2000 | 2, None)); } let chan_update_opt = if code & 0x1000 != 0 { chan_update_opt } else { None }; break Some((err_msg, code, chan_update_opt)); } break None; - } - { - let mut res = VecWriter(Vec::with_capacity(chan_update.serialized_length() + 2 + 8 + 2)); + } { + let mut res = + VecWriter(Vec::with_capacity(chan_update.serialized_length() + 2 + 8 + 2)); if let Some(chan_update) = chan_update { if code == 0x1000 | 11 || code == 0x1000 | 12 { msg.amount_msat.write(&mut res).expect("Writes cannot fail"); - } - else if code == 0x1000 | 13 { + } else if code == 0x1000 | 13 { msg.cltv_expiry.write(&mut res).expect("Writes cannot fail"); - } - else if code == 0x1000 | 20 { + } else if code == 0x1000 | 20 { // TODO: underspecified, follow https://github.com/lightning/bolts/issues/791 0u16.write(&mut res).expect("Writes cannot fail"); } - (chan_update.serialized_length() as u16 + 2).write(&mut res).expect("Writes cannot fail"); + (chan_update.serialized_length() as u16 + 2) + .write(&mut res) + .expect("Writes cannot fail"); msgs::ChannelUpdate::TYPE.write(&mut res).expect("Writes cannot fail"); chan_update.write(&mut res).expect("Writes cannot fail"); } else if code & 0x1000 == 0x1000 { @@ -3210,42 +3546,52 @@ where } fn construct_pending_htlc_status<'a>( - &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, shared_secret: [u8; 32], - decoded_hop: onion_utils::Hop, allow_underpay: bool, + &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, + shared_secret: [u8; 32], decoded_hop: onion_utils::Hop, allow_underpay: bool, next_packet_pubkey_opt: Option>, ) -> PendingHTLCStatus { macro_rules! return_err { - ($msg: expr, $err_code: expr, $data: expr) => { - { - let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id)); - log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg); - if msg.blinding_point.is_some() { - return PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed( - msgs::UpdateFailMalformedHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - sha256_of_onion: [0; 32], - failure_code: INVALID_ONION_BLINDING, - } - )) - } - return PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - reason: HTLCFailReason::reason($err_code, $data.to_vec()) - .get_encrypted_failure_packet(&shared_secret, &None), - })); + ($msg: expr, $err_code: expr, $data: expr) => {{ + let logger = WithContext::from( + &self.logger, + Some(*counterparty_node_id), + Some(msg.channel_id), + ); + log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg); + if msg.blinding_point.is_some() { + return PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed( + msgs::UpdateFailMalformedHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + sha256_of_onion: [0; 32], + failure_code: INVALID_ONION_BLINDING, + }, + )); } - } + return PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + reason: HTLCFailReason::reason($err_code, $data.to_vec()) + .get_encrypted_failure_packet(&shared_secret, &None), + })); + }}; } match decoded_hop { onion_utils::Hop::Receive(next_hop_data) => { // OUR PAYMENT! let current_height: u32 = self.best_block.read().unwrap().height(); - match create_recv_pending_htlc_info(next_hop_data, shared_secret, msg.payment_hash, - msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat, - current_height, self.default_configuration.accept_mpp_keysend) - { + match create_recv_pending_htlc_info( + next_hop_data, + shared_secret, + msg.payment_hash, + msg.amount_msat, + msg.cltv_expiry, + None, + allow_underpay, + msg.skimmed_fee_msat, + current_height, + self.default_configuration.accept_mpp_keysend, + ) { Ok(info) => { // 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 @@ -3253,16 +3599,26 @@ where // delay) once they've send us a commitment_signed! PendingHTLCStatus::Forward(info) }, - Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data) + Err(InboundHTLCErr { err_code, err_data, msg }) => { + return_err!(msg, err_code, &err_data) + }, } }, onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => { - match create_fwd_pending_htlc_info(msg, next_hop_data, next_hop_hmac, - new_packet_bytes, shared_secret, next_packet_pubkey_opt) { + match create_fwd_pending_htlc_info( + msg, + next_hop_data, + next_hop_hmac, + new_packet_bytes, + shared_secret, + next_packet_pubkey_opt, + ) { Ok(info) => PendingHTLCStatus::Forward(info), - Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data) + Err(InboundHTLCErr { err_code, err_data, msg }) => { + return_err!(msg, err_code, &err_data) + }, } - } + }, } } @@ -3276,18 +3632,27 @@ where /// /// [`channel_update`]: msgs::ChannelUpdate /// [`internal_closing_signed`]: Self::internal_closing_signed - fn get_channel_update_for_broadcast(&self, chan: &Channel) -> Result { + fn get_channel_update_for_broadcast( + &self, chan: &Channel, + ) -> 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); - 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) } @@ -3302,28 +3667,47 @@ where /// /// [`channel_update`]: msgs::ChannelUpdate /// [`internal_closing_signed`]: Self::internal_closing_signed - fn get_channel_update_for_unicast(&self, chan: &Channel) -> Result { + fn get_channel_update_for_unicast( + &self, chan: &Channel, + ) -> Result { let logger = WithChannelContext::from(&self.logger, &chan.context); - 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, }; self.get_channel_update_for_onion(short_channel_id, chan) } - fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel) -> Result { + fn get_channel_update_for_onion( + &self, short_channel_id: u64, chan: &Channel, + ) -> Result { let logger = WithChannelContext::from(&self.logger, &chan.context); 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 enabled = chan.context.is_usable() && match chan.channel_update_status() { - ChannelUpdateStatus::Enabled => true, - ChannelUpdateStatus::DisabledStaged(_) => true, - ChannelUpdateStatus::Disabled => false, - ChannelUpdateStatus::EnabledStaged(_) => false, - }; + let were_node_one = self.our_network_pubkey.serialize()[..] + < chan.context.get_counterparty_node_id().serialize()[..]; + + let enabled = chan.context.is_usable() + && match chan.channel_update_status() { + ChannelUpdateStatus::Enabled => true, + ChannelUpdateStatus::DisabledStaged(_) => true, + ChannelUpdateStatus::Disabled => false, + ChannelUpdateStatus::EnabledStaged(_) => false, + }; let unsigned = msgs::UnsignedChannelUpdate { chain_hash: self.chain_hash, @@ -3341,27 +3725,43 @@ 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(test)] - 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, total_value, cur_height, payment_id, keysend_preimage, - session_priv_bytes + path, + payment_hash, + recipient_onion, + total_value, + cur_height, + payment_id, + keysend_preimage, + 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, - session_priv_bytes + path, + payment_hash, + recipient_onion, + total_value, + cur_height, + payment_id, + keysend_preimage, + 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()); @@ -3369,52 +3769,107 @@ 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, prng_seed - ).map_err(|e| { - let logger = WithContext::from(&self.logger, Some(path.hops.first().unwrap().pubkey), None); - 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, + prng_seed, + ) + .map_err(|e| { + let logger = + WithContext::from(&self.logger, Some(path.hops.first().unwrap().pubkey), None); + 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); - 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, + ); + 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)); - log_trace!(logger, + 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_phase_entry) = peer_state.channel_by_id.entry(id) { + if let hash_map::Entry::Occupied(mut chan_phase_entry) = + peer_state.channel_by_id.entry(id) + { match chan_phase_entry.get_mut() { ChannelPhase::Funded(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.context.get_funding_txo().unwrap(); let logger = WithChannelContext::from(&self.logger, &chan.context); - let send_res = chan.send_htlc_and_commit(htlc_msat, payment_hash.clone(), - htlc_cltv, HTLCSource::OutboundRoute { + 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_chan_phase_entry!(self, send_res, chan_phase_entry) { Some(monitor_update) => { - match handle_new_monitor_update!(self, funding_txo, channel_id, monitor_update, peer_state_lock, peer_state, per_peer_state, chan) { + match handle_new_monitor_update!( + self, + funding_txo, + channel_id, + 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 @@ -3430,22 +3885,26 @@ where None => {}, } }, - _ => return Err(APIError::ChannelUnavailable{err: "Channel to first hop is unfunded".to_owned()}), + _ => { + 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 }), } } @@ -3500,57 +3959,114 @@ where /// [`UpdateHTLCs`]: events::MessageSendEvent::UpdateHTLCs /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events /// [`ChannelMonitorUpdateStatus::InProgress`]: crate::chain::ChannelMonitorUpdateStatus::InProgress - pub fn send_payment_with_route(&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId) -> Result<(), PaymentSendFailure> { + pub fn send_payment_with_route( + &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + payment_id: PaymentId, + ) -> Result<(), PaymentSendFailure> { let best_block_height = self.best_block.read().unwrap().height(); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.pending_outbound_payments - .send_payment_with_route(route, payment_hash, recipient_onion, payment_id, - &self.entropy_source, &self.node_signer, best_block_height, - |args| self.send_payment_along_path(args)) + self.pending_outbound_payments.send_payment_with_route( + route, + payment_hash, + recipient_onion, + payment_id, + &self.entropy_source, + &self.node_signer, + best_block_height, + |args| self.send_payment_along_path(args), + ) } /// Similar to [`ChannelManager::send_payment_with_route`], but will automatically find a route based on /// `route_params` and retry failed payment paths based on `retry_strategy`. - pub fn send_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result<(), RetryableSendFailure> { + pub fn send_payment( + &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(test)] - 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(test)] - 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(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); } - pub(super) fn send_payment_for_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> { + pub(super) fn send_payment_for_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); - self.pending_outbound_payments - .send_payment_for_bolt12_invoice( - invoice, payment_id, &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_for_bolt12_invoice( + invoice, + payment_id, + &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), + ) } /// Signals that no further attempts for the given payment should occur. Useful if you have a @@ -3582,7 +4098,11 @@ where /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn abandon_payment(&self, payment_id: PaymentId) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - self.pending_outbound_payments.abandon_payment(payment_id, PaymentFailureReason::UserAbandoned, &self.pending_events); + self.pending_outbound_payments.abandon_payment( + payment_id, + PaymentFailureReason::UserAbandoned, + &self.pending_events, + ); } /// Send a spontaneous payment, which is a payment that does not require the recipient to have @@ -3598,12 +4118,22 @@ where /// [`send_payment`] for more information about the risks of duplicate preimage usage. /// /// [`send_payment`]: Self::send_payment - pub fn send_spontaneous_payment(&self, route: &Route, payment_preimage: Option, recipient_onion: RecipientOnionFields, payment_id: PaymentId) -> Result { + pub fn send_spontaneous_payment( + &self, route: &Route, payment_preimage: Option, + recipient_onion: RecipientOnionFields, payment_id: PaymentId, + ) -> 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_with_route( - route, payment_preimage, recipient_onion, payment_id, &self.entropy_source, - &self.node_signer, best_block_height, |args| self.send_payment_along_path(args)) + route, + payment_preimage, + recipient_onion, + payment_id, + &self.entropy_source, + &self.node_signer, + best_block_height, + |args| self.send_payment_along_path(args), + ) } /// Similar to [`ChannelManager::send_spontaneous_payment`], but will automatically find a route @@ -3613,13 +4143,28 @@ where /// payments. /// /// [`PaymentParameters::for_keysend`]: crate::routing::router::PaymentParameters::for_keysend - pub fn send_spontaneous_payment_with_retry(&self, payment_preimage: Option, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result { + pub fn send_spontaneous_payment_with_retry( + &self, payment_preimage: Option, recipient_onion: RecipientOnionFields, + 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 @@ -3628,15 +4173,22 @@ where pub fn send_probe(&self, path: Path) -> Result<(PaymentHash, PaymentId), PaymentSendFailure> { 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) } @@ -3648,10 +4200,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) } @@ -3752,13 +4304,22 @@ 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, &Transaction) -> 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, &Transaction) -> Result, + >( + &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, + funding_transaction: Transaction, is_batch_funding: bool, mut find_funding_output: FundingOutput, ) -> 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; @@ -3768,21 +4329,41 @@ where funding_txo = find_funding_output(&chan, &funding_transaction)?; let logger = WithChannelContext::from(&self.logger, &chan.context); - let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger) - .map_err(|(mut chan, e)| if let ChannelError::Close(msg) = e { - let channel_id = chan.context.channel_id(); - let reason = ClosureReason::ProcessingError { err: msg.clone() }; - let shutdown_res = chan.context.force_shutdown(false, reason); - (chan, MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None)) - } else { unreachable!(); }); + let funding_res = chan + .get_funding_created( + funding_transaction, + funding_txo, + is_batch_funding, + &&logger, + ) + .map_err(|(mut chan, e)| { + if let ChannelError::Close(msg) = e { + let channel_id = chan.context.channel_id(); + let reason = ClosureReason::ProcessingError { err: msg.clone() }; + let shutdown_res = chan.context.force_shutdown(false, reason); + ( + chan, + MsgHandleErrInternal::from_finish_shutdown( + msg, + channel_id, + shutdown_res, + None, + ), + ) + } else { + unreachable!(); + } + }); match funding_res { Ok(funding_msg) => (chan, funding_msg), Err((chan, err)) => { mem::drop(peer_state_lock); mem::drop(per_peer_state); - let _: Result<(), _> = handle_error!(self, Err(err), chan.context.get_counterparty_node_id()); + let _: Result<(), _> = + handle_error!(self, Err(err), chan.context.get_counterparty_node_id()); return Err(APIError::ChannelUnavailable { - err: "Signer refused to sign the initial commitment transaction".to_owned() + err: "Signer refused to sign the initial commitment transaction" + .to_owned(), }); }, } @@ -3793,12 +4374,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), - }), }; if let Some(msg) = msg_opt { @@ -3814,11 +4399,14 @@ where hash_map::Entry::Vacant(e) => { let mut outpoint_to_peer = self.outpoint_to_peer.lock().unwrap(); match outpoint_to_peer.entry(funding_txo) { - hash_map::Entry::Vacant(e) => { e.insert(chan.context.get_counterparty_node_id()); }, + hash_map::Entry::Vacant(e) => { + e.insert(chan.context.get_counterparty_node_id()); + }, hash_map::Entry::Occupied(o) => { let err = format!( "An existing channel using outpoint {} is open with peer {}", - funding_txo, o.get() + funding_txo, + o.get() ); mem::drop(outpoint_to_peer); mem::drop(peer_state_lock); @@ -3826,19 +4414,26 @@ where let reason = ClosureReason::ProcessingError { err: err.clone() }; self.finish_close_channel(chan.context.force_shutdown(true, reason)); return Err(APIError::ChannelUnavailable { err }); - } + }, } e.insert(ChannelPhase::UnfundedOutboundV1(chan)); - } + }, } Ok(()) } #[cfg(test)] - pub(crate) fn funding_transaction_generated_unchecked(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, funding_transaction: Transaction, output_index: u16) -> Result<(), APIError> { - self.funding_transaction_generated_intern(temporary_channel_id, counterparty_node_id, funding_transaction, false, |_, tx| { - Ok(OutPoint { txid: tx.txid(), index: output_index }) - }) + pub(crate) fn funding_transaction_generated_unchecked( + &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, + funding_transaction: Transaction, output_index: u16, + ) -> Result<(), APIError> { + self.funding_transaction_generated_intern( + temporary_channel_id, + counterparty_node_id, + funding_transaction, + false, + |_, tx| Ok(OutPoint { txid: tx.txid(), index: output_index }), + ) } /// Call this upon creation of a funding transaction for the given channel. @@ -3871,8 +4466,14 @@ 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, + ) } /// Call this upon creation of a batch funding transaction for the given channels. @@ -3885,7 +4486,9 @@ 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); let mut result = Ok(()); @@ -3893,14 +4496,15 @@ where 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(), })); } } } 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(), })); } { @@ -3909,92 +4513,103 @@ 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_transaction.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())), }); 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.clone(), - is_batch_funding, - |chan, tx| { - let mut output_index = None; - let expected_spk = chan.context.get_funding_redeemscript().to_v0_p2wsh(); - for (idx, outp) in tx.output.iter().enumerate() { - if outp.script_pubkey == expected_spk && outp.value == chan.context.get_value_satoshis() { - if output_index.is_some() { - return Err(APIError::APIMisuseError { - err: "Multiple outputs matched the expected script and value".to_owned() - }); + result = result.and_then(|_| { + self.funding_transaction_generated_intern( + temporary_channel_id, + counterparty_node_id, + funding_transaction.clone(), + is_batch_funding, + |chan, tx| { + let mut output_index = None; + let expected_spk = chan.context.get_funding_redeemscript().to_v0_p2wsh(); + for (idx, outp) in tx.output.iter().enumerate() { + if outp.script_pubkey == expected_spk + && outp.value == chan.context.get_value_satoshis() + { + if output_index.is_some() { + return Err(APIError::APIMisuseError { + err: + "Multiple outputs matched the expected script and value" + .to_owned(), + }); + } + output_index = Some(idx as u16); } - output_index = Some(idx as u16); } - } - if output_index.is_none() { - return Err(APIError::APIMisuseError { + if output_index.is_none() { + return Err(APIError::APIMisuseError { err: "No output matched the script_pubkey and value in the FundingGenerationReady event".to_owned() }); - } - let outpoint = OutPoint { txid: tx.txid(), index: output_index.unwrap() }; - 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) - }) - ); + } + let outpoint = OutPoint { txid: tx.txid(), index: output_index.unwrap() }; + 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) + }, + ) + }); } 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(|mut chan| { update_maps_on_chan_removal!(self, &chan.context()); let closure_reason = ClosureReason::ProcessingError { err: e.clone() }; - shutdown_results.push(chan.context_mut().force_shutdown(false, closure_reason)); + shutdown_results + .push(chan.context_mut().force_shutdown(false, closure_reason)); }); } } @@ -4029,24 +4644,41 @@ 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 + ), }); }; } @@ -4059,12 +4691,16 @@ where } if let ChannelPhase::Funded(channel) = channel_phase { if let Ok(msg) = self.get_channel_update_for_broadcast(channel) { - peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { msg }); + peer_state + .pending_msg_events + .push(events::MessageSendEvent::BroadcastChannelUpdate { msg }); } else if let Ok(msg) = self.get_channel_update_for_unicast(channel) { - peer_state.pending_msg_events.push(events::MessageSendEvent::SendChannelUpdate { - node_id: channel.context.get_counterparty_node_id(), - msg, - }); + peer_state.pending_msg_events.push( + events::MessageSendEvent::SendChannelUpdate { + node_id: channel.context.get_counterparty_node_id(), + msg, + }, + ); } } continue; @@ -4106,7 +4742,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 @@ -4134,13 +4774,21 @@ 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) { @@ -4168,24 +4816,32 @@ where } }; - 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, .. } => { PendingHTLCRouting::Forward { - onion_packet, blinded, short_channel_id: next_hop_scid + onion_packet, + blinded, + 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 = [( @@ -4193,7 +4849,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(()) @@ -4209,9 +4865,13 @@ 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, .. } = payment.forward_info.routing { @@ -4227,9 +4887,17 @@ where }); let failure_reason = HTLCFailReason::from_failure_code(0x4000 | 10); - let destination = HTLCDestination::UnknownNextHop { requested_forward_scid: short_channel_id }; - self.fail_htlc_backwards_internal(&htlc_source, &payment.forward_info.payment_hash, &failure_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, + &failure_reason, + destination, + ); + } else { + unreachable!() + } // Only `PendingHTLCRouting::Forward`s are intercepted Ok(()) } @@ -4243,7 +4911,13 @@ where let mut new_events = VecDeque::new(); let mut failed_forwards = Vec::new(); - let mut phantom_receives: Vec<(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)> = Vec::new(); + let mut phantom_receives: Vec<( + u64, + OutPoint, + ChannelId, + u128, + Vec<(PendingHTLCInfo, u64)>, + )> = Vec::new(); { let mut forward_htlcs = HashMap::new(); mem::swap(&mut forward_htlcs, &mut self.forward_htlcs.lock().unwrap()); @@ -4357,13 +5031,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!(); continue; - } + }, }; forwarding_counterparty = Some(counterparty_node_id); let per_peer_state = self.per_peer_state.read().unwrap(); @@ -4374,53 +5049,97 @@ where } let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; - if let Some(ChannelPhase::Funded(ref mut chan)) = peer_state.channel_by_id.get_mut(&forward_chan_id) { + if let Some(ChannelPhase::Funded(ref mut chan)) = + peer_state.channel_by_id.get_mut(&forward_chan_id) + { let logger = WithChannelContext::from(&self.logger, &chan.context); for forward_info in pending_forwards.drain(..) { 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, forward_info: PendingHTLCInfo { - incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value, - routing: PendingHTLCRouting::Forward { - onion_packet, blinded, .. - }, skimmed_fee_msat, .. - }, + prev_short_channel_id, + prev_htlc_id, + prev_channel_id, + prev_funding_outpoint, + prev_user_channel_id, + forward_info: + PendingHTLCInfo { + incoming_shared_secret, + payment_hash, + outgoing_amt_msat, + outgoing_cltv_value, + routing: + PendingHTLCRouting::Forward { + onion_packet, + blinded, + .. + }, + skimmed_fee_msat, + .. + }, }) => { log_trace!(logger, "Adding HTLC from short id {} with payment_hash {} to channel with short id {} after delay", prev_short_channel_id, &payment_hash, short_chan_id); - let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { - short_channel_id: prev_short_channel_id, - user_channel_id: Some(prev_user_channel_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), - }); + let htlc_source = + HTLCSource::PreviousHopData(HTLCPreviousHopData { + short_channel_id: prev_short_channel_id, + user_channel_id: Some(prev_user_channel_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), + }); let next_blinding_point = blinded.and_then(|b| { - 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() }); - if let Err(e) = chan.queue_add_htlc(outgoing_amt_msat, - payment_hash, outgoing_cltv_value, htlc_source.clone(), - onion_packet, skimmed_fee_msat, next_blinding_point, &self.fee_estimator, - &&logger) - { + if let Err(e) = chan.queue_add_htlc( + outgoing_amt_msat, + payment_hash, + outgoing_cltv_value, + htlc_source.clone(), + onion_packet, + skimmed_fee_msat, + next_blinding_point, + &self.fee_estimator, + &&logger, + ) { if let ChannelError::Ignore(msg) = e { - log_trace!(logger, "Failed to forward HTLC with payment_hash {}: {}", &payment_hash, msg); + log_trace!( + logger, + "Failed to forward HTLC with payment_hash {}: {}", + &payment_hash, + msg + ); } else { panic!("Stated return value requirements in send_htlc() were not met"); } - let (failure_code, data) = self.get_htlc_temp_fail_err_and_data(0x1000|7, short_chan_id, chan); - failed_forwards.push((htlc_source, payment_hash, + let (failure_code, data) = self + .get_htlc_temp_fail_err_and_data( + 0x1000 | 7, + short_chan_id, + chan, + ); + failed_forwards.push(( + htlc_source, + payment_hash, HTLCFailReason::reason(failure_code, 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, + }, )); continue; } @@ -4431,12 +5150,22 @@ where }, HTLCForwardInfo::FailHTLC { htlc_id, err_packet } => { 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, &&logger), htlc_id)) + Some(( + chan.queue_fail_htlc(htlc_id, err_packet, &&logger), + htlc_id, + )) }, - HTLCForwardInfo::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => { + HTLCForwardInfo::FailMalformedHTLC { + htlc_id, + failure_code, + sha256_of_onion, + } => { 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)) }, @@ -4463,36 +5192,77 @@ 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, 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, + 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, phantom_shared_secret, mut onion_fields) = match routing { + let ( + cltv_expiry, + onion_payload, + payment_data, + phantom_shared_secret, + mut onion_fields, + ) = match routing { PendingHTLCRouting::Receive { - payment_data, payment_metadata, incoming_cltv_expiry, phantom_shared_secret, - custom_tlvs, requires_blinded_error: _ + payment_data, + payment_metadata, + 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), phantom_shared_secret, onion_fields) + 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), + phantom_shared_secret, + onion_fields, + ) }, - PendingHTLCRouting::ReceiveKeysend { payment_data, payment_preimage, payment_metadata, incoming_cltv_expiry, custom_tlvs } => { + PendingHTLCRouting::ReceiveKeysend { + payment_data, + payment_preimage, + payment_metadata, + incoming_cltv_expiry, + custom_tlvs, + } => { 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, None, onion_fields) + ( + incoming_cltv_expiry, + OnionPayload::Spontaneous(payment_preimage), + payment_data, + None, + onion_fields, + ) }, _ => { panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive"); - } + }, }; let claimable_htlc = ClaimableHTLC { prev_hop: HTLCPreviousHopData { @@ -4512,7 +5282,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, @@ -4523,30 +5297,43 @@ where macro_rules! fail_htlc { ($htlc: expr, $payment_hash: expr) => { debug_assert!(!committed_to_claimable); - let mut htlc_msat_height_data = $htlc.value.to_be_bytes().to_vec(); + 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(), ); - failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData { + failed_forwards.push(( + HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id: $htlc.prev_hop.short_channel_id, user_channel_id: $htlc.prev_hop.user_channel_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, - }), payment_hash, - HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data), - HTLCDestination::FailedPayment { payment_hash: $payment_hash }, + }), + payment_hash, + HTLCFailReason::reason( + 0x4000 | 15, + htlc_msat_height_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"); } @@ -4649,58 +5436,91 @@ where // that we are the ultimate recipient of the given payment hash. // Further, we must not expose whether we have any other HTLCs // associated with the same payment_hash pending or not. - let mut payment_secrets = self.pending_inbound_payments.lock().unwrap(); + let mut payment_secrets = + self.pending_inbound_payments.lock().unwrap(); match payment_secrets.entry(payment_hash) { hash_map::Entry::Vacant(_) => { match claimable_htlc.onion_payload { OnionPayload::Invoice { .. } => { let payment_data = payment_data.unwrap(); - 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 { + 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); fail_htlc!(claimable_htlc, payment_hash); } } - let purpose = events::PaymentPurpose::InvoicePayment { - payment_preimage: payment_preimage.clone(), - payment_secret: payment_data.payment_secret, - }; + let purpose = + events::PaymentPurpose::InvoicePayment { + payment_preimage: payment_preimage.clone(), + payment_secret: payment_data.payment_secret, + }; check_total_value!(purpose); }, OnionPayload::Spontaneous(preimage) => { - let purpose = events::PaymentPurpose::SpontaneousPayment(preimage); + let purpose = + events::PaymentPurpose::SpontaneousPayment( + preimage, + ); check_total_value!(purpose); - } + }, } }, hash_map::Entry::Occupied(inbound_payment) => { - if let OnionPayload::Spontaneous(_) = claimable_htlc.onion_payload { + if let OnionPayload::Spontaneous(_) = + claimable_htlc.onion_payload + { log_trace!(self.logger, "Failing new keysend HTLC with payment_hash {} because we already have an inbound payment with the same payment hash", &payment_hash); fail_htlc!(claimable_htlc, payment_hash); } let payment_data = payment_data.unwrap(); - if inbound_payment.get().payment_secret != payment_data.payment_secret { + if inbound_payment.get().payment_secret + != payment_data.payment_secret + { log_trace!(self.logger, "Failing new HTLC with payment_hash {} as it didn't match our expected payment secret.", &payment_hash); fail_htlc!(claimable_htlc, payment_hash); - } else if inbound_payment.get().min_value_msat.is_some() && payment_data.total_msat < inbound_payment.get().min_value_msat.unwrap() { + } else if inbound_payment.get().min_value_msat.is_some() + && payment_data.total_msat + < inbound_payment.get().min_value_msat.unwrap() + { log_trace!(self.logger, "Failing new HTLC with payment_hash {} as it didn't match our minimum value (had {}, needed {}).", &payment_hash, payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap()); fail_htlc!(claimable_htlc, payment_hash); } else { let purpose = events::PaymentPurpose::InvoicePayment { - payment_preimage: inbound_payment.get().payment_preimage, + payment_preimage: inbound_payment + .get() + .payment_preimage, payment_secret: payment_data.payment_secret, }; - let payment_claimable_generated = check_total_value!(purpose); + let payment_claimable_generated = + check_total_value!(purpose); if payment_claimable_generated { inbound_payment.remove_entry(); } @@ -4708,9 +5528,10 @@ where }, }; }, - HTLCForwardInfo::FailHTLC { .. } | HTLCForwardInfo::FailMalformedHTLC { .. } => { + HTLCForwardInfo::FailHTLC { .. } + | HTLCForwardInfo::FailMalformedHTLC { .. } => { panic!("Got pending fail of our own HTLC"); - } + }, } } } @@ -4718,12 +5539,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); @@ -4733,7 +5567,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); } @@ -4742,7 +5578,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); @@ -4754,12 +5593,21 @@ where for event in background_events.drain(..) { match event { - BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup((funding_txo, _channel_id, update)) => { + BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup(( + funding_txo, + _channel_id, + update, + )) => { // The channel has already been closed, so no use bothering to care about the // monitor updating completing. let _ = self.chain_monitor.update_channel(funding_txo, &update); }, - BackgroundEvent::MonitorUpdateRegeneratedOnStartup { counterparty_node_id, funding_txo, channel_id, update } => { + BackgroundEvent::MonitorUpdateRegeneratedOnStartup { + counterparty_node_id, + funding_txo, + channel_id, + update, + } => { let mut updated_chan = false; { let per_peer_state = self.per_peer_state.read().unwrap(); @@ -4770,10 +5618,21 @@ where hash_map::Entry::Occupied(mut chan_phase) => { if let ChannelPhase::Funded(chan) = chan_phase.get_mut() { updated_chan = true; - handle_new_monitor_update!(self, funding_txo, channel_id, update.clone(), - peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo, + channel_id, + update.clone(), + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } else { - debug_assert!(false, "We shouldn't have an update for a non-funded channel"); + debug_assert!( + false, + "We shouldn't have an update for a non-funded channel" + ); } }, hash_map::Entry::Vacant(_) => {}, @@ -4790,11 +5649,21 @@ where 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(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get_mut(&channel_id) { - handle_monitor_update_completion!(self, peer_state_lock, peer_state, per_peer_state, chan); + if let Some(ChannelPhase::Funded(chan)) = + peer_state.channel_by_id.get_mut(&channel_id) + { + 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); @@ -4813,16 +5682,27 @@ where let _ = self.process_background_events(); } - fn update_channel_fee(&self, chan_id: &ChannelId, chan: &mut Channel, new_feerate: u32) -> NotifyOption { - if !chan.context.is_outbound() { return NotifyOption::SkipPersistNoEvents; } + fn update_channel_fee( + &self, chan_id: &ChannelId, chan: &mut Channel, new_feerate: u32, + ) -> NotifyOption { + if !chan.context.is_outbound() { + return NotifyOption::SkipPersistNoEvents; + } let logger = WithChannelContext::from(&self.logger, &chan.context); // 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() + { if new_feerate != chan.context.get_feerate_sat_per_1000_weight() { - log_trace!(logger, "Channel {} does not qualify for a feerate change from {} to {}.", - chan_id, chan.context.get_feerate_sat_per_1000_weight(), new_feerate); + log_trace!( + logger, + "Channel {} does not qualify for a feerate change from {} to {}.", + chan_id, + chan.context.get_feerate_sat_per_1000_weight(), + new_feerate + ); } return NotifyOption::SkipPersistNoEvents; } @@ -4831,8 +5711,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 @@ -4847,23 +5732,35 @@ 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().filter_map( - |(chan_id, phase)| if let ChannelPhase::Funded(chan) = phase { Some((chan_id, chan)) } else { None } - ) { - let new_feerate = if chan.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { - anchor_feerate - } else { - non_anchor_feerate - }; + for (chan_id, chan) in + peer_state.channel_by_id.iter_mut().filter_map(|(chan_id, phase)| { + if let ChannelPhase::Funded(chan) = phase { + Some((chan_id, chan)) + } else { + None + } + }) { + let new_feerate = + if chan.context.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; + } } } @@ -4896,29 +5793,33 @@ 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(); let mut pending_peers_awaiting_removal = Vec::new(); let mut shutdown_channels = Vec::new(); - let mut process_unfunded_channel_tick = | - chan_id: &ChannelId, - context: &mut ChannelContext, - unfunded_context: &mut UnfundedChannelContext, - pending_msg_events: &mut Vec, - counterparty_node_id: PublicKey, - | { - context.maybe_expire_prev_config(); - if unfunded_context.should_expire_unfunded_channel() { - let logger = WithChannelContext::from(&self.logger, context); - log_error!(logger, + let mut process_unfunded_channel_tick = + |chan_id: &ChannelId, + context: &mut ChannelContext, + unfunded_context: &mut UnfundedChannelContext, + pending_msg_events: &mut Vec, + counterparty_node_id: PublicKey| { + context.maybe_expire_prev_config(); + if unfunded_context.should_expire_unfunded_channel() { + let logger = WithChannelContext::from(&self.logger, context); + log_error!(logger, "Force-closing pending channel with ID {} for not establishing in a timely manner", chan_id); - update_maps_on_chan_removal!(self, &context); - shutdown_channels.push(context.force_shutdown(false, ClosureReason::HolderForceClosed)); - pending_msg_events.push(MessageSendEvent::HandleError { + update_maps_on_chan_removal!(self, &context); + shutdown_channels + .push(context.force_shutdown(false, ClosureReason::HolderForceClosed)); + pending_msg_events.push(MessageSendEvent::HandleError { node_id: counterparty_node_id, action: msgs::ErrorAction::SendErrorMessage { msg: msgs::ErrorMessage { @@ -4927,11 +5828,11 @@ where }, }, }); - false - } else { - true - } - }; + false + } else { + true + } + }; { let per_peer_state = self.per_peer_state.read().unwrap(); @@ -4940,106 +5841,166 @@ 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, phase| { - match phase { - ChannelPhase::Funded(chan) => { - let new_feerate = if chan.context.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; } + peer_state.channel_by_id.retain(|chan_id, phase| match phase { + ChannelPhase::Funded(chan) => { + let new_feerate = if chan + .context + .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 let Err(e) = chan.timer_check_closing_negotiation_progress() { - let (needs_close, err) = convert_chan_phase_err!(self, e, chan, chan_id, FUNDED_CHANNEL); - handle_errors.push((Err(err), counterparty_node_id)); - if needs_close { return false; } + if let Err(e) = chan.timer_check_closing_negotiation_progress() { + let (needs_close, err) = + convert_chan_phase_err!(self, e, chan, chan_id, FUNDED_CHANNEL); + handle_errors.push((Err(err), counterparty_node_id)); + if needs_close { + return false; } + } - match chan.channel_update_status() { - ChannelUpdateStatus::Enabled if !chan.context.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::DisabledStaged(0)), - ChannelUpdateStatus::Disabled if chan.context.is_live() => chan.set_channel_update_status(ChannelUpdateStatus::EnabledStaged(0)), - ChannelUpdateStatus::DisabledStaged(_) if chan.context.is_live() - => chan.set_channel_update_status(ChannelUpdateStatus::Enabled), - ChannelUpdateStatus::EnabledStaged(_) if !chan.context.is_live() - => chan.set_channel_update_status(ChannelUpdateStatus::Disabled), - ChannelUpdateStatus::DisabledStaged(mut n) if !chan.context.is_live() => { - n += 1; - if n >= DISABLE_GOSSIP_TICKS { - chan.set_channel_update_status(ChannelUpdateStatus::Disabled); - if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { - pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); - } - should_persist = NotifyOption::DoPersist; - } else { - chan.set_channel_update_status(ChannelUpdateStatus::DisabledStaged(n)); + match chan.channel_update_status() { + ChannelUpdateStatus::Enabled if !chan.context.is_live() => chan + .set_channel_update_status( + ChannelUpdateStatus::DisabledStaged(0), + ), + ChannelUpdateStatus::Disabled if chan.context.is_live() => chan + .set_channel_update_status(ChannelUpdateStatus::EnabledStaged( + 0, + )), + ChannelUpdateStatus::DisabledStaged(_) + if chan.context.is_live() => + { + chan.set_channel_update_status(ChannelUpdateStatus::Enabled) + }, + ChannelUpdateStatus::EnabledStaged(_) + if !chan.context.is_live() => + { + chan.set_channel_update_status(ChannelUpdateStatus::Disabled) + }, + ChannelUpdateStatus::DisabledStaged(mut n) + if !chan.context.is_live() => + { + n += 1; + if n >= DISABLE_GOSSIP_TICKS { + chan.set_channel_update_status( + ChannelUpdateStatus::Disabled, + ); + if let Ok(update) = + self.get_channel_update_for_broadcast(&chan) + { + pending_msg_events.push( + events::MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } - }, - ChannelUpdateStatus::EnabledStaged(mut n) if chan.context.is_live() => { - n += 1; - if n >= ENABLE_GOSSIP_TICKS { - chan.set_channel_update_status(ChannelUpdateStatus::Enabled); - if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { - pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); - } - should_persist = NotifyOption::DoPersist; - } else { - chan.set_channel_update_status(ChannelUpdateStatus::EnabledStaged(n)); + should_persist = NotifyOption::DoPersist; + } else { + chan.set_channel_update_status( + ChannelUpdateStatus::DisabledStaged(n), + ); + } + }, + ChannelUpdateStatus::EnabledStaged(mut n) + if chan.context.is_live() => + { + n += 1; + if n >= ENABLE_GOSSIP_TICKS { + chan.set_channel_update_status( + ChannelUpdateStatus::Enabled, + ); + if let Ok(update) = + self.get_channel_update_for_broadcast(&chan) + { + pending_msg_events.push( + events::MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } - }, - _ => {}, - } + should_persist = NotifyOption::DoPersist; + } else { + chan.set_channel_update_status( + ChannelUpdateStatus::EnabledStaged(n), + ); + } + }, + _ => {}, + } - chan.context.maybe_expire_prev_config(); + chan.context.maybe_expire_prev_config(); - if chan.should_disconnect_peer_awaiting_response() { - let logger = WithChannelContext::from(&self.logger, &chan.context); - log_debug!(logger, "Disconnecting peer {} due to not making any progress on channel {}", + if chan.should_disconnect_peer_awaiting_response() { + let logger = WithChannelContext::from(&self.logger, &chan.context); + 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 - }, - ChannelPhase::UnfundedInboundV1(chan) => { - process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, - pending_msg_events, counterparty_node_id) - }, - ChannelPhase::UnfundedOutboundV1(chan) => { - process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, - pending_msg_events, counterparty_node_id) - }, - } + true + }, + ChannelPhase::UnfundedInboundV1(chan) => process_unfunded_channel_tick( + chan_id, + &mut chan.context, + &mut chan.unfunded_context, + pending_msg_events, + counterparty_node_id, + ), + ChannelPhase::UnfundedOutboundV1(chan) => process_unfunded_channel_tick( + chan_id, + &mut chan.context, + &mut chan.unfunded_context, + pending_msg_events, + counterparty_node_id, + ), }); 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)); + if { + req.ticks_remaining -= 1; + req.ticks_remaining + } <= 0 + { + let logger = WithContext::from( + &self.logger, + Some(counterparty_node_id), + Some(*chan_id), + ); log_error!(logger, "Force-closing unaccepted inbound channel {} for not accepting in a timely manner", &chan_id); peer_state.pending_msg_events.push( events::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() } + 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); @@ -5069,37 +6030,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()); @@ -5122,12 +6093,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 @@ -5154,17 +6124,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); @@ -5176,13 +6152,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) => { @@ -5191,7 +6174,7 @@ where None => Vec::new(), }; HTLCFailReason::reason(failure_code.into(), fail_data) - } + }, } } @@ -5200,7 +6183,9 @@ where /// /// This is for failures on the channel on which the HTLC was *received*, not failures /// forwarding - fn get_htlc_inbound_temp_fail_err_and_data(&self, desired_err_code: u16, chan: &Channel) -> (u16, Vec) { + fn get_htlc_inbound_temp_fail_err_and_data( + &self, desired_err_code: u16, chan: &Channel, + ) -> (u16, Vec) { // We can't be sure what SCID was used when relaying inbound towards us, so we have to // guess somewhat. If its a public channel, we figure best to just use the real SCID (as // we're not leaking that we have a channel with the counterparty), otherwise we try to use @@ -5213,14 +6198,15 @@ where if let Some(scid) = scid_pref { self.get_htlc_temp_fail_err_and_data(desired_err_code, scid, chan) } else { - (0x4000|10, Vec::new()) + (0x4000 | 10, Vec::new()) } } - /// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code /// that we want to return and a channel. - fn get_htlc_temp_fail_err_and_data(&self, desired_err_code: u16, scid: u64, chan: &Channel) -> (u16, Vec) { + fn get_htlc_temp_fail_err_and_data( + &self, desired_err_code: u16, scid: u64, chan: &Channel, + ) -> (u16, Vec) { debug_assert_eq!(desired_err_code & 0x1000, 0x1000); if let Ok(upd) = self.get_channel_update_for_onion(scid, chan) { let mut enc = VecWriter(Vec::with_capacity(upd.serialized_length() + 6)); @@ -5238,7 +6224,7 @@ where // which means we really shouldn't have gotten a payment to be forwarded over this // channel yet, or if we did it's from a route hint. Either way, returning an error of // PERM|no_such_channel should be fine. - (0x4000|10, Vec::new()) + (0x4000 | 10, Vec::new()) } } @@ -5247,7 +6233,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_code, onion_failure_data) = { let per_peer_state = self.per_peer_state.read().unwrap(); @@ -5257,28 +6243,36 @@ where match peer_state.channel_by_id.entry(channel_id) { hash_map::Entry::Occupied(chan_phase_entry) => { if let ChannelPhase::Funded(chan) = chan_phase_entry.get() { - self.get_htlc_inbound_temp_fail_err_and_data(0x1000|7, &chan) + self.get_htlc_inbound_temp_fail_err_and_data(0x1000 | 7, &chan) } else { // We shouldn't be trying to fail holding cell HTLCs on an unfunded channel. debug_assert!(false); - (0x4000|10, Vec::new()) + (0x4000 | 10, Vec::new()) } }, - hash_map::Entry::Vacant(_) => (0x4000|10, Vec::new()) + hash_map::Entry::Vacant(_) => (0x4000 | 10, Vec::new()), } - } else { (0x4000|10, Vec::new()) } + } else { + (0x4000 | 10, Vec::new()) + } }; for (htlc_src, payment_hash) in htlcs_to_fail.drain(..) { let reason = HTLCFailReason::reason(failure_code, 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); } } /// 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(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) { + fn fail_htlc_backwards_internal( + &self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, + destination: HTLCDestination, + ) { // 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 @@ -5298,41 +6292,60 @@ where // being fully configured. See the docs for `ChannelManagerReadArgs` for more. match source { HTLCSource::OutboundRoute { ref path, ref session_priv, ref payment_id, .. } => { - if 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) - { self.push_pending_forwards_ev(); } + if 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, + ) { + self.push_pending_forwards_ev(); + } }, 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)), "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(INVALID_ONION_BLINDING, vec![0; 32]); + let blinded_onion_error = + HTLCFailReason::reason(INVALID_ONION_BLINDING, 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: INVALID_ONION_BLINDING, - sha256_of_onion: [0; 32] - } + Some(BlindedFailure::FromBlindedNode) => HTLCForwardInfo::FailMalformedHTLC { + htlc_id: *htlc_id, + failure_code: INVALID_ONION_BLINDING, + 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 } - } + }, }; let mut push_forward_ev = false; @@ -5345,16 +6358,21 @@ where entry.get_mut().push(failure); }, hash_map::Entry::Vacant(entry) => { - entry.insert(vec!(failure)); - } + entry.insert(vec![failure]); + }, } mem::drop(forward_htlcs); - if push_forward_ev { self.push_pending_forwards_ev(); } + if push_forward_ev { + self.push_pending_forwards_ev(); + } 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, + )); }, } } @@ -5411,7 +6429,9 @@ where let mut receiver_node_id = self.our_network_pubkey; for htlc in payment.htlcs.iter() { if htlc.prev_hop.phantom_shared_secret.is_some() { - let phantom_pubkey = self.node_signer.get_node_id(Recipient::PhantomNode) + let phantom_pubkey = self + .node_signer + .get_node_id(Recipient::PhantomNode) .expect("Failed to get node_id for phantom node recipient"); receiver_node_id = phantom_pubkey; break; @@ -5420,10 +6440,16 @@ where let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(); let sender_intended_value = payment.htlcs.first().map(|htlc| htlc.total_msat); - let dup_purpose = claimable_payments.pending_claiming_payments.insert(payment_hash, - ClaimingPayment { amount_msat: payment.htlcs.iter().map(|source| source.value).sum(), - payment_purpose: payment.purpose, receiver_node_id, htlcs, sender_intended_value - }); + let dup_purpose = claimable_payments.pending_claiming_payments.insert( + payment_hash, + ClaimingPayment { + amount_msat: payment.htlcs.iter().map(|source| source.value).sum(), + payment_purpose: payment.purpose, + receiver_node_id, + htlcs, + sender_intended_value, + }, + ); if dup_purpose.is_some() { debug_assert!(false, "Shouldn't get a duplicate pending claim event ever"); log_error!(self.logger, "Got a duplicate pending claimable event on payment hash {}! Please report this bug", @@ -5437,17 +6463,27 @@ where claimable_payments.pending_claiming_payments.remove(&payment_hash); mem::drop(claimable_payments); for htlc in payment.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; } } payment.htlcs - } else { return; } + } else { + return; + } }; debug_assert!(!sources.is_empty()); @@ -5482,7 +6518,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() { @@ -5495,25 +6534,36 @@ where for htlc in sources.drain(..) { let prev_hop_chan_id = htlc.prev_hop.channel_id; if let Err((pk, err)) = self.claim_funds_from_hop( - htlc.prev_hop, payment_preimage, + htlc.prev_hop, + payment_preimage, |_, definitely_duplicate| { - debug_assert!(!definitely_duplicate, "We shouldn't claim duplicatively from a payment"); + debug_assert!( + !definitely_duplicate, + "We shouldn't claim duplicatively from a payment" + ); Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash }) - } + }, ) { if let msgs::ErrorAction::IgnoreError = err.err.action { // We got a temporary failure updating monitor, but will claim the // HTLC when the monitor updating is restored (or on chain). let logger = WithContext::from(&self.logger, None, Some(prev_hop_chan_id)); - log_error!(logger, "Temporary failure claiming HTLC, treating as success: {}", err.err.err); - } else { errs.push((pk, err)); } + log_error!( + logger, + "Temporary failure claiming HTLC, treating as success: {}", + err.err.err + ); + } else { + errs.push((pk, err)); + } } } } if !valid_mpp { for htlc in sources.drain(..) { 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()); let source = HTLCSource::PreviousHopData(htlc.prev_hop); let reason = HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data); let receiver = HTLCDestination::FailedPayment { payment_hash }; @@ -5529,9 +6579,12 @@ where } } - fn claim_funds_from_hop, bool) -> Option>(&self, - prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, completion_action: ComplFunc) - -> Result<(), (PublicKey, MsgHandleErrInternal)> { + fn claim_funds_from_hop< + ComplFunc: FnOnce(Option, bool) -> Option, + >( + &self, prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, + completion_action: ComplFunc, + ) -> Result<(), (PublicKey, MsgHandleErrInternal)> { //TODO: Delay the claimed_funds relaying just like we do outbound relay! // If we haven't yet run background events assume we're still deserializing and shouldn't @@ -5547,35 +6600,63 @@ where { let per_peer_state = self.per_peer_state.read().unwrap(); let chan_id = prev_hop.channel_id; - let counterparty_node_id_opt = match self.short_to_chan_info.read().unwrap().get(&prev_hop.short_channel_id) { - Some((cp_id, _dup_chan_id)) => Some(cp_id.clone()), - None => None - }; + let counterparty_node_id_opt = + match self.short_to_chan_info.read().unwrap().get(&prev_hop.short_channel_id) { + Some((cp_id, _dup_chan_id)) => Some(cp_id.clone()), + None => None, + }; - let peer_state_opt = counterparty_node_id_opt.as_ref().map( - |counterparty_node_id| per_peer_state.get(counterparty_node_id) - .map(|peer_mutex| peer_mutex.lock().unwrap()) - ).unwrap_or(None); + let peer_state_opt = counterparty_node_id_opt + .as_ref() + .map(|counterparty_node_id| { + per_peer_state + .get(counterparty_node_id) + .map(|peer_mutex| peer_mutex.lock().unwrap()) + }) + .unwrap_or(None); if peer_state_opt.is_some() { let mut peer_state_lock = peer_state_opt.unwrap(); let peer_state = &mut *peer_state_lock; - if let hash_map::Entry::Occupied(mut chan_phase_entry) = peer_state.channel_by_id.entry(chan_id) { + if let hash_map::Entry::Occupied(mut chan_phase_entry) = + peer_state.channel_by_id.entry(chan_id) + { if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() { let counterparty_node_id = chan.context.get_counterparty_node_id(); let logger = WithChannelContext::from(&self.logger, &chan.context); - let fulfill_res = chan.get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &&logger); + let fulfill_res = chan.get_update_fulfill_htlc_and_commit( + prev_hop.htlc_id, + payment_preimage, + &&logger, + ); match fulfill_res { - UpdateFulfillCommitFetch::NewClaim { htlc_value_msat, monitor_update } => { - if let Some(action) = completion_action(Some(htlc_value_msat), false) { + UpdateFulfillCommitFetch::NewClaim { + htlc_value_msat, + monitor_update, + } => { + if let Some(action) = + completion_action(Some(htlc_value_msat), false) + { 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 !during_init { - handle_new_monitor_update!(self, prev_hop.outpoint, prev_hop.channel_id, monitor_update, peer_state_lock, - peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + prev_hop.outpoint, + prev_hop.channel_id, + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } else { // If we're running during init we cannot update a monitor directly - // they probably haven't actually been loaded yet. Instead, push the @@ -5586,9 +6667,10 @@ where funding_txo: prev_hop.outpoint, channel_id: prev_hop.channel_id, update: monitor_update.clone(), - }); + }, + ); } - } + }, UpdateFulfillCommitFetch::DuplicateClaim {} => { let action = if let Some(action) = completion_action(None, true) { action @@ -5623,7 +6705,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); @@ -5631,7 +6715,7 @@ where } else { debug_assert!(false); } - } + }, } } return Ok(()); @@ -5641,9 +6725,7 @@ where let preimage_update = ChannelMonitorUpdate { update_id: CLOSED_CHANNEL_UPDATE_ID, counterparty_node_id: None, - updates: vec![ChannelMonitorUpdateStep::PaymentPreimage { - payment_preimage, - }], + updates: vec![ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage }], channel_id: Some(prev_hop.channel_id), }; @@ -5656,9 +6738,12 @@ where // with a preimage we *must* somehow manage to propagate it to the upstream // channel, or we must have an ability to receive the same event and try // again on restart. - log_error!(WithContext::from(&self.logger, None, Some(prev_hop.channel_id)), + log_error!( + WithContext::from(&self.logger, None, Some(prev_hop.channel_id)), "Critical error: failed to update channel monitor with preimage {:?}: {:?}", - payment_preimage, update_res); + payment_preimage, + update_res + ); } } else { // If we're running during init we cannot update a monitor directly - they probably @@ -5673,8 +6758,11 @@ where // complete the monitor update completion action from `completion_action`. self.pending_background_events.lock().unwrap().push( BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup(( - prev_hop.outpoint, prev_hop.channel_id, preimage_update, - ))); + prev_hop.outpoint, + prev_hop.channel_id, + preimage_update, + )), + ); } // Note that we do process the completion action here. This totally could be a // duplicate claim, but we have no way of knowing without interrogating the @@ -5689,7 +6777,8 @@ where 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, from_onchain: bool, startup_replay: bool, next_channel_counterparty_node_id: Option, next_channel_outpoint: OutPoint, next_channel_id: ChannelId, @@ -5702,25 +6791,41 @@ where debug_assert_eq!(pubkey, 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 completed_blocker = RAAMonitorUpdateBlockingAction::from_prev_hop_data(&hop_data); + let completed_blocker = + RAAMonitorUpdateBlockingAction::from_prev_hop_data(&hop_data); #[cfg(debug_assertions)] let claiming_chan_funding_outpoint = hop_data.outpoint; #[cfg(debug_assertions)] let claiming_channel_id = hop_data.channel_id; - let res = self.claim_funds_from_hop(hop_data, payment_preimage, + let res = self.claim_funds_from_hop( + hop_data, + payment_preimage, |htlc_claim_value_msat, definitely_duplicate| { let chan_to_release = if let Some(node_id) = next_channel_counterparty_node_id { - Some((node_id, next_channel_outpoint, next_channel_id, completed_blocker)) + Some(( + node_id, + next_channel_outpoint, + next_channel_id, + completed_blocker, + )) } else { // We can only get `None` here if we are processing a // `ChannelMonitor`-originated event, in which case we @@ -5735,11 +6840,14 @@ where // monitor updates still in flight. In that case, we shouldn't // immediately free, but instead let that monitor update complete // in the background. - #[cfg(debug_assertions)] { - let background_events = self.pending_background_events.lock().unwrap(); + #[cfg(debug_assertions)] + { + let background_events = + self.pending_background_events.lock().unwrap(); // There should be a `BackgroundEvent` pending... - assert!(background_events.iter().any(|ev| { - match ev { + assert!( + background_events.iter().any(|ev| { + match ev { // to apply a monitor update that blocked the claiming channel, BackgroundEvent::MonitorUpdateRegeneratedOnStartup { funding_txo, update, .. @@ -5775,7 +6883,10 @@ where } => *channel_id == claiming_channel_id, } - }), "{:?}", *background_events); + }), + "{:?}", + *background_events + ); } None } else if definitely_duplicate { @@ -5786,13 +6897,20 @@ where downstream_channel_id: other_chan.2, blocking_action: other_chan.3, }) - } else { None } + } else { + None + } } else { - let 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 }; + let 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 + }; Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { event: events::Event::PaymentForwarded { fee_earned_msat, @@ -5804,7 +6922,8 @@ where downstream_counterparty_and_funding_outpoint: chan_to_release, }) } - }); + }, + ); if let Err((pk, err)) = res { let result: Result<(), _> = Err(err); let _ = handle_error!(self, result, pk); @@ -5818,7 +6937,11 @@ where self.our_network_pubkey.clone() } - 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); @@ -5826,34 +6949,54 @@ where for action in actions.into_iter() { match action { MonitorUpdateCompletionAction::PaymentClaimed { payment_hash } => { - 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, receiver_node_id, htlcs, sender_intended_value: sender_intended_total_msat, - }) = payment { - self.pending_events.lock().unwrap().push_back((events::Event::PaymentClaimed { - payment_hash, - purpose, - amount_msat, - receiver_node_id: Some(receiver_node_id), - htlcs, - sender_intended_total_msat, - }, None)); + }) = payment + { + self.pending_events.lock().unwrap().push_back(( + events::Event::PaymentClaimed { + payment_hash, + purpose, + amount_msat, + receiver_node_id: Some(receiver_node_id), + htlcs, + sender_intended_total_msat, + }, + None, + )); } }, 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((node_id, funding_outpoint, channel_id, blocker)) = downstream_counterparty_and_funding_outpoint { - self.handle_monitor_update_release(node_id, funding_outpoint, channel_id, Some(blocker)); + if let Some((node_id, funding_outpoint, channel_id, blocker)) = + downstream_counterparty_and_funding_outpoint + { + self.handle_monitor_update_release( + node_id, + funding_outpoint, + channel_id, + Some(blocker), + ); } }, 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, @@ -5868,12 +7011,13 @@ where /// 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 Channel, raa: Option, - commitment_update: Option, order: RAACommitmentOrder, - pending_forwards: Vec<(PendingHTLCInfo, u64)>, funding_broadcastable: Option, - channel_ready: Option, announcement_sigs: Option) - -> Option<(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)> { + fn handle_channel_resumption( + &self, pending_msg_events: &mut Vec, channel: &mut Channel, + raa: Option, commitment_update: Option, + order: RAACommitmentOrder, pending_forwards: Vec<(PendingHTLCInfo, u64)>, + funding_broadcastable: Option, channel_ready: Option, + announcement_sigs: Option, + ) -> Option<(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)> { let logger = WithChannelContext::from(&self.logger, &channel.context); log_trace!(logger, "Handling channel resumption for channel {} with {} RAA, {} commitment update, {} pending forwards, {}broadcasting funding, {} channel ready, {} announcement", &channel.context.channel_id(), @@ -5887,8 +7031,16 @@ where let counterparty_node_id = channel.context.get_counterparty_node_id(); if !pending_forwards.is_empty() { - htlc_forwards = Some((channel.context.get_short_channel_id().unwrap_or(channel.context.outbound_scid_alias()), - channel.context.get_funding_txo().unwrap(), channel.context.channel_id(), channel.context.get_user_id(), pending_forwards)); + htlc_forwards = Some(( + channel + .context + .get_short_channel_id() + .unwrap_or(channel.context.outbound_scid_alias()), + channel.context.get_funding_txo().unwrap(), + channel.context.channel_id(), + channel.context.get_user_id(), + pending_forwards, + )); } if let Some(msg) = channel_ready { @@ -5901,22 +7053,26 @@ where }); } - macro_rules! handle_cs { () => { - if let Some(update) = commitment_update { - pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs { - node_id: counterparty_node_id, - updates: update, - }); - } - } } - macro_rules! handle_raa { () => { - if let Some(revoke_and_ack) = raa { - pending_msg_events.push(events::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(events::MessageSendEvent::UpdateHTLCs { + node_id: counterparty_node_id, + updates: update, + }); + } + }; + } + macro_rules! handle_raa { + () => { + if let Some(revoke_and_ack) = raa { + pending_msg_events.push(events::MessageSendEvent::SendRevokeAndACK { + node_id: counterparty_node_id, + msg: revoke_and_ack, + }); + } + }; + } match order { RAACommitmentOrder::CommitmentFirst => { handle_cs!(); @@ -5942,7 +7098,10 @@ where htlc_forwards } - fn channel_monitor_updated(&self, funding_txo: &OutPoint, channel_id: &ChannelId, highest_applied_update_id: u64, counterparty_node_id: Option<&PublicKey>) { + fn channel_monitor_updated( + &self, funding_txo: &OutPoint, channel_id: &ChannelId, highest_applied_update_id: u64, + counterparty_node_id: Option<&PublicKey>, + ) { debug_assert!(self.total_consistency_lock.try_write().is_err()); // Caller holds read lock let counterparty_node_id = match counterparty_node_id { @@ -5955,38 +7114,55 @@ where Some(cp_id) => cp_id.clone(), None => return, } - } + }, }; 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; - let channel = - if let Some(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get_mut(&channel_id) { - chan - } else { - 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); - return; - }; + let channel = if let Some(ChannelPhase::Funded(chan)) = + peer_state.channel_by_id.get_mut(&channel_id) + { + chan + } else { + 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); + return; + }; let remaining_in_flight = if let Some(pending) = peer_state.in_flight_monitor_updates.get_mut(funding_txo) { pending.retain(|upd| upd.update_id > highest_applied_update_id); pending.len() - } else { 0 }; + } else { + 0 + }; let logger = WithChannelContext::from(&self.logger, &channel.context); - log_trace!(logger, "ChannelMonitor updated to {}. Current highest is {}. {} pending in-flight updates.", - highest_applied_update_id, channel.context.get_latest_monitor_update_id(), - remaining_in_flight); - if !channel.is_awaiting_monitor_update() || channel.context.get_latest_monitor_update_id() != highest_applied_update_id { + log_trace!( + logger, + "ChannelMonitor updated to {}. Current highest is {}. {} pending in-flight updates.", + highest_applied_update_id, + channel.context.get_latest_monitor_update_id(), + remaining_in_flight + ); + if !channel.is_awaiting_monitor_update() + || channel.context.get_latest_monitor_update_id() != highest_applied_update_id + { return; } - handle_monitor_update_completion!(self, peer_state_lock, peer_state, per_peer_state, channel); + handle_monitor_update_completion!( + self, + peer_state_lock, + peer_state, + per_peer_state, + channel + ); } /// Accepts a request to open a channel after a [`Event::OpenChannelRequest`]. @@ -6005,8 +7181,16 @@ where /// /// [`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) -> Result<(), APIError> { - self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, false, user_channel_id) + pub fn accept_inbound_channel( + &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, + user_channel_id: u128, + ) -> Result<(), APIError> { + self.do_accept_inbound_channel( + temporary_channel_id, + counterparty_node_id, + false, + user_channel_id, + ) } /// Accepts a request to open a channel after a [`events::Event::OpenChannelRequest`], treating @@ -6027,21 +7211,37 @@ where /// /// [`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) -> Result<(), APIError> { - self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, true, 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, + ) -> Result<(), APIError> { + self.do_accept_inbound_channel( + temporary_channel_id, + counterparty_node_id, + true, + user_channel_id, + ) } - fn do_accept_inbound_channel(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, accept_0conf: bool, user_channel_id: u128) -> Result<(), APIError> { - - let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(*temporary_channel_id)); + fn do_accept_inbound_channel( + &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, + accept_0conf: bool, user_channel_id: u128, + ) -> Result<(), APIError> { + let logger = WithContext::from( + &self.logger, + Some(*counterparty_node_id), + Some(*temporary_channel_id), + ); 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 } @@ -6054,26 +7254,38 @@ where // happening and return an error. N.B. that we create channel with an outbound SCID of zero so // that we can delay allocating the SCID until after we're sure that the checks below will // succeed. - let mut channel = match peer_state.inbound_channel_request_by_id.remove(temporary_channel_id) { - Some(unaccepted_channel) => { - let best_block_height = self.best_block.read().unwrap().height(); - InboundV1Channel::new(&self.fee_estimator, &self.entropy_source, &self.signer_provider, - counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, - &unaccepted_channel.open_channel_msg, user_channel_id, &self.default_configuration, best_block_height, - &self.logger, accept_0conf).map_err(|e| { + let mut channel = + match peer_state.inbound_channel_request_by_id.remove(temporary_channel_id) { + Some(unaccepted_channel) => { + let best_block_height = self.best_block.read().unwrap().height(); + InboundV1Channel::new( + &self.fee_estimator, + &self.entropy_source, + &self.signer_provider, + counterparty_node_id.clone(), + &self.channel_type_features(), + &peer_state.latest_features, + &unaccepted_channel.open_channel_msg, + user_channel_id, + &self.default_configuration, + best_block_height, + &self.logger, + accept_0conf, + ) + .map_err(|e| { let err_str = e.to_string(); log_error!(logger, "{}", err_str); APIError::ChannelUnavailable { err: err_str } }) - } - _ => { - let err_str = "No such channel awaiting to be accepted.".to_owned(); - log_error!(logger, "{}", err_str); + }, + _ => { + let err_str = "No such channel awaiting to be accepted.".to_owned(); + log_error!(logger, "{}", err_str); - Err(APIError::APIMisuseError { err: err_str }) - } - }?; + Err(APIError::APIMisuseError { err: err_str }) + }, + }?; if accept_0conf { // This should have been correctly configured by the call to InboundV1Channel::new. @@ -6081,9 +7293,12 @@ where } else if channel.context.get_channel_type().requires_zero_conf() { let send_msg_err_event = events::MessageSendEvent::HandleError { node_id: channel.context.get_counterparty_node_id(), - action: msgs::ErrorAction::SendErrorMessage{ - msg: msgs::ErrorMessage { channel_id: temporary_channel_id.clone(), data: "No zero confirmation channels accepted".to_owned(), } - } + action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { + channel_id: temporary_channel_id.clone(), + 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(); @@ -6097,12 +7312,18 @@ where if is_only_peer_channel && peers_without_funded_channels >= MAX_UNFUNDED_CHANNEL_PEERS { let send_msg_err_event = events::MessageSendEvent::HandleError { node_id: channel.context.get_counterparty_node_id(), - action: msgs::ErrorAction::SendErrorMessage{ - msg: msgs::ErrorMessage { channel_id: temporary_channel_id.clone(), 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.clone(), + 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 }); @@ -6118,7 +7339,9 @@ where msg: channel.accept_inbound_channel(), }); - peer_state.channel_by_id.insert(temporary_channel_id.clone(), ChannelPhase::UnfundedInboundV1(channel)); + peer_state + .channel_by_id + .insert(temporary_channel_id.clone(), ChannelPhase::UnfundedInboundV1(channel)); Ok(()) } @@ -6129,14 +7352,18 @@ where /// 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; @@ -6146,17 +7373,16 @@ where 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 (_, phase) in peer.channel_by_id.iter() { match phase { ChannelPhase::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 !chan.context.is_outbound() && chan.context.minimum_depth().unwrap_or(1) != 0 && - chan.context.get_funding_tx_confirmations(best_block_height) == 0 + if !chan.context.is_outbound() + && chan.context.minimum_depth().unwrap_or(1) != 0 + && chan.context.get_funding_tx_confirmations(best_block_height) == 0 { num_unfunded_channels += 1; } @@ -6169,21 +7395,29 @@ where ChannelPhase::UnfundedOutboundV1(_) => { // Outbound channels don't contribute to the unfunded count in the DoS context. continue; - } + }, } } num_unfunded_channels + peer.inbound_channel_request_by_id.len() } - fn internal_open_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> { + fn internal_open_channel( + &self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannel, + ) -> Result<(), MsgHandleErrInternal> { // Note that the ChannelManager is NOT re-persisted on disk after this, so any changes are // likely to be lost on restart! if msg.chain_hash != self.chain_hash { - return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "Unknown genesis block hash".to_owned(), + msg.temporary_channel_id.clone(), + )); } if !self.default_configuration.accept_inbound_channels { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No inbound channels accepted".to_owned(), + msg.temporary_channel_id.clone(), + )); } // Get the number of peers with channels, but without funded ones. We don't care too much @@ -6193,58 +7427,77 @@ where 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), msg.temporary_channel_id.clone()) - })?; + 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.clone(), + ) + })?; 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(), - msg.temporary_channel_id.clone())); + msg.temporary_channel_id.clone(), + )); } 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), - msg.temporary_channel_id.clone())); + msg.temporary_channel_id.clone(), + )); } let channel_id = msg.temporary_channel_id; let channel_exists = peer_state.has_channel(&channel_id); if channel_exists { - return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision for the same peer!".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "temporary_channel_id collision for the same peer!".to_owned(), + msg.temporary_channel_id.clone(), + )); } // 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 channel_type = channel::channel_type_from_open_channel( - &msg, &peer_state.latest_features, &self.channel_type_features() - ).map_err(|e| - MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id) - )?; + &msg, + &peer_state.latest_features, + &self.channel_type_features(), + ) + .map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id))?; let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push_back((events::Event::OpenChannelRequest { - temporary_channel_id: msg.temporary_channel_id.clone(), - counterparty_node_id: counterparty_node_id.clone(), - funding_satoshis: msg.funding_satoshis, - push_msat: msg.push_msat, - channel_type, - }, None)); - peer_state.inbound_channel_request_by_id.insert(channel_id, InboundChannelRequest { - open_channel_msg: msg.clone(), - ticks_remaining: UNACCEPTED_INBOUND_CHANNEL_AGE_LIMIT_TICKS, - }); + pending_events.push_back(( + events::Event::OpenChannelRequest { + temporary_channel_id: msg.temporary_channel_id.clone(), + counterparty_node_id: counterparty_node_id.clone(), + funding_satoshis: msg.funding_satoshis, + push_msat: msg.push_msat, + channel_type, + }, + None, + )); + peer_state.inbound_channel_request_by_id.insert( + channel_id, + InboundChannelRequest { + open_channel_msg: msg.clone(), + ticks_remaining: UNACCEPTED_INBOUND_CHANNEL_AGE_LIMIT_TICKS, + }, + ); return Ok(()); } @@ -6252,22 +7505,38 @@ where let mut random_bytes = [0u8; 16]; random_bytes.copy_from_slice(&self.entropy_source.get_secure_random_bytes()[..16]); let user_channel_id = u128::from_be_bytes(random_bytes); - let mut channel = match InboundV1Channel::new(&self.fee_estimator, &self.entropy_source, &self.signer_provider, - counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, msg, user_channel_id, - &self.default_configuration, best_block_height, &self.logger, /*is_0conf=*/false) - { + let mut channel = match InboundV1Channel::new( + &self.fee_estimator, + &self.entropy_source, + &self.signer_provider, + counterparty_node_id.clone(), + &self.channel_type_features(), + &peer_state.latest_features, + msg, + user_channel_id, + &self.default_configuration, + best_block_height, + &self.logger, + /*is_0conf=*/ false, + ) { Err(e) => { return Err(MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id)); }, - Ok(res) => res + Ok(res) => res, }; let channel_type = channel.context.get_channel_type(); if channel_type.requires_zero_conf() { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No zero confirmation channels accepted".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No zero confirmation channels accepted".to_owned(), + msg.temporary_channel_id.clone(), + )); } 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(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No channels with anchor outputs accepted".to_owned(), + msg.temporary_channel_id.clone(), + )); } let outbound_scid_alias = self.create_and_insert_outbound_scid_alias(); @@ -6281,16 +7550,23 @@ where 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.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; match peer_state.channel_by_id.entry(msg.temporary_channel_id) { @@ -6309,25 +7585,35 @@ where } }; let mut pending_events = self.pending_events.lock().unwrap(); - pending_events.push_back((events::Event::FundingGenerationReady { - temporary_channel_id: msg.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.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; @@ -6359,17 +7645,26 @@ where 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_chan_phase_err` immediately (thus calling - // `update_maps_on_chan_removal`), 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(msg.temporary_channel_id); - return Err(convert_chan_phase_err!(self, err, chan, &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_chan_phase_err` immediately (thus calling + // `update_maps_on_chan_removal`), 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(msg.temporary_channel_id); + return Err(convert_chan_phase_err!( + self, + err, + chan, + &funded_channel_id, + UNFUNDED_CHANNEL + ) + .1); + }}; + } match peer_state.channel_by_id.entry(funded_channel_id) { hash_map::Entry::Occupied(_) => { @@ -6382,7 +7677,8 @@ where fail_chan!("The funding_created message had the same funding_txid as an existing channel - funding is not possible"); }, hash_map::Entry::Vacant(i_e) => { - let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor); + let monitor_res = + self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor); if let Ok(persist_state) = monitor_res { i_e.insert(chan.context.get_counterparty_node_id()); mem::drop(outpoint_to_peer_lock); @@ -6392,17 +7688,29 @@ where // accepted payment from yet. We do, however, need to wait to send our channel_ready // until we have persisted our monitor. if let Some(msg) = funding_msg_opt { - peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingSigned { - node_id: counterparty_node_id.clone(), - msg, - }); + peer_state.pending_msg_events.push( + events::MessageSendEvent::SendFundingSigned { + node_id: counterparty_node_id.clone(), + msg, + }, + ); } - if let ChannelPhase::Funded(chan) = e.insert(ChannelPhase::Funded(chan)) { - handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state, - per_peer_state, chan, INITIAL_MONITOR); + if let ChannelPhase::Funded(chan) = e.insert(ChannelPhase::Funded(chan)) + { + handle_new_monitor_update!( + self, + persist_state, + peer_state_lock, + peer_state, + per_peer_state, + chan, + INITIAL_MONITOR + ); } else { - unreachable!("This must be a funded channel as we just inserted it."); + unreachable!( + "This must be a funded channel as we just inserted it." + ); } Ok(()) } else { @@ -6410,53 +7718,89 @@ where log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated"); fail_chan!("Duplicate funding outpoint"); } - } + }, } - } + }, } } - 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; match peer_state.channel_by_id.entry(msg.channel_id) { hash_map::Entry::Occupied(chan_phase_entry) => { if matches!(chan_phase_entry.get(), ChannelPhase::UnfundedOutboundV1(_)) { - let chan = if let ChannelPhase::UnfundedOutboundV1(chan) = chan_phase_entry.remove() { chan } else { unreachable!() }; + let chan = + if let ChannelPhase::UnfundedOutboundV1(chan) = chan_phase_entry.remove() { + chan + } else { + unreachable!() + }; let logger = WithContext::from( &self.logger, Some(chan.context.get_counterparty_node_id()), - Some(chan.context.channel_id()) + Some(chan.context.channel_id()), ); let res = chan.funding_signed(&msg, best_block, &self.signer_provider, &&logger); match res { Ok((mut chan, monitor)) => { - if let Ok(persist_status) = self.chain_monitor.watch_channel(chan.context.get_funding_txo().unwrap(), monitor) { + if let Ok(persist_status) = self + .chain_monitor + .watch_channel(chan.context.get_funding_txo().unwrap(), monitor) + { // We really should be able to insert here without doing a second // lookup, but sadly rust stdlib doesn't currently allow keeping // the original Entry around with the value removed. - let mut chan = peer_state.channel_by_id.entry(msg.channel_id).or_insert(ChannelPhase::Funded(chan)); + let mut chan = peer_state + .channel_by_id + .entry(msg.channel_id) + .or_insert(ChannelPhase::Funded(chan)); if let ChannelPhase::Funded(ref mut chan) = &mut chan { - handle_new_monitor_update!(self, persist_status, peer_state_lock, peer_state, per_peer_state, chan, INITIAL_MONITOR); - } else { unreachable!(); } + handle_new_monitor_update!( + self, + persist_status, + peer_state_lock, + peer_state, + per_peer_state, + chan, + INITIAL_MONITOR + ); + } else { + unreachable!(); + } Ok(()) } else { - let e = ChannelError::Close("Channel funding outpoint was a duplicate".to_owned()); + let e = ChannelError::Close( + "Channel funding outpoint was a duplicate".to_owned(), + ); // We weren't able to watch the channel to begin with, so no // updates should be made on it. Previously, full_stack_target // found an (unreachable) panic when the monitor update contained // within `shutdown_finish` was applied. chan.unset_funding_info(msg.channel_id); - return Err(convert_chan_phase_err!(self, e, &mut ChannelPhase::Funded(chan), &msg.channel_id).1); + return Err(convert_chan_phase_err!( + self, + e, + &mut ChannelPhase::Funded(chan), + &msg.channel_id + ) + .1); } }, Err((chan, e)) => { @@ -6465,26 +7809,47 @@ where // We've already removed this outbound channel from the map in // `PeerState` above so at this point we just need to clean up any // lingering entries concerning this channel as it is safe to do so. - return Err(convert_chan_phase_err!(self, e, &mut ChannelPhase::UnfundedOutboundV1(chan), &msg.channel_id).1); - } + return Err(convert_chan_phase_err!( + self, + e, + &mut ChannelPhase::UnfundedOutboundV1(chan), + &msg.channel_id + ) + .1); + }, } } else { - return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id)); + 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)) + hash_map::Entry::Vacant(_) => { + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "Failed to find corresponding channel".to_owned(), + msg.channel_id, + )) + }, } } - 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) { @@ -6531,19 +7896,28 @@ where } } - 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_phase_entry) = peer_state.channel_by_id.entry(msg.channel_id.clone()) { + if let hash_map::Entry::Occupied(mut chan_phase_entry) = + peer_state.channel_by_id.entry(msg.channel_id.clone()) + { let phase = chan_phase_entry.get_mut(); match phase { ChannelPhase::Funded(chan) => { @@ -6555,23 +7929,36 @@ where } let funding_txo_opt = chan.context.get_funding_txo(); - let (shutdown, monitor_update_opt, htlcs) = try_chan_phase_entry!(self, - chan.shutdown(&self.signer_provider, &peer_state.latest_features, &msg), chan_phase_entry); + let (shutdown, monitor_update_opt, htlcs) = try_chan_phase_entry!( + self, + chan.shutdown(&self.signer_provider, &peer_state.latest_features, &msg), + chan_phase_entry + ); dropped_htlcs = htlcs; if let Some(msg) = shutdown { // We can send the `shutdown` message before updating the `ChannelMonitor` // here as we don't need the monitor update to complete until we send a // `shutdown_signed`, which we'll delay if we're pending a monitor update. - peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown { - node_id: *counterparty_node_id, - msg, - }); + peer_state.pending_msg_events.push( + events::MessageSendEvent::SendShutdown { + node_id: *counterparty_node_id, + msg, + }, + ); } // 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(), chan.context.channel_id(), monitor_update, - peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo_opt.unwrap(), + chan.context.channel_id(), + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); } }, ChannelPhase::UnfundedInboundV1(_) | ChannelPhase::UnfundedOutboundV1(_) => { @@ -6579,15 +7966,21 @@ where let logger = WithChannelContext::from(&self.logger, context); log_error!(logger, "Immediately closing unfunded channel {} as peer asked to cooperatively shut it down (which is unnecessary)", &msg.channel_id); let mut chan = remove_channel_phase!(self, chan_phase_entry); - finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel)); + finish_shutdown = Some(chan.context_mut().force_shutdown( + false, + ClosureReason::CounterpartyCoopClosedUnfundedChannel, + )); }, } } 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(0x4000 | 8); self.fail_htlc_backwards_internal(&htlc_source.0, &htlc_source.1, &reason, receiver); } @@ -6598,13 +7991,20 @@ where 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; @@ -6637,16 +8037,20 @@ where }; 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), "Broadcasting {}", log_tx!(broadcast_tx)); + log_info!( + WithContext::from(&self.logger, Some(*counterparty_node_id), channel_id), + "Broadcasting {}", + log_tx!(broadcast_tx) + ); self.tx_broadcaster.broadcast_transactions(&[&broadcast_tx]); } if let Some(ChannelPhase::Funded(chan)) = chan_option { if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + peer_state + .pending_msg_events + .push(events::MessageSendEvent::BroadcastChannelUpdate { msg: update }); } } mem::drop(per_peer_state); @@ -6656,7 +8060,9 @@ where 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. @@ -6671,11 +8077,16 @@ where let decoded_hop_res = self.decode_update_add_htlc_onion(msg, counterparty_node_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.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) { @@ -6737,15 +8148,22 @@ where 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 (htlc_source, forwarded_htlc_value) = { 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) { @@ -6777,20 +8195,35 @@ where 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), - false, false, Some(*counterparty_node_id), funding_txo, msg.channel_id); + self.claim_funds_internal( + htlc_source, + msg.payment_preimage.clone(), + Some(forwarded_htlc_value), + false, + false, + Some(*counterparty_node_id), + funding_txo, + msg.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) { @@ -6807,15 +8240,22 @@ where 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) { @@ -6836,13 +8276,20 @@ where } } - 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 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) { @@ -6866,8 +8313,24 @@ where } #[inline] - fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)]) { - for &mut (prev_short_channel_id, prev_funding_outpoint, prev_channel_id, prev_user_channel_id, ref mut pending_forwards) in per_source_pending_forwards { + fn forward_htlcs( + &self, + per_source_pending_forwards: &mut [( + u64, + OutPoint, + ChannelId, + u128, + Vec<(PendingHTLCInfo, u64)>, + )], + ) { + for &mut ( + prev_short_channel_id, + prev_funding_outpoint, + prev_channel_id, + prev_user_channel_id, + ref mut pending_forwards, + ) in per_source_pending_forwards + { let mut push_forward_event = false; let mut new_intercept_events = VecDeque::new(); let mut failed_intercept_forwards = Vec::new(); @@ -6886,45 +8349,83 @@ where match forward_htlcs.entry(scid) { hash_map::Entry::Occupied(mut entry) => { entry.get_mut().push(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, prev_funding_outpoint, prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info })); + prev_short_channel_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_funding_outpoint, prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info }); + prev_short_channel_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)); + let logger = WithContext::from( + &self.logger, + None, + Some(prev_channel_id), + ); 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), - 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(), - }); + let htlc_source = + HTLCSource::PreviousHopData(HTLCPreviousHopData { + short_channel_id: prev_short_channel_id, + user_channel_id: Some(prev_user_channel_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(), + }); - failed_intercept_forwards.push((htlc_source, forward_info.payment_hash, - HTLCFailReason::from_failure_code(0x4000 | 10), - HTLCDestination::InvalidForward { requested_forward_scid: scid }, + failed_intercept_forwards.push(( + htlc_source, + forward_info.payment_hash, + HTLCFailReason::from_failure_code(0x4000 | 10), + HTLCDestination::InvalidForward { + requested_forward_scid: scid, + }, )); - } + }, } } else { // We don't want to generate a PendingHTLCsForwardable event if only intercepted @@ -6932,32 +8433,54 @@ where if forward_htlcs_empty { push_forward_event = true; } - entry.insert(vec!(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { - prev_short_channel_id, prev_funding_outpoint, prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info }))); + entry.insert(vec![HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { + prev_short_channel_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(..) { - self.fail_htlc_backwards_internal(&htlc_source, &payment_hash, &failure_reason, destination); + for (htlc_source, payment_hash, failure_reason, destination) in + failed_intercept_forwards.drain(..) + { + self.fail_htlc_backwards_internal( + &htlc_source, + &payment_hash, + &failure_reason, + destination, + ); } if !new_intercept_events.is_empty() { let mut events = self.pending_events.lock().unwrap(); events.append(&mut new_intercept_events); } - if push_forward_event { self.push_pending_forwards_ev() } + if push_forward_event { + self.push_pending_forwards_ev() + } } } 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 @@ -6965,9 +8488,12 @@ where // 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, + )); } } @@ -6975,24 +8501,31 @@ where /// [`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) { @@ -7000,21 +8533,35 @@ where 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.context().get_funding_txo().unwrap(), channel_id, counterparty_node_id); + return self.raa_monitor_updates_held( + &peer_state.actions_blocking_raa_monitor_updates, + chan.context().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_phase_entry) => { @@ -7047,13 +8594,20 @@ where 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) { @@ -7071,13 +8625,20 @@ where Ok(()) } - 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) { @@ -7107,18 +8668,21 @@ where } /// 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; @@ -7134,14 +8698,24 @@ where } 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.flags & 1 == 0; if were_node_one == msg_from_node_one { return Ok(NotifyOption::SkipPersistNoEvents); } else { let logger = WithChannelContext::from(&self.logger, &chan.context); - log_debug!(logger, "Received channel_update {:?} for channel {}.", msg, chan_id); - let did_change = try_chan_phase_entry!(self, chan.channel_update(&msg), chan_phase_entry); + log_debug!( + logger, + "Received channel_update {:?} for channel {}.", + msg, + chan_id + ); + let did_change = try_chan_phase_entry!( + self, + chan.channel_update(&msg), + chan_phase_entry + ); // If nothing changed after applying their update, we don't need to bother // persisting. if !did_change { @@ -7149,29 +8723,39 @@ where } } } else { - return try_chan_phase_entry!(self, Err(ChannelError::Close( - "Got a channel_update for an unfunded channel!".into())), chan_phase_entry); + return try_chan_phase_entry!( + self, + Err(ChannelError::Close( + "Got a channel_update for an unfunded channel!".into() + )), + chan_phase_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 htlc_forwards; 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)); + 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)); 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) { @@ -7181,37 +8765,62 @@ where // 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_chan_phase_entry!(self, chan.channel_reestablish( - msg, &&logger, &self.node_signer, self.chain_hash, - &self.default_configuration, &*self.best_block.read().unwrap()), chan_phase_entry); + let responses = try_chan_phase_entry!( + self, + chan.channel_reestablish( + msg, + &&logger, + &self.node_signer, + self.chain_hash, + &self.default_configuration, + &*self.best_block.read().unwrap() + ), + chan_phase_entry + ); let mut channel_update = None; if let Some(msg) = responses.shutdown_msg { - peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown { - node_id: counterparty_node_id.clone(), - msg, - }); + peer_state.pending_msg_events.push( + events::MessageSendEvent::SendShutdown { + node_id: counterparty_node_id.clone(), + msg, + }, + ); } else if chan.context.is_usable() { // If the channel is in a usable state (ie the channel is not being shut // down), send a unicast channel_update to our counterparty to make sure // they have the latest channel parameters. if let Ok(msg) = self.get_channel_update_for_unicast(chan) { - channel_update = Some(events::MessageSendEvent::SendChannelUpdate { - node_id: chan.context.get_counterparty_node_id(), - msg, - }); + channel_update = + Some(events::MessageSendEvent::SendChannelUpdate { + node_id: chan.context.get_counterparty_node_id(), + msg, + }); } } let need_lnd_workaround = chan.context.workaround_lnd_bug_4006.take(); htlc_forwards = self.handle_channel_resumption( - &mut peer_state.pending_msg_events, chan, responses.raa, responses.commitment_update, responses.order, - Vec::new(), None, responses.channel_ready, responses.announcement_sigs); + &mut peer_state.pending_msg_events, + chan, + responses.raa, + responses.commitment_update, + responses.order, + Vec::new(), + None, + responses.channel_ready, + responses.announcement_sigs, + ); if let Some(upd) = channel_update { peer_state.pending_msg_events.push(upd); } need_lnd_workaround } else { - return try_chan_phase_entry!(self, Err(ChannelError::Close( - "Got a channel_reestablish message for an unfunded channel!".into())), chan_phase_entry); + return try_chan_phase_entry!( + self, + Err(ChannelError::Close( + "Got a channel_reestablish message for an unfunded channel!".into() + )), + chan_phase_entry + ); } }, hash_map::Entry::Vacant(_) => { @@ -7238,15 +8847,16 @@ where 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) - ) - } + ); + }, } }; @@ -7269,19 +8879,47 @@ where 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, counterparty_node_id, Some(channel_id)); + let logger = + WithContext::from(&self.logger, counterparty_node_id, Some(channel_id)); if let Some(preimage) = htlc_update.payment_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), true, false, counterparty_node_id, funding_outpoint, channel_id); + 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), + true, + false, + counterparty_node_id, + funding_outpoint, + channel_id, + ); } else { - log_trace!(logger, "Failing HTLC with hash {} from our monitor", &htlc_update.payment_hash); - let receiver = HTLCDestination::NextHopChannel { node_id: counterparty_node_id, channel_id }; + log_trace!( + logger, + "Failing HTLC with hash {} from our monitor", + &htlc_update.payment_hash + ); + let receiver = HTLCDestination::NextHopChannel { + node_id: counterparty_node_id, + channel_id, + }; let reason = HTLCFailReason::from_failure_code(0x4000 | 8); - 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(_funding_outpoint) => { @@ -7292,35 +8930,58 @@ where // monitor event, this and the outpoint_to_peer map should be removed. let outpoint_to_peer = self.outpoint_to_peer.lock().unwrap(); outpoint_to_peer.get(&funding_outpoint).cloned() - } + }, }; if let Some(counterparty_node_id) = counterparty_node_id_opt { let per_peer_state = self.per_peer_state.read().unwrap(); - if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) { + 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(chan_phase_entry) = peer_state.channel_by_id.entry(channel_id) { - if let ChannelPhase::Funded(mut chan) = remove_channel_phase!(self, chan_phase_entry) { - failed_channels.push(chan.context.force_shutdown(false, ClosureReason::HolderForceClosed)); - if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { - pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + if let hash_map::Entry::Occupied(chan_phase_entry) = + peer_state.channel_by_id.entry(channel_id) + { + if let ChannelPhase::Funded(mut chan) = + remove_channel_phase!(self, chan_phase_entry) + { + failed_channels.push(chan.context.force_shutdown( + false, + ClosureReason::HolderForceClosed, + )); + if let Ok(update) = + self.get_channel_update_for_broadcast(&chan) + { + pending_msg_events.push( + events::MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } - pending_msg_events.push(events::MessageSendEvent::HandleError { - node_id: chan.context.get_counterparty_node_id(), - action: msgs::ErrorAction::DisconnectPeer { - msg: Some(msgs::ErrorMessage { channel_id: chan.context.channel_id(), data: "Channel force-closed".to_owned() }) + pending_msg_events.push( + events::MessageSendEvent::HandleError { + node_id: chan.context.get_counterparty_node_id(), + action: msgs::ErrorAction::DisconnectPeer { + msg: Some(msgs::ErrorMessage { + channel_id: chan.context.channel_id(), + data: "Channel force-closed".to_owned(), + }), + }, }, - }); + ); } } } } }, MonitorEvent::Completed { funding_txo, channel_id, monitor_update_id } => { - self.channel_monitor_updated(&funding_txo, &channel_id, monitor_update_id, counterparty_node_id.as_ref()); + self.channel_monitor_updated( + &funding_txo, + &channel_id, + monitor_update_id, + counterparty_node_id.as_ref(), + ); }, } } @@ -7359,21 +9020,41 @@ where '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, phase)| if let ChannelPhase::Funded(chan) = phase { Some((chan_id, chan)) } else { None } - ) { + for (channel_id, chan) in + peer_state.channel_by_id.iter_mut().filter_map(|(chan_id, phase)| { + if let ChannelPhase::Funded(chan) = phase { + Some((chan_id, chan)) + } else { + None + } + }) { let counterparty_node_id = chan.context.get_counterparty_node_id(); let funding_txo = chan.context.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)); + let (monitor_opt, holding_cell_failed_htlcs) = chan + .maybe_free_holding_cell_htlcs( + &self.fee_estimator, + &&WithChannelContext::from(&self.logger, &chan.context), + ); 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(), chan.context.channel_id(), monitor_update, - peer_state_lock, peer_state, per_peer_state, chan); + handle_new_monitor_update!( + self, + funding_txo.unwrap(), + chan.context.channel_id(), + monitor_update, + peer_state_lock, + peer_state, + per_peer_state, + chan + ); continue 'peer_loop; } } @@ -7402,35 +9083,30 @@ where pub fn signer_unblocked(&self, channel_opt: Option<(PublicKey, ChannelId)>) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - let unblock_chan = |phase: &mut ChannelPhase, pending_msg_events: &mut Vec| { + let unblock_chan = |phase: &mut ChannelPhase, + pending_msg_events: &mut Vec| { let node_id = phase.context().get_counterparty_node_id(); match phase { ChannelPhase::Funded(chan) => { let msgs = chan.signer_maybe_unblocked(&self.logger); if let Some(updates) = msgs.commitment_update { - pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs { - node_id, - updates, - }); + pending_msg_events + .push(events::MessageSendEvent::UpdateHTLCs { node_id, updates }); } if let Some(msg) = msgs.funding_signed { - pending_msg_events.push(events::MessageSendEvent::SendFundingSigned { - node_id, - msg, - }); + pending_msg_events + .push(events::MessageSendEvent::SendFundingSigned { node_id, msg }); } if let Some(msg) = msgs.channel_ready { send_channel_ready!(self, pending_msg_events, chan, msg); } - } + }, ChannelPhase::UnfundedOutboundV1(chan) => { if let Some(msg) = chan.signer_maybe_unblocked(&self.logger) { - pending_msg_events.push(events::MessageSendEvent::SendFundingCreated { - node_id, - msg, - }); + pending_msg_events + .push(events::MessageSendEvent::SendFundingCreated { node_id, msg }); } - } + }, ChannelPhase::UnfundedInboundV1(_) => {}, } }; @@ -7477,35 +9153,54 @@ where Ok((msg_opt, tx_opt, shutdown_result_opt)) => { if let Some(msg) = msg_opt { has_update = true; - pending_msg_events.push(events::MessageSendEvent::SendClosingSigned { - node_id: chan.context.get_counterparty_node_id(), msg, - }); + pending_msg_events.push( + events::MessageSendEvent::SendClosingSigned { + node_id: chan.context.get_counterparty_node_id(), + msg, + }, + ); } - debug_assert_eq!(shutdown_result_opt.is_some(), chan.is_shutdown()); + debug_assert_eq!( + shutdown_result_opt.is_some(), + chan.is_shutdown() + ); if let Some(shutdown_result) = shutdown_result_opt { 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(&chan) { - pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); + if let Ok(update) = + self.get_channel_update_for_broadcast(&chan) + { + pending_msg_events.push( + events::MessageSendEvent::BroadcastChannelUpdate { + msg: update, + }, + ); } log_info!(logger, "Broadcasting {}", log_tx!(tx)); self.tx_broadcaster.broadcast_transactions(&[&tx]); update_maps_on_chan_removal!(self, &chan.context); false - } else { true } + } else { + true + } }, Err(e) => { has_update = true; - let (close_channel, res) = convert_chan_phase_err!(self, e, chan, channel_id, FUNDED_CHANNEL); - handle_errors.push((chan.context.get_counterparty_node_id(), Err(res))); + let (close_channel, res) = convert_chan_phase_err!( + self, + e, + chan, + channel_id, + FUNDED_CHANNEL + ); + handle_errors + .push((chan.context.get_counterparty_node_id(), Err(res))); !close_channel - } + }, } }, _ => true, // Retain unfunded channels if present. @@ -7537,15 +9232,25 @@ where // Channel::force_shutdown tries to make us do) as we may still be in initialization, // so we track the update internally and handle it when the user next calls // timer_tick_occurred, guaranteeing we're running normally. - if let Some((counterparty_node_id, funding_txo, channel_id, update)) = failure.monitor_update.take() { + if let Some((counterparty_node_id, funding_txo, channel_id, update)) = + failure.monitor_update.take() + { assert_eq!(update.updates.len(), 1); - if let ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } = update.updates[0] { + if let ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } = + update.updates[0] + { assert!(should_broadcast); - } else { unreachable!(); } + } else { + unreachable!(); + } self.pending_background_events.lock().unwrap().push( BackgroundEvent::MonitorUpdateRegeneratedOnStartup { - counterparty_node_id, funding_txo, update, channel_id, - }); + counterparty_node_id, + funding_txo, + update, + channel_id, + }, + ); } self.finish_close_channel(failure); } @@ -7579,7 +9284,7 @@ where /// [`Offer`]: crate::offers::offer::Offer /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest pub fn create_offer_builder( - &self, description: String + &self, description: String, ) -> Result, Bolt12SemanticError> { let node_id = self.get_our_node_id(); let expanded_key = &self.inbound_payment_key; @@ -7588,10 +9293,14 @@ where let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; let builder = OfferBuilder::deriving_signing_pubkey( - description, node_id, expanded_key, entropy, secp_ctx + description, + node_id, + expanded_key, + entropy, + secp_ctx, ) - .chain_hash(self.chain_hash) - .path(path); + .chain_hash(self.chain_hash) + .path(path); Ok(builder) } @@ -7646,7 +9355,7 @@ where /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments pub fn create_refund_builder( &self, description: String, amount_msats: u64, absolute_expiry: Duration, - payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option + payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option, ) -> Result, Bolt12SemanticError> { let node_id = self.get_our_node_id(); let expanded_key = &self.inbound_payment_key; @@ -7655,16 +9364,25 @@ where let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; let builder = RefundBuilder::deriving_payer_id( - description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id + description, + node_id, + expanded_key, + entropy, + secp_ctx, + amount_msats, + payment_id, )? - .chain_hash(self.chain_hash) - .absolute_expiry(absolute_expiry) - .path(path); + .chain_hash(self.chain_hash) + .absolute_expiry(absolute_expiry) + .path(path); let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry); self.pending_outbound_payments .add_new_awaiting_invoice( - payment_id, expiration, retry_strategy, max_total_routing_fee_msat, + payment_id, + expiration, + retry_strategy, + max_total_routing_fee_msat, ) .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?; @@ -7727,7 +9445,7 @@ where pub fn pay_for_offer( &self, offer: &Offer, quantity: Option, amount_msats: Option, payer_note: Option, payment_id: PaymentId, retry_strategy: Retry, - max_total_routing_fee_msat: Option + max_total_routing_fee_msat: Option, ) -> Result<(), Bolt12SemanticError> { let expanded_key = &self.inbound_payment_key; let entropy = &*self.entropy_source; @@ -7749,12 +9467,16 @@ where Some(payer_note) => builder.payer_note(payer_note), }; let invoice_request = builder.build_and_sign()?; - let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; + let reply_path = + self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; let expiration = StaleExpiration::TimerTicks(1); self.pending_outbound_payments .add_new_awaiting_invoice( - payment_id, expiration, retry_strategy, max_total_routing_fee_msat + payment_id, + expiration, + retry_strategy, + max_total_routing_fee_msat, ) .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?; @@ -7814,24 +9536,30 @@ where match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) { Ok((payment_hash, payment_secret)) => { - let payment_paths = self.create_blinded_payment_paths(amount_msats, payment_secret) + let payment_paths = self + .create_blinded_payment_paths(amount_msats, payment_secret) .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 invoice = builder.allow_mpp().build_and_sign(secp_ctx)?; - let reply_path = self.create_blinded_path() - .map_err(|_| Bolt12SemanticError::MissingPaths)?; + let reply_path = + self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap(); if refund.paths().is_empty() { @@ -7890,11 +9618,18 @@ where /// [`PaymentPurpose::InvoicePayment`]: events::PaymentPurpose::InvoicePayment /// [`PaymentPurpose::InvoicePayment::payment_preimage`]: events::PaymentPurpose::InvoicePayment::payment_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 @@ -7943,19 +9678,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 blinded path by delegating to [`MessageRouter::create_blinded_paths`]. @@ -7966,7 +9714,10 @@ where let entropy_source = self.entropy_source.deref(); let secp_ctx = &self.secp_ctx; - let peers = self.per_peer_state.read().unwrap() + let peers = self + .per_peer_state + .read() + .unwrap() .iter() .filter(|(_, peer)| peer.lock().unwrap().latest_features.supports_onion_messages()) .map(|(node_id, _)| *node_id) @@ -7980,24 +9731,27 @@ where /// 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: u64, payment_secret: PaymentSecret + &self, amount_msats: u64, payment_secret: PaymentSecret, ) -> Result, ()> { let entropy_source = self.entropy_source.deref(); let secp_ctx = &self.secp_ctx; let first_hops = self.list_usable_channels(); let payee_node_id = self.get_our_node_id(); - let max_cltv_expiry = self.best_block.read().unwrap().height() + CLTV_FAR_FAR_AWAY + let max_cltv_expiry = self.best_block.read().unwrap().height() + + CLTV_FAR_FAR_AWAY + LATENCY_GRACE_PERIOD_BLOCKS; let payee_tlvs = ReceiveTlvs { payment_secret, - payment_constraints: PaymentConstraints { - max_cltv_expiry, - htlc_minimum_msat: 1, - }, + payment_constraints: PaymentConstraints { max_cltv_expiry, htlc_minimum_msat: 1 }, }; self.router.create_blinded_payment_paths( - payee_node_id, first_hops, payee_tlvs, amount_msats, entropy_source, secp_ctx + payee_node_id, + first_hops, + payee_tlvs, + amount_msats, + entropy_source, + secp_ctx, ) } @@ -8009,11 +9763,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, } } } @@ -8039,10 +9798,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; } } @@ -8055,9 +9821,13 @@ 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; - for chan in peer_state.channel_by_id.values().filter_map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ) { + for chan in peer_state.channel_by_id.values().filter_map(|phase| { + if let ChannelPhase::Funded(chan) = phase { + Some(chan) + } else { + None + } + }) { for (htlc_source, _) in chan.inflight_htlc_sources() { if let HTLCSource::OutboundRoute { path, .. } = htlc_source { inflight_htlcs.process_path(path, self.get_our_node_id()); @@ -8103,13 +9873,11 @@ 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), - ); + 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)); loop { let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mtx) = per_peer_state.get(&counterparty_node_id) { @@ -8117,15 +9885,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. @@ -8134,15 +9906,32 @@ where break; } - if let hash_map::Entry::Occupied(mut chan_phase_entry) = peer_state.channel_by_id.entry( - channel_id) { + if let hash_map::Entry::Occupied(mut chan_phase_entry) = + peer_state.channel_by_id.entry(channel_id) + { if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() { - debug_assert_eq!(chan.context.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, channel_id, monitor_update, - peer_state_lck, peer_state, per_peer_state, chan); + debug_assert_eq!( + chan.context.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, + channel_id, + 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. @@ -8155,9 +9944,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; } @@ -8167,10 +9958,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, + ); + }, } } } @@ -8179,15 +9977,19 @@ where /// using the given event handler. /// /// See the trait-level documentation of [`EventsProvider`] for requirements. - pub async fn process_pending_events_async 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 MessageSendEventsProvider for ChannelManager +impl + MessageSendEventsProvider for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -8249,7 +10051,8 @@ where } } -impl EventsProvider for ChannelManager +impl + EventsProvider for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -8264,13 +10067,17 @@ 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 + chain::Listen for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -8297,7 +10104,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(); @@ -8308,11 +10117,21 @@ 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))); + 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), + ) + }); } } -impl chain::Confirm for ChannelManager +impl + chain::Confirm for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -8329,18 +10148,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)) - .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), + ) + .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))); + 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), + ) + }); } } @@ -8354,10 +10201,21 @@ 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); - self.do_chain_event(Some(height), |channel| channel.best_block_updated(height, header.time, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context))); + self.do_chain_event(Some(height), |channel| { + channel.best_block_updated( + height, + header.time, + self.chain_hash, + &self.node_signer, + &self.default_configuration, + &&WithChannelContext::from(&self.logger, &channel.context), + ) + }); macro_rules! max_time { ($timestamp: expr) => { @@ -8368,18 +10226,27 @@ 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); let mut payment_secrets = self.pending_inbound_payments.lock().unwrap(); - payment_secrets.retain(|_, inbound_payment| { - inbound_payment.expiry_time > header.time as u64 - }); + payment_secrets + .retain(|_, inbound_payment| inbound_payment.expiry_time > header.time as u64); } fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option)> { @@ -8387,11 +10254,19 @@ where for (_cp_id, peer_state_mutex) in self.per_peer_state.read().unwrap().iter() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - for chan in peer_state.channel_by_id.values().filter_map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) { + for chan in peer_state.channel_by_id.values().filter_map(|phase| { + if let ChannelPhase::Funded(chan) = phase { + Some(chan) + } else { + None + } + }) { let txid_opt = chan.context.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))); } } @@ -8402,18 +10277,30 @@ 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.context.get_funding_txo() { if funding_txo.txid == *txid { - channel.funding_transaction_unconfirmed(&&WithChannelContext::from(&self.logger, &channel.context)).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, + )) + .map(|()| (None, Vec::new(), None)) + } else { + Ok((None, Vec::new(), None)) + } + } else { + Ok((None, Vec::new(), None)) + } }); } } -impl ChannelManager +impl + ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -8427,8 +10314,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 Channel, + ) -> 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. @@ -8536,24 +10435,33 @@ 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 mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec(); - htlc_msat_height_data.extend_from_slice(&height.to_be_bytes()); - - timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), - HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data), - 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 mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec(); + htlc_msat_height_data.extend_from_slice(&height.to_be_bytes()); + + timed_out_htlcs.push(( + HTLCSource::PreviousHopData(htlc.prev_hop.clone()), + payment_hash.clone(), + HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data), + 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| { @@ -8573,16 +10481,23 @@ 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(0x2000 | 2), - HTLCDestination::InvalidForward { requested_forward_scid })); - let logger = WithContext::from( - &self.logger, None, Some(htlc.prev_channel_id) + timed_out_htlcs.push(( + prev_hop_data, + htlc.forward_info.payment_hash, + HTLCFailReason::from_failure_code(0x2000 | 2), + HTLCDestination::InvalidForward { requested_forward_scid }, + )); + let logger = WithContext::from(&self.logger, None, Some(htlc.prev_channel_id)); + 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 + } + }); } self.handle_init_event_channel_failures(failed_channels); @@ -8692,9 +10607,14 @@ where } fn handle_open_channel_v2(&self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannelV2) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Dual-funded channels not supported".to_owned(), - msg.temporary_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.temporary_channel_id.clone() + )), + *counterparty_node_id + ); } fn handle_accept_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::AcceptChannel) { @@ -8702,25 +10622,44 @@ 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.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.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_channel_ready(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReady) { @@ -8740,37 +10679,65 @@ where } fn handle_stfu(&self, counterparty_node_id: &PublicKey, msg: &msgs::Stfu) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Quiescence not supported".to_owned(), - msg.channel_id.clone())), *counterparty_node_id); + let _: Result<(), _> = handle_error!( + self, + Err(MsgHandleErrInternal::send_err_msg_no_close( + "Quiescence not supported".to_owned(), + msg.channel_id.clone() + )), + *counterparty_node_id + ); } fn handle_splice(&self, counterparty_node_id: &PublicKey, msg: &msgs::Splice) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Splicing not supported".to_owned(), - msg.channel_id.clone())), *counterparty_node_id); + let _: Result<(), _> = handle_error!( + self, + Err(MsgHandleErrInternal::send_err_msg_no_close( + "Splicing not supported".to_owned(), + msg.channel_id.clone() + )), + *counterparty_node_id + ); } fn handle_splice_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceAck) { - let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( - "Splicing not supported (splice_ack)".to_owned(), - msg.channel_id.clone())), *counterparty_node_id); + let _: Result<(), _> = handle_error!( + self, + Err(MsgHandleErrInternal::send_err_msg_no_close( + "Splicing not supported (splice_ack)".to_owned(), + msg.channel_id.clone() + )), + *counterparty_node_id + ); } 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.clone())), *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.clone() + )), + *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) { @@ -8789,12 +10756,20 @@ 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) { + fn handle_update_fail_htlc( + &self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC, + ) { // Note that we never need to persist the updated ChannelManager for an inbound // update_fail_htlc message - the message itself doesn't change our channel state only the // `commitment_signed` message afterwards will. @@ -8810,7 +10785,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. @@ -8826,14 +10803,24 @@ 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_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) { @@ -8852,14 +10839,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 @@ -8867,7 +10864,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 { @@ -8881,8 +10880,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 = { @@ -8906,16 +10906,13 @@ where &mut chan.context }, // Unfunded channels will always be removed. - ChannelPhase::UnfundedOutboundV1(chan) => { - &mut chan.context - }, - ChannelPhase::UnfundedInboundV1(chan) => { - &mut chan.context - }, + ChannelPhase::UnfundedOutboundV1(chan) => &mut chan.context, + ChannelPhase::UnfundedInboundV1(chan) => &mut chan.context, }; // Clean up for removal. update_maps_on_chan_removal!(self, &context); - failed_channels.push(context.force_shutdown(false, ClosureReason::DisconnectedPeer)); + failed_channels + .push(context.force_shutdown(false, ClosureReason::DisconnectedPeer)); false }); // Note that we don't bother generating any events for pre-accept channels - @@ -8972,7 +10969,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); @@ -8984,10 +10984,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); 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(()); } @@ -8998,8 +11004,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(); @@ -9025,21 +11033,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) { @@ -9047,15 +11062,23 @@ where let peer_state = &mut *peer_state_lock; let pending_msg_events = &mut peer_state.pending_msg_events; - peer_state.channel_by_id.iter_mut().filter_map(|(_, phase)| - if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).for_each(|chan| { - let logger = WithChannelContext::from(&self.logger, &chan.context); - pending_msg_events.push(events::MessageSendEvent::SendChannelReestablish { - node_id: chan.context.get_counterparty_node_id(), - msg: chan.get_channel_reestablish(&&logger), + peer_state + .channel_by_id + .iter_mut() + .filter_map(|(_, phase)| { + if let ChannelPhase::Funded(chan) = phase { + Some(chan) + } else { + None + } + }) + .for_each(|chan| { + let logger = WithChannelContext::from(&self.logger, &chan.context); + pending_msg_events.push(events::MessageSendEvent::SendChannelReestablish { + node_id: chan.context.get_counterparty_node_id(), + msg: chan.get_channel_reestablish(&&logger), + }); }); - }); } return NotifyOption::SkipPersistHandleEvents; @@ -9068,9 +11091,7 @@ where let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); 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 @@ -9081,14 +11102,20 @@ where if !msg.channel_id.is_zero() { 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 = peer_state_mutex_opt.unwrap().lock().unwrap(); - if let Some(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get(&msg.channel_id) { + if let Some(ChannelPhase::Funded(chan)) = + peer_state.channel_by_id.get(&msg.channel_id) + { if let Some(msg) = chan.get_outbound_shutdown() { - peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown { - node_id: *counterparty_node_id, - msg, - }); + peer_state.pending_msg_events.push( + events::MessageSendEvent::SendShutdown { + node_id: *counterparty_node_id, + msg, + }, + ); } peer_state.pending_msg_events.push(events::MessageSendEvent::HandleError { node_id: *counterparty_node_id, @@ -9103,15 +11130,17 @@ where } } return; - } - _ => {} + }, + _ => {}, } if msg.channel_id.is_zero() { 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 - @@ -9121,29 +11150,47 @@ 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; - if let Some(ChannelPhase::UnfundedOutboundV1(chan)) = peer_state.channel_by_id.get_mut(&msg.channel_id) { - if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) { - peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel { - node_id: *counterparty_node_id, - msg, - }); + if let Some(ChannelPhase::UnfundedOutboundV1(chan)) = + peer_state.channel_by_id.get_mut(&msg.channel_id) + { + if let Ok(msg) = + chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) + { + peer_state.pending_msg_events.push( + events::MessageSendEvent::SendOpenChannel { + node_id: *counterparty_node_id, + msg, + }, + ); return; } } } // 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, + ); } } @@ -9160,62 +11207,109 @@ where } fn handle_tx_add_input(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxAddInput) { - 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_add_output(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxAddOutput) { - 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_remove_input(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxRemoveInput) { - 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_remove_output(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxRemoveOutput) { - 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_remove_output( + &self, counterparty_node_id: &PublicKey, msg: &msgs::TxRemoveOutput, + ) { + 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_complete(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxComplete) { - 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_signatures(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxSignatures) { - 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_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) { - 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 + ); } } impl -OffersMessageHandler for ChannelManager + OffersMessageHandler for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -9232,12 +11326,11 @@ where match message { OffersMessage::InvoiceRequest(invoice_request) => { - let amount_msats = match InvoiceBuilder::::amount_msats( - &invoice_request - ) { - Ok(amount_msats) => amount_msats, - Err(error) => return Some(OffersMessage::InvoiceError(error.into())), - }; + let amount_msats = + match InvoiceBuilder::::amount_msats(&invoice_request) { + Ok(amount_msats) => amount_msats, + Err(error) => return Some(OffersMessage::InvoiceError(error.into())), + }; let invoice_request = match invoice_request.verify(expanded_key, secp_ctx) { Ok(invoice_request) => invoice_request, Err(()) => { @@ -9247,39 +11340,35 @@ where }; 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())); - }, - }; + 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())); + }, + }; - let payment_paths = match self.create_blinded_payment_paths( - amount_msats, payment_secret - ) { - Ok(payment_paths) => payment_paths, - Err(()) => { - let error = Bolt12SemanticError::MissingPaths; - return Some(OffersMessage::InvoiceError(error.into())); - }, - }; + let payment_paths = + match self.create_blinded_payment_paths(amount_msats, payment_secret) { + Ok(payment_paths) => payment_paths, + Err(()) => { + let error = Bolt12SemanticError::MissingPaths; + return Some(OffersMessage::InvoiceError(error.into())); + }, + }; #[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); 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, ); match builder.and_then(|b| b.allow_mpp().build_and_sign(secp_ctx)) { Ok(invoice) => Some(OffersMessage::Invoice(invoice)), @@ -9289,44 +11378,55 @@ 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 response = builder.and_then(|builder| builder.allow_mpp().build()) + let builder = invoice_request.respond_with_no_std(payment_paths, payment_hash, created_at); + let response = builder + .and_then(|builder| builder.allow_mpp().build()) .map_err(|e| OffersMessage::InvoiceError(e.into())) - .and_then(|invoice| - match invoice.sign(|invoice| self.node_signer.sign_bolt12_invoice(invoice)) { + .and_then(|invoice| { + match invoice + .sign(|invoice| self.node_signer.sign_bolt12_invoice(invoice)) + { Ok(invoice) => Ok(OffersMessage::Invoice(invoice)), Err(SignError::Signing(())) => Err(OffersMessage::InvoiceError( - InvoiceError::from_string("Failed signing invoice".to_string()) - )), - Err(SignError::Verification(_)) => Err(OffersMessage::InvoiceError( - InvoiceError::from_string("Failed invoice signature verification".to_string()) + InvoiceError::from_string("Failed signing invoice".to_string()), )), - }); + Err(SignError::Verification(_)) => { + Err(OffersMessage::InvoiceError(InvoiceError::from_string( + "Failed invoice signature verification".to_string(), + ))) + }, + } + }); match response { Ok(invoice) => Some(invoice), Err(error) => Some(error), } } }, - OffersMessage::Invoice(invoice) => { - match invoice.verify(expanded_key, secp_ctx) { - Err(()) => { - Some(OffersMessage::InvoiceError(InvoiceError::from_string("Unrecognized invoice".to_owned()))) - }, - Ok(_) if invoice.invoice_features().requires_unknown_bits_from(&self.bolt12_invoice_features()) => { - Some(OffersMessage::InvoiceError(Bolt12SemanticError::UnknownRequiredFeatures.into())) - }, - Ok(payment_id) => { - if let Err(e) = self.send_payment_for_bolt12_invoice(&invoice, payment_id) { - log_trace!(self.logger, "Failed paying invoice: {:?}", e); - Some(OffersMessage::InvoiceError(InvoiceError::from_string(format!("{:?}", e)))) - } else { - None - } - }, - } + OffersMessage::Invoice(invoice) => match invoice.verify(expanded_key, secp_ctx) { + Err(()) => Some(OffersMessage::InvoiceError(InvoiceError::from_string( + "Unrecognized invoice".to_owned(), + ))), + Ok(_) + if invoice + .invoice_features() + .requires_unknown_bits_from(&self.bolt12_invoice_features()) => + { + Some(OffersMessage::InvoiceError( + Bolt12SemanticError::UnknownRequiredFeatures.into(), + )) + }, + Ok(payment_id) => { + if let Err(e) = self.send_payment_for_bolt12_invoice(&invoice, payment_id) { + log_trace!(self.logger, "Failed paying invoice: {:?}", e); + Some(OffersMessage::InvoiceError(InvoiceError::from_string(format!( + "{:?}", + e + )))) + } else { + None + } + }, }, OffersMessage::InvoiceError(invoice_error) => { log_trace!(self.logger, "Received invoice_error: {}", invoice_error); @@ -9497,8 +11597,8 @@ impl Readable for ChannelDetails { // `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_low: u64 = user_channel_id_low.0.unwrap(); - let user_channel_id = user_channel_id_low as u128 + - ((user_channel_id_high_opt.unwrap_or(0 as u64) as u128) << 64); + let user_channel_id = user_channel_id_low as u128 + + ((user_channel_id_high_opt.unwrap_or(0 as u64) as u128) << 64); Ok(Self { inbound_scid_alias, @@ -9576,7 +11676,6 @@ 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 { @@ -9587,7 +11686,10 @@ impl Writeable for HTLCFailureMsg { reason.write(writer)?; }, 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)?; @@ -9604,21 +11706,17 @@ 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)?, - })) - }, - 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)?, + })), + 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. @@ -9706,7 +11804,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); @@ -9716,7 +11814,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); } @@ -9742,7 +11840,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; @@ -9768,7 +11867,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)?; } } } @@ -9778,7 +11878,7 @@ impl Readable for HTLCSource { path, payment_id: payment_id.unwrap(), }) - } + }, 1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)), _ => Err(DecodeError::UnknownRequiredFeature), } @@ -9788,23 +11888,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(()) } @@ -9892,7 +11997,8 @@ impl_writeable_tlv_based!(PendingInboundPayment, { (8, min_value_msat, required), }); -impl Writeable for ChannelManager +impl Writeable + for ChannelManager where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -9926,9 +12032,17 @@ where serializable_peer_count += 1; } - number_of_funded_channels += peer_state.channel_by_id.iter().filter( - |(_, phase)| if let ChannelPhase::Funded(chan) = phase { chan.context.is_funding_broadcast() } else { false } - ).count(); + number_of_funded_channels += peer_state + .channel_by_id + .iter() + .filter(|(_, phase)| { + if let ChannelPhase::Funded(chan) = phase { + chan.context.is_funding_broadcast() + } else { + false + } + }) + .count(); } (number_of_funded_channels as u64).write(writer)?; @@ -9936,11 +12050,17 @@ 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.iter().filter_map( - |(_, phase)| if let ChannelPhase::Funded(channel) = phase { - if channel.context.is_funding_broadcast() { Some(channel) } else { None } - } else { None } - ) { + for channel in peer_state.channel_by_id.iter().filter_map(|(_, phase)| { + if let ChannelPhase::Funded(channel) = phase { + if channel.context.is_funding_broadcast() { + Some(channel) + } else { + None + } + } else { + None + } + }) { channel.write(writer)?; } } @@ -9962,7 +12082,8 @@ where let pending_inbound_payments = self.pending_inbound_payments.lock().unwrap(); 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(); @@ -10048,12 +12169,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::InvoiceReceived { .. } => {}, PendingOutboundPayment::Fulfilled { .. } => {}, @@ -10062,11 +12183,12 @@ where } // Encode without retry info for 0.0.101 compatibility. - let mut pending_outbound_payments_no_retry: HashMap> = HashMap::new(); + let mut pending_outbound_payments_no_retry: HashMap> = + HashMap::new(); 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()); }, _ => {}, @@ -10086,12 +12208,19 @@ where pending_claiming_payments = None; } - let mut in_flight_monitor_updates: Option>> = None; + let mut in_flight_monitor_updates: Option< + HashMap<(&PublicKey, &OutPoint), &Vec>, + > = None; for ((counterparty_id, _), peer_state) in per_peer_state.iter().zip(peer_states.iter()) { for (funding_outpoint, updates) in peer_state.in_flight_monitor_updates.iter() { if !updates.is_empty() { - if in_flight_monitor_updates.is_none() { in_flight_monitor_updates = Some(HashMap::new()); } - in_flight_monitor_updates.as_mut().unwrap().insert((counterparty_id, funding_outpoint), updates); + if in_flight_monitor_updates.is_none() { + in_flight_monitor_updates = Some(HashMap::new()); + } + in_flight_monitor_updates + .as_mut() + .unwrap() + .insert((counterparty_id, funding_outpoint), updates); } } } @@ -10121,7 +12250,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 @@ -10130,7 +12260,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(()) @@ -10141,8 +12273,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)?; @@ -10196,8 +12330,17 @@ impl_writeable_tlv_based_enum!(ChannelShutdownState, /// 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, L: Deref> -where +pub struct ChannelManagerReadArgs< + 'a, + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, +> where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, ES::Target: EntropySource, @@ -10257,11 +12400,12 @@ 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, L: Deref> - ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, L> + ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, L> where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -10275,11 +12419,27 @@ where /// Simple utility function to create a ChannelManagerReadArgs which creates the monitor /// HashMap for you. This is primarily useful for C bindings where it is not practical to /// populate a HashMap directly from C. - pub fn new(entropy_source: ES, node_signer: NS, signer_provider: SP, fee_estimator: F, chain_monitor: M, tx_broadcaster: T, router: R, logger: L, default_config: UserConfig, - mut channel_monitors: Vec<&'a mut ChannelMonitor<::EcdsaSigner>>) -> Self { + pub fn new( + entropy_source: ES, node_signer: NS, signer_provider: SP, fee_estimator: F, + chain_monitor: M, tx_broadcaster: T, router: R, logger: L, default_config: UserConfig, + mut channel_monitors: Vec< + &'a mut ChannelMonitor<::EcdsaSigner>, + >, + ) -> Self { Self { - entropy_source, node_signer, signer_provider, fee_estimator, chain_monitor, tx_broadcaster, router, logger, default_config, - channel_monitors: channel_monitors.drain(..).map(|monitor| { (monitor.get_funding_txo().0, monitor) }).collect() + entropy_source, + node_signer, + signer_provider, + fee_estimator, + chain_monitor, + tx_broadcaster, + router, + logger, + default_config, + channel_monitors: channel_monitors + .drain(..) + .map(|monitor| (monitor.get_funding_txo().0, monitor)) + .collect(), } } } @@ -10287,7 +12447,8 @@ 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, L: Deref> - ReadableArgs> for (BlockHash, Arc>) + ReadableArgs> + for (BlockHash, Arc>) where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -10298,14 +12459,18 @@ where R::Target: Router, L::Target: Logger, { - fn read(reader: &mut Reader, args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, 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, 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, L: Deref> - ReadableArgs> for (BlockHash, ChannelManager) + ReadableArgs> + for (BlockHash, ChannelManager) where M::Target: chain::Watch<::EcdsaSigner>, T::Target: BroadcasterInterface, @@ -10316,7 +12481,9 @@ where R::Target: Router, L::Target: Logger, { - fn read(reader: &mut Reader, mut args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, L>) -> Result { + fn read( + reader: &mut Reader, mut args: ChannelManagerReadArgs<'a, M, T, ES, NS, SP, F, R, L>, + ) -> Result { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); let chain_hash: ChainHash = Readable::read(reader)?; @@ -10327,66 +12494,103 @@ where let channel_count: u64 = Readable::read(reader)?; let mut funding_txo_set = HashSet::with_capacity(cmp::min(channel_count as usize, 128)); - let mut funded_peer_channels: HashMap>> = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); + let mut funded_peer_channels: HashMap>> = + HashMap::with_capacity(cmp::min(channel_count as usize, 128)); let mut outpoint_to_peer = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); let mut channel_closures = VecDeque::new(); let mut close_background_events = Vec::new(); let mut funding_txo_to_channel_id = HashMap::with_capacity(channel_count as usize); for _ in 0..channel_count { - let mut channel: Channel = Channel::read(reader, ( - &args.entropy_source, &args.signer_provider, best_block_height, &provided_channel_type_features(&args.default_config) - ))?; + let mut channel: Channel = Channel::read( + reader, + ( + &args.entropy_source, + &args.signer_provider, + best_block_height, + &provided_channel_type_features(&args.default_config), + ), + )?; let logger = WithChannelContext::from(&args.logger, &channel.context); let funding_txo = channel.context.get_funding_txo().ok_or(DecodeError::InvalidValue)?; funding_txo_to_channel_id.insert(funding_txo, channel.context.channel_id()); funding_txo_set.insert(funding_txo.clone()); if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) { - 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(true, ClosureReason::OutdatedChannelManager); + let mut shutdown_result = + channel.context.force_shutdown(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, update)) = shutdown_result.monitor_update { - close_background_events.push(BackgroundEvent::MonitorUpdateRegeneratedOnStartup { - counterparty_node_id, funding_txo, channel_id, update - }); + if let Some((counterparty_node_id, funding_txo, channel_id, update)) = + shutdown_result.monitor_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.context.get_value_satoshis()), - channel_funding_txo: channel.context.get_funding_txo(), - }, 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.context.get_value_satoshis()), + channel_funding_txo: channel.context.get_funding_txo(), + }, + 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 @@ -10399,7 +12603,12 @@ where 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 { @@ -10407,21 +12616,34 @@ where &channel.context.channel_id(), channel.context.get_latest_monitor_update_id(), monitor.get_latest_update_id()); 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(), + ), + ); } if let Some(funding_txo) = channel.context.get_funding_txo() { - outpoint_to_peer.insert(funding_txo, channel.context.get_counterparty_node_id()); + outpoint_to_peer + .insert(funding_txo, channel.context.get_counterparty_node_id()); } match funded_peer_channels.entry(channel.context.get_counterparty_node_id()) { hash_map::Entry::Occupied(mut entry) => { let by_id_map = entry.get_mut(); - by_id_map.insert(channel.context.channel_id(), ChannelPhase::Funded(channel)); + by_id_map.insert( + channel.context.channel_id(), + ChannelPhase::Funded(channel), + ); }, hash_map::Entry::Vacant(entry) => { let mut by_id_map = HashMap::new(); - by_id_map.insert(channel.context.channel_id(), ChannelPhase::Funded(channel)); + by_id_map.insert( + channel.context.channel_id(), + ChannelPhase::Funded(channel), + ); entry.insert(by_id_map); - } + }, } } } else if channel.is_awaiting_initial_mon_persist() { @@ -10429,19 +12651,29 @@ where // was in-progress, we never broadcasted the funding transaction and can still // safely discard the channel. let _ = channel.context.force_shutdown(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.context.get_value_satoshis()), - channel_funding_txo: channel.context.get_funding_txo(), - }, None)); + 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.context.get_value_satoshis()), + channel_funding_txo: channel.context.get_funding_txo(), + }, + 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); } @@ -10451,15 +12683,26 @@ where if !funding_txo_set.contains(funding_txo) { let logger = WithChannelMonitor::from(&args.logger, monitor); 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: CLOSED_CHANNEL_UPDATE_ID, counterparty_node_id: None, - updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast: true }], + updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { + should_broadcast: true, + }], channel_id: Some(monitor.channel_id()), }; - close_background_events.push(BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup((*funding_txo, channel_id, monitor_update))); + close_background_events.push( + BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup(( + *funding_txo, + channel_id, + monitor_update, + )), + ); } } @@ -10469,7 +12712,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)?); } @@ -10477,32 +12723,37 @@ 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)?); } claimable_htlcs_list.push((payment_hash, previous_hops)); } - let peer_state_from_chans = |channel_by_id| { - PeerState { - channel_by_id, - inbound_channel_request_by_id: HashMap::new(), - 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(), - is_connected: false, - } + let peer_state_from_chans = |channel_by_id| PeerState { + channel_by_id, + inbound_channel_request_by_id: HashMap::new(), + 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(), + is_connected: false, }; let peer_count: u64 = Readable::read(reader)?; - let mut per_peer_state = HashMap::with_capacity(cmp::min(peer_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(PublicKey, Mutex>)>())); + let mut per_peer_state = HashMap::with_capacity(cmp::min( + peer_count as usize, + MAX_ALLOC_SIZE / mem::size_of::<(PublicKey, Mutex>)>(), + )); for _ in 0..peer_count { let peer_pubkey = Readable::read(reader)?; let peer_chans = funded_peer_channels.remove(&peer_pubkey).unwrap_or(HashMap::new()); @@ -10513,7 +12764,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)), @@ -10530,7 +12784,7 @@ where // on-startup monitor updates. let _: OutPoint = Readable::read(reader)?; let _: ChannelMonitorUpdate = Readable::read(reader)?; - } + }, _ => return Err(DecodeError::InvalidValue), } } @@ -10539,39 +12793,54 @@ where let highest_seen_timestamp: u32 = Readable::read(reader)?; let pending_inbound_payment_count: u64 = Readable::read(reader)?; - let mut pending_inbound_payments: HashMap = HashMap::with_capacity(cmp::min(pending_inbound_payment_count as usize, MAX_ALLOC_SIZE/(3*32))); + let mut pending_inbound_payments: HashMap = + HashMap::with_capacity(cmp::min( + pending_inbound_payment_count as usize, + MAX_ALLOC_SIZE / (3 * 32), + )); for _ in 0..pending_inbound_payment_count { - if pending_inbound_payments.insert(Readable::read(reader)?, Readable::read(reader)?).is_some() { + if pending_inbound_payments + .insert(Readable::read(reader)?, Readable::read(reader)?) + .is_some() + { return Err(DecodeError::InvalidValue); } } let pending_outbound_payments_count_compat: u64 = Readable::read(reader)?; let mut pending_outbound_payments_compat: HashMap = - HashMap::with_capacity(cmp::min(pending_outbound_payments_count_compat as usize, MAX_ALLOC_SIZE/32)); + HashMap::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: [session_priv].iter().cloned().collect() + session_privs: [session_priv].iter().cloned().collect(), }; 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(HashMap::new()); + let mut pending_intercepted_htlcs: Option> = + Some(HashMap::new()); 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(HashMap::new()); - 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 in_flight_monitor_updates: Option>> = None; + let mut in_flight_monitor_updates: Option< + HashMap<(PublicKey, OutPoint), Vec>, + > = None; read_tlv_fields!(reader, { (1, pending_outbound_payments_no_retry, option), (2, pending_intercepted_htlcs, option), @@ -10613,7 +12882,7 @@ where } let pending_outbounds = OutboundPayments { pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()), - retry_lock: Mutex::new(()) + retry_lock: Mutex::new(()), }; // We have to replay (or skip, if they were completed after we wrote the `ChannelManager`) @@ -10631,12 +12900,17 @@ where macro_rules! handle_in_flight_updates { ($counterparty_node_id: expr, $chan_in_flight_upds: expr, $funding_txo: 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()); 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 { @@ -10644,24 +12918,31 @@ where 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(), + }); } - if $peer_state.in_flight_monitor_updates.insert($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($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() { @@ -10673,15 +12954,29 @@ where // Channels that were persisted have to be funded, otherwise they should have been // discarded. - let funding_txo = chan.context.get_funding_txo().ok_or(DecodeError::InvalidValue)?; - let monitor = args.channel_monitors.get(&funding_txo) + let funding_txo = + chan.context.get_funding_txo().ok_or(DecodeError::InvalidValue)?; + let monitor = args + .channel_monitors + .get(&funding_txo) .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, funding_txo)) { - max_in_flight_update_id = cmp::max(max_in_flight_update_id, - handle_in_flight_updates!(*counterparty_id, chan_in_flight_upds, - funding_txo, monitor, peer_state, logger, "")); + if let Some(mut chan_in_flight_upds) = + in_flight_upds.remove(&(*counterparty_id, funding_txo)) + { + max_in_flight_update_id = cmp::max( + max_in_flight_update_id, + handle_in_flight_updates!( + *counterparty_id, + chan_in_flight_upds, + funding_txo, + monitor, + peer_state, + logger, + "" + ), + ); } } if chan.get_latest_unblocked_monitor_update_id() > max_in_flight_update_id { @@ -10689,7 +12984,11 @@ where 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.context.channel_id(), monitor.get_latest_update_id(), max_in_flight_update_id); - log_error!(logger, " but the ChannelManager is at update_id {}.", chan.get_latest_unblocked_monitor_update_id()); + log_error!( + logger, + " but the ChannelManager is at update_id {}.", + 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."); @@ -10713,16 +13012,30 @@ where // 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(peer_state_from_chans(HashMap::new())) - }); + let peer_state_mutex = per_peer_state + .entry(counterparty_id) + .or_insert_with(|| Mutex::new(peer_state_from_chans(HashMap::new()))); let mut peer_state = peer_state_mutex.lock().unwrap(); - handle_in_flight_updates!(counterparty_id, chan_in_flight_updates, - funding_txo, monitor, peer_state, logger, "closed "); + handle_in_flight_updates!( + counterparty_id, + chan_in_flight_updates, + funding_txo, + 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.", if let Some(channel_id) = - channel_id { channel_id.to_string() } else { format!("with outpoint {}", funding_txo) } ); + log_error!( + logger, + " The ChannelMonitor for channel {} is missing.", + if let Some(channel_id) = channel_id { + channel_id.to_string() + } else { + format!("with outpoint {}", funding_txo) + } + ); 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."); @@ -10753,8 +13066,12 @@ where let counterparty_opt = outpoint_to_peer.get(&monitor.get_funding_txo().0); if counterparty_opt.is_none() { let logger = WithChannelMonitor::from(&args.logger, monitor); - for (htlc_source, (htlc, _)) in monitor.get_pending_or_resolved_outbound_htlcs() { - if let HTLCSource::OutboundRoute { payment_id, session_priv, path, .. } = htlc_source { + for (htlc_source, (htlc, _)) in monitor.get_pending_or_resolved_outbound_htlcs() + { + 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); @@ -10763,9 +13080,15 @@ where let path_amt = path.final_value_msat(); let mut session_priv_bytes = [0; 32]; session_priv_bytes[..].copy_from_slice(&session_priv[..]); - match pending_outbounds.pending_outbound_payments.lock().unwrap().entry(payment_id) { + match pending_outbounds + .pending_outbound_payments + .lock() + .unwrap() + .entry(payment_id) + { hash_map::Entry::Occupied(mut entry) => { - let newly_added = entry.get_mut().insert(session_priv_bytes, &path); + let newly_added = + 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), htlc.payment_hash); }, @@ -10775,7 +13098,10 @@ where retry_strategy: None, attempts: PaymentAttempts::new(), payment_params: None, - session_privs: [session_priv_bytes].iter().map(|a| *a).collect(), + session_privs: [session_priv_bytes] + .iter() + .map(|a| *a) + .collect(), payment_hash: htlc.payment_hash, payment_secret: None, // only used for retries, and we'll never retry on startup payment_metadata: None, // only used for retries, and we'll never retry on startup @@ -10789,16 +13115,18 @@ where }); log_info!(logger, "Added a pending payment for {} msat with payment hash {} for path with session priv {}", path_amt, &htlc.payment_hash, log_bytes!(session_priv_bytes)); - } + }, } } } - for (htlc_source, (htlc, preimage_opt)) in monitor.get_all_current_outbound_htlcs() { + for (htlc_source, (htlc, preimage_opt)) in + monitor.get_all_current_outbound_htlcs() + { 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 @@ -10830,7 +13158,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, @@ -10847,8 +13177,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(); } }, @@ -10859,19 +13197,29 @@ where // Whether the downstream channel was closed or not, try to re-apply any payment // preimages from it which may be needed in upstream channels for forwarded // payments. - let outbound_claimed_htlcs_iter = monitor.get_all_current_outbound_htlcs() + let outbound_claimed_htlcs_iter = monitor + .get_all_current_outbound_htlcs() .into_iter() .filter_map(|(htlc_source, (htlc, preimage_opt))| { if let HTLCSource::PreviousHopData(_) = htlc_source { if let Some(payment_preimage) = preimage_opt { - Some((htlc_source, payment_preimage, htlc.amount_msat, + Some(( + htlc_source, + payment_preimage, + htlc.amount_msat, // Check if `counterparty_opt.is_none()` to see if the // downstream chan is closed (because we don't have a // channel_id -> peer map entry). counterparty_opt.is_none(), - counterparty_opt.cloned().or(monitor.get_counterparty_node_id()), - monitor.get_funding_txo().0, monitor.channel_id())) - } else { None } + counterparty_opt + .cloned() + .or(monitor.get_counterparty_node_id()), + monitor.get_funding_txo().0, + monitor.channel_id(), + )) + } else { + None + } } else { // If it was an outbound payment, we've handled it above - if a preimage // came in and we persisted the `ChannelManager` we either handled it and @@ -10892,9 +13240,10 @@ where // 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 inbound_pmt_key_material = args.node_signer.get_inbound_payment_key_material(); @@ -10909,22 +13258,31 @@ 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 { // LDK versions prior to 0.0.107 did not write a `pending_htlc_purposes`, but do // include a `_legacy_hop_data` in the `OnionPayload`. @@ -10936,26 +13294,35 @@ where OnionPayload::Invoice { _legacy_hop_data } => { if let Some(hop_data) = _legacy_hop_data { events::PaymentPurpose::InvoicePayment { - payment_preimage: match pending_inbound_payments.get(&payment_hash) { + payment_preimage: match pending_inbound_payments.get(&payment_hash) + { Some(inbound_payment) => inbound_payment.payment_preimage, - None => match inbound_payment::verify(payment_hash, &hop_data, 0, &expanded_inbound_key, &args.logger) { + None => 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 }); } } @@ -10964,7 +13331,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 { @@ -10984,21 +13351,42 @@ 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; + } } chan.context.set_outbound_scid_alias(outbound_scid_alias); } else if !outbound_scid_aliases.insert(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; {}", chan.context.outbound_scid_alias()); + log_error!( + logger, + "Got duplicate outbound SCID alias; {}", + chan.context.outbound_scid_alias() + ); return Err(DecodeError::InvalidValue); } if chan.context.is_usable() { - if short_to_chan_info.insert(chan.context.outbound_scid_alias(), (chan.context.get_counterparty_node_id(), *chan_id)).is_some() { + if short_to_chan_info + .insert( + chan.context.outbound_scid_alias(), + (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; {}", chan.context.outbound_scid_alias()); + log_error!( + logger, + "Got duplicate outbound SCID alias; {}", + chan.context.outbound_scid_alias() + ); return Err(DecodeError::InvalidValue); } } @@ -11021,7 +13409,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 = args.node_signer.get_node_id(Recipient::PhantomNode) + let phantom_pubkey = args + .node_signer + .get_node_id(Recipient::PhantomNode) .expect("Failed to get node_id for phantom node recipient"); receiver_node_id = Some(phantom_pubkey) } @@ -11044,48 +13434,84 @@ where // without the new monitor persisted - we'll end up right back here on // restart. let previous_channel_id = claimable_htlc.prev_hop.channel_id; - if let Some(peer_node_id) = outpoint_to_peer.get(&claimable_htlc.prev_hop.outpoint) { + if let Some(peer_node_id) = + outpoint_to_peer.get(&claimable_htlc.prev_hop.outpoint) + { 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(ChannelPhase::Funded(channel)) = peer_state.channel_by_id.get_mut(&previous_channel_id) { - let logger = WithChannelContext::from(&args.logger, &channel.context); - channel.claim_htlc_while_disconnected_dropping_mon_update(claimable_htlc.prev_hop.htlc_id, payment_preimage, &&logger); + if let Some(ChannelPhase::Funded(channel)) = + peer_state.channel_by_id.get_mut(&previous_channel_id) + { + let logger = + WithChannelContext::from(&args.logger, &channel.context); + channel.claim_htlc_while_disconnected_dropping_mon_update( + claimable_htlc.prev_hop.htlc_id, + payment_preimage, + &&logger, + ); } } - if let Some(previous_hop_monitor) = args.channel_monitors.get(&claimable_htlc.prev_hop.outpoint) { - previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &args.tx_broadcaster, &bounded_fee_estimator, &args.logger); + if let Some(previous_hop_monitor) = + args.channel_monitors.get(&claimable_htlc.prev_hop.outpoint) + { + previous_hop_monitor.provide_payment_preimage( + &payment_hash, + &payment_preimage, + &args.tx_broadcaster, + &bounded_fee_estimator, + &args.logger, + ); } } - pending_events_read.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), - }, None)); + pending_events_read.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), + }, + None, + )); } } } - 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)); for action in actions.iter() { if let MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { downstream_counterparty_and_funding_outpoint: - Some((blocked_node_id, _blocked_channel_outpoint, blocked_channel_id, blocking_action)), .. - } = action { + Some(( + blocked_node_id, + _blocked_channel_outpoint, + blocked_channel_id, + blocking_action, + )), + .. + } = action + { if let Some(blocked_peer_state) = per_peer_state.get(&blocked_node_id) { let channel_id = blocked_channel_id; log_trace!(logger, "Holding the next revoke_and_ack from {} until the preimage is durably persisted in the inbound edge's ChannelMonitor", channel_id); - blocked_peer_state.lock().unwrap().actions_blocking_raa_monitor_updates + blocked_peer_state + .lock() + .unwrap() + .actions_blocking_raa_monitor_updates .entry(*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 @@ -11094,14 +13520,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), "Got blocked actions without a per-peer-state for {}", node_id); + log_error!( + WithContext::from(&args.logger, Some(node_id), None), + "Got blocked actions without a per-peer-state for {}", + node_id + ); return Err(DecodeError::InvalidValue); } } @@ -11121,7 +13555,10 @@ where pending_intercepted_htlcs: Mutex::new(pending_intercepted_htlcs.unwrap()), forward_htlcs: Mutex::new(forward_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), outpoint_to_peer: Mutex::new(outpoint_to_peer), short_to_chan_info: FairRwLock::new(short_to_chan_info), @@ -11159,17 +13596,35 @@ where for htlc_source in failed_htlcs.drain(..) { let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source; - 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(0x4000 | 8); 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), - downstream_closed, true, downstream_node_id, downstream_funding, downstream_channel_id); + channel_manager.claim_funds_internal( + source, + preimage, + Some(downstream_value), + downstream_closed, + true, + downstream_node_id, + downstream_funding, + downstream_channel_id, + ); } //TODO: Broadcast channel update for closed channels, but only after we've made a @@ -11181,24 +13636,29 @@ where #[cfg(test)] mod tests { - use bitcoin::hashes::Hash; - use bitcoin::hashes::sha256::Hash as Sha256; - use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; - use core::sync::atomic::Ordering; - use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason}; - use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; - use crate::ln::ChannelId; - use crate::ln::channelmanager::{create_recv_pending_htlc_info, HTLCForwardInfo, inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId}; + use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, + }; + use crate::ln::channelmanager::{ + create_recv_pending_htlc_info, inbound_payment, HTLCForwardInfo, InterceptId, PaymentId, + PaymentSendFailure, RecipientOnionFields, + }; use crate::ln::functional_test_utils::*; - use crate::ln::msgs::{self, ErrorAction}; use crate::ln::msgs::ChannelMessageHandler; + use crate::ln::msgs::{self, ErrorAction}; + use crate::ln::ChannelId; + use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; 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::util::config::{ChannelConfig, ChannelConfigUpdate}; use crate::util::errors::APIError; use crate::util::ser::Writeable; use crate::util::test_utils; - use crate::util::config::{ChannelConfig, ChannelConfigUpdate}; - use crate::sign::EntropySource; + use bitcoin::hashes::sha256::Hash as Sha256; + use bitcoin::hashes::Hash; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; + use core::sync::atomic::Ordering; #[test] fn test_notify_limits() { @@ -11221,10 +13681,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()); @@ -11257,9 +13723,20 @@ 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.flags & 1 == 0 /* chan.0 is from node one */) { &chan.0 } else { &chan.1 }; - let bs_update = if as_node_one == (chan.0.contents.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.flags & 1 == 0/* chan.0 is from node one */) { + &chan.0 + } else { + &chan.1 + }; + let bs_update = + if as_node_one == (chan.0.contents.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. @@ -11291,7 +13768,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()); @@ -11299,28 +13777,67 @@ 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(&route, Some(payment_preimage), - RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.0)).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_preimage.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()); @@ -11328,17 +13845,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 @@ -11349,29 +13889,57 @@ 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(&nodes[1].node.get_our_node_id(), &bs_first_updates.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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(&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(&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( + &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(&nodes[0].node.get_our_node_id(), &as_second_updates.commitment_signed); + nodes[1].node.handle_commitment_signed( + &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); @@ -11380,7 +13948,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); @@ -11388,7 +13960,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); @@ -11426,30 +14002,55 @@ 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); + PaymentParameters::for_keysend( + expected_route.last().unwrap().node.get_our_node_id(), + TEST_FINAL_CLTV, + false, + ), + 100_000, + ); 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(); - nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), - RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.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(); + nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_preimage.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()); @@ -11457,7 +14058,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); @@ -11467,32 +14071,67 @@ 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(&route, Some(payment_preimage), - RecipientOnionFields::spontaneous_empty(), PaymentId(payment_preimage.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( + &route, + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_preimage.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, 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 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()); @@ -11500,7 +14139,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); @@ -11509,37 +14151,76 @@ 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(&route, Some(payment_preimage), - RecipientOnionFields::spontaneous_empty(), payment_id_1).unwrap(); + let payment_hash = nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_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); 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 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(); + &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_id_2 = PaymentId([45; 32]); - nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), - RecipientOnionFields::spontaneous_empty(), payment_id_2).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_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); 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()); @@ -11547,7 +14228,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); @@ -11569,22 +14253,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()); @@ -11593,9 +14303,15 @@ 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].logger.assert_log_contains("lightning::ln::channelmanager", "Payment preimage didn't match payment hash", 1); + 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", + "Payment preimage didn't match payment hash", + 1, + ); } #[test] @@ -11606,7 +14322,8 @@ mod tests { reject_mpp_keysend_cfg.accept_mpp_keysend = false; 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(reject_mpp_keysend_cfg)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[None, Some(reject_mpp_keysend_cfg)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let payer_pubkey = nodes[0].node.get_our_node_id(); @@ -11614,24 +14331,49 @@ 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 test_secret = PaymentSecret([43; 32]); let payment_hash = PaymentHash(Sha256::hash(&test_preimage.0).to_byte_array()); - let session_privs = nodes[0].node.test_add_new_pending_payment(payment_hash, - RecipientOnionFields::secret_only(test_secret), PaymentId(payment_hash.0), &route).unwrap(); - nodes[0].node.test_send_payment_internal(&route, payment_hash, - RecipientOnionFields::secret_only(test_secret), Some(test_preimage), - PaymentId(payment_hash.0), None, session_privs).unwrap(); + let session_privs = nodes[0] + .node + .test_add_new_pending_payment( + payment_hash, + RecipientOnionFields::secret_only(test_secret), + PaymentId(payment_hash.0), + &route, + ) + .unwrap(); + nodes[0] + .node + .test_send_payment_internal( + &route, + payment_hash, + RecipientOnionFields::secret_only(test_secret), + Some(test_preimage), + PaymentId(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()); @@ -11640,9 +14382,15 @@ 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].logger.assert_log_contains("lightning::ln::channelmanager", "We don't support MPP keysend payments", 1); + 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", + "We don't support MPP keysend payments", + 1, + ); } #[test] @@ -11652,13 +14400,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(); @@ -11668,13 +14421,22 @@ mod tests { route.paths[1].hops[0].short_channel_id = chan_2_id; route.paths[1].hops[1].short_channel_id = chan_4_id; - match nodes[0].node.send_payment_with_route(&route, payment_hash, - RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)) - .unwrap_err() { + match nodes[0] + .node + .send_payment_with_route( + &route, + payment_hash, + RecipientOnionFields::spontaneous_empty(), + PaymentId(payment_hash.0), + ) + .unwrap_err() + { PaymentSendFailure::ParameterError(APIError::APIMisuseError { ref err }) => { - assert!(regex::Regex::new(r"Payment secret is required for multi-path payments").unwrap().is_match(err)) + assert!(regex::Regex::new(r"Payment secret is required for multi-path payments") + .unwrap() + .is_match(err)) }, - _ => panic!("unexpected error") + _ => panic!("unexpected error"), } } @@ -11690,10 +14452,19 @@ mod tests { 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.2, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id()) + .unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); { // Assert that nodes[1] is awaiting removal for nodes[0] once nodes[1] has been @@ -11721,24 +14492,38 @@ 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()); } #[test] @@ -11751,13 +14536,25 @@ mod tests { 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, 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[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); let channel_id = ChannelId::from_bytes(tx.txid().to_byte_array()); { // Ensure that the `outpoint_to_peer` map is empty until either party has received the @@ -11766,7 +14563,14 @@ mod tests { assert_eq!(nodes[1].node.outpoint_to_peer.lock().unwrap().len(), 0); } - 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(); { // Assert that `nodes[0]`'s `outpoint_to_peer` map is populated with the channel as soon as // as it has the funding transaction. @@ -11777,9 +14581,15 @@ mod tests { assert_eq!(nodes[1].node.outpoint_to_peer.lock().unwrap().len(), 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); + nodes[1] + .node + .handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg); { let nodes_0_lock = nodes[0].node.outpoint_to_peer.lock().unwrap(); assert_eq!(nodes_0_lock.len(), 1); @@ -11795,21 +14605,51 @@ mod tests { assert!(nodes_1_lock.contains_key(&funding_output)); } check_added_monitors!(nodes[1], 1); - 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); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); - let (channel_ready, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); - let (announcement, nodes_0_update, nodes_1_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); - update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &nodes_0_update, &nodes_1_update); + let (channel_ready, _) = + create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); + let (announcement, nodes_0_update, nodes_1_update) = + create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready); + update_nodes_with_chan_announce( + &nodes, + 0, + 1, + &announcement, + &nodes_0_update, + &nodes_1_update, + ); 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())); - let nodes_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(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendShutdown, + nodes[1].node.get_our_node_id() + ), + ); + let nodes_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(), &nodes_1_shutdown); - let closing_signed_node_0 = 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(), &closing_signed_node_0); + let closing_signed_node_0 = 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(), &closing_signed_node_0); { // Assert that the channel is kept in the `outpoint_to_peer` map for both nodes until the // channel can be fully closed by both parties (i.e. no outstanding htlcs exists, the @@ -11830,7 +14670,14 @@ mod tests { assert!(nodes_1_lock.contains_key(&funding_output)); } - 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())); + 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() + ), + ); { // `nodes[0]` accepts `nodes[1]`'s proposed fee for the closing transaction, and // therefore has all it needs to fully close the channel (both signatures for the @@ -11846,32 +14693,59 @@ mod tests { assert!(nodes_1_lock.contains_key(&funding_output)); } - let (_nodes_0_update, closing_signed_node_0) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id()); + let (_nodes_0_update, closing_signed_node_0) = + 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(), &closing_signed_node_0.unwrap()); + nodes[1].node.handle_closing_signed( + &nodes[0].node.get_our_node_id(), + &closing_signed_node_0.unwrap(), + ); { // Assert that the channel has now been removed from both parties `outpoint_to_peer` map once // they both have everything required to fully close the channel. assert_eq!(nodes[1].node.outpoint_to_peer.lock().unwrap().len(), 0); } - let (_nodes_1_update, _none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); + let (_nodes_1_update, _none) = + get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 1000000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 1000000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 1000000 + ); } - 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) } @@ -11905,23 +14779,56 @@ 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]); // 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), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.accept_inbound_channel(&channel_id, &unkown_public_key, 42), + 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), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &unkown_public_key), + unkown_public_key, + ); - check_unkown_peer_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key), unkown_public_key); + check_unkown_peer_error( + nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &unkown_public_key), + 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] @@ -11941,17 +14848,50 @@ mod tests { let channel_id = ChannelId::from_bytes([4; 32]); // Test the API functions. - check_api_misuse_error(nodes[0].node.accept_inbound_channel(&channel_id, &counterparty_node_id, 42)); - - 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, + )); + + 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), channel_id, counterparty_node_id); + check_channel_unavailable_error( + nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id), + channel_id, + counterparty_node_id, + ); - check_channel_unavailable_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id); + check_channel_unavailable_error( + nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id), + 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] @@ -11964,57 +14904,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.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.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.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.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.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, + open_channel_msg.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. @@ -12022,19 +15025,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. @@ -12044,11 +15077,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.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.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.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &last_random_pk).channel_id, + open_channel_msg.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(); @@ -12057,10 +15093,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. @@ -12078,29 +15127,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.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.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.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, + open_channel_msg.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.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, + open_channel_msg.temporary_channel_id + ); } #[test] @@ -12116,57 +15188,105 @@ 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).unwrap(); - } + nodes[1] + .node + .accept_inbound_channel(&temporary_channel_id, &random_pk, 23) + .unwrap(); + }, _ => panic!("Unexpected event"), } get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, random_pk); - open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.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) { - 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, + ) { + 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.temporary_channel_id); + assert_eq!( + get_err_msg(&nodes[1], &last_random_pk).channel_id, + open_channel_msg.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).unwrap(); - } + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &last_random_pk, + 23, + ) + .unwrap(); + }, _ => panic!("Unexpected event"), } get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, last_random_pk); @@ -12186,7 +15306,8 @@ mod tests { payment_metadata: None, keysend_preimage: None, payment_data: Some(msgs::FinalOnionHopData { - payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat, + payment_secret: PaymentSecret([0; 32]), + total_msat: sender_intended_amt_msat, }), custom_tlvs: Vec::new(), }; @@ -12194,49 +15315,82 @@ 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 { err_code, .. }) = - 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, node[0].node.default_configuration.accept_mpp_keysend) - { + 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, + node[0].node.default_configuration.accept_mpp_keysend, + ) { assert_eq!(err_code, 19); - } else { panic!(); } + } else { + panic!(); + } // If amt_received + extra_fee is equal to the sender intended amount, we're fine. - let hop_data = msgs::InboundOnionPayload::Receive { // This is the same payload as above, InboundOnionPayload doesn't implement Clone + let hop_data = msgs::InboundOnionPayload::Receive { + // 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, keysend_preimage: None, payment_data: Some(msgs::FinalOnionHopData { - payment_secret: PaymentSecret([0; 32]), total_msat: sender_intended_amt_msat, + payment_secret: PaymentSecret([0; 32]), + total_msat: sender_intended_amt_msat, }), custom_tlvs: Vec::new(), }; 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, node[0].node.default_configuration.accept_mpp_keysend).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, + node[0].node.default_configuration.accept_mpp_keysend + ) + .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(msgs::InboundOnionPayload::Receive { - sender_intended_htlc_amt_msat: 100, - cltv_expiry_height: 22, - payment_metadata: None, - keysend_preimage: None, - payment_data: Some(msgs::FinalOnionHopData { - payment_secret: PaymentSecret([0; 32]), total_msat: 100, - }), - custom_tlvs: Vec::new(), - }, [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height, - node[0].node.default_configuration.accept_mpp_keysend); + let result = create_recv_pending_htlc_info( + msgs::InboundOnionPayload::Receive { + sender_intended_htlc_amt_msat: 100, + cltv_expiry_height: 22, + payment_metadata: None, + keysend_preimage: None, + payment_data: Some(msgs::FinalOnionHopData { + payment_secret: PaymentSecret([0; 32]), + total_msat: 100, + }), + custom_tlvs: Vec::new(), + }, + [0; 32], + PaymentHash([0; 32]), + 100, + 23, + None, + true, + None, + current_height, + node[0].node.default_configuration.accept_mpp_keysend, + ); // Should not return an error as this condition: // https://github.com/lightning/bolts/blob/4dcc377209509b13cf89a4b91fde7d478f5b46d8/04-onion-routing.md?plain=1#L334 @@ -12256,12 +15410,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()); @@ -12270,22 +15438,29 @@ 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).unwrap(), + Event::OpenChannelRequest { temporary_channel_id, .. } => nodes[2] + .node + .accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 23) + .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] @@ -12298,26 +15473,51 @@ 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); - 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.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 + .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()).unwrap(); - } + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + ) + .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()); + let open_channel_msg = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert!(!open_channel_msg.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx()); // Since nodes[1] should not have accepted the channel, it should @@ -12330,18 +15530,36 @@ 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), Some(user_config)]); + let node_chanmgr = + create_node_chanmgrs(2, &node_cfg, &[Some(user_config), Some(user_config)]); 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] { @@ -12349,16 +15567,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] { @@ -12367,12 +15602,25 @@ 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), - ..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), + ..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 + ); let events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match &events[0] { @@ -12383,19 +15631,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); } @@ -12403,11 +15657,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] @@ -12415,17 +15678,27 @@ 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), Some(user_config)]); + let node_chanmgr = + create_node_chanmgrs(2, &node_cfg, &[Some(user_config), Some(user_config)]); let nodes = create_network(2, &node_cfg, &node_chanmgr); // Open a channel, immediately disconnect each other, and broadcast Alice's latest state. 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()) + .unwrap(); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); { let txn = nodes[0].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -12435,17 +15708,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 @@ -12457,13 +15752,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); @@ -12482,29 +15786,35 @@ 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] }, } + let dummy_failed_htlc = |htlc_id| HTLCForwardInfo::FailHTLC { + htlc_id, + err_packet: msgs::OnionErrorPacket { data: vec![42] }, }; - let dummy_malformed_htlc = |htlc_id| { - HTLCForwardInfo::FailMalformedHTLC { htlc_id, failure_code: 0x4000, sha256_of_onion: [0; 32] } + let dummy_malformed_htlc = |htlc_id| HTLCForwardInfo::FailMalformedHTLC { + htlc_id, + failure_code: 0x4000, + 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 = HashMap::new(); @@ -12515,7 +15825,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() { @@ -12531,21 +15848,24 @@ 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, MessageSendEvent, MessageSendEventsProvider}; - 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::{ChannelMessageHandler, Init}; 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::blockdata::locktime::absolute::LockTime; - use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; + use bitcoin::hashes::Hash; use bitcoin::{Transaction, TxOut}; use crate::sync::{Arc, Mutex, RwLock}; @@ -12553,29 +15873,52 @@ pub mod bench { 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::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::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. @@ -12586,64 +15929,148 @@ pub mod bench { let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let logger_a = test_utils::TestLogger::with_id("node a".to_owned()); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(Arc::new(NetworkGraph::new(network, &logger_a)), &logger_a, &scorer); + let router = test_utils::TestRouter::new( + Arc::new(NetworkGraph::new(network, &logger_a)), + &logger_a, + &scorer, + ); 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, &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, + &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, &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, + &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: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 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: 2, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { value: 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"), @@ -12655,13 +16082,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!(), } @@ -12673,7 +16111,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"), @@ -12682,7 +16120,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"), @@ -12691,52 +16129,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(&$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( + &$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(&$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, 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(&$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( + &$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(&$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/features.rs b/lightning/src/ln/features.rs index 79f869a4c58..4aac35a908e 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -76,21 +76,21 @@ //! [BOLT #9]: https://github.com/lightning/bolts/blob/master/09-features.md //! [messages]: crate::ln::msgs -use crate::{io, io_extras}; use crate::prelude::*; -use core::{cmp, fmt}; +use crate::{io, io_extras}; use core::borrow::Borrow; use core::hash::{Hash, Hasher}; use core::marker::PhantomData; +use core::{cmp, fmt}; -use bitcoin::bech32; -use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5, WriteBase32}; use crate::ln::msgs::DecodeError; use crate::util::ser::{Readable, WithoutLength, Writeable, Writer}; +use bitcoin::bech32; +use bitcoin::bech32::{u5, Base32Len, FromBase32, ToBase32, WriteBase32}; mod sealed { - use crate::prelude::*; use crate::ln::features::Features; + use crate::prelude::*; /// The context in which [`Features`] are applicable. Defines which features are known to the /// implementation, though specification of them as required or optional is up to the code @@ -137,38 +137,44 @@ mod sealed { }; } - define_context!(InitContext, [ - // Byte 0 - DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries, - // Byte 1 - VariableLengthOnion | StaticRemoteKey | PaymentSecret, - // Byte 2 - BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx, - // Byte 3 - RouteBlinding | ShutdownAnySegwit | Taproot, - // Byte 4 - OnionMessages, - // Byte 5 - ChannelType | SCIDPrivacy, - // Byte 6 - ZeroConf, - ]); - define_context!(NodeContext, [ - // Byte 0 - DataLossProtect | UpfrontShutdownScript | GossipQueries, - // Byte 1 - VariableLengthOnion | StaticRemoteKey | PaymentSecret, - // Byte 2 - BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx, - // Byte 3 - RouteBlinding | ShutdownAnySegwit | Taproot, - // Byte 4 - OnionMessages, - // Byte 5 - ChannelType | SCIDPrivacy, - // Byte 6 - ZeroConf | Keysend, - ]); + define_context!( + InitContext, + [ + // Byte 0 + DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries, + // Byte 1 + VariableLengthOnion | StaticRemoteKey | PaymentSecret, + // Byte 2 + BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx, + // Byte 3 + RouteBlinding | ShutdownAnySegwit | Taproot, + // Byte 4 + OnionMessages, + // Byte 5 + ChannelType | SCIDPrivacy, + // Byte 6 + ZeroConf, + ] + ); + define_context!( + NodeContext, + [ + // Byte 0 + DataLossProtect | UpfrontShutdownScript | GossipQueries, + // Byte 1 + VariableLengthOnion | StaticRemoteKey | PaymentSecret, + // Byte 2 + BasicMPP | Wumbo | AnchorsNonzeroFeeHtlcTx | AnchorsZeroFeeHtlcTx, + // Byte 3 + RouteBlinding | ShutdownAnySegwit | Taproot, + // Byte 4 + OnionMessages, + // Byte 5 + ChannelType | SCIDPrivacy, + // Byte 6 + ZeroConf | Keysend, + ] + ); define_context!(ChannelContext, []); define_context!(Bolt11InvoiceContext, [ // Byte 0 @@ -357,76 +363,213 @@ mod sealed { } } - define_feature!(1, DataLossProtect, [InitContext, NodeContext], - "Feature flags for `option_data_loss_protect`.", set_data_loss_protect_optional, - set_data_loss_protect_required, supports_data_loss_protect, requires_data_loss_protect); + define_feature!( + 1, + DataLossProtect, + [InitContext, NodeContext], + "Feature flags for `option_data_loss_protect`.", + set_data_loss_protect_optional, + set_data_loss_protect_required, + supports_data_loss_protect, + requires_data_loss_protect + ); // NOTE: Per Bolt #9, initial_routing_sync has no even bit. - define_feature!(3, InitialRoutingSync, [InitContext], "Feature flags for `initial_routing_sync`.", - set_initial_routing_sync_optional, set_initial_routing_sync_required, - initial_routing_sync); - define_feature!(5, UpfrontShutdownScript, [InitContext, NodeContext], - "Feature flags for `option_upfront_shutdown_script`.", set_upfront_shutdown_script_optional, - set_upfront_shutdown_script_required, supports_upfront_shutdown_script, - requires_upfront_shutdown_script); - define_feature!(7, GossipQueries, [InitContext, NodeContext], - "Feature flags for `gossip_queries`.", set_gossip_queries_optional, set_gossip_queries_required, - supports_gossip_queries, requires_gossip_queries); - define_feature!(9, VariableLengthOnion, [InitContext, NodeContext, Bolt11InvoiceContext], - "Feature flags for `var_onion_optin`.", set_variable_length_onion_optional, - set_variable_length_onion_required, supports_variable_length_onion, - requires_variable_length_onion); - define_feature!(13, StaticRemoteKey, [InitContext, NodeContext, ChannelTypeContext], - "Feature flags for `option_static_remotekey`.", set_static_remote_key_optional, - set_static_remote_key_required, supports_static_remote_key, requires_static_remote_key); - define_feature!(15, PaymentSecret, [InitContext, NodeContext, Bolt11InvoiceContext], - "Feature flags for `payment_secret`.", set_payment_secret_optional, set_payment_secret_required, - supports_payment_secret, requires_payment_secret); - define_feature!(17, BasicMPP, [InitContext, NodeContext, Bolt11InvoiceContext, Bolt12InvoiceContext], - "Feature flags for `basic_mpp`.", set_basic_mpp_optional, set_basic_mpp_required, - supports_basic_mpp, requires_basic_mpp); - define_feature!(19, Wumbo, [InitContext, NodeContext], - "Feature flags for `option_support_large_channel` (aka wumbo channels).", set_wumbo_optional, set_wumbo_required, - supports_wumbo, requires_wumbo); - define_feature!(21, AnchorsNonzeroFeeHtlcTx, [InitContext, NodeContext, ChannelTypeContext], - "Feature flags for `option_anchors_nonzero_fee_htlc_tx`.", set_anchors_nonzero_fee_htlc_tx_optional, - set_anchors_nonzero_fee_htlc_tx_required, supports_anchors_nonzero_fee_htlc_tx, requires_anchors_nonzero_fee_htlc_tx); - define_feature!(23, AnchorsZeroFeeHtlcTx, [InitContext, NodeContext, ChannelTypeContext], - "Feature flags for `option_anchors_zero_fee_htlc_tx`.", set_anchors_zero_fee_htlc_tx_optional, - set_anchors_zero_fee_htlc_tx_required, supports_anchors_zero_fee_htlc_tx, requires_anchors_zero_fee_htlc_tx); - define_feature!(25, RouteBlinding, [InitContext, NodeContext], - "Feature flags for `option_route_blinding`.", set_route_blinding_optional, - set_route_blinding_required, supports_route_blinding, requires_route_blinding); - define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext], - "Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional, - set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit); - define_feature!(31, Taproot, [InitContext, NodeContext, ChannelTypeContext], - "Feature flags for `option_taproot`.", set_taproot_optional, - set_taproot_required, supports_taproot, requires_taproot); - define_feature!(39, OnionMessages, [InitContext, NodeContext], - "Feature flags for `option_onion_messages`.", set_onion_messages_optional, - set_onion_messages_required, supports_onion_messages, requires_onion_messages); - define_feature!(45, ChannelType, [InitContext, NodeContext], - "Feature flags for `option_channel_type`.", set_channel_type_optional, - set_channel_type_required, supports_channel_type, requires_channel_type); + define_feature!( + 3, + InitialRoutingSync, + [InitContext], + "Feature flags for `initial_routing_sync`.", + set_initial_routing_sync_optional, + set_initial_routing_sync_required, + initial_routing_sync + ); + define_feature!( + 5, + UpfrontShutdownScript, + [InitContext, NodeContext], + "Feature flags for `option_upfront_shutdown_script`.", + set_upfront_shutdown_script_optional, + set_upfront_shutdown_script_required, + supports_upfront_shutdown_script, + requires_upfront_shutdown_script + ); + define_feature!( + 7, + GossipQueries, + [InitContext, NodeContext], + "Feature flags for `gossip_queries`.", + set_gossip_queries_optional, + set_gossip_queries_required, + supports_gossip_queries, + requires_gossip_queries + ); + define_feature!( + 9, + VariableLengthOnion, + [InitContext, NodeContext, Bolt11InvoiceContext], + "Feature flags for `var_onion_optin`.", + set_variable_length_onion_optional, + set_variable_length_onion_required, + supports_variable_length_onion, + requires_variable_length_onion + ); + define_feature!( + 13, + StaticRemoteKey, + [InitContext, NodeContext, ChannelTypeContext], + "Feature flags for `option_static_remotekey`.", + set_static_remote_key_optional, + set_static_remote_key_required, + supports_static_remote_key, + requires_static_remote_key + ); + define_feature!( + 15, + PaymentSecret, + [InitContext, NodeContext, Bolt11InvoiceContext], + "Feature flags for `payment_secret`.", + set_payment_secret_optional, + set_payment_secret_required, + supports_payment_secret, + requires_payment_secret + ); + define_feature!( + 17, + BasicMPP, + [InitContext, NodeContext, Bolt11InvoiceContext, Bolt12InvoiceContext], + "Feature flags for `basic_mpp`.", + set_basic_mpp_optional, + set_basic_mpp_required, + supports_basic_mpp, + requires_basic_mpp + ); + define_feature!( + 19, + Wumbo, + [InitContext, NodeContext], + "Feature flags for `option_support_large_channel` (aka wumbo channels).", + set_wumbo_optional, + set_wumbo_required, + supports_wumbo, + requires_wumbo + ); + define_feature!( + 21, + AnchorsNonzeroFeeHtlcTx, + [InitContext, NodeContext, ChannelTypeContext], + "Feature flags for `option_anchors_nonzero_fee_htlc_tx`.", + set_anchors_nonzero_fee_htlc_tx_optional, + set_anchors_nonzero_fee_htlc_tx_required, + supports_anchors_nonzero_fee_htlc_tx, + requires_anchors_nonzero_fee_htlc_tx + ); + define_feature!( + 23, + AnchorsZeroFeeHtlcTx, + [InitContext, NodeContext, ChannelTypeContext], + "Feature flags for `option_anchors_zero_fee_htlc_tx`.", + set_anchors_zero_fee_htlc_tx_optional, + set_anchors_zero_fee_htlc_tx_required, + supports_anchors_zero_fee_htlc_tx, + requires_anchors_zero_fee_htlc_tx + ); + define_feature!( + 25, + RouteBlinding, + [InitContext, NodeContext], + "Feature flags for `option_route_blinding`.", + set_route_blinding_optional, + set_route_blinding_required, + supports_route_blinding, + requires_route_blinding + ); + define_feature!( + 27, + ShutdownAnySegwit, + [InitContext, NodeContext], + "Feature flags for `opt_shutdown_anysegwit`.", + set_shutdown_any_segwit_optional, + set_shutdown_any_segwit_required, + supports_shutdown_anysegwit, + requires_shutdown_anysegwit + ); + define_feature!( + 31, + Taproot, + [InitContext, NodeContext, ChannelTypeContext], + "Feature flags for `option_taproot`.", + set_taproot_optional, + set_taproot_required, + supports_taproot, + requires_taproot + ); + define_feature!( + 39, + OnionMessages, + [InitContext, NodeContext], + "Feature flags for `option_onion_messages`.", + set_onion_messages_optional, + set_onion_messages_required, + supports_onion_messages, + requires_onion_messages + ); + define_feature!( + 45, + ChannelType, + [InitContext, NodeContext], + "Feature flags for `option_channel_type`.", + set_channel_type_optional, + set_channel_type_required, + supports_channel_type, + requires_channel_type + ); define_feature!(47, SCIDPrivacy, [InitContext, NodeContext, ChannelTypeContext], "Feature flags for only forwarding with SCID aliasing. Called `option_scid_alias` in the BOLTs", set_scid_privacy_optional, set_scid_privacy_required, supports_scid_privacy, requires_scid_privacy); - define_feature!(49, PaymentMetadata, [Bolt11InvoiceContext], - "Feature flags for payment metadata in invoices.", set_payment_metadata_optional, - set_payment_metadata_required, supports_payment_metadata, requires_payment_metadata); + define_feature!( + 49, + PaymentMetadata, + [Bolt11InvoiceContext], + "Feature flags for payment metadata in invoices.", + set_payment_metadata_optional, + set_payment_metadata_required, + supports_payment_metadata, + requires_payment_metadata + ); define_feature!(51, ZeroConf, [InitContext, NodeContext, ChannelTypeContext], "Feature flags for accepting channels with zero confirmations. Called `option_zeroconf` in the BOLTs", set_zero_conf_optional, set_zero_conf_required, supports_zero_conf, requires_zero_conf); - define_feature!(55, Keysend, [NodeContext], - "Feature flags for keysend payments.", set_keysend_optional, set_keysend_required, - supports_keysend, requires_keysend); + define_feature!( + 55, + Keysend, + [NodeContext], + "Feature flags for keysend payments.", + set_keysend_optional, + set_keysend_required, + supports_keysend, + requires_keysend + ); // Note: update the module-level docs when a new feature bit is added! #[cfg(test)] - define_feature!(123456789, UnknownFeature, - [NodeContext, ChannelContext, Bolt11InvoiceContext, OfferContext, InvoiceRequestContext, Bolt12InvoiceContext, BlindedHopContext], - "Feature flags for an unknown feature used in testing.", set_unknown_feature_optional, - set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature); + define_feature!( + 123456789, + UnknownFeature, + [ + NodeContext, + ChannelContext, + Bolt11InvoiceContext, + OfferContext, + InvoiceRequestContext, + Bolt12InvoiceContext, + BlindedHopContext + ], + "Feature flags for an unknown feature used in testing.", + set_unknown_feature_optional, + set_unknown_feature_required, + supports_unknown_test_feature, + requires_unknown_test_feature + ); } /// Tracks the set of features which a node implements, templated by the context in which it @@ -461,10 +604,7 @@ impl core::ops::BitOr for Features { impl Clone for Features { fn clone(&self) -> Self { - Self { - flags: self.flags.clone(), - mark: PhantomData, - } + Self { flags: self.flags.clone(), mark: PhantomData } } } impl Hash for Features { @@ -482,8 +622,16 @@ impl PartialEq for Features { let mut self_iter = self.flags.iter(); loop { match (o_iter.next(), self_iter.next()) { - (Some(o), Some(us)) => if o != us { return false }, - (Some(b), None) | (None, Some(b)) => if *b != 0 { return false }, + (Some(o), Some(us)) => { + if o != us { + return false; + } + }, + (Some(b), None) | (None, Some(b)) => { + if *b != 0 { + return false; + } + }, (None, None) => return true, } } @@ -619,7 +767,9 @@ impl ChannelTypeFeatures { pub(crate) fn anchors_zero_htlc_fee_and_dependencies() -> Self { let mut ret = Self::empty(); ::set_required_bit(&mut ret.flags); - ::set_required_bit(&mut ret.flags); + ::set_required_bit( + &mut ret.flags, + ); ret } } @@ -636,14 +786,19 @@ impl ToBase32 for Bolt11InvoiceFeatures { let new_bit_pos = bit_pos_from_left_0_indexed % 5; let shifted_chunk_u16 = (*byte as u16) << new_bit_pos; let curr_u5_as_u8 = res_u5s[new_u5_idx].to_u8(); - res_u5s[new_u5_idx] = u5::try_from_u8(curr_u5_as_u8 | ((shifted_chunk_u16 & 0x001f) as u8)).unwrap(); + res_u5s[new_u5_idx] = + u5::try_from_u8(curr_u5_as_u8 | ((shifted_chunk_u16 & 0x001f) as u8)).unwrap(); if new_u5_idx > 0 { let curr_u5_as_u8 = res_u5s[new_u5_idx - 1].to_u8(); - res_u5s[new_u5_idx - 1] = u5::try_from_u8(curr_u5_as_u8 | (((shifted_chunk_u16 >> 5) & 0x001f) as u8)).unwrap(); + res_u5s[new_u5_idx - 1] = + u5::try_from_u8(curr_u5_as_u8 | (((shifted_chunk_u16 >> 5) & 0x001f) as u8)) + .unwrap(); } if new_u5_idx > 1 { let curr_u5_as_u8 = res_u5s[new_u5_idx - 2].to_u8(); - res_u5s[new_u5_idx - 2] = u5::try_from_u8(curr_u5_as_u8 | (((shifted_chunk_u16 >> 10) & 0x001f) as u8)).unwrap(); + res_u5s[new_u5_idx - 2] = + u5::try_from_u8(curr_u5_as_u8 | (((shifted_chunk_u16 >> 10) & 0x001f) as u8)) + .unwrap(); } } // Trim the highest feature bits. @@ -675,7 +830,7 @@ impl FromBase32 for Bolt11InvoiceFeatures { let chunk_u16 = chunk.to_u8() as u16; res_bytes[new_byte_idx] |= ((chunk_u16 << new_bit_pos) & 0xff) as u8; if new_byte_idx != length_bytes - 1 { - res_bytes[new_byte_idx + 1] |= ((chunk_u16 >> (8-new_bit_pos)) & 0xff) as u8; + res_bytes[new_byte_idx + 1] |= ((chunk_u16 >> (8 - new_bit_pos)) & 0xff) as u8; } } // Trim the highest feature bits. @@ -689,10 +844,7 @@ impl FromBase32 for Bolt11InvoiceFeatures { impl Features { /// Create a blank Features with no features set pub fn empty() -> Self { - Features { - flags: Vec::new(), - mark: PhantomData, - } + Features { flags: Vec::new(), mark: PhantomData } } /// Converts `Features` to `Features`. Only known `T` features relevant to context `C` are @@ -708,7 +860,7 @@ impl Features { flags.push(byte & from_known_features & to_known_features); } } - Features:: { flags, mark: PhantomData, } + Features:: { flags, mark: PhantomData } } /// Create a Features given a set of flags, in little-endian. This is in reverse byte order from @@ -716,10 +868,7 @@ impl Features { /// /// This is not exported to bindings users as we don't support export across multiple T pub fn from_le_bytes(flags: Vec) -> Features { - Features { - flags, - mark: PhantomData, - } + Features { flags, mark: PhantomData } } #[cfg(test)] @@ -729,7 +878,8 @@ impl Features { } fn write_be(&self, w: &mut W) -> Result<(), io::Error> { - for f in self.flags.iter().rev() { // Swap back to big-endian + for f in self.flags.iter().rev() { + // Swap back to big-endian f.write(w)?; } Ok(()) @@ -741,10 +891,7 @@ impl Features { /// This is not exported to bindings users as we don't support export across multiple T pub fn from_be_bytes(mut flags: Vec) -> Features { flags.reverse(); // Swap to little-endian - Self { - flags, - mark: PhantomData, - } + Self { flags, mark: PhantomData } } pub(crate) fn supports_any_optional_bits(&self) -> bool { @@ -778,11 +925,8 @@ impl Features { let byte_count = T::KNOWN_FEATURE_MASK.len(); self.flags.iter().enumerate().any(|(i, &byte)| { let required_features = 0b01_01_01_01; - let unknown_features = if i < byte_count { - !T::KNOWN_FEATURE_MASK[i] - } else { - 0b11_11_11_11 - }; + let unknown_features = + if i < byte_count { !T::KNOWN_FEATURE_MASK[i] } else { 0b11_11_11_11 }; (byte & (required_features & unknown_features)) != 0 }) } @@ -792,11 +936,8 @@ impl Features { // both required and optional unknown features. let byte_count = T::KNOWN_FEATURE_MASK.len(); self.flags.iter().enumerate().any(|(i, &byte)| { - let unknown_features = if i < byte_count { - !T::KNOWN_FEATURE_MASK[i] - } else { - 0b11_11_11_11 - }; + let unknown_features = + if i < byte_count { !T::KNOWN_FEATURE_MASK[i] } else { 0b11_11_11_11 }; (byte & unknown_features) != 0 }) } @@ -961,7 +1102,7 @@ macro_rules! impl_feature_len_prefixed_write { Ok(Self::from_be_bytes(Vec::::read(r)?)) } } - } + }; } impl_feature_len_prefixed_write!(InitFeatures); impl_feature_len_prefixed_write!(ChannelFeatures); @@ -983,7 +1124,7 @@ macro_rules! impl_feature_tlv_write { Ok(WithoutLength::::read(r)?.0) } } - } + }; } impl_feature_tlv_write!(ChannelTypeFeatures); @@ -1006,9 +1147,12 @@ impl Readable for WithoutLength> { #[cfg(test)] mod tests { - use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, Bolt11InvoiceFeatures, NodeFeatures, OfferFeatures, sealed}; - use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, u5}; + use super::{ + sealed, Bolt11InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, + NodeFeatures, OfferFeatures, + }; use crate::util::ser::{Readable, WithoutLength, Writeable}; + use bitcoin::bech32::{u5, Base32Len, FromBase32, ToBase32}; #[test] fn sanity_test_unknown_bits() { @@ -1121,8 +1265,10 @@ mod tests { #[test] fn convert_to_context_with_unknown_flags() { // Ensure the `from` context has fewer known feature bytes than the `to` context. - assert!(::KNOWN_FEATURE_MASK.len() < - ::KNOWN_FEATURE_MASK.len()); + assert!( + ::KNOWN_FEATURE_MASK.len() + < ::KNOWN_FEATURE_MASK.len() + ); let mut channel_features = ChannelFeatures::empty(); channel_features.set_unknown_feature_optional(); assert!(channel_features.supports_unknown_bits()); diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index e7fc68924ef..e27afa6c701 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -10,30 +10,40 @@ //! 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, chainmonitor::Persist}; use crate::chain::channelmonitor::ChannelMonitor; use crate::chain::transaction::OutPoint; -use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, PaymentFailureReason}; -use crate::events::bump_transaction::{BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource}; -use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret}; -use crate::ln::channelmanager::{AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA}; +use crate::chain::{ + chainmonitor::Persist, BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch, +}; +use crate::events::bump_transaction::{ + BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource, +}; +use crate::events::{ + ClaimedHTLC, ClosureReason, Event, HTLCDestination, MessageSendEvent, + MessageSendEventsProvider, PathFailure, PaymentFailureReason, PaymentPurpose, +}; +use crate::ln::channelmanager::{ + AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, PaymentId, + PaymentSendFailure, RAACommitmentOrder, RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::features::InitFeatures; use crate::ln::msgs; use crate::ln::msgs::{ChannelMessageHandler, OnionMessageHandler, RoutingMessageHandler}; use crate::ln::peer_handler::IgnoringMessageHandler; +use crate::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use crate::onion_message::messenger::OnionMessenger; -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::util::config::{UserConfig, MaxDustHTLCExposure}; +use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::errors::APIError; #[cfg(test)] use crate::util::logger::Logger; use crate::util::scid_utils; +use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_channel_signer::TestChannelSigner; use crate::util::test_utils; -use crate::util::test_utils::{panicking, TestChainMonitor, TestScorer, TestKeysInterface}; -use crate::util::ser::{ReadableArgs, Writeable}; +use crate::util::test_utils::{panicking, TestChainMonitor, TestKeysInterface, TestScorer}; use bitcoin::blockdata::block::{Block, Header, Version}; use bitcoin::blockdata::locktime::absolute::LockTime; @@ -45,14 +55,14 @@ use bitcoin::network::constants::Network; use bitcoin::pow::CompactTarget; use bitcoin::secp256k1::{PublicKey, SecretKey}; +use crate::io; +use crate::prelude::*; +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::sync::{Arc, Mutex, LockTestExt, RwLock}; pub const CHAN_CONFIRM_DEPTH: u32 = 10; @@ -81,7 +91,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 { @@ -94,8 +106,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: 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: 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); @@ -105,15 +123,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: 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: 0, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }); } for tx in txn { txdata.push((*tx).clone()); @@ -122,7 +148,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) } @@ -190,7 +218,8 @@ impl ConnectStyle { } fn random_style() -> ConnectStyle { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { use core::hash::{BuildHasher, Hasher}; // Get a random value using the only std API to do so - the DefaultHasher let rand_val = std::collections::hash_map::RandomState::new().build_hasher().finish(); @@ -209,7 +238,8 @@ impl ConnectStyle { eprintln!("Using Block Connection Style: {:?}", res); res } - #[cfg(not(feature = "std"))] { + #[cfg(not(feature = "std"))] + { ConnectStyle::FullBlockViaListen } } @@ -253,21 +283,33 @@ pub fn connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block) fn call_claimable_balances<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) { // Ensure `get_claimable_balances`' self-tests never panic for (funding_outpoint, _channel_id) in node.chain_monitor.chain_monitor.list_monitors() { - node.chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances(); + node.chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances(); } } -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; - #[cfg(feature = "std")] { - eprintln!("Connecting block using Block Connection Style: {:?}", *node.connect_style.borrow()); + #[cfg(feature = "std")] + { + 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 // transaction broadcast are correct. @@ -275,17 +317,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() { @@ -300,13 +352,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); @@ -316,7 +381,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); - } + }, } } @@ -336,8 +401,13 @@ 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); - #[cfg(feature = "std")] { - eprintln!("Disconnecting {} blocks using Block Connection Style: {:?}", count, *node.connect_style.borrow()); + #[cfg(feature = "std")] + { + 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(); @@ -349,14 +419,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.txid()); node.node.transaction_unconfirmed(&tx.txid()); @@ -428,7 +501,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> { @@ -441,7 +516,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>, @@ -460,8 +539,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) + }) } } @@ -486,16 +566,21 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> { /// several of the signing methods. Currently, only `get_per_commitment_point` and /// `release_commitment_secret` are affected by this setting. #[cfg(test)] - pub fn set_channel_signer_available(&self, peer_id: &PublicKey, chan_id: &ChannelId, available: bool) { + pub fn set_channel_signer_available( + &self, peer_id: &PublicKey, chan_id: &ChannelId, available: bool, + ) { let per_peer_state = self.node.per_peer_state.read().unwrap(); let chan_lock = per_peer_state.get(peer_id).unwrap().lock().unwrap(); - let signer = (|| { - match chan_lock.channel_by_id.get(chan_id) { - Some(phase) => phase.context().get_signer(), - None => panic!("Couldn't find a channel with id {}", chan_id), - } + let signer = (|| match chan_lock.channel_by_id.get(chan_id) { + Some(phase) => phase.context().get_signer(), + None => panic!("Couldn't find a channel with id {}", chan_id), })(); - 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 + ); signer.as_ecdsa().unwrap().set_available(available); } } @@ -513,10 +598,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, @@ -524,12 +610,15 @@ pub trait NodeHolder { ::SP, ::F, ::R, - ::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, @@ -537,13 +626,22 @@ impl NodeHolder for &H { ::SP, ::F, ::R, - ::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> { @@ -560,22 +658,28 @@ 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 + ); } // 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, @@ -584,8 +688,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), @@ -603,15 +709,26 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { { for (outpoint, _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(outpoint).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(outpoint) + .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())), }; @@ -626,67 +743,115 @@ 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::TestLogger>)>::read(&mut io::Cursor::new(w.0), ChannelManagerReadArgs { - default_config: *self.node.get_current_default_configuration(), - entropy_source: self.keys_manager, - node_signer: self.keys_manager, - signer_provider: self.keys_manager, - fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, - router: &test_utils::TestRouter::new(Arc::new(network_graph), &self.logger, &scorer), - 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::TestLogger, + >, + )>::read( + &mut io::Cursor::new(w.0), + ChannelManagerReadArgs { + default_config: *self.node.get_current_default_configuration(), + entropy_source: self.keys_manager, + node_signer: self.keys_manager, + signer_provider: self.keys_manager, + fee_estimator: &test_utils::TestFeeEstimator { + sat_per_kw: Mutex::new(253), + }, + router: &test_utils::TestRouter::new( + Arc::new(network_graph), + &self.logger, + &scorer, + ), + 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 funding_outpoint = deserialized_monitor.get_funding_txo().0; - if chain_monitor.watch_channel(funding_outpoint, deserialized_monitor) != Ok(ChannelMonitorUpdateStatus::Completed) { + if chain_monitor.watch_channel(funding_outpoint, 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, msgs::CommitmentSigned) { +pub fn get_revoke_commit_msgs>( + node: &H, recipient: &PublicKey, +) -> (msgs::RevokeAndACK, msgs::CommitmentSigned) { 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 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()); - updates.commitment_signed.clone() + match events[1] { + MessageSendEvent::UpdateHTLCs { ref node_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()); + updates.commitment_signed.clone() + }, + _ => panic!("Unexpected event"), }, - _ => panic!("Unexpected event"), - }) + ) } #[macro_export] @@ -696,25 +861,23 @@ pub fn get_revoke_commit_msgs>(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"), - } + ($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"), } - } + }}; } /// Get an error message from the pending events queue. @@ -723,13 +886,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() @@ -741,19 +906,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 @@ -776,7 +937,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. @@ -785,117 +946,47 @@ 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::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::SendSplice { 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::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::SendSplice { 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 { @@ -905,70 +996,78 @@ pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &mut #[cfg(test)] 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(test)] macro_rules! get_feerate { - ($node: expr, $counterparty_node: expr, $channel_id: expr) => { - { - let mut per_peer_state_lock; - let mut peer_state_lock; - let phase = get_channel_ref!($node, $counterparty_node, per_peer_state_lock, peer_state_lock, $channel_id); - phase.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 phase = get_channel_ref!( + $node, + $counterparty_node, + per_peer_state_lock, + peer_state_lock, + $channel_id + ); + phase.context().get_feerate_sat_per_1000_weight() + }}; } #[cfg(test)] 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.context().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.context().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) => { - { - use bitcoin::hashes::Hash; - let mut monitor = None; - // Assume funding vout is either 0 or 1 blindly - for index in 0..2 { - if let Ok(mon) = $node.chain_monitor.chain_monitor.get_monitor( - $crate::chain::transaction::OutPoint { - txid: bitcoin::Txid::from_slice(&$channel_id.0[..]).unwrap(), index - }) - { - monitor = Some(mon); - break; - } + ($node: expr, $channel_id: expr) => {{ + use bitcoin::hashes::Hash; + let mut monitor = None; + // Assume funding vout is either 0 or 1 blindly + for index in 0..2 { + if let Ok(mon) = $node.chain_monitor.chain_monitor.get_monitor( + $crate::chain::transaction::OutPoint { + txid: bitcoin::Txid::from_slice(&$channel_id.0[..]).unwrap(), + index, + }, + ) { + monitor = Some(mon); + break; } - monitor.unwrap() } - } + monitor.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. @@ -979,31 +1078,33 @@ macro_rules! unwrap_send_err { &Err(PaymentSendFailure::AllFailedResendSafe(ref fails)) if $all_failed => { assert_eq!(fails.len(), 1); match fails[0] { - $type => { $check }, + $type => $check, _ => panic!(), } }, &Err(PaymentSendFailure::PartialFailure { ref results, .. }) if !$all_failed => { assert_eq!(results.len(), 1); match results[0] { - Err($type) => { $check }, + Err($type) => $check, _ => panic!(), } }, &Err(PaymentSendFailure::PathParameterError(ref result)) if !$all_failed => { assert_eq!(result.len(), 1); match result[0] { - Err($type) => { $check }, + Err($type) => $check, _ => panic!(), } }, - _ => {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(); @@ -1019,30 +1120,40 @@ 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); - } + }; } /// Checks whether the claimed HTLC for the specified path has the correct channel information. /// /// This will panic if the path is empty, if the HTLC's channel ID is not actually a channel that /// connects the final two nodes in the path, or if the `user_channel_id` is incorrect. -pub fn check_claimed_htlc_channel<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], htlc: &ClaimedHTLC) { +pub fn check_claimed_htlc_channel<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], htlc: &ClaimedHTLC, +) { 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"); assert_eq!(htlc.user_channel_id, ch.user_channel_id); assert_eq!(ch.counterparty.node_id, prev.get_our_node_id()); } -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); } @@ -1053,25 +1164,31 @@ pub fn _reload_node<'a, 'b, 'c>(node: &'a Node<'a, 'b, 'c>, default_config: User for monitor in monitors_read.iter_mut() { assert!(channel_monitors.insert(monitor.get_funding_txo().0, 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, - 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, + 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 funding_outpoint = monitor.get_funding_txo().0; - assert_eq!(node.chain_monitor.watch_channel(funding_outpoint, monitor), - Ok(ChannelMonitorUpdateStatus::Completed)); + assert_eq!( + node.chain_monitor.watch_channel(funding_outpoint, monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); check_added_monitors!(node, 1); } @@ -1084,57 +1201,95 @@ macro_rules! reload_node { let chanman_encoded = $chanman_encoded; $persister = test_utils::TestPersister::new(); - $new_chain_monitor = test_utils::TestChainMonitor::new(Some($node.chain_source), $node.tx_broadcaster.clone(), $node.logger, $node.fee_estimator, &$persister, &$node.keys_manager); + $new_chain_monitor = 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: chan_id as i32, lock_time: LockTime::ZERO, input, output: vec![TxOut { - value: *channel_value_satoshis, script_pubkey: output_script.clone(), - }]}; + let tx = Transaction { + version: chan_id as i32, + lock_time: LockTime::ZERO, + input, + output: vec![TxOut { + value: *channel_value_satoshis, + script_pubkey: output_script.clone(), + }], + }; let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 }; (*temporary_channel_id, tx, funding_outpoint) }, @@ -1142,14 +1297,26 @@ fn internal_create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, } } -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, funding_output) = 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, funding_output) = + 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); node_b.node.handle_funding_created(&node_a.node.get_our_node_id(), &funding_created_msg); { @@ -1160,7 +1327,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); @@ -1177,7 +1347,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); @@ -1185,30 +1362,70 @@ 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).unwrap(); + receiver + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &initiator.node.get_our_node_id(), + 0, + ) + .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.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); @@ -1224,10 +1441,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] { @@ -1235,15 +1459,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); @@ -1254,69 +1486,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.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).unwrap(), + Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, .. } => node_b + .node + .accept_inbound_channel(temporary_channel_id, counterparty_node_id, 42) + .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.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())); -} - -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) { + 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) { 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); @@ -1324,15 +1609,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(); @@ -1344,14 +1638,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 }, @@ -1364,31 +1663,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 = test_default_channel_config(); no_announce_cfg.channel_handshake_config.announced_channel = 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); @@ -1399,18 +1749,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); @@ -1438,7 +1808,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 { assert!(node.gossip_sync.handle_channel_announcement(ann).unwrap()); node.gossip_sync.handle_channel_update(upd_1).unwrap(); @@ -1451,9 +1824,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.dust_value().to_sat(), "Spending tx output didn't meet dust limit"); + assert!( + outp.value >= outp.script_pubkey.dust_value().to_sat(), + "Spending tx output didn't meet dust limit" + ); } let mut total_value_in = 0; for input in tx.input.iter() { @@ -1464,7 +1842,7 @@ pub fn do_check_spends Opti total_value_out += output.value; } 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(); } @@ -1492,17 +1870,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.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); @@ -1510,9 +1889,11 @@ macro_rules! get_closing_signed_broadcast { }, _ => panic!("Unexpected event"), } - } else { None }) - } - } + } else { + None + }, + ) + }}; } #[cfg(test)] @@ -1521,40 +1902,54 @@ 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"), } - }} + }}; } /// 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 msg_events = node.node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), if with_error_msg { num_channels * 2 } else { num_channels }); - msg_events.into_iter().filter_map(|msg_event| { - match msg_event { - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - assert_eq!(msg.contents.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.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 @@ -1565,7 +1960,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)] @@ -1580,7 +1975,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), @@ -1624,30 +2021,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()); } @@ -1657,12 +2060,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) { @@ -1671,8 +2087,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!(), @@ -1680,13 +2098,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); @@ -1716,10 +2148,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()); @@ -1728,14 +2168,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()); @@ -1756,17 +2205,25 @@ pub struct SendEvent { pub commitment_msg: msgs::CommitmentSigned, } impl SendEvent { - pub fn from_commitment_update(node_id: PublicKey, updates: msgs::CommitmentUpdate) -> SendEvent { + pub fn from_commitment_update( + node_id: PublicKey, 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, msgs: updates.update_add_htlcs, commitment_msg: updates.commitment_signed } + SendEvent { + node_id, + msgs: updates.update_add_htlcs, + commitment_msg: updates.commitment_signed, + } } pub fn from_event(event: MessageSendEvent) -> SendEvent { match event { - MessageSendEvent::UpdateHTLCs { node_id, updates } => SendEvent::from_commitment_update(node_id, updates), + MessageSendEvent::UpdateHTLCs { node_id, updates } => { + SendEvent::from_commitment_update(node_id, updates) + }, _ => panic!("Unexpected event type!"), } } @@ -1782,8 +2239,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] @@ -1791,22 +2251,26 @@ macro_rules! expect_htlc_handling_failed_destinations { ($events: expr, $expected_failures: expr) => {{ 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)) }, _ => panic!("Unexpected destination"), } } - }} + }}; } /// 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], +) { match events[0] { - Event::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event {:?}", events), }; @@ -1825,8 +2289,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] @@ -1835,15 +2302,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. @@ -1855,12 +2328,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(test)] @@ -1868,7 +2344,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 { @@ -1877,7 +2353,7 @@ macro_rules! expect_pending_htlcs_forwardable_from_events { // Ensure process_pending_htlc_forwards is idempotent. $node.node.process_pending_htlc_forwards(); } - }} + }}; } #[macro_export] @@ -1885,28 +2361,53 @@ 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(&$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(&$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 @@ -1919,8 +2420,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 @@ -1930,8 +2435,11 @@ 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); @@ -1941,14 +2449,18 @@ pub fn do_main_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node< 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 { @@ -1963,22 +2475,36 @@ 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: &msgs::CommitmentSigned, fail_backwards: bool, skip_last_step: bool) { +pub fn do_commitment_signed_dance( + node_a: &Node<'_, '_, '_>, node_b: &Node<'_, '_, '_>, + commitment_signed: &msgs::CommitmentSigned, 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(&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 got_claim = node_a.node.test_raa_monitor_updates_held(node_b.node.get_our_node_id(), commitment_signed.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(), commitment_signed.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: commitment_signed.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: commitment_signed.channel_id + }] + ); check_added_monitors!(node_a, 1); let node_a_per_peer_state = node_a.node.per_peer_state.read().unwrap(); @@ -1990,7 +2516,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`) @@ -2001,12 +2529,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) } @@ -2022,31 +2560,51 @@ 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, + ) }; } /// Gets a route from the given sender to the node described in `payment_params`. -pub fn get_route(send_node: &Node, route_params: &RouteParameters) -> Result { +pub fn get_route( + send_node: &Node, route_params: &RouteParameters, +) -> Result { let scorer = TestScorer::new(); - let keys_manager = TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet); + let keys_manager = + TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); router::get_route( - &send_node.node.get_our_node_id(), route_params, &send_node.network_graph.read_only(), + &send_node.node.get_our_node_id(), + route_params, + &send_node.network_graph.read_only(), Some(&send_node.node.list_usable_channels().iter().collect::>()), - send_node.logger, &scorer, &Default::default(), &random_seed_bytes + send_node.logger, + &scorer, + &Default::default(), + &random_seed_bytes, ) } /// Like `get_route` above, but adds a random CLTV offset to the final hop. -pub fn find_route(send_node: &Node, route_params: &RouteParameters) -> Result { +pub fn find_route( + send_node: &Node, route_params: &RouteParameters, +) -> Result { let scorer = TestScorer::new(); - let keys_manager = TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet); + let keys_manager = + TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); router::find_route( - &send_node.node.get_our_node_id(), route_params, &send_node.network_graph, + &send_node.node.get_our_node_id(), + route_params, + &send_node.network_graph, Some(&send_node.node.list_usable_channels().iter().collect::>()), - send_node.logger, &scorer, &Default::default(), &random_seed_bytes + send_node.logger, + &scorer, + &Default::default(), + &random_seed_bytes, ) } @@ -2056,30 +2614,51 @@ 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) - }} + }}; } #[cfg(test)] #[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( @@ -2088,7 +2667,13 @@ 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()); @@ -2108,12 +2693,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, + ) }; } @@ -2130,16 +2729,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, ) { 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 { @@ -2149,7 +2750,12 @@ pub fn expect_payment_sent>(node: &H, check_added_monitors(node, 1); } let expected_payment_id = match events[0] { - Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => { + Event::PaymentSent { + ref payment_id, + ref payment_preimage, + ref payment_hash, + ref fee_paid_msat, + } => { assert_eq!(expected_payment_preimage, *payment_preimage); assert_eq!(expected_payment_hash, *payment_hash); if let Some(expected_fee_msat) = expected_fee_msat_opt { @@ -2180,12 +2786,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, + ); + }; } #[cfg(test)] @@ -2198,27 +2814,40 @@ macro_rules! expect_payment_path_successful { $crate::events::Event::PaymentPathSuccessful { .. } => {}, _ => panic!("Unexpected event"), } - } + }; } -pub fn expect_payment_forwarded>( +pub fn expect_payment_forwarded>( event: Event, node: &H, prev_node: &H, next_node: &H, expected_fee: Option, - upstream_force_closed: bool, downstream_force_closed: bool + upstream_force_closed: bool, downstream_force_closed: bool, ) { match event { Event::PaymentForwarded { - fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, - outbound_amount_forwarded_msat: _ + fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat: _, } => { assert_eq!(fee_earned_msat, expected_fee); 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() && x.channel_id == prev_channel_id.unwrap())); + assert!(node + .node() + .list_channels() + .iter() + .any(|x| x.counterparty.node_id == prev_node.node().get_our_node_id() + && x.channel_id == prev_channel_id.unwrap())); } // We check for force closures since a force closed channel is removed from the // node's channel list if !downstream_force_closed { - assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id == next_node.node().get_our_node_id() && 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() + && x.channel_id == next_channel_id.unwrap())); } assert_eq!(claim_from_onchain_tx, downstream_force_closed); }, @@ -2231,23 +2860,36 @@ 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, - $upstream_force_closed, $downstream_force_closed); - } + events.pop().unwrap(), + &$node, + &$prev_node, + &$next_node, + $expected_fee, + $upstream_force_closed, + $downstream_force_closed, + ); + }; } #[cfg(test)] #[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] { @@ -2260,11 +2902,13 @@ 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"), @@ -2272,20 +2916,24 @@ pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, ex } #[cfg(any(test, feature = "_test_utils"))] -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()); @@ -2329,10 +2977,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(test)] @@ -2349,17 +3001,30 @@ 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, + Event::PaymentPathFailed { + payment_hash, + payment_failed_permanently, + payment_id, + failure, #[cfg(test)] error_code, #[cfg(test)] - error_data, .. } => { + 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" + ); #[cfg(test)] { assert!(error_code.is_some(), "expected error_code.is_some() = true"); @@ -2380,7 +3045,9 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( const CHAN_DISABLED_FLAG: u8 = 2; assert_eq!(msg.contents.flags & CHAN_DISABLED_FLAG, 0); }, - NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } if chan_closed => { + NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } + if chan_closed => + { if let Some(scid) = conditions.expected_blamed_scid { assert_eq!(*short_channel_id, scid); } @@ -2388,7 +3055,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() @@ -2400,29 +3069,47 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( Event::PaymentFailed { ref payment_hash, ref payment_id, ref reason } => { assert_eq!(*payment_hash, 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"), } } } 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); -} - -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 { + 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 { let payment_id = PaymentId(origin_node.keys_manager.backing.get_secure_random_bytes()); - origin_node.node.send_payment_with_route(&route, our_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), payment_id).unwrap(); + origin_node + .node + .send_payment_with_route( + &route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + payment_id, + ) + .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 @@ -2434,7 +3121,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(); @@ -2443,7 +3132,12 @@ fn fail_payment_along_path<'a, 'b, 'c>(expected_path: &[&Node<'a, 'b, 'c>]) { } } -pub fn do_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, clear_recipient_events: bool, expected_preimage: Option, is_probe: bool) -> Option { +pub fn do_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, clear_recipient_events: bool, + expected_preimage: Option, is_probe: bool, +) -> Option { let mut payment_event = SendEvent::from_event(ev); let mut prev_node = origin_node; let mut event = None; @@ -2467,27 +3161,52 @@ pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_p 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()); match &purpose { - PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => { + PaymentPurpose::InvoicePayment { + 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"), @@ -2509,11 +3228,28 @@ pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_p 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 { - do_pass_along_path(origin_node, expected_path, recv_value, our_payment_hash, our_payment_secret, ev, payment_claimable_expected, true, expected_preimage, false) +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 { + do_pass_along_path( + origin_node, + expected_path, + recv_value, + our_payment_hash, + our_payment_secret, + ev, + payment_claimable_expected, + true, + expected_preimage, + false, + ) } -pub fn send_probe_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]]) { +pub fn send_probe_along_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]], +) { let mut events = origin_node.node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_route.len()); @@ -2522,54 +3258,107 @@ pub fn send_probe_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expect for path 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(origin_node, path, 0, PaymentHash([0_u8; 32]), None, ev, false, false, None, true); - let nodes_to_fail_payment: Vec<_> = vec![origin_node].into_iter().chain(path.iter().cloned()).collect(); + do_pass_along_path( + origin_node, + path, + 0, + PaymentHash([0_u8; 32]), + None, + ev, + false, + false, + None, + true, + ); + 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()); } } -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<'a, 'b, 'c>( origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, - our_payment_preimage: PaymentPreimage + our_payment_preimage: PaymentPreimage, ) -> u64 { let extra_fees = vec![0; expected_paths.len()]; - do_claim_payment_along_route_with_extra_penultimate_hop_fees(origin_node, expected_paths, - &extra_fees[..], skip_last, our_payment_preimage) + do_claim_payment_along_route_with_extra_penultimate_hop_fees( + origin_node, + expected_paths, + &extra_fees[..], + skip_last, + our_payment_preimage, + ) } pub fn do_claim_payment_along_route_with_extra_penultimate_hop_fees<'a, 'b, 'c>( - origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], expected_extra_fees: - &[u32], skip_last: bool, our_payment_preimage: PaymentPreimage + origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], + expected_extra_fees: &[u32], skip_last: bool, our_payment_preimage: PaymentPreimage, ) -> u64 { assert_eq!(expected_paths.len(), expected_extra_fees.len()); 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.claim_funds(our_payment_preimage); - pass_claimed_payment_along_route(origin_node, expected_paths, expected_extra_fees, skip_last, our_payment_preimage) + pass_claimed_payment_along_route( + origin_node, + expected_paths, + expected_extra_fees, + skip_last, + our_payment_preimage, + ) } -pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], expected_extra_fees: &[u32], skip_last: bool, our_payment_preimage: PaymentPreimage) -> u64 { +pub fn pass_claimed_payment_along_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], + expected_extra_fees: &[u32], skip_last: bool, our_payment_preimage: PaymentPreimage, +) -> u64 { let claim_event = expected_paths[0].last().unwrap().node.get_and_clear_pending_events(); assert_eq!(claim_event.len(), 1); match claim_event[0] { @@ -2577,17 +3366,21 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, ' purpose: PaymentPurpose::SpontaneousPayment(preimage), amount_msat, ref htlcs, - .. } + .. + } | Event::PaymentClaimed { - purpose: PaymentPurpose::InvoicePayment { payment_preimage: Some(preimage), ..}, + purpose: PaymentPurpose::InvoicePayment { payment_preimage: Some(preimage), .. }, ref htlcs, amount_msat, .. } => { 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); - expected_paths.iter().zip(htlcs).for_each(|(path, htlc)| check_claimed_htlc_channel(origin_node, path, htlc)); + expected_paths + .iter() + .zip(htlcs) + .for_each(|(path, htlc)| check_claimed_htlc_channel(origin_node, path, htlc)); }, Event::PaymentClaimed { purpose: PaymentPurpose::InvoicePayment { .. }, @@ -2597,10 +3390,13 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, ' .. } => { 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); - expected_paths.iter().zip(htlcs).for_each(|(path, htlc)| check_claimed_htlc_channel(origin_node, path, htlc)); - } + expected_paths + .iter() + .zip(htlcs) + .for_each(|(path, htlc)| check_claimed_htlc_channel(origin_node, path, htlc)); + }, _ => panic!(), } @@ -2611,7 +3407,18 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, ' macro_rules! msgs_from_ev { ($ev: expr) => { match $ev { - &MessageSendEvent::UpdateHTLCs { ref node_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, + 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()); @@ -2621,9 +3428,10 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, ' }, _ => panic!("Unexpected event"), } - } + }; } - let mut per_path_msgs: Vec<((msgs::UpdateFulfillHTLC, msgs::CommitmentSigned), PublicKey)> = Vec::with_capacity(expected_paths.len()); + let mut per_path_msgs: Vec<((msgs::UpdateFulfillHTLC, msgs::CommitmentSigned), 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()); @@ -2632,58 +3440,80 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, ' } else { for expected_path in expected_paths.iter() { // For MPP payments, we always want the message to the first node in the path. - 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, + ); per_path_msgs.push(msgs_from_ev!(&ev)); } } - 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 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 - } else { - channel.context().config().forwarding_fee_base_msat - } - }; - if $idx == 1 { fee += expected_extra_fees[i]; } - expect_payment_forwarded!(*$node, $next_node, $prev_node, Some(fee as u64), false, false); - expected_total_fee_msat += fee as u64; - 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) + ($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 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 } 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; + channel.context().config().forwarding_fee_base_msat + } + }; + if $idx == 1 { + fee += expected_extra_fees[i]; } - } + expect_payment_forwarded!( + *$node, + $next_node, + $prev_node, + Some(fee as u64), + false, + false + ); + expected_total_fee_msat += fee as u64; + 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(); @@ -2722,22 +3552,35 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, ' expected_total_fee_msat } -pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage) { - let expected_total_fee_msat = do_claim_payment_along_route(origin_node, expected_paths, skip_last, our_payment_preimage); +pub fn claim_payment_along_route<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, + our_payment_preimage: PaymentPreimage, +) { + let expected_total_fee_msat = + do_claim_payment_along_route(origin_node, expected_paths, skip_last, our_payment_preimage); if !skip_last { expect_payment_sent!(origin_node, our_payment_preimage, Some(expected_total_fee_msat)); } } -pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) { +pub fn claim_payment<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], + our_payment_preimage: PaymentPreimage, +) { claim_payment_along_route(origin_node, &[expected_route], false, 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); @@ -2750,57 +3593,108 @@ 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 route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) { - 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_over_limit<'a, 'b, 'c>( + origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, +) { + 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 network_graph = origin_node.network_graph.read_only(); let scorer = test_utils::TestScorer::new(); let seed = [0u8; 32]; let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let route = router::get_route(&origin_node.node.get_our_node_id(), &route_params, &network_graph, - None, origin_node.logger, &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = router::get_route( + &origin_node.node.get_our_node_id(), + &route_params, + &network_graph, + None, + origin_node.logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].hops.len(), expected_route.len()); for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) { assert_eq!(hop.pubkey, node.node.get_our_node_id()); } - let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(expected_route.last().unwrap()); + let (_, our_payment_hash, our_payment_secret) = + get_payment_preimage_hash!(expected_route.last().unwrap()); unwrap_send_err!(origin_node.node.send_payment_with_route(&route, our_payment_hash, RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)), true, APIError::ChannelUnavailable { ref err }, assert!(err.contains("Cannot send value that would put us over the max HTLC value in flight our peer will accept"))); } -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); - - 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) { + 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, + ); +} + +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, msgs::CommitmentSigned), PublicKey)> = Vec::with_capacity(expected_paths.len()); + let mut per_path_msgs: Vec<((msgs::UpdateFailHTLC, msgs::CommitmentSigned), 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, 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, + 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); @@ -2813,9 +3707,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(); @@ -2824,17 +3725,42 @@ 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, 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, + 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); @@ -2857,15 +3783,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() { @@ -2878,10 +3817,13 @@ 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, our_payment_hash, "unexpected second payment_hash"); + assert_eq!( + *payment_hash, 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"), } } @@ -2895,7 +3837,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); } @@ -2911,21 +3856,45 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec { let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); let scorer = RwLock::new(test_utils::TestScorer::new()); - 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 Persist>) -> Vec> { +pub fn create_node_cfgs_with_persisters<'a>( + node_count: usize, chanmon_cfgs: &'a Vec, + persisters: Vec<&'a impl Persist>, +) -> 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 { @@ -2933,7 +3902,11 @@ 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), + 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()), chain_monitor, keys_manager: &chanmon_cfgs[i].keys_manager, @@ -2964,24 +3937,63 @@ 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>, &'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>, + &'b test_utils::TestLogger, + >, +> { let mut chanmgrs = Vec::new(); for i in 0..node_count { let network = Network::Testnet; let genesis_block = bitcoin::blockdata::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].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].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::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::TestLogger, + >, + >, +) -> Vec> { let mut nodes = Vec::new(); let chan_count = Rc::new(RefCell::new(0)); let payment_count = Rc::new(RefCell::new(0)); @@ -2990,31 +4002,47 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec(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 = HashSet::new(); node_txn.retain(|tx| txn_seen.insert(tx.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| { @@ -3070,7 +4110,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()); @@ -3089,7 +4131,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 { @@ -3103,16 +4147,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.txid() { check_spends!(tx, revoked_tx); false - } else { true } + } else { + true + } }); node_txn.retain(|tx| { check_spends!(tx, commitment_revoked_tx); @@ -3121,7 +4171,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 = HashSet::new(); node_txn.retain(|tx| txn_seen.insert(tx.txid())); @@ -3149,24 +4201,30 @@ 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 events_1 = nodes[a].node.get_and_clear_pending_msg_events(); assert_eq!(events_1.len(), 2); let as_update = match events_1[0] { - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - msg.clone() - }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => msg.clone(), _ => panic!("Unexpected event"), }; match events_1[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[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 { @@ -3179,18 +4237,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[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[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); }, @@ -3204,50 +4266,68 @@ 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(test)] 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 = chan_lock.channel_by_id.get(&$channel_id).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .unwrap(); chan.get_value_stat() - }} + }}; } macro_rules! get_chan_reestablish_msgs { - ($src_node: expr, $dst_node: expr) => { - { - let mut announcements = $crate::prelude::HashSet::new(); - 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::HashSet::new(); + 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()) @@ -3255,69 +4335,72 @@ 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 updates } => { - assert_eq!(*node_id, $dst_node.node.get_our_node_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 updates } => { - assert_eq!(*node_id, $dst_node.node.get_our_node_id()); - assert!(commitment_update.is_none()); - 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 updates } => { + assert_eq!(*node_id, $dst_node.node.get_our_node_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 updates } => { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + assert!(commitment_update.is_none()); + 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> { @@ -3358,17 +4441,43 @@ 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; - node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { - features: node_b.node.init_features(), networks: None, remote_network_address: None - }, true).unwrap(); + node_a + .node + .peer_connected( + &node_b.node.get_our_node_id(), + &msgs::Init { + features: node_b.node.init_features(), + networks: None, + remote_network_address: None, + }, + true, + ) + .unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b); - node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { - features: node_a.node.init_features(), networks: None, remote_network_address: None - }, false).unwrap(); + node_b + .node + .peer_connected( + &node_a.node.get_our_node_id(), + &msgs::Init { + features: node_a.node.init_features(), + networks: None, + remote_network_address: None, + }, + false, + ) + .unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(node_b, node_a); if send_channel_ready.0 { @@ -3423,10 +4532,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 { @@ -3436,48 +4553,80 @@ 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()); } if pending_raa.0 { assert!(chan_msgs.3 == RAACommitmentOrder::RevokeAndACKFirst); - node_a.node.handle_revoke_and_ack(&node_b.node.get_our_node_id(), &chan_msgs.1.unwrap()); + node_a + .node + .handle_revoke_and_ack(&node_b.node.get_our_node_id(), &chan_msgs.1.unwrap()); assert!(node_a.node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(node_a, 1); } 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(&node_b.node.get_our_node_id(), &commitment_update.commitment_signed); + node_a.node.handle_commitment_signed( + &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()); @@ -3501,41 +4650,71 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) { } if pending_raa.1 { assert!(chan_msgs.3 == RAACommitmentOrder::RevokeAndACKFirst); - node_b.node.handle_revoke_and_ack(&node_a.node.get_our_node_id(), &chan_msgs.1.unwrap()); + node_b + .node + .handle_revoke_and_ack(&node_a.node.get_our_node_id(), &chan_msgs.1.unwrap()); assert!(node_b.node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(node_b, 1); } 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(&node_a.node.get_our_node_id(), &commitment_update.commitment_signed); + node_b.node.handle_commitment_signed( + &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()); @@ -3554,17 +4733,36 @@ 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, - ).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 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, + ) + .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); // Create the corresponding funding output. let events = funding_node.node.get_and_clear_pending_events(); @@ -3575,14 +4773,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: *channel_value_satoshis, script_pubkey: output_script.clone(), + value: *channel_value_satoshis, + script_pubkey: output_script.clone(), }); }, _ => panic!("Unexpected event"), @@ -3591,16 +4790,15 @@ pub fn create_batch_channel_funding<'a, 'b, 'c>( } // Compose the batch funding transaction and give it to the ChannelManager. - let tx = Transaction { - version: 2, - lock_time: LockTime::ZERO, - 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()); + let tx = + Transaction { version: 2, lock_time: LockTime::ZERO, 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()); check_added_monitors!(funding_node, 0); let events = funding_node.node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), params.len()); @@ -3608,7 +4806,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 14aa14b4398..6d68b65721e 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -12,55 +12,73 @@ //! 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::{CLOSED_CHANNEL_UPDATE_ID, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY}; +use crate::chain::channelmonitor::{ + ANTI_REORG_DELAY, CLOSED_CHANNEL_UPDATE_ID, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, +}; use crate::chain::transaction::OutPoint; -use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, SignerProvider}; -use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason}; -use crate::ln::{ChannelId, PaymentPreimage, PaymentSecret, PaymentHash}; -use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis, OutboundV1Channel, InboundV1Channel, COINBASE_MATURITY, ChannelPhase}; -use crate::ln::channelmanager::{self, PaymentId, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, BREAKDOWN_TIMEOUT, ENABLE_GOSSIP_TICKS, DISABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA}; -use crate::ln::channel::{DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, ChannelError}; -use crate::ln::{chan_utils, onion_utils}; -use crate::ln::chan_utils::{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::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, + PathFailure, PaymentFailureReason, PaymentPurpose, +}; +use crate::ln::chan_utils::{ + htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment, + OFFERED_HTLC_SCRIPT_WEIGHT, +}; +use crate::ln::channel::{ + commitment_tx_base_weight, get_holder_selected_channel_reserve_satoshis, ChannelPhase, + InboundV1Channel, OutboundV1Channel, COINBASE_MATURITY, COMMITMENT_TX_WEIGHT_PER_HTLC, + 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}; +use crate::ln::channelmanager::{ + self, PaymentId, PaymentSendFailure, RAACommitmentOrder, RecipientOnionFields, + BREAKDOWN_TIMEOUT, DISABLE_GOSSIP_TICKS, ENABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures}; use crate::ln::msgs; -use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction}; -use crate::util::test_channel_signer::TestChannelSigner; -use crate::util::test_utils::{self, WatchtowerPersister}; +use crate::ln::msgs::{ChannelMessageHandler, ErrorAction, RoutingMessageHandler}; +use crate::ln::{chan_utils, onion_utils}; +use crate::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; +use crate::routing::gossip::{NetworkGraph, NetworkUpdate}; +use crate::routing::router::{ + get_route, Path, PaymentParameters, Route, RouteHop, RouteParameters, +}; +use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, SignerProvider}; +use crate::util::config::{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::{UserConfig, MaxDustHTLCExposure}; +use crate::util::test_channel_signer::TestChannelSigner; +use crate::util::test_utils::{self, WatchtowerPersister}; -use bitcoin::hash_types::BlockHash; +use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::locktime::absolute::LockTime; -use bitcoin::blockdata::script::{Builder, ScriptBuf}; use bitcoin::blockdata::opcodes; -use bitcoin::blockdata::constants::ChainHash; +use bitcoin::blockdata::script::{Builder, ScriptBuf}; +use bitcoin::hash_types::BlockHash; use bitcoin::network::constants::Network; -use bitcoin::{Sequence, Transaction, TxIn, TxOut, Witness}; use bitcoin::OutPoint as BitcoinOutPoint; +use bitcoin::{Sequence, Transaction, TxIn, TxOut, Witness}; use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::{PublicKey,SecretKey}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use regex; use crate::io; use crate::prelude::*; +use crate::sync::{Arc, Mutex, RwLock}; use alloc::collections::BTreeSet; +use bitcoin::hashes::Hash; use core::default::Default; use core::iter::repeat; -use bitcoin::hashes::Hash; -use crate::sync::{Arc, Mutex, RwLock}; -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; @@ -78,51 +96,127 @@ 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.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.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.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.funding_satoshis = TOTAL_BITCOIN_SUPPLY_SATOSHIS; + msg + }, + ); - insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { msg.channel_reserve_satoshis = msg.funding_satoshis + 1; msg }); + insane_open_helper("Bogus channel_reserve_satoshis", |mut msg| { + msg.channel_reserve_satoshis = msg.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.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.funding_satoshis - msg.channel_reserve_satoshis) * 1000 + 1; + msg + }, + ); - insane_open_helper("Peer never wants payout outputs?", |mut msg| { msg.dust_limit_satoshis = msg.funding_satoshis + 1 ; msg }); + insane_open_helper("Peer never wants payout outputs?", |mut msg| { + msg.dust_limit_satoshis = msg.funding_satoshis + 1; + msg + }); - insane_open_helper(r"Minimum htlc value \(\d+\) was larger than full channel value \(\d+\)", |mut msg| { msg.htlc_minimum_msat = (msg.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.htlc_minimum_msat = (msg.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.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.to_self_delay = MAX_LOCAL_BREAKDOWN_TIMEOUT + 1; + msg + }, + ); - insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { msg.max_accepted_htlcs = 0; msg }); + insane_open_helper("0 max_accepted_htlcs makes for a useless channel", |mut msg| { + msg.max_accepted_htlcs = 0; + msg + }); - insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { msg.max_accepted_htlcs = 484; msg }); + insane_open_helper("max_accepted_htlcs was 484. It must not be larger than 483", |mut msg| { + msg.max_accepted_htlcs = 484; + msg + }); } #[test] @@ -132,15 +226,30 @@ fn test_funding_exceeds_no_wumbo_limit() { use crate::ln::channel::MAX_FUNDING_SATOSHIS_NO_WUMBO; let chanmon_cfgs = create_chanmon_cfgs(2); let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - *node_cfgs[1].override_init_features.borrow_mut() = Some(channelmanager::provided_init_features(&test_default_channel_config()).clear_wumbo()); + *node_cfgs[1].override_init_features.borrow_mut() = + Some(channelmanager::provided_init_features(&test_default_channel_config()).clear_wumbo()); 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!(), } } @@ -159,11 +268,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.max_htlc_value_in_flight_msat = 100_000_000; @@ -171,7 +296,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.max_htlc_value_in_flight_msat = 100_000_000; @@ -183,7 +312,13 @@ 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_phase = get_channel_ref!(sender_node, counterparty_node, sender_node_per_peer_lock, sender_node_peer_state_lock, temp_channel_id); + let channel_phase = get_channel_ref!( + sender_node, + counterparty_node, + sender_node_per_peer_lock, + sender_node_peer_state_lock, + temp_channel_id + ); match channel_phase { ChannelPhase::UnfundedInboundV1(_) | ChannelPhase::UnfundedOutboundV1(_) => { let chan_context = channel_phase.context_mut(); @@ -195,17 +330,22 @@ fn do_test_counterparty_no_reserve(send_from_initiator: bool) { } 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); } @@ -226,7 +366,7 @@ 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 -> @@ -255,19 +395,29 @@ 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 = { @@ -280,14 +430,24 @@ 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(&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(&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(&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()); + 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); @@ -309,13 +469,25 @@ 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(&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(&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(&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(&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); @@ -324,7 +496,7 @@ 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"), } @@ -343,7 +515,7 @@ 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 { @@ -355,19 +527,29 @@ 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 = { @@ -380,8 +562,14 @@ 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(&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(&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); @@ -430,17 +618,20 @@ 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(&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()); + 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 @@ -475,11 +666,18 @@ 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(&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()); + 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 @@ -488,8 +686,12 @@ fn test_multi_flight_update_fee() { check_added_monitors!(nodes[1], 1); // Delever (4) - nodes[1].node.handle_commitment_signed(&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( + &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); @@ -497,7 +699,11 @@ fn test_multi_flight_update_fee() { check_added_monitors!(nodes[0], 1); nodes[0].node.handle_commitment_signed(&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()); + 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); @@ -517,31 +723,64 @@ 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, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42); + let (temporary_channel_id, tx, funding_output) = + 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() + ); - 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(); @@ -551,9 +790,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(); @@ -566,10 +811,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]); @@ -616,15 +865,25 @@ 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:_, 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: _, + 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(&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()); + 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); @@ -632,7 +891,11 @@ fn test_update_fee_vanilla() { check_added_monitors!(nodes[0], 1); nodes[0].node.handle_commitment_signed(&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()); + 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); @@ -649,11 +912,18 @@ 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(); @@ -661,8 +931,12 @@ 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; @@ -671,7 +945,9 @@ 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); @@ -693,7 +969,11 @@ 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; @@ -702,51 +982,78 @@ fn test_update_fee_that_funder_cannot_afford() { // needed to sign the new commitment tx and (2) sign the new commitment tx. let (local_revocation_basepoint, local_htlc_basepoint, local_funding) = { 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 local_chan = chan_lock.channel_by_id.get(&chan.2).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .unwrap(); let chan_signer = local_chan.get_signer(); let pubkeys = chan_signer.as_ref().pubkeys(); - (pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, - pubkeys.funding_pubkey) + (pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, pubkeys.funding_pubkey) }; - let (remote_delayed_payment_basepoint, remote_htlc_basepoint,remote_point, remote_funding) = { + let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point, remote_funding) = { 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).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .unwrap(); let chan_signer = remote_chan.get_signer(); let pubkeys = chan_signer.as_ref().pubkeys(); - (pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, - chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), - pubkeys.funding_pubkey) + ( + pubkeys.delayed_payment_basepoint, + pubkeys.htlc_basepoint, + chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), + pubkeys.funding_pubkey, + ) }; // Assemble the set of keys we can use for signatures for our commitment_signed message. - let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint, - &remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint); + let commit_tx_keys = chan_utils::TxCreationKeys::derive_new( + &secp_ctx, + &remote_point, + &remote_delayed_payment_basepoint, + &remote_htlc_basepoint, + &local_revocation_basepoint, + &local_htlc_basepoint, + ); 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).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .unwrap(); let local_chan_signer = local_chan.get_signer(); let mut htlcs: Vec<(HTLCOutputInCommitment, ())> = vec![]; let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data( INITIAL_COMMITMENT_NUMBER - 1, push_sats, - channel_value - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000, - local_funding, remote_funding, + channel_value + - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) + / 1000, + local_funding, + remote_funding, commit_tx_keys.clone(), non_buffer_feerate + 4, &mut htlcs, - &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable() + &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable(), ); - local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap() + local_chan_signer + .as_ecdsa() + .unwrap() + .sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx) + .unwrap() }; let commit_signed_msg = msgs::CommitmentSigned { @@ -757,10 +1064,7 @@ 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); @@ -768,11 +1072,22 @@ 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 + ); } #[test] @@ -784,7 +1099,7 @@ 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(); @@ -796,21 +1111,39 @@ 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:_, 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: _, + 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(&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()); + 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); @@ -825,7 +1158,11 @@ fn test_update_fee_with_fundee_update_add_htlc() { check_added_monitors!(nodes[0], 1); nodes[0].node.handle_commitment_signed(&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()); + 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); @@ -839,10 +1176,17 @@ 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(&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( + &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); @@ -850,7 +1194,11 @@ fn test_update_fee_with_fundee_update_add_htlc() { nodes[1].node.handle_commitment_signed(&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); @@ -862,17 +1210,29 @@ 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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -911,16 +1271,26 @@ 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:_, 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: _, + 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(&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()); + 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): @@ -938,9 +1308,18 @@ 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:_, 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: _, + 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"), }; @@ -948,13 +1327,21 @@ fn test_update_fee() { nodes[1].node.handle_commitment_signed(&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(&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): @@ -973,9 +1360,16 @@ fn test_update_fee() { check_added_monitors!(nodes[1], 1); // Deliver (7) - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_update.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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); @@ -985,8 +1379,20 @@ 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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1004,30 +1410,31 @@ 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); @@ -1058,11 +1465,17 @@ 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_preimage_1 = send_along_route(&nodes[1], + 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_preimage_1 = send_along_route( + &nodes[1], Route { paths: vec![Path { hops, blinded_tail: None }], route_params: None }, - &vec!(&nodes[2], &nodes[3], &nodes[1])[..], 1000000).0; + &vec![&nodes[2], &nodes[3], &nodes[1]][..], + 1000000, + ) + .0; let mut hops = Vec::with_capacity(3); hops.push(RouteHop { @@ -1092,29 +1505,83 @@ 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: None }, - &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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [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::CooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CooperativeClosure, + [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::CooperativeClosure, [nodes[3].node.get_our_node_id()], 100000); - check_closed_event!(nodes[3], 1, ClosureReason::CooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CooperativeClosure, + [nodes[3].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[3], + 1, + ClosureReason::CooperativeClosure, + [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::CooperativeClosure, [nodes[3].node.get_our_node_id()], 100000); - check_closed_event!(nodes[3], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[3].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[3], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1130,13 +1597,22 @@ 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); @@ -1150,17 +1626,33 @@ 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].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].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); } @@ -1174,43 +1666,75 @@ 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(&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( + &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(&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(&nodes[1].node.get_our_node_id(), &as_updates.commitment_signed); + nodes[2] + .node + .handle_commitment_signed(&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(&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); @@ -1251,17 +1775,21 @@ 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); } #[test] @@ -1277,13 +1805,22 @@ fn test_duplicate_htlc_different_direction_onchain() { let chan_1 = 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 (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], 800_000); - 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]]], 800_000, 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]]], + 800_000, + payment_hash, + node_a_payment_secret, + ); // Provide preimage to node 0 by claiming payment nodes[0].node.claim_funds(payment_preimage); @@ -1306,7 +1843,13 @@ 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(); @@ -1316,11 +1859,12 @@ 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 (preimage_bump_tx, timeout_tx) = if claim_txn[1].input[0].previous_output == preimage_tx.input[0].previous_output { - (&claim_txn[1], &claim_txn[2]) - } else { - (&claim_txn[2], &claim_txn[1]) - }; + let (preimage_bump_tx, timeout_tx) = + if claim_txn[1].input[0].previous_output == preimage_tx.input[0].previous_output { + (&claim_txn[1], &claim_txn[2]) + } else { + (&claim_txn[2], &claim_txn[1]) + }; assert_eq!(preimage_tx.input.len(), 1); assert_eq!(preimage_bump_tx.input.len(), 1); @@ -1339,11 +1883,24 @@ fn test_duplicate_htlc_different_direction_onchain() { 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, 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, + 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); @@ -1367,17 +1924,31 @@ 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)).err().unwrap(); + let err = nodes[0] + .node + .send_payment_with_route( + &route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0), + ) + .err() + .unwrap(); match err { PaymentSendFailure::AllFailedResendSafe(ref fails) => { - if let &APIError::ChannelUnavailable { .. } = &fails[0] {} - else { panic!("Unexpected error variant"); } + if let &APIError::ChannelUnavailable { .. } = &fails[0] { + } else { + panic!("Unexpected error variant"); + } }, _ => panic!("Unexpected error variant"), } @@ -1403,15 +1974,24 @@ fn test_fee_spike_violation_fails_htlc() { 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).unwrap(); - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], - 3460001, RecipientOnionFields::secret_only(payment_secret), cur_height, &None).unwrap(); - let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + let onion_keys = + onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 3460001, + RecipientOnionFields::secret_only(payment_secret), + cur_height, + &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, @@ -1430,38 +2010,64 @@ fn test_fee_spike_violation_fails_htlc() { // Get the TestChannelSigner for each channel, which will be used to (1) get the keys // needed to sign the new commitment tx and (2) sign the new commitment tx. - let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point, local_funding) = { + let ( + local_revocation_basepoint, + local_htlc_basepoint, + local_secret, + next_local_point, + local_funding, + ) = { 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 local_chan = chan_lock.channel_by_id.get(&chan.2).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .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; let pubkeys = chan_signer.as_ref().pubkeys(); - (pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, - chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER), - chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx), - chan_signer.as_ref().pubkeys().funding_pubkey) + ( + pubkeys.revocation_basepoint, + pubkeys.htlc_basepoint, + chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER), + chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx), + chan_signer.as_ref().pubkeys().funding_pubkey, + ) }; let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point, remote_funding) = { 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).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .unwrap(); let chan_signer = remote_chan.get_signer(); let pubkeys = chan_signer.as_ref().pubkeys(); - (pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, - chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), - chan_signer.as_ref().pubkeys().funding_pubkey) + ( + pubkeys.delayed_payment_basepoint, + pubkeys.htlc_basepoint, + chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx), + chan_signer.as_ref().pubkeys().funding_pubkey, + ) }; // Assemble the set of keys we can use for signatures for our commitment_signed message. - let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint, - &remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint); + let commit_tx_keys = chan_utils::TxCreationKeys::derive_new( + &secp_ctx, + &remote_point, + &remote_delayed_payment_basepoint, + &remote_htlc_basepoint, + &local_revocation_basepoint, + &local_htlc_basepoint, + ); // Build the remote commitment transaction so we can sign it, and then later use the // signature for the commitment_signed message. @@ -1479,22 +2085,31 @@ 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).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .unwrap(); let local_chan_signer = local_chan.get_signer(); let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data( commitment_number, 95000, local_chan_balance, - local_funding, remote_funding, + local_funding, + remote_funding, commit_tx_keys.clone(), feerate_per_kw, &mut vec![(accepted_htlc_info, ())], - &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable() + &local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable(), ); - local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap() + local_chan_signer + .as_ecdsa() + .unwrap() + .sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx) + .unwrap() }; let commit_signed_msg = msgs::CommitmentSigned { @@ -1523,7 +2138,10 @@ fn test_fee_spike_violation_fails_htlc() { 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() }, @@ -1550,23 +2168,36 @@ 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].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].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()); } @@ -1584,7 +2215,11 @@ 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); @@ -1600,15 +2235,24 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() { let secp_ctx = Secp256k1::new(); let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); 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).unwrap(); - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], - 700_000, RecipientOnionFields::secret_only(payment_secret), cur_height, &None).unwrap(); - let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + let onion_keys = + onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 700_000, + RecipientOnionFields::secret_only(payment_secret), + cur_height, + &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, @@ -1643,12 +2287,17 @@ 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. @@ -1663,9 +2312,17 @@ 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].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].node.send_payment_with_route( + &route, + our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), + PaymentId(our_payment_hash.0) + ), + true, + APIError::ChannelUnavailable { .. }, + {} + ); } #[test] @@ -1683,22 +2340,36 @@ 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"), @@ -1716,7 +2387,7 @@ 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); @@ -1751,26 +2422,45 @@ 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, 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, + 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(); 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_1.msgs[0]); + nodes[1] + .node + .handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event_1.msgs[0]); // 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; @@ -1779,10 +2469,23 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let secp_ctx = Secp256k1::new(); 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(&secp_ctx, &route_2.paths[0], &session_priv).unwrap(); + let onion_keys = + onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv).unwrap(); let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( - &route_2.paths[0], recv_value_2, RecipientOnionFields::spontaneous_empty(), cur_height, &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, + RecipientOnionFields::spontaneous_empty(), + cur_height, + &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, @@ -1796,13 +2499,24 @@ 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 + ); } #[test] @@ -1819,15 +2533,19 @@ 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 } #[test] @@ -1838,7 +2556,11 @@ 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); @@ -1856,7 +2578,7 @@ 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 @@ -1868,15 +2590,27 @@ 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].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].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()); } @@ -1887,16 +2621,27 @@ 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_) = ( @@ -1910,7 +2655,10 @@ 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. @@ -1924,49 +2672,90 @@ 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, 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, + 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(); 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_1.msgs[0]); + 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].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].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); @@ -1976,23 +2765,43 @@ 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].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].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(&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( + &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 @@ -2001,7 +2810,11 @@ fn test_channel_reserve_holding_cell_htlcs() { let commitment_update_2 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[0].node.handle_commitment_signed(&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()); + 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); @@ -2012,7 +2825,9 @@ 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]); @@ -2020,15 +2835,25 @@ 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]); let ref payment_event_3 = expect_forward!(nodes[1]); assert_eq!(payment_event_3.msgs.len(), 2); - nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event_3.msgs[0]); - nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event_3.msgs[1]); + nodes[2] + .node + .handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event_3.msgs[0]); + nodes[2] + .node + .handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event_3.msgs[1]); commitment_signed_dance!(nodes[2], nodes[1], &payment_event_3.commitment_msg, false); expect_pending_htlcs_forwardable!(nodes[2]); @@ -2036,7 +2861,14 @@ 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()); @@ -2046,13 +2878,20 @@ fn test_channel_reserve_holding_cell_htlcs() { assert!(payment_preimage.is_none()); assert_eq!(our_payment_secret_21, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => 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()); @@ -2062,28 +2901,35 @@ fn test_channel_reserve_holding_cell_htlcs() { assert!(payment_preimage.is_none()); assert_eq!(our_payment_secret_22, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => 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 + ); } #[test] @@ -2118,15 +2964,25 @@ 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); @@ -2147,17 +3003,32 @@ 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(&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(&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(&nodes[0].node.get_our_node_id(), &send_1.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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); @@ -2167,19 +3038,34 @@ 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(&nodes[0].node.get_our_node_id(), &as_cs.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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(&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(&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); @@ -2198,10 +3084,18 @@ 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); @@ -2209,15 +3103,27 @@ 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(&nodes[1].node.get_our_node_id(), &send_2.commitment_msg); + nodes[0] + .node + .handle_commitment_signed(&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(&nodes[0].node.get_our_node_id(), &as_cs.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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); @@ -2227,9 +3133,15 @@ 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(&nodes[0].node.get_our_node_id(), &as_cs.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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); @@ -2257,23 +3169,32 @@ 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: - nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id()) + .unwrap(); check_added_monitors!(nodes[1], 1); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [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); @@ -2289,19 +3210,32 @@ 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). - nodes[1].node.force_close_broadcasting_latest_txn(&chan_2.2, &nodes[2].node.get_our_node_id()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan_2.2, &nodes[2].node.get_our_node_id()) + .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); @@ -2310,39 +3244,59 @@ 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, [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, + [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, 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, + 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) - nodes[2].node.force_close_broadcasting_latest_txn(&chan_3.2, &nodes[3].node.get_our_node_id()).unwrap(); + nodes[2] + .node + .force_close_broadcasting_latest_txn(&chan_3.2, &nodes[3].node.get_our_node_id()) + .unwrap(); check_added_monitors!(nodes[2], 1); check_closed_broadcast!(nodes[2], true); let node2_commitment_txid; { let node_txn = test_txn_broadcast(&nodes[2], &chan_3, None, HTLCType::NONE); - connect_blocks(&nodes[2], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + MIN_CLTV_EXPIRY_DELTA as u32 + 1); + connect_blocks( + &nodes[2], + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + MIN_CLTV_EXPIRY_DELTA as u32 + 1, + ); test_txn_broadcast(&nodes[2], &chan_3, None, HTLCType::TIMEOUT); node2_commitment_txid = node_txn[0].txid(); @@ -2355,15 +3309,31 @@ 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, [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, + [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(&OutPoint { txid: chan_3.3.txid(), index: 0 }); + let chan_3_mon = nodes[3] + .chain_monitor + .chain_monitor + .remove_monitor(&OutPoint { txid: chan_3.3.txid(), index: 0 }); // 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). @@ -2372,13 +3342,14 @@ 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[0] { - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - msg.clone() - }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => msg.clone(), _ => panic!("Unexpected event"), }; match events[1] { - 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"), @@ -2391,7 +3362,9 @@ fn channel_monitor_network_test() { node_txn.retain(|tx| { if tx.input[0].previous_output.txid == node2_commitment_txid { false - } else { true } + } else { + true + } }); } @@ -2404,20 +3377,27 @@ 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[0] { - MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - msg.clone() - }, + MessageSendEvent::BroadcastChannelUpdate { ref msg } => msg.clone(), _ => panic!("Unexpected event"), }; match events[1] { - 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::HolderForceClosed, [nodes[3].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[4], + 1, + ClosureReason::HolderForceClosed, + [nodes[3].node.get_our_node_id()], + 100000 + ); mine_transaction(&nodes[4], &node_txn[0]); check_preimage_claim(&nodes[4], &node_txn); @@ -2428,9 +3408,20 @@ 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(OutPoint { txid: chan_3.3.txid(), index: 0 }, chan_3_mon), - Ok(ChannelMonitorUpdateStatus::Completed)); - check_closed_event!(nodes[3], 1, ClosureReason::HolderForceClosed, [nodes[4].node.get_our_node_id()], 100000); + assert_eq!( + nodes[3] + .chain_monitor + .chain_monitor + .watch_channel(OutPoint { txid: chan_3.3.txid(), index: 0 }, chan_3_mon), + Ok(ChannelMonitorUpdateStatus::Completed) + ); + check_closed_event!( + nodes[3], + 1, + ClosureReason::HolderForceClosed, + [nodes[4].node.get_our_node_id()], + 100000 + ); } #[test] @@ -2455,7 +3446,7 @@ 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 @@ -2464,9 +3455,12 @@ fn test_justice_tx_htlc_timeout() { 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].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].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]); @@ -2478,18 +3472,39 @@ fn test_justice_tx_htlc_timeout() { node_txn.swap_remove(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 + ); 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); @@ -2518,15 +3533,15 @@ 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.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]); { @@ -2541,12 +3556,33 @@ 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); @@ -2568,12 +3604,18 @@ 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 @@ -2583,7 +3625,13 @@ 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 + ); } #[test] @@ -2600,8 +3648,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); @@ -2610,7 +3660,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. @@ -2620,7 +3670,7 @@ 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(funding_txo, &revoked_commitment_tx.txid()).unwrap(); check_spends!(justice_tx, revoked_commitment_tx); @@ -2629,29 +3679,42 @@ fn do_test_forming_justice_tx_from_monitor_updates(broadcast_initial_commitment: 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 }; + let node1_channel_balance = + if broadcast_initial_commitment { 0 } else { revoked_commitment_tx.output[0].value }; let expected_claimable_balance = node1_channel_balance + justice_tx.output[0].value; assert_eq!(total_claimable_balance, expected_claimable_balance); } - #[test] fn claim_htlc_outputs_shared_tx() { // Node revoked old state, htlcs haven't time out yet, claim them in shared justice tx @@ -2668,7 +3731,8 @@ fn claim_htlc_outputs_shared_tx() { 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); @@ -2677,19 +3741,34 @@ fn claim_htlc_outputs_shared_tx() { assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.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].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].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()); @@ -2735,24 +3814,31 @@ fn claim_htlc_outputs_single_tx() { // 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, but this // time as two different claim transactions as we're gonna to timeout htlc with given a high current height 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); //Revoke the old state - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1); + claim_payment(&nodes[0], &vec![&nodes[1]][..], payment_preimage_1); { confirm_transaction_at(&nodes[0], &revoked_local_txn[0], 100); check_added_monitors!(nodes[0], 1); confirm_transaction_at(&nodes[1], &revoked_local_txn[0], 100); 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 events = nodes[0].node.get_and_clear_pending_events(); expect_pending_htlcs_forwardable_from_events!(nodes[0], events[0..1], true); match events.last().unwrap() { - Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {} + Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}, _ => panic!("Unexpected event"), } @@ -2829,17 +3915,20 @@ 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 @@ -2860,20 +3949,39 @@ 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_v0_p2wsh()); // revokeable output assert!(node_txn[1].output[0].script_pubkey.is_v0_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(); @@ -2884,29 +3992,41 @@ 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 { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, outbound_amount_forwarded_msat } => { + Event::PaymentForwarded { + fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, + } => { assert_eq!(fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, chan_id); assert_eq!(claim_from_onchain_tx, true); 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 { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, outbound_amount_forwarded_msat } => { + Event::PaymentForwarded { + fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, + } => { assert_eq!(fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, chan_id); assert_eq!(claim_from_onchain_tx, true); 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(); { @@ -2918,16 +4038,31 @@ 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, 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, + 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); @@ -2944,7 +4079,7 @@ 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(); assert_eq!(node_txn.len(), 2); // Node[1]: 2 * HTLC-timeout tx @@ -2954,18 +4089,30 @@ fn test_htlc_on_chain_success() { assert_ne!(node_txn[0].lock_time, LockTime::ZERO); assert_ne!(node_txn[1].lock_time, LockTime::ZERO); if $htlc_offered { - assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); - assert_eq!(node_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + node_txn[0].input[0].witness.last().unwrap().len(), + OFFERED_HTLC_SCRIPT_WEIGHT + ); + assert_eq!( + node_txn[1].input[0].witness.last().unwrap().len(), + OFFERED_HTLC_SCRIPT_WEIGHT + ); assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output assert!(node_txn[1].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output } else { - assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); - assert_eq!(node_txn[1].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_eq!( + node_txn[1].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment assert!(node_txn[1].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment } 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]); @@ -2977,27 +4124,38 @@ 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() == 3); // HTLC-Success, 2* RBF bumps of above 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 + if node_txn[0].input[0].previous_output.txid == node_a_commitment_tx[0].txid() { + check_spends!(node_txn[1], commitment_tx[0]); + check_spends!(node_txn[2], commitment_tx[0]); + assert_ne!( + node_txn[1].input[0].previous_output.vout, + node_txn[2].input[0].previous_output.vout + ); &node_txn[0] } else { - // Certain `ConnectStyle`s will cause RBF bumps of the previous HTLC transaction to be broadcast. - // FullBlockViaListen - if node_txn[0].input[0].previous_output.txid == node_a_commitment_tx[0].txid() { - check_spends!(node_txn[1], commitment_tx[0]); - check_spends!(node_txn[2], commitment_tx[0]); - assert_ne!(node_txn[1].input[0].previous_output.vout, node_txn[2].input[0].previous_output.vout); - &node_txn[0] - } else { - check_spends!(node_txn[0], commitment_tx[0]); - check_spends!(node_txn[1], commitment_tx[0]); - assert_ne!(node_txn[0].input[0].previous_output.vout, node_txn[1].input[0].previous_output.vout); - &node_txn[2] - } - }; + check_spends!(node_txn[0], commitment_tx[0]); + check_spends!(node_txn[1], commitment_tx[0]); + assert_ne!( + node_txn[0].input[0].previous_output.vout, + node_txn[1].input[0].previous_output.vout + ); + &node_txn[2] + } + }; check_spends!(commitment_spend, node_a_commitment_tx[0]); assert_eq!(commitment_spend.input.len(), 2); @@ -3005,11 +4163,18 @@ 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_v0_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); @@ -3057,23 +4222,37 @@ 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, 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, + 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()); @@ -3085,15 +4264,27 @@ 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); + check_closed_event!( + &nodes[1], + 1, + ClosureReason::CommitmentTxConfirmed, + false, + [nodes[2].node.get_our_node_id()], + 100000 + ); connect_blocks(&nodes[1], 200 - nodes[2].best_block_info().1); let timeout_tx = { let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); @@ -3103,7 +4294,10 @@ fn do_test_htlc_on_chain_timeout(connect_style: ConnectStyle) { assert_eq!(txn.len(), 3); // Two extra fee bumps for timeout transaction } 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) }; @@ -3113,12 +4307,28 @@ 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, 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, + 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()); @@ -3137,11 +4347,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); + assert_eq!( + node_txn[0].clone().input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); } #[test] @@ -3165,7 +4384,8 @@ 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 @@ -3174,32 +4394,65 @@ 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, 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, + 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. @@ -3224,7 +4477,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 }); @@ -3234,16 +4491,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()); @@ -3251,12 +4526,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()); @@ -3264,16 +4552,27 @@ 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(&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(&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()); @@ -3281,21 +4580,37 @@ 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(&nodes[2].node.get_our_node_id(), &updates.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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); @@ -3308,11 +4623,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::PendingHTLCsForwardable { .. } => { }, + Event::PendingHTLCsForwardable { .. } => {}, _ => panic!("Unexpected event"), }; match events[1] { - Event::HTLCHandlingFailed { .. } => { }, + Event::HTLCHandlingFailed { .. } => {}, _ => panic!("Unexpected event"), } // Deliberately don't process the pending fail-back so they all fail back at once after @@ -3348,9 +4663,20 @@ 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, 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, + 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()); @@ -3361,27 +4687,53 @@ 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, 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, + 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); @@ -3393,7 +4745,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"), @@ -3405,7 +4760,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"), @@ -3417,7 +4776,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"), @@ -3469,9 +4832,17 @@ 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 = { @@ -3484,10 +4855,18 @@ 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()); @@ -3495,15 +4874,25 @@ 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 (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads( - &route.paths[0], 50_000, RecipientOnionFields::secret_only(payment_secret), current_height, &None).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); - let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); + &route.paths[0], + 50_000, + RecipientOnionFields::secret_only(payment_secret), + current_height, + &None, + ) + .unwrap(); + let onion_keys = + onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); + 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 { @@ -3560,11 +4949,23 @@ fn test_htlc_ignore_latest_remote_commitment() { let funding_tx = create_announced_chan_between_nodes(&nodes, 0, 1).3; 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + ) + .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, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); let node_txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); assert_eq!(node_txn.len(), 2); @@ -3575,7 +4976,13 @@ 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 @@ -3592,11 +4999,19 @@ 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(); @@ -3616,7 +5031,9 @@ 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(&nodes[1].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[2] + .node + .handle_commitment_signed(&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()); @@ -3624,10 +5041,22 @@ fn test_force_close_fail_back() { // state or updated nodes[1]' state. Now force-close and broadcast that commitment/HTLC // transaction and ensure nodes[1] doesn't fail-backwards (this was originally a bug!). - nodes[2].node.force_close_broadcasting_latest_txn(&payment_event.commitment_msg.channel_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[2] + .node + .force_close_broadcasting_latest_txn( + &payment_event.commitment_msg.channel_id, + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); check_closed_broadcast!(nodes[2], true); check_added_monitors!(nodes[2], 1); - check_closed_event!(nodes[2], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::HolderForceClosed, + [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 @@ -3642,16 +5071,30 @@ 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], payment_event.commitment_msg.channel_id) - .provide_payment_preimage(&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], payment_event.commitment_msg.channel_id).provide_payment_preimage( + &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.txid()); @@ -3680,7 +5123,10 @@ 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()); @@ -3703,18 +5149,41 @@ 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 @@ -3729,10 +5198,22 @@ fn test_peer_disconnected_before_funding_broadcasted() { 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], 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 + ); } #[test] @@ -3751,19 +5232,20 @@ 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()); @@ -3805,8 +5287,8 @@ 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) { @@ -3818,7 +5300,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 @@ -3828,11 +5311,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(); @@ -3844,25 +5335,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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1].node.handle_commitment_signed( + &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(&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( + &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); } @@ -3883,7 +5392,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. @@ -3916,17 +5428,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"), }; } @@ -3940,7 +5452,14 @@ 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()); @@ -3950,7 +5469,7 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken assert!(payment_preimage.is_none()); assert_eq!(payment_secret_1, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => panic!("Unexpected event"), @@ -3976,7 +5495,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); @@ -3989,23 +5510,38 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken } if messages_delivered >= 2 { - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_signed); + nodes[0] + .node + .handle_commitment_signed(&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(&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( + &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); } @@ -4103,7 +5639,11 @@ 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); } @@ -4135,7 +5675,11 @@ 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); } @@ -4170,7 +5714,11 @@ 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); } @@ -4184,12 +5732,21 @@ 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(); @@ -4206,7 +5763,18 @@ 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, 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, + 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); @@ -4214,7 +5782,10 @@ 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] { @@ -4225,8 +5796,14 @@ fn test_drop_messages_peer_disconnect_dual_htlc() { _ => panic!("Unexpected event"), } - nodes[0].node.handle_commitment_signed(&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(&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); }, @@ -4236,14 +5813,32 @@ 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); @@ -4265,14 +5860,27 @@ 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(&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( + &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()); @@ -4289,13 +5897,27 @@ 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(&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( + &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(&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( + &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); @@ -4315,13 +5937,15 @@ fn test_drop_messages_peer_disconnect_dual_htlc() { assert!(payment_preimage.is_none()); assert_eq!(payment_secret_2, *payment_secret); }, - _ => panic!("expected PaymentPurpose::InvoicePayment") + _ => panic!("expected PaymentPurpose::InvoicePayment"), } }, _ => panic!("Unexpected event"), } - nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_revoke_and_ack); + nodes[0] + .node + .handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_revoke_and_ack); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(nodes[0], 1); @@ -4340,22 +5964,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 @@ -4364,14 +6015,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()); @@ -4380,12 +6035,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, 0x4000 | 15, &expected_failure_data[..]); + expect_payment_failed!( + nodes[0], + our_payment_hash, + true, + 0x4000 | 15, + &expected_failure_data[..] + ); } #[test] @@ -4404,26 +6068,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]); } @@ -4435,18 +6118,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); } @@ -4459,31 +6160,50 @@ 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 + }}; } #[test] @@ -4495,10 +6215,19 @@ fn test_claim_sizeable_push_msat() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 98_000_000); - nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()) + .unwrap(); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [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); @@ -4524,10 +6253,19 @@ fn test_claim_on_remote_sizeable_push_msat() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan.2, &nodes[1].node.get_our_node_id()) + .unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [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); @@ -4537,7 +6275,13 @@ 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); @@ -4556,16 +6300,22 @@ 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.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]); @@ -4617,7 +6367,13 @@ 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); @@ -4636,9 +6392,9 @@ 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); @@ -4657,11 +6413,17 @@ 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); @@ -4682,17 +6444,23 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_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.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(); assert_eq!(node_txn.len(), 1); @@ -4718,48 +6486,76 @@ 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.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 // 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 + ); let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert_eq!(node_txn.len(), 2); // ChannelMonitor: bogus justice tx, justice tx on revoked outputs - // The first transaction generated is bogus - it spends both outputs of revoked_local_txn[0] - // including the one already spent by revoked_htlc_txn[1]. That's OK, we'll spend with valid - // transactions next... + // The first transaction generated is bogus - it spends both outputs of revoked_local_txn[0] + // including the one already spent by revoked_htlc_txn[1]. That's OK, we'll spend with valid + // transactions next... assert_eq!(node_txn[0].input.len(), 3); check_spends!(node_txn[0], revoked_local_txn[0], revoked_htlc_txn[0]); assert_eq!(node_txn[1].input.len(), 2); check_spends!(node_txn[1], revoked_local_txn[0], revoked_htlc_txn[0]); if node_txn[1].input[1].previous_output.txid == revoked_htlc_txn[0].txid() { - assert_ne!(node_txn[1].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output); + assert_ne!( + node_txn[1].input[0].previous_output, + revoked_htlc_txn[0].input[0].previous_output + ); } else { assert_eq!(node_txn[1].input[0].previous_output.txid, revoked_htlc_txn[0].txid()); - assert_ne!(node_txn[1].input[1].previous_output, revoked_htlc_txn[0].input[0].previous_output); + assert_ne!( + node_txn[1].input[1].previous_output, + revoked_htlc_txn[0].input[0].previous_output + ); } mine_transaction(&nodes[1], &node_txn[1]); @@ -4783,7 +6579,7 @@ 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.txid()); @@ -4791,18 +6587,27 @@ 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: @@ -4810,10 +6615,23 @@ 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 + ); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); assert_eq!(node_txn.len(), 2); // ChannelMonitor: justice tx on revoked commitment, justice tx on revoked HTLC-success @@ -4824,10 +6642,16 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { assert_eq!(node_txn[0].input.len(), 2); check_spends!(node_txn[0], revoked_local_txn[0], revoked_htlc_txn[0]); if node_txn[0].input[1].previous_output.txid == revoked_htlc_txn[0].txid() { - assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output); + assert_eq!( + node_txn[0].input[0].previous_output, + revoked_htlc_txn[0].input[0].previous_output + ); } else { assert_eq!(node_txn[0].input[0].previous_output.txid, revoked_htlc_txn[0].txid()); - assert_eq!(node_txn[0].input[1].previous_output, revoked_htlc_txn[0].input[0].previous_output); + assert_eq!( + node_txn[0].input[1].previous_output, + revoked_htlc_txn[0].input[0].previous_output + ); } assert_eq!(node_txn[1].input.len(), 1); @@ -4869,16 +6693,18 @@ 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); @@ -4893,26 +6719,48 @@ 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_v0_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 { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, outbound_amount_forwarded_msat } => { + Event::PaymentForwarded { + fee_earned_msat, + prev_channel_id, + claim_from_onchain_tx, + next_channel_id, + outbound_amount_forwarded_msat, + } => { assert_eq!(fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, Some(chan_1.2)); assert_eq!(claim_from_onchain_tx, true); @@ -4924,16 +6772,31 @@ 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, 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, + 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); @@ -4952,7 +6815,13 @@ 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); @@ -4977,30 +6846,47 @@ 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(4, &node_cfgs, - &[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())]); + let node_chanmgrs = create_node_chanmgrs( + 4, + &node_cfgs, + &[Some(config.clone()), Some(config.clone()), Some(config.clone()), Some(config.clone())], + ); let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2); create_announced_chan_between_nodes(&nodes, 2, 3); - 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); connect_blocks(&nodes[3], node_max_height - nodes[3].best_block_info().1); - let (our_payment_preimage, duplicate_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 900_000); + let (our_payment_preimage, duplicate_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 900_000); - let payment_secret = nodes[3].node.create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, None).unwrap(); + let payment_secret = nodes[3] + .node + .create_inbound_payment_for_hash(duplicate_payment_hash, None, 7200, None) + .unwrap(); // We reduce the final CLTV here by a somewhat arbitrary constant to keep it under the one-byte // script push size limit so that the below script length checks match // ACCEPTED_HTLC_SCRIPT_WEIGHT. - let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV - 40) - .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 - 40) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()) + .unwrap(); let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[3], payment_params, 800_000); - send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[3]]], 800_000, duplicate_payment_hash, payment_secret); + send_along_route_with_secret( + &nodes[0], + route, + &[&[&nodes[1], &nodes[2], &nodes[3]]], + 800_000, + duplicate_payment_hash, + payment_secret, + ); let commitment_txn = get_local_commitment_txn!(nodes[2], chan_2.2); assert_eq!(commitment_txn[0].input.len(), 1); @@ -5009,11 +6895,18 @@ 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 + ); connect_blocks(&nodes[1], TEST_FINAL_CLTV - 40 + MIN_CLTV_EXPIRY_DELTA as u32); // Confirm blocks until the HTLC expires let htlc_timeout_tx; - { // Extract one of the two HTLC-Timeout transaction + { + // Extract one of the two HTLC-Timeout transaction let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); // ChannelMonitor: timeout tx * 2-or-3 assert!(node_txn.len() == 2 || node_txn.len() == 3); @@ -5044,10 +6937,21 @@ fn test_duplicate_payment_hash_one_failure_one_success() { // Assign htlc_timeout_tx to the forwarded HTLC (with value ~800 sats). The received HTLC // (with value 900 sats) will be claimed in the below `claim_funds` call. if node_txn.len() > 2 { - assert_eq!(node_txn[2].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); - htlc_timeout_tx = if node_txn[2].output[0].value < 900 { node_txn[2].clone() } else { node_txn[0].clone() }; + assert_eq!( + node_txn[2].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); + htlc_timeout_tx = if node_txn[2].output[0].value < 900 { + node_txn[2].clone() + } else { + node_txn[0].clone() + }; } else { - htlc_timeout_tx = if node_txn[0].output[0].value < 900 { node_txn[1].clone() } else { node_txn[0].clone() }; + htlc_timeout_tx = if node_txn[0].output[0].value < 900 { + node_txn[1].clone() + } else { + node_txn[0].clone() + }; } } @@ -5056,7 +6960,13 @@ fn test_duplicate_payment_hash_one_failure_one_success() { mine_transaction(&nodes[2], &commitment_txn[0]); check_added_monitors!(nodes[2], 2); - 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 events = nodes[2].node.get_and_clear_pending_msg_events(); match events[0] { MessageSendEvent::UpdateHTLCs { .. } => {}, @@ -5071,15 +6981,33 @@ fn test_duplicate_payment_hash_one_failure_one_success() { check_spends!(htlc_success_txn[0], commitment_txn[0]); check_spends!(htlc_success_txn[1], commitment_txn[0]); assert_eq!(htlc_success_txn[0].input.len(), 1); - assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); + assert_eq!( + htlc_success_txn[0].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); 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); - assert_ne!(htlc_success_txn[0].input[0].previous_output, htlc_success_txn[1].input[0].previous_output); - assert_ne!(htlc_success_txn[1].input[0].previous_output, htlc_timeout_tx.input[0].previous_output); + assert_eq!( + htlc_success_txn[1].input[0].witness.last().unwrap().len(), + ACCEPTED_HTLC_SCRIPT_WEIGHT + ); + assert_ne!( + htlc_success_txn[0].input[0].previous_output, + htlc_success_txn[1].input[0].previous_output + ); + assert_ne!( + htlc_success_txn[1].input[0].previous_output, + htlc_timeout_tx.input[0].previous_output + ); 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); @@ -5088,12 +7016,21 @@ 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 + ); // Solve 2nd HTLC by broadcasting on B's chain HTLC-Success Tx from C mine_transaction(&nodes[1], &htlc_success_txn[1]); @@ -5106,7 +7043,10 @@ 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); } @@ -5134,7 +7074,13 @@ 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 { .. } => {}, @@ -5183,53 +7129,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, @@ -5255,10 +7271,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 @@ -5274,34 +7302,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 @@ -5331,7 +7409,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"), } @@ -5340,13 +7418,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[0..1], 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); @@ -5364,28 +7460,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); @@ -5399,7 +7528,13 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno let mut as_failds = HashSet::new(); 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_failds.insert(*payment_hash)); if *payment_hash != payment_hash_2 { assert_eq!(*payment_failed_permanently, deliver_last_raa); @@ -5410,7 +7545,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_failds.contains(&payment_hash_1)); assert!(as_failds.contains(&payment_hash_2)); @@ -5425,7 +7562,13 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno let mut bs_failds = HashSet::new(); 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_failds.insert(*payment_hash)); if *payment_hash != payment_hash_1 && *payment_hash != payment_hash_5 { assert_eq!(*payment_failed_permanently, deliver_last_raa); @@ -5436,7 +7579,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_failds.contains(&payment_hash_1)); assert!(bs_failds.contains(&payment_hash_2)); @@ -5449,8 +7594,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 + } + ); } #[test] @@ -5480,7 +7643,7 @@ 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); @@ -5489,7 +7652,13 @@ 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 = { @@ -5514,8 +7683,10 @@ 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 + ); } #[test] @@ -5530,12 +7701,32 @@ 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()); - 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); @@ -5551,24 +7742,32 @@ 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"); } @@ -5577,7 +7776,13 @@ 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(); @@ -5602,8 +7807,10 @@ 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 + ); } #[test] @@ -5615,11 +7822,17 @@ 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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [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); @@ -5627,7 +7840,13 @@ 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::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [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); @@ -5642,7 +7861,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. @@ -5651,10 +7871,15 @@ 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(&nodes[1].node.get_our_node_id(), &bs_updates.commitment_signed); + nodes[0] + .node + .handle_commitment_signed(&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); @@ -5666,10 +7891,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::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [nodes[0].node.get_our_node_id()], + 100000 + ); } fn do_htlc_claim_current_remote_commitment_only(use_dust: bool) { @@ -5679,9 +7915,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()); @@ -5693,14 +7937,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::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); } fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no_close: bool) { @@ -5717,19 +7969,31 @@ 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(&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(&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(&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); @@ -5738,7 +8002,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(); } @@ -5746,7 +8012,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::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); } else { expect_payment_failed!(nodes[0], our_payment_hash, true); } @@ -5782,7 +8054,8 @@ fn htlc_claim_single_commitment_only_b() { #[test] #[should_panic] -fn bolt2_open_channel_sending_node_checks_part1() { //This test needs to be on its own as we are catching a panic +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]); @@ -5793,16 +8066,42 @@ fn bolt2_open_channel_sending_node_checks_part1() { //This test needs to be on i } // 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); + 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()); } #[test] @@ -5813,30 +8112,67 @@ 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.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.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.channel_flags<=1); + assert!(node0_to_1_send_open_channel.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.to_self_delay==BREAKDOWN_TIMEOUT); + assert!(BREAKDOWN_TIMEOUT > 0); + assert!(node0_to_1_send_open_channel.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); @@ -5844,10 +8180,14 @@ fn bolt2_open_channel_sending_node_checks_part2() { // 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.funding_pubkey.serialize()).is_ok()); - assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.revocation_basepoint.serialize()).is_ok()); + assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.revocation_basepoint.serialize()) + .is_ok()); assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.htlc_basepoint.serialize()).is_ok()); assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.payment_point.serialize()).is_ok()); - assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.delayed_payment_basepoint.serialize()).is_ok()); + assert!(PublicKey::from_slice( + &node0_to_1_send_open_channel.delayed_payment_basepoint.serialize() + ) + .is_ok()); } #[test] @@ -5857,22 +8197,42 @@ 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.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 @@ -5899,9 +8259,10 @@ 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"), }; @@ -5913,12 +8274,21 @@ 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, 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(); chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2); assert_eq!(chan_stat.holding_cell_outbound_amount_msat, max_can_send); @@ -5934,13 +8304,24 @@ 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); @@ -5979,9 +8360,10 @@ 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"), }; @@ -5994,24 +8376,44 @@ 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, payment_hash_2, - RecipientOnionFields::secret_only(payment_secret_2), payment_id_2).unwrap(); + nodes[0] + .node + .send_payment_with_route( + &route_2, + 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(&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()); + 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(&nodes[1].node.get_our_node_id(), &commitment_signed); @@ -6022,13 +8424,24 @@ 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); @@ -6075,7 +8488,10 @@ 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); } @@ -6092,7 +8508,11 @@ 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); @@ -6109,9 +8529,10 @@ 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"), }; @@ -6123,11 +8544,20 @@ 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(); @@ -6145,7 +8575,8 @@ fn test_fail_holding_cell_htlc_upon_free_multihop() { // Flush the pending fee update. nodes[2].node.handle_commitment_signed(&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()); + 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(&nodes[2].node.get_our_node_id(), &commitment_signed); @@ -6156,9 +8587,7 @@ 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"), }; @@ -6197,7 +8626,8 @@ fn test_fail_holding_cell_htlc_upon_free_multihop() { nodes[0].node.handle_commitment_signed(&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(&nodes[0].node.get_our_node_id(), &commitment_signed); @@ -6209,7 +8639,13 @@ 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); } @@ -6224,8 +8660,10 @@ 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(); @@ -6250,12 +8688,21 @@ 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].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].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()); } @@ -6268,7 +8715,8 @@ 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].node.send_payment_with_route(&route, our_payment_hash, RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)), @@ -6276,7 +8724,11 @@ 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", 1); + nodes[0].logger.assert_log_contains( + "lightning::ln::channelmanager", + "Cannot send 0-msat HTLC", + 1, + ); } #[test] @@ -6288,19 +8740,40 @@ 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 + ); } #[test] @@ -6314,8 +8787,10 @@ 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].node.send_payment_with_route(&route, our_payment_hash, RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0) @@ -6333,37 +8808,72 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment() 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: _, updates: msgs::CommitmentUpdate{ update_add_htlcs: ref htlcs, .. }, } = events[0] { + if let MessageSendEvent::UpdateHTLCs { + node_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].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].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()); } @@ -6377,17 +8887,27 @@ 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].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].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); @@ -6405,23 +8925,40 @@ 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 + ); } #[test] @@ -6441,9 +8978,17 @@ 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()); @@ -6451,13 +8996,21 @@ 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 + ); } #[test] @@ -6476,10 +9029,23 @@ 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).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::signing_only(), + &route.paths[0], + &session_priv, + ) + .unwrap(); let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], send_amt, RecipientOnionFields::secret_only(our_payment_secret), cur_height, &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, + RecipientOnionFields::secret_only(our_payment_secret), + cur_height, + &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, @@ -6501,9 +9067,17 @@ 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 + ); } #[test] @@ -6515,19 +9089,39 @@ 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 + ); } #[test] @@ -6539,19 +9133,35 @@ 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 + ); } #[test] @@ -6565,24 +9175,52 @@ 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]); @@ -6591,19 +9229,33 @@ 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.htlc_signatures.len(), 1); - nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &updates.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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 + ); } #[test] @@ -6615,15 +9267,25 @@ 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, @@ -6633,9 +9295,19 @@ 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 + ); } #[test] @@ -6648,26 +9320,46 @@ 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: msgs::OnionErrorPacket { data: Vec::new()}, + reason: msgs::OnionErrorPacket { data: Vec::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 + ); } #[test] @@ -6680,13 +9372,23 @@ fn test_update_fulfill_htlc_bolt2_update_fail_malformed_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]); - 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], @@ -6697,9 +9399,19 @@ fn test_update_fulfill_htlc_bolt2_update_fail_malformed_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 + ); } #[test] @@ -6712,7 +9424,8 @@ 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); @@ -6722,7 +9435,18 @@ 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: _ , 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: _, + 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()); @@ -6742,7 +9466,13 @@ 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 + ); } #[test] @@ -6755,7 +9485,8 @@ 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); @@ -6765,7 +9496,18 @@ 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: _ , 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: _, + 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()); @@ -6783,9 +9525,17 @@ 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 + ); } #[test] @@ -6798,15 +9548,25 @@ fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_messag 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); @@ -6814,7 +9574,18 @@ fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_messag let mut update_msg: msgs::UpdateFailMalformedHTLC = { match events[0] { - MessageSendEvent::UpdateHTLCs { node_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: _, + 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()); @@ -6832,7 +9603,13 @@ fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_messag 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 + ); } #[test] @@ -6847,12 +9624,20 @@ fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_upda 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); @@ -6876,9 +9661,20 @@ fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_upda let events_3 = nodes[2].node.get_and_clear_pending_msg_events(); assert_eq!(events_3.len(), 1); - let update_msg : (msgs::UpdateFailMalformedHTLC, msgs::CommitmentSigned) = { + let update_msg: (msgs::UpdateFailMalformedHTLC, msgs::CommitmentSigned) = { match events_3[0] { - MessageSendEvent::UpdateHTLCs { node_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: _, + 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()); @@ -6890,17 +9686,36 @@ fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_upda } }; - nodes[1].node.handle_update_fail_malformed_htlc(&nodes[2].node.get_our_node_id(), &update_msg.0); + nodes[1] + .node + .handle_update_fail_malformed_htlc(&nodes[2].node.get_our_node_id(), &update_msg.0); 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: _ , 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: _, + 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); @@ -6922,12 +9737,20 @@ 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]) }; @@ -6953,22 +9776,31 @@ 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"), @@ -6980,11 +9812,18 @@ 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"), } @@ -7008,14 +9847,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 @@ -7024,12 +9875,19 @@ 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(&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(&nodes[1].node.get_our_node_id(), &remove.commitment_signed); check_added_monitors!(nodes[0], 1); // Cache one local commitment tx as lastest @@ -7059,7 +9917,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); @@ -7077,7 +9941,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"), } } @@ -7103,10 +9967,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); @@ -7115,14 +9992,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); @@ -7131,7 +10014,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]); @@ -7142,19 +10028,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].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].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); } @@ -7188,61 +10089,157 @@ fn test_user_configurable_csv_delay() { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in OutboundV1Channel::new() - if let Err(error) = OutboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::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) - { + if let Err(error) = OutboundV1Channel::new( + &LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { + sat_per_kw: Mutex::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, + ) { 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.to_self_delay = 200; - if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::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 { + sat_per_kw: Mutex::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) => { 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())); }, + ChannelError::Close(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 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.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.to_self_delay = 200; - if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::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 { + sat_per_kw: Mutex::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) => { 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(err.as_str())); }, + ChannelError::Close(err) => { + 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(err.as_str())); + }, _ => panic!("Unexpected event"), } - } else { assert!(false); } + } else { + assert!(false); + } } #[test] @@ -7261,15 +10258,36 @@ 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(); @@ -7281,7 +10299,10 @@ 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. @@ -7290,7 +10311,18 @@ 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: _ , 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: _, + 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); @@ -7308,7 +10340,13 @@ 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, 0x4000|15, &expected_failure_data[..]); + expect_payment_failed!( + nodes[0], + our_payment_hash, + true, + 0x4000 | 15, + &expected_failure_data[..] + ); } #[test] @@ -7338,9 +10376,12 @@ fn test_announce_disable_channels() { for e in msg_events { match e { MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - assert_eq!(msg.contents.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.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!"); } }, @@ -7348,14 +10389,32 @@ 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); @@ -7385,7 +10444,7 @@ fn test_announce_disable_channels() { for e in msg_events { match e { MessageSendEvent::BroadcastChannelUpdate { ref msg } => { - assert_eq!(msg.contents.flags & (1<<1), 0); // The "channel disabled" bit should be off + assert_eq!(msg.contents.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. @@ -7412,11 +10471,12 @@ 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_preimage = route_payment(&nodes[0], &vec![&nodes[1]][..], 3000000).0; let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), 30) - .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); + .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 @@ -7436,7 +10496,7 @@ 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); @@ -7518,18 +10578,39 @@ 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(); send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000); let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2); @@ -7537,13 +10618,22 @@ fn test_bump_penalty_txn_on_revoked_htlcs() { assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.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 = { @@ -7566,12 +10656,16 @@ 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_from_events!(nodes[0], events[0..1], true); match events.last().unwrap() { - Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {} + Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}, _ => panic!("Unexpected event"), } let first; @@ -7580,7 +10674,7 @@ fn test_bump_penalty_txn_on_revoked_htlcs() { { let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 4); // 3 penalty txn on revoked commitment tx + 1 penalty tnx on revoked HTLC txn - // Verify claim tx are spending revoked HTLC txn + // Verify claim tx are spending revoked HTLC txn // node_txn 0-2 each spend a separate revoked output from revoked_local_txn[0] // Note that node_txn[0] and node_txn[1] are bogus - they double spend the revoked_htlc_txn @@ -7600,8 +10694,14 @@ fn test_bump_penalty_txn_on_revoked_htlcs() { assert_ne!(node_txn[0].input[0].previous_output, node_txn[2].input[0].previous_output); assert_ne!(node_txn[1].input[0].previous_output, node_txn[2].input[0].previous_output); - assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output); - assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output); + assert_eq!( + node_txn[0].input[0].previous_output, + revoked_htlc_txn[1].input[0].previous_output + ); + assert_eq!( + node_txn[1].input[0].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). @@ -7611,7 +10711,8 @@ fn test_bump_penalty_txn_on_revoked_htlcs() { first = node_txn[3].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[3].output[0].value; + let fee_1 = revoked_htlc_txn[0].output[0].value + revoked_htlc_txn[1].output[0].value + - node_txn[3].output[0].value; feerate_1 = fee_1 * 1000 / node_txn[3].weight().to_wu(); penalty_txn = vec![node_txn[2].clone()]; node_txn.clear(); @@ -7635,7 +10736,8 @@ 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].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()]; @@ -7676,7 +10778,7 @@ fn test_bump_penalty_txn_on_remote_commitment() { 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]], 3_000_000); - route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000).0; + route_payment(&nodes[1], &vec![&nodes[0]][..], 3000000).0; // 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); @@ -7714,11 +10816,12 @@ fn test_bump_penalty_txn_on_remote_commitment() { let fee = remote_txn[0].output[index as usize].value - node_txn[0].output[0].value; 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]); @@ -7783,10 +10886,15 @@ 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_mut(&channel_id).map( - |phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).flatten().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_mut(&channel_id) + .map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) + .flatten() + .unwrap() + .get_signer(); const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; @@ -7799,22 +10907,37 @@ fn test_counterparty_raa_skip_no_crash() { keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1); 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()); + next_per_commitment_point = PublicKey::from_secret_key( + &Secp256k1::new(), + &SecretKey::from_slice( + &keys.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2), + ) + .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 + ); } #[test] @@ -7829,25 +10952,34 @@ 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.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(), 3); //ChannelMonitor: justice txn * 3 @@ -7861,7 +10993,11 @@ fn test_bump_txn_sanitize_tracking_maps() { connect_block(&nodes[0], &create_dummy_block(nodes[0].best_block_hash(), 42, penalty_txn)); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); { - let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(OutPoint { txid: chan.3.txid(), index: 0 }).unwrap(); + let monitor = nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(OutPoint { txid: chan.3.txid(), index: 0 }) + .unwrap(); assert!(monitor.inner.lock().unwrap().onchain_tx_handler.pending_claim_requests.is_empty()); assert!(monitor.inner.lock().unwrap().onchain_tx_handler.claimable_outpoints.is_empty()); } @@ -7876,7 +11012,8 @@ 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 @@ -7891,13 +11028,25 @@ 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"), } @@ -7914,10 +11063,24 @@ 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.channel_flags, 0); assert_eq!(res.to_self_delay, 200); } @@ -7931,12 +11094,30 @@ 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.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.htlc_minimum_msat, 1); } @@ -7950,20 +11131,37 @@ fn test_channel_update_has_correct_htlc_maximum_msat() { let mut config_30_percent = UserConfig::default(); config_30_percent.channel_handshake_config.announced_channel = 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.announced_channel = 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.announced_channel = 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.announced_channel = 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; @@ -7972,8 +11170,10 @@ 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`. @@ -7998,11 +11198,26 @@ fn test_manually_accept_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); - let temp_channel_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()); + let temp_channel_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); @@ -8013,8 +11228,11 @@ 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).unwrap(); - } + nodes[1] + .node + .accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 23) + .unwrap(); + }, _ => panic!("Unexpected event"), } @@ -8024,11 +11242,14 @@ fn test_manually_accept_inbound_channel_request() { match accept_msg_ev[0] { MessageSendEvent::SendAcceptChannel { ref node_id, .. } => { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - } + }, _ => panic!("Unexpected event"), } - nodes[1].node.force_close_broadcasting_latest_txn(&temp_channel_id, &nodes[0].node.get_our_node_id()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&temp_channel_id, &nodes[0].node.get_our_node_id()) + .unwrap(); let close_msg_ev = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(close_msg_ev.len(), 1); @@ -8037,7 +11258,7 @@ fn test_manually_accept_inbound_channel_request() { match events[0] { Event::ChannelClosed { user_channel_id, .. } => { assert_eq!(user_channel_id, 23); - } + }, _ => panic!("Unexpected event"), } } @@ -8048,11 +11269,26 @@ 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); @@ -8063,8 +11299,14 @@ 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()).unwrap(); - } + nodes[1] + .node + .force_close_broadcasting_latest_txn( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + ) + .unwrap(); + }, _ => panic!("Unexpected event"), } @@ -8074,7 +11316,7 @@ 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"), } @@ -8088,11 +11330,26 @@ 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); @@ -8103,8 +11360,15 @@ 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).unwrap(); - let api_res = nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0); + nodes[1] + .node + .accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0) + .unwrap(); + let api_res = nodes[1].node.accept_inbound_channel( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ); match api_res { Err(APIError::APIMisuseError { err }) => { assert_eq!(err, "No such channel awaiting to be accepted."); @@ -8112,7 +11376,7 @@ 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"), } @@ -8123,7 +11387,7 @@ 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"), } } @@ -8136,7 +11400,11 @@ 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); + let api_res = nodes[0].node.accept_inbound_channel( + &unknown_channel_id, + &nodes[1].node.get_our_node_id(), + 0, + ); match api_res { Err(APIError::APIMisuseError { err }) => { assert_eq!(err, "No such channel awaiting to be accepted."); @@ -8166,7 +11434,8 @@ 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(); @@ -8187,38 +11456,78 @@ 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).unwrap(); - let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], 100_000, - RecipientOnionFields::secret_only(our_payment_secret), height + 1, &None).unwrap(); + let mut onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ) + .unwrap(); + let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads( + &route.paths[0], + 100_000, + RecipientOnionFields::secret_only(our_payment_secret), + height + 1, + &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; } @@ -8242,14 +11551,23 @@ 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); + 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(&nodes[0], expected_paths, false, 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; @@ -8267,18 +11585,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; @@ -8293,22 +11619,50 @@ 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(&nodes[src_idx], &expected_paths, false, our_payment_preimage); @@ -8333,7 +11687,8 @@ 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(); @@ -8342,8 +11697,20 @@ 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(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, 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( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_preimage, + ); } #[test] @@ -8357,14 +11724,24 @@ 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 @@ -8373,13 +11750,11 @@ 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::InvoicePayment { payment_preimage, .. } => { - claim_payment(&nodes[0], &[&nodes[1]], payment_preimage.unwrap()); - }, - _ => panic!("expected PaymentPurpose::InvoicePayment") - } + Event::PaymentClaimable { ref purpose, .. } => match &purpose { + PaymentPurpose::InvoicePayment { payment_preimage, .. } => { + claim_payment(&nodes[0], &[&nodes[1]], payment_preimage.unwrap()); + }, + _ => panic!("expected PaymentPurpose::InvoicePayment"), }, _ => panic!("Unexpected event"), } @@ -8397,7 +11772,8 @@ 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 @@ -8407,48 +11783,98 @@ 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: _, 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: _, + 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 = 0x4000|15; // incorrect_or_unknown_payment_details - // Error data is the HTLC value (100,000) and current block height + let expected_error_code = 0x4000 | 15; // incorrect_or_unknown_payment_details + // Error data is the HTLC value (100,000) and current block height 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, our_payment_hash, - RecipientOnionFields::secret_only(random_payment_secret), PaymentId(our_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + &route, + 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, random_payment_hash, - RecipientOnionFields::secret_only(our_payment_secret), PaymentId(random_payment_hash.0)).unwrap(); + nodes[0] + .node + .send_payment_with_route( + &route, + 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 + ); } #[test] @@ -8472,7 +11898,7 @@ fn test_update_err_monitor_lockdown() { let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 }; // 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); @@ -8484,13 +11910,28 @@ fn test_update_err_monitor_lockdown() { let watchtower = { let new_monitor = { let monitor = nodes[0].chain_monitor.chain_monitor.get_monitor(outpoint).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(outpoint, 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(outpoint, new_monitor), + Ok(ChannelMonitorUpdateStatus::Completed) + ); watchtower }; let block = create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()); @@ -8506,15 +11947,34 @@ 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 ChannelPhase::Funded(ref mut channel) = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1.2) { - if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) { - assert_eq!(watchtower.chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::InProgress); - assert_eq!(nodes[0].chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::Completed); - } else { assert!(false); } + if let ChannelPhase::Funded(ref mut channel) = get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_1.2 + ) { + if let Ok(Some(update)) = + channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) + { + assert_eq!( + watchtower.chain_monitor.update_channel(outpoint, &update), + ChannelMonitorUpdateStatus::InProgress + ); + assert_eq!( + nodes[0].chain_monitor.update_channel(outpoint, &update), + ChannelMonitorUpdateStatus::Completed + ); + } else { + assert!(false); + } } else { assert!(false); } @@ -8542,35 +12002,55 @@ fn test_concurrent_monitor_claim() { let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 }; // 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(outpoint).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(outpoint, 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(outpoint, 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 @@ -8585,40 +12065,88 @@ 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(outpoint).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(outpoint, 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(outpoint, 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 ChannelPhase::Funded(ref mut channel) = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan_1.2) { - if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) { + if let ChannelPhase::Funded(ref mut channel) = get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + chan_1.2 + ) { + if let Ok(Some(update)) = + channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) + { // Watchtower Alice should already have seen the block and reject the update - assert_eq!(watchtower_alice.chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::InProgress); - assert_eq!(watchtower_bob.chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::Completed); - assert_eq!(nodes[0].chain_monitor.update_channel(outpoint, &update), ChannelMonitorUpdateStatus::Completed); - } else { assert!(false); } + assert_eq!( + watchtower_alice.chain_monitor.update_channel(outpoint, &update), + ChannelMonitorUpdateStatus::InProgress + ); + assert_eq!( + watchtower_bob.chain_monitor.update_channel(outpoint, &update), + ChannelMonitorUpdateStatus::Completed + ); + assert_eq!( + nodes[0].chain_monitor.update_channel(outpoint, &update), + ChannelMonitorUpdateStatus::Completed + ); + } else { + assert!(false); + } } else { assert!(false); } @@ -8627,7 +12155,10 @@ 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; @@ -8641,9 +12172,18 @@ 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::HolderForceClosed, 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::HolderForceClosed, + 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(); @@ -8671,24 +12211,59 @@ 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); - - 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 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 + ); } #[test] @@ -8708,8 +12283,8 @@ 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); @@ -8720,10 +12295,20 @@ 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 = { @@ -8735,12 +12320,17 @@ 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.) @@ -8765,7 +12355,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); @@ -8786,20 +12377,41 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain force_closing_node = 1; counterparty_node = 0; } - nodes[force_closing_node].node.force_close_broadcasting_latest_txn(&chan_ab.2, &nodes[counterparty_node].node.get_our_node_id()).unwrap(); + nodes[force_closing_node] + .node + .force_close_broadcasting_latest_txn( + &chan_ab.2, + &nodes[counterparty_node].node.get_our_node_id(), + ) + .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, [nodes[counterparty_node].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[force_closing_node], + 1, + ClosureReason::HolderForceClosed, + [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 + ); } } @@ -8817,9 +12429,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(); @@ -8831,7 +12453,10 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain _ => panic!("Unexpected event"), }; } - nodes[1].node.handle_commitment_signed(&nodes[2].node.get_our_node_id(), &carol_updates.commitment_signed); + nodes[1].node.handle_commitment_signed( + &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); @@ -8855,7 +12480,9 @@ 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(&nodes[1].node.get_our_node_id(), &bob_updates.commitment_signed); + nodes[2] + .node + .handle_commitment_signed(&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(); @@ -8873,14 +12500,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 { @@ -8903,7 +12541,7 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain { let script_weight = match broadcast_alice { true => OFFERED_HTLC_SCRIPT_WEIGHT, - false => ACCEPTED_HTLC_SCRIPT_WEIGHT + false => ACCEPTED_HTLC_SCRIPT_WEIGHT, }; // If Alice force-closed, Bob only broadcasts a HTLC-output-claiming transaction. Otherwise, // Bob force-closed and broadcasts the commitment transaction along with a @@ -8914,7 +12552,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(), 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(), script_weight); @@ -8940,12 +12581,26 @@ 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]. @@ -9005,32 +12660,69 @@ fn test_peer_funding_sidechannel() { let cs_funding_events = nodes[2].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[2].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[2], MessageSendEvent::SendFundingCreated, nodes[0].node.get_our_node_id()); + nodes[2] + .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[2], + MessageSendEvent::SendFundingCreated, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_funding_created(&nodes[2].node.get_our_node_id(), &funding_created_msg); get_event_msg!(nodes[0], MessageSendEvent::SendFundingSigned, nodes[2].node.get_our_node_id()); expect_channel_pending_event(&nodes[0], &nodes[2].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 outpoint ")); assert!(err_msg.contains(" is open with peer")); // Even though the last funding_transaction_generated errored, it still generated a // SendFundingCreated. However, when the peer responds with a funding_signed it will send the // appropriate error message. - let as_funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let as_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(), &as_funding_created); check_added_monitors!(nodes[1], 1); expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); - let reason = ClosureReason::ProcessingError { err: format!("An existing channel using outpoint {} is open with peer {}", funding_output, nodes[2].node.get_our_node_id()), }; - check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(ChannelId::v1_from_funding_outpoint(funding_output), true, reason)]); + let reason = ClosureReason::ProcessingError { + err: format!( + "An existing channel using outpoint {} is open with peer {}", + funding_output, + nodes[2].node.get_our_node_id() + ), + }; + check_closed_events( + &nodes[0], + &[ExpectedCloseEvent::from_id_reason( + ChannelId::v1_from_funding_outpoint(funding_output), + true, + reason, + )], + ); - 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); get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id()); } @@ -9058,11 +12750,22 @@ 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(funding_output, 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()); @@ -9071,8 +12774,13 @@ 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 funding outpoint was a duplicate".to_owned() }; - check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(funding_signed_msg.channel_id, true, err_reason)]); + let err_reason = ClosureReason::ProcessingError { + err: "Channel funding outpoint was a duplicate".to_owned(), + }; + check_closed_events( + &nodes[0], + &[ExpectedCloseEvent::from_id_reason(funding_signed_msg.channel_id, true, err_reason)], + ); } #[test] @@ -9091,22 +12799,45 @@ fn test_duplicate_funding_err_in_funding() { let real_chan_funding_txo = chain::transaction::OutPoint { txid: funding_tx.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.temporary_channel_id; open_chan_msg.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.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); - - 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()); + 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() + ); 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; @@ -9138,10 +12869,24 @@ 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. @@ -9150,7 +12895,10 @@ 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 @@ -9163,12 +12911,24 @@ fn test_duplicate_chan_id() { } // Move the first channel through the funding flow... - 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 (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(); 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() + ); nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg); { let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); @@ -9178,9 +12938,16 @@ 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 @@ -9195,7 +12962,10 @@ 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.temporary_channel_id); @@ -9206,15 +12976,30 @@ 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 @@ -9222,10 +13007,13 @@ fn test_duplicate_chan_id() { match a_peer_state.channel_by_id.remove(&open_chan_2_msg.temporary_channel_id).unwrap() { ChannelPhase::UnfundedOutboundV1(mut chan) => { 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() }, _ => panic!("Unexpected ChannelPhase variant"), - }.unwrap() + } + .unwrap() }; check_added_monitors!(nodes[0], 0); nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created); @@ -9233,18 +13021,26 @@ 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); @@ -9270,8 +13066,10 @@ 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); @@ -9299,26 +13097,51 @@ 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] { @@ -9360,29 +13183,70 @@ 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_v0_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()); @@ -9395,37 +13259,51 @@ 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: 2i32, lock_time: LockTime::ZERO, - input: tx.output.iter().enumerate().map(|(idx, _)| TxIn { - previous_output: BitcoinOutPoint { - txid: tx.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: 1000, - script_pubkey: ScriptBuf::new(), - }] + version: 2i32, + lock_time: LockTime::ZERO, + input: tx + .output + .iter() + .enumerate() + .map(|(idx, _)| TxIn { + previous_output: BitcoinOutPoint { txid: tx.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: 1000, script_pubkey: ScriptBuf::new() }], }; check_spends!(spend_tx, tx); mine_transaction(&nodes[1], &spend_tx); @@ -9445,26 +13323,57 @@ 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); @@ -9481,7 +13390,14 @@ 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); @@ -9520,9 +13436,18 @@ 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()); - nodes[1].node.force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&channel_id, &nodes[2].node.get_our_node_id()) + .unwrap(); check_closed_broadcast!(nodes[1], true); - check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[2].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [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); @@ -9532,7 +13457,10 @@ fn do_test_tx_confirmed_skipping_blocks_immediate_broadcast(test_height_before_t connect_blocks(&nodes[1], 24 * 6); } 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 @@ -9557,8 +13485,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()); @@ -9567,9 +13504,18 @@ 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 + ); } } @@ -9587,20 +13533,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, 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); 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]); @@ -9608,13 +13566,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 @@ -9633,34 +13600,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); } @@ -9694,19 +13693,25 @@ 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]); @@ -9716,23 +13721,60 @@ 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); { @@ -9740,7 +13782,9 @@ 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]); @@ -9750,7 +13794,9 @@ 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); @@ -9760,34 +13806,78 @@ 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); + 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(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage); + do_claim_payment_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + our_payment_preimage, + ); expect_payment_sent(&nodes[0], our_payment_preimage, Some(None), true, true); } @@ -9807,15 +13897,26 @@ 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. @@ -9829,17 +13930,39 @@ 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. @@ -9859,7 +13982,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) { +fn do_test_max_dust_htlc_exposure( + dust_outbound_balance: bool, exposure_breach_event: ExposureEvent, on_holder_tx: bool, + multiplier_dust_limit: bool, +) { // Test that we properly reject dust HTLC violating our `max_dust_htlc_exposure_msat` // policy. // @@ -9879,30 +14005,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 / 253) - } else { MaxDustHTLCExposure::FixedLimitMsat(5_000_000) }; // initial default setting value + } else { + MaxDustHTLCExposure::FixedLimitMsat(5_000_000) + }; // initial default setting value 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.max_htlc_value_in_flight_msat = 50_000_000; open_channel.max_accepted_htlcs = 60; if on_holder_tx { open_channel.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; - match get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, temporary_channel_id) { + match get_channel_ref!( + nodes[0], + nodes[1], + node_0_per_peer_lock, + node_0_peer_state_lock, + temporary_channel_id + ) { ChannelPhase::UnfundedOutboundV1(chan) => { chan.context.holder_dust_limit_satoshis = 546; }, @@ -9910,17 +14056,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); // Fetch a route in advance as we will be unable to once we're unable to send. @@ -9929,19 +14098,32 @@ 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(&LowerBoundedFeeEstimator(nodes[0].fee_estimator))) + ( + chan.context().get_dust_buffer_feerate(None) as u64, + chan.context() + .get_max_dust_htlc_exposure_msat(&LowerBoundedFeeEstimator(nodes[0].fee_estimator)), + ) }; - let dust_outbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + open_channel.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_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000; - let dust_inbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_inbound_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.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_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate + * htlc_success_tx_weight(&channel_type_features) + / 1000 + open_channel.dust_limit_satoshis + - 1) * 1000; + let dust_inbound_htlc_on_holder_tx: u64 = + max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat; let dust_htlc_on_counterparty_tx: u64 = 4; - let dust_htlc_on_counterparty_tx_msat: u64 = max_dust_htlc_exposure_msat / dust_htlc_on_counterparty_tx; + let dust_htlc_on_counterparty_tx_msat: u64 = + max_dust_htlc_exposure_msat / dust_htlc_on_counterparty_tx; if on_holder_tx { if dust_outbound_balance { @@ -9949,9 +14131,20 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e // Outbound dust balance: 4372 sats // Note, we need sent payment to be above outbound dust threshold on counterparty_tx of 2132 sats for _ in 0..dust_outbound_htlc_on_holder_tx { - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], dust_outbound_htlc_on_holder_tx_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], + dust_outbound_htlc_on_holder_tx_msat + ); + nodes[0] + .node + .send_payment_with_route( + &route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); } } else { // Inbound dust threshold: 2324 sats (`dust_buffer_feerate` * HTLC_SUCCESS_TX_WEIGHT / 1000 + holder's `dust_limit_satoshis`) @@ -9966,9 +14159,20 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e // Outbound dust threshold: 2132 sats (`dust_buffer_feerate` * HTLC_TIMEOUT_TX_WEIGHT / 1000 + counteparty's `dust_limit_satoshis`) // Outbound dust balance: 5000 sats for _ in 0..dust_htlc_on_counterparty_tx - 1 { - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], dust_htlc_on_counterparty_tx_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], + dust_htlc_on_counterparty_tx_msat + ); + nodes[0] + .node + .send_payment_with_route( + &route, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_hash.0), + ) + .unwrap(); } } else { // Inbound dust threshold: 2031 sats (`dust_buffer_feerate` * HTLC_TIMEOUT_TX_WEIGHT / 1000 + counteparty's `dust_limit_satoshis`) @@ -9980,32 +14184,71 @@ 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].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].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].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].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]); // 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 @@ -10020,9 +14263,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..20 { - let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(1_000), None); - nodes[0].node.send_payment_with_route(&route, 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, + 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(); @@ -10030,7 +14281,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(); @@ -10040,17 +14295,72 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e fn do_test_max_dust_htlc_exposure_by_threshold_type(multiplier_dust_limit: bool) { do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCForward, + true, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCReception, + true, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCReception, + false, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtHTLCForward, + false, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtHTLCReception, + false, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtHTLCReception, + true, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtHTLCForward, + false, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtUpdateFeeOutbound, + true, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + true, + ExposureEvent::AtUpdateFeeOutbound, + false, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtUpdateFeeOutbound, + false, + multiplier_dust_limit, + ); + do_test_max_dust_htlc_exposure( + false, + ExposureEvent::AtUpdateFeeOutbound, + true, + multiplier_dust_limit, + ); } #[test] @@ -10066,33 +14376,59 @@ 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: chan_id as i32, lock_time: LockTime::from_height(best_height + 2).unwrap(), input: vec![input], output: vec![TxOut { - value: *channel_value_satoshis, script_pubkey: output_script.clone(), - }]} + Transaction { + version: chan_id as i32, + lock_time: LockTime::from_height(best_height + 2).unwrap(), + input: vec![input], + output: vec![TxOut { + value: *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 events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); @@ -10111,30 +14447,59 @@ 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: chan_id as i32, lock_time: LockTime::from_consensus(best_height + 1), input: vec![input], output: vec![TxOut { - value: *channel_value_satoshis, script_pubkey: output_script.clone(), - }]} + Transaction { + version: chan_id as i32, + lock_time: LockTime::from_consensus(best_height + 1), + input: vec![input], + output: vec![TxOut { + value: *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()); } @@ -10167,8 +14532,13 @@ 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"), @@ -10186,8 +14556,13 @@ 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"), @@ -10205,11 +14580,24 @@ 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::ProcessingError { - err: "Peer's feerate much too low. Actual: 1000. Our expected lower limit: 5000".to_owned() }, - [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::ProcessingError { + err: + "Peer's feerate much too low. Actual: 1000. Our expected lower limit: 5000" + .to_owned() + }, + [nodes[0].node.get_our_node_id()], + 100000 + ); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); }, @@ -10223,24 +14611,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); @@ -10250,17 +14658,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); @@ -10286,17 +14706,18 @@ 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); }; @@ -10328,21 +14749,34 @@ 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(&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( + &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(&nodes[1].node.get_our_node_id(), &bob_commitment_signed); + nodes[0] + .node + .handle_commitment_signed(&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. @@ -10352,11 +14786,15 @@ 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(); @@ -10364,21 +14802,32 @@ 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 { @@ -10411,10 +14860,21 @@ 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(); @@ -10427,7 +14887,8 @@ 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); }; @@ -10447,12 +14908,25 @@ 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, false, &[nodes[1].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); } #[test] @@ -10462,10 +14936,21 @@ 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(); @@ -10478,7 +14963,8 @@ 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); }; @@ -10498,12 +14984,25 @@ 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, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); } fn do_test_multi_post_event_actions(do_reload: bool) { @@ -10527,8 +15026,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); @@ -10539,29 +15040,55 @@ 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(&nodes[1].node.get_our_node_id(), &send_event.commitment_msg); + nodes[0] + .node + .handle_commitment_signed(&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()); @@ -10574,12 +15101,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. @@ -10601,17 +15138,23 @@ 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]); + 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); @@ -10619,11 +15162,17 @@ fn test_batch_channel_open() { assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0); // Go through the funding_created and funding_signed flow with node 2. - nodes[2].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msgs[1]); + nodes[2] + .node + .handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msgs[1]); 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); @@ -10634,9 +15183,9 @@ 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.txid(), index: 1 }) - ); + nodes[0].chain_monitor.complete_sole_pending_chan_update(&ChannelId::v1_from_funding_outpoint( + OutPoint { txid: tx.txid(), index: 1 }, + )); let events = nodes[0].node.get_and_clear_pending_events(); // The transaction should only have been broadcast now. @@ -10669,17 +15218,23 @@ fn test_disconnect_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]); + 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); @@ -10694,22 +15249,25 @@ fn test_disconnect_in_funding_batch() { let funding_txo_2 = OutPoint { txid: tx.txid(), index: 1 }; let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); - 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() + }, + ], + ); // The monitor should become closed. check_added_monitors(&nodes[0], 1); @@ -10736,26 +15294,38 @@ 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]); + 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); // Go through the funding_created and funding_signed flow with node 2. - nodes[2].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msgs[1]); + nodes[2] + .node + .handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msgs[1]); 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); @@ -10768,7 +15338,10 @@ fn test_batch_funding_close_after_funding_signed() { let funding_txo_2 = OutPoint { txid: tx.txid(), index: 1 }; let channel_id_1 = ChannelId::v1_from_funding_outpoint(funding_txo_1); let channel_id_2 = ChannelId::v1_from_funding_outpoint(funding_txo_2); - nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id()) + .unwrap(); check_added_monitors(&nodes[0], 2); { let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap(); @@ -10795,22 +15368,25 @@ 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()); @@ -10823,30 +15399,46 @@ 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), Some(min_depth_1_block_cfg)]); + let node_chanmgrs = create_node_chanmgrs( + 2, + &node_cfgs, + &[Some(min_depth_1_block_cfg), 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.txid(), index: 0 }); + let chan_id = ChannelId::v1_from_funding_outpoint(chain::transaction::OutPoint { + txid: funding_tx.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]) }; - closing_node.node.force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id()).unwrap(); + closing_node + .node + .force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id()) + .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::DisconnectPeer { .. }, .. } => {}, + MessageSendEvent::HandleError { + action: msgs::ErrorAction::DisconnectPeer { .. }, .. + } => {}, _ => panic!("Unexpected event"), } check_added_monitors(closing_node, 1); - check_closed_event(closing_node, 1, ClosureReason::HolderForceClosed, false, &[other_node.node.get_our_node_id()], 1_000_000); + check_closed_event( + closing_node, + 1, + ClosureReason::HolderForceClosed, + false, + &[other_node.node.get_our_node_id()], + 1_000_000, + ); let commitment_tx = { let mut txn = closing_node.tx_broadcaster.txn_broadcast(); @@ -10861,7 +15453,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()); diff --git a/lightning/src/ln/inbound_payment.rs b/lightning/src/ln/inbound_payment.rs index eeae514fdf3..4fcc4a7e2fd 100644 --- a/lightning/src/ln/inbound_payment.rs +++ b/lightning/src/ln/inbound_payment.rs @@ -9,19 +9,19 @@ //! Utilities to generate inbound payment information in service of invoice creation. -use alloc::string::ToString; -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 crate::sign::{KeyMaterial, EntropySource}; -use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; -use crate::ln::msgs; -use crate::ln::msgs::MAX_VALUE_MSAT; use crate::crypto::chacha20::ChaCha20; use crate::crypto::utils::hkdf_extract_expand_5x; +use crate::ln::msgs; +use crate::ln::msgs::MAX_VALUE_MSAT; +use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; +use crate::sign::{EntropySource, KeyMaterial}; use crate::util::errors::APIError; use crate::util::logger::Logger; +use alloc::string::ToString; +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 core::convert::{TryFrom, TryInto}; use core::ops::Deref; @@ -79,7 +79,7 @@ impl ExpandedKey { /// /// [`Offer::metadata`]: crate::offers::offer::Offer::metadata pub(crate) fn hmac_for_offer( - &self, nonce: Nonce, iv_bytes: &[u8; IV_LEN] + &self, nonce: Nonce, iv_bytes: &[u8; IV_LEN], ) -> HmacEngine { let mut hmac = HmacEngine::::new(&self.offers_base_key); hmac.input(iv_bytes); @@ -154,8 +154,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) + }, unknown => Err(unknown), } } @@ -181,16 +185,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_material`]: crate::sign::NodeSigner::get_inbound_payment_key_material -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(); @@ -216,13 +228,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); @@ -235,8 +255,10 @@ pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option, payment Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key)) } -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(()); } @@ -257,13 +279,17 @@ fn construct_metadata_bytes(min_value_msat: Option, payment_type: Method, // `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(); @@ -279,13 +305,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) } @@ -326,14 +358,17 @@ fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METAD /// [`NodeSigner::get_inbound_payment_key_material`]: crate::sign::NodeSigner::get_inbound_payment_key_material /// [`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]); @@ -350,34 +385,52 @@ 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(()); + }, } }, 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()); @@ -385,42 +438,59 @@ 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(), + }) + }, + Err(other) => { + Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }) }, - Ok(Method::UserPaymentHash) | Ok(Method::UserPaymentHashCustomFinalCltv) => Err(APIError::APIMisuseError { - err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash".to_string() - }), - 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) @@ -428,7 +498,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); @@ -436,5 +509,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/mod.rs b/lightning/src/ln/mod.rs index e79f4bbd24d..483590015d7 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -13,16 +13,16 @@ #[macro_use] pub mod functional_test_utils; -pub mod onion_payment; -pub mod channelmanager; +pub mod chan_utils; +mod channel_id; pub mod channel_keys; +pub mod channelmanager; +pub mod features; pub mod inbound_payment; pub mod msgs; +pub mod onion_payment; pub mod peer_handler; -pub mod chan_utils; -pub mod features; pub mod script; -mod channel_id; #[cfg(fuzzing)] pub mod peer_channel_encryptor; @@ -46,42 +46,42 @@ pub use onion_utils::create_payment_onion; // without the node parameter being mut. This is incorrect, and thus newer rustcs will complain // about an unnecessary mut. Thus, we silence the unused_mut warning in two test modules below. +#[cfg(all(test, async_signing))] +#[allow(unused_mut)] +mod async_signer_tests; #[cfg(test)] #[allow(unused_mut)] mod blinded_payment_tests; #[cfg(test)] #[allow(unused_mut)] -mod functional_tests; +mod chanmon_update_fail_tests; #[cfg(test)] #[allow(unused_mut)] -mod payment_tests; +mod functional_tests; #[cfg(test)] #[allow(unused_mut)] -mod priv_short_conf_tests; +mod monitor_tests; #[cfg(test)] #[allow(unused_mut)] -mod chanmon_update_fail_tests; +mod offers_tests; #[cfg(test)] #[allow(unused_mut)] -mod reorg_tests; +mod onion_route_tests; #[cfg(test)] #[allow(unused_mut)] -mod reload_tests; +mod payment_tests; #[cfg(test)] #[allow(unused_mut)] -mod onion_route_tests; +mod priv_short_conf_tests; #[cfg(test)] #[allow(unused_mut)] -mod monitor_tests; +mod reload_tests; #[cfg(test)] #[allow(unused_mut)] -mod shutdown_tests; -#[cfg(all(test, async_signing))] -#[allow(unused_mut)] -mod async_signer_tests; +mod reorg_tests; #[cfg(test)] #[allow(unused_mut)] -mod offers_tests; +mod shutdown_tests; pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN; @@ -117,14 +117,14 @@ pub struct PaymentSecret(pub [u8; 32]); use crate::prelude::*; use bitcoin::bech32; -use bitcoin::bech32::{Base32Len, FromBase32, ToBase32, WriteBase32, u5}; +use bitcoin::bech32::{u5, Base32Len, FromBase32, ToBase32, WriteBase32}; impl FromBase32 for PaymentSecret { type Err = bech32::Error; fn from_base32(field_data: &[u5]) -> Result { if field_data.len() != 52 { - return Err(bech32::Error::InvalidLength) + return Err(bech32::Error::InvalidLength); } else { let data_bytes = Vec::::from_base32(field_data)?; let mut payment_secret = [0; 32]; diff --git a/lightning/src/ln/monitor_tests.rs b/lightning/src/ln/monitor_tests.rs index 6a56c3cf816..e8ab852f45b 100644 --- a/lightning/src/ln/monitor_tests.rs +++ b/lightning/src/ln/monitor_tests.rs @@ -9,28 +9,30 @@ //! Further functional tests which test blockchain reorganizations. -use crate::sign::{ecdsa::EcdsaChannelSigner, SpendableOutputDescriptor}; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS, Balance}; +use crate::chain::chaininterface::{compute_feerate_sat_per_1000_weight, LowerBoundedFeeEstimator}; +use crate::chain::channelmonitor::{Balance, ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS}; use crate::chain::transaction::OutPoint; -use crate::chain::chaininterface::{LowerBoundedFeeEstimator, compute_feerate_sat_per_1000_weight}; +use crate::crypto::utils::sign; use crate::events::bump_transaction::{BumpTransactionEvent, WalletSource}; -use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination}; -use crate::ln::{channel, ChannelId}; -use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, PaymentId, RecipientOnionFields}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, +}; +use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, BREAKDOWN_TIMEOUT}; use crate::ln::msgs::ChannelMessageHandler; +use crate::ln::{channel, ChannelId}; +use crate::sign::{ecdsa::EcdsaChannelSigner, SpendableOutputDescriptor}; use crate::util::config::UserConfig; -use crate::crypto::utils::sign; -use crate::util::ser::Writeable; use crate::util::scid_utils::block_from_scid; +use crate::util::ser::Writeable; use crate::util::test_utils; -use bitcoin::{Amount, PublicKey, ScriptBuf, Transaction, TxIn, TxOut, Witness}; use bitcoin::blockdata::locktime::absolute::LockTime; -use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; +use bitcoin::blockdata::script::Builder; use bitcoin::hashes::hex::FromHex; use bitcoin::secp256k1::{Secp256k1, SecretKey}; -use bitcoin::sighash::{SighashCache, EcdsaSighashType}; +use bitcoin::sighash::{EcdsaSighashType, SighashCache}; +use bitcoin::{Amount, PublicKey, ScriptBuf, Transaction, TxIn, TxOut, Witness}; use crate::prelude::*; @@ -61,15 +63,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]); @@ -81,33 +93,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] @@ -136,7 +187,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); let bs_spend_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); @@ -170,7 +227,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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = @@ -181,28 +239,58 @@ 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 * channel::commitment_tx_base_weight(&channel_type_features) / 1000; + let commitment_tx_fee = + chan_feerate * channel::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 }], - nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); - assert_eq!(vec![Balance::ClaimableOnChannelClose { amount_satoshis: 1_000, }], - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ); + assert_eq!( + vec![Balance::ClaimableOnChannelClose { amount_satoshis: 1_000 }], + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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); @@ -218,47 +306,91 @@ 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, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ); + assert_eq!( + vec![Balance::ClaimableAwaitingConfirmations { amount_satoshis: 1000, confirmation_height: nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1, }], - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances()); - assert_eq!(Vec::::new(), - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + Vec::::new(), + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ); + assert_eq!( + Vec::::new(), + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 1000000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 1000000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 1000000 + ); } #[test] @@ -301,7 +433,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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -320,8 +453,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.txid(), vout: 0 }, coinbase_tx.output[0].value); - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 1 }, coinbase_tx.output[1].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); + nodes[1].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 1 }, + coinbase_tx.output[1].value, + ); } let (_, _, chan_id, funding_tx) = @@ -333,9 +472,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_000); // 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_000); + let (timeout_payment_preimage, timeout_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 4_000_000); // 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 @@ -378,17 +519,46 @@ 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 * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate as u64 + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::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, - }, sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 1_000, - }, received_htlc_balance.clone(), received_htlc_timeout_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + }, + sent_htlc_balance.clone(), + sent_htlc_timeout_balance.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { amount_satoshis: 1_000 }, + received_htlc_balance.clone(), + received_htlc_timeout_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); nodes[1].node.claim_funds(payment_preimage); check_added_monitors!(nodes[1], 1); @@ -407,25 +577,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(&nodes[1].node.get_our_node_id(), &b_htlc_msgs.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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(&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 * - (channel::commitment_tx_base_weight(&channel_type_features) + - if prev_commitment_tx { 1 } else { 2 } * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; - let mut a_expected_balances = vec![Balance::ClaimableOnChannelClose { + let commitment_tx_fee = chan_feerate as u64 + * (channel::commitment_tx_base_weight(&channel_type_features) + + if prev_commitment_tx { 1 } else { 2 } * channel::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 @@ -433,16 +615,32 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { 3 - // The dust HTLC value in satoshis commitment_tx_fee - // The commitment transaction fee with two HTLC outputs anchor_outputs_value, // The anchor outputs value in satoshis - }, 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(funding_outpoint).unwrap().get_claimable_balances())); - assert_eq!(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 1_000 + 3_000 + 4_000, - }], - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + sorted_vec(a_expected_balances), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); + assert_eq!( + vec![Balance::ClaimableOnChannelClose { amount_satoshis: 1_000 + 3_000 + 4_000 }], + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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. @@ -456,13 +654,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"); @@ -481,17 +683,35 @@ 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, 3_000); - assert_eq!(remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize].value, 4_000); + assert_eq!( + remote_txn[0].output[b_broadcast_txn[0].input[0].previous_output.vout as usize].value, + 3_000 + ); + assert_eq!( + remote_txn[0].output[b_broadcast_txn[1].input[0].previous_output.vout as usize].value, + 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()); @@ -501,23 +721,53 @@ 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 * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 3_000 - 4_000 - 1_000 - 3 - commitment_tx_fee - anchor_outputs_value, - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - }, sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + let commitment_tx_fee = chan_feerate as u64 + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 3_000 - 4_000 - 1_000 + - 3 - commitment_tx_fee + - anchor_outputs_value, + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + }, + sent_htlc_balance.clone(), + sent_htlc_timeout_balance.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - }, - // 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(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000, + confirmation_height: node_b_commitment_claimable, + }, + // 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(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); expect_payment_failed!(nodes[0], dust_payment_hash, false); @@ -525,13 +775,35 @@ 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(funding_outpoint).unwrap().get_claimable_balances())); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000, - confirmation_height: node_b_commitment_claimable, - }, received_htlc_claiming_balance.clone(), received_htlc_timeout_claiming_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000, + confirmation_height: node_b_commitment_claimable, + }, + received_htlc_claiming_balance.clone(), + received_htlc_timeout_claiming_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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()); @@ -544,11 +816,27 @@ 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(funding_outpoint).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(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + vec![sent_htlc_timeout_balance.clone()], + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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); @@ -558,26 +846,48 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) { check_spends!(a_broadcast_txn[0], remote_txn[0]); assert_eq!(a_broadcast_txn[1].input.len(), 1); check_spends!(a_broadcast_txn[1], remote_txn[0]); - assert_ne!(a_broadcast_txn[0].input[0].previous_output.vout, - a_broadcast_txn[1].input[0].previous_output.vout); + assert_ne!( + a_broadcast_txn[0].input[0].previous_output.vout, + a_broadcast_txn[1].input[0].previous_output.vout + ); // a_broadcast_txn [0] and [1] should spend the HTLC outputs of the commitment tx - assert_eq!(remote_txn[0].output[a_broadcast_txn[0].input[0].previous_output.vout as usize].value, 3_000); - assert_eq!(remote_txn[0].output[a_broadcast_txn[1].input[0].previous_output.vout as usize].value, 4_000); + assert_eq!( + remote_txn[0].output[a_broadcast_txn[0].input[0].previous_output.vout as usize].value, + 3_000 + ); + assert_eq!( + remote_txn[0].output[a_broadcast_txn[1].input[0].previous_output.vout as usize].value, + 4_000 + ); // Once the HTLC-Timeout transaction confirms, A will no longer consider the HTLC // "MaybeClaimable", but instead move it to "AwaitingConfirmations". mine_transaction(&nodes[0], &a_broadcast_txn[1]); 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, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + Vec::::new(), + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ); expect_payment_failed!(nodes[0], timeout_payment_hash, false); test_spendable_output(&nodes[0], &a_broadcast_txn[1], false); @@ -588,43 +898,89 @@ 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, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 3_000, - confirmation_height: node_b_htlc_claimable, - }, received_htlc_timeout_claiming_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000, + confirmation_height: node_b_commitment_claimable, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 3_000, + confirmation_height: node_b_htlc_claimable, + }, + received_htlc_timeout_claiming_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - }, received_htlc_timeout_claiming_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 3_000, + confirmation_height: node_b_htlc_claimable, + }, + received_htlc_timeout_claiming_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + vec![received_htlc_timeout_claiming_balance.clone()], + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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_broadcast_txn[1]); - assert_eq!(vec![received_htlc_timeout_claiming_balance.clone()], - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + vec![received_htlc_timeout_claiming_balance.clone()], + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ); connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1); - assert_eq!(Vec::::new(), - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + Vec::::new(), + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 @@ -633,7 +989,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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(node + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + .is_empty()); } } @@ -662,7 +1024,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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -681,35 +1044,62 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { ], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, coinbase_tx.output[0].value); - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 1 }, coinbase_tx.output[1].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); + nodes[1].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.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 funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 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]); @@ -725,10 +1115,19 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { // First confirm the commitment transaction on nodes[0], which should leave us with three // claimable balances. 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()) + .unwrap(); check_added_monitors!(nodes[0], 1); check_closed_broadcast!(nodes[0], true); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [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); @@ -754,20 +1153,43 @@ fn do_test_balances_on_local_commitment_htlcs(anchors: bool) { payment_hash: payment_hash_2, }; - let commitment_tx_fee = chan_feerate * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::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, - }, htlc_balance_known_preimage.clone(), htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + }, + htlc_balance_known_preimage.clone(), + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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); @@ -775,11 +1197,26 @@ 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, - }, htlc_balance_known_preimage.clone(), htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + }, + htlc_balance_known_preimage.clone(), + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); if anchors { handle_bump_htlc_event(&nodes[0], 2); } @@ -795,27 +1232,57 @@ 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, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: node_a_htlc_claimable, - }, htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: node_a_htlc_claimable, + }, + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); // 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, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: node_a_htlc_claimable, - }, htlc_balance_unknown_preimage.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: node_a_htlc_claimable, + }, + htlc_balance_unknown_preimage.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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" @@ -823,36 +1290,65 @@ 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, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: node_a_htlc_claimable, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: node_a_htlc_claimable, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, }], - nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 @@ -861,7 +1357,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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -879,7 +1381,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); let funding_outpoint = OutPoint { txid: funding_tx.txid(), index: 0 }; // Send two HTLCs, one from A to B, and one from B to A. @@ -915,16 +1418,43 @@ fn test_no_preimage_inbound_htlc_balances() { // receive the preimage. These will remain the same through the channel closure and until the // HTLC output is spent. - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - }, a_received_htlc_balance.clone(), a_sent_htlc_balance.clone()]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 - chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, + }, + a_received_htlc_balance.clone(), + a_sent_htlc_balance.clone() + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); - assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose { - amount_satoshis: 500_000 - 20_000, - }, b_received_htlc_balance.clone(), b_sent_htlc_balance.clone()]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { amount_satoshis: 500_000 - 20_000 }, + b_received_htlc_balance.clone(), + b_sent_htlc_balance.clone() + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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); @@ -935,33 +1465,75 @@ 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 * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::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 + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, confirmation_height: node_a_commitment_claimable, - }, 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(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + as_pre_spend_claims, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - }, 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(funding_outpoint).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(funding_outpoint) + .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 @@ -969,64 +1541,144 @@ 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(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + as_pre_spend_claims, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + as_pre_spend_claims, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + bs_pre_spend_claims, + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + bs_pre_spend_claims, + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - confirmation_height: node_a_commitment_claimable, - }, a_received_htlc_balance.clone(), Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: as_timeout_claimable_height, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 - chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, + confirmation_height: node_a_commitment_claimable, + }, + a_received_htlc_balance.clone(), + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: as_timeout_claimable_height, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - confirmation_height: node_a_commitment_claimable, - }, a_received_htlc_balance.clone(), Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: as_timeout_claimable_height, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 - chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, + confirmation_height: node_a_commitment_claimable, + }, + a_received_htlc_balance.clone(), + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: as_timeout_claimable_height, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); // Once as_htlc_timeout_claim[0] reaches ANTI_REORG_DELAY confirmations, we should get a // payment failure event. @@ -1034,54 +1686,119 @@ 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 * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000, - confirmation_height: node_a_commitment_claimable, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 10_000, - confirmation_height: core::cmp::max(as_timeout_claimable_height, htlc_cltv_timeout), - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 500_000 - 10_000 - chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000, + confirmation_height: node_a_commitment_claimable, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 10_000, + confirmation_height: core::cmp::max(as_timeout_claimable_height, htlc_cltv_timeout), + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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), }], - nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + vec![b_received_htlc_balance.clone()], + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 @@ -1089,7 +1806,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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + .is_empty()); } fn sorted_vec_with_additions(v_orig: &Vec, extra_ts: &[&T]) -> Vec { @@ -1115,7 +1838,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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = @@ -1136,7 +1860,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_000); + let (claimed_payment_preimage, claimed_payment_hash, ..) = + route_payment(&nodes[0], &[&nodes[1]], 3_000_000); let timeout_payment_hash = route_payment(&nodes[1], &[&nodes[0]], 4_000_000).1; let dust_payment_hash = route_payment(&nodes[1], &[&nodes[0]], 3_000).1; @@ -1170,23 +1895,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::HolderForceClosed, .. } => {}, _ => panic!(), @@ -1195,29 +1929,58 @@ 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::HolderForceClosed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [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, - }, Balance::MaybeTimeoutClaimableHTLC { - amount_satoshis: 2_000, - claimable_height: missing_htlc_cltv_timeout, - payment_hash: missing_htlc_payment_hash, - }, Balance::MaybeTimeoutClaimableHTLC { - amount_satoshis: 4_000, - claimable_height: htlc_cltv_timeout, - payment_hash: timeout_payment_hash, - }, Balance::MaybeTimeoutClaimableHTLC { - amount_satoshis: 5_000, - claimable_height: live_htlc_cltv_timeout, - payment_hash: live_payment_hash, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { + amount_satoshis: 100_000 - 5_000 - 4_000 - 3 - 2_000 + 3_000, + }, + Balance::MaybeTimeoutClaimableHTLC { + amount_satoshis: 2_000, + claimable_height: missing_htlc_cltv_timeout, + payment_hash: missing_htlc_payment_hash, + }, + Balance::MaybeTimeoutClaimableHTLC { + amount_satoshis: 4_000, + claimable_height: htlc_cltv_timeout, + payment_hash: timeout_payment_hash, + }, + Balance::MaybeTimeoutClaimableHTLC { + amount_satoshis: 5_000, + claimable_height: live_htlc_cltv_timeout, + payment_hash: live_payment_hash, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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].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].txid()) + }) + .collect(); // Currently the revoked commitment is claimed in four transactions as the HTLCs all expire // quite soon. assert_eq!(claim_txn.len(), 4); @@ -1235,8 +1998,10 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ fuzzy_assert_eq(claim_txn[2].weight().to_wu(), inbound_htlc_claim_exp_weight); fuzzy_assert_eq(claim_txn[3].weight().to_wu(), BS_TO_SELF_CLAIM_EXP_WEIGHT); - let commitment_tx_fee = chan_feerate * - (channel::commitment_tx_base_weight(&channel_type_features) + 3 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 3 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) + / 1000; let anchor_outputs_value = if anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 }; let inbound_htlc_claim_fee = chan_feerate * inbound_htlc_claim_exp_weight / 1000; let outbound_htlc_claim_fee = chan_feerate * outbound_htlc_claim_exp_weight / 1000; @@ -1244,29 +2009,40 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ // The expected balance for the next three checks, with the largest-HTLC and to_self output // claim balances separated out. - let expected_balance = vec![Balance::ClaimableAwaitingConfirmations { + let expected_balance = vec![ + Balance::ClaimableAwaitingConfirmations { // to_remote output in A's revoked commitment amount_satoshis: 100_000 - 5_000 - 4_000 - 3, confirmation_height: nodes[1].best_block_info().1 + 5, - }, Balance::CounterpartyRevokedOutputClaimable { - amount_satoshis: 3_000, - }, Balance::CounterpartyRevokedOutputClaimable { - amount_satoshis: 4_000, - }]; + }, + Balance::CounterpartyRevokedOutputClaimable { amount_satoshis: 3_000 }, + Balance::CounterpartyRevokedOutputClaimable { amount_satoshis: 4_000 }, + ]; let to_self_unclaimed_balance = Balance::CounterpartyRevokedOutputClaimable { amount_satoshis: 1_000_000 - 100_000 - 3_000 - commitment_tx_fee - anchor_outputs_value, }; let to_self_claimed_avail_height; - let largest_htlc_unclaimed_balance = Balance::CounterpartyRevokedOutputClaimable { - amount_satoshis: 5_000, - }; + let largest_htlc_unclaimed_balance = + Balance::CounterpartyRevokedOutputClaimable { amount_satoshis: 5_000 }; let largest_htlc_claimed_avail_height; // Once the channel has been closed by A, B now considers all of the commitment transactions' // outputs as `CounterpartyRevokedOutputClaimable`. - assert_eq!(sorted_vec_with_additions(&expected_balance, &[&to_self_unclaimed_balance, &largest_htlc_unclaimed_balance]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec_with_additions( + &expected_balance, + &[&to_self_unclaimed_balance, &largest_htlc_unclaimed_balance] + ), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); if confirm_htlc_spend_first { mine_transaction(&nodes[1], &claim_txn[2]); @@ -1284,16 +2060,44 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ confirmation_height: largest_htlc_claimed_avail_height, }; let to_self_claimed_balance = Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 100_000 - 3_000 - commitment_tx_fee - anchor_outputs_value - to_self_claim_fee, + amount_satoshis: 1_000_000 + - 100_000 - 3_000 + - commitment_tx_fee + - anchor_outputs_value + - to_self_claim_fee, confirmation_height: to_self_claimed_avail_height, }; if confirm_htlc_spend_first { - assert_eq!(sorted_vec_with_additions(&expected_balance, &[&to_self_unclaimed_balance, &largest_htlc_claimed_balance]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec_with_additions( + &expected_balance, + &[&to_self_unclaimed_balance, &largest_htlc_claimed_balance] + ), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); } else { - assert_eq!(sorted_vec_with_additions(&expected_balance, &[&to_self_claimed_balance, &largest_htlc_unclaimed_balance]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec_with_additions( + &expected_balance, + &[&to_self_claimed_balance, &largest_htlc_unclaimed_balance] + ), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); } if confirm_htlc_spend_first { @@ -1301,53 +2105,107 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_ } else { mine_transaction(&nodes[1], &claim_txn[2]); } - assert_eq!(sorted_vec_with_additions(&expected_balance, &[&to_self_claimed_balance, &largest_htlc_claimed_balance]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec_with_additions( + &expected_balance, + &[&to_self_claimed_balance, &largest_htlc_claimed_balance] + ), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); // Finally, connect the last two remaining HTLC spends and check that they move to // `ClaimableAwaitingConfirmations` mine_transaction(&nodes[1], &claim_txn[0]); mine_transaction(&nodes[1], &claim_txn[1]); - assert_eq!(sorted_vec(vec![Balance::ClaimableAwaitingConfirmations { - // to_remote output in A's revoked commitment - amount_satoshis: 100_000 - 5_000 - 4_000 - 3, - confirmation_height: nodes[1].best_block_info().1 + 1, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 1_000_000 - 100_000 - 3_000 - commitment_tx_fee - anchor_outputs_value - to_self_claim_fee, - confirmation_height: to_self_claimed_avail_height, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 3_000 - outbound_htlc_claim_fee, - confirmation_height: nodes[1].best_block_info().1 + 4, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 4_000 - inbound_htlc_claim_fee, - confirmation_height: nodes[1].best_block_info().1 + 5, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: 5_000 - inbound_htlc_claim_fee, - confirmation_height: largest_htlc_claimed_avail_height, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableAwaitingConfirmations { + // to_remote output in A's revoked commitment + amount_satoshis: 100_000 - 5_000 - 4_000 - 3, + confirmation_height: nodes[1].best_block_info().1 + 1, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 1_000_000 + - 100_000 - 3_000 - commitment_tx_fee + - anchor_outputs_value + - to_self_claim_fee, + confirmation_height: to_self_claimed_avail_height, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 3_000 - outbound_htlc_claim_fee, + confirmation_height: nodes[1].best_block_info().1 + 4, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 4_000 - inbound_htlc_claim_fee, + confirmation_height: nodes[1].best_block_info().1 + 5, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: 5_000 - inbound_htlc_claim_fee, + confirmation_height: largest_htlc_claimed_avail_height, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); connect_blocks(&nodes[1], 1); 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); - test_spendable_output(&nodes[1], &claim_txn[if confirm_htlc_spend_first { 2 } else { 3 }], false); + test_spendable_output( + &nodes[1], + &claim_txn[if confirm_htlc_spend_first { 2 } else { 3 }], + false, + ); connect_blocks(&nodes[1], 1); - test_spendable_output(&nodes[1], &claim_txn[if confirm_htlc_spend_first { 3 } else { 2 }], false); + test_spendable_output( + &nodes[1], + &claim_txn[if confirm_htlc_spend_first { 3 } else { 2 }], + false, + ); expect_payment_failed!(nodes[1], live_payment_hash, false); connect_blocks(&nodes[1], 1); test_spendable_output(&nodes[1], &claim_txn[0], false); connect_blocks(&nodes[1], 1); test_spendable_output(&nodes[1], &claim_txn[1], false); expect_payment_failed!(nodes[1], timeout_payment_hash, false); - assert_eq!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances(), Vec::new()); + assert_eq!( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 @@ -1355,7 +2213,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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -1376,7 +2240,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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -1395,8 +2260,14 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { ], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, coinbase_tx.output[0].value); - nodes[1].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 1 }, coinbase_tx.output[1].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); + nodes[1].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 1 }, + coinbase_tx.output[1].value, + ); } // Create some initial channels @@ -1429,7 +2300,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); } @@ -1438,8 +2315,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() }; @@ -1459,7 +2338,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); @@ -1467,7 +2349,13 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { 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 = { @@ -1495,23 +2383,41 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { // 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 * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::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, confirmation_height: to_remote_conf_height, - }, 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(funding_outpoint).unwrap().get_claimable_balances())); + }, + ]); + assert_eq!( + as_balances, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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); @@ -1527,63 +2433,126 @@ fn do_test_revoked_counterparty_htlc_tx_balances(anchors: bool) { } 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(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + as_balances, + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - 3_000 - as_revoked_htlc_success_claim_fee); + fuzzy_assert_eq( + as_htlc_claim_tx[0].output[0].value, + 3_000 - as_revoked_htlc_success_claim_fee, + ); } else { - fuzzy_assert_eq(as_htlc_claim_tx[0].output[0].value, - 3_000 - revoked_htlc_success_fee - as_revoked_htlc_success_claim_fee); + fuzzy_assert_eq( + as_htlc_claim_tx[0].output[0].value, + 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, - confirmation_height: to_remote_conf_height, - }, 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, - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + confirmation_height: to_remote_conf_height, + }, + 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, + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - confirmation_height: nodes[0].best_block_info().1 + 2, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + confirmation_height: nodes[0].best_block_info().1 + 2, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).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(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); - connect_blocks(&nodes[0], revoked_htlc_timeout.lock_time.to_consensus_u32() - nodes[0].best_block_info().1); - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!(&nodes[0], - [HTLCDestination::FailedPayment { payment_hash: failed_payment_hash }]); + connect_blocks( + &nodes[0], + revoked_htlc_timeout.lock_time.to_consensus_u32() - nodes[0].best_block_info().1, + ); + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!( + &nodes[0], + [HTLCDestination::FailedPayment { payment_hash: failed_payment_hash }] + ); // 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() { @@ -1622,41 +2591,86 @@ 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(funding_outpoint).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(funding_outpoint) + .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, - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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, - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: revoked_htlc_timeout_claim.output[0].value, - confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 2, - }]), - sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 1, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: revoked_htlc_timeout_claim.output[0].value, + confirmation_height: nodes[0].best_block_info().1 + ANTI_REORG_DELAY - 2, + } + ]), + sorted_vec( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).unwrap().get_claimable_balances(), Vec::new()); + assert_eq!( + nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 @@ -1664,7 +2678,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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[0] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -1688,7 +2708,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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { @@ -1700,7 +2721,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.txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.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); @@ -1711,15 +2735,21 @@ 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_000); + let (claimed_payment_preimage, claimed_payment_hash, ..) = + route_payment(&nodes[1], &[&nodes[0]], 3_000_000); 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 // 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(&claimed_payment_hash, &claimed_payment_preimage, - &node_cfgs[0].tx_broadcaster, &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger); + get_monitor!(nodes[0], chan_id).provide_payment_preimage( + &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 let as_revoked_txn = get_local_commitment_txn!(nodes[0], chan_id); @@ -1741,7 +2771,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); @@ -1749,22 +2781,39 @@ 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, - }, Balance::MaybeTimeoutClaimableHTLC { - amount_satoshis: 4_000, - claimable_height: htlc_cltv_timeout, - payment_hash: revoked_payment_hash, - }, Balance::MaybeTimeoutClaimableHTLC { - amount_satoshis: 3_000, - claimable_height: htlc_cltv_timeout, - payment_hash: claimed_payment_hash, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances())); + assert_eq!( + sorted_vec(vec![ + Balance::ClaimableOnChannelClose { amount_satoshis: 100_000 - 4_000 - 3_000 }, + Balance::MaybeTimeoutClaimableHTLC { + amount_satoshis: 4_000, + claimable_height: htlc_cltv_timeout, + payment_hash: revoked_payment_hash, + }, + Balance::MaybeTimeoutClaimableHTLC { + amount_satoshis: 3_000, + claimable_height: htlc_cltv_timeout, + payment_hash: claimed_payment_hash, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(); @@ -1789,22 +2838,40 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { let to_remote_maturity = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; - let commitment_tx_fee = chan_feerate * - (channel::commitment_tx_base_weight(&channel_type_features) + 2 * channel::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + let commitment_tx_fee = chan_feerate + * (channel::commitment_tx_base_weight(&channel_type_features) + + 2 * channel::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, - confirmation_height: to_remote_maturity, - }, 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(funding_outpoint).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, + confirmation_height: to_remote_maturity, + }, + 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(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); // Confirm A's HTLC-Success transaction which presumably raced B's claim, causing B to create a // new claim. @@ -1812,7 +2879,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 { @@ -1847,63 +2921,122 @@ 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, - confirmation_height: to_remote_maturity, - }, 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(funding_outpoint).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, + confirmation_height: to_remote_maturity, + }, + 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(funding_outpoint) + .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(funding_outpoint).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(funding_outpoint) + .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, - confirmation_height: htlc_2_claim_maturity, - }]), - sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).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, + confirmation_height: htlc_2_claim_maturity, + } + ]), + sorted_vec( + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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(funding_outpoint).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(funding_outpoint) + .unwrap() + .get_claimable_balances() + ) + ); if anchors { mine_transactions(&nodes[1], &[&claim_txn_2[1], revoked_to_self_claim.as_ref().unwrap()]); @@ -1913,20 +3046,37 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { let rest_claim_maturity = nodes[1].best_block_info().1 + ANTI_REORG_DELAY - 1; if anchors { - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { - amount_satoshis: claim_txn_2[1].output[0].value, - confirmation_height: rest_claim_maturity, - }, Balance::ClaimableAwaitingConfirmations { - amount_satoshis: revoked_to_self_claim.as_ref().unwrap().output[0].value, - confirmation_height: rest_claim_maturity, - }], - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + assert_eq!( + vec![ + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: claim_txn_2[1].output[0].value, + confirmation_height: rest_claim_maturity, + }, + Balance::ClaimableAwaitingConfirmations { + amount_satoshis: revoked_to_self_claim.as_ref().unwrap().output[0].value, + confirmation_height: rest_claim_maturity, + } + ], + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + ); } else { - assert_eq!(vec![Balance::ClaimableAwaitingConfirmations { + assert_eq!( + vec![Balance::ClaimableAwaitingConfirmations { amount_satoshis: claim_txn_2[1].output[0].value, confirmation_height: rest_claim_maturity, }], - nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()); + nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 @@ -1939,17 +3089,36 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) { for (i, event) in events.into_iter().enumerate() { if let Event::SpendableOutputs { outputs, .. } = event { 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, &Secp256k1::new() - ).unwrap(); - check_spends!(spend_tx, if i == 0 { &claim_txn_2[1] } else { revoked_to_self_claim.as_ref().unwrap() }); - } else { panic!(); } + 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, + if i == 0 { &claim_txn_2[1] } else { revoked_to_self_claim.as_ref().unwrap() } + ); + } else { + panic!(); + } } } else { test_spendable_output(&nodes[1], &claim_txn_2[1], false); } - assert!(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .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 @@ -1957,7 +3126,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(funding_outpoint).unwrap().get_claimable_balances().is_empty()); + assert!(nodes[1] + .chain_monitor + .chain_monitor + .get_monitor(funding_outpoint) + .unwrap() + .get_claimable_balances() + .is_empty()); } #[test] @@ -1980,14 +3155,24 @@ 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); - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()) + .unwrap(); check_added_monitors(&nodes[0], 1); check_closed_broadcast(&nodes[0], 1, true); - check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed, false, - [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + false, + [nodes[1].node.get_our_node_id()], + 100000 + ); let commitment_tx = { let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); @@ -2019,7 +3204,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. @@ -2062,9 +3254,8 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), 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); @@ -2072,24 +3263,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: 2, 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.to_sat(), script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), }], }; - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.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 @@ -2110,11 +3318,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 - - htlc_tx.output.iter().map(|output| output.value).sum::(); + let htlc_tx_fee = HTLC_AMT_SAT + coinbase_tx.output[0].value + - htlc_tx.output.iter().map(|output| output.value).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 { @@ -2171,7 +3379,10 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) { // If we have a `ConnectStyle` that advertises the new block first without the transactions, // we'll receive an extra bumped claim. if nodes[0].connect_style.borrow().updates_best_block_first() { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, + coinbase_tx.output[0].value, + ); nodes[0].wallet_source.remove_utxo(bitcoin::OutPoint { txid: htlc_tx.txid(), vout: 1 }); check_htlc_retry(true, anchors); } @@ -2199,14 +3410,16 @@ fn test_yield_anchors_events() { anchors_config.channel_handshake_config.announced_channel = 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), Some(anchors_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), 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 (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[1], &[&nodes[0]], 2_000_000); + let (_, _, chan_id, funding_tx) = + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_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[1], &[&nodes[0]], 2_000_000); assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); assert!(nodes[1].node.get_and_clear_pending_events().is_empty()); @@ -2224,12 +3437,18 @@ fn test_yield_anchors_events() { } get_monitor!(nodes[0], chan_id).provide_payment_preimage( - &payment_hash_2, &payment_preimage_2, &node_cfgs[0].tx_broadcaster, - &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), &nodes[0].logger + &payment_hash_2, + &payment_preimage_2, + &node_cfgs[0].tx_broadcaster, + &LowerBoundedFeeEstimator::new(node_cfgs[0].fee_estimator), + &nodes[0].logger, ); get_monitor!(nodes[1], chan_id).provide_payment_preimage( - &payment_hash_1, &payment_preimage_1, &node_cfgs[1].tx_broadcaster, - &LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), &nodes[1].logger + &payment_hash_1, + &payment_preimage_1, + &node_cfgs[1].tx_broadcaster, + &LowerBoundedFeeEstimator::new(node_cfgs[1].fee_estimator), + &nodes[1].logger, ); let mut holder_events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events(); @@ -2240,12 +3459,16 @@ fn test_yield_anchors_events() { version: 2, 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.to_sat(), script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), }], }; - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.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); @@ -2268,7 +3491,10 @@ fn test_yield_anchors_events() { { let mut txn = nodes[1].tx_broadcaster.unique_txn_broadcast(); - assert_eq!(txn.len(), if nodes[1].connect_style.borrow().updates_best_block_first() { 3 } else { 2 }); + assert_eq!( + txn.len(), + if nodes[1].connect_style.borrow().updates_best_block_first() { 3 } else { 2 } + ); let htlc_preimage_tx = txn.pop().unwrap(); assert_eq!(htlc_preimage_tx.input.len(), 1); @@ -2290,8 +3516,12 @@ fn test_yield_anchors_events() { // 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); } @@ -2350,13 +3580,16 @@ fn test_anchors_aggregated_revoked_htlc_tx() { anchors_config.channel_handshake_config.announced_channel = 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), Some(anchors_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(anchors_config), Some(anchors_config)]); 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(); @@ -2386,15 +3619,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( - &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, ); } } @@ -2405,7 +3646,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()); @@ -2419,12 +3666,15 @@ fn test_anchors_aggregated_revoked_htlc_tx() { version: 2, 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.txid(), vout: 0 }, utxo_value); + nodes[1] + .wallet_source + .add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, utxo_value); match event { Event::BumpTransaction(event) => nodes[1].bump_tx_handler.handle_event(&event), _ => panic!("Unexpected event"), @@ -2442,14 +3692,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. @@ -2457,11 +3721,18 @@ 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_htlc_claim_a, revoked_htlc_claim_b) = if txn[0].input[0].previous_output.txid == revoked_commitment_txs[0].txid() { - (if txn[0].input.len() == 2 { &txn[0] } else { &txn[1] }, if txn[2].input.len() == 2 { &txn[2] } else { &txn[3] }) - } else { - (if txn[2].input.len() == 2 { &txn[2] } else { &txn[3] }, if txn[0].input.len() == 2 { &txn[0] } else { &txn[1] }) - }; + let (revoked_htlc_claim_a, revoked_htlc_claim_b) = + if txn[0].input[0].previous_output.txid == revoked_commitment_txs[0].txid() { + ( + if txn[0].input.len() == 2 { &txn[0] } else { &txn[1] }, + if txn[2].input.len() == 2 { &txn[2] } else { &txn[3] }, + ) + } else { + ( + if txn[2].input.len() == 2 { &txn[2] } else { &txn[3] }, + if txn[0].input.len() == 2 { &txn[0] } else { &txn[1] }, + ) + }; assert_eq!(revoked_htlc_claim_a.input.len(), 2); // Spends both HTLC outputs assert_eq!(revoked_htlc_claim_a.output.len(), 1); @@ -2478,13 +3749,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), }; @@ -2496,7 +3776,8 @@ fn test_anchors_aggregated_revoked_htlc_tx() { version: 2, 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.to_sat(), script_pubkey: fee_utxo_script.clone(), }], @@ -2504,12 +3785,14 @@ fn test_anchors_aggregated_revoked_htlc_tx() { let mut htlc_tx = Transaction { version: 2, lock_time: LockTime::ZERO, - input: vec![TxIn { // Fee input + input: vec![TxIn { + // Fee input previous_output: bitcoin::OutPoint { txid: coinbase_tx.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(&[]), }], }; @@ -2517,7 +3800,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); @@ -2533,15 +3821,25 @@ fn test_anchors_aggregated_revoked_htlc_tx() { for (idx, htlc_descriptor) in descriptors.into_iter().enumerate() { let htlc_input_idx = idx + 1; let signer = htlc_descriptor.derive_channel_signer(&nodes[1].keys_manager); - let our_sig = signer.sign_holder_htlc_transaction(&htlc_tx, htlc_input_idx, &htlc_descriptor, &secp).unwrap(); + 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).segwit_signature_hash( - 0, &witness_script, coinbase_tx.output[0].value, EcdsaSighashType::All - ).unwrap()[..]); + let sighash = hash_to_message!( + &SighashCache::new(&htlc_tx) + .segwit_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); @@ -2562,11 +3860,13 @@ fn test_anchors_aggregated_revoked_htlc_tx() { let txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); 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.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.txid() + }) + .collect::>(); assert_eq!(revoked_htlc_claims.len(), 2); for revoked_htlc_claim in revoked_htlc_claims { check_spends!(revoked_htlc_claim, htlc_tx); @@ -2582,7 +3882,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); @@ -2596,20 +3895,35 @@ 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(); assert_eq!(spendable_output_events.len(), 4); for event in spendable_output_events { 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"); @@ -2629,7 +3943,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); @@ -2639,11 +3955,13 @@ 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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); 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(); @@ -2655,11 +3973,20 @@ 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. - nodes[0].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()) + .unwrap(); check_added_monitors(&nodes[0], 1); check_closed_broadcast(&nodes[0], 1, true); - check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed, false, - [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + false, + [nodes[1].node.get_our_node_id()], + 100000 + ); let commitment_tx = { let mut txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); @@ -2674,20 +4001,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_v0_p2wsh()); connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1); @@ -2698,12 +4049,21 @@ fn do_test_anchors_monitor_fixes_counterparty_payment_script_on_reload(confirm_c // get the spendable output event for the `to_remote` output, so we'll need to get it // manually via `get_spendable_outputs`. check_added_monitors(&nodes[1], 1); - 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); @@ -2717,7 +4077,9 @@ fn test_anchors_monitor_fixes_counterparty_payment_script_on_reload() { } #[cfg(not(feature = "_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); @@ -2727,26 +4089,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), Some(user_config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(user_config), Some(user_config)]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let coinbase_tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: vec![TxIn { ..Default::default() }], - output: vec![ - TxOut { - value: Amount::ONE_BTC.to_sat(), - script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), - }, - ], + output: vec![TxOut { + value: Amount::ONE_BTC.to_sat(), + script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(), + }], }; if anchors { - nodes[0].wallet_source.add_utxo(bitcoin::OutPoint { txid: coinbase_tx.txid(), vout: 0 }, coinbase_tx.output[0].value); + nodes[0].wallet_source.add_utxo( + bitcoin::OutPoint { txid: coinbase_tx.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 { @@ -2755,7 +4120,10 @@ fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterp (&nodes[0], &nodes[1]) }; - closing_node.node.force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id()).unwrap(); + closing_node + .node + .force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id()) + .unwrap(); // The commitment transaction comes first. let commitment_tx = { @@ -2768,16 +4136,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::HolderForceClosed, [other_node.node.get_our_node_id()], 1_000_000); + check_closed_event!( + closing_node, + 1, + ClosureReason::HolderForceClosed, + [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(); } diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index d39f1a60842..15b65211dd4 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -25,38 +25,42 @@ //! track the network on the less-secure system. use bitcoin::blockdata::constants::ChainHash; -use bitcoin::secp256k1::PublicKey; -use bitcoin::secp256k1::ecdsa::Signature; -use bitcoin::{secp256k1, Witness}; use bitcoin::blockdata::script::ScriptBuf; use bitcoin::hash_types::Txid; +use bitcoin::secp256k1::ecdsa::Signature; +use bitcoin::secp256k1::PublicKey; +use bitcoin::{secp256k1, Witness}; use crate::blinded_path::payment::{BlindedPaymentTlvs, ForwardTlvs, ReceiveTlvs}; -use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret}; use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; use crate::ln::onion_utils; +use crate::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use crate::onion_message; use crate::sign::{NodeSigner, Recipient}; +use crate::io::{self, Cursor, Read}; +use crate::io_extras::read_to_end; use crate::prelude::*; #[cfg(feature = "std")] use core::convert::TryFrom; 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::events::{EventsProvider, MessageSendEventsProvider}; use crate::crypto::streams::ChaChaPolyReadAdapter; -use crate::util::logger; -use crate::util::ser::{LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize}; +use crate::events::{EventsProvider, MessageSendEventsProvider}; use crate::util::base32; +use crate::util::logger; +use crate::util::ser::{ + BigSize, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, LengthReadable, + LengthReadableArgs, Readable, ReadableArgs, TransactionU16LenLimited, WithoutLength, Writeable, + Writer, +}; use crate::routing::gossip::{NodeAlias, NodeId}; @@ -66,7 +70,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)] @@ -406,7 +413,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. @@ -687,9 +694,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. @@ -766,7 +773,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 @@ -864,23 +871,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, } } @@ -928,33 +935,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)), } } @@ -997,26 +996,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")] @@ -1029,23 +1028,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.", + )), } } } @@ -1053,13 +1054,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); } @@ -1070,7 +1075,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); }, } } @@ -1138,7 +1144,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> { @@ -1380,7 +1386,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 { @@ -1444,7 +1450,7 @@ pub struct CommitmentUpdate { /// /// 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 : MessageSendEventsProvider { +pub trait ChannelMessageHandler: MessageSendEventsProvider { // Channel init: /// Handle an incoming `open_channel` message from the given peer. fn handle_open_channel(&self, their_node_id: &PublicKey, msg: &OpenChannel); @@ -1507,7 +1513,9 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider { /// 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 an incoming `revoke_and_ack` message from the given peer. @@ -1518,7 +1526,9 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider { // 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, + ); // Connection loss/reestablish: /// Indicates a connection to the peer failed/an existing connection was lost. @@ -1529,7 +1539,9 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider { /// May return an `Err(())` if the features the peer supports are not sufficient to communicate /// with us. Implementors should be somewhat conservative about doing so, however, as other /// message handlers may still wish to communicate with this peer. - 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<(), ()>; /// Handle an incoming `channel_reestablish` message from the given peer. fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish); @@ -1567,25 +1579,31 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider { /// 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 : MessageSendEventsProvider { +pub trait RoutingMessageHandler: MessageSendEventsProvider { /// Handle an incoming `node_announcement` message, returning `true` if it should be forwarded on, /// `false` or returning an `Err` otherwise. fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result; /// Handle a `channel_announcement` message, returning `true` if it should be forwarded on, `false` /// or returning an `Err` otherwise. - fn handle_channel_announcement(&self, msg: &ChannelAnnouncement) -> Result; + fn handle_channel_announcement( + &self, msg: &ChannelAnnouncement, + ) -> Result; /// Handle an incoming `channel_update` message, returning true if it should be forwarded on, /// `false` or returning an `Err` otherwise. fn handle_channel_update(&self, 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; /// Called when a connection is established with a peer. This can be used to /// perform routing table synchronization using a strategy defined by the /// implementor. @@ -1593,22 +1611,32 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider { /// May return an `Err(())` if the features the peer supports are not sufficient to communicate /// with us. Implementors should be somewhat conservative about doing so, however, as other /// message handlers may still wish to communicate with this peer. - fn peer_connected(&self, their_node_id: &PublicKey, init: &Init, inbound: bool) -> Result<(), ()>; + fn peer_connected( + &self, their_node_id: &PublicKey, init: &Init, inbound: bool, + ) -> Result<(), ()>; /// 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 @@ -1644,7 +1672,9 @@ pub trait OnionMessageHandler: EventsProvider { /// May return an `Err(())` if the features the peer supports are not sufficient to communicate /// with us. Implementors should be somewhat conservative about doing so, however, as other /// message handlers may still wish to communicate with this peer. - fn peer_connected(&self, their_node_id: &PublicKey, init: &Init, inbound: bool) -> Result<(), ()>; + fn peer_connected( + &self, their_node_id: &PublicKey, init: &Init, inbound: bool, + ) -> Result<(), ()>; /// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to /// drop and refuse to forward onion messages to this peer. @@ -1684,12 +1714,12 @@ pub struct FinalOnionHopData { } mod fuzzy_internal_msgs { - use bitcoin::secp256k1::PublicKey; + use super::FinalOnionHopData; use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay}; - use crate::prelude::*; - use crate::ln::{PaymentPreimage, PaymentSecret}; use crate::ln::features::BlindedHopFeatures; - use super::FinalOnionHopData; + use crate::ln::{PaymentPreimage, PaymentSecret}; + use crate::prelude::*; + use bitcoin::secp256k1::PublicKey; // These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize // them from untrusted input): @@ -1723,7 +1753,7 @@ mod fuzzy_internal_msgs { payment_secret: PaymentSecret, payment_constraints: PaymentConstraints, intro_node_blinding_point: Option, - } + }, } pub(crate) enum OutboundOnionPayload { @@ -1751,7 +1781,7 @@ mod fuzzy_internal_msgs { cltv_expiry_height: u32, encrypted_tlvs: Vec, intro_node_blinding_point: Option, // Set if the introduction node of the blinded path is the final node - } + }, } pub struct DecodedOnionErrorPacket { @@ -1777,7 +1807,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], } @@ -1785,18 +1815,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[..] + )) } } @@ -1811,12 +1840,20 @@ 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::UnsupportedCompression => { + f.write_str("We don't support receiving messages with zlib-compressed fields") + }, } } } @@ -2193,9 +2230,7 @@ impl_writeable_msg!(UpdateFulfillHTLC, { // 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 // position. -impl_writeable!(OnionErrorPacket, { - data -}); +impl_writeable!(OnionErrorPacket, { 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 @@ -2205,7 +2240,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)?; @@ -2218,7 +2253,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) }, @@ -2247,10 +2282,7 @@ impl Readable for OnionMessage { let mut packet_reader = FixedLengthReader::new(r, len as u64); let onion_routing_packet: onion_message::packet::Packet = ::read(&mut packet_reader)?; - Ok(Self { - blinding_point, - onion_routing_packet, - }) + Ok(Self { blinding_point, onion_routing_packet }) } } @@ -2290,14 +2322,19 @@ impl Writeable for OutboundOnionPayload { }); }, 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), @@ -2313,7 +2350,10 @@ impl Writeable for OutboundOnionPayload { }); }, Self::BlindedReceive { - sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs, + sender_intended_htlc_amt_msat, + total_msat, + cltv_expiry_height, + encrypted_tlvs, intro_node_blinding_point, } => { _encode_varint_length_prefixed_tlv!(w, { @@ -2329,7 +2369,10 @@ impl Writeable for OutboundOnionPayload { } } -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; @@ -2365,29 +2408,40 @@ impl ReadableArgs<(Option, &NS)> for InboundOnionPayload w 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 short_id.is_some() || payment_data.is_some() || payment_metadata.is_some() || - keysend_preimage.is_some() + if short_id.is_some() + || payment_data.is_some() + || payment_metadata.is_some() + || keysend_preimage.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 - })} => { + ChaChaPolyReadAdapter { + readable: + BlindedPaymentTlvs::Forward(ForwardTlvs { + short_channel_id, + payment_relay, + payment_constraints, + features, + }), + } => { if amt.is_some() || cltv_value.is_some() || total_msat.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } Ok(Self::BlindedForward { short_channel_id, @@ -2397,10 +2451,13 @@ impl ReadableArgs<(Option, &NS)> for InboundOnionPayload w intro_node_blinding_point, }) }, - ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(ReceiveTlvs { - payment_secret, payment_constraints - })} => { - if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) } + ChaChaPolyReadAdapter { + readable: + BlindedPaymentTlvs::Receive(ReceiveTlvs { payment_secret, payment_constraints }), + } => { + if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { + return Err(DecodeError::InvalidValue); + } Ok(Self::BlindedReceive { sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?, total_msat: total_msat.ok_or(DecodeError::InvalidValue)?, @@ -2412,9 +2469,13 @@ impl ReadableArgs<(Option, &NS)> for InboundOnionPayload w }, } } 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() - { return Err(DecodeError::InvalidValue) } + if payment_data.is_some() + || payment_metadata.is_some() + || encrypted_tlvs_opt.is_some() + || total_msat.is_some() + { + return Err(DecodeError::InvalidValue); + } Ok(Self::Forward { short_channel_id, amt_to_forward: amt.ok_or(DecodeError::InvalidValue)?, @@ -2422,7 +2483,7 @@ impl ReadableArgs<(Option, &NS)> for InboundOnionPayload w }) } else { if encrypted_tlvs_opt.is_some() || total_msat.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } if let Some(data) = &payment_data { if data.total_msat > MAX_VALUE_MSAT { @@ -2457,7 +2518,7 @@ impl Readable for Ping { let byteslen = Readable::read(r)?; r.read_exact(&mut vec![0u8; byteslen as usize][..])?; byteslen - } + }, }) } } @@ -2476,7 +2537,7 @@ impl Readable for Pong { let byteslen = Readable::read(r)?; r.read_exact(&mut vec![0u8; byteslen as usize][..])?; byteslen - } + }, }) } } @@ -2585,7 +2646,7 @@ impl Readable for ErrorMessage { Ok(s) => s, Err(_) => return Err(DecodeError::InvalidValue), } - } + }, }) } } @@ -2612,7 +2673,7 @@ impl Readable for WarningMessage { Ok(s) => s, Err(_) => return Err(DecodeError::InvalidValue), } - } + }, }) } } @@ -2654,7 +2715,9 @@ impl Readable 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() { @@ -2727,16 +2790,13 @@ impl Readable 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 }) } } @@ -2806,7 +2866,7 @@ impl Readable 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)?); @@ -2817,7 +2877,7 @@ impl Readable for ReplyChannelRange { first_blocknum, number_of_blocks, sync_complete, - short_channel_ids + short_channel_ids, }) } } @@ -2848,52 +2908,64 @@ impl_writeable_msg!(GossipTimestampFilter, { #[cfg(test)] mod tests { - use std::convert::TryFrom; - use bitcoin::{Transaction, TxIn, ScriptBuf, Sequence, Witness, TxOut}; - use hex::DisplayHex; - use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; - use crate::ln::ChannelId; use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; - use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket}; use crate::ln::msgs::SocketAddress; + use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket}; + use crate::ln::ChannelId; + use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::routing::gossip::{NodeAlias, NodeId}; - use crate::util::ser::{Writeable, Readable, ReadableArgs, Hostname, TransactionU16LenLimited}; + use crate::util::ser::{Hostname, Readable, ReadableArgs, TransactionU16LenLimited, Writeable}; use crate::util::test_utils; + use bitcoin::{ScriptBuf, Sequence, Transaction, TxIn, TxOut, Witness}; + use hex::DisplayHex; + use std::convert::TryFrom; - use bitcoin::hashes::hex::FromHex; use bitcoin::address::Address; - use bitcoin::network::constants::Network; use bitcoin::blockdata::constants::ChainHash; - use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; + use bitcoin::blockdata::script::Builder; use bitcoin::hash_types::Txid; + use bitcoin::hashes::hex::FromHex; use bitcoin::locktime::absolute::LockTime; + use bitcoin::network::constants::Network; - 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}; #[cfg(feature = "std")] use crate::ln::msgs::SocketAddressParseError; + #[cfg(feature = "std")] + use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; #[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, }; @@ -2902,11 +2974,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 ] ); } @@ -2915,63 +2991,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_slice(&$string.into_bytes()[..]).unwrap(); - $ctx.sign_ecdsa(&sighash, &$privkey) - } - } + ($privkey: expr, $ctx: expr, $string: expr) => {{ + let sighash = Message::from_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, @@ -2983,14 +3084,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]); @@ -3003,7 +3120,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, @@ -3019,7 +3140,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()); @@ -3035,10 +3161,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 { @@ -3047,28 +3180,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 { @@ -3086,16 +3221,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 { @@ -3109,13 +3260,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()); @@ -3145,8 +3303,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, @@ -3157,15 +3319,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()); @@ -3177,7 +3342,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()); @@ -3199,12 +3365,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 { chain_hash: ChainHash::using_genesis_block(Network::Bitcoin), temporary_channel_id: ChannelId::from_bytes([2; 32]), @@ -3224,12 +3408,27 @@ 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 }, + 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 }, }; 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()); @@ -3237,7 +3436,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()); @@ -3257,15 +3459,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 { chain_hash: ChainHash::using_genesis_block(Network::Bitcoin), temporary_channel_id: ChannelId::from_bytes([2; 32]), @@ -3286,14 +3511,34 @@ mod tests { first_per_commitment_point: pubkey_6, second_per_commitment_point: pubkey_7, 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 }, + 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 }, require_confirmed_inputs: if require_confirmed_inputs { Some(()) } else { None }, }; 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()); @@ -3303,13 +3548,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()); @@ -3318,7 +3598,10 @@ mod tests { } if shutdown { target_value.append(&mut >::from_hex("001b").unwrap()); // Type 0 + Length 27 - 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()); @@ -3351,12 +3634,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 { temporary_channel_id: ChannelId::from_bytes([2; 32]), dust_limit_satoshis: 1311768467284833366, @@ -3372,7 +3673,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, #[cfg(taproot)] next_local_nonce: None, @@ -3380,7 +3691,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); } @@ -3393,13 +3707,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 { temporary_channel_id: ChannelId::from_bytes([2; 32]), funding_satoshis: 1311768467284833366, @@ -3416,12 +3751,24 @@ mod tests { htlc_basepoint: pubkey_5, first_per_commitment_point: pubkey_6, second_per_commitment_point: pubkey_7, - 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, 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 @@ -3429,16 +3776,54 @@ 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("001b").unwrap()); // Type 0 + Length 27 - target_value.append(&mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac").unwrap()); + target_value.append( + &mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac") + .unwrap(), + ); } assert_eq!(encoded_value, target_value); } @@ -3452,11 +3837,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)] @@ -3472,8 +3864,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, @@ -3488,7 +3884,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, @@ -3502,9 +3901,15 @@ mod tests { #[test] fn encoding_splice() { 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 = msgs::Splice { - chain_hash: ChainHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(), + chain_hash: ChainHash::from_hex( + "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + ) + .unwrap(), channel_id: ChannelId::from_bytes([2; 32]), relative_satoshis: 123456, funding_feerate_perkw: 2000, @@ -3517,20 +3922,26 @@ mod tests { #[test] fn encoding_stfu() { - let stfu = msgs::Stfu { - channel_id: ChannelId::from_bytes([2; 32]), - initiator: 1, - }; + let stfu = msgs::Stfu { channel_id: ChannelId::from_bytes([2; 32]), initiator: 1 }; let encoded_value = stfu.encode(); - assert_eq!(encoded_value.as_hex().to_string(), "020202020202020202020202020202020202020202020202020202020202020201"); + assert_eq!( + encoded_value.as_hex().to_string(), + "020202020202020202020202020202020202020202020202020202020202020201" + ); } #[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 = msgs::SpliceAck { - chain_hash: ChainHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(), + chain_hash: ChainHash::from_hex( + "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + ) + .unwrap(), channel_id: ChannelId::from_bytes([2; 32]), relative_satoshis: 123456, funding_pubkey: pubkey_1, @@ -3541,11 +3952,12 @@ mod tests { #[test] fn encoding_splice_locked() { - let splice = msgs::SpliceLocked { - channel_id: ChannelId::from_bytes([2; 32]), - }; + let splice = msgs::SpliceLocked { channel_id: ChannelId::from_bytes([2; 32]) }; let encoded_value = splice.encode(); - assert_eq!(encoded_value.as_hex().to_string(), "0202020202020202020202020202020202020202020202020202020202020202"); + assert_eq!( + encoded_value.as_hex().to_string(), + "0202020202020202020202020202020202020202020202020202020202020202" + ); } #[test] @@ -3589,7 +4001,10 @@ mod tests { channel_id: ChannelId::from_bytes([2; 32]), serial_id: 4886718345, sats: 4886718345, - script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload.script_pubkey(), + script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z") + .unwrap() + .payload + .script_pubkey(), }; let encoded_value = tx_add_output.encode(); let target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202000000012345678900000001234567890016001436ec78d514df462da95e6a00c24daa8915362d42").unwrap(); @@ -3603,7 +4018,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); } @@ -3614,17 +4032,20 @@ 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); } @@ -3643,23 +4064,40 @@ mod tests { ], }; 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(), + ); assert_eq!(encoded_value, target_value); } @@ -3668,10 +4106,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 { @@ -3692,10 +4136,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 @@ -3724,26 +4174,58 @@ 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::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).unwrap().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::PublicKey { compressed: true, inner: pubkey_1 }, + Network::Testnet, + ) + .unwrap() + .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); } @@ -3759,8 +4241,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, @@ -3770,7 +4256,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(&mut Cursor::new(&target_value)).unwrap(), closing_signed); + assert_eq!( + msgs::ClosingSigned::read(&mut Cursor::new(&target_value)).unwrap(), + closing_signed + ); let closing_signed_with_range = msgs::ClosingSigned { channel_id: ChannelId::from_bytes([2; 32]), @@ -3784,19 +4273,24 @@ 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(&mut Cursor::new(&target_value_with_range)).unwrap(), - closing_signed_with_range); + assert_eq!( + msgs::ClosingSigned::read(&mut Cursor::new(&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]), @@ -3827,13 +4321,11 @@ mod tests { #[test] fn encoding_update_fail_htlc() { - let reason = OnionErrorPacket { - data: [1; 32].to_vec(), - }; + let reason = OnionErrorPacket { data: [1; 32].to_vec() }; let update_fail_htlc = msgs::UpdateFailHTLC { channel_id: ChannelId::from_bytes([2; 32]), htlc_id: 2316138423780173, - reason + reason, }; let encoded_value = update_fail_htlc.encode(); let target_value = >::from_hex("020202020202020202020202020202020202020202020202020202020202020200083a840000034d00200101010101010101010101010101010101010101010101010101010101010101").unwrap(); @@ -3846,7 +4338,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(); @@ -3855,14 +4347,30 @@ 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, @@ -3889,10 +4397,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, @@ -3909,7 +4423,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); } @@ -3921,22 +4438,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], @@ -3973,10 +4502,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); @@ -3984,9 +4510,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); @@ -4000,18 +4524,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 { - 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] @@ -4029,13 +4560,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 { - 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] @@ -4044,7 +4582,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, @@ -4057,32 +4595,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 { - 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, @@ -4093,28 +4630,31 @@ 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.clone(); } 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 { custom_tlvs, .. } => assert!(custom_tlvs.is_empty()), + msgs::InboundOnionPayload::Receive { 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, @@ -4127,7 +4667,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 { payment_data: None, payment_metadata: None, @@ -4136,20 +4677,20 @@ 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 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 { @@ -4169,7 +4710,10 @@ 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 = Readable::read(&mut Cursor::new(&target_value[..])).unwrap(); @@ -4184,7 +4728,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, @@ -4195,7 +4742,10 @@ 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); @@ -4208,8 +4758,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 = Readable::read(&mut Cursor::new(&target_value[..])); + target_value.append( + &mut >::from_hex("001601789c636000833e08659309a65878be010010a9023a") + .unwrap(), + ); + let result: Result = + Readable::read(&mut Cursor::new(&target_value[..])); assert!(result.is_err(), "Expected decode failure with unsupported zlib encoding"); } } @@ -4221,7 +4775,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, @@ -4229,7 +4785,10 @@ 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); @@ -4239,8 +4798,12 @@ mod tests { 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 = Readable::read(&mut Cursor::new(&target_value[..])); + target_value.append( + &mut >::from_hex("001601789c636000833e08659309a65878be010010a9023a") + .unwrap(), + ); + let result: Result = + Readable::read(&mut Cursor::new(&target_value[..])); assert!(result.is_err(), "Expected decode failure with unsupported zlib encoding"); } } @@ -4253,7 +4816,10 @@ 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 = Readable::read(&mut Cursor::new(&target_value[..])).unwrap(); @@ -4262,7 +4828,7 @@ mod tests { } #[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, @@ -4270,7 +4836,10 @@ 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 = Readable::read(&mut Cursor::new(&target_value[..])).unwrap(); @@ -4292,8 +4861,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> { @@ -4305,7 +4877,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), @@ -4319,10 +4896,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()); @@ -4334,55 +4909,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 0038bdd79a2..31da2b929e2 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -40,10 +40,9 @@ //! Nodes without channels are disconnected and connected as needed to ensure that deterministic //! blinded paths are used. -use core::time::Duration; use crate::blinded_path::BlindedPath; use crate::events::{Event, MessageSendEventsProvider, PaymentPurpose}; -use crate::ln::channelmanager::{PaymentId, RecentPaymentDetails, Retry, self}; +use crate::ln::channelmanager::{self, PaymentId, RecentPaymentDetails, Retry}; use crate::ln::functional_test_utils::*; use crate::ln::msgs::{ChannelMessageHandler, Init, OnionMessage, OnionMessageHandler}; use crate::offers::invoice::Bolt12Invoice; @@ -53,6 +52,7 @@ use crate::offers::parse::Bolt12SemanticError; use crate::onion_message::messenger::PeeledOnion; use crate::onion_message::offers::OffersMessage; use crate::onion_message::packet::ParsedOnionMessageContents; +use core::time::Duration; use crate::prelude::*; @@ -65,7 +65,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>) { @@ -99,7 +99,7 @@ fn disconnect_peers<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, peers: &[&Node<'a, 'b } 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); @@ -112,34 +112,35 @@ fn route_bolt12_payment<'a, 'b, 'c>( // invoice contains the payment_hash but it was encrypted inside an onion message. let amount_msats = invoice.amount_msats(); let payment_hash = invoice.payment_hash(); - do_pass_along_path( - node, path, amount_msats, payment_hash, None, ev, false, false, None, false - ); + do_pass_along_path(node, path, amount_msats, payment_hash, None, ev, false, false, None, false); } fn claim_bolt12_payment<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>]) { let recipient = &path[path.len() - 1]; match get_event!(recipient, Event::PaymentClaimable) { Event::PaymentClaimable { - purpose: PaymentPurpose::InvoicePayment { - payment_preimage: Some(payment_preimage), .. - }, .. + purpose: PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. }, + .. } => claim_payment(node, path, payment_preimage), _ => panic!(), }; } fn extract_invoice_request<'a, 'b, 'c>( - node: &Node<'a, 'b, 'c>, message: &OnionMessage + node: &Node<'a, 'b, 'c>, message: &OnionMessage, ) -> (InvoiceRequest, Option) { match node.onion_messenger.peel_onion_message(message) { Ok(PeeledOnion::Receive(message, _, reply_path)) => match message { ParsedOnionMessageContents::Offers(offers_message) => match offers_message { OffersMessage::InvoiceRequest(invoice_request) => (invoice_request, reply_path), OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice), - OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error), + OffersMessage::InvoiceError(error) => { + panic!("Unexpected invoice_error: {:?}", error) + }, + }, + ParsedOnionMessageContents::Custom(message) => { + panic!("Unexpected custom message: {:?}", message) }, - ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message), }, Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"), Err(e) => panic!("Failed to process onion message {:?}", e), @@ -150,11 +151,17 @@ fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) match node.onion_messenger.peel_onion_message(message) { Ok(PeeledOnion::Receive(message, _, _)) => match message { ParsedOnionMessageContents::Offers(offers_message) => match offers_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, - OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error), + OffersMessage::InvoiceError(error) => { + panic!("Unexpected invoice_error: {:?}", error) + }, + }, + ParsedOnionMessageContents::Custom(message) => { + panic!("Unexpected custom message: {:?}", message) }, - ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message), }, Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"), Err(e) => panic!("Failed to process onion message {:?}", e), @@ -162,16 +169,20 @@ 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::Receive(message, _, _)) => match message { ParsedOnionMessageContents::Offers(offers_message) => match offers_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), OffersMessage::InvoiceError(error) => error, }, - ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message), + ParsedOnionMessageContents::Custom(message) => { + panic!("Unexpected custom message: {:?}", message) + }, }, Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"), Err(e) => panic!("Failed to process onion message {:?}", e), @@ -195,7 +206,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); @@ -216,10 +229,13 @@ 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("coffee".to_string()).unwrap() + let offer = alice + .node + .create_offer_builder("coffee".to_string()) + .unwrap() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); assert_ne!(offer.signing_pubkey(), alice_id); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -227,7 +243,9 @@ 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), None) + david + .node + .pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -284,7 +302,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); @@ -307,12 +327,19 @@ 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 + let refund = david + .node .create_refund_builder( - "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None + "refund".to_string(), + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None, ) .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_id(), david_id); @@ -364,10 +391,13 @@ 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("coffee".to_string()).unwrap() + let offer = alice + .node + .create_offer_builder("coffee".to_string()) + .unwrap() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); assert_ne!(offer.signing_pubkey(), alice_id); assert!(!offer.paths().is_empty()); for path in offer.paths() { @@ -423,12 +453,19 @@ 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 + let refund = bob + .node .create_refund_builder( - "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None + "refund".to_string(), + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None, ) .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_id(), bob_id); @@ -475,11 +512,14 @@ 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("coffee".to_string()).unwrap() + let offer = alice + .node + .create_offer_builder("coffee".to_string()) + .unwrap() .clear_paths() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); assert_eq!(offer.signing_pubkey(), alice_id); assert!(offer.paths().is_empty()); @@ -519,13 +559,20 @@ 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 + let refund = bob + .node .create_refund_builder( - "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None + "refund".to_string(), + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None, ) .unwrap() .clear_paths() - .build().unwrap(); + .build() + .unwrap(); assert_eq!(refund.payer_id(), bob_id); assert!(refund.paths().is_empty()); expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); @@ -573,7 +620,12 @@ fn fails_creating_refund_without_blinded_paths() { let payment_id = PaymentId([1; 32]); match nodes[0].node.create_refund_builder( - "refund".to_string(), 10_000, absolute_expiry, payment_id, Retry::Attempts(0), None + "refund".to_string(), + 10_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None, ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths), @@ -602,10 +654,13 @@ fn fails_creating_invoice_request_without_blinded_reply_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("coffee".to_string()).unwrap() + let offer = alice + .node + .create_offer_builder("coffee".to_string()) + .unwrap() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); let payment_id = PaymentId([1; 32]); @@ -636,17 +691,19 @@ 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("coffee".to_string()).unwrap() + let offer = alice + .node + .create_offer_builder("coffee".to_string()) + .unwrap() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); let payment_id = PaymentId([1; 32]); - assert!( - david.node.pay_for_offer( - &offer, None, None, None, payment_id, Retry::Attempts(0), None - ).is_ok() - ); + assert!(david + .node + .pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) + .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), None) { @@ -668,15 +725,26 @@ 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( - "refund".to_string(), 10_000, absolute_expiry, payment_id, Retry::Attempts(0), None - ).is_ok() - ); + assert!(nodes[0] + .node + .create_refund_builder( + "refund".to_string(), + 10_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None + ) + .is_ok()); expect_recent_payment!(nodes[0], RecentPaymentDetails::AwaitingInvoice, payment_id); match nodes[0].node.create_refund_builder( - "refund".to_string(), 10_000, absolute_expiry, payment_id, Retry::Attempts(0), None + "refund".to_string(), + 10_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None, ) { Ok(_) => panic!("Expected error"), Err(e) => assert_eq!(e, Bolt12SemanticError::DuplicatePaymentId), @@ -701,7 +769,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); @@ -722,13 +792,18 @@ 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("coffee".to_string()).unwrap() + let offer = alice + .node + .create_offer_builder("coffee".to_string()) + .unwrap() .amount_msats(10_000_000) - .build().unwrap(); + .build() + .unwrap(); let payment_id = PaymentId([1; 32]); - david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) + david + .node + .pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) .unwrap(); connect_peers(david, bob); @@ -767,7 +842,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); @@ -786,12 +863,19 @@ 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 + let refund = david + .node .create_refund_builder( - "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None + "refund".to_string(), + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None, ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); match alice.node.request_refund_payment(&refund) { Ok(_) => panic!("Expected error"), @@ -814,7 +898,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); @@ -837,12 +923,19 @@ 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 + let refund = david + .node .create_refund_builder( - "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None + "refund".to_string(), + 10_000_000, + absolute_expiry, + payment_id, + Retry::Attempts(0), + None, ) .unwrap() - .build().unwrap(); + .build() + .unwrap(); expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id); // Alice sends the first invoice diff --git a/lightning/src/ln/onion_payment.rs b/lightning/src/ln/onion_payment.rs index 00843d5e4e9..e504643a6b6 100644 --- a/lightning/src/ln/onion_payment.rs +++ b/lightning/src/ln/onion_payment.rs @@ -3,20 +3,23 @@ //! 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, HashEngine}; use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::secp256k1::{self, PublicKey, Scalar, 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::ln::PaymentHash; -use crate::ln::channelmanager::{BlindedFailure, BlindedForward, CLTV_FAR_FAR_AWAY, HTLCFailureMsg, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting}; +use crate::ln::channelmanager::{ + BlindedFailure, BlindedForward, HTLCFailureMsg, PendingHTLCInfo, PendingHTLCRouting, + CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, +}; use crate::ln::features::BlindedHopFeatures; use crate::ln::msgs; use crate::ln::onion_utils; use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING}; +use crate::ln::PaymentHash; use crate::sign::{NodeSigner, Recipient}; use crate::util::logger::Logger; @@ -35,34 +38,34 @@ pub struct InboundHTLCErr { } 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)) } pub(super) fn create_fwd_pending_htlc_info( msg: &msgs::UpdateAddHTLC, hop_data: msgs::InboundOnionPayload, hop_hmac: [u8; 32], new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32], - next_packet_pubkey_opt: Option> + next_packet_pubkey_opt: Option>, ) -> Result { debug_assert!(next_packet_pubkey_opt.is_some()); let outgoing_packet = msgs::OnionPacket { @@ -72,46 +75,58 @@ pub(super) fn create_fwd_pending_htlc_info( hmac: hop_hmac, }; - let ( - short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point - ) = match hop_data { - msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } => - (short_channel_id, amt_to_forward, outgoing_cltv_value, None), - msgs::InboundOnionPayload::BlindedForward { - short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features, - } => { - let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward( - 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 { + let (short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point) = + match hop_data { + msgs::InboundOnionPayload::Forward { + short_channel_id, + amt_to_forward, + outgoing_cltv_value, + } => (short_channel_id, amt_to_forward, outgoing_cltv_value, None), + msgs::InboundOnionPayload::BlindedForward { + short_channel_id, + payment_relay, + payment_constraints, + intro_node_blinding_point, + features, + } => { + let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward( + 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 { msg: "Underflow calculating outbound amount or cltv value for blinded forward", err_code: INVALID_ONION_BLINDING, err_data: vec![0; 32], } - })?; - (short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point) - }, - msgs::InboundOnionPayload::Receive { .. } | msgs::InboundOnionPayload::BlindedReceive { .. } => - return Err(InboundHTLCErr { - msg: "Final Node OnionHopData provided for us as an intermediary node", - err_code: 0x4000 | 22, - err_data: Vec::new(), - }), - }; + })?; + (short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point) + }, + msgs::InboundOnionPayload::Receive { .. } + | msgs::InboundOnionPayload::BlindedReceive { .. } => { + return Err(InboundHTLCErr { + msg: "Final Node OnionHopData provided for us as an intermediary node", + err_code: 0x4000 | 22, + err_data: Vec::new(), + }) + }, + }; Ok(PendingHTLCInfo { routing: PendingHTLCRouting::Forward { onion_packet: outgoing_packet, short_channel_id, - blinded: intro_node_blinding_point.or(msg.blinding_point) - .map(|bp| BlindedForward { - inbound_blinding_point: bp, - failure: intro_node_blinding_point - .map(|_| BlindedFailure::FromIntroductionNode) - .unwrap_or(BlindedFailure::FromBlindedNode), - }), + blinded: intro_node_blinding_point.or(msg.blinding_point).map(|bp| BlindedForward { + inbound_blinding_point: bp, + failure: intro_node_blinding_point + .map(|_| BlindedFailure::FromIntroductionNode) + .unwrap_or(BlindedFailure::FromBlindedNode), + }), }, payment_hash: msg.payment_hash, incoming_shared_secret: shared_secret, @@ -128,36 +143,64 @@ pub(super) fn create_recv_pending_htlc_info( counterparty_skimmed_fee_msat: Option, current_height: u32, accept_mpp_keysend: bool, ) -> Result { let ( - payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, onion_cltv_expiry, - payment_metadata, requires_blinded_error + payment_data, + keysend_preimage, + custom_tlvs, + onion_amt_msat, + onion_cltv_expiry, + payment_metadata, + requires_blinded_error, ) = match hop_data { msgs::InboundOnionPayload::Receive { - 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, false), + 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, + false, + ), msgs::InboundOnionPayload::BlindedReceive { - sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret, - intro_node_blinding_point, payment_constraints, .. + sender_intended_htlc_amt_msat, + total_msat, + cltv_expiry_height, + payment_secret, + intro_node_blinding_point, + payment_constraints, + .. } => { 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 { - err_code: INVALID_ONION_BLINDING, - err_data: vec![0; 32], - msg: "Amount or cltv_expiry violated blinded payment constraints", - } - })?; + .map_err(|()| InboundHTLCErr { + err_code: INVALID_ONION_BLINDING, + 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), None, Vec::new(), sender_intended_htlc_amt_msat, cltv_expiry_height, - None, intro_node_blinding_point.is_none()) - } + ( + Some(payment_data), + None, + Vec::new(), + sender_intended_htlc_amt_msat, + cltv_expiry_height, + None, + intro_node_blinding_point.is_none(), + ) + }, msgs::InboundOnionPayload::Forward { .. } => { return Err(InboundHTLCErr { - err_code: 0x4000|22, + err_code: 0x4000 | 22, err_data: Vec::new(), msg: "Got non final data with an HMAC of 0", }) @@ -168,15 +211,15 @@ pub(super) fn create_recv_pending_htlc_info( err_data: vec![0; 32], msg: "Got blinded non final data with an HMAC of 0", }) - } + }, }; // final_incorrect_cltv_expiry if onion_cltv_expiry > cltv_expiry { return Err(InboundHTLCErr { msg: "Upstream node set CLTV to less than the CLTV set by the sender", err_code: 18, - 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 @@ -190,13 +233,14 @@ pub(super) fn create_recv_pending_htlc_info( err_data.extend_from_slice(&amt_msat.to_be_bytes()); err_data.extend_from_slice(¤t_height.to_be_bytes()); return Err(InboundHTLCErr { - err_code: 0x4000 | 15, err_data, + err_code: 0x4000 | 15, + err_data, 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 { err_code: 19, @@ -214,14 +258,14 @@ pub(super) fn create_recv_pending_htlc_info( let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array()); if hashed_preimage != payment_hash { return Err(InboundHTLCErr { - err_code: 0x4000|22, + err_code: 0x4000 | 22, err_data: Vec::new(), msg: "Payment preimage didn't match payment hash", }); } if !accept_mpp_keysend && payment_data.is_some() { return Err(InboundHTLCErr { - err_code: 0x4000|22, + err_code: 0x4000 | 22, err_data: Vec::new(), msg: "We don't support MPP keysend payments", }); @@ -244,7 +288,7 @@ pub(super) fn create_recv_pending_htlc_info( } } else { return Err(InboundHTLCErr { - err_code: 0x4000|0x2000|3, + err_code: 0x4000 | 0x2000 | 3, err_data: Vec::new(), msg: "We require payment_secrets", }); @@ -278,53 +322,63 @@ where L::Target: Logger, { let (hop, shared_secret, next_packet_details_opt) = - decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx - ).map_err(|e| { - let (err_code, err_data) = match e { - HTLCFailureMsg::Malformed(m) => (m.failure_code, Vec::new()), - HTLCFailureMsg::Relay(r) => (0x4000 | 22, r.reason.data), - }; - let msg = "Failed to decode update add htlc onion"; - InboundHTLCErr { msg, err_code, err_data } - })?; + decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx).map_err(|e| { + let (err_code, err_data) = match e { + HTLCFailureMsg::Malformed(m) => (m.failure_code, Vec::new()), + HTLCFailureMsg::Relay(r) => (0x4000 | 22, r.reason.data), + }; + let msg = "Failed to decode update add htlc onion"; + InboundHTLCErr { msg, err_code, err_data } + })?; Ok(match hop { onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => { let NextPacketDetails { - next_packet_pubkey, outgoing_amt_msat: _, outgoing_scid: _, outgoing_cltv_value + next_packet_pubkey, + outgoing_amt_msat: _, + outgoing_scid: _, + 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", - err_code: 0x4000 | 22, - err_data: Vec::new(), - }), + None => { + return Err(InboundHTLCErr { + msg: "Failed to decode update add htlc onion", + err_code: 0x4000 | 22, + err_data: Vec::new(), + }) + }, }; - if let Err((err_msg, code)) = check_incoming_htlc_cltv( - cur_height, outgoing_cltv_value, msg.cltv_expiry - ) { - return Err(InboundHTLCErr { - msg: err_msg, - err_code: code, - err_data: Vec::new(), - }); + if let Err((err_msg, code)) = + check_incoming_htlc_cltv(cur_height, outgoing_cltv_value, msg.cltv_expiry) + { + return Err(InboundHTLCErr { msg: err_msg, err_code: code, 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, next_hop_data, next_hop_hmac, new_packet_bytes, shared_secret, - Some(next_packet_pubkey) + msg, + next_hop_data, + next_hop_hmac, + new_packet_bytes, + shared_secret, + Some(next_packet_pubkey), )? }, - onion_utils::Hop::Receive(received_data) => { - create_recv_pending_htlc_info( - received_data, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry, - None, allow_skimmed_fees, msg.skimmed_fee_msat, cur_height, accept_mpp_keysend, - )? - } + onion_utils::Hop::Receive(received_data) => create_recv_pending_htlc_info( + received_data, + shared_secret, + msg.payment_hash, + msg.amount_msat, + msg.cltv_expiry, + None, + allow_skimmed_fees, + msg.skimmed_fee_msat, + cur_height, + accept_mpp_keysend, + )?, }) } @@ -335,7 +389,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, [u8; 32], Option), HTLCFailureMsg> where @@ -343,22 +401,20 @@ where L::Target: Logger, { macro_rules! return_malformed_err { - ($msg: expr, $err_code: expr) => { - { - log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg); - let (sha256_of_onion, failure_code) = if msg.blinding_point.is_some() { - ([0; 32], INVALID_ONION_BLINDING) - } else { - (Sha256::hash(&msg.onion_routing_packet.hop_data).to_byte_array(), $err_code) - }; - return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - sha256_of_onion, - failure_code, - })); - } - } + ($msg: expr, $err_code: expr) => {{ + log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg); + let (sha256_of_onion, failure_code) = if msg.blinding_point.is_some() { + ([0; 32], INVALID_ONION_BLINDING) + } else { + (Sha256::hash(&msg.onion_routing_packet.hop_data).to_byte_array(), $err_code) + }; + return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + sha256_of_onion, + failure_code, + })); + }}; } if let Err(_) = msg.onion_routing_packet.public_key { @@ -371,9 +427,14 @@ where hmac.input(blinded_tlvs_ss.as_ref()); Scalar::from_be_bytes(Hmac::from_engine(hmac).to_byte_array()).unwrap() }); - let shared_secret = node_signer.ecdh( - Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), blinded_node_id_tweak.as_ref() - ).unwrap().secret_bytes(); + let shared_secret = node_signer + .ecdh( + Recipient::Node, + &msg.onion_routing_packet.public_key.unwrap(), + blinded_node_id_tweak.as_ref(), + ) + .unwrap() + .secret_bytes(); if msg.onion_routing_packet.version != 0 { //TODO: Spec doesn't indicate if we should only hash hop_data here (and in other @@ -385,26 +446,28 @@ where return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4); } macro_rules! return_err { - ($msg: expr, $err_code: expr, $data: expr) => { - { - if msg.blinding_point.is_some() { - return_malformed_err!($msg, INVALID_ONION_BLINDING) - } - - log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg); - return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { - channel_id: msg.channel_id, - htlc_id: msg.htlc_id, - reason: HTLCFailReason::reason($err_code, $data.to_vec()) - .get_encrypted_failure_packet(&shared_secret, &None), - })); + ($msg: expr, $err_code: expr, $data: expr) => {{ + if msg.blinding_point.is_some() { + return_malformed_err!($msg, INVALID_ONION_BLINDING) } - } + + log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg); + return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { + channel_id: msg.channel_id, + htlc_id: msg.htlc_id, + reason: HTLCFailReason::reason($err_code, $data.to_vec()) + .get_encrypted_failure_packet(&shared_secret, &None), + })); + }}; } let next_hop = match onion_utils::decode_next_payment_hop( - shared_secret, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac, - msg.payment_hash, msg.blinding_point, node_signer + shared_secret, + &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, err_code }) => { @@ -417,51 +480,85 @@ where let next_packet_details = match next_hop { onion_utils::Hop::Forward { - next_hop_data: msgs::InboundOnionPayload::Forward { - short_channel_id, amt_to_forward, outgoing_cltv_value - }, .. + next_hop_data: + msgs::InboundOnionPayload::Forward { + short_channel_id, + amt_to_forward, + outgoing_cltv_value, + }, + .. } => { - let next_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx, - msg.onion_routing_packet.public_key.unwrap(), &shared_secret); + let next_packet_pubkey = onion_utils::next_hop_pubkey( + secp_ctx, + msg.onion_routing_packet.public_key.unwrap(), + &shared_secret, + ); NextPacketDetails { - next_packet_pubkey, outgoing_scid: short_channel_id, - outgoing_amt_msat: amt_to_forward, outgoing_cltv_value + next_packet_pubkey, + outgoing_scid: short_channel_id, + outgoing_amt_msat: amt_to_forward, + outgoing_cltv_value, } }, onion_utils::Hop::Forward { - next_hop_data: msgs::InboundOnionPayload::BlindedForward { - short_channel_id, ref payment_relay, ref payment_constraints, ref features, .. - }, .. + next_hop_data: + msgs::InboundOnionPayload::BlindedForward { + short_channel_id, + ref payment_relay, + ref payment_constraints, + ref features, + .. + }, + .. } => { - 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_err!("Underflow calculating outbound amount or cltv value for blinded forward", + 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_err!("Underflow calculating outbound amount or cltv value for blinded forward", INVALID_ONION_BLINDING, &[0; 32]); - } - }; - let next_packet_pubkey = onion_utils::next_hop_pubkey(&secp_ctx, - msg.onion_routing_packet.public_key.unwrap(), &shared_secret); + }, + }; + let next_packet_pubkey = onion_utils::next_hop_pubkey( + &secp_ctx, + msg.onion_routing_packet.public_key.unwrap(), + &shared_secret, + ); NextPacketDetails { - next_packet_pubkey, outgoing_scid: short_channel_id, outgoing_amt_msat: amt_to_forward, - outgoing_cltv_value + next_packet_pubkey, + outgoing_scid: short_channel_id, + outgoing_amt_msat: amt_to_forward, + outgoing_cltv_value, } }, onion_utils::Hop::Receive { .. } => return Ok((next_hop, shared_secret, None)), - onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionPayload::Receive { .. }, .. } | - onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionPayload::BlindedReceive { .. }, .. } => - { - return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0; 0]); + onion_utils::Hop::Forward { + next_hop_data: msgs::InboundOnionPayload::Receive { .. }, + .. } + | onion_utils::Hop::Forward { + next_hop_data: msgs::InboundOnionPayload::BlindedReceive { .. }, + .. + } => { + return_err!( + "Final Node OnionHopData provided for us as an intermediary node", + 0x4000 | 22, + &[0; 0] + ); + }, }; Ok((next_hop, shared_secret, Some(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, u16)> { if (cltv_expiry as u64) < (outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 { return Err(( @@ -472,10 +569,12 @@ pub(super) fn check_incoming_htlc_cltv( // Theoretically, channel counterparty shouldn't send us a HTLC expiring now, // but we want to be robust wrt to counterparty packet sanitization (see // HTLC_FAIL_BACK_BUFFER rationale). - if cltv_expiry <= cur_height + HTLC_FAIL_BACK_BUFFER as u32 { // expiry_too_soon + if cltv_expiry <= cur_height + HTLC_FAIL_BACK_BUFFER as u32 { + // expiry_too_soon return Err(("CLTV expiry is too close", 0x1000 | 14)); } - if cltv_expiry > cur_height + CLTV_FAR_FAR_AWAY as u32 { // expiry_too_far + if cltv_expiry > cur_height + CLTV_FAR_FAR_AWAY as u32 { + // expiry_too_far return Err(("CLTV expiry is too far in the future", 21)); } // If the HTLC expires ~now, don't bother trying to forward it to our @@ -495,17 +594,17 @@ 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::{PaymentPreimage, PaymentHash, PaymentSecret}; - use crate::ln::ChannelId; use crate::ln::channelmanager::RecipientOnionFields; use crate::ln::features::{ChannelFeatures, NodeFeatures}; use crate::ln::msgs; use crate::ln::onion_utils::create_payment_onion; + use crate::ln::ChannelId; + use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::routing::router::{Path, RouteHop}; 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() { @@ -521,22 +620,39 @@ 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 onion_keys = super::onion_utils::construct_onion_keys(&secp_ctx, &path, &session_priv).unwrap(); + let path = Path { hops, blinded_tail: None }; + let onion_keys = + super::onion_utils::construct_onion_keys(&secp_ctx, &path, &session_priv).unwrap(); let (onion_payloads, ..) = super::onion_utils::build_onion_payloads( - &path, total_amt_msat, recipient_onion, cur_height + 1, &Some(keysend_preimage) - ).unwrap(); + &path, + total_amt_msat, + recipient_onion, + cur_height + 1, + &Some(keysend_preimage), + ) + .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] @@ -549,42 +665,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), prng_seed - ).unwrap(); + &secp_ctx, + &path, + &session_priv, + total_amt_msat, + recipient_onion, + cur_height, + &payment_hash, + &Some(preimage), + 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, true, 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, true, false) - .map_err(|e| e.msg).unwrap(); + let peeled2 = + peel_payment_onion(&msg2, &&charlie, &&logger, &secp_ctx, cur_height, true, false) + .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); }, @@ -594,7 +731,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]), @@ -608,9 +745,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(); @@ -645,11 +792,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 cfdba07a2f2..0301b76523d 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -12,27 +12,36 @@ //! 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, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentFailureReason}; -use crate::ln::{PaymentHash, PaymentSecret}; +use crate::events::{ + Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, + PaymentFailureReason, +}; 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; -use crate::routing::gossip::{NetworkUpdate, RoutingFees}; -use crate::routing::router::{get_route, PaymentParameters, Route, RouteParameters, RouteHint, RouteHintHop}; -use crate::ln::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::features::{Bolt11InvoiceFeatures, InitFeatures}; use crate::ln::msgs; use crate::ln::msgs::{ChannelMessageHandler, ChannelUpdate}; +use crate::ln::onion_utils; use crate::ln::wire::Encode; -use crate::util::ser::{Writeable, Writer, BigSize}; -use crate::util::test_utils; -use crate::util::config::{UserConfig, ChannelConfig, MaxDustHTLCExposure}; +use crate::ln::{PaymentHash, PaymentSecret}; +use crate::routing::gossip::{NetworkUpdate, RoutingFees}; +use crate::routing::router::{ + get_route, PaymentParameters, Route, RouteHint, RouteHintHop, RouteParameters, +}; +use crate::sign::{EntropySource, NodeSigner, Recipient}; +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 bitcoin::blockdata::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::{Secp256k1, SecretKey}; @@ -43,11 +52,30 @@ use core::default::Default; use crate::ln::functional_test_utils::*; -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) - 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, +) 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); + 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, + ); } // test_case @@ -57,15 +85,15 @@ 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_code: Option, - expected_channel_update: Option, expected_short_channel_id: Option -) - where F1: for <'a> FnMut(&'a mut msgs::UpdateAddHTLC), - F2: for <'a> FnMut(&'a mut msgs::UpdateFailHTLC), - F3: FnMut(), + expected_channel_update: Option, expected_short_channel_id: Option, +) 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) => {{ @@ -75,20 +103,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, *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()); // temper update_add (0 => 1) @@ -102,12 +137,18 @@ 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 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 { @@ -132,7 +173,10 @@ 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() }] + ); } let update_2_1 = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); @@ -166,26 +210,43 @@ 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, expected_error_code); if expected_channel_update.is_some() { match network_update { Some(update) => match update { &NetworkUpdate::ChannelUpdateMessage { .. } => { - if let NetworkUpdate::ChannelUpdateMessage { .. } = expected_channel_update.unwrap() {} else { + if let NetworkUpdate::ChannelUpdateMessage { .. } = + expected_channel_update.unwrap() + { + } else { panic!("channel_update not found!"); } }, &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 { @@ -193,14 +254,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 { @@ -218,15 +283,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!(*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"), } } @@ -234,8 +306,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 { @@ -249,13 +321,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 { @@ -286,25 +358,56 @@ 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), Some(config), Some(config)]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), 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, 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, + 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 // malleated the payment before forwarding, taking funds when they shouldn't have. let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]); let short_channel_id = channels[0].0.contents.short_channel_id; - run_onion_failure_test("fee_insufficient", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, || {}, true, Some(UPDATE|12), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true}), Some(short_channel_id)); + run_onion_failure_test( + "fee_insufficient", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + || {}, + true, + Some(UPDATE | 12), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + ); // In an earlier version, we spuriously failed to forward payments if the expected feerate // changed between the channel open and the payment. @@ -313,11 +416,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); } @@ -340,127 +457,390 @@ 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), Some(config), Some(node_2_cfg)]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[Some(config), 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); // 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).unwrap(); - let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &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(PERM|22), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(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, + ) + .unwrap(); + let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 40000, + RecipientOnionFields::spontaneous_empty(), + cur_height, + &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(PERM | 22), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + ); // 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).unwrap(); - let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &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(PERM|22), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(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, + ) + .unwrap(); + let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 40000, + RecipientOnionFields::spontaneous_empty(), + cur_height, + &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(PERM | 22), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + ); // 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), NODE|2, &[0;0]); - }, ||{}, true, Some(NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: false}), Some(route.paths[0].hops[0].short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[0].shared_secret.as_ref(), + NODE | 2, + &[0; 0], + ); + }, + || {}, + true, + Some(NODE | 2), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: false, + }), + Some(route.paths[0].hops[0].short_channel_id), + ); // 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[1].shared_secret.as_ref(), NODE|2, &[0;0]); - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, true, Some(NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: false}), Some(route.paths[0].hops[1].short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[1].shared_secret.as_ref(), + NODE | 2, + &[0; 0], + ); + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + true, + Some(NODE | 2), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: false, + }), + Some(route.paths[0].hops[1].short_channel_id), + ); 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|NODE|2, &[0;0]); - }, ||{}, true, Some(PERM|NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[0].shared_secret.as_ref(), + PERM | NODE | 2, + &[0; 0], + ); + }, + || {}, + true, + Some(PERM | NODE | 2), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[0].short_channel_id), + ); // 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[1].shared_secret.as_ref(), PERM|NODE|2, &[0;0]); - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, false, Some(PERM|NODE|2), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: true}), Some(route.paths[0].hops[1].short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[1].shared_secret.as_ref(), + PERM | NODE | 2, + &[0; 0], + ); + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + false, + Some(PERM | NODE | 2), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[1].short_channel_id), + ); 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|NODE|3, &[0;0]); - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, true, Some(PERM|NODE|3), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[0].shared_secret.as_ref(), + PERM | NODE | 3, + &[0; 0], + ); + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + true, + Some(PERM | NODE | 3), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[0].short_channel_id), + ); // 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[1].shared_secret.as_ref(), PERM|NODE|3, &[0;0]); - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, false, Some(PERM|NODE|3), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[1].pubkey, is_permanent: true}), Some(route.paths[0].hops[1].short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[1].shared_secret.as_ref(), + PERM | NODE | 3, + &[0; 0], + ); + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + false, + Some(PERM | NODE | 3), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[1].short_channel_id), + ); 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(BADONION|PERM|4), None, Some(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(BADONION | PERM | 4), + None, + Some(short_channel_id), + ); - run_onion_failure_test("invalid_onion_hmac", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { msg.onion_routing_packet.hmac = [3; 32]; }, ||{}, true, - Some(BADONION|PERM|5), None, Some(short_channel_id)); + run_onion_failure_test( + "invalid_onion_hmac", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.onion_routing_packet.hmac = [3; 32]; + }, + || {}, + true, + Some(BADONION | PERM | 5), + None, + Some(short_channel_id), + ); - 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(BADONION|PERM|6), None, Some(short_channel_id)); + 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(BADONION | PERM | 6), + None, + Some(short_channel_id), + ); let short_channel_id = channels[1].0.contents.short_channel_id; let chan_update = ChannelUpdate::dummy(short_channel_id); @@ -469,58 +849,187 @@ 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data); - }, ||{}, true, Some(UPDATE|7), Some(NetworkUpdate::ChannelUpdateMessage{msg: chan_update.clone()}), Some(short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[0].shared_secret.as_ref(), + UPDATE | 7, + &err_data, + ); + }, + || {}, + true, + Some(UPDATE | 7), + Some(NetworkUpdate::ChannelUpdateMessage { msg: chan_update.clone() }), + Some(short_channel_id), + ); // 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), UPDATE|7, &err_data_without_type); - }, ||{}, true, Some(UPDATE|7), Some(NetworkUpdate::ChannelUpdateMessage{msg: chan_update}), Some(short_channel_id)); + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[0].shared_secret.as_ref(), + UPDATE | 7, + &err_data_without_type, + ); + }, + || {}, + true, + Some(UPDATE | 7), + Some(NetworkUpdate::ChannelUpdateMessage { msg: chan_update }), + Some(short_channel_id), + ); 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|8, &[0;0]); - // short_channel_id from the processing node - }, ||{}, true, Some(PERM|8), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[0].shared_secret.as_ref(), + PERM | 8, + &[0; 0], + ); + // short_channel_id from the processing node + }, + || {}, + true, + Some(PERM | 8), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + ); 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[0].shared_secret.as_ref(), PERM|9, &[0;0]); - // short_channel_id from the processing node - }, ||{}, true, Some(PERM|9), Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent: true}), Some(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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[0].shared_secret.as_ref(), + PERM | 9, + &[0; 0], + ); + // short_channel_id from the processing node + }, + || {}, + true, + Some(PERM | 9), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + ); 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", 0, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(PERM|10), - Some(NetworkUpdate::ChannelFailure{short_channel_id, is_permanent:true}), Some(short_channel_id)); + run_onion_failure_test( + "unknown_next_peer", + 0, + &nodes, + &bogus_route, + &payment_hash, + &payment_secret, + |_| {}, + || {}, + true, + Some(PERM | 10), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(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", 0, &nodes, &bogus_route, &payment_hash, &payment_secret, |_| {}, ||{}, true, Some(UPDATE|11), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id)); + bogus_route.paths[0].hops[route_len - 1].fee_msat = amt_to_forward; + run_onion_failure_test( + "amount_below_minimum", + 0, + &nodes, + &bogus_route, + &payment_hash, + &payment_secret, + |_| {}, + || {}, + true, + Some(UPDATE | 11), + Some(NetworkUpdate::ChannelUpdateMessage { msg: ChannelUpdate::dummy(short_channel_id) }), + Some(short_channel_id), + ); // Clear pending payments so that the following positive test has the correct payment hash. for node in nodes.iter() { @@ -528,109 +1037,300 @@ 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); let short_channel_id = channels[0].0.contents.short_channel_id; - run_onion_failure_test("fee_insufficient", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { - msg.amount_msat -= 1; - }, || {}, true, Some(UPDATE|12), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true}), Some(short_channel_id)); + run_onion_failure_test( + "fee_insufficient", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + msg.amount_msat -= 1; + }, + || {}, + true, + Some(UPDATE | 12), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + ); let short_channel_id = channels[0].0.contents.short_channel_id; - run_onion_failure_test("incorrect_cltv_expiry", 0, &nodes, &route, &payment_hash, &payment_secret, |msg| { - // need to violate: cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value - msg.cltv_expiry -= 1; - }, || {}, true, Some(UPDATE|13), Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true}), Some(short_channel_id)); + run_onion_failure_test( + "incorrect_cltv_expiry", + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |msg| { + // need to violate: cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value + msg.cltv_expiry -= 1; + }, + || {}, + true, + Some(UPDATE | 13), + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent: true }), + Some(short_channel_id), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("expiry_too_soon", 0, &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(UPDATE|14), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id)); - - run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, false, Some(PERM|15), None, None); + run_onion_failure_test( + "expiry_too_soon", + 0, + &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(UPDATE | 14), + Some(NetworkUpdate::ChannelUpdateMessage { msg: ChannelUpdate::dummy(short_channel_id) }), + Some(short_channel_id), + ); + + run_onion_failure_test( + "unknown_payment_hash", + 2, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + false, + Some(PERM | 15), + 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(0x4000 | 15), None, None); - - run_onion_failure_test("final_incorrect_cltv_expiry", 1, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - 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(0x4000 | 15), + None, + None, + ); + + run_onion_failure_test( + "final_incorrect_cltv_expiry", + 1, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + 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(18), None, Some(channels[1].0.contents.short_channel_id)); - - run_onion_failure_test("final_incorrect_htlc_amount", 1, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || { - // 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(18), + None, + Some(channels[1].0.contents.short_channel_id), + ); + + run_onion_failure_test( + "final_incorrect_htlc_amount", + 1, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || { + // 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(19), None, Some(channels[1].0.contents.short_channel_id)); + }, + true, + Some(19), + None, + Some(channels[1].0.contents.short_channel_id), + ); let short_channel_id = channels[1].0.contents.short_channel_id; - run_onion_failure_test("channel_disabled", 0, &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(UPDATE|7), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id)); - run_onion_failure_test("channel_disabled", 0, &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(UPDATE|20), Some(NetworkUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy(short_channel_id)}), Some(short_channel_id)); + run_onion_failure_test( + "channel_disabled", + 0, + &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(UPDATE | 7), + Some(NetworkUpdate::ChannelUpdateMessage { msg: ChannelUpdate::dummy(short_channel_id) }), + Some(short_channel_id), + ); + run_onion_failure_test( + "channel_disabled", + 0, + &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(UPDATE | 20), + Some(NetworkUpdate::ChannelUpdateMessage { msg: ChannelUpdate::dummy(short_channel_id) }), + Some(short_channel_id), + ); reconnect_nodes(ReconnectArgs::new(&nodes[1], &nodes[2])); - run_onion_failure_test("expiry_too_far", 0, &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).unwrap(); - let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), height, &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(21), Some(NetworkUpdate::NodeFailure{node_id: route.paths[0].hops[0].pubkey, is_permanent: true}), Some(route.paths[0].hops[0].short_channel_id)); - - 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).unwrap(); - msg.reason = onion_utils::build_first_hop_failure_packet(onion_keys[1].shared_secret.as_ref(), 23, &[0;0]); - }, ||{ - nodes[2].node.fail_htlc_backwards(&payment_hash); - }, true, Some(23), 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", + 0, + &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, + ) + .unwrap(); + let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], + 40000, + RecipientOnionFields::spontaneous_empty(), + height, + &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(21), + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[0].pubkey, + is_permanent: true, + }), + Some(route.paths[0].hops[0].short_channel_id), + ); + + 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, + ) + .unwrap(); + msg.reason = onion_utils::build_first_hop_failure_packet( + onion_keys[1].shared_secret.as_ref(), + 23, + &[0; 0], + ); + }, + || { + nodes[2].node.fail_htlc_backwards(&payment_hash); + }, + true, + Some(23), + 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).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ) + .unwrap(); let mut decoded_err_packet = msgs::DecodedOnionErrorPacket { failuremsg: vec![0], pad: vec![0; 255], @@ -641,20 +1341,41 @@ fn test_onion_failure() { hmac.input(&decoded_err_packet.encode()[32..]); decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array(); msg.reason = onion_utils::encrypt_failure_packet( - &onion_keys[1].shared_secret.as_ref(), &decoded_err_packet.encode()[..]) - }, || nodes[2].node.fail_htlc_backwards(&payment_hash), false, None, - Some(NetworkUpdate::NodeFailure { node_id: route.paths[0].hops[1].pubkey, is_permanent: true }), - Some(channels[1].0.contents.short_channel_id)); - run_onion_failure_test_with_fail_intercept("0-length channel update in intermediate node UPDATE onion failure", - 100, &nodes, &route, &payment_hash, &payment_secret, |msg| { + &onion_keys[1].shared_secret.as_ref(), + &decoded_err_packet.encode()[..], + ) + }, + || nodes[2].node.fail_htlc_backwards(&payment_hash), + false, + None, + Some(NetworkUpdate::NodeFailure { + node_id: route.paths[0].hops[1].pubkey, + is_permanent: true, + }), + Some(channels[1].0.contents.short_channel_id), + ); + run_onion_failure_test_with_fail_intercept( + "0-length channel update in 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).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ) + .unwrap(); let mut decoded_err_packet = msgs::DecodedOnionErrorPacket { failuremsg: vec![ 0x10, 0x7, // UPDATE|7 - 0x0, 0x0 // 0-len channel update + 0x0, 0x0, // 0-len channel update ], pad: vec![0; 255 - 4 /* 4-byte error message */], hmac: [0; 32], @@ -664,21 +1385,39 @@ fn test_onion_failure() { hmac.input(&decoded_err_packet.encode()[32..]); decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array(); msg.reason = onion_utils::encrypt_failure_packet( - &onion_keys[0].shared_secret.as_ref(), &decoded_err_packet.encode()[..]) - }, || {}, true, Some(0x1000|7), + &onion_keys[0].shared_secret.as_ref(), + &decoded_err_packet.encode()[..], + ) + }, + || {}, + true, + Some(0x1000 | 7), Some(NetworkUpdate::ChannelFailure { short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: false, }), - Some(channels[1].0.contents.short_channel_id)); - run_onion_failure_test_with_fail_intercept("0-length channel update in final node UPDATE onion failure", - 200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| { + Some(channels[1].0.contents.short_channel_id), + ); + run_onion_failure_test_with_fail_intercept( + "0-length channel update in final node UPDATE onion failure", + 200, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_msg| {}, + |msg| { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); - let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ) + .unwrap(); let mut decoded_err_packet = msgs::DecodedOnionErrorPacket { failuremsg: vec![ 0x10, 0x7, // UPDATE|7 - 0x0, 0x0 // 0-len channel update + 0x0, 0x0, // 0-len channel update ], pad: vec![0; 255 - 4 /* 4-byte error message */], hmac: [0; 32], @@ -688,13 +1427,19 @@ fn test_onion_failure() { hmac.input(&decoded_err_packet.encode()[32..]); decoded_err_packet.hmac = Hmac::from_engine(hmac).to_byte_array(); msg.reason = onion_utils::encrypt_failure_packet( - &onion_keys[1].shared_secret.as_ref(), &decoded_err_packet.encode()[..]) - }, || nodes[2].node.fail_htlc_backwards(&payment_hash), true, Some(0x1000|7), + &onion_keys[1].shared_secret.as_ref(), + &decoded_err_packet.encode()[..], + ) + }, + || nodes[2].node.fail_htlc_backwards(&payment_hash), + true, + Some(0x1000 | 7), Some(NetworkUpdate::ChannelFailure { short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: false, }), - Some(channels[1].0.contents.short_channel_id)); + Some(channels[1].0.contents.short_channel_id), + ); } #[test] @@ -705,10 +1450,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()); @@ -720,8 +1474,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, _ => {}, } } @@ -746,7 +1501,8 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: bool) { config.channel_handshake_config.announced_channel = announced_channel; config.channel_handshake_limits.force_announced_channel_preference = false; config.accept_forwards_to_priv_channels = !announced_channel; - 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; @@ -755,18 +1511,12 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: 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 announced_channel { - 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(); @@ -789,13 +1539,22 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: 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. @@ -806,11 +1565,15 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: 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 { @@ -840,12 +1603,24 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: bool) { // We'll be attempting to route payments using the default ChannelUpdate for channels. This will // lead to onion failures at the first hop once we update the ChannelConfig for the // second hop. - let expect_onion_failure = |name: &str, error_code: u16, channel_update: &msgs::ChannelUpdate| { + let expect_onion_failure = |name: &str, + error_code: u16, + channel_update: &msgs::ChannelUpdate| { let short_channel_id = channel_to_update.1; let network_update = NetworkUpdate::ChannelUpdateMessage { msg: channel_update.clone() }; run_onion_failure_test( - name, 0, &nodes, &route, &payment_hash, &payment_secret, |_| {}, || {}, true, - Some(error_code), Some(network_update), Some(short_channel_id), + name, + 0, + &nodes, + &route, + &payment_hash, + &payment_secret, + |_| {}, + || {}, + true, + Some(error_code), + Some(network_update), + Some(short_channel_id), ); }; @@ -853,28 +1628,41 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: 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, 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 // forwarding the HTLC. expire_prev_config(); - expect_onion_failure("fee_insufficient", UPDATE|12, &msg); + expect_onion_failure("fee_insufficient", UPDATE | 12, &msg); // Redundant updates should not trigger a new ChannelUpdate. assert!(update_and_get_channel_update(&config, false, None, false).is_none()); @@ -888,24 +1676,36 @@ fn do_test_onion_failure_stale_channel_update(announced_channel: bool) { config.forwarding_fee_base_msat = default_config.forwarding_fee_base_msat; config.cltv_expiry_delta = u16::max_value(); let msg = update_and_get_channel_update(&config, true, Some(&msg), true).unwrap(); - expect_onion_failure("incorrect_cltv_expiry", UPDATE|13, &msg); + expect_onion_failure("incorrect_cltv_expiry", UPDATE | 13, &msg); // Reset the proportional fee and increase the CLTV expiry delta which should trigger a new // ChannelUpdate. config.cltv_expiry_delta = default_config.cltv_expiry_delta; config.forwarding_fee_proportional_millionths = u32::max_value(); let msg = update_and_get_channel_update(&config, true, Some(&msg), true).unwrap(); - expect_onion_failure("fee_insufficient", UPDATE|12, &msg); + expect_onion_failure("fee_insufficient", UPDATE | 12, &msg); // To test persistence of the updated config, we'll re-initialize the ChannelManager. 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(), &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(), + &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); } @@ -936,9 +1736,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. @@ -948,26 +1751,35 @@ fn test_always_create_tlv_format_onion_payloads() { let cur_height = nodes[0].best_block_info().1 + 1; let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], + 40000, + RecipientOnionFields::spontaneous_empty(), + cur_height, + &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" - )} + ) + }, } } 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]); @@ -976,9 +1788,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(); @@ -990,13 +1810,27 @@ 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: _ , 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: _, + 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); @@ -1018,19 +1852,16 @@ 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(); let permanent_flag = 0x4000; let permanent_fail = (failure_code & permanent_flag) != 0; expect_payment_failed!(nodes[0], payment_hash, permanent_fail, failure_code, failure_data); - } #[test] @@ -1047,41 +1878,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() { @@ -1094,12 +1933,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(); @@ -1113,10 +1960,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() @@ -1126,7 +1975,10 @@ fn test_phantom_onion_hmac_failure() { }; 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); @@ -1154,14 +2006,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, 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(); @@ -1174,24 +2034,42 @@ 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).unwrap(); + let mut onion_keys = onion_utils::construct_onion_keys( + &Secp256k1::new(), + &route.paths[0], + &session_priv, + ) + .unwrap(); let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads( - &route.paths[0], msgs::MAX_VALUE_MSAT + 1, - RecipientOnionFields::secret_only(payment_secret), height + 1, &None).unwrap(); + &route.paths[0], + msgs::MAX_VALUE_MSAT + 1, + RecipientOnionFields::secret_only(payment_secret), + height + 1, + &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; }, @@ -1201,7 +2079,10 @@ fn test_phantom_invalid_onion_payload() { } 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); @@ -1230,12 +2111,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(); @@ -1248,7 +2137,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; }, @@ -1258,7 +2148,10 @@ fn test_phantom_final_incorrect_cltv_expiry() { } 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); @@ -1287,15 +2180,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(); @@ -1305,7 +2206,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); @@ -1316,9 +2220,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(0x4000 | 15, &error_data); @@ -1338,12 +2240,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(); @@ -1380,12 +2290,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(); @@ -1419,12 +2337,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(); @@ -1436,7 +2362,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); @@ -1466,9 +2395,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.announced_channel = true; let chanmon_cfgs = create_chanmon_cfgs(2); @@ -1479,12 +2410,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, _) = get_phantom_route!(nodes, max_dust_exposure + 1, 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(); @@ -1508,7 +2447,7 @@ fn do_test_phantom_dust_exposure_failure(multiplier_dust_limit: bool) { .blamed_scid(channel.0.contents.short_channel_id) .blamed_chan_closed(false) .expected_htlc_error_data(0x1000 | 7, &err_data); - expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions); + expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions); } #[test] @@ -1523,12 +2462,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, 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(); @@ -1540,9 +2487,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/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 4b39276c066..8621104911d 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -7,31 +7,31 @@ // You may not use this file except in accordance with one or both of these // licenses. -use crate::ln::{PaymentHash, PaymentPreimage}; +use crate::crypto::chacha20::ChaCha20; +use crate::crypto::streams::ChaChaReader; use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields}; use crate::ln::msgs; use crate::ln::wire::Encode; +use crate::ln::{PaymentHash, PaymentPreimage}; use crate::routing::gossip::NetworkUpdate; use crate::routing::router::{BlindedTail, Path, RouteHop}; use crate::sign::NodeSigner; -use crate::crypto::chacha20::ChaCha20; -use crate::crypto::streams::ChaChaReader; use crate::util::errors::{self, APIError}; -use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, LengthCalculatingWriter}; use crate::util::logger::Logger; +use crate::util::ser::{LengthCalculatingWriter, Readable, ReadableArgs, Writeable, Writer}; -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 bitcoin::secp256k1::{SecretKey, PublicKey, Scalar}; -use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1; +use bitcoin::secp256k1::ecdh::SharedSecret; +use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::{PublicKey, Scalar, SecretKey}; -use crate::prelude::*; use crate::io::{Cursor, Read}; +use crate::prelude::*; use core::convert::{AsMut, TryInto}; use core::ops::Deref; @@ -56,16 +56,18 @@ pub(crate) fn gen_rho_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] { #[inline] pub(crate) fn gen_rho_mu_from_shared_secret(shared_secret: &[u8]) -> ([u8; 32], [u8; 32]) { assert_eq!(shared_secret.len(), 32); - ({ - let mut hmac = HmacEngine::::new(&[0x72, 0x68, 0x6f]); // rho - hmac.input(&shared_secret); - Hmac::from_engine(hmac).to_byte_array() - }, - { - let mut hmac = HmacEngine::::new(&[0x6d, 0x75]); // mu - hmac.input(&shared_secret); - Hmac::from_engine(hmac).to_byte_array() - }) + ( + { + let mut hmac = HmacEngine::::new(&[0x72, 0x68, 0x6f]); // rho + hmac.input(&shared_secret); + Hmac::from_engine(hmac).to_byte_array() + }, + { + let mut hmac = HmacEngine::::new(&[0x6d, 0x75]); // mu + hmac.input(&shared_secret); + Hmac::from_engine(hmac).to_byte_array() + }, + ) } #[inline] @@ -95,7 +97,7 @@ pub(super) fn gen_pad_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] { /// Calculates a pubkey for the next hop, such as the next hop's packet pubkey or blinding point. pub(crate) fn next_hop_pubkey( - secp_ctx: &Secp256k1, curr_pubkey: PublicKey, shared_secret: &[u8] + secp_ctx: &Secp256k1, curr_pubkey: PublicKey, shared_secret: &[u8], ) -> Result { let blinding_factor = { let mut sha = Sha256::engine(); @@ -110,18 +112,21 @@ pub(crate) fn next_hop_pubkey( // can only fail if an intermediary hop has an invalid public key or session_priv is invalid #[inline] pub(super) fn construct_onion_keys_callback( - secp_ctx: &Secp256k1, path: &Path, session_priv: &SecretKey, mut callback: FType + secp_ctx: &Secp256k1, path: &Path, session_priv: &SecretKey, mut callback: FType, ) -> Result<(), secp256k1::Error> where T: secp256k1::Signing, - FType: FnMut(SharedSecret, [u8; 32], PublicKey, Option<&RouteHop>, usize) + FType: FnMut(SharedSecret, [u8; 32], PublicKey, Option<&RouteHop>, usize), { let mut blinded_priv = session_priv.clone(); let mut blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv); let unblinded_hops_iter = path.hops.iter().map(|h| (&h.pubkey, Some(h))); - let blinded_pks_iter = path.blinded_tail.as_ref() - .map(|t| t.hops.iter()).unwrap_or([].iter()) + let blinded_pks_iter = path + .blinded_tail + .as_ref() + .map(|t| t.hops.iter()) + .unwrap_or([].iter()) .skip(1) // Skip the intro node because it's included in the unblinded hops .map(|h| (&h.blinded_node_id, None)); for (idx, (pubkey, route_hop_opt)) in unblinded_hops_iter.chain(blinded_pks_iter).enumerate() { @@ -144,35 +149,43 @@ where } // can only fail if an intermediary hop has an invalid public key or session_priv is invalid -pub(super) fn construct_onion_keys(secp_ctx: &Secp256k1, path: &Path, session_priv: &SecretKey) -> Result, secp256k1::Error> { +pub(super) fn construct_onion_keys( + secp_ctx: &Secp256k1, path: &Path, session_priv: &SecretKey, +) -> Result, secp256k1::Error> { let mut res = Vec::with_capacity(path.hops.len()); - construct_onion_keys_callback(secp_ctx, &path, session_priv, - |shared_secret, _blinding_factor, ephemeral_pubkey, _, _| - { - let (rho, mu) = gen_rho_mu_from_shared_secret(shared_secret.as_ref()); + construct_onion_keys_callback( + secp_ctx, + &path, + session_priv, + |shared_secret, _blinding_factor, ephemeral_pubkey, _, _| { + let (rho, mu) = gen_rho_mu_from_shared_secret(shared_secret.as_ref()); - res.push(OnionKeys { - #[cfg(test)] - shared_secret, - #[cfg(test)] - blinding_factor: _blinding_factor, - ephemeral_pubkey, - rho, - mu, - }); - })?; + res.push(OnionKeys { + #[cfg(test)] + shared_secret, + #[cfg(test)] + blinding_factor: _blinding_factor, + ephemeral_pubkey, + rho, + mu, + }); + }, + )?; Ok(res) } /// returns the hop data, as well as the first-hop value_msat and CLTV value we should send. -pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields, starting_htlc_offset: u32, keysend_preimage: &Option) -> Result<(Vec, u64, u32), APIError> { +pub(super) fn build_onion_payloads( + path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields, + starting_htlc_offset: u32, keysend_preimage: &Option, +) -> Result<(Vec, u64, u32), APIError> { let mut cur_value_msat = 0u64; let mut cur_cltv = starting_htlc_offset; let mut last_short_channel_id = 0; let mut res: Vec = Vec::with_capacity( - path.hops.len() + path.blinded_tail.as_ref().map_or(0, |t| t.hops.len()) + path.hops.len() + path.blinded_tail.as_ref().map_or(0, |t| t.hops.len()), ); for (idx, hop) in path.hops.iter().rev().enumerate() { @@ -180,11 +193,20 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o // exactly as it should be (and the next hop isn't trying to probe to find out if we're // the intended recipient). let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat }; - let cltv = if cur_cltv == starting_htlc_offset { hop.cltv_expiry_delta + starting_htlc_offset } else { cur_cltv }; + let cltv = if cur_cltv == starting_htlc_offset { + hop.cltv_expiry_delta + starting_htlc_offset + } else { + cur_cltv + }; if idx == 0 { if let Some(BlindedTail { - blinding_point, hops, final_value_msat, excess_final_cltv_expiry_delta, .. - }) = &path.blinded_tail { + blinding_point, + hops, + final_value_msat, + excess_final_cltv_expiry_delta, + .. + }) = &path.blinded_tail + { let mut blinding_point = Some(*blinding_point); for (i, blinded_hop) in hops.iter().enumerate() { if i == hops.len() - 1 { @@ -206,11 +228,10 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o } else { res.push(msgs::OutboundOnionPayload::Receive { payment_data: if let Some(secret) = recipient_onion.payment_secret.take() { - Some(msgs::FinalOnionHopData { - payment_secret: secret, - total_msat, - }) - } else { None }, + Some(msgs::FinalOnionHopData { payment_secret: secret, total_msat }) + } else { + None + }, payment_metadata: recipient_onion.payment_metadata.take(), keysend_preimage: *keysend_preimage, custom_tlvs: recipient_onion.custom_tlvs.clone(), @@ -219,19 +240,22 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o }); } } else { - res.insert(0, msgs::OutboundOnionPayload::Forward { - short_channel_id: last_short_channel_id, - amt_to_forward: value_msat, - outgoing_cltv_value: cltv, - }); + res.insert( + 0, + msgs::OutboundOnionPayload::Forward { + short_channel_id: last_short_channel_id, + amt_to_forward: value_msat, + outgoing_cltv_value: cltv, + }, + ); } cur_value_msat += hop.fee_msat; if cur_value_msat >= 21000000 * 100000000 * 1000 { - return Err(APIError::InvalidRoute{err: "Channel fees overflowed?".to_owned()}); + return Err(APIError::InvalidRoute { err: "Channel fees overflowed?".to_owned() }); } cur_cltv += hop.cltv_expiry_delta as u32; if cur_cltv >= 500000000 { - return Err(APIError::InvalidRoute{err: "Channel CLTV overflowed?".to_owned()}); + return Err(APIError::InvalidRoute { err: "Channel CLTV overflowed?".to_owned() }); } last_short_channel_id = hop.short_channel_id; } @@ -240,14 +264,14 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o /// Length of the onion data packet. Before TLV-based onions this was 20 65-byte hops, though now /// the hops can be of variable length. -pub(crate) const ONION_DATA_LEN: usize = 20*65; +pub(crate) const ONION_DATA_LEN: usize = 20 * 65; pub(super) const INVALID_ONION_BLINDING: u16 = 0x8000 | 0x4000 | 24; #[inline] fn shift_slice_right(arr: &mut [u8], amt: usize) { for i in (amt..arr.len()).rev() { - arr[i] = arr[i-amt]; + arr[i] = arr[i - amt]; } for i in 0..amt { arr[i] = 0; @@ -256,7 +280,7 @@ fn shift_slice_right(arr: &mut [u8], amt: usize) { pub(super) fn construct_onion_packet( payloads: Vec, onion_keys: Vec, prng_seed: [u8; 32], - associated_data: &PaymentHash + associated_data: &PaymentHash, ) -> Result { let mut packet_data = [0; ONION_DATA_LEN]; @@ -264,20 +288,31 @@ pub(super) fn construct_onion_packet( chacha.process(&[0; ONION_DATA_LEN], &mut packet_data); construct_onion_packet_with_init_noise::<_, _>( - payloads, onion_keys, FixedSizeOnionPacket(packet_data), Some(associated_data)) + payloads, + onion_keys, + FixedSizeOnionPacket(packet_data), + Some(associated_data), + ) } #[cfg(test)] /// Used in testing to write bogus `BogusOnionHopData` as well as `RawOnionHopData`, which is /// otherwise not representable in `msgs::OnionHopData`. -pub(super) fn construct_onion_packet_with_writable_hopdata(payloads: Vec, onion_keys: Vec, prng_seed: [u8; 32], associated_data: &PaymentHash) -> Result { +pub(super) fn construct_onion_packet_with_writable_hopdata( + payloads: Vec, onion_keys: Vec, prng_seed: [u8; 32], + associated_data: &PaymentHash, +) -> Result { let mut packet_data = [0; ONION_DATA_LEN]; let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]); chacha.process(&[0; ONION_DATA_LEN], &mut packet_data); construct_onion_packet_with_init_noise::<_, _>( - payloads, onion_keys, FixedSizeOnionPacket(packet_data), Some(associated_data)) + payloads, + onion_keys, + FixedSizeOnionPacket(packet_data), + Some(associated_data), + ) } /// Since onion message packets and onion payment packets have different lengths but are otherwise @@ -303,8 +338,8 @@ pub(crate) fn payloads_serialized_length(payloads: &Vec) -> u } pub(crate) fn construct_onion_message_packet>>( - payloads: Vec, onion_keys: Vec, prng_seed: [u8; 32], packet_data_len: usize) -> Result -{ + payloads: Vec, onion_keys: Vec, prng_seed: [u8; 32], packet_data_len: usize, +) -> Result { let mut packet_data = vec![0; packet_data_len]; let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]); @@ -314,8 +349,9 @@ pub(crate) fn construct_onion_message_packet( - mut payloads: Vec, onion_keys: Vec, mut packet_data: P::Data, associated_data: Option<&PaymentHash>) -> Result -{ + mut payloads: Vec, onion_keys: Vec, mut packet_data: P::Data, + associated_data: Option<&PaymentHash>, +) -> Result { let filler = { let packet_data = packet_data.as_mut(); const ONION_HOP_DATA_LEN: usize = 65; // We may decrease this eventually after TLV is common @@ -324,7 +360,8 @@ fn construct_onion_packet_with_init_noise( let mut pos = 0; for (i, (payload, keys)) in payloads.iter().zip(onion_keys.iter()).enumerate() { let mut chacha = ChaCha20::new(&keys.rho, &[0u8; 8]); - for _ in 0..(packet_data.len() - pos) { // TODO: Batch this. + for _ in 0..(packet_data.len() - pos) { + // TODO: Batch this. let mut dummy = [0; 1]; chacha.process_in_place(&mut dummy); // We don't have a seek function :( } @@ -336,7 +373,9 @@ fn construct_onion_packet_with_init_noise( return Err(()); } - if i == payloads.len() - 1 { break; } + if i == payloads.len() - 1 { + break; + } res.resize(pos, 0u8); chacha.process_in_place(&mut res); @@ -376,19 +415,21 @@ fn construct_onion_packet_with_init_noise( /// Encrypts a failure packet. raw_packet can either be a /// msgs::DecodedOnionErrorPacket.encode() result or a msgs::OnionErrorPacket.data element. -pub(super) fn encrypt_failure_packet(shared_secret: &[u8], raw_packet: &[u8]) -> msgs::OnionErrorPacket { +pub(super) fn encrypt_failure_packet( + shared_secret: &[u8], raw_packet: &[u8], +) -> msgs::OnionErrorPacket { let ammag = gen_ammag_from_shared_secret(&shared_secret); let mut packet_crypted = Vec::with_capacity(raw_packet.len()); packet_crypted.resize(raw_packet.len(), 0); let mut chacha = ChaCha20::new(&ammag, &[0u8; 8]); chacha.process(&raw_packet, &mut packet_crypted[..]); - msgs::OnionErrorPacket { - data: packet_crypted, - } + msgs::OnionErrorPacket { data: packet_crypted } } -pub(super) fn build_failure_packet(shared_secret: &[u8], failure_type: u16, failure_data: &[u8]) -> msgs::DecodedOnionErrorPacket { +pub(super) fn build_failure_packet( + shared_secret: &[u8], failure_type: u16, failure_data: &[u8], +) -> msgs::DecodedOnionErrorPacket { assert_eq!(shared_secret.len(), 32); assert!(failure_data.len() <= 256 - 2); @@ -406,11 +447,7 @@ pub(super) fn build_failure_packet(shared_secret: &[u8], failure_type: u16, fail res.resize(256 - 2 - failure_data.len(), 0); res }; - let mut packet = msgs::DecodedOnionErrorPacket { - hmac: [0; 32], - failuremsg, - pad, - }; + let mut packet = msgs::DecodedOnionErrorPacket { hmac: [0; 32], failuremsg, pad }; let mut hmac = HmacEngine::::new(&um); hmac.input(&packet.encode()[32..]); @@ -420,7 +457,9 @@ pub(super) fn build_failure_packet(shared_secret: &[u8], failure_type: u16, fail } #[cfg(test)] -pub(super) fn build_first_hop_failure_packet(shared_secret: &[u8], failure_type: u16, failure_data: &[u8]) -> msgs::OnionErrorPacket { +pub(super) fn build_first_hop_failure_packet( + shared_secret: &[u8], failure_type: u16, failure_data: &[u8], +) -> msgs::OnionErrorPacket { let failure_packet = build_failure_packet(shared_secret, failure_type, failure_data); encrypt_failure_packet(shared_secret, &failure_packet.encode()[..]) } @@ -439,7 +478,7 @@ pub(crate) struct DecodedOnionFailure { /// Note that we always decrypt `packet` in-place here even if the deserialization into /// [`msgs::DecodedOnionErrorPacket`] ultimately fails. fn decrypt_onion_error_packet( - packet: &mut Vec, shared_secret: SharedSecret + packet: &mut Vec, shared_secret: SharedSecret, ) -> Result { let ammag = gen_ammag_from_shared_secret(shared_secret.as_ref()); let mut chacha = ChaCha20::new(&ammag, &[0u8; 8]); @@ -451,13 +490,22 @@ fn decrypt_onion_error_packet( /// OutboundRoute). #[inline] pub(super) fn process_onion_failure( - secp_ctx: &Secp256k1, logger: &L, htlc_source: &HTLCSource, mut encrypted_packet: Vec -) -> DecodedOnionFailure where L::Target: Logger { + secp_ctx: &Secp256k1, logger: &L, htlc_source: &HTLCSource, mut encrypted_packet: Vec, +) -> DecodedOnionFailure +where + L::Target: Logger, +{ let (path, session_priv, first_hop_htlc_msat) = if let &HTLCSource::OutboundRoute { - ref path, ref session_priv, ref first_hop_htlc_msat, .. - } = htlc_source { + ref path, + ref session_priv, + ref first_hop_htlc_msat, + .. + } = htlc_source + { (path, session_priv, first_hop_htlc_msat) - } else { unreachable!() }; + } else { + unreachable!() + }; // Learnings from the HTLC failure to inform future payment retries and scoring. struct FailureLearnings { @@ -723,25 +771,34 @@ pub(super) fn process_onion_failure( } }).expect("Route that we sent via spontaneously grew invalid keys in the middle of it?"); if let Some(FailureLearnings { - network_update, short_channel_id, payment_failed_permanently, failed_within_blinded_path - }) = res { + network_update, + short_channel_id, + payment_failed_permanently, + failed_within_blinded_path, + }) = res + { 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, #[cfg(test)] onion_error_code: error_code_ret, #[cfg(test)] - onion_error_data: error_packet_ret + onion_error_data: error_packet_ret, } } else { // only not set either packet unparseable or hmac does not match with any // payment not retryable only when garbage is from the final node DecodedOnionFailure { - network_update: None, short_channel_id: None, payment_failed_permanently: is_from_final_node, + network_update: None, + short_channel_id: None, + payment_failed_permanently: is_from_final_node, failed_within_blinded_path: false, #[cfg(test)] onion_error_code: None, #[cfg(test)] - onion_error_data: None + onion_error_data: None, } } } @@ -753,13 +810,8 @@ pub(super) struct HTLCFailReason(HTLCFailReasonRepr); #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug #[cfg_attr(test, derive(PartialEq))] enum HTLCFailReasonRepr { - LightningError { - err: msgs::OnionErrorPacket, - }, - Reason { - failure_code: u16, - data: Vec, - } + LightningError { err: msgs::OnionErrorPacket }, + Reason { failure_code: u16, data: Vec }, } impl core::fmt::Debug for HTLCFailReason { @@ -770,7 +822,7 @@ impl core::fmt::Debug for HTLCFailReason { }, HTLCFailReasonRepr::LightningError { .. } => { write!(f, "pre-built LightningError") - } + }, } } } @@ -803,38 +855,73 @@ impl HTLCFailReason { const NODE: u16 = 0x2000; const UPDATE: u16 = 0x1000; - if failure_code == 1 | PERM { debug_assert!(data.is_empty()) } - else if failure_code == 2 | NODE { debug_assert!(data.is_empty()) } - else if failure_code == 2 | PERM | NODE { debug_assert!(data.is_empty()) } - else if failure_code == 3 | PERM | NODE { debug_assert!(data.is_empty()) } - else if failure_code == 4 | BADONION | PERM { debug_assert_eq!(data.len(), 32) } - else if failure_code == 5 | BADONION | PERM { debug_assert_eq!(data.len(), 32) } - else if failure_code == 6 | BADONION | PERM { debug_assert_eq!(data.len(), 32) } - else if failure_code == 7 | UPDATE { - debug_assert_eq!(data.len() - 2, u16::from_be_bytes(data[0..2].try_into().unwrap()) as usize) } - else if failure_code == 8 | PERM { debug_assert!(data.is_empty()) } - else if failure_code == 9 | PERM { debug_assert!(data.is_empty()) } - else if failure_code == 10 | PERM { debug_assert!(data.is_empty()) } - else if failure_code == 11 | UPDATE { - debug_assert_eq!(data.len() - 2 - 8, u16::from_be_bytes(data[8..10].try_into().unwrap()) as usize) } - else if failure_code == 12 | UPDATE { - debug_assert_eq!(data.len() - 2 - 8, u16::from_be_bytes(data[8..10].try_into().unwrap()) as usize) } - else if failure_code == 13 | UPDATE { - debug_assert_eq!(data.len() - 2 - 4, u16::from_be_bytes(data[4..6].try_into().unwrap()) as usize) } - else if failure_code == 14 | UPDATE { - debug_assert_eq!(data.len() - 2, u16::from_be_bytes(data[0..2].try_into().unwrap()) as usize) } - else if failure_code == 15 | PERM { debug_assert_eq!(data.len(), 12) } - else if failure_code == 18 { debug_assert_eq!(data.len(), 4) } - else if failure_code == 19 { debug_assert_eq!(data.len(), 8) } - else if failure_code == 20 | UPDATE { - debug_assert_eq!(data.len() - 2 - 2, u16::from_be_bytes(data[2..4].try_into().unwrap()) as usize) } - else if failure_code == 21 { debug_assert!(data.is_empty()) } - else if failure_code == 22 | PERM { debug_assert!(data.len() <= 11) } - else if failure_code == 23 { debug_assert!(data.is_empty()) } - else if failure_code & BADONION != 0 { + if failure_code == 1 | PERM { + debug_assert!(data.is_empty()) + } else if failure_code == 2 | NODE { + debug_assert!(data.is_empty()) + } else if failure_code == 2 | PERM | NODE { + debug_assert!(data.is_empty()) + } else if failure_code == 3 | PERM | NODE { + debug_assert!(data.is_empty()) + } else if failure_code == 4 | BADONION | PERM { + debug_assert_eq!(data.len(), 32) + } else if failure_code == 5 | BADONION | PERM { + debug_assert_eq!(data.len(), 32) + } else if failure_code == 6 | BADONION | PERM { + debug_assert_eq!(data.len(), 32) + } else if failure_code == 7 | UPDATE { + debug_assert_eq!( + data.len() - 2, + u16::from_be_bytes(data[0..2].try_into().unwrap()) as usize + ) + } else if failure_code == 8 | PERM { + debug_assert!(data.is_empty()) + } else if failure_code == 9 | PERM { + debug_assert!(data.is_empty()) + } else if failure_code == 10 | PERM { + debug_assert!(data.is_empty()) + } else if failure_code == 11 | UPDATE { + debug_assert_eq!( + data.len() - 2 - 8, + u16::from_be_bytes(data[8..10].try_into().unwrap()) as usize + ) + } else if failure_code == 12 | UPDATE { + debug_assert_eq!( + data.len() - 2 - 8, + u16::from_be_bytes(data[8..10].try_into().unwrap()) as usize + ) + } else if failure_code == 13 | UPDATE { + debug_assert_eq!( + data.len() - 2 - 4, + u16::from_be_bytes(data[4..6].try_into().unwrap()) as usize + ) + } else if failure_code == 14 | UPDATE { + debug_assert_eq!( + data.len() - 2, + u16::from_be_bytes(data[0..2].try_into().unwrap()) as usize + ) + } else if failure_code == 15 | PERM { + debug_assert_eq!(data.len(), 12) + } else if failure_code == 18 { + debug_assert_eq!(data.len(), 4) + } else if failure_code == 19 { + debug_assert_eq!(data.len(), 8) + } else if failure_code == 20 | UPDATE { + debug_assert_eq!( + data.len() - 2 - 2, + u16::from_be_bytes(data[2..4].try_into().unwrap()) as usize + ) + } else if failure_code == 21 { + debug_assert!(data.is_empty()) + } else if failure_code == 22 | PERM { + debug_assert!(data.len() <= 11) + } else if failure_code == 23 { + debug_assert!(data.is_empty()) + } else if failure_code & BADONION != 0 { // We set some bogus BADONION failure codes in test, so ignore unknown ones. + } else { + debug_assert!(false, "Unknown failure code: {}", failure_code) } - else { debug_assert!(false, "Unknown failure code: {}", failure_code) } Self(HTLCFailReasonRepr::Reason { failure_code, data }) } @@ -847,28 +934,42 @@ impl HTLCFailReason { Self(HTLCFailReasonRepr::LightningError { err: msg.reason.clone() }) } - pub(super) fn get_encrypted_failure_packet(&self, incoming_packet_shared_secret: &[u8; 32], phantom_shared_secret: &Option<[u8; 32]>) - -> msgs::OnionErrorPacket { + pub(super) fn get_encrypted_failure_packet( + &self, incoming_packet_shared_secret: &[u8; 32], phantom_shared_secret: &Option<[u8; 32]>, + ) -> msgs::OnionErrorPacket { match self.0 { HTLCFailReasonRepr::Reason { ref failure_code, ref data } => { if let Some(phantom_ss) = phantom_shared_secret { - let phantom_packet = build_failure_packet(phantom_ss, *failure_code, &data[..]).encode(); - let encrypted_phantom_packet = encrypt_failure_packet(phantom_ss, &phantom_packet); - encrypt_failure_packet(incoming_packet_shared_secret, &encrypted_phantom_packet.data[..]) + let phantom_packet = + build_failure_packet(phantom_ss, *failure_code, &data[..]).encode(); + let encrypted_phantom_packet = + encrypt_failure_packet(phantom_ss, &phantom_packet); + encrypt_failure_packet( + incoming_packet_shared_secret, + &encrypted_phantom_packet.data[..], + ) } else { - let packet = build_failure_packet(incoming_packet_shared_secret, *failure_code, &data[..]).encode(); + let packet = build_failure_packet( + incoming_packet_shared_secret, + *failure_code, + &data[..], + ) + .encode(); encrypt_failure_packet(incoming_packet_shared_secret, &packet) } }, HTLCFailReasonRepr::LightningError { ref err } => { encrypt_failure_packet(incoming_packet_shared_secret, &err.data) - } + }, } } pub(super) fn decode_onion_failure( - &self, secp_ctx: &Secp256k1, logger: &L, htlc_source: &HTLCSource - ) -> DecodedOnionFailure where L::Target: Logger { + &self, secp_ctx: &Secp256k1, logger: &L, htlc_source: &HTLCSource, + ) -> DecodedOnionFailure + where + L::Target: Logger, + { match self.0 { HTLCFailReasonRepr::LightningError { ref err } => { process_onion_failure(secp_ctx, logger, &htlc_source, err.data.clone()) @@ -891,8 +992,10 @@ impl HTLCFailReason { #[cfg(test)] onion_error_data: Some(data.clone()), } - } else { unreachable!(); } - } + } else { + unreachable!(); + } + }, } } } @@ -904,7 +1007,7 @@ pub(crate) trait NextPacketBytes: AsMut<[u8]> { } impl NextPacketBytes for FixedSizeOnionPacket { - fn new(_len: usize) -> Self { + fn new(_len: usize) -> Self { Self([0 as u8; ONION_DATA_LEN]) } } @@ -935,31 +1038,28 @@ pub(crate) enum Hop { #[derive(Debug)] pub(crate) enum OnionDecodeErr { /// The HMAC of the onion packet did not match the hop data. - Malformed { - err_msg: &'static str, - err_code: u16, - }, + Malformed { err_msg: &'static str, err_code: u16 }, /// We failed to decode the onion payload. - Relay { - err_msg: &'static str, - err_code: u16, - }, + Relay { err_msg: &'static str, err_code: u16 }, } pub(crate) fn decode_next_payment_hop( shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: PaymentHash, blinding_point: Option, node_signer: &NS, -) -> Result where NS::Target: NodeSigner { +) -> Result +where + NS::Target: NodeSigner, +{ match decode_next_hop( - shared_secret, hop_data, hmac_bytes, Some(payment_hash), (blinding_point, node_signer) + shared_secret, + hop_data, + hmac_bytes, + Some(payment_hash), + (blinding_point, node_signer), ) { Ok((next_hop_data, None)) => Ok(Hop::Receive(next_hop_data)), Ok((next_hop_data, Some((next_hop_hmac, FixedSizeOnionPacket(new_packet_bytes))))) => { - Ok(Hop::Forward { - next_hop_data, - next_hop_hmac, - new_packet_bytes - }) + Ok(Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes }) }, Err(e) => Err(e), } @@ -970,27 +1070,35 @@ pub(crate) fn decode_next_payment_hop( pub fn create_payment_onion( secp_ctx: &Secp256k1, path: &Path, session_priv: &SecretKey, total_msat: u64, recipient_onion: RecipientOnionFields, cur_block_height: u32, payment_hash: &PaymentHash, - keysend_preimage: &Option, prng_seed: [u8; 32] + keysend_preimage: &Option, prng_seed: [u8; 32], ) -> Result<(msgs::OnionPacket, u64, u32), APIError> { - let onion_keys = construct_onion_keys(&secp_ctx, &path, &session_priv) - .map_err(|_| APIError::InvalidRoute{ - err: "Pubkey along hop was maliciously selected".to_owned() - })?; + let onion_keys = construct_onion_keys(&secp_ctx, &path, &session_priv).map_err(|_| { + APIError::InvalidRoute { err: "Pubkey along hop was maliciously selected".to_owned() } + })?; let (onion_payloads, htlc_msat, htlc_cltv) = build_onion_payloads( - &path, total_msat, recipient_onion, cur_block_height, keysend_preimage + &path, + total_msat, + recipient_onion, + cur_block_height, + keysend_preimage, )?; let onion_packet = construct_onion_packet(onion_payloads, onion_keys, prng_seed, payment_hash) - .map_err(|_| APIError::InvalidRoute{ - err: "Route size too large considering onion data".to_owned() + .map_err(|_| APIError::InvalidRoute { + err: "Route size too large considering onion data".to_owned(), })?; Ok((onion_packet, htlc_msat, htlc_cltv)) } -pub(crate) fn decode_next_untagged_hop, N: NextPacketBytes>(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], read_args: T) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> { +pub(crate) fn decode_next_untagged_hop, N: NextPacketBytes>( + shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], read_args: T, +) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> { decode_next_hop(shared_secret, hop_data, hmac_bytes, None, read_args) } -fn decode_next_hop, N: NextPacketBytes>(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: Option, read_args: T) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> { +fn decode_next_hop, N: NextPacketBytes>( + shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], + payment_hash: Option, read_args: T, +) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> { let (rho, mu) = gen_rho_mu_from_shared_secret(&shared_secret); let mut hmac = HmacEngine::::new(&mu); hmac.input(hop_data); @@ -1010,10 +1118,10 @@ fn decode_next_hop, N: NextPacketBytes>(shared_secret: [u8 Err(err) => { let error_code = match err { msgs::DecodeError::UnknownVersion => 0x4000 | 1, // unknown realm byte - msgs::DecodeError::UnknownRequiredFeature| - msgs::DecodeError::InvalidValue| - msgs::DecodeError::ShortRead => 0x4000 | 22, // invalid_onion_payload - _ => 0x2000 | 2, // Should never happen + msgs::DecodeError::UnknownRequiredFeature + | msgs::DecodeError::InvalidValue + | msgs::DecodeError::ShortRead => 0x4000 | 22, // invalid_onion_payload + _ => 0x2000 | 2, // Should never happen }; return Err(OnionDecodeErr::Relay { err_msg: "Unable to decode our hop data", @@ -1063,7 +1171,7 @@ fn decode_next_hop, N: NextPacketBytes>(shared_secret: [u8 // Once we've emptied the set of bytes our peer gave us, encrypt 0 bytes until we // fill the onion hop data we'll forward to our next-hop peer. chacha_stream.chacha.process_in_place(&mut new_packet_bytes.as_mut()[read_pos..]); - return Ok((msg, Some((hmac, new_packet_bytes)))) // This packet needs forwarding + return Ok((msg, Some((hmac, new_packet_bytes)))); // This packet needs forwarding } }, } @@ -1072,21 +1180,27 @@ fn decode_next_hop, N: NextPacketBytes>(shared_secret: [u8 #[cfg(test)] mod tests { use crate::io; - use crate::prelude::*; - use crate::ln::PaymentHash; use crate::ln::features::{ChannelFeatures, NodeFeatures}; - use crate::routing::router::{Path, Route, RouteHop}; use crate::ln::msgs; - use crate::util::ser::{Writeable, Writer, VecWriter}; + use crate::ln::PaymentHash; + use crate::prelude::*; + use crate::routing::router::{Path, Route, RouteHop}; + use crate::util::ser::{VecWriter, Writeable, Writer}; use bitcoin::hashes::hex::FromHex; use bitcoin::secp256k1::Secp256k1; - use bitcoin::secp256k1::{PublicKey,SecretKey}; + use bitcoin::secp256k1::{PublicKey, SecretKey}; use super::OnionKeys; fn get_test_session_key() -> SecretKey { - SecretKey::from_slice(&>::from_hex("4141414141414141414141414141414141414141414141414141414141414141").unwrap()[..]).unwrap() + SecretKey::from_slice( + &>::from_hex( + "4141414141414141414141414141414141414141414141414141414141414141", + ) + .unwrap()[..], + ) + .unwrap() } fn build_test_onion_keys() -> Vec { @@ -1124,7 +1238,9 @@ mod tests { route_params: None, }; - let onion_keys = super::construct_onion_keys(&secp_ctx, &route.paths[0], &get_test_session_key()).unwrap(); + let onion_keys = + super::construct_onion_keys(&secp_ctx, &route.paths[0], &get_test_session_key()) + .unwrap(); assert_eq!(onion_keys.len(), route.paths[0].hops.len()); onion_keys } @@ -1135,35 +1251,145 @@ mod tests { // Test generation of ephemeral keys and secrets. These values used to be part of the BOLT4 // test vectors, but have since been removed. We keep them as they provide test coverage. - assert_eq!(onion_keys[0].shared_secret.secret_bytes(), >::from_hex("53eb63ea8a3fec3b3cd433b85cd62a4b145e1dda09391b348c4e1cd36a03ea66").unwrap()[..]); - assert_eq!(onion_keys[0].blinding_factor[..], >::from_hex("2ec2e5da605776054187180343287683aa6a51b4b1c04d6dd49c45d8cffb3c36").unwrap()[..]); - assert_eq!(onion_keys[0].ephemeral_pubkey.serialize()[..], >::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]); - assert_eq!(onion_keys[0].rho, >::from_hex("ce496ec94def95aadd4bec15cdb41a740c9f2b62347c4917325fcc6fb0453986").unwrap()[..]); - assert_eq!(onion_keys[0].mu, >::from_hex("b57061dc6d0a2b9f261ac410c8b26d64ac5506cbba30267a649c28c179400eba").unwrap()[..]); - - assert_eq!(onion_keys[1].shared_secret.secret_bytes(), >::from_hex("a6519e98832a0b179f62123b3567c106db99ee37bef036e783263602f3488fae").unwrap()[..]); - assert_eq!(onion_keys[1].blinding_factor[..], >::from_hex("bf66c28bc22e598cfd574a1931a2bafbca09163df2261e6d0056b2610dab938f").unwrap()[..]); - assert_eq!(onion_keys[1].ephemeral_pubkey.serialize()[..], >::from_hex("028f9438bfbf7feac2e108d677e3a82da596be706cc1cf342b75c7b7e22bf4e6e2").unwrap()[..]); - assert_eq!(onion_keys[1].rho, >::from_hex("450ffcabc6449094918ebe13d4f03e433d20a3d28a768203337bc40b6e4b2c59").unwrap()[..]); - assert_eq!(onion_keys[1].mu, >::from_hex("05ed2b4a3fb023c2ff5dd6ed4b9b6ea7383f5cfe9d59c11d121ec2c81ca2eea9").unwrap()[..]); - - assert_eq!(onion_keys[2].shared_secret.secret_bytes(), >::from_hex("3a6b412548762f0dbccce5c7ae7bb8147d1caf9b5471c34120b30bc9c04891cc").unwrap()[..]); - assert_eq!(onion_keys[2].blinding_factor[..], >::from_hex("a1f2dadd184eb1627049673f18c6325814384facdee5bfd935d9cb031a1698a5").unwrap()[..]); - assert_eq!(onion_keys[2].ephemeral_pubkey.serialize()[..], >::from_hex("03bfd8225241ea71cd0843db7709f4c222f62ff2d4516fd38b39914ab6b83e0da0").unwrap()[..]); - assert_eq!(onion_keys[2].rho, >::from_hex("11bf5c4f960239cb37833936aa3d02cea82c0f39fd35f566109c41f9eac8deea").unwrap()[..]); - assert_eq!(onion_keys[2].mu, >::from_hex("caafe2820fa00eb2eeb78695ae452eba38f5a53ed6d53518c5c6edf76f3f5b78").unwrap()[..]); - - assert_eq!(onion_keys[3].shared_secret.secret_bytes(), >::from_hex("21e13c2d7cfe7e18836df50872466117a295783ab8aab0e7ecc8c725503ad02d").unwrap()[..]); - assert_eq!(onion_keys[3].blinding_factor[..], >::from_hex("7cfe0b699f35525029ae0fa437c69d0f20f7ed4e3916133f9cacbb13c82ff262").unwrap()[..]); - assert_eq!(onion_keys[3].ephemeral_pubkey.serialize()[..], >::from_hex("031dde6926381289671300239ea8e57ffaf9bebd05b9a5b95beaf07af05cd43595").unwrap()[..]); - assert_eq!(onion_keys[3].rho, >::from_hex("cbe784ab745c13ff5cffc2fbe3e84424aa0fd669b8ead4ee562901a4a4e89e9e").unwrap()[..]); - assert_eq!(onion_keys[3].mu, >::from_hex("5052aa1b3d9f0655a0932e50d42f0c9ba0705142c25d225515c45f47c0036ee9").unwrap()[..]); - - assert_eq!(onion_keys[4].shared_secret.secret_bytes(), >::from_hex("b5756b9b542727dbafc6765a49488b023a725d631af688fc031217e90770c328").unwrap()[..]); - assert_eq!(onion_keys[4].blinding_factor[..], >::from_hex("c96e00dddaf57e7edcd4fb5954be5b65b09f17cb6d20651b4e90315be5779205").unwrap()[..]); - assert_eq!(onion_keys[4].ephemeral_pubkey.serialize()[..], >::from_hex("03a214ebd875aab6ddfd77f22c5e7311d7f77f17a169e599f157bbcdae8bf071f4").unwrap()[..]); - assert_eq!(onion_keys[4].rho, >::from_hex("034e18b8cc718e8af6339106e706c52d8df89e2b1f7e9142d996acf88df8799b").unwrap()[..]); - assert_eq!(onion_keys[4].mu, >::from_hex("8e45e5c61c2b24cb6382444db6698727afb063adecd72aada233d4bf273d975a").unwrap()[..]); + assert_eq!( + onion_keys[0].shared_secret.secret_bytes(), + >::from_hex("53eb63ea8a3fec3b3cd433b85cd62a4b145e1dda09391b348c4e1cd36a03ea66") + .unwrap()[..] + ); + assert_eq!( + onion_keys[0].blinding_factor[..], + >::from_hex("2ec2e5da605776054187180343287683aa6a51b4b1c04d6dd49c45d8cffb3c36") + .unwrap()[..] + ); + assert_eq!( + onion_keys[0].ephemeral_pubkey.serialize()[..], + >::from_hex( + "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" + ) + .unwrap()[..] + ); + assert_eq!( + onion_keys[0].rho, + >::from_hex("ce496ec94def95aadd4bec15cdb41a740c9f2b62347c4917325fcc6fb0453986") + .unwrap()[..] + ); + assert_eq!( + onion_keys[0].mu, + >::from_hex("b57061dc6d0a2b9f261ac410c8b26d64ac5506cbba30267a649c28c179400eba") + .unwrap()[..] + ); + + assert_eq!( + onion_keys[1].shared_secret.secret_bytes(), + >::from_hex("a6519e98832a0b179f62123b3567c106db99ee37bef036e783263602f3488fae") + .unwrap()[..] + ); + assert_eq!( + onion_keys[1].blinding_factor[..], + >::from_hex("bf66c28bc22e598cfd574a1931a2bafbca09163df2261e6d0056b2610dab938f") + .unwrap()[..] + ); + assert_eq!( + onion_keys[1].ephemeral_pubkey.serialize()[..], + >::from_hex( + "028f9438bfbf7feac2e108d677e3a82da596be706cc1cf342b75c7b7e22bf4e6e2" + ) + .unwrap()[..] + ); + assert_eq!( + onion_keys[1].rho, + >::from_hex("450ffcabc6449094918ebe13d4f03e433d20a3d28a768203337bc40b6e4b2c59") + .unwrap()[..] + ); + assert_eq!( + onion_keys[1].mu, + >::from_hex("05ed2b4a3fb023c2ff5dd6ed4b9b6ea7383f5cfe9d59c11d121ec2c81ca2eea9") + .unwrap()[..] + ); + + assert_eq!( + onion_keys[2].shared_secret.secret_bytes(), + >::from_hex("3a6b412548762f0dbccce5c7ae7bb8147d1caf9b5471c34120b30bc9c04891cc") + .unwrap()[..] + ); + assert_eq!( + onion_keys[2].blinding_factor[..], + >::from_hex("a1f2dadd184eb1627049673f18c6325814384facdee5bfd935d9cb031a1698a5") + .unwrap()[..] + ); + assert_eq!( + onion_keys[2].ephemeral_pubkey.serialize()[..], + >::from_hex( + "03bfd8225241ea71cd0843db7709f4c222f62ff2d4516fd38b39914ab6b83e0da0" + ) + .unwrap()[..] + ); + assert_eq!( + onion_keys[2].rho, + >::from_hex("11bf5c4f960239cb37833936aa3d02cea82c0f39fd35f566109c41f9eac8deea") + .unwrap()[..] + ); + assert_eq!( + onion_keys[2].mu, + >::from_hex("caafe2820fa00eb2eeb78695ae452eba38f5a53ed6d53518c5c6edf76f3f5b78") + .unwrap()[..] + ); + + assert_eq!( + onion_keys[3].shared_secret.secret_bytes(), + >::from_hex("21e13c2d7cfe7e18836df50872466117a295783ab8aab0e7ecc8c725503ad02d") + .unwrap()[..] + ); + assert_eq!( + onion_keys[3].blinding_factor[..], + >::from_hex("7cfe0b699f35525029ae0fa437c69d0f20f7ed4e3916133f9cacbb13c82ff262") + .unwrap()[..] + ); + assert_eq!( + onion_keys[3].ephemeral_pubkey.serialize()[..], + >::from_hex( + "031dde6926381289671300239ea8e57ffaf9bebd05b9a5b95beaf07af05cd43595" + ) + .unwrap()[..] + ); + assert_eq!( + onion_keys[3].rho, + >::from_hex("cbe784ab745c13ff5cffc2fbe3e84424aa0fd669b8ead4ee562901a4a4e89e9e") + .unwrap()[..] + ); + assert_eq!( + onion_keys[3].mu, + >::from_hex("5052aa1b3d9f0655a0932e50d42f0c9ba0705142c25d225515c45f47c0036ee9") + .unwrap()[..] + ); + + assert_eq!( + onion_keys[4].shared_secret.secret_bytes(), + >::from_hex("b5756b9b542727dbafc6765a49488b023a725d631af688fc031217e90770c328") + .unwrap()[..] + ); + assert_eq!( + onion_keys[4].blinding_factor[..], + >::from_hex("c96e00dddaf57e7edcd4fb5954be5b65b09f17cb6d20651b4e90315be5779205") + .unwrap()[..] + ); + assert_eq!( + onion_keys[4].ephemeral_pubkey.serialize()[..], + >::from_hex( + "03a214ebd875aab6ddfd77f22c5e7311d7f77f17a169e599f157bbcdae8bf071f4" + ) + .unwrap()[..] + ); + assert_eq!( + onion_keys[4].rho, + >::from_hex("034e18b8cc718e8af6339106e706c52d8df89e2b1f7e9142d996acf88df8799b") + .unwrap()[..] + ); + assert_eq!( + onion_keys[4].mu, + >::from_hex("8e45e5c61c2b24cb6382444db6698727afb063adecd72aada233d4bf273d975a") + .unwrap()[..] + ); // Packet creation test vectors from BOLT 4 (see // https://github.com/lightning/bolts/blob/16973e2b857e853308cafd59e42fa830d75b1642/bolt04/onion-test.json). @@ -1228,24 +1454,34 @@ mod tests { let mut w = VecWriter(Vec::new()); payloads[0].write(&mut w).unwrap(); let hop_1_serialized_payload = w.0; - let expected_serialized_hop_1_payload = &>::from_hex("1202023a98040205dc06080000000000000001").unwrap()[..]; + let expected_serialized_hop_1_payload = + &>::from_hex("1202023a98040205dc06080000000000000001").unwrap()[..]; assert_eq!(hop_1_serialized_payload, expected_serialized_hop_1_payload); w = VecWriter(Vec::new()); payloads[2].write(&mut w).unwrap(); let hop_3_serialized_payload = w.0; - let expected_serialized_hop_3_payload = &>::from_hex("12020230d4040204e206080000000000000003").unwrap()[..]; + let expected_serialized_hop_3_payload = + &>::from_hex("12020230d4040204e206080000000000000003").unwrap()[..]; assert_eq!(hop_3_serialized_payload, expected_serialized_hop_3_payload); w = VecWriter(Vec::new()); payloads[3].write(&mut w).unwrap(); let hop_4_serialized_payload = w.0; - let expected_serialized_hop_4_payload = &>::from_hex("1202022710040203e806080000000000000004").unwrap()[..]; + let expected_serialized_hop_4_payload = + &>::from_hex("1202022710040203e806080000000000000004").unwrap()[..]; assert_eq!(hop_4_serialized_payload, expected_serialized_hop_4_payload); - let pad_keytype_seed = super::gen_pad_from_shared_secret(&get_test_session_key().secret_bytes()); + let pad_keytype_seed = + super::gen_pad_from_shared_secret(&get_test_session_key().secret_bytes()); - let packet: msgs::OnionPacket = super::construct_onion_packet_with_writable_hopdata::<_>(payloads, onion_keys, pad_keytype_seed, &PaymentHash([0x42; 32])).unwrap(); + let packet: msgs::OnionPacket = super::construct_onion_packet_with_writable_hopdata::<_>( + payloads, + onion_keys, + pad_keytype_seed, + &PaymentHash([0x42; 32]), + ) + .unwrap(); assert_eq!(packet.encode(), >::from_hex("0002EEC7245D6B7D2CCB30380BFBE2A3648CD7A942653F5AA340EDCEA1F283686619F7F3416A5AA36DC7EEB3EC6D421E9615471AB870A33AC07FA5D5A51DF0A8823AABE3FEA3F90D387529D4F72837F9E687230371CCD8D263072206DBED0234F6505E21E282ABD8C0E4F5B9FF8042800BBAB065036EADD0149B37F27DDE664725A49866E052E809D2B0198AB9610FAA656BBF4EC516763A59F8F42C171B179166BA38958D4F51B39B3E98706E2D14A2DAFD6A5DF808093ABFCA5AEAACA16EDED5DB7D21FB0294DD1A163EDF0FB445D5C8D7D688D6DD9C541762BF5A5123BF9939D957FE648416E88F1B0928BFA034982B22548E1A4D922690EECF546275AFB233ACF4323974680779F1A964CFE687456035CC0FBA8A5428430B390F0057B6D1FE9A8875BFA89693EEB838CE59F09D207A503EE6F6299C92D6361BC335FCBF9B5CD44747AADCE2CE6069CFDC3D671DAEF9F8AE590CF93D957C9E873E9A1BC62D9640DC8FC39C14902D49A1C80239B6C5B7FD91D05878CBF5FFC7DB2569F47C43D6C0D27C438ABFF276E87364DEB8858A37E5A62C446AF95D8B786EAF0B5FCF78D98B41496794F8DCAAC4EEF34B2ACFB94C7E8C32A9E9866A8FA0B6F2A06F00A1CCDE569F97EEC05C803BA7500ACC96691D8898D73D8E6A47B8F43C3D5DE74458D20EDA61474C426359677001FBD75A74D7D5DB6CB4FEB83122F133206203E4E2D293F838BF8C8B3A29ACB321315100B87E80E0EDB272EE80FDA944E3FB6084ED4D7F7C7D21C69D9DA43D31A90B70693F9B0CC3EAC74C11AB8FF655905688916CFA4EF0BD04135F2E50B7C689A21D04E8E981E74C6058188B9B1F9DFC3EEC6838E9FFBCF22CE738D8A177C19318DFFEF090CEE67E12DE1A3E2A39F61247547BA5257489CBC11D7D91ED34617FCC42F7A9DA2E3CF31A94A210A1018143173913C38F60E62B24BF0D7518F38B5BAB3E6A1F8AEB35E31D6442C8ABB5178EFC892D2E787D79C6AD9E2FC271792983FA9955AC4D1D84A36C024071BC6E431B625519D556AF38185601F70E29035EA6A09C8B676C9D88CF7E05E0F17098B584C4168735940263F940033A220F40BE4C85344128B14BEB9E75696DB37014107801A59B13E89CD9D2258C169D523BE6D31552C44C82FF4BB18EC9F099F3BF0E5B1BB2BA9A87D7E26F98D294927B600B5529C47E04D98956677CBCEE8FA2B60F49776D8B8C367465B7C626DA53700684FB6C918EAD0EAB8360E4F60EDD25B4F43816A75ECF70F909301825B512469F8389D79402311D8AECB7B3EF8599E79485A4388D87744D899F7C47EE644361E17040A7958C8911BE6F463AB6A9B2AFACD688EC55EF517B38F1339EFC54487232798BB25522FF4572FF68567FE830F92F7B8113EFCE3E98C3FFFBAEDCE4FD8B50E41DA97C0C08E423A72689CC68E68F752A5E3A9003E64E35C957CA2E1C48BB6F64B05F56B70B575AD2F278D57850A7AD568C24A4D32A3D74B29F03DC125488BC7C637DA582357F40B0A52D16B3B40BB2C2315D03360BC24209E20972C200566BCF3BBE5C5B0AEDD83132A8A4D5B4242BA370B6D67D9B67EB01052D132C7866B9CB502E44796D9D356E4E3CB47CC527322CD24976FE7C9257A2864151A38E568EF7A79F10D6EF27CC04CE382347A2488B1F404FDBF407FE1CA1C9D0D5649E34800E25E18951C98CAE9F43555EEF65FEE1EA8F15828807366C3B612CD5753BF9FB8FCED08855F742CDDD6F765F74254F03186683D646E6F09AC2805586C7CF11998357CAFC5DF3F285329366F475130C928B2DCEBA4AA383758E7A9D20705C4BB9DB619E2992F608A1BA65DB254BB389468741D0502E2588AEB54390AC600C19AF5C8E61383FC1BEBE0029E4474051E4EF908828DB9CCA13277EF65DB3FD47CCC2179126AAEFB627719F421E20").unwrap()); } @@ -1255,27 +1491,43 @@ mod tests { // Returning Errors test vectors from BOLT 4 let onion_keys = build_test_onion_keys(); - let onion_error = super::build_failure_packet(onion_keys[4].shared_secret.as_ref(), 0x2002, &[0; 0]); + let onion_error = + super::build_failure_packet(onion_keys[4].shared_secret.as_ref(), 0x2002, &[0; 0]); assert_eq!(onion_error.encode(), >::from_hex("4c2fc8bc08510334b6833ad9c3e79cd1b52ae59dfe5c2a4b23ead50f09f7ee0b0002200200fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()); - let onion_packet_1 = super::encrypt_failure_packet(onion_keys[4].shared_secret.as_ref(), &onion_error.encode()[..]); + let onion_packet_1 = super::encrypt_failure_packet( + onion_keys[4].shared_secret.as_ref(), + &onion_error.encode()[..], + ); assert_eq!(onion_packet_1.data, >::from_hex("a5e6bd0c74cb347f10cce367f949098f2457d14c046fd8a22cb96efb30b0fdcda8cb9168b50f2fd45edd73c1b0c8b33002df376801ff58aaa94000bf8a86f92620f343baef38a580102395ae3abf9128d1047a0736ff9b83d456740ebbb4aeb3aa9737f18fb4afb4aa074fb26c4d702f42968888550a3bded8c05247e045b866baef0499f079fdaeef6538f31d44deafffdfd3afa2fb4ca9082b8f1c465371a9894dd8c243fb4847e004f5256b3e90e2edde4c9fb3082ddfe4d1e734cacd96ef0706bf63c9984e22dc98851bcccd1c3494351feb458c9c6af41c0044bea3c47552b1d992ae542b17a2d0bba1a096c78d169034ecb55b6e3a7263c26017f033031228833c1daefc0dedb8cf7c3e37c9c37ebfe42f3225c326e8bcfd338804c145b16e34e4").unwrap()); - let onion_packet_2 = super::encrypt_failure_packet(onion_keys[3].shared_secret.as_ref(), &onion_packet_1.data[..]); + let onion_packet_2 = super::encrypt_failure_packet( + onion_keys[3].shared_secret.as_ref(), + &onion_packet_1.data[..], + ); assert_eq!(onion_packet_2.data, >::from_hex("c49a1ce81680f78f5f2000cda36268de34a3f0a0662f55b4e837c83a8773c22aa081bab1616a0011585323930fa5b9fae0c85770a2279ff59ec427ad1bbff9001c0cd1497004bd2a0f68b50704cf6d6a4bf3c8b6a0833399a24b3456961ba00736785112594f65b6b2d44d9f5ea4e49b5e1ec2af978cbe31c67114440ac51a62081df0ed46d4a3df295da0b0fe25c0115019f03f15ec86fabb4c852f83449e812f141a9395b3f70b766ebbd4ec2fae2b6955bd8f32684c15abfe8fd3a6261e52650e8807a92158d9f1463261a925e4bfba44bd20b166d532f0017185c3a6ac7957adefe45559e3072c8dc35abeba835a8cb01a71a15c736911126f27d46a36168ca5ef7dccd4e2886212602b181463e0dd30185c96348f9743a02aca8ec27c0b90dca270").unwrap()); - let onion_packet_3 = super::encrypt_failure_packet(onion_keys[2].shared_secret.as_ref(), &onion_packet_2.data[..]); + let onion_packet_3 = super::encrypt_failure_packet( + onion_keys[2].shared_secret.as_ref(), + &onion_packet_2.data[..], + ); assert_eq!(onion_packet_3.data, >::from_hex("a5d3e8634cfe78b2307d87c6d90be6fe7855b4f2cc9b1dfb19e92e4b79103f61ff9ac25f412ddfb7466e74f81b3e545563cdd8f5524dae873de61d7bdfccd496af2584930d2b566b4f8d3881f8c043df92224f38cf094cfc09d92655989531524593ec6d6caec1863bdfaa79229b5020acc034cd6deeea1021c50586947b9b8e6faa83b81fbfa6133c0af5d6b07c017f7158fa94f0d206baf12dda6b68f785b773b360fd0497e16cc402d779c8d48d0fa6315536ef0660f3f4e1865f5b38ea49c7da4fd959de4e83ff3ab686f059a45c65ba2af4a6a79166aa0f496bf04d06987b6d2ea205bdb0d347718b9aeff5b61dfff344993a275b79717cd815b6ad4c0beb568c4ac9c36ff1c315ec1119a1993c4b61e6eaa0375e0aaf738ac691abd3263bf937e3").unwrap()); - let onion_packet_4 = super::encrypt_failure_packet(onion_keys[1].shared_secret.as_ref(), &onion_packet_3.data[..]); + let onion_packet_4 = super::encrypt_failure_packet( + onion_keys[1].shared_secret.as_ref(), + &onion_packet_3.data[..], + ); assert_eq!(onion_packet_4.data, >::from_hex("aac3200c4968f56b21f53e5e374e3a2383ad2b1b6501bbcc45abc31e59b26881b7dfadbb56ec8dae8857add94e6702fb4c3a4de22e2e669e1ed926b04447fc73034bb730f4932acd62727b75348a648a1128744657ca6a4e713b9b646c3ca66cac02cdab44dd3439890ef3aaf61708714f7375349b8da541b2548d452d84de7084bb95b3ac2345201d624d31f4d52078aa0fa05a88b4e20202bd2b86ac5b52919ea305a8949de95e935eed0319cf3cf19ebea61d76ba92532497fcdc9411d06bcd4275094d0a4a3c5d3a945e43305a5a9256e333e1f64dbca5fcd4e03a39b9012d197506e06f29339dfee3331995b21615337ae060233d39befea925cc262873e0530408e6990f1cbd233a150ef7b004ff6166c70c68d9f8c853c1abca640b8660db2921").unwrap()); - let onion_packet_5 = super::encrypt_failure_packet(onion_keys[0].shared_secret.as_ref(), &onion_packet_4.data[..]); + let onion_packet_5 = super::encrypt_failure_packet( + onion_keys[0].shared_secret.as_ref(), + &onion_packet_4.data[..], + ); assert_eq!(onion_packet_5.data, >::from_hex("9c5add3963fc7f6ed7f148623c84134b5647e1306419dbe2174e523fa9e2fbed3a06a19f899145610741c83ad40b7712aefaddec8c6baf7325d92ea4ca4d1df8bce517f7e54554608bf2bd8071a4f52a7a2f7ffbb1413edad81eeea5785aa9d990f2865dc23b4bc3c301a94eec4eabebca66be5cf638f693ec256aec514620cc28ee4a94bd9565bc4d4962b9d3641d4278fb319ed2b84de5b665f307a2db0f7fbb757366067d88c50f7e829138fde4f78d39b5b5802f1b92a8a820865af5cc79f9f30bc3f461c66af95d13e5e1f0381c184572a91dee1c849048a647a1158cf884064deddbf1b0b88dfe2f791428d0ba0f6fb2f04e14081f69165ae66d9297c118f0907705c9c4954a199bae0bb96fad763d690e7daa6cfda59ba7f2c8d11448b604d12d").unwrap()); } struct RawOnionHopData { - data: Vec + data: Vec, } impl RawOnionHopData { fn new(orig: msgs::OutboundOnionPayload) -> Self { diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index db8b43e3f67..dcaa5d64c03 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -9,23 +9,25 @@ //! 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 crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::events::{self, PaymentFailureReason}; -use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::ln::channelmanager::{ChannelDetails, EventCompletionAction, HTLCSource, PaymentId}; use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason}; +use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::offers::invoice::Bolt12Invoice; -use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router}; +use crate::routing::router::{ + BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router, +}; +use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::util::errors::APIError; use crate::util::logger::Logger; -use crate::util::time::Time; +use crate::util::ser::ReadableArgs; #[cfg(all(feature = "std", test))] use crate::util::time::tests::SinceEpoch; -use crate::util::ser::ReadableArgs; +use crate::util::time::Time; use core::fmt::{self, Display, Formatter}; use core::ops::Deref; @@ -105,10 +107,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, } } @@ -118,9 +121,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, } } @@ -172,16 +175,26 @@ impl PendingOutboundPayment { fn mark_fulfilled(&mut self) { let mut session_privs = HashSet::new(); - 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::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } => { 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::AwaitingInvoice { .. } + | PendingOutboundPayment::InvoiceReceived { .. } => { + debug_assert!(false); + return; + }, + }, + ); let payment_hash = self.payment_hash(); - *self = PendingOutboundPayment::Fulfilled { session_privs, payment_hash, timer_ticks_without_htlcs: 0 }; + *self = PendingOutboundPayment::Fulfilled { + session_privs, + payment_hash, + timer_ticks_without_htlcs: 0, + }; } fn mark_abandoned(&mut self, reason: PaymentFailureReason) { @@ -191,13 +204,13 @@ impl PendingOutboundPayment { *self = PendingOutboundPayment::Abandoned { session_privs: our_session_privs, payment_hash: *payment_hash, - reason: Some(reason) + reason: Some(reason), }; } else if let PendingOutboundPayment::InvoiceReceived { payment_hash, .. } = self { *self = PendingOutboundPayment::Abandoned { session_privs: HashSet::new(), payment_hash: *payment_hash, - reason: Some(reason) + reason: Some(reason), }; } } @@ -205,20 +218,24 @@ impl PendingOutboundPayment { /// 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::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } => { 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::AwaitingInvoice { .. } + | PendingOutboundPayment::InvoiceReceived { .. } => { + 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(); @@ -226,8 +243,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); } } } @@ -236,29 +256,36 @@ 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::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); false }, + PendingOutboundPayment::Legacy { session_privs } + | PendingOutboundPayment::Retryable { session_privs, .. } => session_privs.insert(session_priv), + PendingOutboundPayment::AwaitingInvoice { .. } + | PendingOutboundPayment::InvoiceReceived { .. } => { + 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 @@ -266,12 +293,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::InvoiceReceived { .. } => 0, } @@ -315,11 +340,14 @@ impl Retry { max_retry_count > count }, #[cfg(all(feature = "std", not(test)))] - (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => - *max_duration >= crate::util::time::MonotonicTime::now().duration_since(*first_attempted_at), + (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => { + *max_duration + >= crate::util::time::MonotonicTime::now().duration_since(*first_attempted_at) + }, #[cfg(all(feature = "std", test))] - (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => - *max_duration >= SinceEpoch::now().duration_since(*first_attempted_at), + (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => { + *max_duration >= SinceEpoch::now().duration_since(*first_attempted_at) + }, } } } @@ -328,7 +356,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 @@ -347,7 +375,6 @@ pub(crate) struct PaymentAttemptsUsingTime { first_attempted_at: T, #[cfg(not(feature = "std"))] phantom: core::marker::PhantomData, - } #[cfg(not(feature = "std"))] @@ -560,7 +587,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 @@ -588,8 +619,12 @@ 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 < 1 << 16 { + return Err(()); + } + if *typ == 5482373484 { + return Err(()); + } // keysend match prev_type { Some(prev) if prev >= *typ => return Err(()), _ => {}, @@ -638,15 +673,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)); @@ -674,18 +715,16 @@ pub(super) struct OutboundPayments { impl OutboundPayments { pub(super) fn new() -> Self { - Self { - pending_outbound_payments: Mutex::new(HashMap::new()), - retry_lock: Mutex::new(()), - } + Self { pending_outbound_payments: Mutex::new(HashMap::new()), retry_lock: Mutex::new(()) } } 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, @@ -695,33 +734,71 @@ impl OutboundPayments { IH: Fn() -> InFlightHtlcs, SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - self.send_payment_internal(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_internal( + 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_payment_with_route( &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, entropy_source: &ES, node_signer: &NS, best_block_height: u32, - send_payment_along_path: F + send_payment_along_path: F, ) -> Result<(), PaymentSendFailure> where ES::Target: EntropySource, NS::Target: NodeSigner, - F: Fn(SendAlongPathArgs) -> Result<(), APIError> + F: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - let onion_session_privs = self.add_new_pending_payment(payment_hash, recipient_onion.clone(), payment_id, None, route, None, None, entropy_source, best_block_height)?; - self.pay_route_internal(route, payment_hash, recipient_onion, None, payment_id, None, - 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 }) + let onion_session_privs = self.add_new_pending_payment( + payment_hash, + recipient_onion.clone(), + payment_id, + None, + route, + None, + None, + entropy_source, + best_block_height, + )?; + self.pay_route_internal( + route, + payment_hash, + recipient_onion, + None, + payment_id, + None, + 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 + }) } 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, @@ -734,16 +811,30 @@ 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_internal(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_internal( + 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 send_spontaneous_payment_with_route( &self, route: &Route, payment_preimage: Option, recipient_onion: RecipientOnionFields, payment_id: PaymentId, entropy_source: &ES, - 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 where ES::Target: EntropySource, @@ -753,21 +844,46 @@ 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()); - let onion_session_privs = self.add_new_pending_payment(payment_hash, recipient_onion.clone(), - payment_id, Some(preimage), &route, None, None, entropy_source, best_block_height)?; - - match self.pay_route_internal(route, payment_hash, recipient_onion, Some(preimage), - payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path + let onion_session_privs = self.add_new_pending_payment( + payment_hash, + recipient_onion.clone(), + payment_id, + Some(preimage), + &route, + None, + None, + entropy_source, + best_block_height, + )?; + + match self.pay_route_internal( + route, + payment_hash, + recipient_onion, + Some(preimage), + payment_id, + None, + onion_session_privs, + node_signer, + best_block_height, + &send_payment_along_path, ) { Ok(()) => Ok(payment_hash), Err(e) => { self.remove_outbound_if_all_failed(payment_id, &e); Err(e) - } + }, } } - pub(super) fn send_payment_for_bolt12_invoice( + pub(super) fn send_payment_for_bolt12_invoice< + R: Deref, + ES: Deref, + NS: Deref, + IH, + SP, + L: Deref, + >( &self, invoice: &Bolt12Invoice, payment_id: PaymentId, router: &R, first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, @@ -786,7 +902,11 @@ impl OutboundPayments { let max_total_routing_fee_msat; match self.pending_outbound_payments.lock().unwrap().entry(payment_id) { hash_map::Entry::Occupied(entry) => match entry.get() { - PendingOutboundPayment::AwaitingInvoice { retry_strategy, max_total_routing_fee_msat: max_total_fee, .. } => { + PendingOutboundPayment::AwaitingInvoice { + retry_strategy, + max_total_routing_fee_msat: max_total_fee, + .. + } => { max_total_routing_fee_msat = *max_total_fee; *entry.into_mut() = PendingOutboundPayment::InvoiceReceived { payment_hash, @@ -801,27 +921,36 @@ impl OutboundPayments { let pay_params = PaymentParameters::from_bolt12_invoice(&invoice); let amount_msat = invoice.amount_msats(); - let mut route_params = RouteParameters::from_payment_params_and_value(pay_params, amount_msat); + let mut route_params = + RouteParameters::from_payment_params_and_value(pay_params, amount_msat); if let Some(max_fee_msat) = max_total_routing_fee_msat { route_params.max_total_routing_fee_msat = Some(max_fee_msat); } 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 + 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, ); Ok(()) } 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, @@ -836,35 +965,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: *payment_hash, - reason: *reason, - }, None)); + pending_events.lock().unwrap().push_back(( + events::Event::PaymentFailed { + payment_id: *pmt_id, + payment_hash: *payment_hash, + reason: *reason, + }, + None, + )); retain = false; } } @@ -874,9 +1039,12 @@ 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() + }) } /// Errors immediately on [`RetryableSendFailure`] error conditions. Otherwise, further errors may @@ -885,11 +1053,13 @@ impl OutboundPayments { /// [`Event::PaymentPathFailed`]: crate::events::Event::PaymentPathFailed /// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed fn send_payment_internal( - &self, payment_id: PaymentId, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, - keysend_preimage: Option, 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, + &self, payment_id: PaymentId, payment_hash: PaymentHash, + recipient_onion: RecipientOnionFields, keysend_preimage: Option, + 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, ) -> Result<(), RetryableSendFailure> where R::Target: Router, @@ -899,23 +1069,37 @@ 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 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); } } - 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 - })?; + 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, @@ -923,21 +1107,64 @@ impl OutboundPayments { route.route_params = Some(route_params.clone()); } - 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) + 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, + ) .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, 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, + 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, router, first_hops, &inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, &send_payment_along_path); + self.handle_pay_route_err( + e, + payment_id, + payment_hash, + route, + route_params, + router, + first_hops, + &inflight_htlcs, + entropy_source, + node_signer, + best_block_height, + logger, + pending_events, + &send_payment_along_path, + ); } Ok(()) } @@ -946,9 +1173,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, @@ -956,25 +1183,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) { @@ -986,8 +1234,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; } } @@ -996,116 +1248,164 @@ 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, - reason: *reason, - }, None)); + pending_events.lock().unwrap().push_back(( + events::Event::PaymentFailed { + payment_id, + payment_hash, + reason: *reason, + }, + None, + )); $payment.remove(); } } - } + }; } let (total_msat, recipient_onion, keysend_preimage, onion_session_privs) = { 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, .. - } => { - 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, + .. + } => { + 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 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 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) - }, - PendingOutboundPayment::Legacy { .. } => { - log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102"); - return - }, - PendingOutboundPayment::AwaitingInvoice { .. } => { - log_error!(logger, "Payment not yet sent"); - return - }, - PendingOutboundPayment::InvoiceReceived { payment_hash, retry_strategy, .. } => { - let total_amount = route_params.final_value_msat; - let recipient_onion = RecipientOnionFields { - payment_secret: None, - payment_metadata: None, - custom_tlvs: vec![], - }; - let retry_strategy = Some(*retry_strategy); - let payment_params = Some(route_params.payment_params.clone()); - let (retryable_payment, onion_session_privs) = self.create_pending_payment( - *payment_hash, recipient_onion.clone(), None, &route, - retry_strategy, payment_params, entropy_source, best_block_height - ); - *payment.into_mut() = retryable_payment; - (total_amount, recipient_onion, None, onion_session_privs) - }, - 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) + }, + PendingOutboundPayment::Legacy { .. } => { + log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102"); + return; + }, + PendingOutboundPayment::AwaitingInvoice { .. } => { + log_error!(logger, "Payment not yet sent"); + return; + }, + PendingOutboundPayment::InvoiceReceived { + payment_hash, + retry_strategy, + .. + } => { + let total_amount = route_params.final_value_msat; + let recipient_onion = RecipientOnionFields { + payment_secret: None, + payment_metadata: None, + custom_tlvs: vec![], + }; + let retry_strategy = Some(*retry_strategy); + let payment_params = Some(route_params.payment_params.clone()); + let (retryable_payment, onion_session_privs) = self.create_pending_payment( + *payment_hash, + recipient_onion.clone(), + None, + &route, + retry_strategy, + payment_params, + entropy_source, + best_block_height, + ); + *payment.into_mut() = retryable_payment; + (total_amount, recipient_onion, None, onion_session_privs) + }, + 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, - 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, + 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, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path); + self.handle_pay_route_err( + e, + payment_id, + payment_hash, + route, + route_params, + 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, 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 + &self, err: PaymentSendFailure, payment_id: PaymentId, payment_hash: PaymentHash, + route: Route, 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, + ) where R::Target: Router, ES::Target: EntropySource, NS::Target: NodeSigner, @@ -1115,15 +1415,61 @@ impl OutboundPayments { { match err { PaymentSendFailure::AllFailedResendSafe(errs) => { - 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::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, .. } => { - Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut retry, route.paths, results.into_iter(), logger, pending_events); + PaymentSendFailure::PartialFailure { + failed_paths_retry: Some(mut retry), + results, + .. + } => { + 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 @@ -1132,27 +1478,54 @@ 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::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::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.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.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 { @@ -1160,25 +1533,28 @@ 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(test)] - error_code: None, - #[cfg(test)] - 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(test)] + error_code: None, + #[cfg(test)] + error_data: None, + }, + None, + )); } } } 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), PaymentSendFailure> where ES::Target: EntropySource, @@ -1192,29 +1568,46 @@ impl OutboundPayments { if path.hops.len() < 2 && path.blinded_tail.is_none() { return Err(PaymentSendFailure::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)?; - - match self.pay_route_internal(&route, payment_hash, RecipientOnionFields::spontaneous_empty(), - None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path + 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, + )?; + + match self.pay_route_internal( + &route, + payment_hash, + RecipientOnionFields::spontaneous_empty(), + 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); Err(e) - } + }, } } #[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, .. } => { @@ -1226,24 +1619,48 @@ impl OutboundPayments { #[cfg(test)] 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) + &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, + ) } 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 - ) -> 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, + ) -> 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, route, retry_strategy, - payment_params, entropy_source, best_block_height + payment_hash, + recipient_onion, + keysend_preimage, + route, + retry_strategy, + payment_params, + entropy_source, + best_block_height, ); entry.insert(payment); Ok(onion_session_privs) @@ -1254,7 +1671,7 @@ impl OutboundPayments { fn create_pending_payment( &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, keysend_preimage: 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, @@ -1278,8 +1695,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()) { @@ -1291,7 +1710,7 @@ impl OutboundPayments { pub(super) fn add_new_awaiting_invoice( &self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry, - max_total_routing_fee_msat: Option + max_total_routing_fee_msat: Option, ) -> Result<(), ()> { let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap(); match pending_outbounds.entry(payment_id) { @@ -1310,42 +1729,64 @@ impl OutboundPayments { fn pay_route_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>, { 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; } } @@ -1364,8 +1805,14 @@ 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.into_iter()) { let mut path_res = send_payment_along_path(SendAlongPathArgs { - path: &path, payment_hash: &payment_hash, recipient_onion: recipient_onion.clone(), - total_value, cur_height, payment_id, keysend_preimage: &keysend_preimage, session_priv_bytes + path: &path, + payment_hash: &payment_hash, + recipient_onion: recipient_onion.clone(), + total_value, + cur_height, + payment_id, + keysend_preimage: &keysend_preimage, + session_priv_bytes, }); match path_res { Ok(_) => {}, @@ -1380,10 +1827,13 @@ impl OutboundPayments { 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"); } else { - debug_assert!(false, "This can't happen as the payment was added by callers"); + debug_assert!( + false, + "This can't happen as the payment was added by callers" + ); path_res = Err(APIError::APIMisuseError { err: "Internal error: payment disappeared during processing. Please report this bug!".to_owned() }); } - } + }, } results.push(path_res); } @@ -1398,7 +1848,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. @@ -1420,18 +1872,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(()) } @@ -1440,25 +1899,38 @@ impl OutboundPayments { #[cfg(test)] 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, 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, + 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` // map as the payment is free to be resent. fn remove_outbound_if_all_failed(&self, payment_id: PaymentId, err: &PaymentSendFailure) { if let &PaymentSendFailure::AllFailedResendSafe(_) = err { - let removed = self.pending_outbound_payments.lock().unwrap().remove(&payment_id).is_some(); + 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"); } } @@ -1468,7 +1940,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(); @@ -1478,12 +1952,15 @@ impl OutboundPayments { let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array()); log_info!(logger, "Payment with id {} and hash {} sent!", payment_id, payment_hash); let fee_paid_msat = payment.get().get_pending_fee_msat(); - pending_events.push_back((events::Event::PaymentSent { - payment_id: Some(payment_id), - payment_preimage, - payment_hash, - fee_paid_msat, - }, Some(ev_completion_action.clone()))); + pending_events.push_back(( + events::Event::PaymentSent { + payment_id: Some(payment_id), + payment_preimage, + payment_hash, + fee_paid_msat, + }, + Some(ev_completion_action.clone()), + )); payment.get_mut().mark_fulfilled(); } @@ -1495,22 +1972,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 { @@ -1522,11 +2004,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, + )); } } } @@ -1535,8 +2016,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 { @@ -1547,19 +2028,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; + } + }, _ => {}, } } @@ -1587,9 +2078,10 @@ impl OutboundPayments { }, }; if is_stale { - pending_events.push_back( - (events::Event::InvoiceRequestFailed { payment_id: *payment_id }, None) - ); + pending_events.push_back(( + events::Event::InvoiceRequestFailed { payment_id: *payment_id }, + None, + )); false } else { true @@ -1604,16 +2096,27 @@ 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(test)] 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(test))] 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); @@ -1626,7 +2129,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; } @@ -1637,55 +2141,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: *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: *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); @@ -1722,36 +2243,42 @@ impl OutboundPayments { #[cfg(test)] error_code: onion_error_code, #[cfg(test)] - 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) { payment.get_mut().mark_abandoned(reason); if let PendingOutboundPayment::Abandoned { payment_hash, reason, .. } = payment.get() { if payment.get().remaining_parts() == 0 { - pending_events.lock().unwrap().push_back((events::Event::PaymentFailed { - payment_id, - payment_hash: *payment_hash, - reason: *reason, - }, None)); + pending_events.lock().unwrap().push_back(( + events::Event::PaymentFailed { + payment_id, + payment_hash: *payment_hash, + reason: *reason, + }, + None, + )); payment.remove(); } } else if let PendingOutboundPayment::AwaitingInvoice { .. } = payment.get() { - pending_events.lock().unwrap().push_back((events::Event::InvoiceRequestFailed { - payment_id, - }, None)); + pending_events + .lock() + .unwrap() + .push_back((events::Event::InvoiceRequestFailed { payment_id }, None)); payment.remove(); } } @@ -1770,9 +2297,9 @@ impl OutboundPayments { /// 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 } @@ -1837,17 +2364,21 @@ mod tests { use core::time::Duration; use crate::events::{Event, PathFailure, PaymentFailureReason}; - use crate::ln::PaymentHash; use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; use crate::ln::features::{ChannelFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError}; - use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, Retry, RetryableSendFailure, StaleExpiration}; + use crate::ln::outbound_payment::{ + Bolt12PaymentError, OutboundPayments, Retry, RetryableSendFailure, StaleExpiration, + }; + use crate::ln::PaymentHash; #[cfg(feature = "std")] use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY; 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}; + use crate::routing::router::{ + InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters, + }; use crate::sync::{Arc, Mutex, RwLock}; use crate::util::errors::APIError; use crate::util::test_utils; @@ -1858,21 +2389,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()); } @@ -1894,31 +2417,71 @@ 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).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, + ) + .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"); + } } } @@ -1937,31 +2500,73 @@ 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(LightningError { err: String::new(), action: ErrorAction::IgnoreError })); + router.expect_find_route( + route_params.clone(), + Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError }), + ); 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).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, + ) + .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"); + } } } @@ -1975,21 +2580,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())); @@ -2004,46 +2615,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] @@ -2056,11 +2720,9 @@ 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), None - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), None) + .is_ok()); assert!(outbound_payments.has_pending_payments()); for seconds_since_epoch in (0..absolute_expiry).step_by(tick_interval) { @@ -2082,18 +2744,14 @@ mod tests { ); assert!(pending_events.lock().unwrap().is_empty()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), None - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), None) + .is_ok()); assert!(outbound_payments.has_pending_payments()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), None - ).is_err() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), None) + .is_err()); } #[test] @@ -2105,11 +2763,9 @@ 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), None - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), None) + .is_ok()); assert!(outbound_payments.has_pending_payments()); for i in 0..timer_ticks { @@ -2131,18 +2787,14 @@ mod tests { ); assert!(pending_events.lock().unwrap().is_empty()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), None - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), None) + .is_ok()); assert!(outbound_payments.has_pending_payments()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), None - ).is_err() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), None) + .is_err()); } #[test] @@ -2153,15 +2805,15 @@ 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), None - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), 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()); @@ -2186,28 +2838,42 @@ 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), None - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), None) + .is_ok()); assert!(outbound_payments.has_pending_payments()); let created_at = now() - DEFAULT_RELATIVE_EXPIRY; let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), created_at).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_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![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| panic!() ), Ok(()), ); @@ -2239,20 +2905,29 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); - - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); + + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), Some(invoice.amount_msats() / 100 + 50_000) - ).is_ok() - ); + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); router.expect_find_route( @@ -2265,8 +2940,17 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| panic!() ), Ok(()), ); @@ -2298,20 +2982,29 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); - - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); + + assert!(outbound_payments + .add_new_awaiting_invoice( + payment_id, + expiration, + Retry::Attempts(0), Some(invoice.amount_msats() / 100 + 50_000) - ).is_ok() - ); + ) + .is_ok()); assert!(outbound_payments.has_pending_payments()); let route_params = RouteParameters::from_payment_params_and_value( @@ -2319,13 +3012,23 @@ mod tests { invoice.amount_msats(), ); router.expect_find_route( - route_params.clone(), Ok(Route { paths: vec![], route_params: Some(route_params) }) + route_params.clone(), + Ok(Route { paths: vec![], route_params: Some(route_params) }), ); assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| panic!() ), Ok(()), ); @@ -2357,13 +3060,20 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_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), @@ -2373,48 +3083,60 @@ 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![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::UnexpectedInvoice), ); assert!(!outbound_payments.has_pending_payments()); assert!(pending_events.lock().unwrap().is_empty()); - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), Some(1234) - ).is_ok() - ); + assert!(outbound_payments + .add_new_awaiting_invoice(payment_id, expiration, Retry::Attempts(0), Some(1234)) + .is_ok()); assert!(outbound_payments.has_pending_payments()); assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| Ok(()) + &invoice, + payment_id, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| Ok(()) ), Ok(()), ); @@ -2423,8 +3145,17 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &invoice, + payment_id, + &&router, + vec![], + || InFlightHtlcs::new(), + &&keys_manager, + &&keys_manager, + 0, + &&logger, + &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::DuplicateInvoice), ); diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index 0db815a7085..c50c2fa4aee 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -11,29 +11,44 @@ //! serialization ordering between ChannelManager/ChannelMonitors and ensuring we can still retry //! payments thereafter. -use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS}; -use crate::sign::EntropySource; +use crate::chain::channelmonitor::{ + ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, +}; use crate::chain::transaction::OutPoint; -use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentFailureReason, PaymentPurpose}; -use crate::ln::channel::{EXPIRE_PREV_CONFIG_TICKS, commit_tx_fee_msat, get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI}; -use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, RecentPaymentDetails, RecipientOnionFields, HTLCForwardInfo, PendingHTLCRouting, PendingAddHTLCInfo}; +use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, + PathFailure, PaymentFailureReason, PaymentPurpose, +}; +use crate::ln::channel::{ + commit_tx_fee_msat, get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI, + EXPIRE_PREV_CONFIG_TICKS, +}; +use crate::ln::channelmanager::{ + HTLCForwardInfo, PaymentId, PaymentSendFailure, PendingAddHTLCInfo, PendingHTLCRouting, + RecentPaymentDetails, RecipientOnionFields, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, + MPP_TIMEOUT_TICKS, +}; use crate::ln::features::{Bolt11InvoiceFeatures, ChannelTypeFeatures}; -use crate::ln::{msgs, ChannelId, PaymentHash, PaymentSecret, PaymentPreimage}; use crate::ln::msgs::ChannelMessageHandler; use crate::ln::onion_utils; -use crate::ln::outbound_payment::{IDEMPOTENCY_TIMEOUT_TICKS, Retry}; +use crate::ln::outbound_payment::{Retry, IDEMPOTENCY_TIMEOUT_TICKS}; +use crate::ln::{msgs, ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use crate::routing::gossip::{EffectiveCapacity, RoutingFees}; -use crate::routing::router::{get_route, Path, PaymentParameters, Route, Router, RouteHint, RouteHintHop, RouteHop, RouteParameters, find_route}; +use crate::routing::router::{ + find_route, get_route, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, + RouteParameters, Router, +}; use crate::routing::scoring::ChannelUsage; +use crate::sign::EntropySource; 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::constants::Network; use bitcoin::secp256k1::{Secp256k1, SecretKey}; @@ -46,7 +61,7 @@ use crate::routing::gossip::NodeId; #[cfg(feature = "std")] use { crate::util::time::tests::SinceEpoch, - std::time::{SystemTime, Instant, Duration}, + std::time::{Duration, Instant, SystemTime}, }; #[test] @@ -61,7 +76,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(); @@ -70,8 +86,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] @@ -86,14 +114,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(); @@ -108,48 +143,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); @@ -159,8 +230,22 @@ 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(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, 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( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_preimage, + ); } #[test] @@ -177,22 +262,36 @@ 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), Some(limited_config_1), Some(limited_config_2), Some(user_config)]); + let node_chanmgrs = create_node_chanmgrs( + 4, + &node_cfgs, + &[Some(user_config), 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); @@ -209,28 +308,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()); @@ -239,20 +358,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(); @@ -260,7 +385,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); @@ -272,15 +400,27 @@ 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. let extra_fees = vec![0, total_overpaid_amount]; let expected_total_fee_msat = do_claim_payment_along_route_with_extra_penultimate_hop_fees( - &nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], &extra_fees[..], false, - payment_preimage); + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + &extra_fees[..], + false, + payment_preimage, + ); expect_payment_sent!(&nodes[0], payment_preimage, Some(expected_total_fee_msat)); } @@ -295,7 +435,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(); @@ -306,15 +447,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 @@ -323,33 +480,80 @@ 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(23, &[][..])); + expect_payment_failed_conditions( + &nodes[0], + payment_hash, + false, + PaymentFailedConditions::new().mpp_parts_remain().expected_htlc_error_data(23, &[][..]), + ); } 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(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); + claim_payment_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_preimage, + ); } } @@ -381,7 +585,9 @@ fn do_test_keysend_payments(public_node: bool, with_retry: bool) { let payer_pubkey = nodes[0].node.get_our_node_id(); 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 network_graph = nodes[0].network_graph; let channels = nodes[0].node.list_usable_channels(); @@ -391,19 +597,40 @@ fn do_test_keysend_payments(public_node: bool, with_retry: bool) { 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, first_hops, - nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes - ).unwrap(); + &payer_pubkey, + &route_params, + &network_graph, + first_hops, + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); { let test_preimage = PaymentPreimage([42; 32]); if with_retry { - nodes[0].node.send_spontaneous_payment_with_retry(Some(test_preimage), - RecipientOnionFields::spontaneous_empty(), PaymentId(test_preimage.0), - route_params, Retry::Attempts(1)).unwrap() + nodes[0] + .node + .send_spontaneous_payment_with_retry( + Some(test_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(test_preimage.0), + route_params, + Retry::Attempts(1), + ) + .unwrap() } else { - nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage), - RecipientOnionFields::spontaneous_empty(), PaymentId(test_preimage.0)).unwrap() + nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(test_preimage), + RecipientOnionFields::spontaneous_empty(), + PaymentId(test_preimage.0), + ) + .unwrap() }; } check_added_monitors!(nodes[0], 1); @@ -417,9 +644,14 @@ fn do_test_keysend_payments(public_node: bool, with_retry: 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] @@ -428,7 +660,8 @@ fn test_mpp_keysend() { mpp_keysend_config.accept_mpp_keysend = true; 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, Some(mpp_keysend_config)]); + let node_chanmgrs = + create_node_chanmgrs(4, &node_cfgs, &[None, None, None, Some(mpp_keysend_config)]); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1); @@ -441,16 +674,34 @@ 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 scorer = test_utils::TestScorer::new(); let random_seed_bytes = chanmon_cfgs[0].keys_manager.get_secure_random_bytes(); - let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger, - &scorer, &Default::default(), &random_seed_bytes).unwrap(); + let route = find_route( + &payer_pubkey, + &route_params, + &network_graph, + None, + nodes[0].logger, + &scorer, + &Default::default(), + &random_seed_bytes, + ) + .unwrap(); let payment_preimage = PaymentPreimage([42; 32]); let payment_secret = PaymentSecret(payment_preimage.0); - let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_preimage.0)).unwrap(); + let payment_hash = nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(payment_preimage), + RecipientOnionFields::secret_only(payment_secret), + PaymentId(payment_preimage.0), + ) + .unwrap(); check_added_monitors!(nodes[0], 2); let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]]; @@ -458,12 +709,28 @@ 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)); + 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(&nodes[0], expected_route, false, payment_preimage); } @@ -480,7 +747,8 @@ fn test_reject_mpp_keysend_htlc() { 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, Some(reject_mpp_keysend_cfg)]); + let node_chanmgrs = + create_node_chanmgrs(4, &node_cfgs, &[None, None, None, Some(reject_mpp_keysend_cfg)]); 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; @@ -488,7 +756,8 @@ fn test_reject_mpp_keysend_htlc() { 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(); @@ -496,7 +765,15 @@ fn test_reject_mpp_keysend_htlc() { route.paths[0].hops[1].short_channel_id = chan_3_id; let payment_id_0 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); - nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_0).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_0, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -515,16 +792,16 @@ fn test_reject_mpp_keysend_htlc() { 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"), }, _ => {}, } @@ -538,7 +815,15 @@ fn test_reject_mpp_keysend_htlc() { route.paths[0].hops[1].short_channel_id = chan_4_id; let payment_id_1 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); - nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_1).unwrap(); + nodes[0] + .node + .send_spontaneous_payment( + &route, + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + payment_id_1, + ) + .unwrap(); check_added_monitors!(nodes[0], 1); let update_2 = get_htlc_update_msgs!(nodes[0], nodes[2].node.get_our_node_id()); @@ -557,16 +842,16 @@ fn test_reject_mpp_keysend_htlc() { 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"), }, _ => {}, } @@ -577,20 +862,34 @@ fn test_reject_mpp_keysend_htlc() { // 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()); - 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 }] + ); } - #[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 @@ -606,7 +905,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()); @@ -648,11 +948,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(); @@ -682,16 +992,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].txid(), as_commitment_tx.txid()); } else { @@ -700,28 +1025,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"), } @@ -734,7 +1083,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); @@ -767,7 +1119,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); @@ -775,13 +1127,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 @@ -793,8 +1151,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; @@ -807,14 +1165,37 @@ 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, 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, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + assert!(nodes[0] + .node + .send_payment_with_route( + &new_route, + 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, + 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); + 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(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage); expect_payment_sent!(nodes[0], payment_preimage, Some(new_route.paths[0].hops[0].fee_msat)); } @@ -844,7 +1225,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 +1245,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 +1337,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 +1388,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, 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, + payment_hash, + RecipientOnionFields::secret_only(payment_secret), + payment_id, + ) { Err(PaymentSendFailure::DuplicatePayment) => {}, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), } assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -966,18 +1406,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, payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id).is_ok()); + assert!(nodes[0] + .node + .send_payment_with_route( + &new_route, + 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(); @@ -989,15 +1449,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, payment_hash, - RecipientOnionFields::secret_only(payment_secret), payment_id).is_ok()); + assert!(nodes[0] + .node + .send_payment_with_route( + &new_route, + 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, 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(PaymentSendFailure::DuplicatePayment) => {}, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), } assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -1007,7 +1485,15 @@ 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(); @@ -1015,9 +1501,14 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { 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(PaymentSendFailure::DuplicatePayment) => {}, - _ => panic!("Unexpected error") + _ => panic!("Unexpected error"), } assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -1028,8 +1519,9 @@ fn test_completed_payment_not_retryable_on_reload() { do_test_completed_payment_not_retryable_on_reload(false); } - -fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, confirm_commitment_tx: bool, payment_timeout: bool) { +fn do_test_dup_htlc_onchain_fails_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 when the Channel is. 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 @@ -1051,10 +1543,22 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co // 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [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()); @@ -1076,7 +1580,13 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co 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); @@ -1090,7 +1600,11 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co 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! @@ -1111,8 +1625,15 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co } let funding_txo = OutPoint { txid: funding_tx.txid(), index: 0 }; - let mon_updates: Vec<_> = chanmon_cfgs[0].persister.chain_sync_monitor_persistences.lock().unwrap() - .get_mut(&funding_txo).unwrap().drain().collect(); + let mon_updates: Vec<_> = chanmon_cfgs[0] + .persister + .chain_sync_monitor_persistences + .lock() + .unwrap() + .get_mut(&funding_txo) + .unwrap() + .drain() + .collect(); // If we are using chain::Confirm instead of chain::Listen, we will get the same update twice. // If we're testing connection idempotency we may get substantially more. assert!(mon_updates.len() >= 1); @@ -1146,7 +1667,14 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co } // 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()); @@ -1204,20 +1732,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. @@ -1235,27 +1779,54 @@ 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)); + 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(&nodes[0], &[&[&nodes[1]]], false, payment_preimage); } @@ -1325,7 +1896,8 @@ 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(); @@ -1343,7 +1915,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); @@ -1421,9 +1995,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); @@ -1438,8 +2017,10 @@ 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); @@ -1463,9 +2044,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); @@ -1484,8 +2070,10 @@ 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); @@ -1509,9 +2097,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); @@ -1531,14 +2124,16 @@ 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]] = &[&[&nodes[1], &nodes[2], &nodes[4]]]; + let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[2], &nodes[4]]]; // We check that only one probe was sent, the other one was skipped due to limited liquidity. assert_eq!(res.len(), 1); @@ -1560,15 +2155,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, second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), payment_id); + let send_result = nodes[0].node.send_payment_with_route( + &route, + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + payment_id, + ); match send_result { Err(PaymentSendFailure::DuplicatePayment) => {}, _ => panic!("Unexpected send result: {:?}", send_result), @@ -1577,12 +2178,16 @@ 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( - &route, None, RecipientOnionFields::spontaneous_empty(), payment_id); + &route, + None, + RecipientOnionFields::spontaneous_empty(), + payment_id, + ); match send_result { Err(PaymentSendFailure::DuplicatePayment) => {}, _ => panic!("Unexpected send result: {:?}", send_result), } - } + }; } check_send_rejected!(); @@ -1617,10 +2222,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); } @@ -1635,15 +2253,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, second_payment_hash, - RecipientOnionFields::secret_only(second_payment_secret), payment_id); + let send_result = nodes[0].node.send_payment_with_route( + &route, + second_payment_hash, + RecipientOnionFields::secret_only(second_payment_secret), + payment_id, + ); match send_result { Err(PaymentSendFailure::DuplicatePayment) => {}, _ => panic!("Unexpected send result: {:?}", send_result), @@ -1652,18 +2276,25 @@ 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( - &route, None, RecipientOnionFields::spontaneous_empty(), payment_id); + &route, + None, + RecipientOnionFields::spontaneous_empty(), + payment_id, + ); match send_result { Err(PaymentSendFailure::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. @@ -1672,14 +2303,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); } @@ -1691,7 +2341,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 @@ -1710,31 +2360,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 { @@ -1742,17 +2407,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)); @@ -1760,19 +2432,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); @@ -1786,24 +2467,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); } @@ -1820,17 +2513,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, 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); - 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); } @@ -1839,12 +2547,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)); @@ -1873,7 +2587,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(); @@ -1883,30 +2601,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, 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, + 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(); @@ -1925,26 +2656,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); @@ -1961,18 +2714,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 = { @@ -1985,28 +2764,48 @@ 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(&nodes[0], &vec!(&vec!(&nodes[1], &nodes[2])[..]), false, 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( + &nodes[0], + &vec![&vec![&nodes[1], &nodes[2]][..]], + false, + 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 { @@ -2018,7 +2817,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()); @@ -2026,16 +2828,38 @@ 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, 0x2000 | 2, []); // 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)) + } + ); } } @@ -2053,13 +2877,20 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { intercept_forwards_config.accept_intercept_htlcs = true; let mut underpay_config = test_default_channel_config(); underpay_config.channel_config.accept_underpaying_htlcs = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), Some(underpay_config)]); + 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 mut chan_ids = Vec::new(); for _ in 0..num_mpp_parts { let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000, 0); - let channel_id = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 2_000_000, 0).0.channel_id; + let channel_id = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 2_000_000, 0) + .0 + .channel_id; chan_ids.push(channel_id); } @@ -2071,24 +2902,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. @@ -2100,15 +2945,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 = { { @@ -2120,29 +2975,45 @@ 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); assert_eq!(skimmed_fee_msat * num_mpp_parts as u64, counterparty_skimmed_fee_msat); assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap()); match purpose { - crate::events::PaymentPurpose::InvoicePayment { payment_preimage: ev_payment_preimage, - payment_secret: ev_payment_secret, .. } => - { + crate::events::PaymentPurpose::InvoicePayment { + payment_preimage: ev_payment_preimage, + payment_secret: ev_payment_secret, + .. + } => { assert_eq!(payment_preimage, ev_payment_preimage.unwrap()); assert_eq!(payment_secret, *ev_payment_secret); }, @@ -2153,14 +3024,27 @@ 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][..]); + } let total_fee_msat = do_claim_payment_along_route_with_extra_penultimate_hop_fees( - &nodes[0], &expected_paths[..], &vec![skimmed_fee_msat as u32; num_mpp_parts][..], false, - payment_preimage); + &nodes[0], + &expected_paths[..], + &vec![skimmed_fee_msat as u32; num_mpp_parts][..], + false, + payment_preimage, + ); // 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)] @@ -2207,11 +3091,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) => { @@ -2264,8 +3151,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 @@ -2277,12 +3172,28 @@ 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); + 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(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage); } else if test == AutoRetry::Spontaneous { - nodes[0].node.send_spontaneous_payment_with_retry(Some(payment_preimage), - RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, - Retry::Attempts(1)).unwrap(); + nodes[0] + .node + .send_spontaneous_payment_with_retry( + Some(payment_preimage), + RecipientOnionFields::spontaneous_empty(), + 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 @@ -2294,12 +3205,29 @@ 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)); + 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(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, 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, 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 no liquidity on the second hop so we can find a (bad) route for @@ -2315,10 +3243,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. @@ -2332,7 +3269,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!(payment_hash, *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RetriesExhausted, ev_reason.unwrap()); @@ -2343,8 +3284,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 @@ -2358,7 +3307,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); @@ -2369,7 +3325,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!(payment_hash, *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RetriesExhausted, ev_reason.unwrap()); @@ -2377,8 +3337,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 @@ -2390,7 +3358,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!(payment_hash, *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RouteNotFound, ev_reason.unwrap()); @@ -2411,12 +3383,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"))] @@ -2425,9 +3406,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); @@ -2435,24 +3418,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()), }; @@ -2461,29 +3450,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()), }; @@ -2492,12 +3488,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, @@ -2505,15 +3502,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] { @@ -2534,9 +3540,12 @@ 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(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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); @@ -2544,23 +3553,39 @@ fn auto_retry_partial_failure() { nodes[0].node.handle_commitment_signed(&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(&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( + &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(&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); @@ -2573,11 +3598,18 @@ 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(&nodes[1].node.get_our_node_id(), &bs_claim_update.commitment_signed); + nodes[0].node.handle_commitment_signed( + &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); @@ -2585,31 +3617,55 @@ fn auto_retry_partial_failure() { nodes[1].node.handle_commitment_signed(&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(&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( + &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(&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] @@ -2621,11 +3677,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"))] @@ -2634,15 +3695,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, @@ -2650,19 +3713,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); } @@ -2677,7 +3755,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"))] @@ -2686,13 +3765,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); @@ -2704,8 +3793,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] @@ -2721,7 +3819,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"))] @@ -2730,34 +3829,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()), }; @@ -2776,22 +3883,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); }, @@ -2814,7 +3960,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"))] @@ -2823,15 +3970,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(), @@ -2839,8 +3988,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())); @@ -2855,15 +4005,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); }, @@ -2896,11 +4057,18 @@ fn no_extra_retries_on_back_to_back_fail() { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - 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_2_scid = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 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; + let chan_2_scid = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 0) + .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"))] @@ -2909,48 +4077,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()), }; @@ -2961,21 +4143,33 @@ 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())); - 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 htlc_updates = SendEvent::from_node(&nodes[0]); check_added_monitors!(nodes[0], 1); assert_eq!(htlc_updates.msgs.len(), 1); nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &htlc_updates.msgs[0]); - nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &htlc_updates.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&nodes[0].node.get_our_node_id(), &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); @@ -2983,12 +4177,25 @@ fn no_extra_retries_on_back_to_back_fail() { nodes[0].node.handle_commitment_signed(&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_update_add_htlc(&nodes[0].node.get_our_node_id(), &second_htlc_updates.msgs[0]); - nodes[1].node.handle_commitment_signed(&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( + &nodes[0].node.get_our_node_id(), + &second_htlc_updates.commitment_msg, + ); 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); check_added_monitors!(nodes[1], 1); @@ -2997,10 +4204,17 @@ fn no_extra_retries_on_back_to_back_fail() { 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_update_fail_htlc(&nodes[1].node.get_our_node_id(), &bs_fail_update.update_fail_htlcs[0]); - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_fail_update.commitment_signed); + 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_commitment_signed( + &nodes[1].node.get_our_node_id(), + &bs_fail_update.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let (as_second_raa, as_third_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (as_second_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_second_raa); check_added_monitors!(nodes[1], 1); @@ -3008,21 +4222,36 @@ fn no_extra_retries_on_back_to_back_fail() { nodes[1].node.handle_commitment_signed(&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_update_fail_htlc(&nodes[1].node.get_our_node_id(), &bs_second_fail_update.update_fail_htlcs[0]); - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_fail_update.commitment_signed); + nodes[0].node.handle_update_fail_htlc( + &nodes[1].node.get_our_node_id(), + &bs_second_fail_update.update_fail_htlcs[0], + ); + nodes[0].node.handle_commitment_signed( + &nodes[1].node.get_our_node_id(), + &bs_second_fail_update.commitment_signed, + ); 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); - let (as_third_raa, as_fourth_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (as_third_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_third_raa); check_added_monitors!(nodes[1], 1); nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_fourth_cs); check_added_monitors!(nodes[1], 1); - let bs_fourth_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id()); + let bs_fourth_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_fourth_raa); check_added_monitors!(nodes[0], 1); @@ -3042,7 +4271,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); }, @@ -3053,7 +4286,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); }, @@ -3064,23 +4301,36 @@ 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); 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!(payment_hash, *ev_payment_hash); assert_eq!(PaymentId(payment_hash.0), *ev_payment_id); assert_eq!(PaymentFailureReason::RetriesExhausted, ev_reason.unwrap()); @@ -3101,11 +4351,18 @@ fn test_simple_partial_retry() { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - 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_2_scid = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 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; + let chan_2_scid = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 0) + .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"))] @@ -3114,48 +4371,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()), }; @@ -3166,21 +4437,33 @@ 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())); - 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 htlc_updates = SendEvent::from_node(&nodes[0]); check_added_monitors!(nodes[0], 1); assert_eq!(htlc_updates.msgs.len(), 1); nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &htlc_updates.msgs[0]); - nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &htlc_updates.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&nodes[0].node.get_our_node_id(), &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); @@ -3188,12 +4471,25 @@ fn test_simple_partial_retry() { nodes[0].node.handle_commitment_signed(&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_update_add_htlc(&nodes[0].node.get_our_node_id(), &second_htlc_updates.msgs[0]); - nodes[1].node.handle_commitment_signed(&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( + &nodes[0].node.get_our_node_id(), + &second_htlc_updates.commitment_msg, + ); 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); check_added_monitors!(nodes[1], 1); @@ -3202,10 +4498,17 @@ fn test_simple_partial_retry() { 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_update_fail_htlc(&nodes[1].node.get_our_node_id(), &bs_fail_update.update_fail_htlcs[0]); - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_fail_update.commitment_signed); + 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_commitment_signed( + &nodes[1].node.get_our_node_id(), + &bs_fail_update.commitment_signed, + ); check_added_monitors!(nodes[0], 1); - let (as_second_raa, as_third_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + let (as_second_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_second_raa); check_added_monitors!(nodes[1], 1); @@ -3213,7 +4516,11 @@ fn test_simple_partial_retry() { nodes[1].node.handle_commitment_signed(&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); @@ -3221,7 +4528,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); }, @@ -3236,15 +4547,23 @@ 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_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_forward_update.update_add_htlcs[0]); - nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &bs_forward_update.update_add_htlcs[1]); + nodes[2].node.handle_update_add_htlc( + &nodes[1].node.get_our_node_id(), + &bs_forward_update.update_add_htlcs[0], + ); + nodes[2].node.handle_update_add_htlc( + &nodes[1].node.get_our_node_id(), + &bs_forward_update.update_add_htlcs[1], + ); commitment_signed_dance!(nodes[2], nodes[1], &bs_forward_update.commitment_signed, false); expect_pending_htlcs_forwardable!(nodes[2]); @@ -3269,13 +4588,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"))] @@ -3284,66 +4613,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, .. } = 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; @@ -3366,7 +4721,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 @@ -3387,25 +4744,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... @@ -3439,7 +4810,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(); @@ -3451,12 +4823,20 @@ 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(&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(&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 @@ -3467,12 +4847,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(); @@ -3484,23 +4879,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()); check_added_monitors(&nodes[0], 1); @@ -3545,14 +4960,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. @@ -3561,22 +4991,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, .. } => { @@ -3587,8 +5045,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 }, + ); if fail_payment { // We fail the HTLC on the A->B->D path first as it expires 4 blocks earlier. We go ahead // and expire both immediately, though, by connecting another 4 blocks. @@ -3596,11 +5059,26 @@ 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()).unwrap(); - check_closed_event!(&nodes[1], 1, ClosureReason::HolderForceClosed, 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()) + .unwrap(); + check_closed_event!( + &nodes[1], + 1, + ClosureReason::HolderForceClosed, + 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); @@ -3608,8 +5086,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); @@ -3627,28 +5111,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]); } @@ -3683,7 +5183,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]), @@ -3692,12 +5193,18 @@ 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(&route, Some(our_payment_preimage), onion_fields, payment_id).unwrap(); + nodes[0] + .node + .send_spontaneous_payment(&route, Some(our_payment_preimage), onion_fields, payment_id) + .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); @@ -3722,7 +5229,13 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) { match (known_tlvs, even_tlvs) { (true, _) => { nodes[1].node.claim_funds_with_known_custom_tlvs(our_payment_preimage); - let expected_total_fee_msat = pass_claimed_payment_along_route(&nodes[0], &[&[&nodes[1]]], &[0; 1], false, our_payment_preimage); + let expected_total_fee_msat = pass_claimed_payment_along_route( + &nodes[0], + &[&[&nodes[1]]], + &[0; 1], + false, + our_payment_preimage, + ); expect_payment_sent!(&nodes[0], our_payment_preimage, Some(expected_total_fee_msat)); }, (false, false) => { @@ -3730,10 +5243,20 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) { }, (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, + ); + }, } } @@ -3749,7 +5272,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) = @@ -3764,8 +5287,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. @@ -3777,11 +5308,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()); @@ -3793,25 +5326,41 @@ 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(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); - let payment_claimable = pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000, - payment_hash, Some(payment_secret), events.pop().unwrap(), true, None).unwrap(); + let payment_claimable = pass_along_path( + &nodes[0], + &[&nodes[1], &nodes[2]], + 1_000_000, + payment_hash, + Some(payment_secret), + events.pop().unwrap(), + true, + None, + ) + .unwrap(); match payment_claimable { Event::PaymentClaimable { onion_fields, .. } => { assert_eq!(&onion_fields.unwrap().custom_tlvs()[..], &custom_tlvs[..]); @@ -3824,9 +5373,9 @@ fn test_retry_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]; @@ -3857,9 +5406,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]); @@ -3870,17 +5420,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; @@ -3888,21 +5444,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()); @@ -3910,10 +5486,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); { @@ -3921,7 +5508,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]); @@ -3931,7 +5520,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); } @@ -3949,32 +5540,49 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: _ => panic!("Unexpected event"), } - do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], - false, our_payment_preimage); + do_claim_payment_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + our_payment_preimage, + ); 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(), + ); } } @@ -3992,7 +5600,8 @@ 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), Some(config), Some(config)]); + let node_chanmgrs = + create_node_chanmgrs(4, &node_cfgs, &[None, Some(config), Some(config), Some(config)]); let nodes_0_deserialized; let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs); @@ -4004,18 +5613,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(); @@ -4048,13 +5671,21 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { commitment_signed_dance!(nodes[2], nodes[0], c_recv_ev.commitment_msg, false, true); 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. @@ -4067,8 +5698,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])); } @@ -4099,21 +5737,36 @@ 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: chan_id_cd_2 }]); + 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: chan_id_cd_2, + }], + ); } else { expect_pending_htlcs_forwardable!(nodes[3]); expect_payment_claimable!(nodes[3], payment_hash, payment_secret, amt_msat); - claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); + claim_payment_along_route( + &nodes[0], + &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, + payment_preimage, + ); } } @@ -4126,7 +5779,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 @@ -4144,21 +5797,35 @@ 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), Some(config), Some(config)]); + let node_chanmgrs = + create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), Some(config)]); 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 = commit_tx_fee_msat( - *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(), ); 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); @@ -4168,17 +5835,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() @@ -4188,16 +5867,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 { @@ -4210,9 +5895,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); } @@ -4227,21 +5919,30 @@ 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.clone(), - nodes[0].best_block_info().1, &payment_hash, &Some(keysend_preimage), prng_seed - ).unwrap(); + &secp_ctx, + &route.paths[0], + &session_priv, + amt_msat, + recipient_onion.clone(), + nodes[0].best_block_info().1, + &payment_hash, + &Some(keysend_preimage), + prng_seed, + ) + .unwrap(); let update_add = msgs::UpdateAddHTLC { channel_id: ChannelId([0; 32]), @@ -4254,9 +5955,15 @@ 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, true, false - ).unwrap(); + &update_add, + &&chanmon_cfgs[1].keys_manager, + &&chanmon_cfgs[1].logger, + &secp_ctx, + nodes[1].best_block_info().1, + true, + false, + ) + .unwrap(); assert_eq!(peeled_onion.incoming_amt_msat, Some(amt_msat)); match peeled_onion.routing { PendingHTLCRouting::ReceiveKeysend { @@ -4269,6 +5976,6 @@ fn peel_payment_onion_custom_tlvs() { assert!(payment_metadata.is_none()); assert!(payment_data.is_none()); }, - _ => panic!() + _ => panic!(), } } diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index 51e34bdb969..2da14d90360 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -9,18 +9,18 @@ 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::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 hex::DisplayHex; @@ -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::hashes::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 3b9f9848ec8..dd59cff4365 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -16,35 +16,40 @@ //! messages they should handle, and encoding/sending response messages. use bitcoin::blockdata::constants::ChainHash; -use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey}; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; -use crate::sign::{NodeSigner, Recipient}; use crate::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider}; -use crate::ln::ChannelId; use crate::ln::features::{InitFeatures, NodeFeatures}; use crate::ln::msgs; -use crate::ln::msgs::{ChannelMessageHandler, LightningError, SocketAddress, OnionMessageHandler, RoutingMessageHandler}; -use crate::util::macro_logger::DebugFundingChannelId; -use crate::util::ser::{VecWriter, Writeable, Writer}; -use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE}; +use crate::ln::msgs::{ + ChannelMessageHandler, LightningError, OnionMessageHandler, RoutingMessageHandler, + SocketAddress, +}; +use crate::ln::peer_channel_encryptor::{ + MessageBuf, NextNoiseStep, PeerChannelEncryptor, MSG_BUF_ALLOC_SIZE, +}; use crate::ln::wire; use crate::ln::wire::{Encode, Type}; +use crate::ln::ChannelId; use crate::onion_message::messenger::{CustomOnionMessageHandler, PendingOnionMessage}; 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::util::atomic_counter::AtomicCounter; use crate::util::logger::{Logger, WithContext}; +use crate::util::macro_logger::DebugFundingChannelId; +use crate::util::ser::{VecWriter, Writeable, Writer}; use crate::util::string::PrintableString; -use crate::prelude::*; use crate::io; +use crate::prelude::*; +use crate::sync::{FairRwLock, Mutex, MutexGuard}; use alloc::collections::VecDeque; -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 core::convert::Infallible; +use core::ops::Deref; +use core::sync::atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering}; +use core::{cmp, fmt, hash, mem}; #[cfg(feature = "std")] use std::error; #[cfg(not(c_bindings))] @@ -58,7 +63,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. /// @@ -72,7 +77,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 @@ -96,44 +103,102 @@ 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 EventsProvider for IgnoringMessageHandler { - fn process_pending_events(&self, _handler: H) where H::Target: EventHandler {} + fn process_pending_events(&self, _handler: H) + where + H::Target: EventHandler, + { + } } impl MessageSendEventsProvider for IgnoringMessageHandler { - 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, _msg: &msgs::NodeAnnouncement) -> Result { Ok(false) } - fn handle_channel_announcement(&self, _msg: &msgs::ChannelAnnouncement) -> Result { Ok(false) } - fn handle_channel_update(&self, _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 peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) } - 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 provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } + fn handle_node_announcement( + &self, _msg: &msgs::NodeAnnouncement, + ) -> Result { + Ok(false) + } + fn handle_channel_announcement( + &self, _msg: &msgs::ChannelAnnouncement, + ) -> Result { + Ok(false) + } + fn handle_channel_update(&self, _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 peer_connected( + &self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { + Ok(()) + } + 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 provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::empty() } - fn processing_queue_high(&self) -> bool { false } + 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 peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) } + fn next_onion_message_for_peer(&self, _peer_node_id: PublicKey) -> Option { + None + } + fn peer_connected( + &self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { + Ok(()) + } fn peer_disconnected(&self, _their_node_id: &PublicKey) {} fn timer_tick_occurred(&self) {} - 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() } } impl OffersMessageHandler for IgnoringMessageHandler { - fn handle_message(&self, _msg: OffersMessage) -> Option { None } + fn handle_message(&self, _msg: OffersMessage) -> Option { + None + } } impl CustomOnionMessageHandler for IgnoringMessageHandler { type CustomMessage = Infallible; @@ -141,7 +206,12 @@ impl CustomOnionMessageHandler for IgnoringMessageHandler { // 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> { @@ -150,12 +220,16 @@ impl CustomOnionMessageHandler for IgnoringMessageHandler { } impl OnionMessageContents for Infallible { - fn tlv_type(&self) -> u64 { unreachable!(); } + fn tlv_type(&self) -> u64 { + 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 @@ -173,20 +247,28 @@ 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 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() @@ -196,7 +278,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 @@ -206,7 +288,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: node_id.clone(), }); @@ -264,7 +349,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) { @@ -276,18 +363,28 @@ 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) { + fn handle_channel_reestablish( + &self, their_node_id: &PublicKey, msg: &msgs::ChannelReestablish, + ) { ErroringMessageHandler::push_error(self, their_node_id, msg.channel_id); } // msgs::ChannelUpdate does not contain the channel_id field, so we just drop them. fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &msgs::ChannelUpdate) {} fn peer_disconnected(&self, _their_node_id: &PublicKey) {} - fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool) -> Result<(), ()> { Ok(()) } + fn peer_connected( + &self, _their_node_id: &PublicKey, _init: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { + Ok(()) + } fn handle_error(&self, _their_node_id: &PublicKey, _msg: &msgs::ErrorMessage) {} - 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 { // 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 @@ -362,11 +459,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, @@ -406,7 +506,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. @@ -436,7 +536,7 @@ pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone { /// 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") @@ -455,7 +555,7 @@ impl error::Error for PeerHandleError { } } -enum InitSyncTracker{ +enum InitSyncTracker { NoSyncRequested, ChannelsSyncing(u64), NodesSyncing(NodeId), @@ -472,7 +572,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. @@ -558,11 +659,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, @@ -572,15 +676,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() + }, } } @@ -590,14 +699,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() } @@ -605,14 +715,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 } @@ -621,8 +733,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) { @@ -645,7 +758,7 @@ pub type SimpleArcPeerManager = PeerManager< Arc>, Arc, IgnoringMessageHandler, - Arc + Arc, >; /// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference @@ -658,7 +771,24 @@ 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, SD, M, T, F, C, L + 'a, + 'b, + 'c, + 'd, + 'e, + 'f, + 'logger, + 'h, + 'i, + 'j, + 'graph, + 'k, + SD, + M, + T, + F, + C, + L, > = PeerManager< SD, &'j SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'graph, 'logger, 'i, M, T, F, L>, @@ -666,10 +796,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. @@ -680,25 +809,35 @@ 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; /// Returns the peer manager's [`OnionMessageHandler`]. fn onion_message_handler(&self) -> &Self::OMT; } -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, @@ -719,7 +858,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 + } fn onion_message_handler(&self) -> &Self::OMT { self.message_handler.onion_message_handler.deref() } @@ -744,13 +885,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 @@ -793,7 +943,7 @@ pub struct PeerManager + secp_ctx: Secp256k1, } enum MessageHandlingError { @@ -818,14 +968,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. @@ -839,20 +992,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 @@ -867,13 +1039,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, + ) } } @@ -884,7 +1065,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(()) + } } } @@ -892,39 +1077,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. /// @@ -935,7 +1132,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); @@ -971,20 +1171,24 @@ impl Vec<(PublicKey, Option)> { let peers = self.peers.read().unwrap(); - peers.values().filter_map(|peer_mutex| { - let p = peer_mutex.lock().unwrap(); - if !p.handshake_complete() { - return None; - } - Some((p.their_node_id.unwrap().0, p.their_socket_address.clone())) - }).collect() + peers + .values() + .filter_map(|peer_mutex| { + let p = peer_mutex.lock().unwrap(); + if !p.handshake_complete() { + return None; + } + Some((p.their_node_id.unwrap().0, p.their_socket_address.clone())) + }) + .collect() } fn get_ephemeral_key(&self) -> SecretKey { let mut ephemeral_hash = self.ephemeral_key_midstate.clone(); let counter = self.peer_counter.get_increment(); ephemeral_hash.input(&counter.to_le_bytes()); - SecretKey::from_slice(&Sha256::from_engine(ephemeral_hash).to_byte_array()).expect("You broke SHA-256!") + SecretKey::from_slice(&Sha256::from_engine(ephemeral_hash).to_byte_array()) + .expect("You broke SHA-256!") } fn init_features(&self, their_node_id: &PublicKey) -> InitFeatures { @@ -1009,8 +1213,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 @@ -1047,7 +1255,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 @@ -1103,7 +1313,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 { @@ -1164,7 +1385,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 { @@ -1186,7 +1411,7 @@ impl buff, }; @@ -1223,20 +1448,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(()) } @@ -1258,14 +1485,19 @@ 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) => { - log_trace!(self.logger, "Disconnecting peer due to a protocol error (usually a duplicate connection)."); + log_trace!( + self.logger, + "Disconnecting peer due to a protocol error (usually a duplicate connection)." + ); self.disconnect_event_internal(peer_descriptor); Err(e) - } + }, } } @@ -1273,9 +1505,19 @@ impl(&self, peer: &mut Peer, message: &M) { let logger = WithContext::from(&self.logger, peer.their_node_id.map(|p| p.0), 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)); @@ -1288,7 +1530,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(); @@ -1298,7 +1542,7 @@ impl { let mut read_pos = 0; @@ -1365,8 +1609,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; } @@ -1398,16 +1647,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; @@ -1416,47 +1676,83 @@ 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); peer.awaiting_pong_timer_tick_intervals = 0; }, 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[..])); - - let mut reader = io::Cursor::new(&peer.pending_read_buffer[..peer.pending_read_buffer.len() - 16]); - let message_result = wire::read(&mut reader, &*self.message_handler.custom_message_handler); + try_potential_handleerror!( + peer, + peer.channel_encryptor + .decrypt_message(&mut peer.pending_read_buffer[..]) + ); + + let mut reader = io::Cursor::new( + &peer.pending_read_buffer + [..peer.pending_read_buffer.len() - 16], + ); + let message_result = wire::read( + &mut reader, + &*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); + let logger = WithContext::from( + &self.logger, + peer.their_node_id.map(|p| p.0), + None, + ); let message = match message_result { Ok(x) => x, Err(e) => { @@ -1465,15 +1761,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 { @@ -1481,29 +1780,35 @@ 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 { }), + return Err(PeerHandleError {}); + }, + (msgs::DecodeError::BadLengthDescriptor, _) => { + return Err(PeerHandleError {}) + }, + (msgs::DecodeError::Io(_), _) => { + return Err(PeerHandleError {}) + }, } - } + }, }; msg_to_handle = Some(message); } - } + }, } } pause_read = !self.peer_should_read(peer); @@ -1511,9 +1816,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)) => { @@ -1523,7 +1831,7 @@ impl, - mut 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.clone().expect("We know the peer's public key by the time we receive messages").0; + &self, peer_mutex: &Mutex, mut peer_lock: MutexGuard, + message: wire::Message< + <::Target as wire::CustomMessageReader>::CustomMessage, + >, + ) -> Result< + Option< + wire::Message< + <::Target as wire::CustomMessageReader>::CustomMessage, + >, + >, + MessageHandlingError, + > { + let their_node_id = peer_lock + .their_node_id + .clone() + .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); peer_lock.received_message_since_timer_tick = true; @@ -1561,7 +1880,7 @@ 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) => { @@ -1691,18 +2060,18 @@ impl { self.message_handler.chan_handler.handle_stfu(&their_node_id, &msg); - } + }, // Splicing messages: wire::Message::Splice(msg) => { self.message_handler.chan_handler.handle_splice(&their_node_id, &msg); - } + }, wire::Message::SpliceAck(msg) => { self.message_handler.chan_handler.handle_splice_ack(&their_node_id, &msg); - } + }, wire::Message::SpliceLocked(msg) => { self.message_handler.chan_handler.handle_splice_locked(&their_node_id, &msg); - } + }, // Interactive transaction construction messages: wire::Message::TxAddInput(msg) => { @@ -1731,7 +2100,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); @@ -1751,7 +2120,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) => { @@ -1769,64 +2140,100 @@ 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(&msg) - .map_err(|e| -> MessageHandlingError { e.into() })? { + if self + .message_handler + .route_handler + .handle_channel_announcement(&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(&msg) - .map_err(|e| -> MessageHandlingError { e.into() })? { + if self + .message_handler + .route_handler + .handle_node_announcement(&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(&msg) - .map_err(|e| -> MessageHandlingError { e.into() })? { + if self + .message_handler + .route_handler + .handle_channel_update(&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) } - fn forward_broadcast_msg(&self, peers: &HashMap>, msg: &wire::Message<<::Target as wire::CustomMessageReader>::CustomMessage>, except_node: Option<&PublicKey>) { + fn forward_broadcast_msg( + &self, peers: &HashMap>, + msg: &wire::Message< + <::Target as wire::CustomMessageReader>::CustomMessage, + >, + except_node: Option<&PublicKey>, + ) { match msg { wire::Message::ChannelAnnouncement(ref msg) => { log_gossip!(self.logger, "Sending message to all peers except {:?} or the announced channel's counterparties: {:?}", except_node, msg); @@ -1834,43 +2241,67 @@ 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); + let logger = + WithContext::from(&self.logger, peer.their_node_id.map(|p| p.0), None); if peer.buffer_full_drop_gossip_broadcast() { - 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 { @@ -1878,36 +2309,59 @@ 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); + let logger = + WithContext::from(&self.logger, peer.their_node_id.map(|p| p.0), None); if peer.buffer_full_drop_gossip_broadcast() { - 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") + }, } } @@ -1937,45 +2391,48 @@ impl { - { - if peers_to_disconnect.get($node_id).is_some() { - // If we've "disconnected" this peer, do not send to it. - continue; - } - 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() { - continue; - } - 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. + continue; + } + 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() { continue; } + peer_lock }, None => { + debug_assert!(false, "Inconsistent peers set state!"); continue; }, - } + }, + None => { + continue; + }, } - } + }}; } for event in events_generated.drain(..) { match event { @@ -2024,34 +2481,50 @@ impl { - let logger = WithContext::from(&self.logger, Some(*node_id), Some(msg.channel_id)); + MessageSendEvent::SendStfu { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + ); 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::SendSplice { ref node_id, ref msg} => { - let logger = WithContext::from(&self.logger, Some(*node_id), Some(msg.channel_id)); + }, + MessageSendEvent::SendSplice { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + ); log_debug!(logger, "Handling SendSplice 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)); + }, + MessageSendEvent::SendSpliceAck { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + ); 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)); + }, + MessageSendEvent::SendSpliceLocked { ref node_id, ref msg } => { + let logger = WithContext::from( + &self.logger, + Some(*node_id), + Some(msg.channel_id), + ); 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)), "Handling SendTxAddInput event in peer_handler for node {} for channel {}", log_pubkey!(node_id), @@ -2112,7 +2585,18 @@ impl { + MessageSendEvent::UpdateHTLCs { + ref node_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(commitment_signed.channel_id)), "Handling UpdateHTLCs event in peer_handler for node {} with {} adds, {} fulfills, {} fails for channel {}", log_pubkey!(node_id), update_add_htlcs.len(), @@ -2161,24 +2645,50 @@ impl { + MessageSendEvent::SendChannelAnnouncement { + ref node_id, + ref msg, + ref update_msg, + } => { log_debug!(WithContext::from(&self.logger, Some(*node_id), 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(&msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => - self.forward_broadcast_msg(peers, &wire::Message::ChannelAnnouncement(msg), None), + match self + .message_handler + .route_handler + .handle_channel_announcement(&msg) + { + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => self.forward_broadcast_msg( + peers, + &wire::Message::ChannelAnnouncement(msg), + None, + ), _ => {}, } if let Some(msg) = update_msg { - match self.message_handler.route_handler.handle_channel_update(&msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => - self.forward_broadcast_msg(peers, &wire::Message::ChannelUpdate(msg), None), + match self.message_handler.route_handler.handle_channel_update(&msg) + { + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => self.forward_broadcast_msg( + peers, + &wire::Message::ChannelUpdate(msg), + None, + ), _ => {}, } } @@ -2186,16 +2696,31 @@ impl { log_debug!(self.logger, "Handling BroadcastChannelUpdate event in peer_handler for contents {:?}", msg.contents); match self.message_handler.route_handler.handle_channel_update(&msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => - self.forward_broadcast_msg(peers, &wire::Message::ChannelUpdate(msg), None), + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => self.forward_broadcast_msg( + peers, + &wire::Message::ChannelUpdate(msg), + None, + ), _ => {}, } }, 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(&msg) { - Ok(_) | Err(LightningError { action: msgs::ErrorAction::IgnoreDuplicateGossip, .. }) => - self.forward_broadcast_msg(peers, &wire::Message::NodeAnnouncement(msg), None), + match self.message_handler.route_handler.handle_node_announcement(&msg) + { + Ok(_) + | Err(LightningError { + action: msgs::ErrorAction::IgnoreDuplicateGossip, + .. + }) => self.forward_broadcast_msg( + peers, + &wire::Message::NodeAnnouncement(msg), + None, + ), _ => {}, } }, @@ -2227,26 +2752,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, + ); }, } }, @@ -2255,7 +2799,7 @@ impl { self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg); - } + }, MessageSendEvent::SendReplyChannelRange { ref node_id, ref msg } => { log_gossip!(WithContext::from(&self.logger, Some(*node_id), None), "Handling SendReplyChannelRange event in peer_handler for node {} with num_scids={} first_blocknum={} number_of_blocks={}, sync_complete={}", log_pubkey!(node_id), @@ -2264,22 +2808,32 @@ impl { self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), 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; } + 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 *get_peer_for_forwarding!(&node_id), &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() { @@ -2291,7 +2845,8 @@ impl { let peer = peer_lock.lock().unwrap(); if let Some((node_id, _)) = peer.their_node_id { - log_trace!(WithContext::from(&self.logger, Some(node_id), None), "Handling disconnection of peer {}", log_pubkey!(node_id)); + log_trace!( + WithContext::from(&self.logger, Some(node_id), None), + "Handling disconnection of peer {}", + log_pubkey!(node_id) + ); let removed = self.node_id_to_descriptor.lock().unwrap().remove(&node_id); debug_assert!(removed.is_some(), "descriptor maps should be consistent"); - if !peer.handshake_complete() { return; } + if !peer.handshake_complete() { + return; + } self.message_handler.chan_handler.peer_disconnected(&node_id); self.message_handler.onion_message_handler.peer_disconnected(&node_id); } - } + }, }; } @@ -2373,7 +2945,9 @@ 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; @@ -2464,14 +3045,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!"); } @@ -2540,9 +3125,10 @@ impl sig, Err(_) => { log_error!(self.logger, "Failed to generate signature for node_announcement"); @@ -2550,46 +3136,53 @@ 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, } } #[cfg(test)] mod tests { - use crate::sign::{NodeSigner, Recipient}; use crate::events; use crate::io; - use crate::ln::ChannelId; use crate::ln::features::{InitFeatures, NodeFeatures}; + use crate::ln::msgs::{LightningError, SocketAddress}; use crate::ln::peer_channel_encryptor::PeerChannelEncryptor; - use crate::ln::peer_handler::{CustomMessageHandler, PeerManager, MessageHandler, SocketDescriptor, IgnoringMessageHandler, filter_addresses}; + use crate::ln::peer_handler::{ + filter_addresses, CustomMessageHandler, IgnoringMessageHandler, MessageHandler, + PeerManager, SocketDescriptor, + }; + use crate::ln::ChannelId; use crate::ln::{msgs, wire}; - use crate::ln::msgs::{LightningError, SocketAddress}; + use crate::sign::{NodeSigner, Recipient}; use crate::util::test_utils; - use bitcoin::Network; use bitcoin::blockdata::constants::ChainHash; use bitcoin::secp256k1::{PublicKey, SecretKey}; + use bitcoin::Network; use crate::prelude::*; use crate::sync::{Arc, Mutex}; @@ -2607,7 +3200,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) @@ -2620,7 +3213,9 @@ mod tests { data.len() } - fn disconnect_socket(&mut self) { self.disconnect.store(true, Ordering::Release); } + fn disconnect_socket(&mut self) { + self.disconnect.store(true, Ordering::Release); + } } struct PeerManagerCfg { @@ -2637,19 +3232,27 @@ mod tests { 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) } } impl CustomMessageHandler for TestCustomMessageHandler { - fn handle_custom_message(&self, _: Infallible, _: &PublicKey) -> Result<(), LightningError> { + fn handle_custom_message( + &self, _: Infallible, _: &PublicKey, + ) -> Result<(), LightningError> { 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 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() @@ -2665,15 +3268,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::new(), - routing_handler: test_utils::TestRoutingMessageHandler::new(), - custom_handler: TestCustomMessageHandler { 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 { features }, + node_signer: test_utils::TestNodeSigner::new(node_secret), + }); } cfgs @@ -2688,15 +3291,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 { 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 { features }, + node_signer: test_utils::TestNodeSigner::new(node_secret), + }); } cfgs @@ -2708,49 +3311,89 @@ 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 { 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 { 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 establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { + 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 id_a = peer_a.node_signer.get_node_id(Recipient::Node).unwrap(); let mut fd_a = FileDescriptor { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; - 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 id_b = peer_b.node_signer.get_node_id(Recipient::Node).unwrap(); let mut fd_b = FileDescriptor { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; - 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(); @@ -2783,68 +3426,94 @@ 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 { - fd: $id + ctr * 3, outbound_data: Arc::new(Mutex::new(Vec::new())), - disconnect: Arc::new(AtomicBool::new(false)), - }; - let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; - let mut fd_b = FileDescriptor { - fd: $id + ctr * 3, outbound_data: Arc::new(Mutex::new(Vec::new())), - disconnect: Arc::new(AtomicBool::new(false)), - }; - 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(crate::events::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 { + fd: $id + ctr * 3, + outbound_data: Arc::new(Mutex::new(Vec::new())), + disconnect: Arc::new(AtomicBool::new(false)), + }; + let addr_a = SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1000 }; + let mut fd_b = FileDescriptor { + fd: $id + ctr * 3, + outbound_data: Arc::new(Mutex::new(Vec::new())), + disconnect: Arc::new(AtomicBool::new(false)), + }; + 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( + crate::events::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(crate::events::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( + crate::events::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); @@ -2863,16 +3532,19 @@ 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 { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; - 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 { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; - 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(); @@ -2899,16 +3571,19 @@ 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 { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; - 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 { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; - 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(); @@ -2934,10 +3609,12 @@ mod tests { assert_eq!(peers[0].peers.read().unwrap().len(), 1); let their_id = peers[1].node_signer.get_node_id(Recipient::Node).unwrap(); - cfgs[0].chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError { - node_id: their_id, - action: msgs::ErrorAction::DisconnectPeer { msg: None }, - }); + cfgs[0].chan_handler.pending_events.lock().unwrap().push( + events::MessageSendEvent::HandleError { + node_id: their_id, + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }, + ); peers[0].process_events(); assert_eq!(peers[0].peers.read().unwrap().len(), 0); @@ -2948,18 +3625,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(events::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(events::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)); @@ -2981,14 +3667,16 @@ mod tests { let peers = create_network(2, &cfgs); let mut fd_dup = FileDescriptor { - fd: 3, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 3, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; - 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(); @@ -3053,7 +3741,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()); @@ -3066,7 +3754,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 @@ -3088,11 +3780,13 @@ mod tests { let a_id = peers[0].node_signer.get_node_id(Recipient::Node).unwrap(); let mut fd_a = FileDescriptor { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; let mut fd_b = FileDescriptor { - fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())), + fd: 1, + outbound_data: Arc::new(Mutex::new(Vec::new())), disconnect: Arc::new(AtomicBool::new(false)), }; let initial_data = peers[1].new_outbound_connection(a_id, fd_b.clone(), None).unwrap(); @@ -3118,95 +3812,113 @@ mod tests { } #[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) @@ -3228,21 +3940,28 @@ mod tests { // should always have at least one count at the end. 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 exit_flag = Arc::new(AtomicBool::new(false)); - macro_rules! spawn_thread { () => { { - let thread_cfg = Arc::clone(&cfg); - let thread_peer = Arc::clone(&peer); - let thread_exit = Arc::clone(&exit_flag); - std::thread::spawn(move || { - while !thread_exit.load(Ordering::Acquire) { - thread_cfg[0].chan_handler.message_fetch_counter.store(0, Ordering::Release); - thread_peer.process_events(); - std::thread::sleep(Duration::from_micros(1)); - } - }) - } } } + macro_rules! spawn_thread { + () => {{ + let thread_cfg = Arc::clone(&cfg); + let thread_peer = Arc::clone(&peer); + let thread_exit = Arc::clone(&exit_flag); + std::thread::spawn(move || { + while !thread_exit.load(Ordering::Acquire) { + thread_cfg[0] + .chan_handler + .message_fetch_counter + .store(0, Ordering::Release); + thread_peer.process_events(); + std::thread::sleep(Duration::from_micros(1)); + } + }) + }}; + } let thread_a = spawn_thread!(); let thread_b = spawn_thread!(); diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs index 1bdebafdc6f..f60c2f9d8ba 100644 --- a/lightning/src/ln/priv_short_conf_tests.rs +++ b/lightning/src/ln/priv_short_conf_tests.rs @@ -12,16 +12,18 @@ //! LSP). use crate::chain::ChannelMonitorUpdateStatus; -use crate::sign::NodeSigner; -use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider}; -use crate::ln::channelmanager::{MIN_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields}; -use crate::routing::gossip::RoutingFees; -use crate::routing::router::{PaymentParameters, RouteHint, RouteHintHop}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, +}; +use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, MIN_CLTV_EXPIRY_DELTA}; use crate::ln::features::ChannelTypeFeatures; -use crate::ln::{msgs, ChannelId}; -use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ChannelUpdate, ErrorAction}; +use crate::ln::msgs::{ChannelMessageHandler, ChannelUpdate, ErrorAction, RoutingMessageHandler}; use crate::ln::wire::Encode; -use crate::util::config::{UserConfig, MaxDustHTLCExposure}; +use crate::ln::{msgs, ChannelId}; +use crate::routing::gossip::RoutingFees; +use crate::routing::router::{PaymentParameters, RouteHint, RouteHintHop}; +use crate::sign::NodeSigner; +use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::ser::Writeable; use crate::util::test_utils; @@ -48,8 +50,12 @@ fn test_priv_forwarding_rejection() { 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: @@ -66,15 +72,27 @@ 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, 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, + 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); @@ -84,9 +102,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. @@ -99,14 +126,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); @@ -114,12 +167,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); @@ -127,10 +198,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); } @@ -141,33 +225,48 @@ fn do_test_1_conf_open(connect_style: ConnectStyle) { alice_config.channel_handshake_config.minimum_depth = 1; alice_config.channel_handshake_config.announced_channel = 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.announced_channel = 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()); @@ -176,7 +275,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); @@ -185,26 +286,50 @@ 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[0] { - 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[1] { - (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[0] + { + 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[1] + { + (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 node in nodes { @@ -231,7 +356,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 { @@ -239,19 +365,39 @@ 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(), 42) - .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); + .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); @@ -290,8 +436,22 @@ fn test_scid_privacy_on_pub_channel() { let mut scid_privacy_cfg = test_default_channel_config(); scid_privacy_cfg.channel_handshake_config.announced_channel = 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.channel_type.as_ref().unwrap().supports_scid_privacy()); // we ignore `negotiate_scid_privacy` on pub channels open_channel.channel_type.as_mut().unwrap().set_scid_privacy_required(); @@ -314,24 +474,52 @@ fn test_scid_privacy_negotiation() { let mut scid_privacy_cfg = test_default_channel_config(); scid_privacy_cfg.channel_handshake_config.announced_channel = 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.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.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.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()); + let second_open_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendOpenChannel, + nodes[1].node.get_our_node_id() + ); assert!(!second_open_channel.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); @@ -340,8 +528,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] @@ -352,7 +548,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); @@ -360,39 +557,96 @@ fn test_inbound_scid_privacy() { let mut no_announce_cfg = test_default_channel_config(); no_announce_cfg.channel_handshake_config.announced_channel = 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.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); @@ -405,19 +659,39 @@ 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(), 42) - .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); + .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); @@ -428,12 +702,22 @@ fn test_inbound_scid_privacy() { 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(), 42) - .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); + .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]); @@ -441,15 +725,30 @@ fn test_inbound_scid_privacy() { 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, true, true); - 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(0x4000|10, &[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(0x4000 | 10, &[0; 0]), + ); } #[test] @@ -461,7 +760,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); @@ -473,34 +773,68 @@ 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, 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_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); // Build the expected channel update @@ -513,10 +847,18 @@ fn test_scid_alias_returned() { htlc_minimum_msat: 1_000, htlc_maximum_msat: 1_000_000, // Defaults to 10% of the channel value fee_base_msat: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_base_msat, - fee_proportional_millionths: last_hop[0].counterparty.forwarding_info.as_ref().unwrap().fee_proportional_millionths, + fee_proportional_millionths: last_hop[0] + .counterparty + .forwarding_info + .as_ref() + .unwrap() + .fee_proportional_millionths, excess_data: Vec::new(), }; - let signature = nodes[1].keys_manager.sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&contents)).unwrap(); + let signature = nodes[1] + .keys_manager + .sign_gossip_message(msgs::UnsignedGossipMessage::ChannelUpdate(&contents)) + .unwrap(); let msg = msgs::ChannelUpdate { signature, contents }; let mut err_data = Vec::new(); @@ -524,23 +866,41 @@ fn test_scid_alias_returned() { err_data.extend_from_slice(&ChannelUpdate::TYPE.to_be_bytes()); err_data.extend_from_slice(&msg.encode()); - 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(0x1000|7, &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(0x1000 | 7, &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); 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(); @@ -548,9 +908,15 @@ fn test_scid_alias_returned() { err_data.extend_from_slice(&(msg.serialized_length() as u16 + 2).to_be_bytes()); err_data.extend_from_slice(&ChannelUpdate::TYPE.to_be_bytes()); err_data.extend_from_slice(&msg.encode()); - 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(0x1000|12, &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(0x1000 | 12, &err_data), + ); } #[test] @@ -591,26 +957,56 @@ fn test_0conf_channel_with_async_monitor() { create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); chan_config.channel_handshake_config.announced_channel = 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).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ) + .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.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); @@ -630,14 +1026,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"), } @@ -672,18 +1068,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"), }; @@ -700,18 +1100,29 @@ 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(&nodes[0].node.get_our_node_id(), &as_send.commitment_msg); + nodes[1] + .node + .handle_commitment_signed(&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); @@ -719,12 +1130,26 @@ fn test_0conf_channel_with_async_monitor() { 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 (outpoint, _, latest_update) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&bs_raa.channel_id).unwrap().clone(); + let (outpoint, _, 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(outpoint, latest_update).unwrap(); check_added_monitors!(nodes[1], 0); expect_pending_htlcs_forwardable!(nodes[1]); @@ -764,7 +1189,13 @@ fn test_0conf_close_no_early_chan_update() { nodes[0].node.force_close_all_channels_broadcasting_latest_txn(); check_added_monitors!(nodes[0], 1); - check_closed_event!(&nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 100000 + ); let _ = get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id()); } @@ -787,12 +1218,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()); - - 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_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); let bs_announcement = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(bs_announcement.len(), 1); @@ -813,7 +1256,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"), @@ -848,9 +1294,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); @@ -859,14 +1313,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); } @@ -882,8 +1350,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.channel_type = Some(channel_type_features.clone()); @@ -891,7 +1366,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!(), @@ -903,15 +1381,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)).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.channel_type = Some(channel_type_features.clone()); @@ -925,25 +1415,42 @@ 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).is_err()); + assert!(nodes[1] + .node + .accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0) + .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.channel_type = Some(channel_type_features); @@ -954,8 +1461,14 @@ 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).is_ok()); + assert!(nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0 + ) + .is_ok()); }, _ => panic!(), } @@ -982,20 +1495,38 @@ 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).unwrap(); + nodes[1] + .node + .accept_inbound_channel_from_trusted_peer_0conf( + &temporary_channel_id, + &nodes[0].node.get_our_node_id(), + 0, + ) + .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.minimum_depth, 0); nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_channel); @@ -1032,15 +1563,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()); - - nodes[0].node.handle_announcement_signatures(&nodes[1].node.get_our_node_id(), &bs_announcement_sigs); + 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); 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 76dd78ae2ad..04e9bbbfb9b 100644 --- a/lightning/src/ln/reload_tests.rs +++ b/lightning/src/ln/reload_tests.rs @@ -9,26 +9,30 @@ //! Functional tests which test for correct behavior across node restarts. -use crate::chain::{ChannelMonitorUpdateStatus, Watch}; use crate::chain::chaininterface::LowerBoundedFeeEstimator; -use crate::chain::channelmonitor::{CLOSED_CHANNEL_UPDATE_ID, ChannelMonitor}; -use crate::sign::EntropySource; +use crate::chain::channelmonitor::{ChannelMonitor, CLOSED_CHANNEL_UPDATE_ID}; use crate::chain::transaction::OutPoint; -use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider}; -use crate::ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, PaymentId, RecipientOnionFields}; +use crate::chain::{ChannelMonitorUpdateStatus, Watch}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, +}; +use crate::ln::channelmanager::{ + ChannelManager, ChannelManagerReadArgs, PaymentId, RecipientOnionFields, +}; +use crate::ln::msgs::{ChannelMessageHandler, ErrorAction, RoutingMessageHandler}; use crate::ln::{msgs, ChannelId}; -use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction}; +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::hash_types::BlockHash; use crate::prelude::*; -use core::default::Default; use crate::sync::Mutex; +use core::default::Default; use crate::ln::functional_test_utils::*; @@ -63,13 +67,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. @@ -142,7 +164,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] { @@ -154,7 +178,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] { @@ -180,7 +206,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])); } @@ -200,17 +233,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.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(); + let chan_0_monitor_serialized = get_monitor!( + nodes[0], + ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.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(); 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]); @@ -218,8 +279,10 @@ 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 node in nodes.iter() { assert!(node.gossip_sync.handle_channel_announcement(&announcement).unwrap()); node.gossip_sync.handle_channel_update(&as_update).unwrap(); @@ -246,16 +309,40 @@ 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.funding_transaction_generated(&temporary_channel_id, &node_b.node.get_our_node_id(), tx.clone()).unwrap(); + 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 + .funding_transaction_generated( + &temporary_channel_id, + &node_b.node.get_our_node_id(), + tx.clone(), + ) + .unwrap(); check_added_monitors!(node_a, 0); - node_b.node.handle_funding_created(&node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id())); + node_b.node.handle_funding_created( + &node_a.node.get_our_node_id(), + &get_event_msg!( + node_a, + MessageSendEvent::SendFundingCreated, + node_b.node.get_our_node_id() + ), + ); { let mut added_monitors = node_b.chain_monitor.added_monitors.lock().unwrap(); assert_eq!(added_monitors.len(), 1); @@ -263,7 +350,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(); @@ -281,7 +369,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()); @@ -289,18 +384,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].txid(), funding_output.txid); + assert_eq!( + nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].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]); @@ -308,8 +424,10 @@ 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 node in nodes.iter() { assert!(node.gossip_sync.handle_channel_announcement(&announcement).unwrap()); node.gossip_sync.handle_channel_update(&as_update).unwrap(); @@ -337,7 +455,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])); @@ -391,14 +516,24 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::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); } @@ -406,55 +541,104 @@ 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::InvalidValue) = - <(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::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, - chain_monitor: nodes[0].chain_monitor, - tx_broadcaster: nodes[0].tx_broadcaster, - logger: &logger, - channel_monitors: node_0_stale_monitors.iter_mut().map(|monitor| { (monitor.get_funding_txo().0, monitor) }).collect(), - }) { } else { + if let Err(msgs::DecodeError::InvalidValue) = <( + 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::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, + chain_monitor: nodes[0].chain_monitor, + tx_broadcaster: nodes[0].tx_broadcaster, + logger: &logger, + channel_monitors: node_0_stale_monitors + .iter_mut() + .map(|monitor| (monitor.get_funding_txo().0, 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::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, - chain_monitor: nodes[0].chain_monitor, - tx_broadcaster: nodes[0].tx_broadcaster, - logger: &logger, - channel_monitors: node_0_monitors.iter_mut().map(|monitor| { (monitor.get_funding_txo().0, 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::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, + chain_monitor: nodes[0].chain_monitor, + tx_broadcaster: nodes[0].tx_broadcaster, + logger: &logger, + channel_monitors: node_0_monitors + .iter_mut() + .map(|monitor| (monitor.get_funding_txo().0, monitor)) + .collect(), + }, + ) + .unwrap(); nodes_0_deserialized = nodes_0_deserialized_tmp; assert!(nodes_0_read.is_empty()); for monitor in node_0_monitors.drain(..) { let funding_outpoint = monitor.get_funding_txo().0; - assert_eq!(nodes[0].chain_monitor.watch_channel(funding_outpoint, monitor), - Ok(ChannelMonitorUpdateStatus::Completed)); + assert_eq!( + nodes[0].chain_monitor.watch_channel(funding_outpoint, 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); @@ -469,13 +653,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() { @@ -495,8 +697,8 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { #[cfg(feature = "std")] fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, not_stale: bool) { - use crate::routing::router::{RouteParameters, PaymentParameters}; use crate::ln::channelmanager::Retry; + use crate::routing::router::{PaymentParameters, RouteParameters}; use crate::util::string::UntrustedString; // When we get a data_loss_protect proving we're behind, we immediately panic as the // chain::Watch API requirements have been violated (e.g. the user restored from a backup). The @@ -526,14 +728,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_with_retry(None, RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), route_params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_spontaneous_payment_with_retry( + 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(&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( + &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()); @@ -544,7 +761,11 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, nodes[0].node.handle_commitment_signed(&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]); @@ -557,21 +778,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(); @@ -579,7 +827,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), @@ -595,7 +846,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(), @@ -611,7 +864,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()); @@ -630,9 +885,18 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool, } else { 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()).unwrap(); + nodes[0] + .node + .force_close_without_broadcasting_txn(&chan.2, &nodes[1].node.get_our_node_id()) + .unwrap(); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [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); @@ -655,17 +919,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())); @@ -714,9 +1000,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(); @@ -728,9 +1022,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(); @@ -749,7 +1051,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 @@ -802,29 +1111,66 @@ 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(&nodes[0], &[&nodes[1], &nodes[3]], 15_000_000, payment_hash, Some(payment_secret), node_1_msgs, true, false, None, false); - do_pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, payment_hash, Some(payment_secret), node_2_msgs, true, false, None, false); + 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( + &nodes[0], + &[&nodes[1], &nodes[3]], + 15_000_000, + payment_hash, + Some(payment_secret), + node_1_msgs, + true, + false, + None, + false, + ); + do_pass_along_path( + &nodes[0], + &[&nodes[2], &nodes[3]], + 15_000_000, + payment_hash, + Some(payment_secret), + node_2_msgs, + true, + false, + None, + false, + ); // 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. @@ -833,7 +1179,13 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { for (outpoint, 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(outpoint).unwrap().write(&mut original_monitor).unwrap(); + nodes[3] + .chain_monitor + .chain_monitor + .get_monitor(outpoint) + .unwrap() + .write(&mut original_monitor) + .unwrap(); } } } @@ -853,7 +1205,13 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { for (outpoint, 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(outpoint).unwrap().write(&mut updated_monitor).unwrap(); + nodes[3] + .chain_monitor + .chain_monitor + .get_monitor(outpoint) + .unwrap() + .write(&mut updated_monitor) + .unwrap(); } } // If `persist_both_monitors` is set, get the second monitor here as well @@ -861,17 +1219,34 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { for (outpoint, 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(outpoint).unwrap().write(&mut original_monitor).unwrap(); + nodes[3] + .chain_monitor + .chain_monitor + .get_monitor(outpoint) + .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 + ); // On startup 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)); nodes[1].node.peer_disconnected(&nodes[3].node.get_our_node_id()); nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id()); @@ -881,10 +1256,21 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { // never finished processing. 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::ChannelClosed { reason: ClosureReason::OutdatedChannelManager, .. } = + events[2] + { + } else { + panic!(); + } check_added_monitors(&nodes[3], 2); } else { check_added_monitors(&nodes[3], 1); @@ -892,51 +1278,95 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) { // 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); } @@ -948,8 +1378,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. @@ -961,7 +1395,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); @@ -978,8 +1413,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]); @@ -997,55 +1439,108 @@ 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(); } expect_pending_htlcs_forwardable!(nodes[1]); 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(&nodes[1].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[2] + .node + .handle_commitment_signed(&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(&payment_hash, &payment_preimage, - &nodes[2].tx_broadcaster, &LowerBoundedFeeEstimator(nodes[2].fee_estimator), &nodes[2].logger); + get_monitor!(nodes[2], chan_id_2).provide_payment_preimage( + &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()); let _ = nodes[2].node.get_and_clear_pending_msg_events(); - nodes[2].node.force_close_broadcasting_latest_txn(&chan_id_2, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[2] + .node + .force_close_broadcasting_latest_txn(&chan_id_2, &nodes[1].node.get_our_node_id()) + .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, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[2], + 1, + ClosureReason::HolderForceClosed, + [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(); @@ -1068,7 +1563,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); } @@ -1077,7 +1575,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); } @@ -1086,11 +1590,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); }, @@ -1143,13 +1662,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"), @@ -1157,7 +1684,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, .. } => { @@ -1175,13 +1709,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"), @@ -1202,18 +1747,24 @@ 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]); + 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()); // 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); @@ -1224,7 +1775,14 @@ fn test_reload_partial_funding_batch() { let channel_id_1 = ChannelId::v1_from_funding_outpoint(OutPoint { txid: tx.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()); diff --git a/lightning/src/ln/reorg_tests.rs b/lightning/src/ln/reorg_tests.rs index a31d9520dad..191c9c27659 100644 --- a/lightning/src/ln/reorg_tests.rs +++ b/lightning/src/ln/reorg_tests.rs @@ -13,14 +13,16 @@ 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, MessageSendEventsProvider, ClosureReason, HTLCDestination, MessageSendEvent}; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, +}; use crate::ln::msgs::{ChannelMessageHandler, Init}; -use crate::util::test_utils; use crate::util::ser::Writeable; use crate::util::string::UntrustedString; +use crate::util::test_utils; -use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; +use bitcoin::blockdata::script::Builder; use bitcoin::secp256k1::Secp256k1; use crate::prelude::*; @@ -52,11 +54,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); @@ -73,18 +76,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()] @@ -110,7 +126,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); @@ -129,7 +151,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); @@ -137,16 +165,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 + ); } } @@ -187,7 +227,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); @@ -197,14 +238,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).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).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 @@ -238,7 +287,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. @@ -253,12 +305,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); } @@ -294,7 +348,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); } @@ -308,7 +363,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(), &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(), + &nodes_0_serialized, + &[&chan_0_monitor_serialized], + persister, + new_chain_monitor, + nodes_0_deserialized + ); assert!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty()); } @@ -340,7 +403,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); } @@ -354,12 +418,27 @@ 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 + ); assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); @@ -368,9 +447,18 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_ // 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); @@ -426,8 +514,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); @@ -450,7 +540,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 { @@ -465,7 +561,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::HolderForceClosed, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::HolderForceClosed, + [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 = { @@ -542,11 +644,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()); @@ -583,8 +697,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]); } @@ -604,8 +728,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]); } } @@ -638,15 +772,35 @@ 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()) + .unwrap(); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + 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()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id()) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); check_added_monitors(&nodes[1], 1); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -673,8 +827,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( - &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(); @@ -684,7 +841,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 @@ -707,23 +865,35 @@ 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, 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, 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); // 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()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[1].node.get_our_node_id()) + .unwrap(); check_closed_broadcast(&nodes[0], 1, true); check_added_monitors(&nodes[0], 1); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); assert_eq!(txn.len(), 1); @@ -736,7 +906,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); @@ -747,8 +924,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( - &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(); @@ -757,10 +937,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); @@ -795,11 +980,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 ); } @@ -807,7 +1000,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::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[1].node.get_our_node_id()], + 100_000, + ); { let mut txn = nodes[0].tx_broadcaster.txn_broadcast(); @@ -825,10 +1025,20 @@ 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()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id()) + .unwrap(); check_closed_broadcast(&nodes[1], 1, true); check_added_monitors(&nodes[1], 1); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100_000); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed, + 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/script.rs b/lightning/src/ln/script.rs index dc733dd25a1..cb4487a603b 100644 --- a/lightning/src/ln/script.rs +++ b/lightning/src/ln/script.rs @@ -1,19 +1,19 @@ //! Abstractions for scripts used in the Lightning Network. +use bitcoin::address::WitnessProgram; use bitcoin::blockdata::opcodes::all::OP_PUSHBYTES_0 as SEGWIT_V0; use bitcoin::blockdata::script::{Script, ScriptBuf}; -use bitcoin::hashes::Hash; use bitcoin::hash_types::{WPubkeyHash, WScriptHash}; +use bitcoin::hashes::Hash; use bitcoin::secp256k1::PublicKey; -use bitcoin::address::WitnessProgram; use crate::ln::channelmanager; use crate::ln::features::InitFeatures; use crate::ln::msgs::DecodeError; use crate::util::ser::{Readable, Writeable, Writer}; -use core::convert::TryFrom; use crate::io; +use core::convert::TryFrom; /// A script pubkey for shutting down a channel as defined by [BOLT #2]. /// @@ -27,7 +27,7 @@ pub struct InvalidShutdownScript { /// The script that did not meet the requirements from [BOLT #2]. /// /// [BOLT #2]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md - pub script: ScriptBuf + pub script: ScriptBuf, } #[derive(Clone, PartialEq, Eq)] @@ -81,7 +81,9 @@ impl ShutdownScript { /// # Errors /// /// This function may return an error if `program` is invalid for the segwit `version`. - pub fn new_witness_program(witness_program: &WitnessProgram) -> Result { + pub fn new_witness_program( + witness_program: &WitnessProgram, + ) -> Result { Self::try_from(ScriptBuf::new_witness_program(witness_program)) } @@ -127,7 +129,10 @@ impl TryFrom for ShutdownScript { type Error = InvalidShutdownScript; fn try_from(script: ScriptBuf) -> Result { - Self::try_from((script, &channelmanager::provided_init_features(&crate::util::config::UserConfig::default()))) + Self::try_from(( + script, + &channelmanager::provided_init_features(&crate::util::config::UserConfig::default()), + )) } } @@ -148,14 +153,15 @@ impl TryFrom<(ScriptBuf, &InitFeatures)> for ShutdownScript { impl Into for ShutdownScript { fn into(self) -> ScriptBuf { match self.0 { - ShutdownScriptImpl::Legacy(pubkey) => - ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::hash(&pubkey.serialize())), + ShutdownScriptImpl::Legacy(pubkey) => { + ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::hash(&pubkey.serialize())) + }, ShutdownScriptImpl::Bolt2(script_pubkey) => script_pubkey, } } } -impl core::fmt::Display for ShutdownScript{ +impl core::fmt::Display for ShutdownScript { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match &self.0 { ShutdownScriptImpl::Legacy(_) => self.clone().into_inner().fmt(f), @@ -167,17 +173,21 @@ impl core::fmt::Display for ShutdownScript{ #[cfg(test)] mod shutdown_script_tests { use super::ShutdownScript; + use crate::ln::features::InitFeatures; + use bitcoin::address::{WitnessProgram, WitnessVersion}; use bitcoin::blockdata::opcodes; use bitcoin::blockdata::script::{Builder, ScriptBuf}; use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::{PublicKey, SecretKey}; - use crate::ln::features::InitFeatures; use core::convert::TryFrom; - use bitcoin::address::{WitnessProgram, WitnessVersion}; fn pubkey() -> bitcoin::key::PublicKey { let secp_ctx = Secp256k1::signing_only(); - let secret_key = SecretKey::from_slice(&[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, 1]).unwrap(); + let secret_key = SecretKey::from_slice(&[ + 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, 1, + ]) + .unwrap(); bitcoin::key::PublicKey::new(PublicKey::from_secret_key(&secp_ctx, &secret_key)) } diff --git a/lightning/src/ln/shutdown_tests.rs b/lightning/src/ln/shutdown_tests.rs index 0eb56434169..1b7a24a5998 100644 --- a/lightning/src/ln/shutdown_tests.rs +++ b/lightning/src/ln/shutdown_tests.rs @@ -10,28 +10,33 @@ //! 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, MessageSendEvent, HTLCDestination, MessageSendEventsProvider, ClosureReason}; -use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, Retry, ChannelShutdownState, ChannelDetails}; -use crate::routing::router::{PaymentParameters, get_route, RouteParameters}; -use crate::ln::{ChannelId, msgs}; +use crate::chain::ChannelMonitorUpdateStatus; +use crate::events::{ + ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, +}; +use crate::ln::channelmanager::{ + self, ChannelDetails, ChannelShutdownState, PaymentId, PaymentSendFailure, + RecipientOnionFields, Retry, +}; use crate::ln::msgs::{ChannelMessageHandler, ErrorAction}; use crate::ln::onion_utils::INVALID_ONION_BLINDING; use crate::ln::script::ShutdownScript; -use crate::util::test_utils; -use crate::util::test_utils::OnGetShutdownScriptpubkey; -use crate::util::errors::APIError; +use crate::ln::{msgs, ChannelId}; +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::util::test_utils; +use crate::util::test_utils::OnGetShutdownScriptpubkey; -use bitcoin::{Transaction, TxOut}; +use bitcoin::address::{WitnessProgram, WitnessVersion}; use bitcoin::blockdata::locktime::absolute::LockTime; -use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; +use bitcoin::blockdata::script::Builder; use bitcoin::network::constants::Network; -use bitcoin::address::{WitnessProgram, WitnessVersion}; +use bitcoin::{Transaction, TxOut}; use regex; @@ -51,25 +56,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.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.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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 8000000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 8000000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 8000000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 8000000 + ); } #[test] @@ -88,7 +126,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 @@ -96,25 +135,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -127,7 +192,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); @@ -137,13 +203,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); @@ -164,7 +232,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()); @@ -179,7 +250,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); @@ -188,16 +262,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [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()); @@ -217,22 +316,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()); @@ -243,16 +354,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [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()); @@ -266,18 +402,30 @@ 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.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.temporary_channel_id, scriptpubkey: script }, + ); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CounterpartyCoopClosedUnfundedChannel, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); } #[test] @@ -288,11 +436,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, [nodes[1].node.get_our_node_id()], 1_000_000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::HolderForceClosed, + [nodes[1].node.get_our_node_id()], + 1_000_000 + ); } #[test] @@ -307,7 +468,10 @@ 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()).unwrap(); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id()) + .unwrap(); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); @@ -323,8 +487,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, [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, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -341,12 +517,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 +533,60 @@ 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].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].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].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].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 +598,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 +612,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); assert!(nodes[0].node.list_channels().is_empty()); @@ -414,8 +662,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::CooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -434,19 +694,32 @@ 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, - 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, + 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,12 +729,18 @@ 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(&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(&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); @@ -473,14 +752,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(INVALID_ONION_BLINDING, &[0; 32])); + expect_payment_failed_conditions( + &nodes[0], + our_payment_hash, + false, + PaymentFailedConditions::new() + .expected_htlc_error_data(INVALID_ONION_BLINDING, &[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(); @@ -495,11 +787,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()); @@ -509,9 +810,27 @@ 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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 2, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id(), nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 2, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id(), nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } fn do_test_shutdown_rebroadcast(recv_count: u8) { @@ -524,13 +843,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); } @@ -539,26 +864,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.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()) @@ -578,7 +930,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()); @@ -589,34 +944,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] { @@ -636,8 +1027,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); @@ -645,14 +1042,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::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [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. @@ -663,7 +1079,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] { @@ -674,7 +1092,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 @@ -692,9 +1112,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[2].node.get_our_node_id()], 100000); - check_closed_event!(nodes[2], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[2].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[2], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } #[test] @@ -722,9 +1160,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); @@ -737,27 +1177,34 @@ 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"), } // We test that if case of peer non-signaling we don't enforce committed script at channel opening - *nodes[0].override_init_features.borrow_mut() = Some(nodes[0].node.init_features().clear_upfront_shutdown_script()); + *nodes[0].override_init_features.borrow_mut() = + Some(nodes[0].node.init_features().clear_upfront_shutdown_script()); 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"), } @@ -767,12 +1214,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"), } @@ -781,16 +1231,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"), } } @@ -800,26 +1255,36 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() { let chanmon_cfgs = create_chanmon_cfgs(2); let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs); // Clear shutdown_anysegwit on initiator - *node_cfgs[0].override_init_features.borrow_mut() = Some(channelmanager::provided_init_features(&test_default_channel_config()).clear_shutdown_anysegwit()); + *node_cfgs[0].override_init_features.borrow_mut() = Some( + channelmanager::provided_init_features(&test_default_channel_config()) + .clear_shutdown_anysegwit(), + ); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); 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.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"); }, @@ -829,22 +1294,39 @@ fn test_unsupported_anysegwit_upfront_shutdown_script() { let chanmon_cfgs = create_chanmon_cfgs(2); let mut node_cfgs = create_node_cfgs(2, &chanmon_cfgs); // Clear shutdown_anysegwit on responder - *node_cfgs[1].override_init_features.borrow_mut() = Some(channelmanager::provided_init_features(&test_default_channel_config()).clear_shutdown_anysegwit()); + *node_cfgs[1].override_init_features.borrow_mut() = Some( + channelmanager::provided_init_features(&test_default_channel_config()) + .clear_shutdown_anysegwit(), + ); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); 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.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"); }, @@ -861,19 +1343,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.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.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"); }, @@ -898,20 +1389,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"), } } @@ -933,20 +1427,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"), } } @@ -960,17 +1457,21 @@ fn test_unsupported_anysegwit_shutdown_script() { let user_cfgs = [None, Some(config), None]; let chanmon_cfgs = create_chanmon_cfgs(3); let mut node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - *node_cfgs[0].override_init_features.borrow_mut() = Some(channelmanager::provided_init_features(&config).clear_shutdown_anysegwit()); - *node_cfgs[1].override_init_features.borrow_mut() = Some(channelmanager::provided_init_features(&config).clear_shutdown_anysegwit()); + *node_cfgs[0].override_init_features.borrow_mut() = + Some(channelmanager::provided_init_features(&config).clear_shutdown_anysegwit()); + *node_cfgs[1].override_init_features.borrow_mut() = + Some(channelmanager::provided_init_features(&config).clear_shutdown_anysegwit()); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &user_cfgs); 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 }); @@ -986,12 +1487,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] @@ -1011,14 +1515,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] @@ -1034,17 +1539,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); } @@ -1061,16 +1573,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)); - - assert_eq!(result, Err(APIError::APIMisuseError { err: "Cannot override shutdown script for a channel with one already set".to_string() })); + 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() + }) + ); } #[derive(PartialEq)] @@ -1098,9 +1618,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); { @@ -1111,13 +1633,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")); @@ -1127,17 +1655,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::CooperativeClosure, [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::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); } if timeout_step != TimeoutStep::NoTimeout { @@ -1154,14 +1717,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_v0_p2wpkh() && - txn[0].output[1].script_pubkey.is_v0_p2wsh()) || - (txn[0].output[1].script_pubkey.is_v0_p2wpkh() && - txn[0].output[0].script_pubkey.is_v0_p2wsh())); + assert!( + (txn[0].output[0].script_pubkey.is_v0_p2wpkh() + && txn[0].output[1].script_pubkey.is_v0_p2wsh()) + || (txn[0].output[1].script_pubkey.is_v0_p2wpkh() + && txn[0].output[0].script_pubkey.is_v0_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_v0_p2wpkh()); assert!(txn[0].output[1].script_pubkey.is_v0_p2wpkh()); @@ -1201,12 +1774,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); @@ -1215,14 +1794,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1242,42 +1837,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } fn do_outbound_update_no_early_closing_signed(use_htlc: bool) { @@ -1295,16 +1934,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(); @@ -1313,19 +1951,28 @@ 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(&nodes[0].node.get_our_node_id(), &updates.commitment_signed); + nodes[1] + .node + .handle_commitment_signed(&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()); @@ -1344,7 +1991,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 (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_id).unwrap().clone(); + let (outpoint, 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(outpoint, latest_update); let as_raa_closing_signed = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1356,21 +2010,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::CooperativeClosure, [nodes[1].node.get_our_node_id()], 100000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 100000); + check_closed_event!( + nodes[0], + 1, + ClosureReason::CooperativeClosure, + [nodes[1].node.get_our_node_id()], + 100000 + ); + check_closed_event!( + nodes[1], + 1, + ClosureReason::CooperativeClosure, + [nodes[0].node.get_our_node_id()], + 100000 + ); } #[test] @@ -1394,21 +2072,38 @@ 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: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + let mut tx = Transaction { + version: 2, + 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: 1_000_000, script_pubkey: output_script.clone() }); } chans.push((temporary_channel_id, counterparty_node_id)); - } else { panic!(); } + } else { + panic!(); + } } // We should probably end up with an error for both channels, but currently we don't generate // an error for the failing channel itself. let err = "Error in transaction funding: Misuse error: No output matched the script_pubkey and value in the FundingGenerationReady event".to_string(); - let close = [ExpectedCloseEvent::from_id_reason(ChannelId::v1_from_funding_txid(tx.txid().as_ref(), 0), true, ClosureReason::ProcessingError { err })]; + let close = [ExpectedCloseEvent::from_id_reason( + ChannelId::v1_from_funding_txid(tx.txid().as_ref(), 0), + true, + ClosureReason::ProcessingError { err }, + )]; nodes[0].node.batch_funding_transaction_generated(&chans, tx).unwrap_err(); diff --git a/lightning/src/ln/wire.rs b/lightning/src/ln/wire.rs index 5087df33b83..4d11f398edb 100644 --- a/lightning/src/ln/wire.rs +++ b/lightning/src/ln/wire.rs @@ -25,14 +25,16 @@ pub trait CustomMessageReader { /// implementation and the message could be decoded, must return `Ok(Some(message))`. If the /// message type is unknown to the implementation, must return `Ok(None)`. If a decoding error /// occur, must return `Err(DecodeError::X)` where `X` details the encountered error. - fn read(&self, message_type: u16, buffer: &mut R) -> Result, msgs::DecodeError>; + fn read( + &self, message_type: u16, buffer: &mut R, + ) -> Result, msgs::DecodeError>; } // TestEq is a dummy trait which requires PartialEq when built in testing, and otherwise is // blanket-implemented for all types. #[cfg(test)] -pub trait TestEq : PartialEq {} +pub trait TestEq: PartialEq {} #[cfg(test)] impl TestEq for T {} @@ -41,13 +43,15 @@ pub(crate) trait TestEq {} #[cfg(not(test))] impl TestEq for T {} - /// A Lightning message returned by [`read`] when decoding bytes received over the wire. Each /// variant contains a message from [`msgs`] or otherwise the message type if unknown. #[allow(missing_docs)] #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] -pub(crate) enum Message where T: core::fmt::Debug + Type + TestEq { +pub(crate) enum Message +where + T: core::fmt::Debug + Type + TestEq, +{ Init(msgs::Init), Error(msgs::ErrorMessage), Warning(msgs::WarningMessage), @@ -100,7 +104,10 @@ pub(crate) enum Message where T: core::fmt::Debug + Type + TestEq { Custom(T), } -impl Writeable for Message where T: core::fmt::Debug + Type + TestEq { +impl Writeable for Message +where + T: core::fmt::Debug + Type + TestEq, +{ fn write(&self, writer: &mut W) -> Result<(), io::Error> { match self { &Message::Init(ref msg) => msg.write(writer), @@ -148,13 +155,16 @@ impl Writeable for Message where T: core::fmt::Debug + Type + TestEq { &Message::QueryChannelRange(ref msg) => msg.write(writer), &Message::ReplyChannelRange(ref msg) => msg.write(writer), &Message::GossipTimestampFilter(ref msg) => msg.write(writer), - &Message::Unknown(_) => { Ok(()) }, + &Message::Unknown(_) => Ok(()), &Message::Custom(ref msg) => msg.write(writer), } } } -impl Type for Message where T: core::fmt::Debug + Type + TestEq { +impl Type for Message +where + T: core::fmt::Debug + Type + TestEq, +{ /// Returns the type that was used to decode the message payload. fn type_id(&self) -> u16 { match self { @@ -209,7 +219,10 @@ impl Type for Message where T: core::fmt::Debug + Type + TestEq { } } -impl Message where T: core::fmt::Debug + Type + TestEq { +impl Message +where + T: core::fmt::Debug + Type + TestEq, +{ /// Returns whether the message's type is even, indicating both endpoints must support it. pub fn is_even(&self) -> bool { (self.type_id() & 1) == 0 @@ -222,8 +235,10 @@ impl Message where T: core::fmt::Debug + Type + TestEq { /// # Errors /// /// Returns an error if the message payload could not be decoded as the specified type. -pub(crate) fn read(buffer: &mut R, custom_reader: H) --> Result, (msgs::DecodeError, Option)> where +pub(crate) fn read( + buffer: &mut R, custom_reader: H, +) -> Result, (msgs::DecodeError, Option)> +where T: core::fmt::Debug + Type + Writeable, H::Target: CustomMessageReader, { @@ -231,144 +246,68 @@ pub(crate) fn read(buffer: &mut R, custom_r do_read(buffer, message_type, custom_reader).map_err(|e| (e, Some(message_type))) } -fn do_read(buffer: &mut R, message_type: u16, custom_reader: H) --> Result, msgs::DecodeError> where +fn do_read( + buffer: &mut R, message_type: u16, custom_reader: H, +) -> Result, msgs::DecodeError> +where T: core::fmt::Debug + Type + Writeable, H::Target: CustomMessageReader, { match message_type { - msgs::Init::TYPE => { - Ok(Message::Init(Readable::read(buffer)?)) - }, - msgs::ErrorMessage::TYPE => { - Ok(Message::Error(Readable::read(buffer)?)) - }, - msgs::WarningMessage::TYPE => { - Ok(Message::Warning(Readable::read(buffer)?)) - }, - msgs::Ping::TYPE => { - Ok(Message::Ping(Readable::read(buffer)?)) - }, - msgs::Pong::TYPE => { - Ok(Message::Pong(Readable::read(buffer)?)) - }, - msgs::OpenChannel::TYPE => { - Ok(Message::OpenChannel(Readable::read(buffer)?)) - }, - msgs::OpenChannelV2::TYPE => { - Ok(Message::OpenChannelV2(Readable::read(buffer)?)) - }, - msgs::AcceptChannel::TYPE => { - Ok(Message::AcceptChannel(Readable::read(buffer)?)) - }, - msgs::AcceptChannelV2::TYPE => { - Ok(Message::AcceptChannelV2(Readable::read(buffer)?)) - }, - msgs::FundingCreated::TYPE => { - Ok(Message::FundingCreated(Readable::read(buffer)?)) - }, - msgs::FundingSigned::TYPE => { - Ok(Message::FundingSigned(Readable::read(buffer)?)) - }, - msgs::Splice::TYPE => { - Ok(Message::Splice(Readable::read(buffer)?)) - }, - msgs::Stfu::TYPE => { - Ok(Message::Stfu(Readable::read(buffer)?)) - }, - msgs::SpliceAck::TYPE => { - Ok(Message::SpliceAck(Readable::read(buffer)?)) - }, - msgs::SpliceLocked::TYPE => { - Ok(Message::SpliceLocked(Readable::read(buffer)?)) - }, - msgs::TxAddInput::TYPE => { - Ok(Message::TxAddInput(Readable::read(buffer)?)) - }, - msgs::TxAddOutput::TYPE => { - Ok(Message::TxAddOutput(Readable::read(buffer)?)) - }, - msgs::TxRemoveInput::TYPE => { - Ok(Message::TxRemoveInput(Readable::read(buffer)?)) - }, - msgs::TxRemoveOutput::TYPE => { - Ok(Message::TxRemoveOutput(Readable::read(buffer)?)) - }, - msgs::TxComplete::TYPE => { - Ok(Message::TxComplete(Readable::read(buffer)?)) - }, - msgs::TxSignatures::TYPE => { - Ok(Message::TxSignatures(Readable::read(buffer)?)) - }, - msgs::TxInitRbf::TYPE => { - Ok(Message::TxInitRbf(Readable::read(buffer)?)) - }, - msgs::TxAckRbf::TYPE => { - Ok(Message::TxAckRbf(Readable::read(buffer)?)) - }, - msgs::TxAbort::TYPE => { - Ok(Message::TxAbort(Readable::read(buffer)?)) - }, - msgs::ChannelReady::TYPE => { - Ok(Message::ChannelReady(Readable::read(buffer)?)) - }, - msgs::Shutdown::TYPE => { - Ok(Message::Shutdown(Readable::read(buffer)?)) - }, - msgs::ClosingSigned::TYPE => { - Ok(Message::ClosingSigned(Readable::read(buffer)?)) - }, - msgs::OnionMessage::TYPE => { - Ok(Message::OnionMessage(Readable::read(buffer)?)) - }, - msgs::UpdateAddHTLC::TYPE => { - Ok(Message::UpdateAddHTLC(Readable::read(buffer)?)) - }, - msgs::UpdateFulfillHTLC::TYPE => { - Ok(Message::UpdateFulfillHTLC(Readable::read(buffer)?)) - }, - msgs::UpdateFailHTLC::TYPE => { - Ok(Message::UpdateFailHTLC(Readable::read(buffer)?)) - }, + msgs::Init::TYPE => Ok(Message::Init(Readable::read(buffer)?)), + msgs::ErrorMessage::TYPE => Ok(Message::Error(Readable::read(buffer)?)), + msgs::WarningMessage::TYPE => Ok(Message::Warning(Readable::read(buffer)?)), + msgs::Ping::TYPE => Ok(Message::Ping(Readable::read(buffer)?)), + msgs::Pong::TYPE => Ok(Message::Pong(Readable::read(buffer)?)), + msgs::OpenChannel::TYPE => Ok(Message::OpenChannel(Readable::read(buffer)?)), + msgs::OpenChannelV2::TYPE => Ok(Message::OpenChannelV2(Readable::read(buffer)?)), + msgs::AcceptChannel::TYPE => Ok(Message::AcceptChannel(Readable::read(buffer)?)), + msgs::AcceptChannelV2::TYPE => Ok(Message::AcceptChannelV2(Readable::read(buffer)?)), + msgs::FundingCreated::TYPE => Ok(Message::FundingCreated(Readable::read(buffer)?)), + msgs::FundingSigned::TYPE => Ok(Message::FundingSigned(Readable::read(buffer)?)), + msgs::Splice::TYPE => Ok(Message::Splice(Readable::read(buffer)?)), + msgs::Stfu::TYPE => Ok(Message::Stfu(Readable::read(buffer)?)), + msgs::SpliceAck::TYPE => Ok(Message::SpliceAck(Readable::read(buffer)?)), + msgs::SpliceLocked::TYPE => Ok(Message::SpliceLocked(Readable::read(buffer)?)), + msgs::TxAddInput::TYPE => Ok(Message::TxAddInput(Readable::read(buffer)?)), + msgs::TxAddOutput::TYPE => Ok(Message::TxAddOutput(Readable::read(buffer)?)), + msgs::TxRemoveInput::TYPE => Ok(Message::TxRemoveInput(Readable::read(buffer)?)), + msgs::TxRemoveOutput::TYPE => Ok(Message::TxRemoveOutput(Readable::read(buffer)?)), + msgs::TxComplete::TYPE => Ok(Message::TxComplete(Readable::read(buffer)?)), + msgs::TxSignatures::TYPE => Ok(Message::TxSignatures(Readable::read(buffer)?)), + msgs::TxInitRbf::TYPE => Ok(Message::TxInitRbf(Readable::read(buffer)?)), + msgs::TxAckRbf::TYPE => Ok(Message::TxAckRbf(Readable::read(buffer)?)), + msgs::TxAbort::TYPE => Ok(Message::TxAbort(Readable::read(buffer)?)), + msgs::ChannelReady::TYPE => Ok(Message::ChannelReady(Readable::read(buffer)?)), + msgs::Shutdown::TYPE => Ok(Message::Shutdown(Readable::read(buffer)?)), + msgs::ClosingSigned::TYPE => Ok(Message::ClosingSigned(Readable::read(buffer)?)), + msgs::OnionMessage::TYPE => Ok(Message::OnionMessage(Readable::read(buffer)?)), + msgs::UpdateAddHTLC::TYPE => Ok(Message::UpdateAddHTLC(Readable::read(buffer)?)), + msgs::UpdateFulfillHTLC::TYPE => Ok(Message::UpdateFulfillHTLC(Readable::read(buffer)?)), + msgs::UpdateFailHTLC::TYPE => Ok(Message::UpdateFailHTLC(Readable::read(buffer)?)), msgs::UpdateFailMalformedHTLC::TYPE => { Ok(Message::UpdateFailMalformedHTLC(Readable::read(buffer)?)) }, - msgs::CommitmentSigned::TYPE => { - Ok(Message::CommitmentSigned(Readable::read(buffer)?)) - }, - msgs::RevokeAndACK::TYPE => { - Ok(Message::RevokeAndACK(Readable::read(buffer)?)) - }, - msgs::UpdateFee::TYPE => { - Ok(Message::UpdateFee(Readable::read(buffer)?)) - }, - msgs::ChannelReestablish::TYPE => { - Ok(Message::ChannelReestablish(Readable::read(buffer)?)) - }, + msgs::CommitmentSigned::TYPE => Ok(Message::CommitmentSigned(Readable::read(buffer)?)), + msgs::RevokeAndACK::TYPE => Ok(Message::RevokeAndACK(Readable::read(buffer)?)), + msgs::UpdateFee::TYPE => Ok(Message::UpdateFee(Readable::read(buffer)?)), + msgs::ChannelReestablish::TYPE => Ok(Message::ChannelReestablish(Readable::read(buffer)?)), msgs::AnnouncementSignatures::TYPE => { Ok(Message::AnnouncementSignatures(Readable::read(buffer)?)) }, msgs::ChannelAnnouncement::TYPE => { Ok(Message::ChannelAnnouncement(Readable::read(buffer)?)) }, - msgs::NodeAnnouncement::TYPE => { - Ok(Message::NodeAnnouncement(Readable::read(buffer)?)) - }, - msgs::ChannelUpdate::TYPE => { - Ok(Message::ChannelUpdate(Readable::read(buffer)?)) - }, + msgs::NodeAnnouncement::TYPE => Ok(Message::NodeAnnouncement(Readable::read(buffer)?)), + msgs::ChannelUpdate::TYPE => Ok(Message::ChannelUpdate(Readable::read(buffer)?)), msgs::QueryShortChannelIds::TYPE => { Ok(Message::QueryShortChannelIds(Readable::read(buffer)?)) }, msgs::ReplyShortChannelIdsEnd::TYPE => { Ok(Message::ReplyShortChannelIdsEnd(Readable::read(buffer)?)) }, - msgs::QueryChannelRange::TYPE => { - Ok(Message::QueryChannelRange(Readable::read(buffer)?)) - }, - msgs::ReplyChannelRange::TYPE => { - Ok(Message::ReplyChannelRange(Readable::read(buffer)?)) - } + msgs::QueryChannelRange::TYPE => Ok(Message::QueryChannelRange(Readable::read(buffer)?)), + msgs::ReplyChannelRange::TYPE => Ok(Message::ReplyChannelRange(Readable::read(buffer)?)), msgs::GossipTimestampFilter::TYPE => { Ok(Message::GossipTimestampFilter(Readable::read(buffer)?)) }, @@ -388,7 +327,9 @@ fn do_read(buffer: &mut R, message_type: u1 /// # Errors /// /// Returns an I/O error if the write could not be completed. -pub(crate) fn write(message: &M, buffer: &mut W) -> Result<(), io::Error> { +pub(crate) fn write( + message: &M, buffer: &mut W, +) -> Result<(), io::Error> { message.type_id().write(buffer)?; message.write(buffer) } @@ -419,17 +360,29 @@ pub trait Type: core::fmt::Debug + Writeable + PartialEq { #[cfg(any(feature = "_test_utils", fuzzing, test))] impl Type for () { - fn type_id(&self) -> u16 { unreachable!(); } + fn type_id(&self) -> u16 { + unreachable!(); + } } #[cfg(test)] -impl Type for T where T: Encode { - fn type_id(&self) -> u16 { T::TYPE } +impl Type for T +where + T: Encode, +{ + fn type_id(&self) -> u16 { + T::TYPE + } } #[cfg(not(test))] -impl Type for T where T: Encode { - fn type_id(&self) -> u16 { T::TYPE } +impl Type for T +where + T: Encode, +{ + fn type_id(&self) -> u16 { + T::TYPE + } } impl Encode for msgs::Stfu { @@ -616,9 +569,9 @@ impl Encode for msgs::GossipTimestampFilter { #[cfg(test)] mod tests { use super::*; + use crate::ln::peer_handler::IgnoringMessageHandler; use crate::prelude::*; use core::convert::TryInto; - use crate::ln::peer_handler::IgnoringMessageHandler; // Big-endian wire encoding of Pong message (type = 19, byteslen = 2). const ENCODED_PONG: [u8; 6] = [0u8, 19u8, 0u8, 2u8, 0u8, 0u8]; @@ -627,35 +580,35 @@ mod tests { fn read_empty_buffer() { let buffer = []; let mut reader = io::Cursor::new(buffer); - assert!(read(&mut reader, &IgnoringMessageHandler{}).is_err()); + assert!(read(&mut reader, &IgnoringMessageHandler {}).is_err()); } #[test] fn read_incomplete_type() { let buffer = &ENCODED_PONG[..1]; let mut reader = io::Cursor::new(buffer); - assert!(read(&mut reader, &IgnoringMessageHandler{}).is_err()); + assert!(read(&mut reader, &IgnoringMessageHandler {}).is_err()); } #[test] fn read_empty_payload() { let buffer = &ENCODED_PONG[..2]; let mut reader = io::Cursor::new(buffer); - assert!(read(&mut reader, &IgnoringMessageHandler{}).is_err()); + assert!(read(&mut reader, &IgnoringMessageHandler {}).is_err()); } #[test] fn read_invalid_message() { let buffer = &ENCODED_PONG[..4]; let mut reader = io::Cursor::new(buffer); - assert!(read(&mut reader, &IgnoringMessageHandler{}).is_err()); + assert!(read(&mut reader, &IgnoringMessageHandler {}).is_err()); } #[test] fn read_known_message() { let buffer = &ENCODED_PONG[..]; let mut reader = io::Cursor::new(buffer); - let message = read(&mut reader, &IgnoringMessageHandler{}).unwrap(); + let message = read(&mut reader, &IgnoringMessageHandler {}).unwrap(); match message { Message::Pong(_) => (), _ => panic!("Expected pong message; found message type: {}", message.type_id()), @@ -666,7 +619,7 @@ mod tests { fn read_unknown_message() { let buffer = &::core::u16::MAX.to_be_bytes(); let mut reader = io::Cursor::new(buffer); - let message = read(&mut reader, &IgnoringMessageHandler{}).unwrap(); + let message = read(&mut reader, &IgnoringMessageHandler {}).unwrap(); match message { Message::Unknown(::core::u16::MAX) => (), _ => panic!("Expected message type {}; found: {}", ::core::u16::MAX, message.type_id()), @@ -692,7 +645,7 @@ mod tests { assert!(write(&message, &mut buffer).is_ok()); let mut reader = io::Cursor::new(buffer); - let decoded_message = read(&mut reader, &IgnoringMessageHandler{}).unwrap(); + let decoded_message = read(&mut reader, &IgnoringMessageHandler {}).unwrap(); match decoded_message { Message::Pong(msgs::Pong { byteslen: 2u16 }) => (), Message::Pong(msgs::Pong { byteslen }) => { @@ -724,13 +677,17 @@ mod tests { #[test] fn read_clightning_init_msg() { // Taken from c-lightning v0.8.0. - let buffer = vec![0, 16, 0, 2, 34, 0, 0, 3, 2, 170, 162, 1, 32, 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15]; + let buffer = vec![ + 0, 16, 0, 2, 34, 0, 0, 3, 2, 170, 162, 1, 32, 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, + 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, + 145, 15, + ]; check_init_msg(buffer, true); } fn check_init_msg(buffer: Vec, expect_unknown: bool) { let mut reader = io::Cursor::new(buffer); - let decoded_msg = read(&mut reader, &IgnoringMessageHandler{}).unwrap(); + let decoded_msg = read(&mut reader, &IgnoringMessageHandler {}).unwrap(); match decoded_msg { Message::Init(msgs::Init { features, .. }) => { assert!(features.supports_variable_length_onion()); @@ -740,45 +697,88 @@ mod tests { assert!(!features.requires_unknown_bits()); assert!(!features.initial_routing_sync()); }, - _ => panic!("Expected init message, found message type: {}", decoded_msg.type_id()) + _ => panic!("Expected init message, found message type: {}", decoded_msg.type_id()), } } #[test] fn read_lnd_node_announcement() { // Taken from lnd v0.9.0-beta. - let buffer = vec![1, 1, 91, 164, 146, 213, 213, 165, 21, 227, 102, 33, 105, 179, 214, 21, 221, 175, 228, 93, 57, 177, 191, 127, 107, 229, 31, 50, 21, 81, 179, 71, 39, 18, 35, 2, 89, 224, 110, 123, 66, 39, 148, 246, 177, 85, 12, 19, 70, 226, 173, 132, 156, 26, 122, 146, 71, 213, 247, 48, 93, 190, 185, 177, 12, 172, 0, 3, 2, 162, 161, 94, 103, 195, 37, 2, 37, 242, 97, 140, 2, 111, 69, 85, 39, 118, 30, 221, 99, 254, 120, 49, 103, 22, 170, 227, 111, 172, 164, 160, 49, 68, 138, 116, 16, 22, 206, 107, 51, 153, 255, 97, 108, 105, 99, 101, 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, 7, 1, 172, 21, 0, 2, 38, 7]; + let buffer = vec![ + 1, 1, 91, 164, 146, 213, 213, 165, 21, 227, 102, 33, 105, 179, 214, 21, 221, 175, 228, + 93, 57, 177, 191, 127, 107, 229, 31, 50, 21, 81, 179, 71, 39, 18, 35, 2, 89, 224, 110, + 123, 66, 39, 148, 246, 177, 85, 12, 19, 70, 226, 173, 132, 156, 26, 122, 146, 71, 213, + 247, 48, 93, 190, 185, 177, 12, 172, 0, 3, 2, 162, 161, 94, 103, 195, 37, 2, 37, 242, + 97, 140, 2, 111, 69, 85, 39, 118, 30, 221, 99, 254, 120, 49, 103, 22, 170, 227, 111, + 172, 164, 160, 49, 68, 138, 116, 16, 22, 206, 107, 51, 153, 255, 97, 108, 105, 99, 101, + 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, 7, + 1, 172, 21, 0, 2, 38, 7, + ]; let mut reader = io::Cursor::new(buffer); - let decoded_msg = read(&mut reader, &IgnoringMessageHandler{}).unwrap(); + let decoded_msg = read(&mut reader, &IgnoringMessageHandler {}).unwrap(); match decoded_msg { - Message::NodeAnnouncement(msgs::NodeAnnouncement { contents: msgs::UnsignedNodeAnnouncement { features, ..}, ..}) => { + Message::NodeAnnouncement(msgs::NodeAnnouncement { + contents: msgs::UnsignedNodeAnnouncement { features, .. }, + .. + }) => { assert!(features.supports_variable_length_onion()); assert!(features.supports_upfront_shutdown_script()); assert!(features.supports_gossip_queries()); assert!(!features.requires_unknown_bits()); }, - _ => panic!("Expected node announcement, found message type: {}", decoded_msg.type_id()) + _ => { + panic!("Expected node announcement, found message type: {}", decoded_msg.type_id()) + }, } } #[test] fn read_lnd_chan_announcement() { // Taken from lnd v0.9.0-beta. - let buffer = vec![1, 0, 82, 238, 153, 33, 128, 87, 215, 2, 28, 241, 140, 250, 98, 255, 56, 5, 79, 240, 214, 231, 172, 35, 240, 171, 44, 9, 78, 91, 8, 193, 102, 5, 17, 178, 142, 106, 180, 183, 46, 38, 217, 212, 25, 236, 69, 47, 92, 217, 181, 221, 161, 205, 121, 201, 99, 38, 158, 216, 186, 193, 230, 86, 222, 6, 206, 67, 22, 255, 137, 212, 141, 161, 62, 134, 76, 48, 241, 54, 50, 167, 187, 247, 73, 27, 74, 1, 129, 185, 197, 153, 38, 90, 255, 138, 39, 161, 102, 172, 213, 74, 107, 88, 150, 90, 0, 49, 104, 7, 182, 184, 194, 219, 181, 172, 8, 245, 65, 226, 19, 228, 101, 145, 25, 159, 52, 31, 58, 93, 53, 59, 218, 91, 37, 84, 103, 17, 74, 133, 33, 35, 2, 203, 101, 73, 19, 94, 175, 122, 46, 224, 47, 168, 128, 128, 25, 26, 25, 214, 52, 247, 43, 241, 117, 52, 206, 94, 135, 156, 52, 164, 143, 234, 58, 185, 50, 185, 140, 198, 174, 71, 65, 18, 105, 70, 131, 172, 137, 0, 164, 51, 215, 143, 117, 119, 217, 241, 197, 177, 227, 227, 170, 199, 114, 7, 218, 12, 107, 30, 191, 236, 203, 21, 61, 242, 48, 192, 90, 233, 200, 199, 111, 162, 68, 234, 54, 219, 1, 233, 66, 5, 82, 74, 84, 211, 95, 199, 245, 202, 89, 223, 102, 124, 62, 166, 253, 253, 90, 180, 118, 21, 61, 110, 37, 5, 96, 167, 0, 0, 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15, 0, 2, 65, 0, 0, 1, 0, 0, 2, 37, 242, 97, 140, 2, 111, 69, 85, 39, 118, 30, 221, 99, 254, 120, 49, 103, 22, 170, 227, 111, 172, 164, 160, 49, 68, 138, 116, 16, 22, 206, 107, 3, 54, 61, 144, 88, 171, 247, 136, 208, 99, 9, 135, 37, 201, 178, 253, 136, 0, 185, 235, 68, 160, 106, 110, 12, 46, 21, 125, 204, 18, 75, 234, 16, 3, 42, 171, 28, 52, 224, 11, 30, 30, 253, 156, 148, 175, 203, 121, 250, 111, 122, 195, 84, 122, 77, 183, 56, 135, 101, 88, 41, 60, 191, 99, 232, 85, 2, 36, 17, 156, 11, 8, 12, 189, 177, 68, 88, 28, 15, 207, 21, 179, 151, 56, 226, 158, 148, 3, 120, 113, 177, 243, 184, 17, 173, 37, 46, 222, 16]; + let buffer = vec![ + 1, 0, 82, 238, 153, 33, 128, 87, 215, 2, 28, 241, 140, 250, 98, 255, 56, 5, 79, 240, + 214, 231, 172, 35, 240, 171, 44, 9, 78, 91, 8, 193, 102, 5, 17, 178, 142, 106, 180, + 183, 46, 38, 217, 212, 25, 236, 69, 47, 92, 217, 181, 221, 161, 205, 121, 201, 99, 38, + 158, 216, 186, 193, 230, 86, 222, 6, 206, 67, 22, 255, 137, 212, 141, 161, 62, 134, 76, + 48, 241, 54, 50, 167, 187, 247, 73, 27, 74, 1, 129, 185, 197, 153, 38, 90, 255, 138, + 39, 161, 102, 172, 213, 74, 107, 88, 150, 90, 0, 49, 104, 7, 182, 184, 194, 219, 181, + 172, 8, 245, 65, 226, 19, 228, 101, 145, 25, 159, 52, 31, 58, 93, 53, 59, 218, 91, 37, + 84, 103, 17, 74, 133, 33, 35, 2, 203, 101, 73, 19, 94, 175, 122, 46, 224, 47, 168, 128, + 128, 25, 26, 25, 214, 52, 247, 43, 241, 117, 52, 206, 94, 135, 156, 52, 164, 143, 234, + 58, 185, 50, 185, 140, 198, 174, 71, 65, 18, 105, 70, 131, 172, 137, 0, 164, 51, 215, + 143, 117, 119, 217, 241, 197, 177, 227, 227, 170, 199, 114, 7, 218, 12, 107, 30, 191, + 236, 203, 21, 61, 242, 48, 192, 90, 233, 200, 199, 111, 162, 68, 234, 54, 219, 1, 233, + 66, 5, 82, 74, 84, 211, 95, 199, 245, 202, 89, 223, 102, 124, 62, 166, 253, 253, 90, + 180, 118, 21, 61, 110, 37, 5, 96, 167, 0, 0, 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, + 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, + 145, 15, 0, 2, 65, 0, 0, 1, 0, 0, 2, 37, 242, 97, 140, 2, 111, 69, 85, 39, 118, 30, + 221, 99, 254, 120, 49, 103, 22, 170, 227, 111, 172, 164, 160, 49, 68, 138, 116, 16, 22, + 206, 107, 3, 54, 61, 144, 88, 171, 247, 136, 208, 99, 9, 135, 37, 201, 178, 253, 136, + 0, 185, 235, 68, 160, 106, 110, 12, 46, 21, 125, 204, 18, 75, 234, 16, 3, 42, 171, 28, + 52, 224, 11, 30, 30, 253, 156, 148, 175, 203, 121, 250, 111, 122, 195, 84, 122, 77, + 183, 56, 135, 101, 88, 41, 60, 191, 99, 232, 85, 2, 36, 17, 156, 11, 8, 12, 189, 177, + 68, 88, 28, 15, 207, 21, 179, 151, 56, 226, 158, 148, 3, 120, 113, 177, 243, 184, 17, + 173, 37, 46, 222, 16, + ]; let mut reader = io::Cursor::new(buffer); - let decoded_msg = read(&mut reader, &IgnoringMessageHandler{}).unwrap(); + let decoded_msg = read(&mut reader, &IgnoringMessageHandler {}).unwrap(); match decoded_msg { - Message::ChannelAnnouncement(msgs::ChannelAnnouncement { contents: msgs::UnsignedChannelAnnouncement { features, ..}, ..}) => { + Message::ChannelAnnouncement(msgs::ChannelAnnouncement { + contents: msgs::UnsignedChannelAnnouncement { features, .. }, + .. + }) => { assert!(!features.requires_unknown_bits()); }, - _ => panic!("Expected node announcement, found message type: {}", decoded_msg.type_id()) + _ => { + panic!("Expected node announcement, found message type: {}", decoded_msg.type_id()) + }, } } #[derive(Eq, PartialEq, Debug)] struct TestCustomMessage {} - const CUSTOM_MESSAGE_TYPE : u16 = 9000; + const CUSTOM_MESSAGE_TYPE: u16 = 9000; impl Type for TestCustomMessage { fn type_id(&self) -> u16 { @@ -797,12 +797,10 @@ mod tests { impl CustomMessageReader for TestCustomMessageReader { type CustomMessage = TestCustomMessage; fn read( - &self, - message_type: u16, - _: &mut R + &self, message_type: u16, _: &mut R, ) -> Result, msgs::DecodeError> { if message_type == CUSTOM_MESSAGE_TYPE { - return Ok(Some(TestCustomMessage{})); + return Ok(Some(TestCustomMessage {})); } Ok(None) @@ -813,7 +811,7 @@ mod tests { fn read_custom_message() { let buffer = vec![35, 40]; let mut reader = io::Cursor::new(buffer); - let decoded_msg = read(&mut reader, &TestCustomMessageReader{}).unwrap(); + let decoded_msg = read(&mut reader, &TestCustomMessageReader {}).unwrap(); match decoded_msg { Message::Custom(custom) => { assert_eq!(custom.type_id(), CUSTOM_MESSAGE_TYPE); @@ -827,7 +825,7 @@ mod tests { fn read_with_custom_reader_unknown_message_type() { let buffer = vec![35, 42]; let mut reader = io::Cursor::new(buffer); - let decoded_msg = read(&mut reader, &TestCustomMessageReader{}).unwrap(); + let decoded_msg = read(&mut reader, &TestCustomMessageReader {}).unwrap(); match decoded_msg { Message::Unknown(_) => {}, _ => panic!("Expected unknown message, found message type: {}", decoded_msg.type_id()), @@ -838,7 +836,7 @@ mod tests { fn custom_reader_unknown_message_type() { let buffer = Vec::new(); let mut reader = io::Cursor::new(buffer); - let res = TestCustomMessageReader{}.read(CUSTOM_MESSAGE_TYPE + 1, &mut reader).unwrap(); + let res = TestCustomMessageReader {}.read(CUSTOM_MESSAGE_TYPE + 1, &mut reader).unwrap(); assert!(res.is_none()); } } diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index bb29c76164e..2a5ae5a0906 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -45,12 +45,18 @@ //! //! // Invoice for the "offer to be paid" flow. //! InvoiceRequest::try_from(bytes)? -#![cfg_attr(feature = "std", doc = " +#![cfg_attr( + feature = "std", + doc = " .respond_with(payment_paths, payment_hash)? -")] -#![cfg_attr(not(feature = "std"), doc = " +" +)] +#![cfg_attr( + not(feature = "std"), + doc = " .respond_with_no_std(payment_paths, payment_hash, core::time::Duration::from_secs(0))? -")] +" +)] //! .relative_expiry(3600) //! .allow_mpp() //! .fallback_v0_p2wpkh(&wpubkey_hash) @@ -76,12 +82,18 @@ //! // Invoice for the "offer for money" flow. //! "lnr1qcp4256ypq" //! .parse::()? -#![cfg_attr(feature = "std", doc = " +#![cfg_attr( + feature = "std", + doc = " .respond_with(payment_paths, payment_hash, pubkey)? -")] -#![cfg_attr(not(feature = "std"), doc = " +" +)] +#![cfg_attr( + not(feature = "std"), + doc = " .respond_with_no_std(payment_paths, payment_hash, pubkey, core::time::Duration::from_secs(0))? -")] +" +)] //! .relative_expiry(3600) //! .allow_mpp() //! .fallback_v0_p2wpkh(&wpubkey_hash) @@ -97,32 +109,42 @@ //! //! ``` -use bitcoin::blockdata::constants::ChainHash; -use bitcoin::hash_types::{WPubkeyHash, WScriptHash}; -use bitcoin::hashes::Hash; -use bitcoin::network::constants::Network; -use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self}; -use bitcoin::secp256k1::schnorr::Signature; -use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion}; -use bitcoin::key::TweakedPublicKey; -use core::convert::{AsRef, Infallible, TryFrom}; -use core::time::Duration; -use crate::io; use crate::blinded_path::BlindedPath; -use crate::ln::PaymentHash; +use crate::io; use crate::ln::channelmanager::PaymentId; -use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; +use crate::ln::features::{ + BlindedHopFeatures, Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures, +}; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::DecodeError; -use crate::offers::invoice_request::{INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, IV_BYTES as INVOICE_REQUEST_IV_BYTES, InvoiceRequest, InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; -use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream, WithoutSignatures, self}; -use crate::offers::offer::{Amount, OFFER_TYPES, OfferTlvStream, OfferTlvStreamRef, Quantity}; +use crate::ln::PaymentHash; +use crate::offers::invoice_request::{ + InvoiceRequest, InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef, + INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, IV_BYTES as INVOICE_REQUEST_IV_BYTES, +}; +use crate::offers::merkle::{ + self, SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream, + WithoutSignatures, +}; +use crate::offers::offer::{Amount, OfferTlvStream, OfferTlvStreamRef, Quantity, OFFER_TYPES}; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; -use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef}; -use crate::offers::refund::{IV_BYTES as REFUND_IV_BYTES, Refund, RefundContents}; +use crate::offers::payer::{PayerTlvStream, PayerTlvStreamRef, PAYER_METADATA_TYPE}; +use crate::offers::refund::{Refund, RefundContents, IV_BYTES as REFUND_IV_BYTES}; use crate::offers::signer; -use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer}; +use crate::util::ser::{ + HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer, +}; use crate::util::string::PrintableString; +use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion}; +use bitcoin::blockdata::constants::ChainHash; +use bitcoin::hash_types::{WPubkeyHash, WScriptHash}; +use bitcoin::hashes::Hash; +use bitcoin::key::TweakedPublicKey; +use bitcoin::network::constants::Network; +use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{self, KeyPair, PublicKey, Secp256k1}; +use core::convert::{AsRef, Infallible, TryFrom}; +use core::time::Duration; use crate::prelude::*; @@ -172,14 +194,18 @@ impl SigningPubkeyStrategy for DerivedSigningPubkey {} impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { pub(super) fn for_offer( invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, - created_at: Duration, payment_hash: PaymentHash + created_at: Duration, payment_hash: PaymentHash, ) -> Result { let amount_msats = Self::amount_msats(invoice_request)?; let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, ), }; @@ -187,14 +213,18 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { } pub(super) fn for_refund( - refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, created_at: Duration, - payment_hash: PaymentHash, signing_pubkey: PublicKey + refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, + created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey, ) -> Result { let amount_msats = refund.amount_msats(); let contents = InvoiceContents::ForRefund { refund: refund.contents.clone(), fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, ), }; @@ -205,14 +235,18 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { pub(super) fn for_offer_using_keys( invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, - created_at: Duration, payment_hash: PaymentHash, keys: KeyPair + created_at: Duration, payment_hash: PaymentHash, keys: KeyPair, ) -> Result { let amount_msats = Self::amount_msats(invoice_request)?; let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, ), }; @@ -220,15 +254,19 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { } pub(super) fn for_refund_using_keys( - refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, created_at: Duration, - payment_hash: PaymentHash, keys: KeyPair, + refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, + created_at: Duration, payment_hash: PaymentHash, keys: KeyPair, ) -> Result { let amount_msats = refund.amount_msats(); let signing_pubkey = keys.public_key(); let contents = InvoiceContents::ForRefund { refund: refund.contents.clone(), fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, ), }; @@ -238,15 +276,14 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { pub(crate) fn amount_msats( - invoice_request: &InvoiceRequest + invoice_request: &InvoiceRequest, ) -> Result { match invoice_request.amount_msats() { Some(amount_msats) => Ok(amount_msats), None => match invoice_request.contents.inner.offer.amount() { - Some(Amount::Bitcoin { amount_msats }) => { - amount_msats.checked_mul(invoice_request.quantity().unwrap_or(1)) - .ok_or(Bolt12SemanticError::InvalidAmount) - }, + Some(Amount::Bitcoin { amount_msats }) => amount_msats + .checked_mul(invoice_request.quantity().unwrap_or(1)) + .ok_or(Bolt12SemanticError::InvalidAmount), Some(Amount::Currency { .. }) => Err(Bolt12SemanticError::UnsupportedCurrency), None => Err(Bolt12SemanticError::MissingAmount), }, @@ -255,16 +292,22 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { fn fields( payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, created_at: Duration, - payment_hash: PaymentHash, amount_msats: u64, signing_pubkey: PublicKey + payment_hash: PaymentHash, amount_msats: u64, signing_pubkey: PublicKey, ) -> InvoiceFields { InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, - fallbacks: None, features: Bolt12InvoiceFeatures::empty(), signing_pubkey, + payment_paths, + created_at, + relative_expiry: None, + payment_hash, + amount_msats, + fallbacks: None, + features: Bolt12InvoiceFeatures::empty(), + signing_pubkey, } } fn new( - invreq_bytes: &'a Vec, contents: InvoiceContents, signing_pubkey_strategy: S + invreq_bytes: &'a Vec, contents: InvoiceContents, signing_pubkey_strategy: S, ) -> Result { if contents.fields().payment_paths.is_empty() { return Err(Bolt12SemanticError::MissingPaths); @@ -335,13 +378,15 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { /// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. It can be signed by /// [`UnsignedBolt12Invoice::sign`]. pub fn build(self) -> Result { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if self.invoice.is_offer_or_refund_expired() { return Err(Bolt12SemanticError::AlreadyExpired); } } - #[cfg(not(feature = "std"))] { + #[cfg(not(feature = "std"))] + { if self.invoice.is_offer_or_refund_expired_no_std(self.invoice.created_at()) { return Err(Bolt12SemanticError::AlreadyExpired); } @@ -355,29 +400,33 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { /// Builds a signed [`Bolt12Invoice`] after checking for valid semantics. pub fn build_and_sign( - self, secp_ctx: &Secp256k1 + self, secp_ctx: &Secp256k1, ) -> Result { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if self.invoice.is_offer_or_refund_expired() { return Err(Bolt12SemanticError::AlreadyExpired); } } - #[cfg(not(feature = "std"))] { + #[cfg(not(feature = "std"))] + { if self.invoice.is_offer_or_refund_expired_no_std(self.invoice.created_at()) { return Err(Bolt12SemanticError::AlreadyExpired); } } let InvoiceBuilder { - invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys) + invreq_bytes, + invoice, + signing_pubkey_strategy: DerivedSigningPubkey(keys), } = self; let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice); let invoice = unsigned_invoice - .sign::<_, Infallible>( - |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + .sign::<_, Infallible>(|message| { + Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) + }) .unwrap(); Ok(invoice) } @@ -424,15 +473,13 @@ impl UnsignedBolt12Invoice { /// This is not exported to bindings users as functions aren't currently mapped. pub fn sign(mut self, sign: F) -> Result> where - F: FnOnce(&Self) -> Result + F: FnOnce(&Self) -> Result, { let pubkey = self.contents.fields().signing_pubkey; let signature = merkle::sign_message(sign, &self, pubkey)?; // Append the signature TLV record to the bytes. - let signature_tlv_stream = SignatureTlvStreamRef { - signature: Some(&signature), - }; + let signature_tlv_stream = SignatureTlvStreamRef { signature: Some(&signature) }; signature_tlv_stream.write(&mut self.bytes).unwrap(); Ok(Bolt12Invoice { @@ -477,17 +524,11 @@ enum InvoiceContents { /// Contents for an [`Bolt12Invoice`] corresponding to an [`Offer`]. /// /// [`Offer`]: crate::offers::offer::Offer - ForOffer { - invoice_request: InvoiceRequestContents, - fields: InvoiceFields, - }, + ForOffer { invoice_request: InvoiceRequestContents, fields: InvoiceFields }, /// Contents for an [`Bolt12Invoice`] corresponding to a [`Refund`]. /// /// [`Refund`]: crate::offers::refund::Refund - ForRefund { - refund: RefundContents, - fields: InvoiceFields, - }, + ForRefund { refund: RefundContents, fields: InvoiceFields }, } /// Invoice-specific fields for an `invoice` message. @@ -715,7 +756,7 @@ impl Bolt12Invoice { /// Verifies that the invoice was for a request or refund created using the given key. Returns /// the associated [`PaymentId`] to use when sending the payment. pub fn verify( - &self, key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result { self.contents.verify(TlvStream::new(&self.bytes), key, secp_ctx) } @@ -723,11 +764,14 @@ impl Bolt12Invoice { pub(crate) fn as_tlv_stream(&self) -> FullInvoiceTlvStreamRef { let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream) = self.contents.as_tlv_stream(); - let signature_tlv_stream = SignatureTlvStreamRef { - signature: Some(&self.signature), - }; - (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, - signature_tlv_stream) + let signature_tlv_stream = SignatureTlvStreamRef { signature: Some(&self.signature) }; + ( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, + signature_tlv_stream, + ) } } @@ -736,8 +780,9 @@ impl InvoiceContents { #[cfg(feature = "std")] fn is_offer_or_refund_expired(&self) -> bool { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.is_expired(), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.is_expired() + }, InvoiceContents::ForRefund { refund, .. } => refund.is_expired(), } } @@ -745,17 +790,20 @@ impl InvoiceContents { #[cfg(not(feature = "std"))] fn is_offer_or_refund_expired_no_std(&self, duration_since_epoch: Duration) -> bool { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.is_expired_no_std(duration_since_epoch), - InvoiceContents::ForRefund { refund, .. } => - refund.is_expired_no_std(duration_since_epoch), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.is_expired_no_std(duration_since_epoch) + }, + InvoiceContents::ForRefund { refund, .. } => { + refund.is_expired_no_std(duration_since_epoch) + }, } } fn offer_chains(&self) -> Option> { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - Some(invoice_request.inner.offer.chains()), + InvoiceContents::ForOffer { invoice_request, .. } => { + Some(invoice_request.inner.offer.chains()) + }, InvoiceContents::ForRefund { .. } => None, } } @@ -769,16 +817,18 @@ impl InvoiceContents { fn metadata(&self) -> Option<&Vec> { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.metadata(), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.metadata() + }, InvoiceContents::ForRefund { .. } => None, } } fn amount(&self) -> Option<&Amount> { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.amount(), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.amount() + }, InvoiceContents::ForRefund { .. } => None, } } @@ -915,7 +965,7 @@ impl InvoiceContents { } else if chain == ChainHash::using_genesis_block(Network::Regtest) { Network::Regtest } else { - return Vec::new() + return Vec::new(); }; let to_valid_address = |address: &FallbackAddress| { @@ -932,7 +982,8 @@ impl InvoiceContents { Some(Address::new(network, Payload::WitnessProgram(witness_program))) }; - self.fields().fallbacks + self.fields() + .fallbacks .as_ref() .map(|fallbacks| fallbacks.iter().filter_map(to_valid_address).collect()) .unwrap_or_else(Vec::new) @@ -961,7 +1012,7 @@ impl InvoiceContents { } fn verify( - &self, tlv_stream: TlvStream<'_>, key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, tlv_stream: TlvStream<'_>, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result { let offer_records = tlv_stream.clone().range(OFFER_TYPES); let invreq_records = tlv_stream.range(INVOICE_REQUEST_TYPES).filter(|record| { @@ -1006,8 +1057,11 @@ impl InvoiceContents { impl InvoiceFields { fn as_tlv_stream(&self) -> InvoiceTlvStreamRef { let features = { - if self.features == Bolt12InvoiceFeatures::empty() { None } - else { Some(&self.features) } + if self.features == Bolt12InvoiceFeatures::empty() { + None + } else { + Some(&self.features) + } }; InvoiceTlvStreamRef { @@ -1048,12 +1102,14 @@ impl TryFrom> for UnsignedBolt12Invoice { fn try_from(bytes: Vec) -> Result { let invoice = ParsedMessage::::try_from(bytes)?; let ParsedMessage { bytes, tlv_stream } = invoice; - let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, - ) = tlv_stream; - let contents = InvoiceContents::try_from( - (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream) - )?; + let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream) = + tlv_stream; + let contents = InvoiceContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, + ))?; let tagged_hash = TaggedHash::new(SIGNATURE_TAG, &bytes); @@ -1189,15 +1245,25 @@ impl TryFrom> for Bolt12Invoice { fn try_from(invoice: ParsedMessage) -> Result { let ParsedMessage { bytes, tlv_stream } = invoice; let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, SignatureTlvStream { signature }, ) = tlv_stream; - let contents = InvoiceContents::try_from( - (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream) - )?; + let contents = InvoiceContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, + ))?; let signature = match signature { - None => return Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), + None => { + return Err(Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingSignature, + )) + }, Some(signature) => signature, }; let tagged_hash = TaggedHash::new(SIGNATURE_TAG, &bytes); @@ -1217,8 +1283,15 @@ impl TryFrom for InvoiceContents { offer_tlv_stream, invoice_request_tlv_stream, InvoiceTlvStream { - paths, blindedpay, created_at, relative_expiry, payment_hash, amount, fallbacks, - features, node_id, + paths, + blindedpay, + created_at, + relative_expiry, + payment_hash, + amount, + fallbacks, + features, + node_id, }, ) = tlv_stream; @@ -1239,9 +1312,7 @@ impl TryFrom for InvoiceContents { Some(timestamp) => Duration::from_secs(timestamp), }; - let relative_expiry = relative_expiry - .map(Into::::into) - .map(Duration::from_secs); + let relative_expiry = relative_expiry.map(Into::::into).map(Duration::from_secs); let payment_hash = match payment_hash { None => return Err(Bolt12SemanticError::MissingPaymentHash), @@ -1261,8 +1332,14 @@ impl TryFrom for InvoiceContents { }; let fields = InvoiceFields { - payment_paths, created_at, relative_expiry, payment_hash, amount_msats, fallbacks, - features, signing_pubkey, + payment_paths, + created_at, + relative_expiry, + payment_hash, + amount_msats, + fallbacks, + features, + signing_pubkey, }; match offer_tlv_stream.node_id { @@ -1271,15 +1348,19 @@ impl TryFrom for InvoiceContents { return Err(Bolt12SemanticError::InvalidSigningPubkey); } - let invoice_request = InvoiceRequestContents::try_from( - (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) - )?; + let invoice_request = InvoiceRequestContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + ))?; Ok(InvoiceContents::ForOffer { invoice_request, fields }) }, None => { - let refund = RefundContents::try_from( - (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) - )?; + let refund = RefundContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + ))?; Ok(InvoiceContents::ForRefund { refund, fields }) }, } @@ -1288,31 +1369,34 @@ impl TryFrom for InvoiceContents { #[cfg(test)] mod tests { - use super::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, FallbackAddress, FullInvoiceTlvStreamRef, InvoiceTlvStreamRef, SIGNATURE_TAG, UnsignedBolt12Invoice}; + use super::{ + Bolt12Invoice, FallbackAddress, FullInvoiceTlvStreamRef, InvoiceTlvStreamRef, + UnsignedBolt12Invoice, DEFAULT_RELATIVE_EXPIRY, SIGNATURE_TAG, + }; - use bitcoin::blockdata::constants::ChainHash; - use bitcoin::blockdata::script::ScriptBuf; - use bitcoin::hashes::Hash; - use bitcoin::network::constants::Network; - use bitcoin::secp256k1::{Message, Secp256k1, XOnlyPublicKey, self}; - use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion}; - use bitcoin::key::TweakedPublicKey; - use core::convert::TryFrom; - use core::time::Duration; use crate::blinded_path::{BlindedHop, BlindedPath}; - use crate::sign::KeyMaterial; use crate::ln::features::{Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::DecodeError; use crate::offers::invoice_request::InvoiceRequestTlvStreamRef; - use crate::offers::merkle::{SignError, SignatureTlvStreamRef, TaggedHash, self}; + use crate::offers::merkle::{self, SignError, SignatureTlvStreamRef, TaggedHash}; use crate::offers::offer::{Amount, OfferBuilder, OfferTlvStreamRef, Quantity}; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::payer::PayerTlvStreamRef; use crate::offers::refund::RefundBuilder; use crate::offers::test_utils::*; + use crate::sign::KeyMaterial; use crate::util::ser::{BigSize, Iterable, Writeable}; use crate::util::string::PrintableString; + use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion}; + use bitcoin::blockdata::constants::ChainHash; + use bitcoin::blockdata::script::ScriptBuf; + use bitcoin::hashes::Hash; + use bitcoin::key::TweakedPublicKey; + use bitcoin::network::constants::Network; + use bitcoin::secp256k1::{self, Message, Secp256k1, XOnlyPublicKey}; + use core::convert::TryFrom; + use core::time::Duration; trait ToBytes { fn to_bytes(&self) -> Vec; @@ -1337,19 +1421,28 @@ mod tests { let now = now(); let unsigned_invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths.clone(), payment_hash, now).unwrap() - .build().unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths.clone(), payment_hash, now) + .unwrap() + .build() + .unwrap(); let mut buffer = Vec::new(); unsigned_invoice.write(&mut buffer).unwrap(); assert_eq!(unsigned_invoice.bytes, buffer.as_slice()); assert_eq!(unsigned_invoice.payer_metadata(), &[1; 32]); - assert_eq!(unsigned_invoice.offer_chains(), Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)])); + assert_eq!( + unsigned_invoice.offer_chains(), + Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]) + ); assert_eq!(unsigned_invoice.metadata(), None); assert_eq!(unsigned_invoice.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(unsigned_invoice.description(), PrintableString("foo")); @@ -1391,7 +1484,10 @@ mod tests { assert_eq!(invoice.bytes, buffer.as_slice()); assert_eq!(invoice.payer_metadata(), &[1; 32]); - assert_eq!(invoice.offer_chains(), Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)])); + assert_eq!( + invoice.offer_chains(), + Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]) + ); assert_eq!(invoice.metadata(), None); assert_eq!(invoice.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(invoice.description(), PrintableString("foo")); @@ -1476,12 +1572,16 @@ mod tests { let payment_paths = payment_paths(); let payment_hash = payment_hash(); let now = now(); - let invoice = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap() + let invoice = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap() .respond_with_no_std(payment_paths.clone(), payment_hash, recipient_pubkey(), now) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -1572,10 +1672,14 @@ mod tests { if let Err(e) = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .absolute_expiry(future_expiry) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() .respond_with(payment_paths(), payment_hash()) .unwrap() .build() @@ -1586,10 +1690,13 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .absolute_expiry(past_expiry) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build_unchecked() - .sign(payer_sign).unwrap() + .sign(payer_sign) + .unwrap() .respond_with(payment_paths(), payment_hash()) .unwrap() .build() @@ -1605,9 +1712,11 @@ mod tests { let future_expiry = Duration::from_secs(u64::max_value()); let past_expiry = Duration::from_secs(0); - if let Err(e) = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + if let Err(e) = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(future_expiry) - .build().unwrap() + .build() + .unwrap() .respond_with(payment_paths(), payment_hash(), recipient_pubkey()) .unwrap() .build() @@ -1615,9 +1724,11 @@ mod tests { panic!("error building invoice: {:?}", e); } - match RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + match RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(past_expiry) - .build().unwrap() + .build() + .unwrap() .respond_with(payment_paths(), payment_hash(), recipient_pubkey()) .unwrap() .build() @@ -1644,18 +1755,31 @@ mod tests { ], }; - let offer = OfferBuilder - ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx) - .amount_msats(1000) - .path(blinded_path) - .build().unwrap(); - let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); - - if let Err(e) = invoice_request.clone() - .verify(&expanded_key, &secp_ctx).unwrap() - .respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()).unwrap() + let offer = OfferBuilder::deriving_signing_pubkey( + desc, + node_id, + &expanded_key, + &entropy, + &secp_ctx, + ) + .amount_msats(1000) + .path(blinded_path) + .build() + .unwrap(); + let invoice_request = offer + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); + + if let Err(e) = invoice_request + .clone() + .verify(&expanded_key, &secp_ctx) + .unwrap() + .respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .build_and_sign(&secp_ctx) { panic!("error building invoice: {:?}", e); @@ -1665,17 +1789,28 @@ mod tests { assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err()); let desc = "foo".to_string(); - let offer = OfferBuilder - ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx) - .amount_msats(1000) - // Omit the path so that node_id is used for the signing pubkey instead of deriving - .build().unwrap(); - let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + let offer = OfferBuilder::deriving_signing_pubkey( + desc, + node_id, + &expanded_key, + &entropy, + &secp_ctx, + ) + .amount_msats(1000) + // Omit the path so that node_id is used for the signing pubkey instead of deriving + .build() + .unwrap(); + let invoice_request = offer + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); match invoice_request - .verify(&expanded_key, &secp_ctx).unwrap() + .verify(&expanded_key, &secp_ctx) + .unwrap() .respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()) { Ok(_) => panic!("expected error"), @@ -1689,12 +1824,18 @@ mod tests { let entropy = FixedEntropy {}; let secp_ctx = Secp256k1::new(); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap(); if let Err(e) = refund .respond_using_derived_keys_no_std( - payment_paths(), payment_hash(), now(), &expanded_key, &entropy + payment_paths(), + payment_hash(), + now(), + &expanded_key, + &entropy, ) .unwrap() .build_and_sign(&secp_ctx) @@ -1710,14 +1851,21 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now) + .unwrap() .relative_expiry(one_hour.as_secs() as u32) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _) = invoice.as_tlv_stream(); #[cfg(feature = "std")] assert!(!invoice.is_expired()); @@ -1726,14 +1874,21 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now - one_hour).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now - one_hour) + .unwrap() .relative_expiry(one_hour.as_secs() as u32 - 1) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _) = invoice.as_tlv_stream(); #[cfg(feature = "std")] assert!(invoice.is_expired()); @@ -1745,14 +1900,22 @@ mod tests { fn builds_invoice_with_amount_from_request() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(1001).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(1001) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _) = invoice.as_tlv_stream(); assert_eq!(invoice.amount_msats(), 1001); assert_eq!(tlv_stream.amount, Some(1001)); @@ -1763,14 +1926,22 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .quantity(2).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .quantity(2) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _) = invoice.as_tlv_stream(); assert_eq!(invoice.amount_msats(), 2000); assert_eq!(tlv_stream.amount, Some(2000)); @@ -1778,11 +1949,15 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .quantity(u64::max_value()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .quantity(u64::max_value()) + .unwrap() .build_unchecked() - .sign(payer_sign).unwrap() + .sign(payer_sign) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), now()) { Ok(_) => panic!("expected error"), @@ -1799,16 +1974,23 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .fallback_v0_p2wsh(&script.wscript_hash()) .fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap()) .fallback_v1_p2tr_tweaked(&tweaked_pubkey) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _) = invoice.as_tlv_stream(); assert_eq!( invoice.fallbacks(), @@ -1844,14 +2026,21 @@ mod tests { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .allow_mpp() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _) = invoice.as_tlv_stream(); assert_eq!(invoice.invoice_features(), &features); assert_eq!(tlv_stream.features, Some(&features)); @@ -1861,12 +2050,18 @@ mod tests { fn fails_signing_invoice() { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() .sign(|_| Err(())) { Ok(_) => panic!("expected error"), @@ -1875,12 +2070,18 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() .sign(payer_sign) { Ok(_) => panic!("expected error"), @@ -1892,13 +2093,20 @@ mod tests { fn parses_invoice_with_payment_paths() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -1912,7 +2120,9 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)), + Err(e) => { + assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)) + }, } let mut tlv_stream = invoice.as_tlv_stream(); @@ -1920,7 +2130,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo) + ), } let empty_payment_paths = vec![]; @@ -1929,7 +2142,9 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)), + Err(e) => { + assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)) + }, } let mut payment_paths = payment_paths(); @@ -1939,7 +2154,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo) + ), } } @@ -1947,13 +2165,20 @@ mod tests { fn parses_invoice_with_created_at() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -1968,7 +2193,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingCreationTime)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingCreationTime) + ); }, } } @@ -1977,14 +2205,21 @@ mod tests { fn parses_invoice_with_relative_expiry() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .relative_expiry(3600) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -1999,13 +2234,20 @@ mod tests { fn parses_invoice_with_payment_hash() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2020,7 +2262,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaymentHash)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaymentHash) + ); }, } } @@ -2029,13 +2274,20 @@ mod tests { fn parses_invoice_with_amount() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2049,7 +2301,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ), } } @@ -2057,14 +2312,21 @@ mod tests { fn parses_invoice_with_allow_mpp() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .allow_mpp() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2086,15 +2348,18 @@ mod tests { let x_only_pubkey = XOnlyPublicKey::from_keypair(&recipient_keys()).0; let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(x_only_pubkey); - let offer = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap(); + let offer = + OfferBuilder::new("foo".into(), recipient_pubkey()).amount_msats(1000).build().unwrap(); let invoice_request = offer - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut invoice_builder = invoice_request - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .fallback_v0_p2wsh(&script.wscript_hash()) .fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap()) .fallback_v1_p2tr_tweaked(&tweaked_pubkey); @@ -2115,8 +2380,10 @@ mod tests { match Bolt12Invoice::try_from(buffer) { Ok(invoice) => { - let v1_witness_program = WitnessProgram::new(WitnessVersion::V1, vec![0u8; 33]).unwrap(); - let v2_witness_program = WitnessProgram::new(WitnessVersion::V2, vec![0u8; 40]).unwrap(); + let v1_witness_program = + WitnessProgram::new(WitnessVersion::V1, vec![0u8; 33]).unwrap(); + let v2_witness_program = + WitnessProgram::new(WitnessVersion::V2, vec![0u8; 40]).unwrap(); assert_eq!( invoice.fallbacks(), vec![ @@ -2136,13 +2403,20 @@ mod tests { fn parses_invoice_with_node_id() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2157,7 +2431,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey) + ); }, } @@ -2168,7 +2445,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidSigningPubkey) + ); }, } } @@ -2178,18 +2458,28 @@ mod tests { let mut buffer = Vec::new(); OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() .contents - .write(&mut buffer).unwrap(); + .write(&mut buffer) + .unwrap(); match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature) + ), } } @@ -2197,13 +2487,20 @@ mod tests { fn fails_parsing_invoice_with_invalid_signature() { let mut invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let last_signature_byte = invoice.bytes.last_mut().unwrap(); *last_signature_byte = last_signature_byte.wrapping_add(1); @@ -2213,7 +2510,10 @@ mod tests { match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSignature(secp256k1::Error::InvalidSignature)); + assert_eq!( + e, + Bolt12ParseError::InvalidSignature(secp256k1::Error::InvalidSignature) + ); }, } } @@ -2222,13 +2522,20 @@ mod tests { fn fails_parsing_invoice_with_extra_tlv_records() { let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut encoded_invoice = Vec::new(); invoice.write(&mut encoded_invoice).unwrap(); diff --git a/lightning/src/offers/invoice_error.rs b/lightning/src/offers/invoice_error.rs index 5476ad551b7..292546a6f11 100644 --- a/lightning/src/offers/invoice_error.rs +++ b/lightning/src/offers/invoice_error.rs @@ -51,10 +51,7 @@ pub struct ErroneousField { impl InvoiceError { /// Creates an [`InvoiceError`] with the given message. pub fn from_string(s: String) -> Self { - Self { - erroneous_field: None, - message: UntrustedString(s), - } + Self { erroneous_field: None, message: UntrustedString(s) } } } @@ -105,10 +102,7 @@ impl Readable for InvoiceError { impl From for InvoiceError { fn from(error: Bolt12SemanticError) -> Self { - InvoiceError { - erroneous_field: None, - message: UntrustedString(format!("{:?}", error)), - } + InvoiceError { erroneous_field: None, message: UntrustedString(format!("{:?}", error)) } } } @@ -117,7 +111,9 @@ mod tests { use super::{ErroneousField, InvoiceError}; use crate::ln::msgs::DecodeError; - use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, VecWriter, WithoutLength, Writeable}; + use crate::util::ser::{ + HighZeroBytesDroppedBigSize, Readable, VecWriter, WithoutLength, Writeable, + }; use crate::util::string::UntrustedString; #[test] @@ -134,7 +130,7 @@ mod tests { Ok(invoice_error) => { assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string())); assert_eq!(invoice_error.erroneous_field, None); - } + }, Err(e) => panic!("Unexpected error: {:?}", e), } } @@ -159,7 +155,7 @@ mod tests { invoice_error.erroneous_field, Some(ErroneousField { tlv_fieldnum: 42, suggested_value: Some(vec![42; 32]) }), ); - } + }, Err(e) => panic!("Unexpected error: {:?}", e), } } @@ -168,10 +164,7 @@ mod tests { fn parses_invoice_error_without_suggested_value() { let mut writer = VecWriter(Vec::new()); let invoice_error = InvoiceError { - erroneous_field: Some(ErroneousField { - tlv_fieldnum: 42, - suggested_value: None, - }), + erroneous_field: Some(ErroneousField { tlv_fieldnum: 42, suggested_value: None }), message: UntrustedString("Invalid value".to_string()), }; invoice_error.write(&mut writer).unwrap(); @@ -184,7 +177,7 @@ mod tests { invoice_error.erroneous_field, Some(ErroneousField { tlv_fieldnum: 42, suggested_value: None }), ); - } + }, Err(e) => panic!("Unexpected error: {:?}", e), } } diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index 4dd85b352f7..5fce4c1f7fa 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -54,28 +54,34 @@ //! # } //! ``` -use bitcoin::blockdata::constants::ChainHash; -use bitcoin::network::constants::Network; -use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self}; -use bitcoin::secp256k1::schnorr::Signature; -use core::convert::{AsRef, Infallible, TryFrom}; -use core::ops::Deref; -use crate::sign::EntropySource; -use crate::io; use crate::blinded_path::BlindedPath; -use crate::ln::PaymentHash; +use crate::io; use crate::ln::channelmanager::PaymentId; use crate::ln::features::InvoiceRequestFeatures; -use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce}; +use crate::ln::inbound_payment::{ExpandedKey, Nonce, IV_LEN}; use crate::ln::msgs::DecodeError; -use crate::offers::invoice::{BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}; -use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, self}; +use crate::ln::PaymentHash; +use crate::offers::invoice::{ + BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, +}; +use crate::offers::merkle::{ + self, SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, +}; use crate::offers::offer::{Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef}; -use crate::offers::parse::{Bolt12ParseError, ParsedMessage, Bolt12SemanticError}; +use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; use crate::offers::signer::{Metadata, MetadataMaterial}; -use crate::util::ser::{HighZeroBytesDroppedBigSize, SeekReadable, WithoutLength, Writeable, Writer}; +use crate::sign::EntropySource; +use crate::util::ser::{ + HighZeroBytesDroppedBigSize, SeekReadable, WithoutLength, Writeable, Writer, +}; use crate::util::string::PrintableString; +use bitcoin::blockdata::constants::ChainHash; +use bitcoin::network::constants::Network; +use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{self, KeyPair, PublicKey, Secp256k1}; +use core::convert::{AsRef, Infallible, TryFrom}; +use core::ops::Deref; use crate::prelude::*; @@ -131,7 +137,10 @@ impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, ExplicitPayerI pub(super) fn deriving_metadata( offer: &'a Offer, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES, payment_id: PaymentId, - ) -> Self where ES::Target: EntropySource { + ) -> Self + where + ES::Target: EntropySource, + { let nonce = Nonce::from_entropy_source(entropy_source); let payment_id = Some(payment_id); let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, payment_id); @@ -149,8 +158,11 @@ impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, ExplicitPayerI impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T> { pub(super) fn deriving_payer_id( offer: &'a Offer, expanded_key: &ExpandedKey, entropy_source: ES, - secp_ctx: &'b Secp256k1, payment_id: PaymentId - ) -> Self where ES::Target: EntropySource { + secp_ctx: &'b Secp256k1, payment_id: PaymentId, + ) -> Self + where + ES::Target: EntropySource, + { let nonce = Nonce::from_entropy_source(entropy_source); let payment_id = Some(payment_id); let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, payment_id); @@ -169,8 +181,13 @@ impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a fn create_contents(offer: &Offer, metadata: Metadata) -> InvoiceRequestContentsWithoutPayerId { let offer = offer.contents.clone(); InvoiceRequestContentsWithoutPayerId { - payer: PayerContents(metadata), offer, chain: None, amount_msats: None, - features: InvoiceRequestFeatures::empty(), quantity: None, payer_note: None, + payer: PayerContents(metadata), + offer, + chain: None, + amount_msats: None, + features: InvoiceRequestFeatures::empty(), + quantity: None, + payer_note: None, } } @@ -204,9 +221,9 @@ impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a /// /// [`quantity`]: Self::quantity pub fn amount_msats(mut self, amount_msats: u64) -> Result { - self.invoice_request.offer.check_amount_msats_for_quantity( - Some(amount_msats), self.invoice_request.quantity - )?; + self.invoice_request + .offer + .check_amount_msats_for_quantity(Some(amount_msats), self.invoice_request.quantity)?; self.invoice_request.amount_msats = Some(amount_msats); Ok(self) } @@ -229,11 +246,14 @@ impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a self } - fn build_with_checks(mut self) -> Result< + fn build_with_checks( + mut self, + ) -> Result< (UnsignedInvoiceRequest, Option, Option<&'b Secp256k1>), - Bolt12SemanticError + Bolt12SemanticError, > { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if self.offer.is_expired() { return Err(Bolt12SemanticError::AlreadyExpired); } @@ -254,15 +274,16 @@ impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a self.invoice_request.offer.check_quantity(self.invoice_request.quantity)?; self.invoice_request.offer.check_amount_msats_for_quantity( - self.invoice_request.amount_msats, self.invoice_request.quantity + self.invoice_request.amount_msats, + self.invoice_request.quantity, )?; Ok(self.build_without_checks()) } - fn build_without_checks(mut self) -> - (UnsignedInvoiceRequest, Option, Option<&'b Secp256k1>) - { + fn build_without_checks( + mut self, + ) -> (UnsignedInvoiceRequest, Option, Option<&'b Secp256k1>) { // Create the metadata for stateless verification of a Bolt12Invoice. let mut keys = None; let secp_ctx = self.secp_ctx.clone(); @@ -291,10 +312,7 @@ impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a debug_assert!(self.payer_id.is_some()); let payer_id = self.payer_id.unwrap(); - let invoice_request = InvoiceRequestContents { - inner: self.invoice_request, - payer_id, - }; + let invoice_request = InvoiceRequestContents { inner: self.invoice_request, payer_id }; let unsigned_invoice_request = UnsignedInvoiceRequest::new(self.offer, invoice_request); (unsigned_invoice_request, keys, secp_ctx) @@ -320,9 +338,9 @@ impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, DerivedPayerId let secp_ctx = secp_ctx.unwrap(); let keys = keys.unwrap(); let invoice_request = unsigned_invoice_request - .sign::<_, Infallible>( - |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + .sign::<_, Infallible>(|message| { + Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) + }) .unwrap(); Ok(invoice_request) } @@ -397,22 +415,16 @@ impl UnsignedInvoiceRequest { /// This is not exported to bindings users as functions are not yet mapped. pub fn sign(mut self, sign: F) -> Result> where - F: FnOnce(&Self) -> Result + F: FnOnce(&Self) -> Result, { let pubkey = self.contents.payer_id; let signature = merkle::sign_message(sign, &self, pubkey)?; // Append the signature TLV record to the bytes. - let signature_tlv_stream = SignatureTlvStreamRef { - signature: Some(&signature), - }; + let signature_tlv_stream = SignatureTlvStreamRef { signature: Some(&signature) }; signature_tlv_stream.write(&mut self.bytes).unwrap(); - Ok(InvoiceRequest { - bytes: self.bytes, - contents: self.contents, - signature, - }) + Ok(InvoiceRequest { bytes: self.bytes, contents: self.contents, signature }) } } @@ -548,7 +560,7 @@ impl InvoiceRequest { /// [`Duration`]: core::time::Duration #[cfg(feature = "std")] pub fn respond_with( - &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash + &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, ) -> Result, Bolt12SemanticError> { let created_at = std::time::SystemTime::now() .duration_since(std::time::SystemTime::UNIX_EPOCH) @@ -584,7 +596,7 @@ impl InvoiceRequest { /// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey pub fn respond_with_no_std( &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, - created_at: core::time::Duration + created_at: core::time::Duration, ) -> Result, Bolt12SemanticError> { if self.invoice_request_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); @@ -599,21 +611,16 @@ impl InvoiceRequest { /// /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn verify( - self, key: &ExpandedKey, secp_ctx: &Secp256k1 + self, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result { let keys = self.contents.inner.offer.verify(&self.bytes, key, secp_ctx)?; - Ok(VerifiedInvoiceRequest { - inner: self, - keys, - }) + Ok(VerifiedInvoiceRequest { inner: self, keys }) } pub(crate) fn as_tlv_stream(&self) -> FullInvoiceRequestTlvStreamRef { let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) = self.contents.as_tlv_stream(); - let signature_tlv_stream = SignatureTlvStreamRef { - signature: Some(&self.signature), - }; + let signature_tlv_stream = SignatureTlvStreamRef { signature: Some(&self.signature) }; (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, signature_tlv_stream) } } @@ -632,7 +639,7 @@ impl VerifiedInvoiceRequest { /// [`Duration`]: core::time::Duration #[cfg(feature = "std")] pub fn respond_with( - &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash + &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, ) -> Result, Bolt12SemanticError> { self.inner.respond_with(payment_paths, payment_hash) } @@ -644,7 +651,7 @@ impl VerifiedInvoiceRequest { /// This is not exported to bindings users as builder patterns don't map outside of move semantics. pub fn respond_with_no_std( &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, - created_at: core::time::Duration + created_at: core::time::Duration, ) -> Result, Bolt12SemanticError> { self.inner.respond_with_no_std(payment_paths, payment_hash, created_at) } @@ -660,7 +667,7 @@ impl VerifiedInvoiceRequest { /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice #[cfg(feature = "std")] pub fn respond_using_derived_keys( - &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash + &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, ) -> Result, Bolt12SemanticError> { let created_at = std::time::SystemTime::now() .duration_since(std::time::SystemTime::UNIX_EPOCH) @@ -680,7 +687,7 @@ impl VerifiedInvoiceRequest { /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn respond_using_derived_keys_no_std( &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, - created_at: core::time::Duration + created_at: core::time::Duration, ) -> Result, Bolt12SemanticError> { if self.inner.invoice_request_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); @@ -692,7 +699,11 @@ impl VerifiedInvoiceRequest { }; InvoiceBuilder::for_offer_using_keys( - &self.inner, payment_paths, created_at, payment_hash, keys + &self.inner, + payment_paths, + created_at, + payment_hash, + keys, ) } } @@ -727,8 +738,7 @@ impl InvoiceRequestContents { } pub(super) fn payer_note(&self) -> Option { - self.inner.payer_note.as_ref() - .map(|payer_note| PrintableString(payer_note.as_str())) + self.inner.payer_note.as_ref().map(|payer_note| PrintableString(payer_note.as_str())) } pub(super) fn as_tlv_stream(&self) -> PartialInvoiceRequestTlvStreamRef { @@ -748,15 +758,16 @@ impl InvoiceRequestContentsWithoutPayerId { } pub(super) fn as_tlv_stream(&self) -> PartialInvoiceRequestTlvStreamRef { - let payer = PayerTlvStreamRef { - metadata: self.payer.0.as_bytes(), - }; + let payer = PayerTlvStreamRef { metadata: self.payer.0.as_bytes() }; let offer = self.offer.as_tlv_stream(); let features = { - if self.features == InvoiceRequestFeatures::empty() { None } - else { Some(&self.features) } + if self.features == InvoiceRequestFeatures::empty() { + None + } else { + Some(&self.features) + } }; let invoice_request = InvoiceRequestTlvStreamRef { @@ -830,11 +841,8 @@ impl SeekReadable for FullInvoiceRequestTlvStream { type PartialInvoiceRequestTlvStream = (PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream); -type PartialInvoiceRequestTlvStreamRef<'a> = ( - PayerTlvStreamRef<'a>, - OfferTlvStreamRef<'a>, - InvoiceRequestTlvStreamRef<'a>, -); +type PartialInvoiceRequestTlvStreamRef<'a> = + (PayerTlvStreamRef<'a>, OfferTlvStreamRef<'a>, InvoiceRequestTlvStreamRef<'a>); impl TryFrom> for UnsignedInvoiceRequest { type Error = Bolt12ParseError; @@ -842,12 +850,12 @@ impl TryFrom> for UnsignedInvoiceRequest { fn try_from(bytes: Vec) -> Result { let invoice_request = ParsedMessage::::try_from(bytes)?; let ParsedMessage { bytes, tlv_stream } = invoice_request; - let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, - ) = tlv_stream; - let contents = InvoiceRequestContents::try_from( - (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) - )?; + let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) = tlv_stream; + let contents = InvoiceRequestContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + ))?; let tagged_hash = TaggedHash::new(SIGNATURE_TAG, &bytes); @@ -862,15 +870,23 @@ impl TryFrom> for InvoiceRequest { let invoice_request = ParsedMessage::::try_from(bytes)?; let ParsedMessage { bytes, tlv_stream } = invoice_request; let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, SignatureTlvStream { signature }, ) = tlv_stream; - let contents = InvoiceRequestContents::try_from( - (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) - )?; + let contents = InvoiceRequestContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + ))?; let signature = match signature { - None => return Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), + None => { + return Err(Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingSignature, + )) + }, Some(signature) => signature, }; let message = TaggedHash::new(SIGNATURE_TAG, &bytes); @@ -916,7 +932,13 @@ impl TryFrom for InvoiceRequestContents { Ok(InvoiceRequestContents { inner: InvoiceRequestContentsWithoutPayerId { - payer, offer, chain, amount_msats: amount, features, quantity, payer_note, + payer, + offer, + chain, + amount_msats: amount, + features, + quantity, + payer_note, }, payer_id, }) @@ -925,45 +947,56 @@ impl TryFrom for InvoiceRequestContents { #[cfg(test)] mod tests { - use super::{InvoiceRequest, InvoiceRequestTlvStreamRef, SIGNATURE_TAG, UnsignedInvoiceRequest}; + use super::{ + InvoiceRequest, InvoiceRequestTlvStreamRef, UnsignedInvoiceRequest, SIGNATURE_TAG, + }; - use bitcoin::blockdata::constants::ChainHash; - use bitcoin::network::constants::Network; - use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey, self}; - use core::convert::{Infallible, TryFrom}; - use core::num::NonZeroU64; - #[cfg(feature = "std")] - use core::time::Duration; - use crate::sign::KeyMaterial; use crate::ln::channelmanager::PaymentId; use crate::ln::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; use crate::offers::invoice::{Bolt12Invoice, SIGNATURE_TAG as INVOICE_SIGNATURE_TAG}; - use crate::offers::merkle::{SignError, SignatureTlvStreamRef, TaggedHash, self}; + use crate::offers::merkle::{self, SignError, SignatureTlvStreamRef, TaggedHash}; use crate::offers::offer::{Amount, OfferBuilder, OfferTlvStreamRef, Quantity}; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::payer::PayerTlvStreamRef; use crate::offers::test_utils::*; + use crate::sign::KeyMaterial; use crate::util::ser::{BigSize, Writeable}; use crate::util::string::PrintableString; + use bitcoin::blockdata::constants::ChainHash; + use bitcoin::network::constants::Network; + use bitcoin::secp256k1::{self, KeyPair, Secp256k1, SecretKey}; + use core::convert::{Infallible, TryFrom}; + use core::num::NonZeroU64; + #[cfg(feature = "std")] + use core::time::Duration; #[test] fn builds_invoice_request_with_defaults() { let unsigned_invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap(); let mut buffer = Vec::new(); unsigned_invoice_request.write(&mut buffer).unwrap(); assert_eq!(unsigned_invoice_request.bytes, buffer.as_slice()); assert_eq!(unsigned_invoice_request.payer_metadata(), &[1; 32]); - assert_eq!(unsigned_invoice_request.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]); + assert_eq!( + unsigned_invoice_request.chains(), + vec![ChainHash::using_genesis_block(Network::Bitcoin)] + ); assert_eq!(unsigned_invoice_request.metadata(), None); - assert_eq!(unsigned_invoice_request.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 })); + assert_eq!( + unsigned_invoice_request.amount(), + Some(&Amount::Bitcoin { amount_msats: 1000 }) + ); assert_eq!(unsigned_invoice_request.description(), PrintableString("foo")); assert_eq!(unsigned_invoice_request.offer_features(), &OfferFeatures::empty()); assert_eq!(unsigned_invoice_request.absolute_expiry(), None); @@ -971,9 +1004,15 @@ mod tests { assert_eq!(unsigned_invoice_request.issuer(), None); assert_eq!(unsigned_invoice_request.supported_quantity(), Quantity::One); assert_eq!(unsigned_invoice_request.signing_pubkey(), recipient_pubkey()); - assert_eq!(unsigned_invoice_request.chain(), ChainHash::using_genesis_block(Network::Bitcoin)); + assert_eq!( + unsigned_invoice_request.chain(), + ChainHash::using_genesis_block(Network::Bitcoin) + ); assert_eq!(unsigned_invoice_request.amount_msats(), None); - assert_eq!(unsigned_invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty()); + assert_eq!( + unsigned_invoice_request.invoice_request_features(), + &InvoiceRequestFeatures::empty() + ); assert_eq!(unsigned_invoice_request.quantity(), None); assert_eq!(unsigned_invoice_request.payer_id(), payer_pubkey()); assert_eq!(unsigned_invoice_request.payer_note(), None); @@ -993,7 +1032,10 @@ mod tests { assert_eq!(invoice_request.bytes, buffer.as_slice()); assert_eq!(invoice_request.payer_metadata(), &[1; 32]); - assert_eq!(invoice_request.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]); + assert_eq!( + invoice_request.chains(), + vec![ChainHash::using_genesis_block(Network::Bitcoin)] + ); assert_eq!(invoice_request.metadata(), None); assert_eq!(invoice_request.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(invoice_request.description(), PrintableString("foo")); @@ -1011,7 +1053,9 @@ mod tests { assert_eq!(invoice_request.payer_note(), None); let message = TaggedHash::new(SIGNATURE_TAG, &invoice_request.bytes); - assert!(merkle::verify_signature(&invoice_request.signature, &message, payer_pubkey()).is_ok()); + assert!( + merkle::verify_signature(&invoice_request.signature, &message, payer_pubkey()).is_ok() + ); assert_eq!( invoice_request.as_tlv_stream(), @@ -1056,8 +1100,10 @@ mod tests { if let Err(e) = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .absolute_expiry(future_expiry) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build() { panic!("error building invoice_request: {:?}", e); @@ -1066,8 +1112,10 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .absolute_expiry(past_expiry) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build() { Ok(_) => panic!("expected error"), @@ -1083,20 +1131,24 @@ mod tests { let secp_ctx = Secp256k1::new(); let payment_id = PaymentId([1; 32]); - let offer = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap(); + let offer = + OfferBuilder::new("foo".into(), recipient_pubkey()).amount_msats(1000).build().unwrap(); let invoice_request = offer .request_invoice_deriving_metadata(payer_id, &expanded_key, &entropy, payment_id) .unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); assert_eq!(invoice_request.payer_id(), payer_pubkey()); - let invoice = invoice_request.respond_with_no_std(payment_paths(), payment_hash(), now()) + let invoice = invoice_request + .respond_with_no_std(payment_paths(), payment_hash(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); match invoice.verify(&expanded_key, &secp_ctx) { Ok(payment_id) => assert_eq!(payment_id, PaymentId([1; 32])), Err(()) => panic!("verification failed"), @@ -1104,8 +1156,11 @@ mod tests { // Fails verification with altered fields let ( - payer_tlv_stream, offer_tlv_stream, mut invoice_request_tlv_stream, - mut invoice_tlv_stream, mut signature_tlv_stream + payer_tlv_stream, + offer_tlv_stream, + mut invoice_request_tlv_stream, + mut invoice_tlv_stream, + mut signature_tlv_stream, ) = invoice.as_tlv_stream(); invoice_request_tlv_stream.amount = Some(2000); invoice_tlv_stream.amount = Some(2000); @@ -1127,8 +1182,11 @@ mod tests { // Fails verification with altered metadata let ( - mut payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, - mut signature_tlv_stream + mut payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, + mut signature_tlv_stream, ) = invoice.as_tlv_stream(); let metadata = payer_tlv_stream.metadata.unwrap().iter().copied().rev().collect(); payer_tlv_stream.metadata = Some(&metadata); @@ -1156,19 +1214,21 @@ mod tests { let secp_ctx = Secp256k1::new(); let payment_id = PaymentId([1; 32]); - let offer = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap(); + let offer = + OfferBuilder::new("foo".into(), recipient_pubkey()).amount_msats(1000).build().unwrap(); let invoice_request = offer .request_invoice_deriving_payer_id(&expanded_key, &entropy, &secp_ctx, payment_id) .unwrap() .build_and_sign() .unwrap(); - let invoice = invoice_request.respond_with_no_std(payment_paths(), payment_hash(), now()) + let invoice = invoice_request + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .sign(recipient_sign) + .unwrap(); match invoice.verify(&expanded_key, &secp_ctx) { Ok(payment_id) => assert_eq!(payment_id, PaymentId([1; 32])), Err(()) => panic!("verification failed"), @@ -1176,8 +1236,11 @@ mod tests { // Fails verification with altered fields let ( - payer_tlv_stream, offer_tlv_stream, mut invoice_request_tlv_stream, - mut invoice_tlv_stream, mut signature_tlv_stream + payer_tlv_stream, + offer_tlv_stream, + mut invoice_request_tlv_stream, + mut invoice_tlv_stream, + mut signature_tlv_stream, ) = invoice.as_tlv_stream(); invoice_request_tlv_stream.amount = Some(2000); invoice_tlv_stream.amount = Some(2000); @@ -1199,8 +1262,11 @@ mod tests { // Fails verification with altered payer id let ( - payer_tlv_stream, offer_tlv_stream, mut invoice_request_tlv_stream, invoice_tlv_stream, - mut signature_tlv_stream + payer_tlv_stream, + offer_tlv_stream, + mut invoice_request_tlv_stream, + invoice_tlv_stream, + mut signature_tlv_stream, ) = invoice.as_tlv_stream(); let payer_id = pubkey(1); invoice_request_tlv_stream.payer_id = Some(&payer_id); @@ -1228,11 +1294,16 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .chain(Network::Bitcoin).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), mainnet); assert_eq!(tlv_stream.chain, None); @@ -1240,11 +1311,16 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .chain(Network::Testnet).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .chain(Network::Testnet) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); @@ -1253,11 +1329,16 @@ mod tests { .amount_msats(1000) .chain(Network::Bitcoin) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .chain(Network::Bitcoin).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), mainnet); assert_eq!(tlv_stream.chain, None); @@ -1266,12 +1347,18 @@ mod tests { .amount_msats(1000) .chain(Network::Bitcoin) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .chain(Network::Bitcoin).unwrap() - .chain(Network::Testnet).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .chain(Network::Testnet) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); @@ -1279,8 +1366,10 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .chain(Network::Bitcoin) { Ok(_) => panic!("expected error"), @@ -1290,8 +1379,10 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build() { Ok(_) => panic!("expected error"), @@ -1303,42 +1394,60 @@ mod tests { fn builds_invoice_request_with_amount() { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(1000).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(1000) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.amount_msats(), Some(1000)); assert_eq!(tlv_stream.amount, Some(1000)); let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(1001).unwrap() - .amount_msats(1000).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(1001) + .unwrap() + .amount_msats(1000) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.amount_msats(), Some(1000)); assert_eq!(tlv_stream.amount, Some(1000)); let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(1001).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(1001) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.amount_msats(), Some(1001)); assert_eq!(tlv_stream.amount, Some(1001)); match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .amount_msats(999) { Ok(_) => panic!("expected error"), @@ -1348,9 +1457,12 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .quantity(2).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .quantity(2) + .unwrap() .amount_msats(1000) { Ok(_) => panic!("expected error"), @@ -1359,8 +1471,10 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .amount_msats(MAX_VALUE_MSAT + 1) { Ok(_) => panic!("expected error"), @@ -1370,10 +1484,14 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(1000).unwrap() - .quantity(2).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(1000) + .unwrap() + .quantity(2) + .unwrap() .build() { Ok(_) => panic!("expected error"), @@ -1381,8 +1499,10 @@ mod tests { } match OfferBuilder::new("foo".into(), recipient_pubkey()) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build() { Ok(_) => panic!("expected error"), @@ -1392,9 +1512,12 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .quantity(u64::max_value()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .quantity(u64::max_value()) + .unwrap() .build() { Ok(_) => panic!("expected error"), @@ -1406,23 +1529,31 @@ mod tests { fn builds_invoice_request_with_features() { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::unknown()); assert_eq!(tlv_stream.features, Some(&InvoiceRequestFeatures::unknown())); let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) .features_unchecked(InvoiceRequestFeatures::empty()) - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty()); assert_eq!(tlv_stream.features, None); @@ -1436,10 +1567,14 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.quantity(), None); assert_eq!(tlv_stream.quantity, None); @@ -1447,9 +1582,12 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(2_000).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(2_000) + .unwrap() .quantity(2) { Ok(_) => panic!("expected error"), @@ -1459,12 +1597,18 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(10_000).unwrap() - .quantity(10).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(10_000) + .unwrap() + .quantity(10) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.amount_msats(), Some(10_000)); assert_eq!(tlv_stream.amount, Some(10_000)); @@ -1472,9 +1616,12 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(11_000).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(11_000) + .unwrap() .quantity(11) { Ok(_) => panic!("expected error"), @@ -1484,12 +1631,18 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(2_000).unwrap() - .quantity(2).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(2_000) + .unwrap() + .quantity(2) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.amount_msats(), Some(2_000)); assert_eq!(tlv_stream.amount, Some(2_000)); @@ -1497,8 +1650,10 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build() { Ok(_) => panic!("expected error"), @@ -1508,8 +1663,10 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(one)) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build() { Ok(_) => panic!("expected error"), @@ -1521,23 +1678,31 @@ mod tests { fn builds_invoice_request_with_payer_note() { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .payer_note("bar".into()) - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.payer_note(), Some(PrintableString("bar"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("bar"))); let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .payer_note("bar".into()) .payer_note("baz".into()) - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let (_, _, tlv_stream, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.payer_note(), Some(PrintableString("baz"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("baz"))); @@ -1547,9 +1712,12 @@ mod tests { fn fails_signing_invoice_request() { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() .sign(|_| Err(())) { Ok(_) => panic!("expected error"), @@ -1558,9 +1726,12 @@ mod tests { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() .sign(recipient_sign) { Ok(_) => panic!("expected error"), @@ -1572,11 +1743,15 @@ mod tests { fn fails_responding_with_unknown_required_features() { match OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![42; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![42; 32], payer_pubkey()) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) - .build().unwrap() - .sign(payer_sign).unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), now()) { Ok(_) => panic!("expected error"), @@ -1588,10 +1763,14 @@ mod tests { fn parses_invoice_request_with_metadata() { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1605,11 +1784,16 @@ mod tests { fn parses_invoice_request_with_chain() { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .chain(Network::Bitcoin).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1620,18 +1804,24 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .chain_unchecked(Network::Testnet) .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedChain)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedChain) + ), } } @@ -1639,10 +1829,14 @@ mod tests { fn parses_invoice_request_with_amount() { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1652,11 +1846,16 @@ mod tests { } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(1000).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(1000) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1666,41 +1865,55 @@ mod tests { } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ), } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .amount_msats_unchecked(999) .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InsufficientAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InsufficientAmount) + ), } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount(Amount::Currency { iso4217_code: *b"USD", amount: 1000 }) .build_unchecked() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1708,25 +1921,35 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedCurrency)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedCurrency) + ); }, } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .quantity(u64::max_value()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .quantity(u64::max_value()) + .unwrap() .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ), } } @@ -1738,10 +1961,14 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1753,12 +1980,16 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(2_000).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(2_000) + .unwrap() .quantity_unchecked(2) .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1766,19 +1997,28 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity) + ); }, } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(10_000).unwrap() - .quantity(10).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(10_000) + .unwrap() + .quantity(10) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1790,30 +2030,43 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(11_000).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(11_000) + .unwrap() .quantity_unchecked(11) .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidQuantity)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidQuantity) + ), } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .amount_msats(2_000).unwrap() - .quantity(2).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .amount_msats(2_000) + .unwrap() + .quantity(2) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -1825,43 +2078,54 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity) + ), } let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(one)) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() .build_unchecked() - .sign(payer_sign).unwrap(); + .sign(payer_sign) + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity) + ), } } #[test] fn fails_parsing_invoice_request_without_metadata() { - let offer = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap(); - let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap(); + let offer = + OfferBuilder::new("foo".into(), recipient_pubkey()).amount_msats(1000).build().unwrap(); + let unsigned_invoice_request = + offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap().build().unwrap(); let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream(); tlv_stream.0.metadata = None; @@ -1871,18 +2135,20 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata) + ); }, } } #[test] fn fails_parsing_invoice_request_without_payer_id() { - let offer = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap(); - let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap(); + let offer = + OfferBuilder::new("foo".into(), recipient_pubkey()).amount_msats(1000).build().unwrap(); + let unsigned_invoice_request = + offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap().build().unwrap(); let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream(); tlv_stream.2.payer_id = None; @@ -1891,17 +2157,19 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerId)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerId) + ), } } #[test] fn fails_parsing_invoice_request_without_node_id() { - let offer = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap(); - let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap(); + let offer = + OfferBuilder::new("foo".into(), recipient_pubkey()).amount_msats(1000).build().unwrap(); + let unsigned_invoice_request = + offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap().build().unwrap(); let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream(); tlv_stream.1.node_id = None; @@ -1911,7 +2179,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey) + ); }, } } @@ -1921,15 +2192,22 @@ mod tests { let mut buffer = Vec::new(); OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() .contents - .write(&mut buffer).unwrap(); + .write(&mut buffer) + .unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature) + ), } } @@ -1937,10 +2215,14 @@ mod tests { fn fails_parsing_invoice_request_with_invalid_signature() { let mut invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); let last_signature_byte = invoice_request.bytes.last_mut().unwrap(); *last_signature_byte = last_signature_byte.wrapping_add(1); @@ -1950,7 +2232,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSignature(secp256k1::Error::InvalidSignature)); + assert_eq!( + e, + Bolt12ParseError::InvalidSignature(secp256k1::Error::InvalidSignature) + ); }, } } @@ -1961,12 +2246,15 @@ mod tests { let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let invoice_request = OfferBuilder::new("foo".into(), keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], keys.public_key()).unwrap() - .build().unwrap() - .sign::<_, Infallible>( - |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + .build() + .unwrap() + .request_invoice(vec![1; 32], keys.public_key()) + .unwrap() + .build() + .unwrap() + .sign::<_, Infallible>(|message| { + Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) + }) .unwrap(); let mut encoded_invoice_request = Vec::new(); diff --git a/lightning/src/offers/merkle.rs b/lightning/src/offers/merkle.rs index ced3b08b7c2..dd8fad92bcc 100644 --- a/lightning/src/offers/merkle.rs +++ b/lightning/src/offers/merkle.rs @@ -9,12 +9,12 @@ //! Tagged hashes for use in signature calculation and verification. -use bitcoin::hashes::{Hash, HashEngine, sha256}; -use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, self}; -use bitcoin::secp256k1::schnorr::Signature; -use core::convert::AsRef; use crate::io; use crate::util::ser::{BigSize, Readable, Writeable, Writer}; +use bitcoin::hashes::{sha256, Hash, HashEngine}; +use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{self, Message, PublicKey, Secp256k1}; +use core::convert::AsRef; use crate::prelude::*; @@ -44,12 +44,9 @@ impl TaggedHash { pub(super) fn new(tag: &'static str, tlv_stream: &[u8]) -> Self { let tag_hash = sha256::Hash::hash(tag.as_bytes()); let merkle_root = root_hash(tlv_stream); - let digest = Message::from_slice(tagged_hash(tag_hash, merkle_root).as_byte_array()).unwrap(); - Self { - tag, - merkle_root, - digest, - } + let digest = + Message::from_slice(tagged_hash(tag_hash, merkle_root).as_byte_array()).unwrap(); + Self { tag, merkle_root, digest } } /// Returns the digest to sign. @@ -198,9 +195,7 @@ pub(super) struct TlvStream<'a> { impl<'a> TlvStream<'a> { pub fn new(data: &'a [u8]) -> Self { - Self { - data: io::Cursor::new(data), - } + Self { data: io::Cursor::new(data) } } pub fn range(self, types: T) -> impl core::iter::Iterator> @@ -270,36 +265,62 @@ impl<'a> Writeable for WithoutSignatures<'a> { #[cfg(test)] mod tests { - use super::{SIGNATURE_TYPES, TlvStream, WithoutSignatures}; + use super::{TlvStream, WithoutSignatures, SIGNATURE_TYPES}; - use bitcoin::hashes::{Hash, sha256}; - use bitcoin::hashes::hex::FromHex; - use bitcoin::secp256k1::{KeyPair, Message, Secp256k1, SecretKey}; - use bitcoin::secp256k1::schnorr::Signature; - use core::convert::Infallible; - use crate::offers::offer::{Amount, OfferBuilder}; use crate::offers::invoice_request::InvoiceRequest; + use crate::offers::offer::{Amount, OfferBuilder}; use crate::offers::parse::Bech32Encode; use crate::offers::test_utils::{payer_pubkey, recipient_pubkey}; use crate::util::ser::Writeable; + use bitcoin::hashes::hex::FromHex; + use bitcoin::hashes::{sha256, Hash}; + use bitcoin::secp256k1::schnorr::Signature; + use bitcoin::secp256k1::{KeyPair, Message, Secp256k1, SecretKey}; + use core::convert::Infallible; #[test] fn calculates_merkle_root_hash() { // BOLT 12 test vectors - macro_rules! tlv1 { () => { "010203e8" } } - macro_rules! tlv2 { () => { "02080000010000020003" } } + macro_rules! tlv1 { + () => { + "010203e8" + }; + } + macro_rules! tlv2 { + () => { + "02080000010000020003" + }; + } macro_rules! tlv3 { () => { "03310266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c0351800000000000000010000000000000002" } } assert_eq!( super::root_hash(&>::from_hex(tlv1!()).unwrap()), - sha256::Hash::from_slice(&>::from_hex("b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93").unwrap()).unwrap(), + sha256::Hash::from_slice( + &>::from_hex( + "b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93" + ) + .unwrap() + ) + .unwrap(), ); assert_eq!( super::root_hash(&>::from_hex(concat!(tlv1!(), tlv2!())).unwrap()), - sha256::Hash::from_slice(&>::from_hex("c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1").unwrap()).unwrap(), + sha256::Hash::from_slice( + &>::from_hex( + "c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1" + ) + .unwrap() + ) + .unwrap(), ); assert_eq!( super::root_hash(&>::from_hex(concat!(tlv1!(), tlv2!(), tlv3!())).unwrap()), - sha256::Hash::from_slice(&>::from_hex("ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d").unwrap()).unwrap(), + sha256::Hash::from_slice( + &>::from_hex( + "ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d" + ) + .unwrap() + ) + .unwrap(), ); } @@ -307,11 +328,23 @@ mod tests { fn calculates_merkle_root_hash_from_invoice_request() { let secp_ctx = Secp256k1::new(); let recipient_pubkey = { - let secret_key = SecretKey::from_slice(&>::from_hex("4141414141414141414141414141414141414141414141414141414141414141").unwrap()).unwrap(); + let secret_key = SecretKey::from_slice( + &>::from_hex( + "4141414141414141414141414141414141414141414141414141414141414141", + ) + .unwrap(), + ) + .unwrap(); KeyPair::from_secret_key(&secp_ctx, &secret_key).public_key() }; let payer_keys = { - let secret_key = SecretKey::from_slice(&>::from_hex("4242424242424242424242424242424242424242424242424242424242424242").unwrap()).unwrap(); + let secret_key = SecretKey::from_slice( + &>::from_hex( + "4242424242424242424242424242424242424242424242424242424242424242", + ) + .unwrap(), + ) + .unwrap(); KeyPair::from_secret_key(&secp_ctx, &secret_key) }; @@ -319,11 +352,12 @@ mod tests { let invoice_request = OfferBuilder::new("A Mathematical Treatise".into(), recipient_pubkey) .amount(Amount::Currency { iso4217_code: *b"USD", amount: 100 }) .build_unchecked() - .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap() + .request_invoice(vec![0; 8], payer_keys.public_key()) + .unwrap() .build_unchecked() - .sign::<_, Infallible>( - |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys)) - ) + .sign::<_, Infallible>(|message| { + Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys)) + }) .unwrap(); assert_eq!( invoice_request.to_string(), @@ -331,7 +365,13 @@ mod tests { ); assert_eq!( super::root_hash(&invoice_request.bytes[..]), - sha256::Hash::from_slice(&>::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624").unwrap()).unwrap(), + sha256::Hash::from_slice( + &>::from_hex( + "608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624" + ) + .unwrap() + ) + .unwrap(), ); assert_eq!( invoice_request.signature(), @@ -339,24 +379,28 @@ mod tests { ); } - #[test] - fn compute_tagged_hash() { - let unsigned_invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .payer_note("bar".into()) - .build().unwrap(); - - // Simply test that we can grab the tag and merkle root exposed by the accessor - // functions, then use them to succesfully compute a tagged hash. - let tagged_hash = unsigned_invoice_request.as_ref(); - let expected_digest = unsigned_invoice_request.as_ref().as_digest(); - let tag = sha256::Hash::hash(tagged_hash.tag().as_bytes()); - let actual_digest = Message::from_slice(super::tagged_hash(tag, tagged_hash.merkle_root()).as_byte_array()) - .unwrap(); - assert_eq!(*expected_digest, actual_digest); - } + #[test] + fn compute_tagged_hash() { + let unsigned_invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey()) + .amount_msats(1000) + .build() + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .payer_note("bar".into()) + .build() + .unwrap(); + + // Simply test that we can grab the tag and merkle root exposed by the accessor + // functions, then use them to succesfully compute a tagged hash. + let tagged_hash = unsigned_invoice_request.as_ref(); + let expected_digest = unsigned_invoice_request.as_ref().as_digest(); + let tag = sha256::Hash::hash(tagged_hash.tag().as_bytes()); + let actual_digest = + Message::from_slice(super::tagged_hash(tag, tagged_hash.merkle_root()).as_byte_array()) + .unwrap(); + assert_eq!(*expected_digest, actual_digest); + } #[test] fn skips_encoding_signature_tlv_records() { @@ -373,11 +417,12 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey) .amount_msats(100) .build_unchecked() - .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap() + .request_invoice(vec![0; 8], payer_keys.public_key()) + .unwrap() .build_unchecked() - .sign::<_, Infallible>( - |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys)) - ) + .sign::<_, Infallible>(|message| { + Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys)) + }) .unwrap(); let mut bytes_without_signature = Vec::new(); @@ -405,14 +450,16 @@ mod tests { let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey) .amount_msats(100) .build_unchecked() - .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap() + .request_invoice(vec![0; 8], payer_keys.public_key()) + .unwrap() .build_unchecked() - .sign::<_, Infallible>( - |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys)) - ) + .sign::<_, Infallible>(|message| { + Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys)) + }) .unwrap(); - let tlv_stream = TlvStream::new(&invoice_request.bytes).range(0..1) + let tlv_stream = TlvStream::new(&invoice_request.bytes) + .range(0..1) .chain(TlvStream::new(&invoice_request.bytes).range(1..80)) .chain(TlvStream::new(&invoice_request.bytes).range(80..160)) .chain(TlvStream::new(&invoice_request.bytes).range(160..240)) diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 802813fd180..5b32ed89bf0 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -76,27 +76,27 @@ //! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager //! [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder -use bitcoin::blockdata::constants::ChainHash; -use bitcoin::network::constants::Network; -use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self}; -use core::convert::TryFrom; -use core::num::NonZeroU64; -use core::ops::Deref; -use core::str::FromStr; -use core::time::Duration; -use crate::sign::EntropySource; -use crate::io; use crate::blinded_path::BlindedPath; +use crate::io; use crate::ln::channelmanager::PaymentId; use crate::ln::features::OfferFeatures; -use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce}; +use crate::ln::inbound_payment::{ExpandedKey, Nonce, IV_LEN}; use crate::ln::msgs::MAX_VALUE_MSAT; use crate::offers::invoice_request::{DerivedPayerId, ExplicitPayerId, InvoiceRequestBuilder}; use crate::offers::merkle::TlvStream; use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; -use crate::offers::signer::{Metadata, MetadataMaterial, self}; +use crate::offers::signer::{self, Metadata, MetadataMaterial}; +use crate::sign::EntropySource; use crate::util::ser::{HighZeroBytesDroppedBigSize, WithoutLength, Writeable, Writer}; use crate::util::string::PrintableString; +use bitcoin::blockdata::constants::ChainHash; +use bitcoin::network::constants::Network; +use bitcoin::secp256k1::{self, KeyPair, PublicKey, Secp256k1}; +use core::convert::TryFrom; +use core::num::NonZeroU64; +use core::ops::Deref; +use core::str::FromStr; +use core::time::Duration; use crate::prelude::*; @@ -153,9 +153,16 @@ impl<'a> OfferBuilder<'a, ExplicitMetadata, secp256k1::SignOnly> { pub fn new(description: String, signing_pubkey: PublicKey) -> Self { OfferBuilder { offer: OfferContents { - chains: None, metadata: None, amount: None, description, - features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None, - supported_quantity: Quantity::One, signing_pubkey, + chains: None, + metadata: None, + amount: None, + description, + features: OfferFeatures::empty(), + absolute_expiry: None, + issuer: None, + paths: None, + supported_quantity: Quantity::One, + signing_pubkey, }, metadata_strategy: core::marker::PhantomData, secp_ctx: None, @@ -185,16 +192,26 @@ impl<'a, T: secp256k1::Signing> OfferBuilder<'a, DerivedMetadata, T> { /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey pub fn deriving_signing_pubkey( description: String, node_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES, - secp_ctx: &'a Secp256k1 - ) -> Self where ES::Target: EntropySource { + secp_ctx: &'a Secp256k1, + ) -> Self + where + ES::Target: EntropySource, + { let nonce = Nonce::from_entropy_source(entropy_source); let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, None); let metadata = Metadata::DerivedSigningPubkey(derivation_material); OfferBuilder { offer: OfferContents { - chains: None, metadata: Some(metadata), amount: None, description, - features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None, - supported_quantity: Quantity::One, signing_pubkey: node_id, + chains: None, + metadata: Some(metadata), + amount: None, + description, + features: OfferFeatures::empty(), + absolute_expiry: None, + issuer: None, + paths: None, + supported_quantity: Quantity::One, + signing_pubkey: node_id, }, metadata_strategy: core::marker::PhantomData, secp_ctx: Some(secp_ctx), @@ -509,7 +526,7 @@ impl Offer { /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey pub fn request_invoice_deriving_payer_id<'a, 'b, ES: Deref, T: secp256k1::Signing>( &'a self, expanded_key: &ExpandedKey, entropy_source: ES, secp_ctx: &'b Secp256k1, - payment_id: PaymentId + payment_id: PaymentId, ) -> Result, Bolt12SemanticError> where ES::Target: EntropySource, @@ -519,7 +536,11 @@ impl Offer { } Ok(InvoiceRequestBuilder::deriving_payer_id( - self, expanded_key, entropy_source, secp_ctx, payment_id + self, + expanded_key, + entropy_source, + secp_ctx, + payment_id, )) } @@ -533,7 +554,7 @@ impl Offer { /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id pub fn request_invoice_deriving_metadata( &self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES, - payment_id: PaymentId + payment_id: PaymentId, ) -> Result, Bolt12SemanticError> where ES::Target: EntropySource, @@ -543,7 +564,11 @@ impl Offer { } Ok(InvoiceRequestBuilder::deriving_metadata( - self, payer_id, expanded_key, entropy_source, payment_id + self, + payer_id, + expanded_key, + entropy_source, + payment_id, )) } @@ -563,7 +588,7 @@ impl Offer { /// /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest pub fn request_invoice( - &self, metadata: Vec, payer_id: PublicKey + &self, metadata: Vec, payer_id: PublicKey, ) -> Result, Bolt12SemanticError> { if self.offer_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); @@ -640,7 +665,7 @@ impl OfferContents { } pub(super) fn check_amount_msats_for_quantity( - &self, amount_msats: Option, quantity: Option + &self, amount_msats: Option, quantity: Option, ) -> Result<(), Bolt12SemanticError> { let offer_amount_msats = match self.amount { None => 0, @@ -649,7 +674,8 @@ impl OfferContents { }; if !self.expects_quantity() || quantity.is_some() { - let expected_amount_msats = offer_amount_msats.checked_mul(quantity.unwrap_or(1)) + let expected_amount_msats = offer_amount_msats + .checked_mul(quantity.unwrap_or(1)) .ok_or(Bolt12SemanticError::InvalidAmount)?; let amount_msats = amount_msats.unwrap_or(expected_amount_msats); @@ -703,21 +729,25 @@ impl OfferContents { /// Verifies that the offer metadata was produced from the offer in the TLV stream. pub(super) fn verify( - &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result, ()> { match self.metadata() { Some(metadata) => { - let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| { - match record.r#type { + let tlv_stream = + TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| match record.r#type { OFFER_METADATA_TYPE => false, OFFER_NODE_ID_TYPE => { !self.metadata.as_ref().unwrap().derives_recipient_keys() }, _ => true, - } - }); + }); signer::verify_recipient_metadata( - metadata, key, IV_BYTES, self.signing_pubkey(), tlv_stream, secp_ctx + metadata, + key, + IV_BYTES, + self.signing_pubkey(), + tlv_stream, + secp_ctx, ) }, None => Err(()), @@ -728,13 +758,15 @@ impl OfferContents { let (currency, amount) = match &self.amount { None => (None, None), Some(Amount::Bitcoin { amount_msats }) => (None, Some(*amount_msats)), - Some(Amount::Currency { iso4217_code, amount }) => ( - Some(iso4217_code), Some(*amount) - ), + Some(Amount::Currency { iso4217_code, amount }) => (Some(iso4217_code), Some(*amount)), }; let features = { - if self.features == OfferFeatures::empty() { None } else { Some(&self.features) } + if self.features == OfferFeatures::empty() { + None + } else { + Some(&self.features) + } }; OfferTlvStreamRef { @@ -862,8 +894,17 @@ impl TryFrom for OfferContents { fn try_from(tlv_stream: OfferTlvStream) -> Result { let OfferTlvStream { - chains, metadata, currency, amount, description, features, absolute_expiry, paths, - issuer, quantity_max, node_id, + chains, + metadata, + currency, + amount, + description, + features, + absolute_expiry, + paths, + issuer, + quantity_max, + node_id, } = tlv_stream; let metadata = metadata.map(|metadata| Metadata::Bytes(metadata)); @@ -885,8 +926,8 @@ impl TryFrom for OfferContents { let features = features.unwrap_or_else(OfferFeatures::empty); - let absolute_expiry = absolute_expiry - .map(|seconds_from_epoch| Duration::from_secs(seconds_from_epoch)); + let absolute_expiry = + absolute_expiry.map(|seconds_from_epoch| Duration::from_secs(seconds_from_epoch)); let supported_quantity = match quantity_max { None => Quantity::One, @@ -900,8 +941,16 @@ impl TryFrom for OfferContents { }; Ok(OfferContents { - chains, metadata, amount, description, features, absolute_expiry, issuer, paths, - supported_quantity, signing_pubkey, + chains, + metadata, + amount, + description, + features, + absolute_expiry, + issuer, + paths, + supported_quantity, + signing_pubkey, }) } } @@ -916,21 +965,21 @@ impl core::fmt::Display for Offer { mod tests { use super::{Amount, Offer, OfferBuilder, OfferTlvStreamRef, Quantity}; - use bitcoin::blockdata::constants::ChainHash; - use bitcoin::network::constants::Network; - use bitcoin::secp256k1::Secp256k1; - use core::convert::TryFrom; - use core::num::NonZeroU64; - use core::time::Duration; use crate::blinded_path::{BlindedHop, BlindedPath}; - use crate::sign::KeyMaterial; use crate::ln::features::OfferFeatures; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::test_utils::*; + use crate::sign::KeyMaterial; use crate::util::ser::{BigSize, Writeable}; use crate::util::string::PrintableString; + use bitcoin::blockdata::constants::ChainHash; + use bitcoin::network::constants::Network; + use bitcoin::secp256k1::Secp256k1; + use core::convert::TryFrom; + use core::num::NonZeroU64; + use core::time::Duration; #[test] fn builds_offer_with_defaults() { @@ -981,18 +1030,14 @@ mod tests { let mainnet = ChainHash::using_genesis_block(Network::Bitcoin); let testnet = ChainHash::using_genesis_block(Network::Testnet); - let offer = OfferBuilder::new("foo".into(), pubkey(42)) - .chain(Network::Bitcoin) - .build() - .unwrap(); + let offer = + OfferBuilder::new("foo".into(), pubkey(42)).chain(Network::Bitcoin).build().unwrap(); assert!(offer.supports_chain(mainnet)); assert_eq!(offer.chains(), vec![mainnet]); assert_eq!(offer.as_tlv_stream().chains, None); - let offer = OfferBuilder::new("foo".into(), pubkey(42)) - .chain(Network::Testnet) - .build() - .unwrap(); + let offer = + OfferBuilder::new("foo".into(), pubkey(42)).chain(Network::Testnet).build().unwrap(); assert!(offer.supports_chain(testnet)); assert_eq!(offer.chains(), vec![testnet]); assert_eq!(offer.as_tlv_stream().chains, Some(&vec![testnet])); @@ -1020,15 +1065,18 @@ mod tests { #[test] fn builds_offer_with_metadata() { let offer = OfferBuilder::new("foo".into(), pubkey(42)) - .metadata(vec![42; 32]).unwrap() + .metadata(vec![42; 32]) + .unwrap() .build() .unwrap(); assert_eq!(offer.metadata(), Some(&vec![42; 32])); assert_eq!(offer.as_tlv_stream().metadata, Some(&vec![42; 32])); let offer = OfferBuilder::new("foo".into(), pubkey(42)) - .metadata(vec![42; 32]).unwrap() - .metadata(vec![43; 32]).unwrap() + .metadata(vec![42; 32]) + .unwrap() + .metadata(vec![43; 32]) + .unwrap() .build() .unwrap(); assert_eq!(offer.metadata(), Some(&vec![43; 32])); @@ -1043,15 +1091,25 @@ mod tests { let entropy = FixedEntropy {}; let secp_ctx = Secp256k1::new(); - let offer = OfferBuilder - ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx) - .amount_msats(1000) - .build().unwrap(); + let offer = OfferBuilder::deriving_signing_pubkey( + desc, + node_id, + &expanded_key, + &entropy, + &secp_ctx, + ) + .amount_msats(1000) + .build() + .unwrap(); assert_eq!(offer.signing_pubkey(), node_id); - let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + let invoice_request = offer + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok()); // Fails verification with altered offer field @@ -1061,10 +1119,14 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err()); // Fails verification with altered metadata @@ -1075,10 +1137,14 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err()); } @@ -1099,16 +1165,26 @@ mod tests { ], }; - let offer = OfferBuilder - ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx) - .amount_msats(1000) - .path(blinded_path) - .build().unwrap(); + let offer = OfferBuilder::deriving_signing_pubkey( + desc, + node_id, + &expanded_key, + &entropy, + &secp_ctx, + ) + .amount_msats(1000) + .path(blinded_path) + .build() + .unwrap(); assert_ne!(offer.signing_pubkey(), node_id); - let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + let invoice_request = offer + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok()); // Fails verification with altered offer field @@ -1118,10 +1194,14 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err()); // Fails verification with altered signing pubkey @@ -1132,10 +1212,14 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap(); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(vec![1; 32], payer_pubkey()) + .unwrap() + .build() + .unwrap() + .sign(payer_sign) + .unwrap(); assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err()); } @@ -1144,17 +1228,13 @@ mod tests { let bitcoin_amount = Amount::Bitcoin { amount_msats: 1000 }; let currency_amount = Amount::Currency { iso4217_code: *b"USD", amount: 10 }; - let offer = OfferBuilder::new("foo".into(), pubkey(42)) - .amount_msats(1000) - .build() - .unwrap(); + let offer = OfferBuilder::new("foo".into(), pubkey(42)).amount_msats(1000).build().unwrap(); let tlv_stream = offer.as_tlv_stream(); assert_eq!(offer.amount(), Some(&bitcoin_amount)); assert_eq!(tlv_stream.amount, Some(1000)); assert_eq!(tlv_stream.currency, None); - let builder = OfferBuilder::new("foo".into(), pubkey(42)) - .amount(currency_amount.clone()); + let builder = OfferBuilder::new("foo".into(), pubkey(42)).amount(currency_amount.clone()); let tlv_stream = builder.offer.as_tlv_stream(); assert_eq!(builder.offer.amount, Some(currency_amount.clone())); assert_eq!(tlv_stream.amount, Some(10)); @@ -1262,10 +1342,8 @@ mod tests { #[test] fn builds_offer_with_issuer() { - let offer = OfferBuilder::new("foo".into(), pubkey(42)) - .issuer("bar".into()) - .build() - .unwrap(); + let offer = + OfferBuilder::new("foo".into(), pubkey(42)).issuer("bar".into()).build().unwrap(); assert_eq!(offer.issuer(), Some(PrintableString("bar"))); assert_eq!(offer.as_tlv_stream().issuer, Some(&String::from("bar"))); @@ -1329,7 +1407,8 @@ mod tests { fn fails_requesting_invoice_with_unknown_required_features() { match OfferBuilder::new("foo".into(), pubkey(42)) .features_unchecked(OfferFeatures::unknown()) - .build().unwrap() + .build() + .unwrap() .request_invoice(vec![1; 32], pubkey(43)) { Ok(_) => panic!("expected error"), @@ -1379,7 +1458,10 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ), } let mut tlv_stream = offer.as_tlv_stream(); @@ -1391,7 +1473,10 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ), } } @@ -1411,7 +1496,10 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription) + ); }, } } @@ -1501,7 +1589,10 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey) + ); }, } } @@ -1590,7 +1681,8 @@ mod bolt12_tests { fn fails_parsing_bech32_encoded_offers() { // Malformed: fields out of order assert_eq!( - "lno1zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszpgz5znzfgdzs".parse::(), + "lno1zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszpgz5znzfgdzs" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); @@ -1632,19 +1724,22 @@ mod bolt12_tests { // Malformed: invalid offer_chains length assert_eq!( - "lno1qgqszzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1qgqszzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); // Malformed: truncated currency UTF-8 assert_eq!( - "lno1qcqcqzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1qcqcqzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); // Malformed: invalid currency UTF-8 assert_eq!( - "lno1qcpgqsg2q4q5cj2rg5tzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg".parse::(), + "lno1qcpgqsg2q4q5cj2rg5tzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); @@ -1662,7 +1757,8 @@ mod bolt12_tests { // Malformed: truncated offer_paths assert_eq!( - "lno1pgz5znzfgdz3qqgpzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1pgz5znzfgdz3qqgpzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); @@ -1698,19 +1794,22 @@ mod bolt12_tests { // Malformed: truncated issuer UTF-8 assert_eq!( - "lno1pgz5znzfgdz3yqvqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1pgz5znzfgdz3yqvqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); // Malformed: invalid issuer UTF-8 assert_eq!( - "lno1pgz5znzfgdz3yq5qgytzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg".parse::(), + "lno1pgz5znzfgdz3yq5qgytzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); // Malformed: invalid offer_node_id assert_eq!( - "lno1pgz5znzfgdz3vggzqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvps".parse::(), + "lno1pgz5znzfgdz3vggzqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvps" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); diff --git a/lightning/src/offers/parse.rs b/lightning/src/offers/parse.rs index 400cf51a294..52bffc5e29f 100644 --- a/lightning/src/offers/parse.rs +++ b/lightning/src/offers/parse.rs @@ -9,12 +9,12 @@ //! Parsing and formatting for bech32 message encoding. -use bitcoin::bech32; -use bitcoin::secp256k1; -use core::convert::TryFrom; use crate::io; use crate::ln::msgs::DecodeError; use crate::util::ser::SeekReadable; +use bitcoin::bech32; +use bitcoin::secp256k1; +use core::convert::TryFrom; use crate::prelude::*; @@ -25,16 +25,16 @@ pub(super) use sealed::Bech32Encode; pub use sealed::Bech32Encode; mod sealed { + use super::Bolt12ParseError; use bitcoin::bech32; use bitcoin::bech32::{FromBase32, ToBase32}; use core::convert::TryFrom; use core::fmt; - use super::Bolt12ParseError; use crate::prelude::*; /// Indicates a message can be encoded using bech32. - pub trait Bech32Encode: AsRef<[u8]> + TryFrom, Error=Bolt12ParseError> { + pub trait Bech32Encode: AsRef<[u8]> + TryFrom, Error = Bolt12ParseError> { /// Human readable part of the message's bech32 encoding. const BECH32_HRP: &'static str; @@ -69,7 +69,8 @@ mod sealed { /// Formats the message using bech32-encoding. fn fmt_bech32_str(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { bech32::encode_without_checksum_to_fmt(f, Self::BECH32_HRP, self.as_ref().to_base32()) - .expect("HRP is invalid").unwrap(); + .expect("HRP is invalid") + .unwrap(); Ok(()) } @@ -275,9 +276,9 @@ mod bolt12_tests { #[cfg(test)] mod tests { use super::Bolt12ParseError; - use bitcoin::bech32; use crate::ln::msgs::DecodeError; use crate::offers::offer::Offer; + use bitcoin::bech32; #[test] fn fails_parsing_bech32_encoded_offer_with_invalid_hrp() { diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index ba3ab1d1ef3..994c2279ffb 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -81,29 +81,31 @@ //! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager //! [`ChannelManager::create_refund_builder`]: crate::ln::channelmanager::ChannelManager::create_refund_builder -use bitcoin::blockdata::constants::ChainHash; -use bitcoin::network::constants::Network; -use bitcoin::secp256k1::{PublicKey, Secp256k1, self}; -use core::convert::TryFrom; -use core::ops::Deref; -use core::str::FromStr; -use core::time::Duration; -use crate::sign::EntropySource; -use crate::io; use crate::blinded_path::BlindedPath; -use crate::ln::PaymentHash; +use crate::io; use crate::ln::channelmanager::PaymentId; use crate::ln::features::InvoiceRequestFeatures; -use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce}; +use crate::ln::inbound_payment::{ExpandedKey, Nonce, IV_LEN}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; -use crate::offers::invoice::{BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}; +use crate::ln::PaymentHash; +use crate::offers::invoice::{ + BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, +}; use crate::offers::invoice_request::{InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; use crate::offers::offer::{OfferTlvStream, OfferTlvStreamRef}; use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; -use crate::offers::signer::{Metadata, MetadataMaterial, self}; +use crate::offers::signer::{self, Metadata, MetadataMaterial}; +use crate::sign::EntropySource; use crate::util::ser::{SeekReadable, WithoutLength, Writeable, Writer}; use crate::util::string::PrintableString; +use bitcoin::blockdata::constants::ChainHash; +use bitcoin::network::constants::Network; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; +use core::convert::TryFrom; +use core::ops::Deref; +use core::str::FromStr; +use core::time::Duration; use crate::prelude::*; @@ -139,7 +141,7 @@ impl<'a> RefundBuilder<'a, secp256k1::SignOnly> { /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [`ChannelManager::create_refund_builder`]: crate::ln::channelmanager::ChannelManager::create_refund_builder pub fn new( - description: String, metadata: Vec, payer_id: PublicKey, amount_msats: u64 + description: String, metadata: Vec, payer_id: PublicKey, amount_msats: u64, ) -> Result { if amount_msats > MAX_VALUE_MSAT { return Err(Bolt12SemanticError::InvalidAmount); @@ -148,9 +150,17 @@ impl<'a> RefundBuilder<'a, secp256k1::SignOnly> { let metadata = Metadata::Bytes(metadata); Ok(Self { refund: RefundContents { - payer: PayerContents(metadata), description, absolute_expiry: None, issuer: None, - paths: None, chain: None, amount_msats, features: InvoiceRequestFeatures::empty(), - quantity: None, payer_id, payer_note: None, + payer: PayerContents(metadata), + description, + absolute_expiry: None, + issuer: None, + paths: None, + chain: None, + amount_msats, + features: InvoiceRequestFeatures::empty(), + quantity: None, + payer_id, + payer_note: None, }, secp_ctx: None, }) @@ -173,8 +183,11 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey pub fn deriving_payer_id( description: String, node_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES, - secp_ctx: &'a Secp256k1, amount_msats: u64, payment_id: PaymentId - ) -> Result where ES::Target: EntropySource { + secp_ctx: &'a Secp256k1, amount_msats: u64, payment_id: PaymentId, + ) -> Result + where + ES::Target: EntropySource, + { if amount_msats > MAX_VALUE_MSAT { return Err(Bolt12SemanticError::InvalidAmount); } @@ -185,9 +198,17 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { let metadata = Metadata::DerivedSigningPubkey(derivation_material); Ok(Self { refund: RefundContents { - payer: PayerContents(metadata), description, absolute_expiry: None, issuer: None, - paths: None, chain: None, amount_msats, features: InvoiceRequestFeatures::empty(), - quantity: None, payer_id: node_id, payer_note: None, + payer: PayerContents(metadata), + description, + absolute_expiry: None, + issuer: None, + paths: None, + chain: None, + amount_msats, + features: InvoiceRequestFeatures::empty(), + quantity: None, + payer_id: node_id, + payer_note: None, }, secp_ctx: Some(secp_ctx), }) @@ -469,7 +490,7 @@ impl Refund { /// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at pub fn respond_with_no_std( &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, - signing_pubkey: PublicKey, created_at: Duration + signing_pubkey: PublicKey, created_at: Duration, ) -> Result, Bolt12SemanticError> { if self.features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); @@ -489,7 +510,7 @@ impl Refund { #[cfg(feature = "std")] pub fn respond_using_derived_keys( &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, - expanded_key: &ExpandedKey, entropy_source: ES + expanded_key: &ExpandedKey, entropy_source: ES, ) -> Result, Bolt12SemanticError> where ES::Target: EntropySource, @@ -499,7 +520,11 @@ impl Refund { .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH"); self.respond_using_derived_keys_no_std( - payment_paths, payment_hash, created_at, expanded_key, entropy_source + payment_paths, + payment_hash, + created_at, + expanded_key, + entropy_source, ) } @@ -513,7 +538,7 @@ impl Refund { /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn respond_using_derived_keys_no_std( &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, - created_at: core::time::Duration, expanded_key: &ExpandedKey, entropy_source: ES + created_at: core::time::Duration, expanded_key: &ExpandedKey, entropy_source: ES, ) -> Result, Bolt12SemanticError> where ES::Target: EntropySource, @@ -614,9 +639,7 @@ impl RefundContents { } pub(super) fn as_tlv_stream(&self) -> RefundTlvStreamRef { - let payer = PayerTlvStreamRef { - metadata: self.payer.0.as_bytes(), - }; + let payer = PayerTlvStreamRef { metadata: self.payer.0.as_bytes() }; let offer = OfferTlvStreamRef { chains: None, @@ -633,8 +656,11 @@ impl RefundContents { }; let features = { - if self.features == InvoiceRequestFeatures::empty() { None } - else { Some(&self.features) } + if self.features == InvoiceRequestFeatures::empty() { + None + } else { + Some(&self.features) + } }; let invoice_request = InvoiceRequestTlvStreamRef { @@ -664,11 +690,8 @@ impl Writeable for RefundContents { type RefundTlvStream = (PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream); -type RefundTlvStreamRef<'a> = ( - PayerTlvStreamRef<'a>, - OfferTlvStreamRef<'a>, - InvoiceRequestTlvStreamRef<'a>, -); +type RefundTlvStreamRef<'a> = + (PayerTlvStreamRef<'a>, OfferTlvStreamRef<'a>, InvoiceRequestTlvStreamRef<'a>); impl SeekReadable for RefundTlvStream { fn read(r: &mut R) -> Result { @@ -711,8 +734,17 @@ impl TryFrom for RefundContents { let ( PayerTlvStream { metadata: payer_metadata }, OfferTlvStream { - chains, metadata, currency, amount: offer_amount, description, - features: offer_features, absolute_expiry, paths, issuer, quantity_max, node_id, + chains, + metadata, + currency, + amount: offer_amount, + description, + features: offer_features, + absolute_expiry, + paths, + issuer, + quantity_max, + node_id, }, InvoiceRequestTlvStream { chain, amount, features, quantity, payer_id, payer_note }, ) = tlv_stream; @@ -769,8 +801,17 @@ impl TryFrom for RefundContents { }; Ok(RefundContents { - payer, description, absolute_expiry, issuer, paths, chain, amount_msats, features, - quantity, payer_id, payer_note, + payer, + description, + absolute_expiry, + issuer, + paths, + chain, + amount_msats, + features, + quantity, + payer_id, + payer_note, }) } } @@ -785,13 +826,7 @@ impl core::fmt::Display for Refund { mod tests { use super::{Refund, RefundBuilder, RefundTlvStreamRef}; - use bitcoin::blockdata::constants::ChainHash; - use bitcoin::network::constants::Network; - use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey}; - use core::convert::TryFrom; - use core::time::Duration; use crate::blinded_path::{BlindedHop, BlindedPath}; - use crate::sign::KeyMaterial; use crate::ln::channelmanager::PaymentId; use crate::ln::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::ln::inbound_payment::ExpandedKey; @@ -801,8 +836,14 @@ mod tests { use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::payer::PayerTlvStreamRef; use crate::offers::test_utils::*; + use crate::sign::KeyMaterial; use crate::util::ser::{BigSize, Writeable}; use crate::util::string::PrintableString; + use bitcoin::blockdata::constants::ChainHash; + use bitcoin::network::constants::Network; + use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey}; + use core::convert::TryFrom; + use core::time::Duration; trait ToBytes { fn to_bytes(&self) -> Vec; @@ -818,8 +859,10 @@ mod tests { #[test] fn builds_refund_with_defaults() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap(); let mut buffer = Vec::new(); refund.write(&mut buffer).unwrap(); @@ -888,18 +931,28 @@ mod tests { let secp_ctx = Secp256k1::new(); let payment_id = PaymentId([1; 32]); - let refund = RefundBuilder - ::deriving_payer_id(desc, node_id, &expanded_key, &entropy, &secp_ctx, 1000, payment_id) - .unwrap() - .build().unwrap(); + let refund = RefundBuilder::deriving_payer_id( + desc, + node_id, + &expanded_key, + &entropy, + &secp_ctx, + 1000, + payment_id, + ) + .unwrap() + .build() + .unwrap(); assert_eq!(refund.payer_id(), node_id); // Fails verification with altered fields let invoice = refund .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); match invoice.verify(&expanded_key, &secp_ctx) { Ok(payment_id) => assert_eq!(payment_id, PaymentId([1; 32])), Err(()) => panic!("verification failed"), @@ -911,11 +964,14 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify(&expanded_key, &secp_ctx).is_err()); // Fails verification with altered metadata @@ -926,11 +982,14 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify(&expanded_key, &secp_ctx).is_err()); } @@ -952,18 +1011,28 @@ mod tests { ], }; - let refund = RefundBuilder - ::deriving_payer_id(desc, node_id, &expanded_key, &entropy, &secp_ctx, 1000, payment_id) - .unwrap() - .path(blinded_path) - .build().unwrap(); + let refund = RefundBuilder::deriving_payer_id( + desc, + node_id, + &expanded_key, + &entropy, + &secp_ctx, + 1000, + payment_id, + ) + .unwrap() + .path(blinded_path) + .build() + .unwrap(); assert_ne!(refund.payer_id(), node_id); let invoice = refund .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); match invoice.verify(&expanded_key, &secp_ctx) { Ok(payment_id) => assert_eq!(payment_id, PaymentId([1; 32])), Err(()) => panic!("verification failed"), @@ -976,11 +1045,14 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify(&expanded_key, &secp_ctx).is_err()); // Fails verification with altered payer_id @@ -991,11 +1063,14 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify(&expanded_key, &secp_ctx).is_err()); } @@ -1005,7 +1080,8 @@ mod tests { let past_expiry = Duration::from_secs(0); let now = future_expiry - Duration::from_secs(1_000); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(future_expiry) .build() .unwrap(); @@ -1016,7 +1092,8 @@ mod tests { assert_eq!(refund.absolute_expiry(), Some(future_expiry)); assert_eq!(tlv_stream.absolute_expiry, Some(future_expiry.as_secs())); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(future_expiry) .absolute_expiry(past_expiry) .build() @@ -1050,7 +1127,8 @@ mod tests { }, ]; - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .path(paths[0].clone()) .path(paths[1].clone()) .build() @@ -1065,7 +1143,8 @@ mod tests { #[test] fn builds_refund_with_issuer() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .issuer("bar".into()) .build() .unwrap(); @@ -1073,7 +1152,8 @@ mod tests { assert_eq!(refund.issuer(), Some(PrintableString("bar"))); assert_eq!(tlv_stream.issuer, Some(&String::from("bar"))); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .issuer("bar".into()) .issuer("baz".into()) .build() @@ -1088,24 +1168,30 @@ mod tests { let mainnet = ChainHash::using_genesis_block(Network::Bitcoin); let testnet = ChainHash::using_genesis_block(Network::Testnet); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .chain(Network::Bitcoin) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream) = refund.as_tlv_stream(); assert_eq!(refund.chain(), mainnet); assert_eq!(tlv_stream.chain, None); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .chain(Network::Testnet) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream) = refund.as_tlv_stream(); assert_eq!(refund.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .chain(Network::Regtest) .chain(Network::Testnet) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream) = refund.as_tlv_stream(); assert_eq!(refund.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); @@ -1113,17 +1199,21 @@ mod tests { #[test] fn builds_refund_with_quantity() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .quantity(10) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream) = refund.as_tlv_stream(); assert_eq!(refund.quantity(), Some(10)); assert_eq!(tlv_stream.quantity, Some(10)); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .quantity(10) .quantity(1) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream) = refund.as_tlv_stream(); assert_eq!(refund.quantity(), Some(1)); assert_eq!(tlv_stream.quantity, Some(1)); @@ -1131,17 +1221,21 @@ mod tests { #[test] fn builds_refund_with_payer_note() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .payer_note("bar".into()) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream) = refund.as_tlv_stream(); assert_eq!(refund.payer_note(), Some(PrintableString("bar"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("bar"))); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .payer_note("bar".into()) .payer_note("baz".into()) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream) = refund.as_tlv_stream(); assert_eq!(refund.payer_note(), Some(PrintableString("baz"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("baz"))); @@ -1149,9 +1243,11 @@ mod tests { #[test] fn fails_responding_with_unknown_required_features() { - match RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + match RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) - .build().unwrap() + .build() + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) { Ok(_) => panic!("expected error"), @@ -1161,8 +1257,10 @@ mod tests { #[test] fn parses_refund_with_metadata() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1173,15 +1271,20 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata) + ); }, } } #[test] fn parses_refund_with_description() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1192,15 +1295,20 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription) + ); }, } } #[test] fn parses_refund_with_amount() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1211,7 +1319,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ); }, } @@ -1221,15 +1332,20 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ); }, } } #[test] fn parses_refund_with_payer_id() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1240,7 +1356,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerId)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerId) + ); }, } } @@ -1267,7 +1386,8 @@ mod tests { }, ]; - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(past_expiry) .issuer("bar".into()) .path(paths[0].clone()) @@ -1296,8 +1416,10 @@ mod tests { #[test] fn fails_parsing_refund_with_unexpected_fields() { - let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1309,7 +1431,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedMetadata)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedMetadata) + ); }, } @@ -1320,7 +1445,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedChain)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedChain) + ); }, } @@ -1331,7 +1459,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedAmount)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedAmount) + ); }, } @@ -1342,7 +1473,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedFeatures)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedFeatures) + ); }, } @@ -1352,7 +1486,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity) + ); }, } @@ -1363,7 +1500,12 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::UnexpectedSigningPubkey + ) + ); }, } } @@ -1372,8 +1514,10 @@ mod tests { fn fails_parsing_refund_with_extra_tlv_records() { let secp_ctx = Secp256k1::new(); let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let refund = RefundBuilder::new("foo".into(), vec![1; 32], keys.public_key(), 1000).unwrap() - .build().unwrap(); + let refund = RefundBuilder::new("foo".into(), vec![1; 32], keys.public_key(), 1000) + .unwrap() + .build() + .unwrap(); let mut encoded_refund = Vec::new(); refund.write(&mut encoded_refund).unwrap(); diff --git a/lightning/src/offers/signer.rs b/lightning/src/offers/signer.rs index e0abd82767f..9a6369c6963 100644 --- a/lightning/src/offers/signer.rs +++ b/lightning/src/offers/signer.rs @@ -9,17 +9,17 @@ //! Utilities for signing offer messages and verifying metadata. -use bitcoin::hashes::{Hash, HashEngine}; +use crate::ln::channelmanager::PaymentId; +use crate::ln::inbound_payment::{ExpandedKey, Nonce, IV_LEN}; +use crate::offers::merkle::TlvRecord; +use crate::util::ser::Writeable; use bitcoin::hashes::cmp::fixed_time_eq; use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey, self}; +use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::secp256k1::{self, KeyPair, PublicKey, Secp256k1, SecretKey}; use core::convert::TryFrom; use core::fmt; -use crate::ln::channelmanager::PaymentId; -use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce}; -use crate::offers::merkle::TlvRecord; -use crate::util::ser::Writeable; use crate::prelude::*; @@ -102,7 +102,7 @@ impl Metadata { } pub fn derive_from( - self, tlv_stream: W, secp_ctx: Option<&Secp256k1> + self, tlv_stream: W, secp_ctx: Option<&Secp256k1>, ) -> (Self, Option) { match self { Metadata::Bytes(_) => (self, None), @@ -140,10 +140,12 @@ impl fmt::Debug for Metadata { impl PartialEq for Metadata { fn eq(&self, other: &Self) -> bool { match self { - Metadata::Bytes(bytes) => if let Metadata::Bytes(other_bytes) = other { - bytes == other_bytes - } else { - false + Metadata::Bytes(bytes) => { + if let Metadata::Bytes(other_bytes) = other { + bytes == other_bytes + } else { + false + } }, Metadata::Derived(_) => false, Metadata::DerivedSigningPubkey(_) => false, @@ -163,18 +165,13 @@ pub(super) struct MetadataMaterial { impl MetadataMaterial { pub fn new( nonce: Nonce, expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN], - payment_id: Option + payment_id: Option, ) -> Self { // Encrypt payment_id - let encrypted_payment_id = payment_id.map(|payment_id| { - expanded_key.crypt_for_offer(payment_id.0, nonce) - }); - - Self { - nonce, - hmac: expanded_key.hmac_for_offer(nonce, iv_bytes), - encrypted_payment_id, - } + let encrypted_payment_id = + payment_id.map(|payment_id| expanded_key.crypt_for_offer(payment_id.0, nonce)); + + Self { nonce, hmac: expanded_key.hmac_for_offer(nonce, iv_bytes), encrypted_payment_id } } fn derive_metadata(mut self) -> Vec { @@ -188,7 +185,7 @@ impl MetadataMaterial { } fn derive_metadata_and_keys( - mut self, secp_ctx: &Secp256k1 + mut self, secp_ctx: &Secp256k1, ) -> (Vec, KeyPair) { self.hmac.input(DERIVED_METADATA_AND_KEYS_HMAC_INPUT); self.maybe_include_encrypted_payment_id(); @@ -234,7 +231,7 @@ pub(super) fn derive_keys(nonce: Nonce, expanded_key: &ExpandedKey) -> KeyPair { pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>( metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN], signing_pubkey: PublicKey, tlv_stream: impl core::iter::Iterator>, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result { if metadata.len() < PaymentId::LENGTH { return Err(()); @@ -243,14 +240,16 @@ pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>( let mut encrypted_payment_id = [0u8; PaymentId::LENGTH]; encrypted_payment_id.copy_from_slice(&metadata[..PaymentId::LENGTH]); - let mut hmac = hmac_for_message( - &metadata[PaymentId::LENGTH..], expanded_key, iv_bytes, tlv_stream - )?; + let mut hmac = + hmac_for_message(&metadata[PaymentId::LENGTH..], expanded_key, iv_bytes, tlv_stream)?; hmac.input(WITH_ENCRYPTED_PAYMENT_ID_HMAC_INPUT); hmac.input(&encrypted_payment_id); verify_metadata( - &metadata[PaymentId::LENGTH..], Hmac::from_engine(hmac), signing_pubkey, secp_ctx + &metadata[PaymentId::LENGTH..], + Hmac::from_engine(hmac), + signing_pubkey, + secp_ctx, )?; let nonce = Nonce::try_from(&metadata[PaymentId::LENGTH..][..Nonce::LENGTH]).unwrap(); @@ -270,7 +269,7 @@ pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>( pub(super) fn verify_recipient_metadata<'a, T: secp256k1::Signing>( metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN], signing_pubkey: PublicKey, tlv_stream: impl core::iter::Iterator>, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result, ()> { let mut hmac = hmac_for_message(metadata, expanded_key, iv_bytes, tlv_stream)?; hmac.input(WITHOUT_ENCRYPTED_PAYMENT_ID_HMAC_INPUT); @@ -279,11 +278,12 @@ pub(super) fn verify_recipient_metadata<'a, T: secp256k1::Signing>( } fn verify_metadata( - metadata: &[u8], hmac: Hmac, signing_pubkey: PublicKey, secp_ctx: &Secp256k1 + metadata: &[u8], hmac: Hmac, signing_pubkey: PublicKey, secp_ctx: &Secp256k1, ) -> Result, ()> { if metadata.len() == Nonce::LENGTH { let derived_keys = KeyPair::from_secret_key( - secp_ctx, &SecretKey::from_slice(hmac.as_byte_array()).unwrap() + secp_ctx, + &SecretKey::from_slice(hmac.as_byte_array()).unwrap(), ); if fixed_time_eq(&signing_pubkey.serialize(), &derived_keys.public_key().serialize()) { Ok(Some(derived_keys)) @@ -303,7 +303,7 @@ fn verify_metadata( fn hmac_for_message<'a>( metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN], - tlv_stream: impl core::iter::Iterator> + tlv_stream: impl core::iter::Iterator>, ) -> Result, ()> { if metadata.len() < Nonce::LENGTH { return Err(()); diff --git a/lightning/src/offers/test_utils.rs b/lightning/src/offers/test_utils.rs index 39122472eac..b810fad1b52 100644 --- a/lightning/src/offers/test_utils.rs +++ b/lightning/src/offers/test_utils.rs @@ -9,16 +9,16 @@ //! Utilities for testing BOLT 12 Offers interfaces -use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey}; -use bitcoin::secp256k1::schnorr::Signature; -use core::convert::{AsRef, Infallible}; -use core::time::Duration; use crate::blinded_path::{BlindedHop, BlindedPath}; -use crate::sign::EntropySource; -use crate::ln::PaymentHash; use crate::ln::features::BlindedHopFeatures; +use crate::ln::PaymentHash; use crate::offers::invoice::BlindedPayInfo; use crate::offers::merkle::TaggedHash; +use crate::sign::EntropySource; +use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey}; +use core::convert::{AsRef, Infallible}; +use core::time::Duration; pub(crate) fn payer_keys() -> KeyPair { let secp_ctx = Secp256k1::new(); diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index 23d27b18943..cd4c98c7611 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -9,6 +9,12 @@ //! Onion message testing and test utilities live here. +use super::messenger::{ + CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger, + PendingOnionMessage, SendError, +}; +use super::offers::{OffersMessage, OffersMessageHandler}; +use super::packet::{OnionMessageContents, Packet}; use crate::blinded_path::BlindedPath; use crate::events::{Event, EventsProvider}; use crate::ln::features::InitFeatures; @@ -16,13 +22,10 @@ use crate::ln::msgs::{self, DecodeError, OnionMessageHandler, SocketAddress}; use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer}; use crate::util::test_utils; -use super::messenger::{CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger, PendingOnionMessage, SendError}; -use super::offers::{OffersMessage, OffersMessageHandler}; -use super::packet::{OnionMessageContents, Packet}; -use bitcoin::network::constants::Network; use bitcoin::hashes::hex::FromHex; -use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey, self}; +use bitcoin::network::constants::Network; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; use crate::io; use crate::io_extras::read_to_end; @@ -39,7 +42,7 @@ struct MessengerNode { Arc, Arc, Arc, - Arc + Arc, >, custom_message_handler: Arc, } @@ -48,21 +51,24 @@ struct TestMessageRouter {} impl MessageRouter for TestMessageRouter { fn find_path( - &self, _sender: PublicKey, _peers: Vec, destination: Destination + &self, _sender: PublicKey, _peers: Vec, destination: Destination, ) -> Result { Ok(OnionMessagePath { intermediate_nodes: vec![], destination, - first_node_addresses: - Some(vec![SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: 1000 }]), + first_node_addresses: Some(vec![SocketAddress::TcpIpV4 { + addr: [127, 0, 0, 1], + port: 1000, + }]), }) } fn create_blinded_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, _recipient: PublicKey, _peers: Vec, _entropy_source: &ES, - _secp_ctx: &Secp256k1 + _secp_ctx: &Secp256k1, ) -> Result, ()> { unreachable!() } @@ -121,7 +127,8 @@ impl TestCustomMessageHandler { impl Drop for TestCustomMessageHandler { fn drop(&mut self) { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if std::thread::panicking() { return; } @@ -143,7 +150,12 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler { TestCustomMessage::Response => None, } } - fn read_custom_message(&self, message_type: u64, buffer: &mut R) -> Result, DecodeError> where Self: Sized { + fn read_custom_message( + &self, message_type: u64, buffer: &mut R, + ) -> Result, DecodeError> + where + Self: Sized, + { match message_type { CUSTOM_REQUEST_MESSAGE_TYPE => { let buf = read_to_end(buffer)?; @@ -186,8 +198,12 @@ fn create_nodes_using_secrets(secrets: Vec) -> Vec { node_id: node_signer.get_node_id(Recipient::Node).unwrap(), entropy_source: entropy_source.clone(), messenger: OnionMessenger::new( - entropy_source, node_signer, logger.clone(), message_router, - offers_message_handler, custom_message_handler.clone() + entropy_source, + node_signer, + logger.clone(), + message_router, + offers_message_handler, + custom_message_handler.clone(), ), custom_message_handler, }); @@ -221,7 +237,7 @@ fn pass_along_path(path: &Vec) { let mut prev_node = &path[0]; for node in path.into_iter().skip(1) { let events = prev_node.messenger.release_pending_msgs(); - let onion_msg = { + let onion_msg = { let msgs = events.get(&node.node_id).unwrap(); assert_eq!(msgs.len(), 1); msgs[0].clone() @@ -267,7 +283,9 @@ fn one_blinded_hop() { let test_msg = TestCustomMessage::Response; let secp_ctx = Secp256k1::new(); - let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id], &*nodes[1].entropy_source, &secp_ctx).unwrap(); + let blinded_path = + BlindedPath::new_for_message(&[nodes[1].node_id], &*nodes[1].entropy_source, &secp_ctx) + .unwrap(); let path = OnionMessagePath { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), @@ -284,7 +302,12 @@ fn two_unblinded_two_blinded() { let test_msg = TestCustomMessage::Response; let secp_ctx = Secp256k1::new(); - let blinded_path = BlindedPath::new_for_message(&[nodes[3].node_id, nodes[4].node_id], &*nodes[4].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedPath::new_for_message( + &[nodes[3].node_id, nodes[4].node_id], + &*nodes[4].entropy_source, + &secp_ctx, + ) + .unwrap(); let path = OnionMessagePath { intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id], destination: Destination::BlindedPath(blinded_path), @@ -302,7 +325,12 @@ fn three_blinded_hops() { let test_msg = TestCustomMessage::Response; let secp_ctx = Secp256k1::new(); - let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], &*nodes[3].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedPath::new_for_message( + &[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], + &*nodes[3].entropy_source, + &secp_ctx, + ) + .unwrap(); let path = OnionMessagePath { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), @@ -339,7 +367,12 @@ fn we_are_intro_node() { let test_msg = TestCustomMessage::Response; let secp_ctx = Secp256k1::new(); - let blinded_path = BlindedPath::new_for_message(&[nodes[0].node_id, nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedPath::new_for_message( + &[nodes[0].node_id, nodes[1].node_id, nodes[2].node_id], + &*nodes[2].entropy_source, + &secp_ctx, + ) + .unwrap(); let path = OnionMessagePath { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), @@ -351,7 +384,12 @@ fn we_are_intro_node() { pass_along_path(&nodes); // Try with a two-hop blinded path where we are the introduction node. - let blinded_path = BlindedPath::new_for_message(&[nodes[0].node_id, nodes[1].node_id], &*nodes[1].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedPath::new_for_message( + &[nodes[0].node_id, nodes[1].node_id], + &*nodes[1].entropy_source, + &secp_ctx, + ) + .unwrap(); let path = OnionMessagePath { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), @@ -371,14 +409,20 @@ fn invalid_blinded_path_error() { // 0 hops let secp_ctx = Secp256k1::new(); - let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx).unwrap(); + let mut blinded_path = BlindedPath::new_for_message( + &[nodes[1].node_id, nodes[2].node_id], + &*nodes[2].entropy_source, + &secp_ctx, + ) + .unwrap(); blinded_path.blinded_hops.clear(); let path = OnionMessagePath { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), first_node_addresses: None, }; - let err = nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), None).unwrap_err(); + let err = + nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), None).unwrap_err(); assert_eq!(err, SendError::TooFewBlindedHops); } @@ -394,8 +438,16 @@ fn reply_path() { destination: Destination::Node(nodes[3].node_id), first_node_addresses: None, }; - let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], &*nodes[0].entropy_source, &secp_ctx).unwrap(); - nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)).unwrap(); + let reply_path = BlindedPath::new_for_message( + &[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], + &*nodes[0].entropy_source, + &secp_ctx, + ) + .unwrap(); + nodes[0] + .messenger + .send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)) + .unwrap(); nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request); pass_along_path(&nodes); // Make sure the last node successfully decoded the reply path. @@ -404,13 +456,23 @@ fn reply_path() { pass_along_path(&nodes); // Destination::BlindedPath - let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], &*nodes[3].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedPath::new_for_message( + &[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], + &*nodes[3].entropy_source, + &secp_ctx, + ) + .unwrap(); let path = OnionMessagePath { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), first_node_addresses: None, }; - let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], &*nodes[0].entropy_source, &secp_ctx).unwrap(); + let reply_path = BlindedPath::new_for_message( + &[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], + &*nodes[0].entropy_source, + &secp_ctx, + ) + .unwrap(); nodes[0].messenger.send_onion_message_using_path(path, test_msg, Some(reply_path)).unwrap(); nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request); @@ -427,7 +489,7 @@ fn invalid_custom_message_type() { let nodes = create_nodes(2); #[derive(Debug)] - struct InvalidCustomMessage{} + struct InvalidCustomMessage {} impl OnionMessageContents for InvalidCustomMessage { fn tlv_type(&self) -> u64 { // Onion message contents must have a TLV >= 64. @@ -436,7 +498,9 @@ fn invalid_custom_message_type() { } impl Writeable for InvalidCustomMessage { - fn write(&self, _w: &mut W) -> Result<(), io::Error> { unreachable!() } + fn write(&self, _w: &mut W) -> Result<(), io::Error> { + unreachable!() + } } let test_msg = InvalidCustomMessage {}; @@ -458,8 +522,12 @@ fn peer_buffer_full() { destination: Destination::Node(nodes[1].node_id), first_node_addresses: None, }; - for _ in 0..188 { // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger - nodes[0].messenger.send_onion_message_using_path(path.clone(), test_msg.clone(), None).unwrap(); + for _ in 0..188 { + // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger + nodes[0] + .messenger + .send_onion_message_using_path(path.clone(), test_msg.clone(), None) + .unwrap(); } let err = nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap_err(); assert_eq!(err, SendError::BufferFull); @@ -474,17 +542,17 @@ fn many_hops() { let test_msg = TestCustomMessage::Response; let mut intermediate_nodes = vec![]; - for i in 1..(num_nodes-1) { + for i in 1..(num_nodes - 1) { intermediate_nodes.push(nodes[i].node_id); } let path = OnionMessagePath { intermediate_nodes, - destination: Destination::Node(nodes[num_nodes-1].node_id), + destination: Destination::Node(nodes[num_nodes - 1].node_id), first_node_addresses: None, }; nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap(); - nodes[num_nodes-1].custom_message_handler.expect_message(TestCustomMessage::Response); + nodes[num_nodes - 1].custom_message_handler.expect_message(TestCustomMessage::Response); pass_along_path(&nodes); } @@ -494,8 +562,11 @@ fn requests_peer_connection_for_buffered_messages() { let message = TestCustomMessage::Request; let secp_ctx = Secp256k1::new(); let blinded_path = BlindedPath::new_for_message( - &[nodes[1].node_id, nodes[2].node_id], &*nodes[0].entropy_source, &secp_ctx - ).unwrap(); + &[nodes[1].node_id, nodes[2].node_id], + &*nodes[0].entropy_source, + &secp_ctx, + ) + .unwrap(); let destination = Destination::BlindedPath(blinded_path); // Buffer an onion message for a connected peer @@ -529,8 +600,11 @@ fn drops_buffered_messages_waiting_for_peer_connection() { let message = TestCustomMessage::Request; let secp_ctx = Secp256k1::new(); let blinded_path = BlindedPath::new_for_message( - &[nodes[1].node_id, nodes[2].node_id], &*nodes[0].entropy_source, &secp_ctx - ).unwrap(); + &[nodes[1].node_id, nodes[2].node_id], + &*nodes[0].entropy_source, + &secp_ctx, + ) + .unwrap(); let destination = Destination::BlindedPath(blinded_path); // Buffer an onion message for a disconnected peer @@ -562,9 +636,9 @@ fn spec_test_vector() { "4343434343434343434343434343434343434343434343434343434343434343", // Carol "4444444444444444444444444444444444444444444444444444444444444444", // Dave ] - .iter() - .map(|secret| SecretKey::from_slice(&>::from_hex(secret).unwrap()).unwrap()) - .collect(); + .iter() + .map(|secret| SecretKey::from_slice(&>::from_hex(secret).unwrap()).unwrap()) + .collect(); let nodes = create_nodes_using_secrets(secret_keys); // Hardcode the sender->Alice onion message, because it includes an unknown TLV of type 1, which @@ -577,7 +651,16 @@ fn spec_test_vector() { ::read(&mut packet_reader).unwrap(); let secp_ctx = Secp256k1::new(); let sender_to_alice_om = msgs::OnionMessage { - blinding_point: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&>::from_hex("6363636363636363636363636363636363636363636363636363636363636363").unwrap()).unwrap()), + blinding_point: PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice( + &>::from_hex( + "6363636363636363636363636363636363636363636363636363636363636363", + ) + .unwrap(), + ) + .unwrap(), + ), onion_routing_packet: sender_to_alice_packet, }; // The spec test vectors prepend the OM message type (513) to the encoded onion message strings, @@ -591,7 +674,8 @@ fn spec_test_vector() { let bob_to_carol_om = nodes[1].messenger.next_onion_message_for_peer(nodes[2].node_id).unwrap(); assert_eq!(bob_to_carol_om.encode(), >::from_hex("02b684babfd400c8dd48b367e9754b8021a3594a34dc94d7101776c7f6a86d0582055600029a77e8523162efa1f4208f4f2050cd5c386ddb6ce6d36235ea569d217ec52209fb85fdf7dbc4786c373eebdba0ddc184cfbe6da624f610e93f62c70f2c56be1090b926359969f040f932c03f53974db5656233bd60af375517d4323002937d784c2c88a564bcefe5c33d3fc21c26d94dfacab85e2e19685fd2ff4c543650958524439b6da68779459aee5ffc9dc543339acec73ff43be4c44ddcbe1c11d50e2411a67056ba9db7939d780f5a86123fdd3abd6f075f7a1d78ab7daf3a82798b7ec1e9f1345bc0d1e935098497067e2ae5a51ece396fcb3bb30871ad73aee51b2418b39f00c8e8e22be4a24f4b624e09cb0414dd46239de31c7be035f71e8da4f5a94d15b44061f46414d3f355069b5c5b874ba56704eb126148a22ec873407fe118972127e63ff80e682e410f297f23841777cec0517e933eaf49d7e34bd203266b42081b3a5193b51ccd34b41342bc67cf73523b741f5c012ba2572e9dda15fbe131a6ac2ff24dc2a7622d58b9f3553092cfae7fae3c8864d95f97aa49ec8edeff5d9f5782471160ee412d82ff6767030fc63eec6a93219a108cd41433834b26676a39846a944998796c79cd1cc460531b8ded659cedfd8aecefd91944f00476f1496daafb4ea6af3feacac1390ea510709783c2aa81a29de27f8959f6284f4684102b17815667cbb0645396ac7d542b878d90c42a1f7f00c4c4eedb2a22a219f38afadb4f1f562b6e000a94e75cc38f535b43a3c0384ccef127fde254a9033a317701c710b2b881065723486e3f4d3eea5e12f374a41565fe43fa137c1a252c2153dde055bb343344c65ad0529010ece29bbd405effbebfe3ba21382b94a60ac1a5ffa03f521792a67b30773cb42e862a8a02a8bbd41b842e115969c87d1ff1f8c7b5726b9f20772dd57fe6e4ea41f959a2a673ffad8e2f2a472c4c8564f3a5a47568dd75294b1c7180c500f7392a7da231b1fe9e525ea2d7251afe9ca52a17fe54a116cb57baca4f55b9b6de915924d644cba9dade4ccc01939d7935749c008bafc6d3ad01cd72341ce5ddf7a5d7d21cf0465ab7a3233433aef21f9acf2bfcdc5a8cc003adc4d82ac9d72b36eb74e05c9aa6ccf439ac92e6b84a3191f0764dd2a2e0b4cc3baa08782b232ad6ecd3ca6029bc08cc094aef3aebddcaddc30070cb6023a689641de86cfc6341c8817215a4650f844cd2ca60f2f10c6e44cfc5f23912684d4457bf4f599879d30b79bf12ef1ab8d34dddc15672b82e56169d4c770f0a2a7a960b1e8790773f5ff7fce92219808f16d061cc85e053971213676d28fb48925e9232b66533dbd938458eb2cc8358159df7a2a2e4cf87500ede2afb8ce963a845b98978edf26a6948d4932a6b95d022004556d25515fe158092ce9a913b4b4a493281393ca731e8d8e5a3449b9d888fc4e73ffcbb9c6d6d66e88e03cf6e81a0496ede6e4e4172b08c000601993af38f80c7f68c9d5fff9e0e215cff088285bf039ca731744efcb7825a272ca724517736b4890f47e306b200aa2543c363e2c9090bcf3cf56b5b86868a62471c7123a41740392fc1d5ab28da18dca66618e9af7b42b62b23aba907779e73ca03ec60e6ab9e0484b9cae6578e0fddb6386cb3468506bf6420298bf4a690947ab582255551d82487f271101c72e19e54872ab47eae144db66bc2f8194a666a5daec08d12822cb83a61946234f2dfdbd6ca7d8763e6818adee7b401fcdb1ac42f9df1ac5cc5ac131f2869013c8d6cd29d4c4e3d05bccd34ca83366d616296acf854fa05149bfd763a25b9938e96826a037fdcb85545439c76df6beed3bdbd01458f9cf984997cc4f0a7ac3cc3f5e1eeb59c09cadcf5a537f16e444149c8f17d4bdaef16c9fbabc5ef06eb0f0bf3a07a1beddfeacdaf1df5582d6dbd6bb808d6ab31bc22e5d7").unwrap()); nodes[2].messenger.handle_onion_message(&nodes[1].node_id, &bob_to_carol_om); - let carol_to_dave_om = nodes[2].messenger.next_onion_message_for_peer(nodes[3].node_id).unwrap(); + let carol_to_dave_om = + nodes[2].messenger.next_onion_message_for_peer(nodes[3].node_id).unwrap(); assert_eq!(carol_to_dave_om.encode(), >::from_hex("025aaca62db7ce6b46386206ef9930daa32e979a35cb185a41cb951aa7d254b03c055600025550b2910294fa73bda99b9de9c851be9cbb481e23194a1743033630efba546b86e7d838d0f6e9cc0ed088dbf6889f0dceca3bfc745bd77d013a31311fa932a8bf1d28387d9ff521eabc651dee8f861fed609a68551145a451f017ec44978addeee97a423c08445531da488fd1ddc998e9cdbfcea59517b53fbf1833f0bbe6188dba6ca773a247220ec934010daca9cc185e1ceb136803469baac799e27a0d82abe53dc48a06a55d1f643885cc7894677dd20a4e4152577d1ba74b870b9279f065f9b340cedb3ca13b7df218e853e10ccd1b59c42a2acf93f489e170ee4373d30ab158b60fc20d3ba73a1f8c750951d69fb5b9321b968ddc8114936412346aff802df65516e1c09c51ef19849ff36c0199fd88c8bec301a30fef0c7cb497901c038611303f64e4174b5daf42832aa5586b84d2c9b95f382f4269a5d1bd4be898618dc78dfd451170f72ca16decac5b03e60702112e439cadd104fb3bbb3d5023c9b80823fdcd0a212a7e1aaa6eeb027adc7f8b3723031d135a09a979a4802788bb7861c6cc85501fb91137768b70aeab309b27b885686604ffc387004ac4f8c44b101c39bc0597ef7fd957f53fc5051f534b10eb3852100962b5e58254e5558689913c26ad6072ea41f5c5db10077cfc91101d4ae393be274c74297da5cc381cd88d54753aaa7df74b2f9da8d88a72bc9218fcd1f19e4ff4aace182312b9509c5175b6988f044c5756d232af02a451a02ca752f3c52747773acff6fd07d2032e6ce562a2c42105d106eba02d0b1904182cdc8c74875b082d4989d3a7e9f0e73de7c75d357f4af976c28c0b206c5e8123fc2391d078592d0d5ff686fd245c0a2de2e535b7cca99c0a37d432a8657393a9e3ca53eec1692159046ba52cb9bc97107349d8673f74cbc97e231f1108005c8d03e24ca813cea2294b39a7a493bcc062708f1f6cf0074e387e7d50e0666ce784ef4d31cb860f6cad767438d9ea5156ff0ae86e029e0247bf94df75ee0cda4f2006061455cb2eaff513d558863ae334cef7a3d45f55e7cc13153c6719e9901c1d4db6c03f643b69ea4860690305651794284d9e61eb848ccdf5a77794d376f0af62e46d4835acce6fd9eef5df73ebb8ea3bb48629766967f446e744ecc57ff3642c4aa1ccee9a2f72d5caa75fa05787d08b79408fce792485fdecdc25df34820fb061275d70b84ece540b0fc47b2453612be34f2b78133a64e812598fbe225fd85415f8ffe5340ce955b5fd9d67dd88c1c531dde298ed25f96df271558c812c26fa386966c76f03a6ebccbca49ac955916929bd42e134f982dde03f924c464be5fd1ba44f8dc4c3cbc8162755fd1d8f7dc044b15b1a796c53df7d8769bb167b2045b49cc71e08908796c92c16a235717cabc4bb9f60f8f66ff4fff1f9836388a99583acebdff4a7fb20f48eedcd1f4bdcc06ec8b48e35307df51d9bc81d38a94992dd135b30079e1f592da6e98dff496cb1a7776460a26b06395b176f585636ebdf7eab692b227a31d6979f5a6141292698e91346b6c806b90c7c6971e481559cae92ee8f4136f2226861f5c39ddd29bbdb118a35dece03f49a96804caea79a3dacfbf09d65f2611b5622de51d98e18151acb3bb84c09caaa0cc80edfa743a4679f37d6167618ce99e73362fa6f213409931762618a61f1738c071bba5afc1db24fe94afb70c40d731908ab9a505f76f57a7d40e708fd3df0efc5b7cbb2a7b75cd23449e09684a2f0e2bfa0d6176c35f96fe94d92fc9fa4103972781f81cb6e8df7dbeb0fc529c600d768bed3f08828b773d284f69e9a203459d88c12d6df7a75be2455fec128f07a497a2b2bf626cc6272d0419ca663e9dc66b8224227eb796f0246dcae9c5b0b6cfdbbd40c3245a610481c92047c968c9fc92c04b89cc41a0c15355a8f").unwrap()); // Dave handles the onion message but he'll log that he errored while decoding the hop data // because he sees it as an empty onion message (the only contents of the sender's OM is "hello" diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 3678dea84d6..0cf88f86dd4 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -10,38 +10,41 @@ //! LDK sends, receives, and forwards onion messages via this [`OnionMessenger`], which lives here, //! as well as various types, traits, and utilities that it uses. -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::{self, PublicKey, Scalar, Secp256k1, SecretKey}; -use crate::blinded_path::BlindedPath; +use super::offers::OffersMessageHandler; +use super::packet::OnionMessageContents; +use super::packet::ParsedOnionMessageContents; +use super::packet::{ + ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, BIG_PACKET_HOP_DATA_LEN, + SMALL_PACKET_HOP_DATA_LEN, +}; use crate::blinded_path::message::{advance_path_by_one, ForwardTlvs, ReceiveTlvs}; use crate::blinded_path::utils; +use crate::blinded_path::BlindedPath; use crate::events::{Event, EventHandler, EventsProvider}; -use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::ln::features::{InitFeatures, NodeFeatures}; use crate::ln::msgs::{self, OnionMessage, OnionMessageHandler, SocketAddress}; use crate::ln::onion_utils; use crate::routing::gossip::{NetworkGraph, NodeId}; -use super::packet::OnionMessageContents; -use super::packet::ParsedOnionMessageContents; -use super::offers::OffersMessageHandler; -use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN}; +use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::util::logger::Logger; use crate::util::ser::Writeable; -use core::fmt; -use core::ops::Deref; use crate::io; -use crate::sync::Mutex; use crate::prelude::*; +use crate::sync::Mutex; +use core::fmt; +use core::ops::Deref; #[cfg(not(c_bindings))] use { - crate::sign::KeysManager, crate::ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager}, crate::ln::peer_handler::IgnoringMessageHandler, + crate::sign::KeysManager, crate::sync::Arc, }; @@ -267,7 +270,7 @@ pub struct PendingOnionMessage { pub type PendingOnionMessage = (T, Destination, Option); pub(crate) fn new_pending_onion_message( - contents: T, destination: Destination, reply_path: Option + contents: T, destination: Destination, reply_path: Option, ) -> PendingOnionMessage { #[cfg(not(c_bindings))] return PendingOnionMessage { contents, destination, reply_path }; @@ -279,28 +282,29 @@ pub(crate) fn new_pending_onion_message( pub trait MessageRouter { /// Returns a route for sending an [`OnionMessage`] to the given [`Destination`]. fn find_path( - &self, sender: PublicKey, peers: Vec, destination: Destination + &self, sender: PublicKey, peers: Vec, destination: Destination, ) -> Result; /// Creates [`BlindedPath`]s to the `recipient` node. The nodes in `peers` are assumed to be /// direct peers with the `recipient`. fn create_blinded_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, peers: Vec, entropy_source: &ES, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result, ()>; } /// A [`MessageRouter`] that can only route to a directly connected [`Destination`]. -pub struct DefaultMessageRouter>, L: Deref> +pub struct DefaultMessageRouter>, L: Deref> where L::Target: Logger, { network_graph: G, } -impl>, L: Deref> DefaultMessageRouter +impl>, L: Deref> DefaultMessageRouter where L::Target: Logger, { @@ -310,17 +314,19 @@ where } } -impl>, L: Deref> MessageRouter for DefaultMessageRouter +impl>, L: Deref> MessageRouter for DefaultMessageRouter where L::Target: Logger, { fn find_path( - &self, _sender: PublicKey, peers: Vec, destination: Destination + &self, _sender: PublicKey, peers: Vec, destination: Destination, ) -> Result { let first_node = destination.first_node(); if peers.contains(&first_node) { Ok(OnionMessagePath { - intermediate_nodes: vec![], destination, first_node_addresses: None + intermediate_nodes: vec![], + destination, + first_node_addresses: None, }) } else { let network_graph = self.network_graph.deref().read_only(); @@ -334,7 +340,9 @@ where Some(node_announcement) if node_announcement.features.supports_onion_messages() => { let first_node_addresses = Some(node_announcement.addresses.clone()); Ok(OnionMessagePath { - intermediate_nodes: vec![], destination, first_node_addresses + intermediate_nodes: vec![], + destination, + first_node_addresses, }) }, _ => Err(()), @@ -343,10 +351,11 @@ where } fn create_blinded_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, peers: Vec, entropy_source: &ES, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result, ()> { // Limit the number of blinded paths that are computed. const MAX_PATHS: usize = 3; @@ -356,15 +365,16 @@ where const MIN_PEER_CHANNELS: usize = 3; let network_graph = self.network_graph.deref().read_only(); - let paths = peers.iter() + let paths = peers + .iter() // Limit to peers with announced channels - .filter(|pubkey| + .filter(|pubkey| { network_graph .node(&NodeId::from_pubkey(pubkey)) .map(|info| &info.channels[..]) .map(|channels| channels.len() >= MIN_PEER_CHANNELS) .unwrap_or(false) - ) + }) .map(|pubkey| vec![*pubkey, recipient]) .map(|node_pks| BlindedPath::new_for_message(&node_pks, entropy_source, secp_ctx)) .take(MAX_PATHS) @@ -403,10 +413,7 @@ pub struct OnionMessagePath { impl OnionMessagePath { /// Returns the first node in the path. pub fn first_node(&self) -> PublicKey { - self.intermediate_nodes - .first() - .copied() - .unwrap_or_else(|| self.destination.first_node()) + self.intermediate_nodes.first().copied().unwrap_or_else(|| self.destination.first_node()) } } @@ -502,7 +509,9 @@ pub trait CustomOnionMessageHandler { /// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the /// message type is unknown. - fn read_custom_message(&self, message_type: u64, buffer: &mut R) -> Result, msgs::DecodeError>; + fn read_custom_message( + &self, message_type: u64, buffer: &mut R, + ) -> Result, msgs::DecodeError>; /// Releases any [`Self::CustomMessage`]s that need to be sent. /// @@ -516,7 +525,9 @@ pub trait CustomOnionMessageHandler { /// Typically, this is used for messages initiating a message flow rather than in response to /// another message. The latter should use the return value of [`Self::handle_custom_message`]. #[cfg(c_bindings)] - fn release_pending_custom_messages(&self) -> Vec<(Self::CustomMessage, Destination, Option)>; + fn release_pending_custom_messages( + &self, + ) -> Vec<(Self::CustomMessage, Destination, Option)>; } /// A processed incoming onion message, containing either a Forward (another onion message) @@ -525,7 +536,7 @@ pub enum PeeledOnion { /// Forwarded onion, with the next node id and a new onion Forward(PublicKey, OnionMessage), /// Received onion message, with decrypted contents, path_id, and reply path - Receive(ParsedOnionMessageContents, Option<[u8; 32]>, Option) + Receive(ParsedOnionMessageContents, Option<[u8; 32]>, Option), } /// Creates an [`OnionMessage`] with the given `contents` for sending to the destination of @@ -548,13 +559,16 @@ where } } - if contents.tlv_type() < 64 { return Err(SendError::InvalidMessage) } + if contents.tlv_type() < 64 { + return Err(SendError::InvalidMessage); + } // If we are sending straight to a blinded path and we are the introduction node, we need to // advance the blinded path by 1 hop so the second hop is the new introduction node. if intermediate_nodes.len() == 0 { if let Destination::BlindedPath(ref mut blinded_path) = destination { - let our_node_id = node_signer.get_node_id(Recipient::Node) + let our_node_id = node_signer + .get_node_id(Recipient::Node) .map_err(|()| SendError::GetNodeIdFailed)?; if blinded_path.introduction_node_id == our_node_id { advance_path_by_one(blinded_path, node_signer, &secp_ctx) @@ -570,17 +584,25 @@ where } else { match destination { Destination::Node(pk) => (pk, PublicKey::from_secret_key(&secp_ctx, &blinding_secret)), - Destination::BlindedPath(BlindedPath { introduction_node_id, blinding_point, .. }) => - (introduction_node_id, blinding_point), + Destination::BlindedPath(BlindedPath { + introduction_node_id, blinding_point, .. + }) => (introduction_node_id, blinding_point), } }; let (packet_payloads, packet_keys) = packet_payloads_and_keys( - &secp_ctx, &intermediate_nodes, destination, contents, reply_path, &blinding_secret) - .map_err(|e| SendError::Secp256k1(e))?; + &secp_ctx, + &intermediate_nodes, + destination, + contents, + reply_path, + &blinding_secret, + ) + .map_err(|e| SendError::Secp256k1(e))?; let prng_seed = entropy_source.get_secure_random_bytes(); - let onion_routing_packet = construct_onion_message_packet( - packet_payloads, packet_keys, prng_seed).map_err(|()| SendError::TooBigPacket)?; + let onion_routing_packet = + construct_onion_message_packet(packet_payloads, packet_keys, prng_seed) + .map_err(|()| SendError::TooBigPacket)?; let message = OnionMessage { blinding_point, onion_routing_packet }; Ok((first_node_id, message, first_node_addresses)) @@ -601,10 +623,10 @@ where { let control_tlvs_ss = match node_signer.ecdh(Recipient::Node, &msg.blinding_point, None) { Ok(ss) => ss, - Err(e) => { + Err(e) => { log_error!(logger, "Failed to retrieve node secret: {:?}", e); return Err(()); - } + }, }; let onion_decode_ss = { let blinding_factor = { @@ -612,39 +634,58 @@ where hmac.input(control_tlvs_ss.as_ref()); Hmac::from_engine(hmac).to_byte_array() }; - match node_signer.ecdh(Recipient::Node, &msg.onion_routing_packet.public_key, - Some(&Scalar::from_be_bytes(blinding_factor).unwrap())) - { + match node_signer.ecdh( + Recipient::Node, + &msg.onion_routing_packet.public_key, + Some(&Scalar::from_be_bytes(blinding_factor).unwrap()), + ) { Ok(ss) => ss.secret_bytes(), Err(()) => { log_trace!(logger, "Failed to compute onion packet shared secret"); return Err(()); - } + }, } }; match onion_utils::decode_next_untagged_hop( - onion_decode_ss, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac, - (control_tlvs_ss, custom_handler.deref(), logger.deref()) + onion_decode_ss, + &msg.onion_routing_packet.hop_data[..], + msg.onion_routing_packet.hmac, + (control_tlvs_ss, custom_handler.deref(), logger.deref()), ) { - Ok((Payload::Receive::::Target as CustomOnionMessageHandler>::CustomMessage>> { - message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path, - }, None)) => { - Ok(PeeledOnion::Receive(message, path_id, reply_path)) - }, - Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs { - next_node_id, next_blinding_override - })), Some((next_hop_hmac, new_packet_bytes)))) => { + Ok(( + Payload::Receive::< + ParsedOnionMessageContents< + <::Target as CustomOnionMessageHandler>::CustomMessage, + >, + > { + message, + control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), + reply_path, + }, + None, + )) => Ok(PeeledOnion::Receive(message, path_id, reply_path)), + Ok(( + Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs { + next_node_id, + next_blinding_override, + })), + Some((next_hop_hmac, new_packet_bytes)), + )) => { // TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy // blinded hop and this onion message is destined for us. In this situation, we should keep // unwrapping the onion layers to get to the final payload. Since we don't have the option // of creating blinded paths with dummy hops currently, we should be ok to not handle this // for now. - let new_pubkey = match onion_utils::next_hop_pubkey(&secp_ctx, msg.onion_routing_packet.public_key, &onion_decode_ss) { + let new_pubkey = match onion_utils::next_hop_pubkey( + &secp_ctx, + msg.onion_routing_packet.public_key, + &onion_decode_ss, + ) { Ok(pk) => pk, Err(e) => { log_trace!(logger, "Failed to compute next hop packet pubkey: {}", e); - return Err(()) - } + return Err(()); + }, }; let outgoing_packet = Packet { version: 0, @@ -657,15 +698,17 @@ where Some(blinding_point) => blinding_point, None => { match onion_utils::next_hop_pubkey( - &secp_ctx, msg.blinding_point, control_tlvs_ss.as_ref() + &secp_ctx, + msg.blinding_point, + control_tlvs_ss.as_ref(), ) { Ok(bp) => bp, Err(e) => { log_trace!(logger, "Failed to compute next blinding point: {}", e); - return Err(()) - } + return Err(()); + }, } - } + }, }, onion_routing_packet: outgoing_packet, }; @@ -684,7 +727,7 @@ where } impl -OnionMessenger + OnionMessenger where ES::Target: EntropySource, NS::Target: NodeSigner, @@ -697,7 +740,7 @@ where /// their respective handlers. pub fn new( entropy_source: ES, node_signer: NS, logger: L, message_router: MR, offers_handler: OMH, - custom_handler: CMH + custom_handler: CMH, ) -> Self { let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes()); @@ -722,18 +765,22 @@ where /// /// See [`OnionMessenger`] for example usage. pub fn send_onion_message( - &self, contents: T, destination: Destination, reply_path: Option + &self, contents: T, destination: Destination, reply_path: Option, ) -> Result { self.find_path_and_enqueue_onion_message( - contents, destination, reply_path, format_args!("") + contents, + destination, + reply_path, + format_args!(""), ) } fn find_path_and_enqueue_onion_message( &self, contents: T, destination: Destination, reply_path: Option, - log_suffix: fmt::Arguments + log_suffix: fmt::Arguments, ) -> Result { - let result = self.find_path(destination) + let result = self + .find_path(destination) .and_then(|path| self.enqueue_onion_message(path, contents, reply_path, log_suffix)); match result.as_ref() { @@ -751,8 +798,10 @@ where }, Ok(SendSuccess::BufferedAwaitingConnection(node_id)) => { log_trace!( - self.logger, "Buffered onion message waiting on peer connection {}: {:?}", - log_suffix, node_id + self.logger, + "Buffered onion message waiting on peer connection {}: {:?}", + log_suffix, + node_id ); }, } @@ -761,11 +810,15 @@ where } fn find_path(&self, destination: Destination) -> Result { - let sender = self.node_signer + let sender = self + .node_signer .get_node_id(Recipient::Node) .map_err(|_| SendError::GetNodeIdFailed)?; - let peers = self.message_recipients.lock().unwrap() + let peers = self + .message_recipients + .lock() + .unwrap() .iter() .filter(|(_, recipient)| matches!(recipient, OnionMessageRecipient::ConnectedPeer(_))) .map(|(node_id, _)| *node_id) @@ -778,12 +831,17 @@ where fn enqueue_onion_message( &self, path: OnionMessagePath, contents: T, reply_path: Option, - log_suffix: fmt::Arguments + log_suffix: fmt::Arguments, ) -> Result { log_trace!(self.logger, "Constructing onion message {}: {:?}", log_suffix, contents); let (first_node_id, onion_message, addresses) = create_onion_message( - &self.entropy_source, &self.node_signer, &self.secp_ctx, path, contents, reply_path + &self.entropy_source, + &self.node_signer, + &self.secp_ctx, + path, + contents, + reply_path, )?; let mut message_recipients = self.message_recipients.lock().unwrap(); @@ -813,27 +871,34 @@ where #[cfg(test)] pub(super) fn send_onion_message_using_path( - &self, path: OnionMessagePath, contents: T, reply_path: Option + &self, path: OnionMessagePath, contents: T, reply_path: Option, ) -> Result { self.enqueue_onion_message(path, contents, reply_path, format_args!("")) } pub(crate) fn peel_onion_message( - &self, msg: &OnionMessage + &self, msg: &OnionMessage, ) -> Result::Target as CustomOnionMessageHandler>::CustomMessage>, ()> { peel_onion_message( - msg, &self.secp_ctx, &*self.node_signer, &*self.logger, &*self.custom_handler + msg, + &self.secp_ctx, + &*self.node_signer, + &*self.logger, + &*self.custom_handler, ) } fn handle_onion_message_response( - &self, response: Option, reply_path: Option, log_suffix: fmt::Arguments + &self, response: Option, reply_path: Option, log_suffix: fmt::Arguments, ) { if let Some(response) = response { match reply_path { Some(reply_path) => { let _ = self.find_path_and_enqueue_onion_message( - response, Destination::BlindedPath(reply_path), None, log_suffix + response, + Destination::BlindedPath(reply_path), + None, + log_suffix, ); }, None => { @@ -856,7 +921,9 @@ where } } -fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap) -> bool { +fn outbound_buffer_full( + peer_node_id: &PublicKey, buffer: &HashMap, +) -> bool { const MAX_TOTAL_BUFFER_SIZE: usize = (1 << 20) * 128; const MAX_PER_PEER_BUFFER_SIZE: usize = (1 << 10) * 256; let mut total_buffered_bytes = 0; @@ -869,10 +936,10 @@ fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap= MAX_TOTAL_BUFFER_SIZE || - peer_buffered_bytes >= MAX_PER_PEER_BUFFER_SIZE + if total_buffered_bytes >= MAX_TOTAL_BUFFER_SIZE + || peer_buffered_bytes >= MAX_PER_PEER_BUFFER_SIZE { - return true + return true; } } } @@ -880,7 +947,7 @@ fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap EventsProvider -for OnionMessenger + for OnionMessenger where ES::Target: EntropySource, NS::Target: NodeSigner, @@ -889,7 +956,10 @@ where OMH::Target: OffersMessageHandler, CMH::Target: CustomOnionMessageHandler, { - fn process_pending_events(&self, handler: H) where H::Target: EventHandler { + fn process_pending_events(&self, handler: H) + where + H::Target: EventHandler, + { for (node_id, recipient) in self.message_recipients.lock().unwrap().iter_mut() { if let OnionMessageRecipient::PendingConnection(_, addresses, _) = recipient { if let Some(addresses) = addresses.take() { @@ -901,7 +971,7 @@ where } impl OnionMessageHandler -for OnionMessenger + for OnionMessenger where ES::Target: EntropySource, NS::Target: NodeSigner, @@ -915,26 +985,33 @@ where Ok(PeeledOnion::Receive(message, path_id, reply_path)) => { log_trace!( self.logger, - "Received an onion message with path_id {:02x?} and {} reply_path: {:?}", - path_id, if reply_path.is_some() { "a" } else { "no" }, message); + "Received an onion message with path_id {:02x?} and {} reply_path: {:?}", + path_id, + if reply_path.is_some() { "a" } else { "no" }, + message + ); match message { ParsedOnionMessageContents::Offers(msg) => { let response = self.offers_handler.handle_message(msg); self.handle_onion_message_response( - response, reply_path, format_args!( + response, + reply_path, + format_args!( "when responding to Offers onion message with path_id {:02x?}", path_id - ) + ), ); }, ParsedOnionMessageContents::Custom(msg) => { let response = self.custom_handler.handle_custom_message(msg); self.handle_onion_message_response( - response, reply_path, format_args!( + response, + reply_path, + format_args!( "when responding to Custom onion message with path_id {:02x?}", path_id - ) + ), ); }, } @@ -942,8 +1019,12 @@ where Ok(PeeledOnion::Forward(next_node_id, onion_message)) => { let mut message_recipients = self.message_recipients.lock().unwrap(); if outbound_buffer_full(&next_node_id, &message_recipients) { - log_trace!(self.logger, "Dropping forwarded onion message to peer {:?}: outbound buffer full", next_node_id); - return + log_trace!( + self.logger, + "Dropping forwarded onion message to peer {:?}: outbound buffer full", + next_node_id + ); + return; } #[cfg(fuzzing)] @@ -952,27 +1033,39 @@ where .or_insert_with(|| OnionMessageRecipient::ConnectedPeer(VecDeque::new())); match message_recipients.entry(next_node_id) { - hash_map::Entry::Occupied(mut e) if matches!( - e.get(), OnionMessageRecipient::ConnectedPeer(..) - ) => { + hash_map::Entry::Occupied(mut e) + if matches!(e.get(), OnionMessageRecipient::ConnectedPeer(..)) => + { e.get_mut().enqueue_message(onion_message); - log_trace!(self.logger, "Forwarding an onion message to peer {}", next_node_id); + log_trace!( + self.logger, + "Forwarding an onion message to peer {}", + next_node_id + ); }, _ => { - log_trace!(self.logger, "Dropping forwarded onion message to disconnected peer {:?}", next_node_id); - return + log_trace!( + self.logger, + "Dropping forwarded onion message to disconnected peer {:?}", + next_node_id + ); + return; }, } }, Err(e) => { log_error!(self.logger, "Failed to process onion message {:?}", e); - } + }, } } - fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init, _inbound: bool) -> Result<(), ()> { + fn peer_connected( + &self, their_node_id: &PublicKey, init: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { if init.features.supports_onion_messages() { - self.message_recipients.lock().unwrap() + self.message_recipients + .lock() + .unwrap() .entry(*their_node_id) .or_insert_with(|| OnionMessageRecipient::ConnectedPeer(VecDeque::new())) .mark_connected(); @@ -1034,7 +1127,10 @@ where #[cfg(c_bindings)] let (contents, destination, reply_path) = message; let _ = self.find_path_and_enqueue_onion_message( - contents, destination, reply_path, format_args!("when sending OffersMessage") + contents, + destination, + reply_path, + format_args!("when sending OffersMessage"), ); } @@ -1045,11 +1141,16 @@ where #[cfg(c_bindings)] let (contents, destination, reply_path) = message; let _ = self.find_path_and_enqueue_onion_message( - contents, destination, reply_path, format_args!("when sending CustomMessage") + contents, + destination, + reply_path, + format_args!("when sending CustomMessage"), ); } - self.message_recipients.lock().unwrap() + self.message_recipients + .lock() + .unwrap() .get_mut(&peer_node_id) .and_then(|buffer| buffer.dequeue_message()) } @@ -1071,7 +1172,7 @@ pub type SimpleArcOnionMessenger = OnionMessenger< Arc, Arc>>, Arc>>, Arc>, - IgnoringMessageHandler + IgnoringMessageHandler, >; /// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and @@ -1082,60 +1183,85 @@ pub type SimpleArcOnionMessenger = OnionMessenger< /// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager /// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager #[cfg(not(c_bindings))] -pub type SimpleRefOnionMessenger< - 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, M, T, F, L -> = OnionMessenger< - &'a KeysManager, - &'a KeysManager, - &'b L, - &'i DefaultMessageRouter<&'g NetworkGraph<&'b L>, &'b L>, - &'j SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>, - IgnoringMessageHandler ->; +pub type SimpleRefOnionMessenger<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, M, T, F, L> = + OnionMessenger< + &'a KeysManager, + &'a KeysManager, + &'b L, + &'i DefaultMessageRouter<&'g NetworkGraph<&'b L>, &'b L>, + &'j SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>, + IgnoringMessageHandler, + >; /// Construct onion packet payloads and keys for sending an onion message along the given /// `unblinded_path` to the given `destination`. -fn packet_payloads_and_keys( +fn packet_payloads_and_keys< + T: OnionMessageContents, + S: secp256k1::Signing + secp256k1::Verification, +>( secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], destination: Destination, message: T, - mut reply_path: Option, session_priv: &SecretKey + mut reply_path: Option, session_priv: &SecretKey, ) -> Result<(Vec<(Payload, [u8; 32])>, Vec), secp256k1::Error> { let num_hops = unblinded_path.len() + destination.num_hops(); let mut payloads = Vec::with_capacity(num_hops); let mut onion_packet_keys = Vec::with_capacity(num_hops); - let (mut intro_node_id_blinding_pt, num_blinded_hops) = if let Destination::BlindedPath(BlindedPath { - introduction_node_id, blinding_point, blinded_hops }) = &destination { - (Some((*introduction_node_id, *blinding_point)), blinded_hops.len()) } else { (None, 0) }; + let (mut intro_node_id_blinding_pt, num_blinded_hops) = + if let Destination::BlindedPath(BlindedPath { + introduction_node_id, + blinding_point, + blinded_hops, + }) = &destination + { + (Some((*introduction_node_id, *blinding_point)), blinded_hops.len()) + } else { + (None, 0) + }; let num_unblinded_hops = num_hops - num_blinded_hops; let mut unblinded_path_idx = 0; let mut blinded_path_idx = 0; let mut prev_control_tlvs_ss = None; let mut final_control_tlvs = None; - utils::construct_keys_callback(secp_ctx, unblinded_path.iter(), Some(destination), session_priv, - |_, onion_packet_ss, ephemeral_pubkey, control_tlvs_ss, unblinded_pk_opt, enc_payload_opt| { + utils::construct_keys_callback( + secp_ctx, + unblinded_path.iter(), + Some(destination), + session_priv, + |_, + onion_packet_ss, + ephemeral_pubkey, + control_tlvs_ss, + unblinded_pk_opt, + enc_payload_opt| { if num_unblinded_hops != 0 && unblinded_path_idx < num_unblinded_hops { if let Some(ss) = prev_control_tlvs_ss.take() { - payloads.push((Payload::Forward(ForwardControlTlvs::Unblinded( - ForwardTlvs { + payloads.push(( + Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs { next_node_id: unblinded_pk_opt.unwrap(), next_blinding_override: None, - } - )), ss)); + })), + ss, + )); } prev_control_tlvs_ss = Some(control_tlvs_ss); unblinded_path_idx += 1; } else if let Some((intro_node_id, blinding_pt)) = intro_node_id_blinding_pt.take() { if let Some(control_tlvs_ss) = prev_control_tlvs_ss.take() { - payloads.push((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs { - next_node_id: intro_node_id, - next_blinding_override: Some(blinding_pt), - })), control_tlvs_ss)); + payloads.push(( + Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs { + next_node_id: intro_node_id, + next_blinding_override: Some(blinding_pt), + })), + control_tlvs_ss, + )); } } if blinded_path_idx < num_blinded_hops.saturating_sub(1) && enc_payload_opt.is_some() { - payloads.push((Payload::Forward(ForwardControlTlvs::Blinded(enc_payload_opt.unwrap())), - control_tlvs_ss)); + payloads.push(( + Payload::Forward(ForwardControlTlvs::Blinded(enc_payload_opt.unwrap())), + control_tlvs_ss, + )); blinded_path_idx += 1; } else if let Some(encrypted_payload) = enc_payload_opt { final_control_tlvs = Some(ReceiveControlTlvs::Blinded(encrypted_payload)); @@ -1152,28 +1278,33 @@ fn packet_payloads_and_keys(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec, prng_seed: [u8; 32]) -> Result { +fn construct_onion_message_packet( + payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec, + prng_seed: [u8; 32], +) -> Result { // Spec rationale: // "`len` allows larger messages to be sent than the standard 1300 bytes allowed for an HTLC // onion, but this should be used sparingly as it is reduces anonymity set, hence the @@ -1183,8 +1314,14 @@ fn construct_onion_message_packet(payloads: Vec<(Payloa SMALL_PACKET_HOP_DATA_LEN } else if payloads_ser_len <= BIG_PACKET_HOP_DATA_LEN { BIG_PACKET_HOP_DATA_LEN - } else { return Err(()) }; + } else { + return Err(()); + }; onion_utils::construct_onion_message_packet::<_, _>( - payloads, onion_keys, prng_seed, hop_data_len) + payloads, + onion_keys, + prng_seed, + hop_data_len, + ) } diff --git a/lightning/src/onion_message/mod.rs b/lightning/src/onion_message/mod.rs index 05a8b7d6fbd..41a1edfe696 100644 --- a/lightning/src/onion_message/mod.rs +++ b/lightning/src/onion_message/mod.rs @@ -21,8 +21,8 @@ //! [blinded paths]: crate::blinded_path::BlindedPath //! [`OnionMessenger`]: self::messenger::OnionMessenger +#[cfg(test)] +mod functional_tests; pub mod messenger; pub mod offers; pub mod packet; -#[cfg(test)] -mod functional_tests; diff --git a/lightning/src/onion_message/offers.rs b/lightning/src/onion_message/offers.rs index 6672b5dfcdd..b914a27fd3f 100644 --- a/lightning/src/onion_message/offers.rs +++ b/lightning/src/onion_message/offers.rs @@ -9,19 +9,19 @@ //! Message handling for BOLT 12 Offers. -use core::convert::TryFrom; -use core::fmt; use crate::io::{self, Read}; use crate::ln::msgs::DecodeError; +use crate::offers::invoice::Bolt12Invoice; use crate::offers::invoice_error::InvoiceError; use crate::offers::invoice_request::InvoiceRequest; -use crate::offers::invoice::Bolt12Invoice; use crate::offers::parse::Bolt12ParseError; +#[cfg(not(c_bindings))] +use crate::onion_message::messenger::PendingOnionMessage; use crate::onion_message::packet::OnionMessageContents; use crate::util::logger::Logger; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; -#[cfg(not(c_bindings))] -use crate::onion_message::messenger::PendingOnionMessage; +use core::convert::TryFrom; +use core::fmt; use crate::prelude::*; @@ -47,14 +47,24 @@ pub trait OffersMessageHandler { /// Typically, this is used for messages initiating a payment flow rather than in response to /// another message. The latter should use the return value of [`Self::handle_message`]. #[cfg(not(c_bindings))] - fn release_pending_messages(&self) -> Vec> { vec![] } + fn release_pending_messages(&self) -> Vec> { + vec![] + } /// Releases any [`OffersMessage`]s that need to be sent. /// /// Typically, this is used for messages initiating a payment flow rather than in response to /// another message. The latter should use the return value of [`Self::handle_message`]. #[cfg(c_bindings)] - fn release_pending_messages(&self) -> Vec<(OffersMessage, crate::onion_message::messenger::Destination, Option)> { vec![] } + fn release_pending_messages( + &self, + ) -> Vec<( + OffersMessage, + crate::onion_message::messenger::Destination, + Option, + )> { + vec![] + } } /// Possible BOLT 12 Offers messages sent and received via an [`OnionMessage`]. @@ -99,13 +109,13 @@ impl fmt::Debug for OffersMessage { match self { OffersMessage::InvoiceRequest(message) => { write!(f, "{:?}", message.as_tlv_stream()) - } + }, OffersMessage::Invoice(message) => { write!(f, "{:?}", message.as_tlv_stream()) - } + }, OffersMessage::InvoiceError(message) => { write!(f, "{:?}", message) - } + }, } } } diff --git a/lightning/src/onion_message/packet.rs b/lightning/src/onion_message/packet.rs index d9349fdadbf..de104aaf5fd 100644 --- a/lightning/src/onion_message/packet.rs +++ b/lightning/src/onion_message/packet.rs @@ -9,23 +9,26 @@ //! Structs and enums useful for constructing and reading an onion message packet. -use bitcoin::secp256k1::PublicKey; use bitcoin::secp256k1::ecdh::SharedSecret; +use bitcoin::secp256k1::PublicKey; -use crate::blinded_path::BlindedPath; +use super::messenger::CustomOnionMessageHandler; +use super::offers::OffersMessage; use crate::blinded_path::message::{ForwardTlvs, ReceiveTlvs}; use crate::blinded_path::utils::Padding; +use crate::blinded_path::BlindedPath; +use crate::crypto::streams::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter}; use crate::ln::msgs::DecodeError; use crate::ln::onion_utils; -use super::messenger::CustomOnionMessageHandler; -use super::offers::OffersMessage; -use crate::crypto::streams::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter}; use crate::util::logger::Logger; -use crate::util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer}; +use crate::util::ser::{ + BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, + ReadableArgs, Writeable, Writer, +}; -use core::cmp; use crate::io::{self, Read}; use crate::prelude::*; +use core::cmp; // Per the spec, an onion message packet's `hop_data` field length should be // SMALL_PACKET_HOP_DATA_LEN if it fits, else BIG_PACKET_HOP_DATA_LEN if it fits. @@ -53,12 +56,7 @@ pub struct Packet { impl onion_utils::Packet for Packet { type Data = Vec; fn new(public_key: PublicKey, hop_data: Vec, hmac: [u8; 32]) -> Packet { - Self { - version: 0, - public_key, - hop_data, - hmac, - } + Self { version: 0, public_key, hop_data, hmac } } } @@ -91,12 +89,7 @@ impl LengthReadable for Packet { } let hmac = Readable::read(r)?; - Ok(Packet { - version, - public_key, - hop_data, - hmac, - }) + Ok(Packet { version, public_key, hop_data, hmac }) } } @@ -107,11 +100,7 @@ pub(super) enum Payload { /// This payload is for an intermediate hop. Forward(ForwardControlTlvs), /// This payload is for the final hop. - Receive { - control_tlvs: ReceiveControlTlvs, - reply_path: Option, - message: T, - } + Receive { control_tlvs: ReceiveControlTlvs, reply_path: Option, message: T }, } /// The contents of an [`OnionMessage`] as read from the wire. @@ -177,12 +166,12 @@ impl Writeable for (Payload, [u8; 32]) { fn write(&self, w: &mut W) -> Result<(), io::Error> { match &self.0 { Payload::Forward(ForwardControlTlvs::Blinded(encrypted_bytes)) => { - _encode_varint_length_prefixed_tlv!(w, { - (4, *encrypted_bytes, required_vec) - }) + _encode_varint_length_prefixed_tlv!(w, { (4, *encrypted_bytes, required_vec) }) }, Payload::Receive { - control_tlvs: ReceiveControlTlvs::Blinded(encrypted_bytes), reply_path, message, + control_tlvs: ReceiveControlTlvs::Blinded(encrypted_bytes), + reply_path, + message, } => { _encode_varint_length_prefixed_tlv!(w, { (2, reply_path, option), @@ -192,12 +181,12 @@ impl Writeable for (Payload, [u8; 32]) { }, Payload::Forward(ForwardControlTlvs::Unblinded(control_tlvs)) => { let write_adapter = ChaChaPolyWriteAdapter::new(self.1, &control_tlvs); - _encode_varint_length_prefixed_tlv!(w, { - (4, write_adapter, required) - }) + _encode_varint_length_prefixed_tlv!(w, { (4, write_adapter, required) }) }, Payload::Receive { - control_tlvs: ReceiveControlTlvs::Unblinded(control_tlvs), reply_path, message, + control_tlvs: ReceiveControlTlvs::Unblinded(control_tlvs), + reply_path, + message, } => { let write_adapter = ChaChaPolyWriteAdapter::new(self.1, &control_tlvs); _encode_varint_length_prefixed_tlv!(w, { @@ -213,7 +202,8 @@ impl Writeable for (Payload, [u8; 32]) { // Uses the provided secret to simultaneously decode and decrypt the control TLVs and data TLV. impl ReadableArgs<(SharedSecret, &H, &L)> -for Payload::CustomMessage>> { + for Payload::CustomMessage>> +{ fn read(r: &mut R, args: (SharedSecret, &H, &L)) -> Result { let (encrypted_tlvs_ss, handler, logger) = args; @@ -252,13 +242,13 @@ for Payload::CustomM match read_adapter { None => return Err(DecodeError::InvalidValue), - Some(ChaChaPolyReadAdapter { readable: ControlTlvs::Forward(tlvs)}) => { + Some(ChaChaPolyReadAdapter { readable: ControlTlvs::Forward(tlvs) }) => { if message_type.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } Ok(Payload::Forward(ForwardControlTlvs::Unblinded(tlvs))) }, - Some(ChaChaPolyReadAdapter { readable: ControlTlvs::Receive(tlvs)}) => { + Some(ChaChaPolyReadAdapter { readable: ControlTlvs::Receive(tlvs) }) => { Ok(Payload::Receive { control_tlvs: ReceiveControlTlvs::Unblinded(tlvs), reply_path, @@ -292,7 +282,7 @@ impl Readable for ControlTlvs { let _padding: Option = _padding; let _short_channel_id: Option = _short_channel_id; - let valid_fwd_fmt = next_node_id.is_some() && path_id.is_none(); + let valid_fwd_fmt = next_node_id.is_some() && path_id.is_none(); let valid_recv_fmt = next_node_id.is_none() && next_blinding_override.is_none(); let payload_fmt = if valid_fwd_fmt { @@ -301,11 +291,9 @@ impl Readable for ControlTlvs { next_blinding_override, }) } else if valid_recv_fmt { - ControlTlvs::Receive(ReceiveTlvs { - path_id, - }) + ControlTlvs::Receive(ReceiveTlvs { path_id }) } else { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); }; Ok(payload_fmt) diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index 9c8fd40af13..98e95d77e5d 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -11,40 +11,47 @@ use bitcoin::blockdata::constants::ChainHash; +use bitcoin::secp256k1; use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE; -use bitcoin::secp256k1::{PublicKey, Verification}; use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1; +use bitcoin::secp256k1::{PublicKey, Verification}; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hashes::Hash; use bitcoin::network::constants::Network; use crate::events::{MessageSendEvent, MessageSendEventsProvider}; -use crate::ln::ChannelId; -use crate::ln::features::{ChannelFeatures, NodeFeatures, InitFeatures}; -use crate::ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, SocketAddress, MAX_VALUE_MSAT}; -use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, GossipTimestampFilter}; -use crate::ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, ReplyShortChannelIdsEnd}; +use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use crate::ln::msgs; +use crate::ln::msgs::{ + ChannelAnnouncement, ChannelUpdate, GossipTimestampFilter, NodeAnnouncement, +}; +use crate::ln::msgs::{ + DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, SocketAddress, + MAX_VALUE_MSAT, +}; +use crate::ln::msgs::{ + QueryChannelRange, QueryShortChannelIds, ReplyChannelRange, ReplyShortChannelIdsEnd, +}; +use crate::ln::ChannelId; use crate::routing::utxo::{self, UtxoLookup, UtxoResolver}; -use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, MaybeReadable}; -use crate::util::logger::{Logger, Level}; +use crate::util::indexed_map::{Entry as IndexedMapEntry, IndexedMap}; +use crate::util::logger::{Level, Logger}; use crate::util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK}; +use crate::util::ser::{MaybeReadable, Readable, ReadableArgs, Writeable, Writer}; use crate::util::string::PrintableString; -use crate::util::indexed_map::{IndexedMap, Entry as IndexedMapEntry}; use crate::io; use crate::io_extras::{copy, sink}; use crate::prelude::*; -use core::{cmp, fmt}; -use core::convert::TryFrom; -use crate::sync::{RwLock, RwLockReadGuard, LockTestExt}; -#[cfg(feature = "std")] -use core::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::Mutex; +use crate::sync::{LockTestExt, RwLock, RwLockReadGuard}; +use core::convert::TryFrom; use core::ops::{Bound, Deref}; use core::str::FromStr; +#[cfg(feature = "std")] +use core::sync::atomic::{AtomicUsize, Ordering}; +use core::{cmp, fmt}; #[cfg(feature = "std")] use std::time::{SystemTime, UNIX_EPOCH}; @@ -166,7 +173,10 @@ impl FromStr for NodeId { } /// Represents the network as nodes and channels between them -pub struct NetworkGraph where L::Target: Logger { +pub struct NetworkGraph +where + L::Target: Logger, +{ secp_ctx: Secp256k1, last_rapid_gossip_sync_timestamp: Mutex>, chain_hash: ChainHash, @@ -232,7 +242,7 @@ pub enum NetworkUpdate { /// Whether the node should be permanently removed from consideration or can be restored /// when a new `channel_update` message is received. is_permanent: bool, - } + }, } impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate, @@ -254,8 +264,10 @@ impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate, /// This network graph is then used for routing payments. /// Provides interface to help with initial routing sync by /// serving historical announcements. -pub struct P2PGossipSync>, U: Deref, L: Deref> -where U::Target: UtxoLookup, L::Target: Logger +pub struct P2PGossipSync>, U: Deref, L: Deref> +where + U::Target: UtxoLookup, + L::Target: Logger, { network_graph: G, utxo_lookup: RwLock>, @@ -265,8 +277,10 @@ where U::Target: UtxoLookup, L::Target: Logger logger: L, } -impl>, U: Deref, L: Deref> P2PGossipSync -where U::Target: UtxoLookup, L::Target: Logger +impl>, U: Deref, L: Deref> P2PGossipSync +where + U::Target: UtxoLookup, + L::Target: Logger, { /// Creates a new tracker of the actual state of the network of channels and nodes, /// assuming an existing [`NetworkGraph`]. @@ -318,20 +332,25 @@ where U::Target: UtxoLookup, L::Target: Logger pub(super) fn forward_gossip_msg(&self, mut ev: MessageSendEvent) { match &mut ev { MessageSendEvent::BroadcastChannelAnnouncement { msg, ref mut update_msg } => { - if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; } - if update_msg.as_ref() - .map(|msg| msg.contents.excess_data.len()).unwrap_or(0) > MAX_EXCESS_BYTES_FOR_RELAY + if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { + return; + } + if update_msg.as_ref().map(|msg| msg.contents.excess_data.len()).unwrap_or(0) + > MAX_EXCESS_BYTES_FOR_RELAY { *update_msg = None; } }, MessageSendEvent::BroadcastChannelUpdate { msg } => { - if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; } + if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { + return; + } }, MessageSendEvent::BroadcastNodeAnnouncement { msg } => { - if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY || - msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY || - msg.contents.excess_data.len() + msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY + if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY + || msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY + || msg.contents.excess_data.len() + msg.contents.excess_address_data.len() + > MAX_EXCESS_BYTES_FOR_RELAY { return; } @@ -342,7 +361,10 @@ where U::Target: UtxoLookup, L::Target: Logger } } -impl NetworkGraph where L::Target: Logger { +impl NetworkGraph +where + L::Target: Logger, +{ /// Handles any network updates originating from [`Event`]s. // /// Note that this will skip applying any [`NetworkUpdate::ChannelUpdateMessage`] to avoid @@ -359,14 +381,21 @@ impl NetworkGraph where L::Target: Logger { }, NetworkUpdate::ChannelFailure { short_channel_id, is_permanent } => { if is_permanent { - log_debug!(self.logger, "Removing channel graph entry for {} due to a payment failure.", short_channel_id); + log_debug!( + self.logger, + "Removing channel graph entry for {} due to a payment failure.", + short_channel_id + ); self.channel_failed_permanent(short_channel_id); } }, NetworkUpdate::NodeFailure { ref node_id, is_permanent } => { if is_permanent { - log_debug!(self.logger, - "Removed node graph entry for {} due to a payment failure.", log_pubkey!(node_id)); + log_debug!( + self.logger, + "Removed node graph entry for {} due to a payment failure.", + log_pubkey!(node_id) + ); self.node_failed_permanent(node_id); }; }, @@ -401,18 +430,17 @@ macro_rules! secp_verify_sig { macro_rules! get_pubkey_from_node_id { ( $node_id: expr, $msg_type: expr ) => { - PublicKey::from_slice($node_id.as_slice()) - .map_err(|_| LightningError { - err: format!("Invalid public key on {} message", $msg_type), - action: ErrorAction::SendWarningMessage { - msg: msgs::WarningMessage { - channel_id: ChannelId::new_zero(), - data: format!("Invalid public key on {} message", $msg_type), - }, - log_level: Level::Trace - } - })? - } + PublicKey::from_slice($node_id.as_slice()).map_err(|_| LightningError { + err: format!("Invalid public key on {} message", $msg_type), + action: ErrorAction::SendWarningMessage { + msg: msgs::WarningMessage { + channel_id: ChannelId::new_zero(), + data: format!("Invalid public key on {} message", $msg_type), + }, + log_level: Level::Trace, + }, + })? + }; } fn message_sha256d_hash(msg: &M) -> Sha256dHash { @@ -424,9 +452,17 @@ fn message_sha256d_hash(msg: &M) -> Sha256dHash { /// Verifies the signature of a [`NodeAnnouncement`]. /// /// Returns an error if it is invalid. -pub fn verify_node_announcement(msg: &NodeAnnouncement, secp_ctx: &Secp256k1) -> Result<(), LightningError> { +pub fn verify_node_announcement( + msg: &NodeAnnouncement, secp_ctx: &Secp256k1, +) -> Result<(), LightningError> { let msg_hash = hash_to_message!(&message_sha256d_hash(&msg.contents)[..]); - secp_verify_sig!(secp_ctx, &msg_hash, &msg.signature, &get_pubkey_from_node_id!(msg.contents.node_id, "node_announcement"), "node_announcement"); + secp_verify_sig!( + secp_ctx, + &msg_hash, + &msg.signature, + &get_pubkey_from_node_id!(msg.contents.node_id, "node_announcement"), + "node_announcement" + ); Ok(()) } @@ -434,28 +470,63 @@ pub fn verify_node_announcement(msg: &NodeAnnouncement, secp_ct /// Verifies all signatures included in a [`ChannelAnnouncement`]. /// /// Returns an error if one of the signatures is invalid. -pub fn verify_channel_announcement(msg: &ChannelAnnouncement, secp_ctx: &Secp256k1) -> Result<(), LightningError> { +pub fn verify_channel_announcement( + msg: &ChannelAnnouncement, secp_ctx: &Secp256k1, +) -> Result<(), LightningError> { let msg_hash = hash_to_message!(&message_sha256d_hash(&msg.contents)[..]); - secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_1, &get_pubkey_from_node_id!(msg.contents.node_id_1, "channel_announcement"), "channel_announcement"); - secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_2, &get_pubkey_from_node_id!(msg.contents.node_id_2, "channel_announcement"), "channel_announcement"); - secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_1, "channel_announcement"), "channel_announcement"); - secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_2, "channel_announcement"), "channel_announcement"); + secp_verify_sig!( + secp_ctx, + &msg_hash, + &msg.node_signature_1, + &get_pubkey_from_node_id!(msg.contents.node_id_1, "channel_announcement"), + "channel_announcement" + ); + secp_verify_sig!( + secp_ctx, + &msg_hash, + &msg.node_signature_2, + &get_pubkey_from_node_id!(msg.contents.node_id_2, "channel_announcement"), + "channel_announcement" + ); + secp_verify_sig!( + secp_ctx, + &msg_hash, + &msg.bitcoin_signature_1, + &get_pubkey_from_node_id!(msg.contents.bitcoin_key_1, "channel_announcement"), + "channel_announcement" + ); + secp_verify_sig!( + secp_ctx, + &msg_hash, + &msg.bitcoin_signature_2, + &get_pubkey_from_node_id!(msg.contents.bitcoin_key_2, "channel_announcement"), + "channel_announcement" + ); Ok(()) } -impl>, U: Deref, L: Deref> RoutingMessageHandler for P2PGossipSync -where U::Target: UtxoLookup, L::Target: Logger +impl>, U: Deref, L: Deref> RoutingMessageHandler + for P2PGossipSync +where + U::Target: UtxoLookup, + L::Target: Logger, { - fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result { + fn handle_node_announcement( + &self, msg: &msgs::NodeAnnouncement, + ) -> Result { self.network_graph.update_node_from_announcement(msg)?; - Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY && - msg.contents.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY && - msg.contents.excess_data.len() + msg.contents.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY) + Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY + && msg.contents.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY + && msg.contents.excess_data.len() + msg.contents.excess_address_data.len() + <= MAX_EXCESS_BYTES_FOR_RELAY) } - fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result { - self.network_graph.update_channel_from_announcement(msg, &*self.utxo_lookup.read().unwrap())?; + fn handle_channel_announcement( + &self, msg: &msgs::ChannelAnnouncement, + ) -> Result { + self.network_graph + .update_channel_from_announcement(msg, &*self.utxo_lookup.read().unwrap())?; Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY) } @@ -464,7 +535,9 @@ where U::Target: UtxoLookup, L::Target: Logger Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY) } - 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)> { let mut channels = self.network_graph.channels.write().unwrap(); for (_, ref chan) in channels.range(starting_point..) { if chan.announcement_message.is_some() { @@ -486,13 +559,15 @@ where U::Target: UtxoLookup, L::Target: Logger None } - fn get_next_node_announcement(&self, starting_point: Option<&NodeId>) -> Option { + fn get_next_node_announcement( + &self, starting_point: Option<&NodeId>, + ) -> Option { let mut nodes = self.network_graph.nodes.write().unwrap(); let iter = if let Some(node_id) = starting_point { - nodes.range((Bound::Excluded(node_id), Bound::Unbounded)) - } else { - nodes.range(..) - }; + nodes.range((Bound::Excluded(node_id), Bound::Unbounded)) + } else { + nodes.range(..) + }; for (_, ref node) in iter { if let Some(node_info) = node.announcement_info.as_ref() { if let Some(msg) = node_info.announcement_message.clone() { @@ -518,7 +593,9 @@ where U::Target: UtxoLookup, L::Target: Logger /// [`query_channel_range`]: msgs::QueryChannelRange /// [`query_scid`]: msgs::QueryShortChannelIds /// [`reply_scids_end`]: msgs::ReplyShortChannelIdsEnd - fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &Init, _inbound: bool) -> Result<(), ()> { + fn peer_connected( + &self, their_node_id: &PublicKey, init_msg: &Init, _inbound: bool, + ) -> Result<(), ()> { // We will only perform a sync with peers that support gossip_queries. if !init_msg.features.supports_gossip_queries() { // Don't disconnect peers for not supporting gossip queries. We may wish to have @@ -580,7 +657,10 @@ where U::Target: UtxoLookup, L::Target: Logger let mut gossip_start_time = 0; #[cfg(feature = "std")] { - gossip_start_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); + gossip_start_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); if self.should_request_full_sync(&their_node_id) { gossip_start_time -= 60 * 60 * 24 * 7 * 2; // 2 weeks ago } else { @@ -600,14 +680,18 @@ where U::Target: UtxoLookup, L::Target: Logger Ok(()) } - 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> { // We don't make queries, so should never receive replies. If, in the future, the set // reconciliation extensions to gossip queries become broadly supported, we should revert // this code to its state pre-0.0.106. Ok(()) } - 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> { // We don't make queries, so should never receive replies. If, in the future, the set // reconciliation extensions to gossip queries become broadly supported, we should revert // this code to its state pre-0.0.106. @@ -621,17 +705,30 @@ where U::Target: UtxoLookup, L::Target: Logger /// sync of the public routing table with 128k channels will generated 16 messages and allocate ~1MB. /// Logic can be changed to reduce allocation if/when a full sync of the routing table impacts /// memory constrained systems. - fn handle_query_channel_range(&self, their_node_id: &PublicKey, msg: QueryChannelRange) -> Result<(), LightningError> { - log_debug!(self.logger, "Handling query_channel_range peer={}, first_blocknum={}, number_of_blocks={}", log_pubkey!(their_node_id), msg.first_blocknum, msg.number_of_blocks); + fn handle_query_channel_range( + &self, their_node_id: &PublicKey, msg: QueryChannelRange, + ) -> Result<(), LightningError> { + log_debug!( + self.logger, + "Handling query_channel_range peer={}, first_blocknum={}, number_of_blocks={}", + log_pubkey!(their_node_id), + msg.first_blocknum, + msg.number_of_blocks + ); let inclusive_start_scid = scid_from_parts(msg.first_blocknum as u64, 0, 0); // We might receive valid queries with end_blocknum that would overflow SCID conversion. // If so, we manually cap the ending block to avoid this overflow. - let exclusive_end_scid = scid_from_parts(cmp::min(msg.end_blocknum() as u64, MAX_SCID_BLOCK), 0, 0); + let exclusive_end_scid = + scid_from_parts(cmp::min(msg.end_blocknum() as u64, MAX_SCID_BLOCK), 0, 0); // Per spec, we must reply to a query. Send an empty message when things are invalid. - if msg.chain_hash != self.network_graph.chain_hash || inclusive_start_scid.is_err() || exclusive_end_scid.is_err() || msg.number_of_blocks == 0 { + if msg.chain_hash != self.network_graph.chain_hash + || inclusive_start_scid.is_err() + || exclusive_end_scid.is_err() + || msg.number_of_blocks == 0 + { let mut pending_events = self.pending_events.lock().unwrap(); pending_events.push(MessageSendEvent::SendReplyChannelRange { node_id: their_node_id.clone(), @@ -641,7 +738,7 @@ where U::Target: UtxoLookup, L::Target: Logger number_of_blocks: msg.number_of_blocks, sync_complete: true, short_channel_ids: vec![], - } + }, }); return Err(LightningError { err: String::from("query_channel_range could not be processed"), @@ -654,7 +751,9 @@ where U::Target: UtxoLookup, L::Target: Logger // exists even if its not yet routable. let mut batches: Vec> = vec![Vec::with_capacity(MAX_SCIDS_PER_REPLY)]; let mut channels = self.network_graph.channels.write().unwrap(); - for (_, ref chan) in channels.range(inclusive_start_scid.unwrap()..exclusive_end_scid.unwrap()) { + for (_, ref chan) in + channels.range(inclusive_start_scid.unwrap()..exclusive_end_scid.unwrap()) + { if let Some(chan_announcement) = &chan.announcement_message { // Construct a new batch if last one is full if batches.last().unwrap().len() == batches.last().unwrap().capacity() { @@ -692,7 +791,7 @@ where U::Target: UtxoLookup, L::Target: Logger // // Overflow safe since end_blocknum=msg.first_block_num+msg.number_of_blocks and // first_blocknum will be either msg.first_blocknum or a higher block height. - let (sync_complete, number_of_blocks) = if batch_index == batch_count-1 { + let (sync_complete, number_of_blocks) = if batch_index == batch_count - 1 { (true, msg.end_blocknum() - first_blocknum) } // Prior replies should use the number of blocks that fit into the reply. Overflow @@ -711,14 +810,16 @@ where U::Target: UtxoLookup, L::Target: Logger number_of_blocks, sync_complete, short_channel_ids: batch, - } + }, }); } Ok(()) } - 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> { // TODO Err(LightningError { err: String::from("Not implemented"), @@ -743,7 +844,8 @@ where U::Target: UtxoLookup, L::Target: Logger } } -impl>, U: Deref, L: Deref> MessageSendEventsProvider for P2PGossipSync +impl>, U: Deref, L: Deref> MessageSendEventsProvider + for P2PGossipSync where U::Target: UtxoLookup, L::Target: Logger, @@ -781,7 +883,15 @@ pub struct ChannelUpdateInfo { impl fmt::Display for ChannelUpdateInfo { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "last_update {}, enabled {}, cltv_expiry_delta {}, htlc_minimum_msat {}, fees {:?}", self.last_update, self.enabled, self.cltv_expiry_delta, self.htlc_minimum_msat, self.fees)?; + write!( + f, + "last_update {}, enabled {}, cltv_expiry_delta {}, htlc_minimum_msat {}, fees {:?}", + self.last_update, + self.enabled, + self.cltv_expiry_delta, + self.htlc_minimum_msat, + self.fees + )?; Ok(()) } } @@ -910,8 +1020,15 @@ impl ChannelInfo { impl fmt::Display for ChannelInfo { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "features: {}, node_one: {}, one_to_two: {:?}, node_two: {}, two_to_one: {:?}", - log_bytes!(self.features.encode()), &self.node_one, self.one_to_two, &self.node_two, self.two_to_one)?; + write!( + f, + "features: {}, node_one: {}, one_to_two: {:?}, node_two: {}, two_to_one: {:?}", + log_bytes!(self.features.encode()), + &self.node_one, + self.one_to_two, + &self.node_two, + self.two_to_one + )?; Ok(()) } } @@ -979,7 +1096,10 @@ impl Readable for ChannelInfo { two_to_one: two_to_one_wrap.map(|w| w.0).unwrap_or(None), capacity_sats: _init_tlv_based_struct_field!(capacity_sats, required), announcement_message: _init_tlv_based_struct_field!(announcement_message, required), - announcement_received_time: _init_tlv_based_struct_field!(announcement_received_time, (default_value, 0)), + announcement_received_time: _init_tlv_based_struct_field!( + announcement_received_time, + (default_value, 0) + ), }) } } @@ -997,13 +1117,17 @@ pub struct DirectedChannelInfo<'a> { impl<'a> DirectedChannelInfo<'a> { #[inline] - fn new(channel: &'a ChannelInfo, direction: &'a ChannelUpdateInfo, from_node_one: bool) -> Self { + fn new( + channel: &'a ChannelInfo, direction: &'a ChannelUpdateInfo, from_node_one: bool, + ) -> Self { Self { channel, direction, from_node_one } } /// Returns information for the channel. #[inline] - pub fn channel(&self) -> &'a ChannelInfo { self.channel } + pub fn channel(&self) -> &'a ChannelInfo { + self.channel + } /// Returns the [`EffectiveCapacity`] of the channel in the direction. /// @@ -1026,26 +1150,38 @@ impl<'a> DirectedChannelInfo<'a> { /// Returns information for the direction. #[inline] - pub(super) fn direction(&self) -> &'a ChannelUpdateInfo { self.direction } + pub(super) fn direction(&self) -> &'a ChannelUpdateInfo { + self.direction + } /// Returns the `node_id` of the source hop. /// /// Refers to the `node_id` forwarding the payment to the next hop. #[inline] - pub(super) fn source(&self) -> &'a NodeId { if self.from_node_one { &self.channel.node_one } else { &self.channel.node_two } } + pub(super) fn source(&self) -> &'a NodeId { + if self.from_node_one { + &self.channel.node_one + } else { + &self.channel.node_two + } + } /// Returns the `node_id` of the target hop. /// /// Refers to the `node_id` receiving the payment from the previous hop. #[inline] - pub(super) fn target(&self) -> &'a NodeId { if self.from_node_one { &self.channel.node_two } else { &self.channel.node_one } } + pub(super) fn target(&self) -> &'a NodeId { + if self.from_node_one { + &self.channel.node_two + } else { + &self.channel.node_one + } + } } impl<'a> fmt::Debug for DirectedChannelInfo<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.debug_struct("DirectedChannelInfo") - .field("channel", &self.channel) - .finish() + f.debug_struct("DirectedChannelInfo").field("channel", &self.channel).finish() } } @@ -1072,7 +1208,7 @@ pub enum EffectiveCapacity { /// The funding amount denominated in millisatoshi. capacity_msat: u64, /// The maximum HTLC amount denominated in millisatoshi. - htlc_maximum_msat: u64 + htlc_maximum_msat: u64, }, /// A capacity sufficient to route any payment, typically used for private channels provided by /// an invoice. @@ -1138,13 +1274,14 @@ pub struct NodeAnnouncementInfo { /// Mostly redundant with the data we store in fields explicitly. /// Everything else is useful only for sending out for initial routing sync. /// Not stored if contains excess data to prevent DoS. - pub announcement_message: Option + pub announcement_message: Option, } impl NodeAnnouncementInfo { /// Internet-level addresses via which one can connect to the node pub fn addresses(&self) -> &[SocketAddress] { - self.announcement_message.as_ref() + self.announcement_message + .as_ref() .map(|msg| msg.contents.addresses.as_slice()) .unwrap_or_default() } @@ -1176,8 +1313,13 @@ impl Readable for NodeAnnouncementInfo { (10, _addresses, optional_vec), // deprecated, not used anymore }); let _: Option> = _addresses; - Ok(Self { features: features.0.unwrap(), last_update: last_update.0.unwrap(), rgb: rgb.0.unwrap(), - alias: alias.0.unwrap(), announcement_message }) + Ok(Self { + features: features.0.unwrap(), + last_update: last_update.0.unwrap(), + rgb: rgb.0.unwrap(), + alias: alias.0.unwrap(), + announcement_message, + }) } } @@ -1228,13 +1370,17 @@ pub struct NodeInfo { /// More information about a node from node_announcement. /// Optional because we store a Node entry after learning about it from /// a channel announcement, but before receiving a node announcement. - pub announcement_info: Option + pub announcement_info: Option, } impl fmt::Display for NodeInfo { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, " channels: {:?}, announcement_info: {:?}", - &self.channels[..], self.announcement_info)?; + write!( + f, + " channels: {:?}, announcement_info: {:?}", + &self.channels[..], + self.announcement_info + )?; Ok(()) } } @@ -1262,7 +1408,7 @@ impl MaybeReadable for NodeAnnouncementInfoDeserWrapper { Ok(node_announcement_info) => return Ok(Some(Self(node_announcement_info))), Err(_) => { copy(reader, &mut sink()).unwrap(); - return Ok(None) + return Ok(None); }, }; } @@ -1281,19 +1427,20 @@ impl Readable for NodeInfo { (4, channels, required_vec), }); let _: Option = _lowest_inbound_channel_fees; - let announcement_info_wrap: Option = announcement_info_wrap; + let announcement_info_wrap: Option = + announcement_info_wrap; - Ok(NodeInfo { - announcement_info: announcement_info_wrap.map(|w| w.0), - channels, - }) + Ok(NodeInfo { announcement_info: announcement_info_wrap.map(|w| w.0), channels }) } } const SERIALIZATION_VERSION: u8 = 1; const MIN_SERIALIZATION_VERSION: u8 = 1; -impl Writeable for NetworkGraph where L::Target: Logger { +impl Writeable for NetworkGraph +where + L::Target: Logger, +{ fn write(&self, writer: &mut W) -> Result<(), io::Error> { write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION); @@ -1319,7 +1466,10 @@ impl Writeable for NetworkGraph where L::Target: Logger { } } -impl ReadableArgs for NetworkGraph where L::Target: Logger { +impl ReadableArgs for NetworkGraph +where + L::Target: Logger, +{ fn read(reader: &mut R, logger: L) -> Result, DecodeError> { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); @@ -1360,7 +1510,10 @@ impl ReadableArgs for NetworkGraph where L::Target: Logger { } } -impl fmt::Display for NetworkGraph where L::Target: Logger { +impl fmt::Display for NetworkGraph +where + L::Target: Logger, +{ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { writeln!(f, "Network map\n[Channels]")?; for (key, val) in self.channels.read().unwrap().unordered_iter() { @@ -1375,20 +1528,32 @@ impl fmt::Display for NetworkGraph where L::Target: Logger { } impl Eq for NetworkGraph where L::Target: Logger {} -impl PartialEq for NetworkGraph where L::Target: Logger { +impl PartialEq for NetworkGraph +where + L::Target: Logger, +{ fn eq(&self, other: &Self) -> bool { // For a total lockorder, sort by position in memory and take the inner locks in that order. // (Assumes 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.channels, &self.nodes) } else { (&other.channels, &other.nodes) }; let b = if ord { (&other.channels, &other.nodes) } else { (&self.channels, &self.nodes) }; - let (channels_a, channels_b) = (a.0.unsafe_well_ordered_double_lock_self(), b.0.unsafe_well_ordered_double_lock_self()); - let (nodes_a, nodes_b) = (a.1.unsafe_well_ordered_double_lock_self(), b.1.unsafe_well_ordered_double_lock_self()); + let (channels_a, channels_b) = ( + a.0.unsafe_well_ordered_double_lock_self(), + b.0.unsafe_well_ordered_double_lock_self(), + ); + let (nodes_a, nodes_b) = ( + a.1.unsafe_well_ordered_double_lock_self(), + b.1.unsafe_well_ordered_double_lock_self(), + ); self.chain_hash.eq(&other.chain_hash) && channels_a.eq(&channels_b) && nodes_a.eq(&nodes_b) } } -impl NetworkGraph where L::Target: Logger { +impl NetworkGraph +where + L::Target: Logger, +{ /// Creates a new, empty, network graph. pub fn new(network: Network, logger: L) -> NetworkGraph { Self { @@ -1408,10 +1573,7 @@ impl NetworkGraph where L::Target: Logger { pub fn read_only(&'_ self) -> ReadOnlyNetworkGraph<'_> { let channels = self.channels.read().unwrap(); let nodes = self.nodes.read().unwrap(); - ReadOnlyNetworkGraph { - channels, - nodes, - } + ReadOnlyNetworkGraph { channels, nodes } } /// The unix timestamp provided by the most recent rapid gossip sync. @@ -1423,7 +1585,10 @@ impl NetworkGraph where L::Target: Logger { /// Update the unix timestamp provided by the most recent rapid gossip sync. /// This should be done automatically by the rapid sync process after every sync completion. pub fn set_last_rapid_gossip_sync_timestamp(&self, last_rapid_gossip_sync_timestamp: u32) { - self.last_rapid_gossip_sync_timestamp.lock().unwrap().replace(last_rapid_gossip_sync_timestamp); + self.last_rapid_gossip_sync_timestamp + .lock() + .unwrap() + .replace(last_rapid_gossip_sync_timestamp); } /// Clears the `NodeAnnouncementInfo` field for all nodes in the `NetworkGraph` for testing @@ -1441,7 +1606,9 @@ impl NetworkGraph where L::Target: Logger { /// You probably don't want to call this directly, instead relying on a P2PGossipSync's /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept /// routing messages from a source using a protocol other than the lightning P2P protocol. - pub fn update_node_from_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<(), LightningError> { + pub fn update_node_from_announcement( + &self, msg: &msgs::NodeAnnouncement, + ) -> Result<(), LightningError> { verify_node_announcement(msg, &self.secp_ctx)?; self.update_node_from_announcement_intern(&msg.contents, Some(&msg)) } @@ -1450,34 +1617,48 @@ impl NetworkGraph where L::Target: Logger { /// given node announcement without verifying the associated signatures. Because we aren't /// given the associated signatures here we cannot relay the node announcement to any of our /// peers. - pub fn update_node_from_unsigned_announcement(&self, msg: &msgs::UnsignedNodeAnnouncement) -> Result<(), LightningError> { + pub fn update_node_from_unsigned_announcement( + &self, msg: &msgs::UnsignedNodeAnnouncement, + ) -> Result<(), LightningError> { self.update_node_from_announcement_intern(msg, None) } - fn update_node_from_announcement_intern(&self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement>) -> Result<(), LightningError> { + fn update_node_from_announcement_intern( + &self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement>, + ) -> Result<(), LightningError> { let mut nodes = self.nodes.write().unwrap(); match nodes.get_mut(&msg.node_id) { None => { core::mem::drop(nodes); self.pending_checks.check_hold_pending_node_announcement(msg, full_msg)?; - Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError}) + Err(LightningError { + err: "No existing channels for node_announcement".to_owned(), + action: ErrorAction::IgnoreError, + }) }, Some(node) => { if let Some(node_info) = node.announcement_info.as_ref() { // The timestamp field is somewhat of a misnomer - the BOLTs use it to order // updates to ensure you always have the latest one, only vaguely suggesting // that it be at least the current time. - if node_info.last_update > msg.timestamp { - return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip}); - } else if node_info.last_update == msg.timestamp { - return Err(LightningError{err: "Update had the same timestamp as last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip}); + if node_info.last_update > msg.timestamp { + return Err(LightningError { + err: "Update older than last processed update".to_owned(), + action: ErrorAction::IgnoreDuplicateGossip, + }); + } else if node_info.last_update == msg.timestamp { + return Err(LightningError { + err: "Update had the same timestamp as last processed update" + .to_owned(), + action: ErrorAction::IgnoreDuplicateGossip, + }); } } - let should_relay = - msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY && - msg.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY && - msg.excess_data.len() + msg.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY; + let should_relay = msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY + && msg.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY + && msg.excess_data.len() + msg.excess_address_data.len() + <= MAX_EXCESS_BYTES_FOR_RELAY; node.announcement_info = Some(NodeAnnouncementInfo { features: msg.features.clone(), last_update: msg.timestamp, @@ -1487,7 +1668,7 @@ impl NetworkGraph where L::Target: Logger { }); Ok(()) - } + }, } } @@ -1517,7 +1698,7 @@ impl NetworkGraph where L::Target: Logger { /// /// This will skip verification of if the channel is actually on-chain. pub fn update_channel_from_announcement_no_lookup( - &self, msg: &ChannelAnnouncement + &self, msg: &ChannelAnnouncement, ) -> Result<(), LightningError> { self.update_channel_from_announcement::<&UtxoResolver>(msg, &None) } @@ -1529,7 +1710,7 @@ impl NetworkGraph where L::Target: Logger { /// If a [`UtxoLookup`] object is provided via `utxo_lookup`, it will be called to verify /// the corresponding UTXO exists on chain and is correctly-formatted. pub fn update_channel_from_unsigned_announcement( - &self, msg: &msgs::UnsignedChannelAnnouncement, utxo_lookup: &Option + &self, msg: &msgs::UnsignedChannelAnnouncement, utxo_lookup: &Option, ) -> Result<(), LightningError> where U::Target: UtxoLookup, @@ -1543,9 +1724,15 @@ impl NetworkGraph where L::Target: Logger { /// rapid gossip sync server) /// /// All other parameters as used in [`msgs::UnsignedChannelAnnouncement`] fields. - pub fn add_channel_from_partial_announcement(&self, short_channel_id: u64, timestamp: u64, features: ChannelFeatures, node_id_1: PublicKey, node_id_2: PublicKey) -> Result<(), LightningError> { + pub fn add_channel_from_partial_announcement( + &self, short_channel_id: u64, timestamp: u64, features: ChannelFeatures, + node_id_1: PublicKey, node_id_2: PublicKey, + ) -> Result<(), LightningError> { if node_id_1 == node_id_2 { - return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Channel announcement node had a channel with itself".to_owned(), + action: ErrorAction::IgnoreError, + }); }; let node_1 = NodeId::from_pubkey(&node_id_1); @@ -1564,14 +1751,22 @@ impl NetworkGraph where L::Target: Logger { self.add_channel_between_nodes(short_channel_id, channel_info, None) } - fn add_channel_between_nodes(&self, short_channel_id: u64, channel_info: ChannelInfo, utxo_value: Option) -> Result<(), LightningError> { + fn add_channel_between_nodes( + &self, short_channel_id: u64, channel_info: ChannelInfo, utxo_value: Option, + ) -> Result<(), LightningError> { let mut channels = self.channels.write().unwrap(); let mut nodes = self.nodes.write().unwrap(); let node_id_a = channel_info.node_one.clone(); let node_id_b = channel_info.node_two.clone(); - log_gossip!(self.logger, "Adding channel {} between nodes {} and {}", short_channel_id, node_id_a, node_id_b); + log_gossip!( + self.logger, + "Adding channel {} between nodes {} and {}", + short_channel_id, + node_id_a, + node_id_b + ); match channels.entry(short_channel_id) { IndexedMapEntry::Occupied(mut entry) => { @@ -1590,12 +1785,15 @@ impl NetworkGraph where L::Target: Logger { Self::remove_channel_in_nodes(&mut nodes, &entry.get(), short_channel_id); *entry.get_mut() = channel_info; } else { - return Err(LightningError{err: "Already have knowledge of channel".to_owned(), action: ErrorAction::IgnoreDuplicateGossip}); + return Err(LightningError { + err: "Already have knowledge of channel".to_owned(), + action: ErrorAction::IgnoreDuplicateGossip, + }); } }, IndexedMapEntry::Vacant(entry) => { entry.insert(channel_info); - } + }, }; for current_node_id in [node_id_a, node_id_b].iter() { @@ -1605,24 +1803,28 @@ impl NetworkGraph where L::Target: Logger { }, IndexedMapEntry::Vacant(node_entry) => { node_entry.insert(NodeInfo { - channels: vec!(short_channel_id), + channels: vec![short_channel_id], announcement_info: None, }); - } + }, }; - }; + } Ok(()) } fn update_channel_from_unsigned_announcement_intern( - &self, msg: &msgs::UnsignedChannelAnnouncement, full_msg: Option<&msgs::ChannelAnnouncement>, utxo_lookup: &Option + &self, msg: &msgs::UnsignedChannelAnnouncement, + full_msg: Option<&msgs::ChannelAnnouncement>, utxo_lookup: &Option, ) -> Result<(), LightningError> where U::Target: UtxoLookup, { if msg.node_id_1 == msg.node_id_2 || msg.bitcoin_key_1 == msg.bitcoin_key_2 { - return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Channel announcement node had a channel with itself".to_owned(), + action: ErrorAction::IgnoreError, + }); } if msg.chain_hash != self.chain_hash { @@ -1651,7 +1853,7 @@ impl NetworkGraph where L::Target: Logger { if msg.node_id_1 == chan.node_one && msg.node_id_2 == chan.node_two { return Err(LightningError { err: "Already have chain-validated channel".to_owned(), - action: ErrorAction::IgnoreDuplicateGossip + action: ErrorAction::IgnoreDuplicateGossip, }); } } else if utxo_lookup.is_none() { @@ -1659,7 +1861,7 @@ impl NetworkGraph where L::Target: Logger { // duplicate announcement without bothering to take the channels write lock. return Err(LightningError { err: "Already have non-chain-validated channel".to_owned(), - action: ErrorAction::IgnoreDuplicateGossip + action: ErrorAction::IgnoreDuplicateGossip, }); } } @@ -1668,23 +1870,27 @@ impl NetworkGraph where L::Target: Logger { { let removed_channels = self.removed_channels.lock().unwrap(); let removed_nodes = self.removed_nodes.lock().unwrap(); - if removed_channels.contains_key(&msg.short_channel_id) || - removed_nodes.contains_key(&msg.node_id_1) || - removed_nodes.contains_key(&msg.node_id_2) { + if removed_channels.contains_key(&msg.short_channel_id) + || removed_nodes.contains_key(&msg.node_id_1) + || removed_nodes.contains_key(&msg.node_id_2) + { return Err(LightningError{ err: format!("Channel with SCID {} or one of its nodes was removed from our network graph recently", &msg.short_channel_id), action: ErrorAction::IgnoreAndLog(Level::Gossip)}); } } - let utxo_value = self.pending_checks.check_channel_announcement( - utxo_lookup, msg, full_msg)?; + let utxo_value = + self.pending_checks.check_channel_announcement(utxo_lookup, msg, full_msg)?; #[allow(unused_mut, unused_assignments)] let mut announcement_received_time = 0; #[cfg(feature = "std")] { - announcement_received_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); + announcement_received_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); } let chan_info = ChannelInfo { @@ -1694,14 +1900,22 @@ impl NetworkGraph where L::Target: Logger { node_two: msg.node_id_2, two_to_one: None, capacity_sats: utxo_value, - announcement_message: if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY - { full_msg.cloned() } else { None }, + announcement_message: if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY { + full_msg.cloned() + } else { + None + }, announcement_received_time, }; self.add_channel_between_nodes(msg.short_channel_id, chan_info, utxo_value)?; - log_gossip!(self.logger, "Added channel_announcement for {}{}", msg.short_channel_id, if !msg.excess_data.is_empty() { " with excess uninterpreted data!" } else { "" }); + log_gossip!( + self.logger, + "Added channel_announcement for {}{}", + msg.short_channel_id, + if !msg.excess_data.is_empty() { " with excess uninterpreted data!" } else { "" } + ); Ok(()) } @@ -1710,7 +1924,9 @@ impl NetworkGraph where L::Target: Logger { /// The channel and any node for which this was their last channel are removed from the graph. pub fn channel_failed_permanent(&self, short_channel_id: u64) { #[cfg(feature = "std")] - let current_time_unix = Some(SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs()); + let current_time_unix = Some( + SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(), + ); #[cfg(not(feature = "std"))] let current_time_unix = None; @@ -1720,7 +1936,9 @@ impl NetworkGraph where L::Target: Logger { /// Marks a channel in the graph as failed permanently. /// /// The channel and any node for which this was their last channel are removed from the graph. - fn channel_failed_permanent_with_time(&self, short_channel_id: u64, current_time_unix: Option) { + fn channel_failed_permanent_with_time( + &self, short_channel_id: u64, current_time_unix: Option, + ) { let mut channels = self.channels.write().unwrap(); if let Some(chan) = channels.remove(&short_channel_id) { let mut nodes = self.nodes.write().unwrap(); @@ -1733,7 +1951,9 @@ impl NetworkGraph where L::Target: Logger { /// from local storage. pub fn node_failed_permanent(&self, node_id: &PublicKey) { #[cfg(feature = "std")] - let current_time_unix = Some(SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs()); + let current_time_unix = Some( + SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(), + ); #[cfg(not(feature = "std"))] let current_time_unix = None; @@ -1746,11 +1966,15 @@ impl NetworkGraph where L::Target: Logger { if let Some(node) = nodes.remove(&node_id) { for scid in node.channels.iter() { if let Some(chan_info) = channels.remove(scid) { - let other_node_id = if node_id == chan_info.node_one { chan_info.node_two } else { chan_info.node_one }; - if let IndexedMapEntry::Occupied(mut other_node_entry) = nodes.entry(other_node_id) { - other_node_entry.get_mut().channels.retain(|chan_id| { - *scid != *chan_id - }); + let other_node_id = if node_id == chan_info.node_one { + chan_info.node_two + } else { + chan_info.node_one + }; + if let IndexedMapEntry::Occupied(mut other_node_entry) = + nodes.entry(other_node_id) + { + other_node_entry.get_mut().channels.retain(|chan_id| *scid != *chan_id); if other_node_entry.get().channels.is_empty() { other_node_entry.remove_entry(); } @@ -1780,7 +2004,8 @@ impl NetworkGraph where L::Target: Logger { /// This method is only available with the `std` feature. See /// [`NetworkGraph::remove_stale_channels_and_tracking_with_time`] for `no-std` use. pub fn remove_stale_channels_and_tracking(&self) { - let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); + let time = + SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); self.remove_stale_channels_and_tracking_with_time(time); } @@ -1800,19 +2025,27 @@ impl NetworkGraph where L::Target: Logger { pub fn remove_stale_channels_and_tracking_with_time(&self, current_time_unix: u64) { let mut channels = self.channels.write().unwrap(); // Time out if we haven't received an update in at least 14 days. - if current_time_unix > u32::max_value() as u64 { return; } // Remove by 2106 - if current_time_unix < STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS { return; } + if current_time_unix > u32::max_value() as u64 { + return; + } // Remove by 2106 + if current_time_unix < STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS { + return; + } let min_time_unix: u32 = (current_time_unix - STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS) as u32; // Sadly BTreeMap::retain was only stabilized in 1.53 so we can't switch to it for some // time. let mut scids_to_remove = Vec::new(); for (scid, info) in channels.unordered_iter_mut() { - if info.one_to_two.is_some() && info.one_to_two.as_ref().unwrap().last_update < min_time_unix { + if info.one_to_two.is_some() + && info.one_to_two.as_ref().unwrap().last_update < min_time_unix + { log_gossip!(self.logger, "Removing directional update one_to_two (0) for channel {} due to its timestamp {} being below {}", scid, info.one_to_two.as_ref().unwrap().last_update, min_time_unix); info.one_to_two = None; } - if info.two_to_one.is_some() && info.two_to_one.as_ref().unwrap().last_update < min_time_unix { + if info.two_to_one.is_some() + && info.two_to_one.as_ref().unwrap().last_update < min_time_unix + { log_gossip!(self.logger, "Removing directional update two_to_one (1) for channel {} due to its timestamp {} being below {}", scid, info.two_to_one.as_ref().unwrap().last_update, min_time_unix); info.two_to_one = None; @@ -1832,7 +2065,9 @@ impl NetworkGraph where L::Target: Logger { if !scids_to_remove.is_empty() { let mut nodes = self.nodes.write().unwrap(); for scid in scids_to_remove { - let info = channels.remove(&scid).expect("We just accessed this scid, it should be present"); + let info = channels + .remove(&scid) + .expect("We just accessed this scid, it should be present"); Self::remove_channel_in_nodes(&mut nodes, &info, scid); self.removed_channels.lock().unwrap().insert(scid, Some(current_time_unix)); } @@ -1853,7 +2088,8 @@ impl NetworkGraph where L::Target: Logger { } #[allow(unreachable_code)] false - }}; + } + }; self.removed_channels.lock().unwrap().retain(|_, time| should_keep_tracking(time)); self.removed_nodes.lock().unwrap().retain(|_, time| should_keep_tracking(time)); @@ -1878,7 +2114,9 @@ impl NetworkGraph where L::Target: Logger { /// /// If built with `no-std`, any updates with a timestamp more than two weeks in the past or /// materially in the future will be rejected. - pub fn update_channel_unsigned(&self, msg: &msgs::UnsignedChannelUpdate) -> Result<(), LightningError> { + pub fn update_channel_unsigned( + &self, msg: &msgs::UnsignedChannelUpdate, + ) -> Result<(), LightningError> { self.update_channel_internal(msg, None, None, false) } @@ -1892,10 +2130,10 @@ impl NetworkGraph where L::Target: Logger { self.update_channel_internal(&msg.contents, Some(&msg), Some(&msg.signature), true) } - fn update_channel_internal(&self, msg: &msgs::UnsignedChannelUpdate, - full_msg: Option<&msgs::ChannelUpdate>, sig: Option<&secp256k1::ecdsa::Signature>, - only_verify: bool) -> Result<(), LightningError> - { + fn update_channel_internal( + &self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate>, + sig: Option<&secp256k1::ecdsa::Signature>, only_verify: bool, + ) -> Result<(), LightningError> { let chan_enabled = msg.flags & (1 << 1) != (1 << 1); if msg.chain_hash != self.chain_hash { @@ -1909,35 +2147,56 @@ impl NetworkGraph where L::Target: Logger { { // Note that many tests rely on being able to set arbitrarily old timestamps, thus we // disable this check during tests! - let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); + let time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); if (msg.timestamp as u64) < time - STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS { - return Err(LightningError{err: "channel_update is older than two weeks old".to_owned(), action: ErrorAction::IgnoreAndLog(Level::Gossip)}); + return Err(LightningError { + err: "channel_update is older than two weeks old".to_owned(), + action: ErrorAction::IgnoreAndLog(Level::Gossip), + }); } if msg.timestamp as u64 > time + 60 * 60 * 24 { - return Err(LightningError{err: "channel_update has a timestamp more than a day in the future".to_owned(), action: ErrorAction::IgnoreAndLog(Level::Gossip)}); + return Err(LightningError { + err: "channel_update has a timestamp more than a day in the future".to_owned(), + action: ErrorAction::IgnoreAndLog(Level::Gossip), + }); } } - log_gossip!(self.logger, "Updating channel {} in direction {} with timestamp {}", msg.short_channel_id, msg.flags & 1, msg.timestamp); + log_gossip!( + self.logger, + "Updating channel {} in direction {} with timestamp {}", + msg.short_channel_id, + msg.flags & 1, + msg.timestamp + ); let mut channels = self.channels.write().unwrap(); match channels.get_mut(&msg.short_channel_id) { None => { core::mem::drop(channels); self.pending_checks.check_hold_pending_channel_update(msg, full_msg)?; - return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Couldn't find channel for update".to_owned(), + action: ErrorAction::IgnoreError, + }); }, Some(channel) => { if msg.htlc_maximum_msat > MAX_VALUE_MSAT { - return Err(LightningError{err: - "htlc_maximum_msat is larger than maximum possible msats".to_owned(), - action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "htlc_maximum_msat is larger than maximum possible msats".to_owned(), + action: ErrorAction::IgnoreError, + }); } if let Some(capacity_sats) = channel.capacity_sats { // It's possible channel capacity is available now, although it wasn't available at announcement (so the field is None). // Don't query UTXO set here to reduce DoS risks. - if capacity_sats > MAX_VALUE_MSAT / 1000 || msg.htlc_maximum_msat > capacity_sats * 1000 { + if capacity_sats > MAX_VALUE_MSAT / 1000 + || msg.htlc_maximum_msat > capacity_sats * 1000 + { return Err(LightningError{err: "htlc_maximum_msat is larger than channel capacity or capacity is bogus".to_owned(), action: ErrorAction::IgnoreError}); @@ -1953,18 +2212,29 @@ impl NetworkGraph where L::Target: Logger { // pruning based on the timestamp field being more than two weeks old, // but only in the non-normative section. if existing_chan_info.last_update > msg.timestamp { - return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip}); + return Err(LightningError { + err: "Update older than last processed update".to_owned(), + action: ErrorAction::IgnoreDuplicateGossip, + }); } else if existing_chan_info.last_update == msg.timestamp { - return Err(LightningError{err: "Update had same timestamp as last processed update".to_owned(), action: ErrorAction::IgnoreDuplicateGossip}); + return Err(LightningError { + err: "Update had same timestamp as last processed update" + .to_owned(), + action: ErrorAction::IgnoreDuplicateGossip, + }); } } - } + }; } macro_rules! get_new_channel_info { - () => { { - let last_update_message = if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY - { full_msg.cloned() } else { None }; + () => {{ + let last_update_message = + if msg.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY { + full_msg.cloned() + } else { + None + }; let updated_channel_update_info = ChannelUpdateInfo { enabled: chan_enabled, @@ -1976,20 +2246,28 @@ impl NetworkGraph where L::Target: Logger { base_msat: msg.fee_base_msat, proportional_millionths: msg.fee_proportional_millionths, }, - last_update_message + last_update_message, }; Some(updated_channel_update_info) - } } + }}; } let msg_hash = hash_to_message!(&message_sha256d_hash(&msg)[..]); if msg.flags & 1 == 1 { check_update_latest!(channel.two_to_one); if let Some(sig) = sig { - secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| LightningError{ - err: "Couldn't parse source node pubkey".to_owned(), - action: ErrorAction::IgnoreAndLog(Level::Debug) - })?, "channel_update"); + secp_verify_sig!( + self.secp_ctx, + &msg_hash, + &sig, + &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| { + LightningError { + err: "Couldn't parse source node pubkey".to_owned(), + action: ErrorAction::IgnoreAndLog(Level::Debug), + } + })?, + "channel_update" + ); } if !only_verify { channel.two_to_one = get_new_channel_info!(); @@ -1997,35 +2275,45 @@ impl NetworkGraph where L::Target: Logger { } else { check_update_latest!(channel.one_to_two); if let Some(sig) = sig { - secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| LightningError{ - err: "Couldn't parse destination node pubkey".to_owned(), - action: ErrorAction::IgnoreAndLog(Level::Debug) - })?, "channel_update"); + secp_verify_sig!( + self.secp_ctx, + &msg_hash, + &sig, + &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| { + LightningError { + err: "Couldn't parse destination node pubkey".to_owned(), + action: ErrorAction::IgnoreAndLog(Level::Debug), + } + })?, + "channel_update" + ); } if !only_verify { channel.one_to_two = get_new_channel_info!(); } } - } + }, } Ok(()) } - fn remove_channel_in_nodes(nodes: &mut IndexedMap, chan: &ChannelInfo, short_channel_id: u64) { + fn remove_channel_in_nodes( + nodes: &mut IndexedMap, chan: &ChannelInfo, short_channel_id: u64, + ) { macro_rules! remove_from_node { ($node_id: expr) => { if let IndexedMapEntry::Occupied(mut entry) = nodes.entry($node_id) { - entry.get_mut().channels.retain(|chan_id| { - short_channel_id != *chan_id - }); + entry.get_mut().channels.retain(|chan_id| short_channel_id != *chan_id); if entry.get().channels.is_empty() { entry.remove_entry(); } } else { - panic!("Had channel that pointed to unknown node (ie inconsistent network map)!"); + panic!( + "Had channel that pointed to unknown node (ie inconsistent network map)!" + ); } - } + }; } remove_from_node!(chan.node_one); @@ -2074,7 +2362,8 @@ impl ReadOnlyNetworkGraph<'_> { /// Returns None if the requested node is completely unknown, /// or if node announcement for the node was never received. pub fn get_addresses(&self, pubkey: &PublicKey) -> Option> { - self.nodes.get(&NodeId::from_pubkey(&pubkey)) + self.nodes + .get(&NodeId::from_pubkey(&pubkey)) .and_then(|node| node.announcement_info.as_ref().map(|ann| ann.addresses().to_vec())) } } @@ -2082,46 +2371,59 @@ impl ReadOnlyNetworkGraph<'_> { #[cfg(test)] pub(crate) mod tests { use crate::events::{MessageSendEvent, MessageSendEventsProvider}; - use crate::ln::channelmanager; use crate::ln::chan_utils::make_funding_redeemscript; + use crate::ln::channelmanager; #[cfg(feature = "std")] use crate::ln::features::InitFeatures; - use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, NodeAlias, MAX_EXCESS_BYTES_FOR_RELAY, NodeId, RoutingFees, ChannelUpdateInfo, ChannelInfo, NodeAnnouncementInfo, NodeInfo}; + use crate::ln::msgs::{ + ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, QueryChannelRange, + QueryShortChannelIds, ReplyChannelRange, RoutingMessageHandler, + UnsignedChannelAnnouncement, UnsignedChannelUpdate, UnsignedNodeAnnouncement, + MAX_VALUE_MSAT, + }; + use crate::routing::gossip::{ + ChannelInfo, ChannelUpdateInfo, NetworkGraph, NetworkUpdate, NodeAlias, + NodeAnnouncementInfo, NodeId, NodeInfo, P2PGossipSync, RoutingFees, + MAX_EXCESS_BYTES_FOR_RELAY, + }; use crate::routing::utxo::{UtxoLookupError, UtxoResult}; - use crate::ln::msgs::{RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement, - UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate, - ReplyChannelRange, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT}; use crate::util::config::UserConfig; - use crate::util::test_utils; - use crate::util::ser::{ReadableArgs, Readable, Writeable}; use crate::util::scid_utils::scid_from_parts; + use crate::util::ser::{Readable, ReadableArgs, Writeable}; + use crate::util::test_utils; - use crate::routing::gossip::REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS; use super::STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS; + use crate::routing::gossip::REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS; - use bitcoin::hashes::sha256d::Hash as Sha256dHash; - use bitcoin::hashes::Hash; - use bitcoin::hashes::hex::FromHex; - use bitcoin::network::constants::Network; use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::script::ScriptBuf; use bitcoin::blockdata::transaction::TxOut; - use bitcoin::secp256k1::{PublicKey, SecretKey}; + use bitcoin::hashes::hex::FromHex; + use bitcoin::hashes::sha256d::Hash as Sha256dHash; + use bitcoin::hashes::Hash; + use bitcoin::network::constants::Network; use bitcoin::secp256k1::{All, Secp256k1}; + use bitcoin::secp256k1::{PublicKey, SecretKey}; use crate::io; - use bitcoin::secp256k1; use crate::prelude::*; use crate::sync::Arc; + use bitcoin::secp256k1; fn create_network_graph() -> NetworkGraph> { let logger = Arc::new(test_utils::TestLogger::new()); NetworkGraph::new(Network::Testnet, logger) } - fn create_gossip_sync(network_graph: &NetworkGraph>) -> ( - Secp256k1, P2PGossipSync<&NetworkGraph>, - Arc, Arc> + fn create_gossip_sync( + network_graph: &NetworkGraph>, + ) -> ( + Secp256k1, + P2PGossipSync< + &NetworkGraph>, + Arc, + Arc, + >, ) { let secp_ctx = Secp256k1::new(); let logger = Arc::new(test_utils::TestLogger::new()); @@ -2134,7 +2436,16 @@ pub(crate) mod tests { fn request_full_sync_finite_times() { let network_graph = create_network_graph(); let (secp_ctx, gossip_sync) = create_gossip_sync(&network_graph); - let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&>::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap()[..]).unwrap()); + let node_id = PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice( + &>::from_hex( + "0202020202020202020202020202020202020202020202020202020202020202", + ) + .unwrap()[..], + ) + .unwrap(), + ); assert!(gossip_sync.should_request_full_sync(&node_id)); assert!(gossip_sync.should_request_full_sync(&node_id)); @@ -2144,7 +2455,9 @@ pub(crate) mod tests { assert!(!gossip_sync.should_request_full_sync(&node_id)); } - pub(crate) fn get_signed_node_announcement(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1) -> NodeAnnouncement { + pub(crate) fn get_signed_node_announcement( + f: F, node_key: &SecretKey, secp_ctx: &Secp256k1, + ) -> NodeAnnouncement { let node_id = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_key)); let mut unsigned_announcement = UnsignedNodeAnnouncement { features: channelmanager::provided_node_features(&UserConfig::default()), @@ -2160,11 +2473,13 @@ pub(crate) mod tests { let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); NodeAnnouncement { signature: secp_ctx.sign_ecdsa(&msghash, node_key), - contents: unsigned_announcement + contents: unsigned_announcement, } } - pub(crate) fn get_signed_channel_announcement(f: F, node_1_key: &SecretKey, node_2_key: &SecretKey, secp_ctx: &Secp256k1) -> ChannelAnnouncement { + pub(crate) fn get_signed_channel_announcement( + f: F, node_1_key: &SecretKey, node_2_key: &SecretKey, secp_ctx: &Secp256k1, + ) -> ChannelAnnouncement { let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_key); let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_key); let node_1_btckey = &SecretKey::from_slice(&[40; 32]).unwrap(); @@ -2176,8 +2491,14 @@ pub(crate) mod tests { short_channel_id: 0, node_id_1: NodeId::from_pubkey(&node_id_1), node_id_2: NodeId::from_pubkey(&node_id_2), - bitcoin_key_1: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_1_btckey)), - bitcoin_key_2: NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_2_btckey)), + bitcoin_key_1: NodeId::from_pubkey(&PublicKey::from_secret_key( + &secp_ctx, + node_1_btckey, + )), + bitcoin_key_2: NodeId::from_pubkey(&PublicKey::from_secret_key( + &secp_ctx, + node_2_btckey, + )), excess_data: Vec::new(), }; f(&mut unsigned_announcement); @@ -2194,11 +2515,16 @@ pub(crate) mod tests { pub(crate) fn get_channel_script(secp_ctx: &Secp256k1) -> ScriptBuf { let node_1_btckey = SecretKey::from_slice(&[40; 32]).unwrap(); let node_2_btckey = SecretKey::from_slice(&[39; 32]).unwrap(); - make_funding_redeemscript(&PublicKey::from_secret_key(secp_ctx, &node_1_btckey), - &PublicKey::from_secret_key(secp_ctx, &node_2_btckey)).to_v0_p2wsh() + make_funding_redeemscript( + &PublicKey::from_secret_key(secp_ctx, &node_1_btckey), + &PublicKey::from_secret_key(secp_ctx, &node_2_btckey), + ) + .to_v0_p2wsh() } - pub(crate) fn get_signed_channel_update(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1) -> ChannelUpdate { + pub(crate) fn get_signed_channel_update( + f: F, node_key: &SecretKey, secp_ctx: &Secp256k1, + ) -> ChannelUpdate { let mut unsigned_channel_update = UnsignedChannelUpdate { chain_hash: ChainHash::using_genesis_block(Network::Testnet), short_channel_id: 0, @@ -2209,13 +2535,14 @@ pub(crate) mod tests { htlc_maximum_msat: 1_000_000, fee_base_msat: 10_000, fee_proportional_millionths: 20, - excess_data: Vec::new() + excess_data: Vec::new(), }; f(&mut unsigned_channel_update); - let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_channel_update.encode()[..])[..]); + let msghash = + hash_to_message!(&Sha256dHash::hash(&unsigned_channel_update.encode()[..])[..]); ChannelUpdate { signature: secp_ctx.sign_ecdsa(&msghash, node_key), - contents: unsigned_channel_update + contents: unsigned_channel_update, } } @@ -2231,51 +2558,59 @@ pub(crate) mod tests { let valid_announcement = get_signed_node_announcement(|_| {}, node_1_privkey, &secp_ctx); match gossip_sync.handle_node_announcement(&valid_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!("No existing channels for node_announcement", e.err) + Err(e) => assert_eq!("No existing channels for node_announcement", e.err), }; { // Announce a channel to add a corresponding node. - 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); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(res), - _ => panic!() + _ => panic!(), }; } match gossip_sync.handle_node_announcement(&valid_announcement) { Ok(res) => assert!(res), - Err(_) => panic!() + Err(_) => panic!(), }; let fake_msghash = hash_to_message!(zero_hash.as_byte_array()); - match gossip_sync.handle_node_announcement( - &NodeAnnouncement { - signature: secp_ctx.sign_ecdsa(&fake_msghash, node_1_privkey), - contents: valid_announcement.contents.clone() + match gossip_sync.handle_node_announcement(&NodeAnnouncement { + signature: secp_ctx.sign_ecdsa(&fake_msghash, node_1_privkey), + contents: valid_announcement.contents.clone(), }) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Invalid signature on node_announcement message") + Err(e) => assert_eq!(e.err, "Invalid signature on node_announcement message"), }; - let announcement_with_data = get_signed_node_announcement(|unsigned_announcement| { - unsigned_announcement.timestamp += 1000; - unsigned_announcement.excess_data.resize(MAX_EXCESS_BYTES_FOR_RELAY + 1, 0); - }, node_1_privkey, &secp_ctx); + let announcement_with_data = get_signed_node_announcement( + |unsigned_announcement| { + unsigned_announcement.timestamp += 1000; + unsigned_announcement.excess_data.resize(MAX_EXCESS_BYTES_FOR_RELAY + 1, 0); + }, + node_1_privkey, + &secp_ctx, + ); // Return false because contains excess data. match gossip_sync.handle_node_announcement(&announcement_with_data) { Ok(res) => assert!(!res), - Err(_) => panic!() + Err(_) => panic!(), }; // Even though previous announcement was not relayed further, we still accepted it, // so we now won't accept announcements before the previous one. - let outdated_announcement = get_signed_node_announcement(|unsigned_announcement| { - unsigned_announcement.timestamp += 1000 - 10; - }, node_1_privkey, &secp_ctx); + let outdated_announcement = get_signed_node_announcement( + |unsigned_announcement| { + unsigned_announcement.timestamp += 1000 - 10; + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_node_announcement(&outdated_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Update older than last processed update") + Err(e) => assert_eq!(e.err, "Update older than last processed update"), }; } @@ -2288,20 +2623,25 @@ pub(crate) mod tests { let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap(); let good_script = get_channel_script(&secp_ctx); - 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); // Test if the UTXO lookups were not supported let network_graph = NetworkGraph::new(Network::Testnet, &logger); let mut gossip_sync = P2PGossipSync::new(&network_graph, None, &logger); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(res), - _ => panic!() + _ => panic!(), }; { - match network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id) { + match network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + { None => panic!(), - Some(_) => () + Some(_) => (), }; } @@ -2309,7 +2649,7 @@ pub(crate) mod tests { // drop new one on the floor, since we can't see any changes. match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Already have non-chain-validated channel") + Err(e) => assert_eq!(e.err, "Already have non-chain-validated channel"), }; // Test if an associated transaction were not on-chain (or not confirmed). @@ -2318,29 +2658,43 @@ pub(crate) mod tests { let network_graph = NetworkGraph::new(Network::Testnet, &logger); gossip_sync = P2PGossipSync::new(&network_graph, Some(&chain_source), &logger); - let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| { - unsigned_announcement.short_channel_id += 1; - }, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_announcement = get_signed_channel_announcement( + |unsigned_announcement| { + unsigned_announcement.short_channel_id += 1; + }, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry") + Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry"), }; // Now test if the transaction is found in the UTXO set and the script is correct. *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script.clone() })); - let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| { - unsigned_announcement.short_channel_id += 2; - }, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_announcement = get_signed_channel_announcement( + |unsigned_announcement| { + unsigned_announcement.short_channel_id += 2; + }, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(res), - _ => panic!() + _ => panic!(), }; { - match network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id) { + match network_graph + .read_only() + .channels() + .get(&valid_announcement.contents.short_channel_id) + { None => panic!(), - Some(_) => () + Some(_) => (), }; } @@ -2350,66 +2704,91 @@ pub(crate) mod tests { UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script })); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Already have chain-validated channel") + Err(e) => assert_eq!(e.err, "Already have chain-validated channel"), }; #[cfg(feature = "std")] { use std::time::{SystemTime, UNIX_EPOCH}; - let tracking_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); + let tracking_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); // Mark a node as permanently failed so it's tracked as removed. - gossip_sync.network_graph().node_failed_permanent(&PublicKey::from_secret_key(&secp_ctx, node_1_privkey)); + gossip_sync + .network_graph() + .node_failed_permanent(&PublicKey::from_secret_key(&secp_ctx, node_1_privkey)); // Return error and ignore valid channel announcement if one of the nodes has been tracked as removed. - let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| { - unsigned_announcement.short_channel_id += 3; - }, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_announcement = get_signed_channel_announcement( + |unsigned_announcement| { + unsigned_announcement.short_channel_id += 3; + }, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(_) => panic!(), Err(e) => assert_eq!(e.err, "Channel with SCID 3 or one of its nodes was removed from our network graph recently") } - gossip_sync.network_graph().remove_stale_channels_and_tracking_with_time(tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS); + gossip_sync.network_graph().remove_stale_channels_and_tracking_with_time( + tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS, + ); // The above channel announcement should be handled as per normal now. match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(res), - _ => panic!() + _ => panic!(), } } // Don't relay valid channels with excess data - let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| { - unsigned_announcement.short_channel_id += 4; - unsigned_announcement.excess_data.resize(MAX_EXCESS_BYTES_FOR_RELAY + 1, 0); - }, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_announcement = get_signed_channel_announcement( + |unsigned_announcement| { + unsigned_announcement.short_channel_id += 4; + unsigned_announcement.excess_data.resize(MAX_EXCESS_BYTES_FOR_RELAY + 1, 0); + }, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(!res), - _ => panic!() + _ => panic!(), }; let mut invalid_sig_announcement = valid_announcement.clone(); invalid_sig_announcement.contents.excess_data = Vec::new(); match gossip_sync.handle_channel_announcement(&invalid_sig_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Invalid signature on channel_announcement message") + Err(e) => assert_eq!(e.err, "Invalid signature on channel_announcement message"), }; - let channel_to_itself_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_1_privkey, &secp_ctx); + let channel_to_itself_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_1_privkey, &secp_ctx); match gossip_sync.handle_channel_announcement(&channel_to_itself_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Channel announcement node had a channel with itself") + Err(e) => assert_eq!(e.err, "Channel announcement node had a channel with itself"), }; // Test that channel announcements with the wrong chain hash are ignored (network graph is testnet, // announcement is mainnet). - let incorrect_chain_announcement = get_signed_channel_announcement(|unsigned_announcement| { - unsigned_announcement.chain_hash = ChainHash::using_genesis_block(Network::Bitcoin); - }, node_1_privkey, node_2_privkey, &secp_ctx); + let incorrect_chain_announcement = get_signed_channel_announcement( + |unsigned_announcement| { + unsigned_announcement.chain_hash = ChainHash::using_genesis_block(Network::Bitcoin); + }, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_announcement(&incorrect_chain_announcement) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Channel announcement chain hash does not match genesis hash") + Err(e) => { + assert_eq!(e.err, "Channel announcement chain hash does not match genesis hash") + }, }; } @@ -2430,16 +2809,18 @@ pub(crate) mod tests { { // Announce a channel we will update let good_script = get_channel_script(&secp_ctx); - *chain_source.utxo_ret.lock().unwrap() = - UtxoResult::Sync(Ok(TxOut { value: amount_sats, script_pubkey: good_script.clone() })); + *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Sync(Ok(TxOut { + value: amount_sats, + script_pubkey: good_script.clone(), + })); - let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_channel_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); short_channel_id = valid_channel_announcement.contents.short_channel_id; match gossip_sync.handle_channel_announcement(&valid_channel_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; - } let valid_channel_update = get_signed_channel_update(|_| {}, node_1_privkey, &secp_ctx); @@ -2455,77 +2836,109 @@ pub(crate) mod tests { Some(channel_info) => { assert_eq!(channel_info.one_to_two.as_ref().unwrap().cltv_expiry_delta, 144); assert!(channel_info.two_to_one.is_none()); - } + }, }; } - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.timestamp += 100; - unsigned_channel_update.excess_data.resize(MAX_EXCESS_BYTES_FOR_RELAY + 1, 0); - }, node_1_privkey, &secp_ctx); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.timestamp += 100; + unsigned_channel_update.excess_data.resize(MAX_EXCESS_BYTES_FOR_RELAY + 1, 0); + }, + node_1_privkey, + &secp_ctx, + ); // Return false because contains excess data match gossip_sync.handle_channel_update(&valid_channel_update) { Ok(res) => assert!(!res), - _ => panic!() + _ => panic!(), }; - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.timestamp += 110; - unsigned_channel_update.short_channel_id += 1; - }, node_1_privkey, &secp_ctx); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.timestamp += 110; + unsigned_channel_update.short_channel_id += 1; + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_update(&valid_channel_update) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Couldn't find channel for update") + Err(e) => assert_eq!(e.err, "Couldn't find channel for update"), }; - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.htlc_maximum_msat = MAX_VALUE_MSAT + 1; - unsigned_channel_update.timestamp += 110; - }, node_1_privkey, &secp_ctx); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.htlc_maximum_msat = MAX_VALUE_MSAT + 1; + unsigned_channel_update.timestamp += 110; + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_update(&valid_channel_update) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "htlc_maximum_msat is larger than maximum possible msats") + Err(e) => assert_eq!(e.err, "htlc_maximum_msat is larger than maximum possible msats"), }; - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.htlc_maximum_msat = amount_sats * 1000 + 1; - unsigned_channel_update.timestamp += 110; - }, node_1_privkey, &secp_ctx); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.htlc_maximum_msat = amount_sats * 1000 + 1; + unsigned_channel_update.timestamp += 110; + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_update(&valid_channel_update) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "htlc_maximum_msat is larger than channel capacity or capacity is bogus") + Err(e) => assert_eq!( + e.err, + "htlc_maximum_msat is larger than channel capacity or capacity is bogus" + ), }; // Even though previous update was not relayed further, we still accepted it, // so we now won't accept update before the previous one. - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.timestamp += 100; - }, node_1_privkey, &secp_ctx); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.timestamp += 100; + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_update(&valid_channel_update) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Update had same timestamp as last processed update") + Err(e) => assert_eq!(e.err, "Update had same timestamp as last processed update"), }; - let mut invalid_sig_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.timestamp += 500; - }, node_1_privkey, &secp_ctx); + let mut invalid_sig_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.timestamp += 500; + }, + node_1_privkey, + &secp_ctx, + ); let zero_hash = Sha256dHash::hash(&[0; 32]); let fake_msghash = hash_to_message!(zero_hash.as_byte_array()); invalid_sig_channel_update.signature = secp_ctx.sign_ecdsa(&fake_msghash, node_1_privkey); match gossip_sync.handle_channel_update(&invalid_sig_channel_update) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Invalid signature on channel_update message") + Err(e) => assert_eq!(e.err, "Invalid signature on channel_update message"), }; // Test that channel updates with the wrong chain hash are ignored (network graph is testnet, channel // update is mainet). - let incorrect_chain_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.chain_hash = ChainHash::using_genesis_block(Network::Bitcoin); - }, node_1_privkey, &secp_ctx); + let incorrect_chain_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.chain_hash = + ChainHash::using_genesis_block(Network::Bitcoin); + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_update(&incorrect_chain_update) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "Channel update chain hash does not match genesis hash") + Err(e) => assert_eq!(e.err, "Channel update chain hash does not match genesis hash"), }; } @@ -2548,20 +2961,35 @@ pub(crate) mod tests { { // Check we won't apply an update via `handle_network_update` for privacy reasons, but // can continue fine if we manually apply it. - let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_channel_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); short_channel_id = valid_channel_announcement.contents.short_channel_id; let chain_source: Option<&test_utils::TestChainSource> = None; - assert!(network_graph.update_channel_from_announcement(&valid_channel_announcement, &chain_source).is_ok()); + assert!(network_graph + .update_channel_from_announcement(&valid_channel_announcement, &chain_source) + .is_ok()); assert!(network_graph.read_only().channels().get(&short_channel_id).is_some()); let valid_channel_update = get_signed_channel_update(|_| {}, node_1_privkey, &secp_ctx); - assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none()); + assert!(network_graph + .read_only() + .channels() + .get(&short_channel_id) + .unwrap() + .one_to_two + .is_none()); network_graph.handle_network_update(&NetworkUpdate::ChannelUpdateMessage { msg: valid_channel_update.clone(), }); - assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none()); + assert!(network_graph + .read_only() + .channels() + .get(&short_channel_id) + .unwrap() + .one_to_two + .is_none()); network_graph.update_channel(&valid_channel_update).unwrap(); } @@ -2571,7 +2999,7 @@ pub(crate) mod tests { None => panic!(), Some(channel_info) => { assert!(channel_info.one_to_two.as_ref().unwrap().enabled); - } + }, }; network_graph.handle_network_update(&NetworkUpdate::ChannelFailure { @@ -2583,7 +3011,7 @@ pub(crate) mod tests { None => panic!(), Some(channel_info) => { assert!(channel_info.one_to_two.as_ref().unwrap().enabled); - } + }, }; } @@ -2602,10 +3030,13 @@ pub(crate) mod tests { let network_graph = NetworkGraph::new(Network::Testnet, &logger); // Announce a channel to test permanent node failure - let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_channel_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); let short_channel_id = valid_channel_announcement.contents.short_channel_id; let chain_source: Option<&test_utils::TestChainSource> = None; - assert!(network_graph.update_channel_from_announcement(&valid_channel_announcement, &chain_source).is_ok()); + assert!(network_graph + .update_channel_from_announcement(&valid_channel_announcement, &chain_source) + .is_ok()); assert!(network_graph.read_only().channels().get(&short_channel_id).is_some()); // Non-permanent node failure does not delete any nodes or channels @@ -2615,7 +3046,11 @@ pub(crate) mod tests { }); assert!(network_graph.read_only().channels().get(&short_channel_id).is_some()); - assert!(network_graph.read_only().nodes().get(&NodeId::from_pubkey(&node_2_id)).is_some()); + assert!(network_graph + .read_only() + .nodes() + .get(&NodeId::from_pubkey(&node_2_id)) + .is_some()); // Permanent node failure deletes node and its channels network_graph.handle_network_update(&NetworkUpdate::NodeFailure { @@ -2641,32 +3076,59 @@ pub(crate) mod tests { let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap(); let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap(); - let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_channel_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); let short_channel_id = valid_channel_announcement.contents.short_channel_id; let chain_source: Option<&test_utils::TestChainSource> = None; - assert!(network_graph.update_channel_from_announcement(&valid_channel_announcement, &chain_source).is_ok()); + assert!(network_graph + .update_channel_from_announcement(&valid_channel_announcement, &chain_source) + .is_ok()); assert!(network_graph.read_only().channels().get(&short_channel_id).is_some()); // Submit two channel updates for each channel direction (update.flags bit). let valid_channel_update = get_signed_channel_update(|_| {}, node_1_privkey, &secp_ctx); assert!(gossip_sync.handle_channel_update(&valid_channel_update).is_ok()); - assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_some()); - - let valid_channel_update_2 = get_signed_channel_update(|update| {update.flags |=1;}, node_2_privkey, &secp_ctx); + assert!(network_graph + .read_only() + .channels() + .get(&short_channel_id) + .unwrap() + .one_to_two + .is_some()); + + let valid_channel_update_2 = get_signed_channel_update( + |update| { + update.flags |= 1; + }, + node_2_privkey, + &secp_ctx, + ); gossip_sync.handle_channel_update(&valid_channel_update_2).unwrap(); - assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().two_to_one.is_some()); - - network_graph.remove_stale_channels_and_tracking_with_time(100 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS); + assert!(network_graph + .read_only() + .channels() + .get(&short_channel_id) + .unwrap() + .two_to_one + .is_some()); + + network_graph.remove_stale_channels_and_tracking_with_time( + 100 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS, + ); assert_eq!(network_graph.read_only().channels().len(), 1); assert_eq!(network_graph.read_only().nodes().len(), 2); - network_graph.remove_stale_channels_and_tracking_with_time(101 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS); - #[cfg(not(feature = "std"))] { + network_graph.remove_stale_channels_and_tracking_with_time( + 101 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS, + ); + #[cfg(not(feature = "std"))] + { // Make sure removed channels are tracked. assert_eq!(network_graph.removed_channels.lock().unwrap().len(), 1); } - network_graph.remove_stale_channels_and_tracking_with_time(101 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS + - REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS); + network_graph.remove_stale_channels_and_tracking_with_time( + 101 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS, + ); #[cfg(feature = "std")] { @@ -2679,20 +3141,45 @@ pub(crate) mod tests { // Note that the directional channel information will have been removed already.. // We want to check that this will work even if *one* of the channel updates is recent, // so we should add it with a recent timestamp. - assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none()); + assert!(network_graph + .read_only() + .channels() + .get(&short_channel_id) + .unwrap() + .one_to_two + .is_none()); use std::time::{SystemTime, UNIX_EPOCH}; - let announcement_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.timestamp = (announcement_time + 1 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS) as u32; - }, node_1_privkey, &secp_ctx); + let announcement_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.timestamp = + (announcement_time + 1 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS) as u32; + }, + node_1_privkey, + &secp_ctx, + ); assert!(gossip_sync.handle_channel_update(&valid_channel_update).is_ok()); - assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_some()); - network_graph.remove_stale_channels_and_tracking_with_time(announcement_time + 1 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS); + assert!(network_graph + .read_only() + .channels() + .get(&short_channel_id) + .unwrap() + .one_to_two + .is_some()); + network_graph.remove_stale_channels_and_tracking_with_time( + announcement_time + 1 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS, + ); // Make sure removed channels are tracked. assert_eq!(network_graph.removed_channels.lock().unwrap().len(), 1); // Provide a later time so that sufficient time has passed - network_graph.remove_stale_channels_and_tracking_with_time(announcement_time + 1 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS + - REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS); + network_graph.remove_stale_channels_and_tracking_with_time( + announcement_time + + 1 + STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS + + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS, + ); } assert_eq!(network_graph.read_only().channels().len(), 0); @@ -2703,7 +3190,10 @@ pub(crate) mod tests { { use std::time::{SystemTime, UNIX_EPOCH}; - let tracking_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); + let tracking_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); // Clear tracked nodes and channels for clean slate network_graph.removed_channels.lock().unwrap().clear(); @@ -2711,8 +3201,9 @@ pub(crate) mod tests { // Add a channel and nodes from channel announcement. So our network graph will // now only consist of two nodes and one channel between them. - assert!(network_graph.update_channel_from_announcement( - &valid_channel_announcement, &chain_source).is_ok()); + assert!(network_graph + .update_channel_from_announcement(&valid_channel_announcement, &chain_source) + .is_ok()); // Mark the channel as permanently failed. This will also remove the two nodes // and all of the entries will be tracked as removed. @@ -2720,14 +3211,29 @@ pub(crate) mod tests { // Should not remove from tracking if insufficient time has passed network_graph.remove_stale_channels_and_tracking_with_time( - tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS - 1); - assert_eq!(network_graph.removed_channels.lock().unwrap().len(), 1, "Removed channel count ≠ 1 with tracking_time {}", tracking_time); + tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS - 1, + ); + assert_eq!( + network_graph.removed_channels.lock().unwrap().len(), + 1, + "Removed channel count ≠ 1 with tracking_time {}", + tracking_time + ); // Provide a later time so that sufficient time has passed network_graph.remove_stale_channels_and_tracking_with_time( - tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS); - assert!(network_graph.removed_channels.lock().unwrap().is_empty(), "Unexpectedly removed channels with tracking_time {}", tracking_time); - assert!(network_graph.removed_nodes.lock().unwrap().is_empty(), "Unexpectedly removed nodes with tracking_time {}", tracking_time); + tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS, + ); + assert!( + network_graph.removed_channels.lock().unwrap().is_empty(), + "Unexpectedly removed channels with tracking_time {}", + tracking_time + ); + assert!( + network_graph.removed_nodes.lock().unwrap().is_empty(), + "Unexpectedly removed nodes with tracking_time {}", + tracking_time + ); } #[cfg(not(feature = "std"))] @@ -2744,8 +3250,9 @@ pub(crate) mod tests { // Add a channel and nodes from channel announcement. So our network graph will // now only consist of two nodes and one channel between them. - assert!(network_graph.update_channel_from_announcement( - &valid_channel_announcement, &chain_source).is_ok()); + assert!(network_graph + .update_channel_from_announcement(&valid_channel_announcement, &chain_source) + .is_ok()); // Mark the channel as permanently failed. This will also remove the two nodes // and all of the entries will be tracked as removed. @@ -2757,7 +3264,8 @@ pub(crate) mod tests { // Provide a later time so that sufficient time has passed network_graph.remove_stale_channels_and_tracking_with_time( - removal_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS); + removal_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS, + ); assert!(network_graph.removed_channels.lock().unwrap().is_empty()); assert!(network_graph.removed_nodes.lock().unwrap().is_empty()); } @@ -2777,16 +3285,18 @@ pub(crate) mod tests { let short_channel_id; { // Announce a channel we will update - let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_channel_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); short_channel_id = valid_channel_announcement.contents.short_channel_id; match gossip_sync.handle_channel_announcement(&valid_channel_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; } // Contains initial channel announcement now. - let channels_with_announcements = gossip_sync.get_next_channel_announcement(short_channel_id); + let channels_with_announcements = + gossip_sync.get_next_channel_announcement(short_channel_id); if let Some(channel_announcements) = channels_with_announcements { let (_, ref update_1, ref update_2) = channel_announcements; assert_eq!(update_1, &None); @@ -2797,17 +3307,22 @@ pub(crate) mod tests { { // Valid channel update - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.timestamp = 101; - }, node_1_privkey, &secp_ctx); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.timestamp = 101; + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_update(&valid_channel_update) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; } // Now contains an initial announcement and an update. - let channels_with_announcements = gossip_sync.get_next_channel_announcement(short_channel_id); + let channels_with_announcements = + gossip_sync.get_next_channel_announcement(short_channel_id); if let Some(channel_announcements) = channels_with_announcements { let (_, ref update_1, ref update_2) = channel_announcements; assert_ne!(update_1, &None); @@ -2818,18 +3333,24 @@ pub(crate) mod tests { { // Channel update with excess data. - let valid_channel_update = get_signed_channel_update(|unsigned_channel_update| { - unsigned_channel_update.timestamp = 102; - unsigned_channel_update.excess_data = [1; MAX_EXCESS_BYTES_FOR_RELAY + 1].to_vec(); - }, node_1_privkey, &secp_ctx); + let valid_channel_update = get_signed_channel_update( + |unsigned_channel_update| { + unsigned_channel_update.timestamp = 102; + unsigned_channel_update.excess_data = + [1; MAX_EXCESS_BYTES_FOR_RELAY + 1].to_vec(); + }, + node_1_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_update(&valid_channel_update) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; } // Test that announcements with excess data won't be returned - let channels_with_announcements = gossip_sync.get_next_channel_announcement(short_channel_id); + let channels_with_announcements = + gossip_sync.get_next_channel_announcement(short_channel_id); if let Some(channel_announcements) = channels_with_announcements { let (_, ref update_1, ref update_2) = channel_announcements; assert_eq!(update_1, &None); @@ -2839,7 +3360,8 @@ pub(crate) mod tests { } // Further starting point have no channels after it - let channels_with_announcements = gossip_sync.get_next_channel_announcement(short_channel_id + 1000); + let channels_with_announcements = + gossip_sync.get_next_channel_announcement(short_channel_id + 1000); assert!(channels_with_announcements.is_none()); } @@ -2857,10 +3379,11 @@ pub(crate) mod tests { { // Announce a channel to add 2 nodes - let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_channel_announcement = + get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx); match gossip_sync.handle_channel_announcement(&valid_channel_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; } @@ -2869,16 +3392,18 @@ pub(crate) mod tests { assert!(next_announcements.is_none()); { - let valid_announcement = get_signed_node_announcement(|_| {}, node_1_privkey, &secp_ctx); + let valid_announcement = + get_signed_node_announcement(|_| {}, node_1_privkey, &secp_ctx); match gossip_sync.handle_node_announcement(&valid_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; - let valid_announcement = get_signed_node_announcement(|_| {}, node_2_privkey, &secp_ctx); + let valid_announcement = + get_signed_node_announcement(|_| {}, node_2_privkey, &secp_ctx); match gossip_sync.handle_node_announcement(&valid_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; } @@ -2891,13 +3416,18 @@ pub(crate) mod tests { { // Later announcement which should not be relayed (excess data) prevent us from sharing a node - let valid_announcement = get_signed_node_announcement(|unsigned_announcement| { - unsigned_announcement.timestamp += 10; - unsigned_announcement.excess_data = [1; MAX_EXCESS_BYTES_FOR_RELAY + 1].to_vec(); - }, node_2_privkey, &secp_ctx); + let valid_announcement = get_signed_node_announcement( + |unsigned_announcement| { + unsigned_announcement.timestamp += 10; + unsigned_announcement.excess_data = + [1; MAX_EXCESS_BYTES_FOR_RELAY + 1].to_vec(); + }, + node_2_privkey, + &secp_ctx, + ); match gossip_sync.handle_node_announcement(&valid_announcement) { Ok(res) => assert!(!res), - Err(_) => panic!() + Err(_) => panic!(), }; } @@ -2914,16 +3444,17 @@ pub(crate) mod tests { let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap(); // Announce a channel to add a corresponding node. - 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); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(res), - _ => panic!() + _ => panic!(), }; let valid_announcement = get_signed_node_announcement(|_| {}, node_1_privkey, &secp_ctx); match gossip_sync.handle_node_announcement(&valid_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; let mut w = test_utils::TestVecWriter(Vec::new()); @@ -2932,7 +3463,9 @@ pub(crate) mod tests { network_graph.write(&mut w).unwrap(); let logger = Arc::new(test_utils::TestLogger::new()); - assert!(>::read(&mut io::Cursor::new(&w.0), logger).unwrap() == network_graph); + assert!( + >::read(&mut io::Cursor::new(&w.0), logger).unwrap() == network_graph + ); } #[test] @@ -2944,7 +3477,8 @@ pub(crate) mod tests { network_graph.write(&mut w).unwrap(); let logger = Arc::new(test_utils::TestLogger::new()); - let reassembled_network_graph: NetworkGraph<_> = ReadableArgs::read(&mut io::Cursor::new(&w.0), logger).unwrap(); + let reassembled_network_graph: NetworkGraph<_> = + ReadableArgs::read(&mut io::Cursor::new(&w.0), logger).unwrap(); assert!(reassembled_network_graph == network_graph); assert_eq!(reassembled_network_graph.get_last_rapid_gossip_sync_timestamp().unwrap(), 42); } @@ -2952,8 +3486,8 @@ pub(crate) mod tests { #[test] #[cfg(feature = "std")] fn calling_sync_routing_table() { - use std::time::{SystemTime, UNIX_EPOCH}; use crate::ln::msgs::Init; + use std::time::{SystemTime, UNIX_EPOCH}; let network_graph = create_network_graph(); let (secp_ctx, gossip_sync) = create_gossip_sync(&network_graph); @@ -2964,7 +3498,11 @@ pub(crate) mod tests { // It should ignore if gossip_queries feature is not enabled { - let init_msg = Init { features: InitFeatures::empty(), networks: None, remote_network_address: None }; + let init_msg = Init { + features: InitFeatures::empty(), + networks: None, + remote_network_address: None, + }; gossip_sync.peer_connected(&node_id_1, &init_msg, true).unwrap(); let events = gossip_sync.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 0); @@ -2979,15 +3517,23 @@ pub(crate) mod tests { let events = gossip_sync.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); match &events[0] { - MessageSendEvent::SendGossipTimestampFilter{ node_id, msg } => { + MessageSendEvent::SendGossipTimestampFilter { node_id, msg } => { assert_eq!(node_id, &node_id_1); assert_eq!(msg.chain_hash, chain_hash); - let expected_timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); - assert!((msg.first_timestamp as u64) >= expected_timestamp - 60*60*24*7*2); - assert!((msg.first_timestamp as u64) < expected_timestamp - 60*60*24*7*2 + 10); + let expected_timestamp = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); + assert!( + (msg.first_timestamp as u64) >= expected_timestamp - 60 * 60 * 24 * 7 * 2 + ); + assert!( + (msg.first_timestamp as u64) + < expected_timestamp - 60 * 60 * 24 * 7 * 2 + 10 + ); assert_eq!(msg.timestamp_range, u32::max_value()); }, - _ => panic!("Expected MessageSendEvent::SendChannelRangeQuery") + _ => panic!("Expected MessageSendEvent::SendChannelRangeQuery"), }; } } @@ -3016,12 +3562,17 @@ pub(crate) mod tests { scids.push(scid_from_parts(108001, 1, 0).unwrap()); for scid in scids { - let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| { - unsigned_announcement.short_channel_id = scid; - }, node_1_privkey, node_2_privkey, &secp_ctx); + let valid_announcement = get_signed_channel_announcement( + |unsigned_announcement| { + unsigned_announcement.short_channel_id = scid; + }, + node_1_privkey, + node_2_privkey, + &secp_ctx, + ); match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(_) => (), - _ => panic!() + _ => panic!(), }; } @@ -3040,8 +3591,8 @@ pub(crate) mod tests { first_blocknum: 0, number_of_blocks: 0, sync_complete: true, - short_channel_ids: vec![] - }] + short_channel_ids: vec![], + }], ); // Error when wrong chain @@ -3060,7 +3611,7 @@ pub(crate) mod tests { number_of_blocks: 0xffff_ffff, sync_complete: true, short_channel_ids: vec![], - }] + }], ); // Error when first_blocknum > 0xffffff @@ -3078,8 +3629,8 @@ pub(crate) mod tests { first_blocknum: 0x01000000, number_of_blocks: 0xffff_ffff, sync_complete: true, - short_channel_ids: vec![] - }] + short_channel_ids: vec![], + }], ); // Empty reply when max valid SCID block num @@ -3092,15 +3643,13 @@ pub(crate) mod tests { number_of_blocks: 1, }, true, - vec![ - ReplyChannelRange { - chain_hash: chain_hash.clone(), - first_blocknum: 0xffffff, - number_of_blocks: 1, - sync_complete: true, - short_channel_ids: vec![] - }, - ] + vec![ReplyChannelRange { + chain_hash: chain_hash.clone(), + first_blocknum: 0xffffff, + number_of_blocks: 1, + sync_complete: true, + short_channel_ids: vec![], + }], ); // No results in valid query range @@ -3113,15 +3662,13 @@ pub(crate) mod tests { number_of_blocks: 1000, }, true, - vec![ - ReplyChannelRange { - chain_hash: chain_hash.clone(), - first_blocknum: 1000, - number_of_blocks: 1000, - sync_complete: true, - short_channel_ids: vec![], - } - ] + vec![ReplyChannelRange { + chain_hash: chain_hash.clone(), + first_blocknum: 1000, + number_of_blocks: 1000, + sync_complete: true, + short_channel_ids: vec![], + }], ); // Overflow first_blocknum + number_of_blocks @@ -3134,17 +3681,15 @@ pub(crate) mod tests { number_of_blocks: 0xffffffff, }, true, - vec![ - ReplyChannelRange { - chain_hash: chain_hash.clone(), - first_blocknum: 0xfe0000, - number_of_blocks: 0xffffffff - 0xfe0000, - sync_complete: true, - short_channel_ids: vec![ - 0xfffffe_ffffff_ffff, // max - ] - } - ] + vec![ReplyChannelRange { + chain_hash: chain_hash.clone(), + first_blocknum: 0xfe0000, + number_of_blocks: 0xffffffff - 0xfe0000, + sync_complete: true, + short_channel_ids: vec![ + 0xfffffe_ffffff_ffff, // max + ], + }], ); // Single block exactly full @@ -3157,17 +3702,15 @@ pub(crate) mod tests { number_of_blocks: 8000, }, true, - vec![ - ReplyChannelRange { - chain_hash: chain_hash.clone(), - first_blocknum: 100000, - number_of_blocks: 8000, - sync_complete: true, - short_channel_ids: (100000..=107999) - .map(|block| scid_from_parts(block, 0, 0).unwrap()) - .collect(), - }, - ] + vec![ReplyChannelRange { + chain_hash: chain_hash.clone(), + first_blocknum: 100000, + number_of_blocks: 8000, + sync_complete: true, + short_channel_ids: (100000..=107999) + .map(|block| scid_from_parts(block, 0, 0).unwrap()) + .collect(), + }], ); // Multiple split on new block @@ -3195,11 +3738,9 @@ pub(crate) mod tests { first_blocknum: 107999, number_of_blocks: 2, sync_complete: true, - short_channel_ids: vec![ - scid_from_parts(108000, 0, 0).unwrap(), - ], - } - ] + short_channel_ids: vec![scid_from_parts(108000, 0, 0).unwrap()], + }, + ], ); // Multiple split on same block @@ -3227,20 +3768,20 @@ pub(crate) mod tests { first_blocknum: 108001, number_of_blocks: 1, sync_complete: true, - short_channel_ids: vec![ - scid_from_parts(108001, 1, 0).unwrap(), - ], - } - ] + short_channel_ids: vec![scid_from_parts(108001, 1, 0).unwrap()], + }, + ], ); } fn do_handling_query_channel_range( - gossip_sync: &P2PGossipSync<&NetworkGraph>, Arc, Arc>, - test_node_id: &PublicKey, - msg: QueryChannelRange, - expected_ok: bool, - expected_replies: Vec + gossip_sync: &P2PGossipSync< + &NetworkGraph>, + Arc, + Arc, + >, + test_node_id: &PublicKey, msg: QueryChannelRange, expected_ok: bool, + expected_replies: Vec, ) { let mut max_firstblocknum = msg.first_blocknum.saturating_sub(1); let mut c_lightning_0_9_prev_end_blocknum = max_firstblocknum; @@ -3268,14 +3809,22 @@ pub(crate) mod tests { assert_eq!(msg.short_channel_ids, expected_reply.short_channel_ids); // Enforce exactly the sequencing requirements present on c-lightning v0.9.3 - assert!(msg.first_blocknum == c_lightning_0_9_prev_end_blocknum || msg.first_blocknum == c_lightning_0_9_prev_end_blocknum.saturating_add(1)); + assert!( + msg.first_blocknum == c_lightning_0_9_prev_end_blocknum + || msg.first_blocknum + == c_lightning_0_9_prev_end_blocknum.saturating_add(1) + ); assert!(msg.first_blocknum >= max_firstblocknum); max_firstblocknum = msg.first_blocknum; - c_lightning_0_9_prev_end_blocknum = msg.first_blocknum.saturating_add(msg.number_of_blocks); + c_lightning_0_9_prev_end_blocknum = + msg.first_blocknum.saturating_add(msg.number_of_blocks); // Check that the last block count is >= the query's end_blocknum if i == events.len() - 1 { - assert!(msg.first_blocknum.saturating_add(msg.number_of_blocks) >= query_end_blocknum); + assert!( + msg.first_blocknum.saturating_add(msg.number_of_blocks) + >= query_end_blocknum + ); } }, _ => panic!("expected MessageSendEvent::SendReplyChannelRange"), @@ -3292,10 +3841,10 @@ pub(crate) mod tests { let chain_hash = ChainHash::using_genesis_block(Network::Testnet); - let result = gossip_sync.handle_query_short_channel_ids(&node_id, QueryShortChannelIds { - chain_hash, - short_channel_ids: vec![0x0003e8_000000_0000], - }); + let result = gossip_sync.handle_query_short_channel_ids( + &node_id, + QueryShortChannelIds { chain_hash, short_channel_ids: vec![0x0003e8_000000_0000] }, + ); assert!(result.is_err()); } @@ -3326,7 +3875,11 @@ pub(crate) mod tests { fn channel_info_is_readable() { let chanmon_cfgs = crate::ln::functional_test_utils::create_chanmon_cfgs(2); let node_cfgs = crate::ln::functional_test_utils::create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = crate::ln::functional_test_utils::create_node_chanmgrs(2, &node_cfgs, &[None, None, None, None]); + let node_chanmgrs = crate::ln::functional_test_utils::create_node_chanmgrs( + 2, + &node_cfgs, + &[None, None, None, None], + ); let nodes = crate::ln::functional_test_utils::create_network(2, &node_cfgs, &node_chanmgrs); let config = crate::ln::functional_test_utils::test_default_channel_config(); @@ -3345,7 +3898,8 @@ pub(crate) mod tests { assert!(chan_update_info.write(&mut encoded_chan_update_info).is_ok()); // First make sure we can read ChannelUpdateInfos we just wrote - let read_chan_update_info: ChannelUpdateInfo = crate::util::ser::Readable::read(&mut encoded_chan_update_info.as_slice()).unwrap(); + let read_chan_update_info: ChannelUpdateInfo = + crate::util::ser::Readable::read(&mut encoded_chan_update_info.as_slice()).unwrap(); assert_eq!(chan_update_info, read_chan_update_info); // Check the serialization hasn't changed. @@ -3355,11 +3909,15 @@ pub(crate) mod tests { // Check we fail if htlc_maximum_msat is not present in either the ChannelUpdateInfo itself // or the ChannelUpdate enclosed with `last_update_message`. let legacy_chan_update_info_with_some_and_fail_update: Vec = >::from_hex("b40004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c8181d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f00083a840000034d013413a70000009000000000000f42400000271000000014").unwrap(); - let read_chan_update_info_res: Result = crate::util::ser::Readable::read(&mut legacy_chan_update_info_with_some_and_fail_update.as_slice()); + let read_chan_update_info_res: Result = + crate::util::ser::Readable::read( + &mut legacy_chan_update_info_with_some_and_fail_update.as_slice(), + ); assert!(read_chan_update_info_res.is_err()); let legacy_chan_update_info_with_none: Vec = >::from_hex("2c0004000000170201010402002a060800000000000004d20801000a0d0c00040000000902040000000a0c0100").unwrap(); - let read_chan_update_info_res: Result = crate::util::ser::Readable::read(&mut legacy_chan_update_info_with_none.as_slice()); + let read_chan_update_info_res: Result = + crate::util::ser::Readable::read(&mut legacy_chan_update_info_with_none.as_slice()); assert!(read_chan_update_info_res.is_err()); // 2. Test encoding/decoding of ChannelInfo @@ -3378,7 +3936,8 @@ pub(crate) mod tests { let mut encoded_chan_info: Vec = Vec::new(); assert!(chan_info_none_updates.write(&mut encoded_chan_info).is_ok()); - let read_chan_info: ChannelInfo = crate::util::ser::Readable::read(&mut encoded_chan_info.as_slice()).unwrap(); + let read_chan_info: ChannelInfo = + crate::util::ser::Readable::read(&mut encoded_chan_info.as_slice()).unwrap(); assert_eq!(chan_info_none_updates, read_chan_info); // Check we can encode/decode ChannelInfo with ChannelUpdateInfo fields present. @@ -3396,7 +3955,8 @@ pub(crate) mod tests { let mut encoded_chan_info: Vec = Vec::new(); assert!(chan_info_some_updates.write(&mut encoded_chan_info).is_ok()); - let read_chan_info: ChannelInfo = crate::util::ser::Readable::read(&mut encoded_chan_info.as_slice()).unwrap(); + let read_chan_info: ChannelInfo = + crate::util::ser::Readable::read(&mut encoded_chan_info.as_slice()).unwrap(); assert_eq!(chan_info_some_updates, read_chan_info); // Check the serialization hasn't changed. @@ -3406,13 +3966,17 @@ pub(crate) mod tests { // Check we can decode legacy ChannelInfo, even if the `two_to_one` / `one_to_two` / // `last_update_message` fields fail to decode due to missing htlc_maximum_msat. let legacy_chan_info_with_some_and_fail_update = >::from_hex("fd01ca00020000010800000000000156660221027f921585f2ac0c7c70e36110adecfd8fd14b8a99bfb3d000a283fcac358fce8804b6b6b40004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c8181d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f00083a840000034d013413a70000009000000000000f4240000027100000001406210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c2308b6b6b40004000000170201010402002a060800000000000004d2080909000000000000162e0a0d0c00040000000902040000000a0c8181d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f00083a840000034d013413a70000009000000000000f424000002710000000140a01000c0100").unwrap(); - let read_chan_info: ChannelInfo = crate::util::ser::Readable::read(&mut legacy_chan_info_with_some_and_fail_update.as_slice()).unwrap(); + let read_chan_info: ChannelInfo = crate::util::ser::Readable::read( + &mut legacy_chan_info_with_some_and_fail_update.as_slice(), + ) + .unwrap(); assert_eq!(read_chan_info.announcement_received_time, 87654); assert_eq!(read_chan_info.one_to_two, None); assert_eq!(read_chan_info.two_to_one, None); let legacy_chan_info_with_none: Vec = >::from_hex("ba00020000010800000000000156660221027f921585f2ac0c7c70e36110adecfd8fd14b8a99bfb3d000a283fcac358fce88042e2e2c0004000000170201010402002a060800000000000004d20801000a0d0c00040000000902040000000a0c010006210355f8d2238a322d16b602bd0ceaad5b01019fb055971eaadcc9b29226a4da6c23082e2e2c0004000000170201010402002a060800000000000004d20801000a0d0c00040000000902040000000a0c01000a01000c0100").unwrap(); - let read_chan_info: ChannelInfo = crate::util::ser::Readable::read(&mut legacy_chan_info_with_none.as_slice()).unwrap(); + let read_chan_info: ChannelInfo = + crate::util::ser::Readable::read(&mut legacy_chan_info_with_none.as_slice()).unwrap(); assert_eq!(read_chan_info.announcement_received_time, 87654); assert_eq!(read_chan_info.one_to_two, None); assert_eq!(read_chan_info.two_to_one, None); @@ -3422,30 +3986,31 @@ pub(crate) mod tests { fn node_info_is_readable() { // 1. Check we can read a valid NodeAnnouncementInfo and fail on an invalid one let announcement_message = >::from_hex("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000122013413a7031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f2020201010101010101010101010101010101010101010101010101010101010101010000701fffefdfc2607").unwrap(); - let announcement_message = NodeAnnouncement::read(&mut announcement_message.as_slice()).unwrap(); + let announcement_message = + NodeAnnouncement::read(&mut announcement_message.as_slice()).unwrap(); let valid_node_ann_info = NodeAnnouncementInfo { features: channelmanager::provided_node_features(&UserConfig::default()), last_update: 0, rgb: [0u8; 3], alias: NodeAlias([0u8; 32]), - announcement_message: Some(announcement_message) + announcement_message: Some(announcement_message), }; let mut encoded_valid_node_ann_info = Vec::new(); assert!(valid_node_ann_info.write(&mut encoded_valid_node_ann_info).is_ok()); - let read_valid_node_ann_info = NodeAnnouncementInfo::read(&mut encoded_valid_node_ann_info.as_slice()).unwrap(); + let read_valid_node_ann_info = + NodeAnnouncementInfo::read(&mut encoded_valid_node_ann_info.as_slice()).unwrap(); assert_eq!(read_valid_node_ann_info, valid_node_ann_info); assert_eq!(read_valid_node_ann_info.addresses().len(), 1); let encoded_invalid_node_ann_info = >::from_hex("3f0009000788a000080a51a20204000000000403000000062000000000000000000000000000000000000000000000000000000000000000000a0505014004d2").unwrap(); - let read_invalid_node_ann_info_res = NodeAnnouncementInfo::read(&mut encoded_invalid_node_ann_info.as_slice()); + let read_invalid_node_ann_info_res = + NodeAnnouncementInfo::read(&mut encoded_invalid_node_ann_info.as_slice()); assert!(read_invalid_node_ann_info_res.is_err()); // 2. Check we can read a NodeInfo anyways, but set the NodeAnnouncementInfo to None if invalid - let valid_node_info = NodeInfo { - channels: Vec::new(), - announcement_info: Some(valid_node_ann_info), - }; + let valid_node_info = + NodeInfo { channels: Vec::new(), announcement_info: Some(valid_node_ann_info) }; let mut encoded_valid_node_info = Vec::new(); assert!(valid_node_info.write(&mut encoded_valid_node_info).is_ok()); @@ -3453,14 +4018,16 @@ pub(crate) mod tests { assert_eq!(read_valid_node_info, valid_node_info); let encoded_invalid_node_info_hex = >::from_hex("4402403f0009000788a000080a51a20204000000000403000000062000000000000000000000000000000000000000000000000000000000000000000a0505014004d20400").unwrap(); - let read_invalid_node_info = NodeInfo::read(&mut encoded_invalid_node_info_hex.as_slice()).unwrap(); + let read_invalid_node_info = + NodeInfo::read(&mut encoded_invalid_node_info_hex.as_slice()).unwrap(); assert_eq!(read_invalid_node_info.announcement_info, None); } #[test] fn test_node_info_keeps_compatibility() { let old_ann_info_with_addresses = >::from_hex("3f0009000708a000080a51220204000000000403000000062000000000000000000000000000000000000000000000000000000000000000000a0505014104d2").unwrap(); - let ann_info_with_addresses = NodeAnnouncementInfo::read(&mut old_ann_info_with_addresses.as_slice()) + let ann_info_with_addresses = + NodeAnnouncementInfo::read(&mut old_ann_info_with_addresses.as_slice()) .expect("to be able to read an old NodeAnnouncementInfo with addresses"); // This serialized info has an address field but no announcement_message, therefore the addresses returned by our function will still be empty assert!(ann_info_with_addresses.addresses().is_empty()); @@ -3469,32 +4036,35 @@ pub(crate) mod tests { #[test] fn test_node_id_display() { let node_id = NodeId([42; 33]); - assert_eq!(format!("{}", &node_id), "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a"); + assert_eq!( + format!("{}", &node_id), + "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a" + ); } } #[cfg(ldk_bench)] pub mod benches { use super::*; - use std::io::Read; use criterion::{black_box, Criterion}; + use std::io::Read; pub fn read_network_graph(bench: &mut Criterion) { let logger = crate::util::test_utils::TestLogger::new(); let mut d = crate::routing::router::bench_utils::get_route_file().unwrap(); let mut v = Vec::new(); d.read_to_end(&mut v).unwrap(); - bench.bench_function("read_network_graph", |b| b.iter(|| - NetworkGraph::read(&mut std::io::Cursor::new(black_box(&v)), &logger).unwrap() - )); + bench.bench_function("read_network_graph", |b| { + b.iter(|| { + NetworkGraph::read(&mut std::io::Cursor::new(black_box(&v)), &logger).unwrap() + }) + }); } pub fn write_network_graph(bench: &mut Criterion) { let logger = crate::util::test_utils::TestLogger::new(); let mut d = crate::routing::router::bench_utils::get_route_file().unwrap(); let net_graph = NetworkGraph::read(&mut d, &logger).unwrap(); - bench.bench_function("write_network_graph", |b| b.iter(|| - black_box(&net_graph).encode() - )); + bench.bench_function("write_network_graph", |b| b.iter(|| black_box(&net_graph).encode())); } } diff --git a/lightning/src/routing/mod.rs b/lightning/src/routing/mod.rs index 7fff856345c..2110033afea 100644 --- a/lightning/src/routing/mod.rs +++ b/lightning/src/routing/mod.rs @@ -9,9 +9,9 @@ //! Structs and impls for receiving messages about the network and storing the topology live here. -pub mod utxo; pub mod gossip; pub mod router; pub mod scoring; #[cfg(test)] mod test_utils; +pub mod utxo; diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 1bf90883ec5..9323d5c581a 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -9,36 +9,50 @@ //! The router finds paths within a [`NetworkGraph`] for a payment. -use bitcoin::secp256k1::{PublicKey, Secp256k1, self}; -use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; +use crate::blinded_path::payment::{ + ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs, +}; use crate::blinded_path::{BlindedHop, BlindedPath}; -use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs}; -use crate::ln::PaymentHash; +use crate::crypto::chacha20::ChaCha20; use crate::ln::channelmanager::{ChannelDetails, PaymentId}; -use crate::ln::features::{BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures}; +use crate::ln::features::{ + BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures, +}; use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT}; +use crate::ln::PaymentHash; use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice}; -use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath}; -use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees}; +use crate::onion_message::messenger::{ + DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath, +}; +use crate::routing::gossip::{ + DirectedChannelInfo, EffectiveCapacity, NetworkGraph, NodeId, ReadOnlyNetworkGraph, RoutingFees, +}; use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::sign::EntropySource; -use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer}; use crate::util::logger::{Level, Logger}; -use crate::crypto::chacha20::ChaCha20; +use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; use crate::io; use crate::prelude::*; use crate::sync::Mutex; use alloc::collections::BinaryHeap; -use core::{cmp, fmt}; use core::ops::Deref; +use core::{cmp, fmt}; /// A [`Router`] implemented using [`find_route`]. -pub struct DefaultRouter> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where +pub struct DefaultRouter< + G: Deref> + Clone, + L: 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>, { network_graph: G, logger: L, @@ -48,28 +62,41 @@ pub struct DefaultRouter> + Clone, L: Deref, S message_router: DefaultMessageRouter, } -impl> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where +impl< + G: Deref> + Clone, + L: 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>, { /// Creates a new router. - pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: SP) -> Self { + pub fn new( + network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: SP, + ) -> Self { let random_seed_bytes = Mutex::new(random_seed_bytes); let message_router = DefaultMessageRouter::new(network_graph.clone()); Self { network_graph, logger, random_seed_bytes, scorer, score_params, message_router } } } -impl> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where +impl< + G: Deref> + Clone, + L: 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>, { 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 = { let mut locked_random_seed_bytes = self.random_seed_bytes.lock().unwrap(); @@ -77,18 +104,23 @@ impl> + Clone, L: Deref, S: Deref, SP: Sized, *locked_random_seed_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< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, first_hops: Vec, tlvs: ReceiveTlvs, - amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1 + amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result, ()> { // Limit the number of blinded paths that are computed. const MAX_PAYMENT_PATHS: usize = 3; @@ -98,16 +130,18 @@ impl> + Clone, L: Deref, S: Deref, SP: Sized, const MIN_PEER_CHANNELS: usize = 3; let network_graph = self.network_graph.deref().read_only(); - let paths = first_hops.into_iter() + let paths = first_hops + .into_iter() .filter(|details| details.counterparty.features.supports_route_blinding()) .filter(|details| amount_msats <= details.inbound_capacity_msat) .filter(|details| amount_msats >= details.inbound_htlc_minimum_msat.unwrap_or(0)) .filter(|details| amount_msats <= details.inbound_htlc_maximum_msat.unwrap_or(u64::MAX)) - .filter(|details| network_graph + .filter(|details| { + network_graph .node(&NodeId::from_pubkey(&details.counterparty.node_id)) .map(|node_info| node_info.channels.len() >= MIN_PEER_CHANNELS) .unwrap_or(false) - ) + }) .filter_map(|details| { let short_channel_id = match details.get_inbound_payment_scid() { Some(short_channel_id) => short_channel_id, @@ -139,7 +173,12 @@ impl> + Clone, L: Deref, S: Deref, SP: Sized, }) .map(|forward_node| { BlindedPath::new_for_payment( - &[forward_node], recipient, tlvs.clone(), u64::MAX, entropy_source, secp_ctx + &[forward_node], + recipient, + tlvs.clone(), + u64::MAX, + entropy_source, + secp_ctx, ) }) .take(MAX_PAYMENT_PATHS) @@ -159,21 +198,29 @@ impl> + Clone, L: Deref, S: Deref, SP: Sized, } } -impl< G: Deref> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> MessageRouter for DefaultRouter where +impl< + G: Deref> + Clone, + L: Deref, + S: Deref, + SP: Sized, + Sc: ScoreLookUp, + > MessageRouter for DefaultRouter +where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, + S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>, { fn find_path( - &self, sender: PublicKey, peers: Vec, destination: Destination + &self, sender: PublicKey, peers: Vec, destination: Destination, ) -> Result { self.message_router.find_path(sender, peers, destination) } fn create_blinded_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, peers: Vec, entropy_source: &ES, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result, ()> { self.message_router.create_blinded_paths(recipient, peers, entropy_source, secp_ctx) } @@ -187,7 +234,7 @@ pub trait Router: MessageRouter { /// 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. @@ -200,7 +247,7 @@ pub trait Router: MessageRouter { 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) } @@ -209,10 +256,11 @@ pub trait Router: MessageRouter { /// are assumed to be with the `recipient`'s peers. The payment secret and any constraints are /// given in `tlvs`. fn create_blinded_payment_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, first_hops: Vec, tlvs: ReceiveTlvs, - amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1 + amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result, ()>; } @@ -222,24 +270,32 @@ pub trait Router: MessageRouter { /// [`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), @@ -249,9 +305,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 @@ -272,16 +328,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(HashMap::new()) } + pub fn new() -> Self { + InFlightHtlcs(HashMap::new()) + } /// 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 { @@ -293,7 +353,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)); @@ -303,7 +367,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); } @@ -311,7 +378,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) @@ -320,13 +389,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 { @@ -430,9 +503,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()) + }, } } @@ -440,7 +514,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), } } @@ -448,7 +522,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), } } } @@ -478,7 +552,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::() } @@ -520,7 +596,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, { @@ -539,7 +617,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 { @@ -548,7 +628,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 }); @@ -561,7 +643,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; } @@ -569,9 +653,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, }; @@ -603,8 +689,14 @@ 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), + } } } @@ -739,7 +831,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)), @@ -755,7 +849,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, features: features.and_then(|f: Features| f.bolt12()), @@ -769,18 +865,24 @@ 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()), + previously_failed_blinded_path_idxs: previously_failed_blinded_path_idxs + .unwrap_or(Vec::new()), }) } } - impl PaymentParameters { /// Creates a payee with the node id of the given `pubkey`. /// @@ -788,7 +890,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, @@ -809,10 +916,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 @@ -820,8 +931,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 blinded route hints. @@ -844,8 +958,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 }) + }, } } @@ -856,12 +971,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 + }), } } @@ -872,12 +990,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 + }), } } @@ -906,15 +1022,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; @@ -973,8 +1093,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 { @@ -992,14 +1116,14 @@ impl Payee { fn blinded_route_hints(&self) -> &[(BlindedPayInfo, BlindedPath)] { match self { Self::Blinded { route_hints, .. } => &route_hints[..], - Self::Clear { .. } => &[] + Self::Clear { .. } => &[], } } fn unblinded_route_hints(&self) -> &[RouteHint] { match self { Self::Blinded { .. } => &[], - Self::Clear { route_hints, .. } => &route_hints[..] + Self::Clear { route_hints, .. } => &route_hints[..], } } } @@ -1039,7 +1163,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)?)) } } @@ -1168,7 +1294,7 @@ pub struct PrivateHopCandidate<'a> { /// Information about the private hop communicated via BOLT 11. pub hint: &'a RouteHintHop, /// Node id of the next hop in BOLT 11 route hint. - pub target_node_id: &'a NodeId + pub target_node_id: &'a NodeId, } /// A [`CandidateRouteHop::Blinded`] entry. @@ -1272,7 +1398,13 @@ impl<'a> CandidateRouteHop<'a> { #[inline] pub fn globally_unique_short_channel_id(&self) -> Option { match self { - CandidateRouteHop::FirstHop(hop) => if hop.details.is_public { hop.details.short_channel_id } else { None }, + CandidateRouteHop::FirstHop(hop) => { + if hop.details.is_public { + hop.details.short_channel_id + } else { + None + } + }, CandidateRouteHop::PublicHop(hop) => Some(hop.short_channel_id), CandidateRouteHop::PrivateHop(_) => None, CandidateRouteHop::Blinded(_) => None, @@ -1323,19 +1455,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.0.fee_base_msat, - proportional_millionths: hop.hint.0.fee_proportional_millionths - } + CandidateRouteHop::Blinded(hop) => RoutingFees { + base_msat: hop.hint.0.fee_base_msat, + proportional_millionths: hop.hint.0.fee_proportional_millionths, + }, + CandidateRouteHop::OneHopBlinded(_) => { + RoutingFees { base_msat: 0, proportional_millionths: 0 } }, - CandidateRouteHop::OneHopBlinded(_) => - RoutingFees { base_msat: 0, proportional_millionths: 0 }, } } @@ -1349,12 +1480,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.0.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.0.htlc_maximum_msat } + }, CandidateRouteHop::OneHopBlinded(_) => EffectiveCapacity::Infinite, } } @@ -1367,23 +1503,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 BlindedPath> { match self { - CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => { - Some(&hint.1) - }, + CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) + | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => Some(&hint.1), _ => 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, } } @@ -1441,30 +1577,42 @@ enum CandidateHopId { } #[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; + } } } @@ -1498,7 +1646,6 @@ struct PathBuildingHop<'a> { // only place fields which are not hot there. Luckily, the next three fields are only read if // we end up on the selected path, and only in the final path layout phase, so we don't care // too much if reading them is slow. - fee_msat: u64, /// All the fees paid *after* this channel on the way to the destination @@ -1523,9 +1670,11 @@ struct PathBuildingHop<'a> { // Note that these assertions only pass on somewhat recent rustc, and thus are gated on the // ldk_bench flag. #[cfg(ldk_bench)] -const _NODE_MAP_SIZE_TWO_CACHE_LINES: usize = 128 - core::mem::size_of::<(NodeId, PathBuildingHop)>(); +const _NODE_MAP_SIZE_TWO_CACHE_LINES: usize = + 128 - core::mem::size_of::<(NodeId, PathBuildingHop)>(); #[cfg(ldk_bench)] -const _NODE_MAP_SIZE_EXACTLY_CACHE_LINES: usize = core::mem::size_of::<(NodeId, PathBuildingHop)>() - 128; +const _NODE_MAP_SIZE_EXACTLY_CACHE_LINES: usize = + core::mem::size_of::<(NodeId, PathBuildingHop)>() - 128; impl<'a> core::fmt::Debug for PathBuildingHop<'a> { fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { @@ -1536,13 +1685,15 @@ 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 - (&self.next_hops_fee_msat + &self.hop_use_fee_msat))) + .field( + "total_fee_msat - (next_hops_fee_msat + hop_use_fee_msat)", + &(&self.total_fee_msat - (&self.next_hops_fee_msat + &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()); #[cfg(all(not(ldk_bench), any(test, fuzzing)))] - let debug_struct = debug_struct - .field("value_contribution_msat", &self.value_contribution_msat); + let debug_struct = debug_struct.field("value_contribution_msat", &self.value_contribution_msat); debug_struct.finish() } } @@ -1617,7 +1768,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. // @@ -1652,7 +1805,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 { @@ -1670,7 +1825,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)) } @@ -1678,8 +1834,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) } @@ -1702,9 +1860,7 @@ impl fmt::Display for LoggedPayeePubkey { "payee node id ".fmt(f)?; pk.fmt(f) }, - None => { - "blinded payee".fmt(f) - }, + None => "blinded payee".fmt(f), } } } @@ -1713,7 +1869,8 @@ 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 id ".fmt(f)?; hint.1.introduction_node_id.fmt(f)?; " and blinding point ".fmt(f)?; @@ -1738,7 +1895,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. @@ -1754,13 +1911,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 { @@ -1796,25 +1965,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 final_value_msat = route_params.final_value_msat; // If we're routing to a blinded recipient, we won't have their node id. Therefore, keep the @@ -1822,23 +2008,38 @@ 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); if payee_node_id_opt.map_or(false, |payee| payee == our_node_id) { - return Err(LightningError{err: "Cannot generate a route to ourselves".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Cannot generate a route to ourselves".to_owned(), + action: ErrorAction::IgnoreError, + }); } if our_node_id == maybe_dummy_payee_node_id { - return Err(LightningError{err: "Invalid origin node id provided, use a different one".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Invalid origin node id provided, use a different one".to_owned(), + action: ErrorAction::IgnoreError, + }); } if final_value_msat > MAX_VALUE_MSAT { - return Err(LightningError{err: "Cannot generate a route of more value than all existing satoshis".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Cannot generate a route of more value than all existing satoshis".to_owned(), + action: ErrorAction::IgnoreError, + }); } if final_value_msat == 0 { - return Err(LightningError{err: "Cannot send a payment of 0 msat".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Cannot send a payment of 0 msat".to_owned(), + action: ErrorAction::IgnoreError, + }); } match &payment_params.payee { @@ -1846,7 +2047,10 @@ where L::Target: Logger { for route in route_hints.iter() { for hop in &route.0 { if hop.src_node_id == *node_id { - return Err(LightningError{err: "Route hint cannot have the payee as the source.".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Route hint cannot have the payee as the source.".to_owned(), + action: ErrorAction::IgnoreError, + }); } } } @@ -1857,17 +2061,29 @@ where L::Target: Logger { } for (_, blinded_path) in route_hints.iter() { if blinded_path.blinded_hops.len() == 0 { - return Err(LightningError{err: "0-hop blinded path provided".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "0-hop blinded path provided".to_owned(), + action: ErrorAction::IgnoreError, + }); } else if &blinded_path.introduction_node_id == our_node_pubkey { - log_info!(logger, "Got blinded path with ourselves as the introduction node, ignoring"); - } else if blinded_path.blinded_hops.len() == 1 && - route_hints.iter().any( |(_, p)| p.blinded_hops.len() == 1 - && p.introduction_node_id != blinded_path.introduction_node_id) - { - return Err(LightningError{err: format!("1-hop blinded paths must all have matching introduction node ids"), action: ErrorAction::IgnoreError}); + log_info!( + logger, + "Got blinded path with ourselves as the introduction node, ignoring" + ); + } else if blinded_path.blinded_hops.len() == 1 + && route_hints.iter().any(|(_, p)| { + p.blinded_hops.len() == 1 + && p.introduction_node_id != blinded_path.introduction_node_id + }) { + return Err(LightningError { + err: format!( + "1-hop blinded paths must all have matching introduction node ids" + ), + action: ErrorAction::IgnoreError, + }); } } - } + }, } let final_cltv_expiry_delta = payment_params.payee.final_cltv_expiry_delta().unwrap_or(0); if payment_params.max_total_cltv_expiry_delta <= final_cltv_expiry_delta { @@ -1934,7 +2150,10 @@ where L::Target: Logger { let network_nodes = network_graph.nodes(); if payment_params.max_path_count == 0 { - return Err(LightningError{err: "Can't find a route with no paths allowed.".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Can't find a route with no paths allowed.".to_owned(), + action: ErrorAction::IgnoreError, + }); } // Allow MPP only if we have a features set from somewhere that indicates the payee supports @@ -1945,11 +2164,15 @@ 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()); log_trace!(logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph with a fee limit of {} msat", our_node_pubkey, LoggedPayeePubkey(payment_params.payee.node_id()), @@ -1962,14 +2185,21 @@ where L::Target: Logger { // inserting first hops suggested by the caller as targets. // Our search will then attempt to reach them while traversing from the payee node. let mut first_hop_targets: HashMap<_, Vec<&ChannelDetails>> = - HashMap::with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 }); + HashMap::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() { panic!("first_hops should be filled in with usable channels, not pending ones"); } if chan.counterparty.node_id == *our_node_pubkey { - return Err(LightningError{err: "First hop cannot have our_node_pubkey as a destination.".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "First hop cannot have our_node_pubkey as a destination.".to_owned(), + action: ErrorAction::IgnoreError, + }); } first_hop_targets .entry(NodeId::from_pubkey(&chan.counterparty.node_id)) @@ -1977,12 +2207,15 @@ where L::Target: Logger { .push(chan); } if first_hop_targets.is_empty() { - return Err(LightningError{err: "Cannot route when there are no outbound routes away from us".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Cannot route when there are no outbound routes away from us".to_owned(), + action: ErrorAction::IgnoreError, + }); } } let mut private_hop_key_cache = HashMap::with_capacity( - payment_params.payee.unblinded_route_hints().iter().map(|path| path.0.len()).sum() + payment_params.payee.unblinded_route_hints().iter().map(|path| path.0.len()).sum(), ); // Because we store references to private hop node_ids in `dist`, below, we need them to exist @@ -2027,7 +2260,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 }; @@ -2050,12 +2284,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); - } - - log_trace!(logger, "Building path from {} to payer {} for value {} msat.", - LoggedPayeePubkey(payment_params.payee.node_id()), our_node_pubkey, final_value_msat); + 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 + ); // Remember how many candidates we ignored to allow for some logging afterwards. let mut num_ignored_value_contribution: u32 = 0; @@ -2420,12 +2663,18 @@ where L::Target: Logger { if let Some(first_channels) = first_hop_targets.get(&$node_id) { for details in first_channels { let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate { - details, payer_node_id: &our_node_id, + details, + payer_node_id: &our_node_id, }); - 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 + ); } } @@ -2439,19 +2688,24 @@ 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 + ); } } } @@ -2474,17 +2728,23 @@ where L::Target: Logger { // If first hop is a private channel and the only way to reach the payee, this is the only // place where it could be added. - payee_node_id_opt.map(|payee| first_hop_targets.get(&payee).map(|first_channels| { - for details in first_channels { - let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate { - details, payer_node_id: &our_node_id, - }); - let added = add_entry!(&candidate, 0, path_value_msat, - 0, 0u64, 0, 0).is_some(); - log_trace!(logger, "{} direct route to payee via {}", - if added { "Added" } else { "Skipped" }, LoggedCandidateHop(&candidate)); - } - })); + payee_node_id_opt.map(|payee| { + first_hop_targets.get(&payee).map(|first_channels| { + for details in first_channels { + let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate { + details, + payer_node_id: &our_node_id, + }); + let added = add_entry!(&candidate, 0, path_value_msat, 0, 0u64, 0, 0).is_some(); + log_trace!( + logger, + "{} direct route to payee via {}", + if added { "Added" } else { "Skipped" }, + LoggedCandidateHop(&candidate) + ); + } + }) + }); // Add the payee as a target, so that the payee-to-payer // search algorithm knows what to start with. @@ -2511,37 +2771,58 @@ where L::Target: Logger { // in the regular network graph. first_hop_targets.get(&intro_node_id).is_some() || network_nodes.get(&intro_node_id).is_some(); - if !have_intro_node_in_graph || our_node_id == intro_node_id { continue } + if !have_intro_node_in_graph || our_node_id == intro_node_id { + continue; + } let candidate = if hint.1.blinded_hops.len() == 1 { CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, hint_idx }) - } else { CandidateRouteHop::Blinded(BlindedPathCandidate { hint, hint_idx }) }; + } else { + CandidateRouteHop::Blinded(BlindedPathCandidate { hint, hint_idx }) + }; let mut path_contribution_msat = path_value_msat; - if let Some(hop_used_msat) = add_entry!(&candidate, - 0, path_contribution_msat, 0, 0_u64, 0, 0) + if let Some(hop_used_msat) = + add_entry!(&candidate, 0, path_contribution_msat, 0, 0_u64, 0, 0) { path_contribution_msat = hop_used_msat; - } else { continue } - if let Some(first_channels) = first_hop_targets.get_mut(&NodeId::from_pubkey(&hint.1.introduction_node_id)) { - sort_first_hop_channels(first_channels, &used_liquidities, recommended_value_msat, - our_node_pubkey); + } else { + continue; + } + if let Some(first_channels) = + first_hop_targets.get_mut(&NodeId::from_pubkey(&hint.1.introduction_node_id)) + { + sort_first_hop_channels( + 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, + details, + payer_node_id: &our_node_id, }); - 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(), - candidate.blinded_path().map_or(1, |bp| bp.blinded_hops.len() as u8)); + 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(), + candidate.blinded_path().map_or(1, |bp| bp.blinded_hops.len() as u8) + ); } } } - 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 first_hop_src_id = NodeId::from_pubkey(&route.0.first().unwrap().src_node_id); let first_hop_src_is_reachable = @@ -2555,8 +2836,8 @@ where L::Target: Logger { // We start building the path from reverse, i.e., from payee // to the first RouteHintHop in the path. 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)); let mut hop_used = true; let mut aggregate_next_hops_fee_msat: u64 = 0; let mut aggregate_next_hops_path_htlc_minimum_msat: u64 = 0; @@ -2569,7 +2850,10 @@ where L::Target: Logger { let target = private_hop_key_cache.get(&prev_hop_id).unwrap(); if let Some(first_channels) = first_hop_targets.get(&target) { - if first_channels.iter().any(|d| d.outbound_scid_alias == Some(hop.short_channel_id)) { + if first_channels + .iter() + .any(|d| d.outbound_scid_alias == Some(hop.short_channel_id)) + { log_trace!(logger, "Ignoring route hint with SCID {} (and any previous) due to it being a direct channel of ours.", hop.short_channel_id); break; @@ -2579,17 +2863,28 @@ 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 })); - - if let Some(hop_used_msat) = add_entry!(&candidate, - aggregate_next_hops_fee_msat, aggregate_path_contribution_msat, - aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, - aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length) - { + .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, + }) + }); + + if let Some(hop_used_msat) = add_entry!( + &candidate, + aggregate_next_hops_fee_msat, + aggregate_path_contribution_msat, + aggregate_next_hops_path_htlc_minimum_msat, + aggregate_next_hops_path_penalty_msat, + aggregate_next_hops_cltv_delta, + aggregate_next_hops_path_length + ) { aggregate_path_contribution_msat = hop_used_msat; } else { // If this hop was not used then there is no use checking the preceding @@ -2598,38 +2893,47 @@ where L::Target: Logger { hop_used = false; } - let used_liquidity_msat = used_liquidities - .get(&candidate.id()).copied() - .unwrap_or(0); + let used_liquidity_msat = + used_liquidities.get(&candidate.id()).copied().unwrap_or(0); let channel_usage = ChannelUsage { amount_msat: final_value_msat + aggregate_next_hops_fee_msat, inflight_htlc_msat: used_liquidity_msat, effective_capacity: candidate.effective_capacity(), }; - let channel_penalty_msat = scorer.channel_penalty_msat( - &candidate, channel_usage, score_params - ); - aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat - .saturating_add(channel_penalty_msat); + let channel_penalty_msat = + scorer.channel_penalty_msat(&candidate, channel_usage, score_params); + aggregate_next_hops_path_penalty_msat = + aggregate_next_hops_path_penalty_msat.saturating_add(channel_penalty_msat); - aggregate_next_hops_cltv_delta = aggregate_next_hops_cltv_delta - .saturating_add(hop.cltv_expiry_delta as u32); + aggregate_next_hops_cltv_delta = + aggregate_next_hops_cltv_delta.saturating_add(hop.cltv_expiry_delta as u32); - aggregate_next_hops_path_length = aggregate_next_hops_path_length - .saturating_add(1); + aggregate_next_hops_path_length = + aggregate_next_hops_path_length.saturating_add(1); // Searching for a direct channel between last checked hop and first_hop_targets if let Some(first_channels) = first_hop_targets.get_mut(&target) { - sort_first_hop_channels(first_channels, &used_liquidities, - recommended_value_msat, our_node_pubkey); + sort_first_hop_channels( + 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, - }); - add_entry!(&first_hop_candidate, - aggregate_next_hops_fee_msat, aggregate_path_contribution_msat, - aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, - aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length); + let first_hop_candidate = + CandidateRouteHop::FirstHop(FirstHopCandidate { + details, + payer_node_id: &our_node_id, + }); + add_entry!( + &first_hop_candidate, + aggregate_next_hops_fee_msat, + aggregate_path_contribution_msat, + aggregate_next_hops_path_htlc_minimum_msat, + aggregate_next_hops_path_penalty_msat, + aggregate_next_hops_cltv_delta, + aggregate_next_hops_path_length + ); } } @@ -2642,18 +2946,33 @@ where L::Target: Logger { // for the last node in the RouteHint. We need to just add the fees to // route through the current node so that the preceding node (next iteration) // can use it. - let hops_fee = compute_fees(aggregate_next_hops_fee_msat + final_value_msat, hop.fees) - .map_or(None, |inc| inc.checked_add(aggregate_next_hops_fee_msat)); - aggregate_next_hops_fee_msat = if let Some(val) = hops_fee { val } else { break; }; + let hops_fee = + compute_fees(aggregate_next_hops_fee_msat + final_value_msat, hop.fees) + .map_or(None, |inc| inc.checked_add(aggregate_next_hops_fee_msat)); + aggregate_next_hops_fee_msat = if let Some(val) = hops_fee { + val + } else { + break; + }; // The next channel will need to relay this channel's min_htlc *plus* the fees taken by // this route hint's source node to forward said min over this channel. aggregate_next_hops_path_htlc_minimum_msat = { let curr_htlc_min = cmp::max( - candidate.htlc_minimum_msat(), aggregate_next_hops_path_htlc_minimum_msat + candidate.htlc_minimum_msat(), + aggregate_next_hops_path_htlc_minimum_msat, ); - let curr_htlc_min_fee = if let Some(val) = compute_fees(curr_htlc_min, hop.fees) { val } else { break }; - if let Some(min) = curr_htlc_min.checked_add(curr_htlc_min_fee) { min } else { break } + let curr_htlc_min_fee = + if let Some(val) = compute_fees(curr_htlc_min, hop.fees) { + val + } else { + break; + }; + if let Some(min) = curr_htlc_min.checked_add(curr_htlc_min_fee) { + min + } else { + break; + } }; if idx == route.0.len() - 1 { @@ -2666,20 +2985,30 @@ where L::Target: Logger { // Note that we *must* check if the last hop was added as `add_entry` // always assumes that the third argument is a node to which we have a // path. - if let Some(first_channels) = first_hop_targets.get_mut(&NodeId::from_pubkey(&hop.src_node_id)) { - sort_first_hop_channels(first_channels, &used_liquidities, - recommended_value_msat, our_node_pubkey); + if let Some(first_channels) = + first_hop_targets.get_mut(&NodeId::from_pubkey(&hop.src_node_id)) + { + sort_first_hop_channels( + 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, - }); - add_entry!(&first_hop_candidate, + let first_hop_candidate = + CandidateRouteHop::FirstHop(FirstHopCandidate { + details, + payer_node_id: &our_node_id, + }); + add_entry!( + &first_hop_candidate, aggregate_next_hops_fee_msat, aggregate_path_contribution_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta, - aggregate_next_hops_path_length); + aggregate_next_hops_path_length + ); } } } @@ -2687,7 +3016,11 @@ where L::Target: Logger { } } - 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. @@ -2702,24 +3035,42 @@ 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, total_cltv_delta, mut value_contribution_msat, path_length_to_node, .. }) = targets.pop() { - + 'path_construction: while let Some(RouteGraphNode { + node_id, + 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.remove(&our_node_id).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; - let target = ordered_hops.last().unwrap().0.candidate.target().unwrap_or(maybe_dummy_payee_node_id); + let target = ordered_hops + .last() + .unwrap() + .0 + .candidate + .target() + .unwrap_or(maybe_dummy_payee_node_id); if let Some(first_channels) = first_hop_targets.get(&target) { for details in first_channels { - if let CandidateRouteHop::FirstHop(FirstHopCandidate { details: last_hop_details, .. }) - = ordered_hops.last().unwrap().0.candidate + if let CandidateRouteHop::FirstHop(FirstHopCandidate { + details: last_hop_details, + .. + }) = ordered_hops.last().unwrap().0.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; } @@ -2766,7 +3117,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 @@ -2774,8 +3125,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 @@ -2794,7 +3147,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. @@ -2806,14 +3160,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; } } @@ -2829,7 +3187,9 @@ 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 @@ -2837,9 +3197,13 @@ where L::Target: Logger { match network_nodes.get(&node_id) { None => {}, Some(node) => { - add_entries_to_cheapest_to_target_node!(node, node_id, + add_entries_to_cheapest_to_target_node!( + node, + node_id, value_contribution_msat, - total_cltv_delta, path_length_to_node); + total_cltv_delta, + path_length_to_node + ); }, } } @@ -2860,14 +3224,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, @@ -2882,10 +3253,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.", @@ -2897,32 +3271,41 @@ where L::Target: Logger { // Step (5). if payment_paths.len() == 0 { - return Err(LightningError{err: "Failed to find a path to the given destination".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Failed to find a path to the given destination".to_owned(), + action: ErrorAction::IgnoreError, + }); } if already_collected_value_msat < final_value_msat { - return Err(LightningError{err: "Failed to find a sufficient route to the given destination".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Failed to find a sufficient route to the given destination".to_owned(), + action: ErrorAction::IgnoreError, + }); } // 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 { @@ -2940,15 +3323,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); } @@ -2958,18 +3350,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); } @@ -2978,10 +3378,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 @@ -2993,14 +3394,20 @@ 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(|_| LightningError{err: format!("Public key {:?} is invalid", &target), action: ErrorAction::IgnoreAndLog(Level::Trace)})?, + pubkey: PublicKey::from_slice(target.as_slice()).map_err(|_| LightningError { + err: format!("Public key {:?} is invalid", &target), + action: ErrorAction::IgnoreAndLog(Level::Trace), + })?, node_features: node_features.clone(), short_channel_id: hop.candidate.short_channel_id().unwrap(), channel_features: hop.candidate.features(), @@ -3019,7 +3426,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. @@ -3043,8 +3452,13 @@ where L::Target: Logger { // Make sure we would never create a route whose total fees exceed max_total_routing_fee_msat. if let Some(max_total_routing_fee_msat) = route_params.max_total_routing_fee_msat { if route.get_total_fees() > max_total_routing_fee_msat { - return Err(LightningError{err: format!("Failed to find route that adheres to the maximum total fee limit of {}msat", - max_total_routing_fee_msat), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: format!( + "Failed to find route that adheres to the maximum total fee limit of {}msat", + max_total_routing_fee_msat + ), + action: ErrorAction::IgnoreError, + }); } } @@ -3056,8 +3470,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(); @@ -3067,17 +3482,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. @@ -3086,7 +3507,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 @@ -3100,15 +3522,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); + } + }); + } } } @@ -3118,26 +3541,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); } } } @@ -3148,21 +3579,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], @@ -3170,9 +3617,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] { @@ -3196,7 +3644,10 @@ fn build_route_from_hops_internal( } if hops.len() > MAX_PATH_LENGTH_ESTIMATE.into() { - return Err(LightningError{err: "Cannot build a route exceeding the maximum path length.".to_owned(), action: ErrorAction::IgnoreError}); + return Err(LightningError { + err: "Cannot build a route exceeding the maximum path length.".to_owned(), + action: ErrorAction::IgnoreError, + }); } let our_node_id = NodeId::from_pubkey(our_node_pubkey); @@ -3207,42 +3658,60 @@ 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, BlindedPath}; - 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::chain::transaction::OutPoint; - use crate::sign::EntropySource; - use crate::ln::ChannelId; + use crate::crypto::chacha20::ChaCha20; + use crate::ln::channelmanager; use crate::ln::features::{BlindedHopFeatures, ChannelFeatures, InitFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT}; - use crate::ln::channelmanager; + use crate::ln::ChannelId; use crate::offers::invoice::BlindedPayInfo; + 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::sign::EntropySource; use crate::util::config::UserConfig; - use crate::util::test_utils as ln_test_utils; - use crate::crypto::chacha20::ChaCha20; - use crate::util::ser::{Readable, Writeable}; #[cfg(c_bindings)] use crate::util::ser::Writer; + use crate::util::ser::{Readable, Writeable}; + use crate::util::test_utils as ln_test_utils; - use bitcoin::hashes::Hash; - use bitcoin::network::constants::Network; use bitcoin::blockdata::constants::ChainHash; - use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::opcodes; + use bitcoin::blockdata::script::Builder; use bitcoin::blockdata::transaction::TxOut; use bitcoin::hashes::hex::FromHex; - use bitcoin::secp256k1::{PublicKey,SecretKey}; + use bitcoin::hashes::Hash; + use bitcoin::network::constants::Network; use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; use crate::io::Cursor; use crate::prelude::*; @@ -3250,8 +3719,10 @@ mod tests { use core::convert::TryInto; - fn get_channel_details(short_channel_id: Option, node_id: PublicKey, - features: InitFeatures, outbound_capacity_msat: u64) -> channelmanager::ChannelDetails { + fn get_channel_details( + short_channel_id: Option, node_id: PublicKey, features: InitFeatures, + outbound_capacity_msat: u64, + ) -> channelmanager::ChannelDetails { channelmanager::ChannelDetails { channel_id: ChannelId::new_zero(), counterparty: channelmanager::ChannelCounterparty { @@ -3262,7 +3733,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, @@ -3278,8 +3752,10 @@ mod tests { confirmations_required: None, confirmations: None, force_close_spend_delay: None, - is_outbound: true, is_channel_ready: true, - is_usable: true, is_public: true, + is_outbound: true, + is_channel_ready: true, + is_usable: true, + is_public: true, inbound_htlc_minimum_msat: None, inbound_htlc_maximum_msat: None, config: None, @@ -3299,17 +3775,35 @@ mod tests { // Simple route to 2 via 1 - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 0); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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(LightningError { err, action: ErrorAction::IgnoreError }) = 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, 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]); @@ -3338,17 +3832,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(LightningError{err, action: ErrorAction::IgnoreError}) = 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(LightningError { err, action: ErrorAction::IgnoreError }) = 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); } @@ -3364,123 +3881,181 @@ 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, - 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, - 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, - 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, - 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, - 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, + 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, + 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, + 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, + 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, + 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, - 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, + 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, - 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, + 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(LightningError{err, action: ErrorAction::IgnoreError}) = 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(LightningError { err, action: ErrorAction::IgnoreError }) = 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, - 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, + 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); } @@ -3499,76 +4074,110 @@ 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, - 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, - 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, + 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, + 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, - 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, - 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, + 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, + 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, - 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, + 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. @@ -3576,45 +4185,69 @@ 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, - 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, - 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, - 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, + 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, + 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, + 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); @@ -3622,8 +4255,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); @@ -3637,7 +4279,9 @@ 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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); @@ -3645,51 +4289,82 @@ mod tests { // 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, - 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, + 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, - 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, + 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(LightningError{err, action: ErrorAction::IgnoreError}) = 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 of 9999msat"); - } else { panic!(); } - - let mut route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 5_000); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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 of 9999msat" + ); + } 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); } @@ -3703,45 +4378,76 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); // // 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, - 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, - 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, + 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, + 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 route_params = RouteParameters::from_payment_params_and_value(payment_params, 100); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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(LightningError { err, action: ErrorAction::IgnoreError }) = 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]); @@ -3777,18 +4483,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(LightningError{err, action: ErrorAction::IgnoreError}) = 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(LightningError { err, action: ErrorAction::IgnoreError }) = 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]); @@ -3821,8 +4548,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]); @@ -3849,11 +4585,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]); @@ -3872,79 +4620,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] @@ -3963,10 +4705,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, @@ -3976,20 +4715,40 @@ 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(LightningError{err, action: ErrorAction::IgnoreError}) = 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(LightningError { err, action: ErrorAction::IgnoreError }) = 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 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(); 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]); @@ -4026,47 +4785,61 @@ 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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); // 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]); @@ -4103,43 +4876,46 @@ 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, - }])] - } - - #[test] - fn multi_hint_last_hops_test() { + 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] + fn multi_hint_last_hops_test() { 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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); @@ -4147,34 +4923,53 @@ mod tests { // 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, - 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, - 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, + 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, + 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(), &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]); @@ -4202,8 +4997,12 @@ 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].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 } #[test] @@ -4211,44 +5010,68 @@ 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, - 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, - 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, + 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, + 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]); @@ -4269,61 +5092,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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); @@ -4331,8 +5164,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]); @@ -4369,8 +5211,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] @@ -4382,14 +5228,28 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); // 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]); @@ -4403,18 +5263,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]); @@ -4444,13 +5316,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]); @@ -4487,38 +5371,75 @@ 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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); 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 } @@ -4529,8 +5450,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); @@ -4544,7 +5477,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 } @@ -4556,14 +5492,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] @@ -4584,78 +5532,116 @@ 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, - 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, - 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, + 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, + 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, - 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, + 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, - 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 250_000_001); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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); @@ -4665,41 +5651,67 @@ 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, - 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 200_000_001); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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); @@ -4708,51 +5720,78 @@ 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, - 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, + 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, - 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 15_001); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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); @@ -4764,72 +5803,115 @@ 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, - 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() - }); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[0], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 4, + 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_v0_p2wsh(); + 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_v0_p2wsh(); *chain_monitor.utxo_ret.lock().unwrap() = UtxoResult::Sync(Ok(TxOut { value: 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, - 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, - 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() - }); + 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, + 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 15_001); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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); @@ -4838,36 +5920,59 @@ 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, - 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 10_001); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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); @@ -4895,99 +6000,147 @@ 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, - 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, - 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, + 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, + 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, - 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, - 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, - 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, - 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } - } + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 12, + timestamp: 2, + 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, + 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, + 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, + 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); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } + } { // 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 { @@ -5000,10 +6153,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 { @@ -5025,36 +6187,55 @@ 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, - 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, - 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, + 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, + 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 { @@ -5081,9 +6262,13 @@ mod tests { let blinded_path = BlindedPath { introduction_node_id: nodes[2], blinding_point: ln_test_utils::pubkey(42), - blinded_hops: vec![BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }], + blinded_hops: vec![BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42 as u8), + encrypted_payload: Vec::new(), + }], }; - 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, @@ -5091,8 +6276,10 @@ mod tests { cltv_expiry_delta: 0, features: BlindedHopFeatures::empty(), }; - let one_hop_blinded_payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), blinded_path.clone())]) - .with_bolt12_features(bolt12_features.clone()).unwrap(); + let one_hop_blinded_payment_params = + PaymentParameters::blinded(vec![(blinded_payinfo.clone(), blinded_path.clone())]) + .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 @@ -5112,17 +6299,16 @@ mod tests { let mut node_1_payinfo = blinded_payinfo.clone(); node_1_payinfo.htlc_maximum_msat = 180_000; - let two_hop_blinded_payment_params = PaymentParameters::blinded( - vec![ - (node_0_payinfo, blinded_path_node_0), - (node_7_payinfo, blinded_path_node_7), - (node_1_payinfo, blinded_path_node_1) - ]) - .with_bolt12_features(bolt12_features).unwrap(); + let two_hop_blinded_payment_params = PaymentParameters::blinded(vec![ + (node_0_payinfo, blinded_path_node_0), + (node_7_payinfo, blinded_path_node_7), + (node_1_payinfo, 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); @@ -5139,106 +6325,154 @@ 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, - 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, - 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, + 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, + 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, - 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, - 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, + 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, + 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, - 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, - 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, + 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 300_000); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(zero_payment_params, 100); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { @@ -5246,22 +6480,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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(fail_payment_params, 250_000); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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 { @@ -5278,22 +6530,40 @@ 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 { - assert_eq!(path.hops.last().unwrap().pubkey, - payment_params.payee.blinded_route_hints().iter() + assert_eq!( + path.hops.last().unwrap().pubkey, + payment_params + .payee + .blinded_route_hints() + .iter() .find(|(p, _)| p.htlc_maximum_msat == path.final_value_msat()) - .map(|(_, p)| p.introduction_node_id).unwrap()); + .map(|(_, p)| p.introduction_node_id) + .unwrap() + ); } else { assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]); } @@ -5327,124 +6597,176 @@ mod tests { // are used twice will have 200 sats capacity. // 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, - 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, - 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, + 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, + 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, - 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, - 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, + 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, + 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(), + }, + ); // Capacity of 200 sats because this channel will be used by 3rd path as well. - 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, - 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() - }); + 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, + 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, 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, - 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[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - 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, - 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[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 11, - timestamp: 2, - 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, + 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[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + 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, + 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[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 11, + timestamp: 2, + 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(), + }, + ); // Path via {node7, node2} is channels {12, 13, 5}. // We already limited them to 200 sats (they are used twice for 100 sats). @@ -5452,22 +6774,40 @@ mod tests { { // Attempt to route more than available results in a failure. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params.clone(), 350_000); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 350_000); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // Now, attempt to route 300 sats (exact amount we can route). // Our algorithm should provide us with these 3 paths, 100 sats each. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 300_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, 300_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; @@ -5477,7 +6817,6 @@ mod tests { } assert_eq!(total_amount_paid_msat, 300_000); } - } #[test] @@ -5504,124 +6843,176 @@ mod tests { // are used twice will have 200 sats capacity. // 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, - 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, - 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, + 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, + 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, - 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, - 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, + 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, + 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(), + }, + ); // Capacity of 200 sats because this channel will be used by 3rd path as well. - 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, - 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() - }); + 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, + 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, 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, - 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[7], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 13, - timestamp: 2, - 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, - 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[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 11, - timestamp: 2, - 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, + 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[7], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 13, + timestamp: 2, + 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, + 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[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 11, + timestamp: 2, + 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(), + }, + ); // Path via {node7, node2} is channels {12, 13, 5}. // We already limited them to 200 sats (they are used twice for 100 sats). @@ -5630,10 +7021,19 @@ mod tests { { // Now, attempt to route 180 sats. // Our algorithm should provide us with these 2 paths. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 180_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, 180_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_value_transferred_msat = 0; @@ -5677,71 +7077,103 @@ 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, - 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, - 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, + 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, + 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, - 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, - 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, - 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, + 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, + 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, + 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(), + }, + ); // Path via {node7, node2, node4} is channels {12, 13, 6, 11}. // All channels should be 100 sats capacity. But for the fee experiment, @@ -5753,84 +7185,137 @@ 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, - 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, - 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, - 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, - 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, + 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, + 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, + 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 210_000); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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) }; - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + 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(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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; @@ -5864,77 +7349,109 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); 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, - 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, - 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, - 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, - 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, + 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, + 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, + 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, + 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: @@ -5974,102 +7491,150 @@ mod tests { // First, we set limits on these (previously unlimited) channels. // 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, - 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, - 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 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, + 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, + 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, - 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, - 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, + 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, + 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, - 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, - 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, + 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, + 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); - if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = 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!(); } + let route_params = + RouteParameters::from_payment_params_and_value(payment_params.clone(), 150_000); + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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!(); + } } { // 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 { @@ -6082,10 +7647,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 { @@ -6133,101 +7707,212 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); 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); - update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 6, - timestamp: 1, - 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[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); - update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 5, - timestamp: 1, - flags: 0, - 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_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 4, - timestamp: 1, - flags: 0, - 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_channel(&gossip_sync, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3); - update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 3, - timestamp: 1, - flags: 0, - 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_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2); - update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 2, - timestamp: 1, - flags: 0, - 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); - update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate { - chain_hash: ChainHash::using_genesis_block(Network::Testnet), - short_channel_id: 1, - timestamp: 1, - flags: 0, - 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_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + &privkeys[1], + ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), + 6, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &our_privkey, + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 6, + timestamp: 1, + 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[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, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[1], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 5, + timestamp: 1, + flags: 0, + 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_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + &privkeys[3], + ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), + 4, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 4, + timestamp: 1, + flags: 0, + 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_channel( + &gossip_sync, + &secp_ctx, + &privkeys[3], + &privkeys[2], + ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), + 3, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[3], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 3, + timestamp: 1, + flags: 0, + 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_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + &privkeys[4], + ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), + 2, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[2], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 2, + timestamp: 1, + flags: 0, + 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, + ); + update_channel( + &gossip_sync, + &secp_ctx, + &privkeys[4], + UnsignedChannelUpdate { + chain_hash: ChainHash::using_genesis_block(Network::Testnet), + short_channel_id: 1, + timestamp: 1, + flags: 0, + 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, + ); { // 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); @@ -6254,7 +7939,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 @@ -6269,56 +7953,81 @@ mod tests { // 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, - 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, - 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: 2, + timestamp: 2, + 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, + 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) + ); } } @@ -6341,56 +8050,84 @@ 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, - 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, - 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, + 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, + 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) + ); } } @@ -6415,12 +8152,32 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); { - 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); @@ -6429,18 +8186,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); @@ -6457,18 +8238,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); @@ -6482,16 +8313,27 @@ 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 keys_manager = ln_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.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); @@ -6501,10 +8343,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); @@ -6518,12 +8368,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 + } } } @@ -6533,13 +8392,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 + } } } @@ -6547,17 +8415,27 @@ 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 keys_manager = ln_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, 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); @@ -6566,8 +8444,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); @@ -6576,12 +8463,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(LightningError { 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(LightningError { err, .. }) => { + assert_eq!(err, "Failed to find a path to the given destination"); + }, + Ok(_) => panic!("Expected error"), } } @@ -6666,27 +8561,46 @@ 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 keys_manager = ln_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( - 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) - { - Err(LightningError { err, .. } ) => { + 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(LightningError { err, .. }) => { assert_eq!(err, "Failed to find a path to the given destination"); }, Ok(_) => panic!("Expected error"), @@ -6702,30 +8616,54 @@ 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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); // 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; + } } } @@ -6741,21 +8679,36 @@ 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) - { - Err(LightningError { err, .. } ) => { + 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(LightningError { err, .. }) => { assert_eq!(err, "Failed to find a path to the given destination"); }, Ok(_) => panic!("Expected error"), @@ -6769,31 +8722,59 @@ 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 keys_manager = ln_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.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); } @@ -6809,10 +8790,19 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[4u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - 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![]; @@ -6824,10 +8814,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(); @@ -6835,9 +8827,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; } @@ -6846,10 +8845,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)); @@ -6877,9 +8883,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]); @@ -6895,30 +8909,40 @@ mod tests { // Set the fee on channel 13 to 100% 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, - 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, - 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, + 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, + 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) @@ -6927,13 +8951,26 @@ mod tests { let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); // 100,000 sats is less than the available liquidity on each channel, set above. - let route_params = RouteParameters::from_payment_params_and_value( - payment_params, 100_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, 100_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) + ); } #[cfg(feature = "std")] @@ -6960,10 +8997,22 @@ mod tests { }; let params = ProbabilisticScoringFeeParameters::default(); - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &graph, + &logger, + ); 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] @@ -6981,10 +9030,22 @@ mod tests { }; let params = ProbabilisticScoringFeeParameters::default(); - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &graph, + &logger, + ); 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] @@ -7002,10 +9063,22 @@ mod tests { }; let params = ProbabilisticScoringFeeParameters::default(); - let mut scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &graph, &logger); + let mut scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &graph, + &logger, + ); 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] @@ -7017,13 +9090,20 @@ mod tests { let random_seed_bytes = keys_manager.get_secure_random_bytes(); 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); @@ -7031,28 +9111,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()); } @@ -7072,44 +9175,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(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, - &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), - &random_seed_bytes) - { + if let Err(LightningError { err, action: ErrorAction::IgnoreError }) = 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); @@ -7128,46 +9247,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); @@ -7176,12 +9305,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); @@ -7192,8 +9339,14 @@ mod tests { introduction_node_id: intermed_node_id, blinding_point: ln_test_utils::pubkey(42), blinded_hops: vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42), encrypted_payload: vec![] }, - BlindedHop { blinded_node_id: ln_test_utils::pubkey(43), encrypted_payload: vec![] }, + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(42), + encrypted_payload: vec![], + }, + BlindedHop { + blinded_node_id: ln_test_utils::pubkey(43), + encrypted_payload: vec![], + }, ], }; let blinded_payinfo = BlindedPayInfo { @@ -7207,13 +9360,22 @@ mod tests { let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); let payment_params = PaymentParameters::blinded(vec![ (blinded_payinfo.clone(), blinded_path.clone()), - (blinded_payinfo.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(); + (blinded_payinfo.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); @@ -7226,44 +9388,63 @@ mod tests { introduction_node_id: ln_test_utils::pubkey(42), blinding_point: ln_test_utils::pubkey(43), blinded_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() } + 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(), + }, ], }; let blinded_path_2 = BlindedPath { introduction_node_id: ln_test_utils::pubkey(46), blinding_point: ln_test_utils::pubkey(47), blinded_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(), + }, ], }; // (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 { - hops: blinded_path_1.blinded_hops, - blinding_point: blinded_path_1.blinding_point, - 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 { + hops: blinded_path_1.blinded_hops, + blinding_point: blinded_path_1.blinding_point, + 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(); @@ -7292,27 +9473,32 @@ mod tests { let blinded_path = BlindedPath { introduction_node_id: ln_test_utils::pubkey(43), blinding_point: ln_test_utils::pubkey(48), - blinded_hops: vec![BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() }], + blinded_hops: vec![BlindedHop { + blinded_node_id: ln_test_utils::pubkey(49), + encrypted_payload: Vec::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: blinded_path.introduction_node_id, - 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: blinded_path.introduction_node_id, + 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 { hops: blinded_path.blinded_hops, blinding_point: blinded_path.blinding_point, @@ -7332,42 +9518,55 @@ mod tests { introduction_node_id: ln_test_utils::pubkey(43), blinding_point: ln_test_utils::pubkey(44), blinded_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() } + 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(), + }, ], }; - 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: blinded_path.introduction_node_id, - 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 { - hops: blinded_path.blinded_hops, - blinding_point: blinded_path.blinding_point, - excess_final_cltv_expiry_delta: 0, - final_value_msat: 200, - }), - }], route_params: None}; + 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: blinded_path.introduction_node_id, + 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 { + hops: blinded_path.blinded_hops, + blinding_point: blinded_path.blinding_point, + 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); } @@ -7394,9 +9593,10 @@ mod tests { blinded_hops: Vec::with_capacity(num_blinded_hops), }; for i in 0..num_blinded_hops { - blinded_path.blinded_hops.push( - BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 + i as u8), encrypted_payload: Vec::new() }, - ); + blinded_path.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, @@ -7407,11 +9607,20 @@ mod tests { features: BlindedHopFeatures::empty(), }; - let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), blinded_path.clone())]); - 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 payment_params = + PaymentParameters::blinded(vec![(blinded_payinfo.clone(), blinded_path.clone())]); + 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); @@ -7423,8 +9632,12 @@ mod tests { let final_hop = route.paths[0].hops.last().unwrap(); assert_eq!(final_hop.pubkey, blinded_path.introduction_node_id); 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); @@ -7446,9 +9659,10 @@ mod tests { let mut invalid_blinded_path = BlindedPath { introduction_node_id: nodes[2], blinding_point: ln_test_utils::pubkey(42), - blinded_hops: vec![ - BlindedHop { blinded_node_id: ln_test_utils::pubkey(43), encrypted_payload: vec![0; 43] }, - ], + blinded_hops: vec![BlindedHop { + blinded_node_id: ln_test_utils::pubkey(43), + encrypted_payload: vec![0; 43], + }], }; let blinded_payinfo = BlindedPayInfo { fee_base_msat: 100, @@ -7463,40 +9677,66 @@ mod tests { invalid_blinded_path_2.introduction_node_id = ln_test_utils::pubkey(45); let payment_params = PaymentParameters::blinded(vec![ (blinded_payinfo.clone(), invalid_blinded_path.clone()), - (blinded_payinfo.clone(), invalid_blinded_path_2)]); + (blinded_payinfo.clone(), invalid_blinded_path_2), + ]); 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(LightningError { err, .. }) => { assert_eq!(err, "1-hop blinded paths must all have matching introduction node ids"); }, - _ => panic!("Expected error") + _ => panic!("Expected error"), } invalid_blinded_path.introduction_node_id = our_id; - let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), invalid_blinded_path.clone())]); + let payment_params = PaymentParameters::blinded(vec![( + blinded_payinfo.clone(), + invalid_blinded_path.clone(), + )]); 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(LightningError { 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"), } invalid_blinded_path.introduction_node_id = ln_test_utils::pubkey(46); invalid_blinded_path.blinded_hops.clear(); - let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo, invalid_blinded_path)]); + let payment_params = + PaymentParameters::blinded(vec![(blinded_payinfo, 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(LightningError { err, .. }) => { assert_eq!(err, "0-hop blinded path provided"); }, - _ => panic!("Expected error") + _ => panic!("Expected error"), } } @@ -7518,8 +9758,14 @@ mod tests { introduction_node_id: nodes[2], blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let blinded_payinfo_1 = BlindedPayInfo { @@ -7541,21 +9787,39 @@ mod tests { (blinded_payinfo_2.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.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.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); @@ -7582,41 +9846,67 @@ 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, - 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, - 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, + 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, + 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_path = BlindedPath { introduction_node_id: nodes[1], blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let blinded_payinfo = BlindedPayInfo { @@ -7632,21 +9922,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(LightningError { 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(LightningError { 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); } @@ -7676,16 +9985,25 @@ 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_path = BlindedPath { introduction_node_id: nodes[1], blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let blinded_payinfo = BlindedPayInfo { @@ -7708,14 +10026,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); } @@ -7740,8 +10066,14 @@ mod tests { introduction_node_id: our_id, blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let blinded_payinfo = BlindedPayInfo { @@ -7760,16 +10092,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(LightningError { 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] @@ -7792,8 +10133,14 @@ mod tests { introduction_node_id: our_id, blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let blinded_payinfo = BlindedPayInfo { @@ -7817,16 +10164,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(LightningError { 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] @@ -7852,8 +10208,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; @@ -7863,8 +10221,14 @@ mod tests { introduction_node_id: nodes[0], blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let blinded_payinfo = BlindedPayInfo { @@ -7877,41 +10241,47 @@ mod tests { }; let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config); PaymentParameters::blinded(vec![(blinded_payinfo, 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(LightningError { 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 @@ -7930,11 +10300,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]; @@ -7943,52 +10322,67 @@ mod tests { introduction_node_id: nodes[0], blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let mut blinded_hints = Vec::new(); for (base_fee, htlc_min) in base_fees.iter().zip(htlc_mins.iter()) { - blinded_hints.push((BlindedPayInfo { - fee_base_msat: *base_fee, - fee_proportional_millionths: 0, - htlc_minimum_msat: *htlc_min, - htlc_maximum_msat: htlc_min * 100, - cltv_expiry_delta: 10, - features: BlindedHopFeatures::empty(), - }, blinded_path.clone())); + blinded_hints.push(( + BlindedPayInfo { + fee_base_msat: *base_fee, + fee_proportional_millionths: 0, + htlc_minimum_msat: *htlc_min, + htlc_maximum_msat: htlc_min * 100, + cltv_expiry_delta: 10, + features: BlindedHopFeatures::empty(), + }, + blinded_path.clone(), + )); } 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); } @@ -8004,7 +10398,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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); @@ -8013,56 +10411,91 @@ 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, - 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, + 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![ - (BlindedPayInfo { + let blinded_hints = vec![( + 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(), - }, BlindedPath { + }, + BlindedPath { introduction_node_id: nodes[0], blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], - }) - ]; + }, + )]; 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(LightningError { 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] @@ -8074,7 +10507,11 @@ 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 keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); let config = UserConfig::default(); @@ -8082,11 +10519,12 @@ mod tests { // 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 = { @@ -8094,34 +10532,49 @@ mod tests { introduction_node_id: nodes[0], blinding_point: ln_test_utils::pubkey(42), blinded_hops: 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(), + }, ], }; let mut blinded_hints = Vec::new(); for htlc_min in htlc_mins.iter() { - blinded_hints.push((BlindedPayInfo { - fee_base_msat: 0, - fee_proportional_millionths: 0, - htlc_minimum_msat: *htlc_min, - htlc_maximum_msat: *htlc_min * 100, - cltv_expiry_delta: 10, - features: BlindedHopFeatures::empty(), - }, blinded_path.clone())); + blinded_hints.push(( + BlindedPayInfo { + fee_base_msat: 0, + fee_proportional_millionths: 0, + htlc_minimum_msat: *htlc_min, + htlc_maximum_msat: *htlc_min * 100, + cltv_expiry_delta: 10, + features: BlindedHopFeatures::empty(), + }, + blinded_path.clone(), + )); } 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); } @@ -8142,100 +10595,141 @@ 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, - 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, - 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, - 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, - 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, + 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, + 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, + 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, + 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); @@ -8245,25 +10739,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); @@ -8288,32 +10806,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); @@ -8334,12 +10862,12 @@ pub(crate) mod bench_utils { use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use crate::chain::transaction::OutPoint; - use crate::routing::scoring::ScoreUpdate; - use crate::sign::{EntropySource, KeysManager}; - use crate::ln::ChannelId; use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails}; use crate::ln::features::Bolt11InvoiceFeatures; + use crate::ln::ChannelId; use crate::routing::gossip::NetworkGraph; + use crate::routing::scoring::ScoreUpdate; + use crate::sign::{EntropySource, KeysManager}; use crate::util::config::UserConfig; use crate::util::ser::ReadableArgs; use crate::util::test_utils::TestLogger; @@ -8378,7 +10906,9 @@ pub(crate) mod bench_utils { return res; } - pub(crate) fn read_network_graph(logger: &TestLogger) -> Result, &'static str> { + pub(crate) fn read_network_graph( + logger: &TestLogger, + ) -> Result, &'static str> { get_route_file().map(|mut f| NetworkGraph::read(&mut f, logger).unwrap()) } @@ -8400,7 +10930,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), @@ -8429,9 +10960,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 keys_manager = KeysManager::new(&[0u8; 32], 42, 42); @@ -8444,20 +10975,43 @@ pub(crate) mod bench_utils { for _ in 0..route_count * 3 / 2 { 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 { // ...and seed the scorer with success and failure data... seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0; @@ -8466,23 +11020,44 @@ pub(crate) mod bench_utils { // Generate fail/success paths for a wider range of potential amounts with // MPP enabled to give us a chance to apply penalties for more potential // routes. - let mpp_features = channelmanager::provided_bolt11_invoice_features(&UserConfig::default()); + let mpp_features = channelmanager::provided_bolt11_invoice_features( + &UserConfig::default(), + ); let params = PaymentParameters::from_node_id(dst, 42) - .with_bolt11_features(mpp_features).unwrap(); + .with_bolt11_features(mpp_features) + .unwrap(); let route_params = RouteParameters::from_payment_params_and_value( - params.clone(), score_amt); - let route_res = get_route(&payer, &route_params, &graph.read_only(), - Some(&[&first_hop]), &TestLogger::new(), scorer, score_params, - &random_seed_bytes); + params.clone(), + score_amt, + ); + let route_res = get_route( + &payer, + &route_params, + &graph.read_only(), + Some(&[&first_hop]), + &TestLogger::new(), + scorer, + score_params, + &random_seed_bytes, + ); if let Ok(route) = route_res { for path in route.paths { if seed & 0x80 == 0 { scorer.payment_path_successful(&path, Duration::ZERO); } else { - let short_channel_id = path.hops[path.hops.len() / 2].short_channel_id; - scorer.payment_path_failed(&path, short_channel_id, Duration::ZERO); + let short_channel_id = + path.hops[path.hops.len() / 2].short_channel_id; + scorer.payment_path_failed( + &path, + short_channel_id, + Duration::ZERO, + ); } - seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0; + seed = seed + .overflowing_mul(6364136223846793005) + .0 + .overflowing_add(1) + .0; } break; } @@ -8500,10 +11075,19 @@ pub(crate) mod bench_utils { // selected destinations, possibly causing us to fail because, eg, the newly-selected path // requires a too-high CLTV delta. route_endpoints.retain(|(first_hop, params, amt_msat)| { - let route_params = RouteParameters::from_payment_params_and_value( - params.clone(), *amt_msat); - 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); + get_route( + &payer, + &route_params, + &graph.read_only(), + Some(&[first_hop]), + &TestLogger::new(), + scorer, + score_params, + &random_seed_bytes, + ) + .is_ok() }); route_endpoints.truncate(route_count); assert_eq!(route_endpoints.len(), route_count); @@ -8514,12 +11098,15 @@ pub(crate) mod bench_utils { #[cfg(ldk_bench)] pub mod benches { use super::*; - use crate::routing::scoring::{ScoreUpdate, ScoreLookUp}; - use crate::sign::{EntropySource, KeysManager}; use crate::ln::channelmanager; use crate::ln::features::Bolt11InvoiceFeatures; use crate::routing::gossip::NetworkGraph; - use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters}; + use crate::routing::scoring::{ + FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringDecayParameters, + ProbabilisticScoringFeeParameters, + }; + use crate::routing::scoring::{ScoreLookUp, ScoreUpdate}; + use crate::sign::{EntropySource, KeysManager}; use crate::util::config::UserConfig; use crate::util::logger::{Logger, Record}; use crate::util::test_utils::TestLogger; @@ -8535,46 +11122,90 @@ pub mod benches { let logger = TestLogger::new(); let network_graph = bench_utils::read_network_graph(&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_network_graph(&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 = bench_utils::read_network_graph(&logger).unwrap(); let params = ProbabilisticScoringFeeParameters::default(); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - generate_routes(bench, &network_graph, scorer, ¶ms, Bolt11InvoiceFeatures::empty(), 0, - "generate_routes_with_probabilistic_scorer"); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); + 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 = bench_utils::read_network_graph(&logger).unwrap(); let params = ProbabilisticScoringFeeParameters::default(); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, - "generate_mpp_routes_with_probabilistic_scorer"); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); + 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 = bench_utils::read_network_graph(&logger).unwrap(); let params = ProbabilisticScoringFeeParameters::default(); - let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 100_000_000, - "generate_large_mpp_routes_with_probabilistic_scorer"); + let scorer = ProbabilisticScorer::new( + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); + 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) { @@ -8583,10 +11214,19 @@ pub mod benches { let mut params = ProbabilisticScoringFeeParameters::default(); params.linear_success_probability = false; let scorer = ProbabilisticScorer::new( - ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, - "generate_routes_with_nonlinear_probabilistic_scorer"); + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); + 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) { @@ -8595,10 +11235,19 @@ pub mod benches { let mut params = ProbabilisticScoringFeeParameters::default(); params.linear_success_probability = false; let scorer = ProbabilisticScorer::new( - ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - generate_routes(bench, &network_graph, scorer, ¶ms, - channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0, - "generate_mpp_routes_with_nonlinear_probabilistic_scorer"); + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); + 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) { @@ -8607,10 +11256,19 @@ pub mod benches { let mut params = ProbabilisticScoringFeeParameters::default(); params.linear_success_probability = false; let scorer = ProbabilisticScorer::new( - ProbabilisticScoringDecayParameters::default(), &network_graph, &logger); - 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"); + ProbabilisticScoringDecayParameters::default(), + &network_graph, + &logger, + ); + 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( @@ -8623,16 +11281,36 @@ pub mod benches { let random_seed_bytes = keys_manager.get_secure_random_bytes(); // 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. 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 8c36bd100e5..e35483c480f 100644 --- a/lightning/src/routing/scoring.rs +++ b/lightning/src/routing/scoring.rs @@ -58,21 +58,21 @@ use crate::ln::msgs::DecodeError; use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId}; -use crate::routing::router::{Path, CandidateRouteHop, PublicHopCandidate}; -use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; +use crate::routing::router::{CandidateRouteHop, Path, PublicHopCandidate}; use crate::util::logger::Logger; +use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; +use crate::io::{self, Read}; use crate::prelude::*; -use core::{cmp, fmt}; +use crate::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use core::convert::TryInto; use core::ops::{Deref, DerefMut}; use core::time::Duration; -use crate::io::{self, Read}; -use crate::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; +use core::{cmp, fmt}; #[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 @@ -328,7 +328,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) } @@ -359,7 +360,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) } @@ -380,7 +383,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 { @@ -410,17 +412,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) {} @@ -475,7 +485,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, @@ -802,7 +814,11 @@ struct ChannelLiquidity { } /// A snapshot of [`ChannelLiquidity`] in one direction assuming a certain channel capacity. -struct DirectedChannelLiquidity, BRT: Deref, T: Deref> { +struct DirectedChannelLiquidity< + L: Deref, + BRT: Deref, + T: Deref, +> { min_liquidity_offset_msat: L, max_liquidity_offset_msat: L, liquidity_history: HistoricalMinMaxBuckets, @@ -811,16 +827,16 @@ struct DirectedChannelLiquidity, BRT: 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 { - Self { - decay_params, - network_graph, - logger, - channel_liquidities: HashMap::new(), - } + pub fn new( + decay_params: ProbabilisticScoringDecayParameters, network_graph: G, logger: L, + ) -> Self { + Self { decay_params, network_graph, logger, channel_liquidities: HashMap::new() } } #[cfg(test)] @@ -842,8 +858,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", @@ -871,7 +889,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 + ); } }; @@ -885,7 +909,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) { @@ -926,8 +952,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) { @@ -936,8 +963,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. @@ -957,8 +986,9 @@ 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) - -> Option { + &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) { @@ -967,9 +997,14 @@ impl>, L: Deref> ProbabilisticScorer whe let capacity_msat = directed_info.effective_capacity().as_msat(); let dir_liq = liq.as_directed(source, target, capacity_msat); - return dir_liq.liquidity_history.calculate_success_probability_times_billion( - ¶ms, amount_msat, capacity_msat - ).map(|p| p as f64 / (1024 * 1024 * 1024) as f64); + return dir_liq + .liquidity_history + .calculate_success_probability_times_billion( + ¶ms, + amount_msat, + capacity_msat, + ) + .map(|p| p as f64 / (1024 * 1024 * 1024) as f64); } } } @@ -994,14 +1029,26 @@ impl ChannelLiquidity { fn as_directed( &self, source: &NodeId, target: &NodeId, capacity_msat: u64, ) -> DirectedChannelLiquidity<&u64, &HistoricalBucketRangeTracker, &Duration> { - let (min_liquidity_offset_msat, max_liquidity_offset_msat, min_liquidity_offset_history, max_liquidity_offset_history) = - if source < target { - (&self.min_liquidity_offset_msat, &self.max_liquidity_offset_msat, - &self.min_liquidity_offset_history, &self.max_liquidity_offset_history) - } else { - (&self.max_liquidity_offset_msat, &self.min_liquidity_offset_msat, - &self.max_liquidity_offset_history, &self.min_liquidity_offset_history) - }; + let ( + min_liquidity_offset_msat, + max_liquidity_offset_msat, + min_liquidity_offset_history, + max_liquidity_offset_history, + ) = if source < target { + ( + &self.min_liquidity_offset_msat, + &self.max_liquidity_offset_msat, + &self.min_liquidity_offset_history, + &self.max_liquidity_offset_history, + ) + } else { + ( + &self.max_liquidity_offset_msat, + &self.min_liquidity_offset_msat, + &self.max_liquidity_offset_history, + &self.min_liquidity_offset_history, + ) + }; DirectedChannelLiquidity { min_liquidity_offset_msat, @@ -1021,14 +1068,26 @@ impl ChannelLiquidity { fn as_directed_mut( &mut self, source: &NodeId, target: &NodeId, capacity_msat: u64, ) -> DirectedChannelLiquidity<&mut u64, &mut HistoricalBucketRangeTracker, &mut Duration> { - let (min_liquidity_offset_msat, max_liquidity_offset_msat, min_liquidity_offset_history, max_liquidity_offset_history) = - if source < target { - (&mut self.min_liquidity_offset_msat, &mut self.max_liquidity_offset_msat, - &mut self.min_liquidity_offset_history, &mut self.max_liquidity_offset_history) - } else { - (&mut self.max_liquidity_offset_msat, &mut self.min_liquidity_offset_msat, - &mut self.max_liquidity_offset_history, &mut self.min_liquidity_offset_history) - }; + let ( + min_liquidity_offset_msat, + max_liquidity_offset_msat, + min_liquidity_offset_history, + max_liquidity_offset_history, + ) = if source < target { + ( + &mut self.min_liquidity_offset_msat, + &mut self.max_liquidity_offset_msat, + &mut self.min_liquidity_offset_history, + &mut self.max_liquidity_offset_history, + ) + } else { + ( + &mut self.max_liquidity_offset_msat, + &mut self.min_liquidity_offset_msat, + &mut self.max_liquidity_offset_history, + &mut self.min_liquidity_offset_history, + ) + }; DirectedChannelLiquidity { min_liquidity_offset_msat, @@ -1091,42 +1150,54 @@ fn success_probability( debug_assert!(amount_msat < max_liquidity_msat); debug_assert!(max_liquidity_msat <= capacity_msat); - let (numerator, mut denominator) = - if params.linear_success_probability { - (max_liquidity_msat - amount_msat, - (max_liquidity_msat - min_liquidity_msat).saturating_add(1)) - } else { - let capacity = capacity_msat as f64; - let min = (min_liquidity_msat as f64) / capacity; - let max = (max_liquidity_msat as f64) / capacity; - let amount = (amount_msat as f64) / capacity; - - // Assume the channel has a probability density function of (x - 0.5)^2 for values from - // 0 to 1 (where 1 is the channel's full capacity). The success probability given some - // liquidity bounds is thus the integral under the curve from the amount to maximum - // estimated liquidity, divided by the same integral from the minimum to the maximum - // estimated liquidity bounds. - // - // Because the integral from x to y is simply (y - 0.5)^3 - (x - 0.5)^3, we can - // calculate the cumulative density function between the min/max bounds trivially. Note - // that we don't bother to normalize the CDF to total to 1, as it will come out in the - // division of num / den. - let (max_pow, amt_pow, min_pow) = three_f64_pow_3(max - 0.5, amount - 0.5, min - 0.5); - let num = max_pow - amt_pow; - let den = max_pow - min_pow; - - // Because our numerator and denominator max out at 0.5^3 we need to multiply them by - // quite a large factor to get something useful (ideally in the 2^30 range). - const BILLIONISH: f64 = 1024.0 * 1024.0 * 1024.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); - (numerator, denominator) - }; - - if min_zero_implies_no_successes && min_liquidity_msat == 0 && - denominator < u64::max_value() / 21 + let (numerator, mut denominator) = if params.linear_success_probability { + ( + max_liquidity_msat - amount_msat, + (max_liquidity_msat - min_liquidity_msat).saturating_add(1), + ) + } else { + let capacity = capacity_msat as f64; + let min = (min_liquidity_msat as f64) / capacity; + let max = (max_liquidity_msat as f64) / capacity; + let amount = (amount_msat as f64) / capacity; + + // Assume the channel has a probability density function of (x - 0.5)^2 for values from + // 0 to 1 (where 1 is the channel's full capacity). The success probability given some + // liquidity bounds is thus the integral under the curve from the amount to maximum + // estimated liquidity, divided by the same integral from the minimum to the maximum + // estimated liquidity bounds. + // + // Because the integral from x to y is simply (y - 0.5)^3 - (x - 0.5)^3, we can + // calculate the cumulative density function between the min/max bounds trivially. Note + // that we don't bother to normalize the CDF to total to 1, as it will come out in the + // division of num / den. + let (max_pow, amt_pow, min_pow) = three_f64_pow_3(max - 0.5, amount - 0.5, min - 0.5); + let num = max_pow - amt_pow; + let den = max_pow - min_pow; + + // Because our numerator and denominator max out at 0.5^3 we need to multiply them by + // quite a large factor to get something useful (ideally in the 2^30 range). + const BILLIONISH: f64 = 1024.0 * 1024.0 * 1024.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 + ); + (numerator, denominator) + }; + + if min_zero_implies_no_successes + && min_liquidity_msat == 0 + && denominator < u64::max_value() / 21 { // If we have no knowledge of the channel, scale probability down by ~75% // Note that we prefer to increase the denominator rather than decrease the numerator as @@ -1138,11 +1209,17 @@ fn success_probability( (numerator, denominator) } -impl, BRT: Deref, T: Deref> -DirectedChannelLiquidity< L, BRT, T> { +impl< + L: Deref, + BRT: Deref, + T: Deref, + > DirectedChannelLiquidity +{ /// Returns a liquidity penalty for routing the given HTLC `amount_msat` through the channel in /// this direction. - fn penalty_msat(&self, amount_msat: u64, score_params: &ProbabilisticScoringFeeParameters) -> u64 { + fn penalty_msat( + &self, amount_msat: u64, score_params: &ProbabilisticScoringFeeParameters, + ) -> u64 { let available_capacity = self.capacity_msat; let max_liquidity_msat = self.max_liquidity_msat(); let min_liquidity_msat = core::cmp::min(self.min_liquidity_msat(), max_liquidity_msat); @@ -1154,13 +1231,22 @@ DirectedChannelLiquidity< L, BRT, 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; - Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, - score_params.liquidity_penalty_multiplier_msat, - score_params.liquidity_penalty_amount_multiplier_msat) - .saturating_add(score_params.considered_impossible_penalty_msat) + Self::combined_penalty_msat( + amount_msat, + negative_log10_times_2048, + score_params.liquidity_penalty_multiplier_msat, + score_params.liquidity_penalty_amount_multiplier_msat, + ) + .saturating_add(score_params.considered_impossible_penalty_msat) } else { - let (numerator, denominator) = success_probability(amount_msat, - min_liquidity_msat, max_liquidity_msat, available_capacity, score_params, false); + let (numerator, denominator) = success_probability( + 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), // don't bother trying to use the log approximation as it gets too noisy to be @@ -1169,42 +1255,65 @@ DirectedChannelLiquidity< L, BRT, T> { } else { let negative_log10_times_2048 = approx::negative_log10_times_2048(numerator, denominator); - Self::combined_penalty_msat(amount_msat, negative_log10_times_2048, + 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, + ) } }; if 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, amount_msat, self.capacity_msat) - { - let historical_negative_log10_times_2048 = 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, + amount_msat, + self.capacity_msat, + ) { + let historical_negative_log10_times_2048 = 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(amount_msat, 0, - available_capacity, available_capacity, score_params, true); + let (numerator, denominator) = success_probability( + amount_msat, + 0, + available_capacity, + available_capacity, + score_params, + true, + ); let negative_log10_times_2048 = 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, + )); } } @@ -1213,18 +1322,20 @@ DirectedChannelLiquidity< L, BRT, 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) } @@ -1238,49 +1349,89 @@ DirectedChannelLiquidity< L, BRT, 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, BRT: DerefMut, T: DerefMut> -DirectedChannelLiquidity { +impl< + L: DerefMut, + BRT: 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); } /// 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); } /// 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.update_history_buckets(amount_msat, duration_since_epoch); } @@ -1291,10 +1442,12 @@ DirectedChannelLiquidity { /// represents the amount of the successful payment we just made. fn update_history_buckets(&mut self, bucket_offset_msat: u64, duration_since_epoch: Duration) { self.liquidity_history.min_liquidity_offset_history.track_datapoint( - *self.min_liquidity_offset_msat + bucket_offset_msat, self.capacity_msat + *self.min_liquidity_offset_msat + bucket_offset_msat, + self.capacity_msat, ); self.liquidity_history.max_liquidity_offset_history.track_datapoint( - self.max_liquidity_offset_msat.saturating_sub(bucket_offset_msat), self.capacity_msat + self.max_liquidity_offset_msat.saturating_sub(bucket_offset_msat), + self.capacity_msat, ); *self.offset_history_last_updated = duration_since_epoch; } @@ -1318,10 +1471,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 }) => { @@ -1335,14 +1492,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 { @@ -1350,7 +1507,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; } }, @@ -1369,14 +1526,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)); @@ -1393,32 +1561,47 @@ 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; + } } } 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)); @@ -1429,8 +1612,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); @@ -1449,10 +1636,16 @@ impl>, L: Deref> ScoreUpdate for Probabilistic fn time_passed(&mut self, duration_since_epoch: Duration) { let decay_params = self.decay_params; self.channel_liquidities.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; let elapsed_time = @@ -1470,16 +1663,19 @@ impl>, L: Deref> ScoreUpdate for Probabilistic liquidity.offset_history_last_updated = duration_since_epoch; } } - liquidity.min_liquidity_offset_msat != 0 || liquidity.max_liquidity_offset_msat != 0 || - liquidity.min_liquidity_offset_history.buckets != [0; 32] || - liquidity.max_liquidity_offset_history.buckets != [0; 32] + liquidity.min_liquidity_offset_msat != 0 + || liquidity.max_liquidity_offset_msat != 0 + || liquidity.min_liquidity_offset_history.buckets != [0; 32] + || liquidity.max_liquidity_offset_history.buckets != [0; 32] }); } } #[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] @@ -1501,262 +1697,499 @@ mod approx { /// Look-up table for `log10(x) * 2048` where row `i` is used for each `x` having `i` as the /// most significant bit. The next 4 bits of `x`, if applicable, are used for the second index. const LOG10_TIMES_2048: [[u16; (LOWER_BITS_BOUND) as usize]; BITS as usize] = [ - [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, 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], - [617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, - 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, - 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, - 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977], - [1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, - 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, - 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, - 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731], - [1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133, - 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281, - 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2409, 2409, 2409, 2409, 2409, 2409, 2409, 2409], - [2466, 2466, 2466, 2466, 2520, 2520, 2520, 2520, 2571, 2571, 2571, 2571, 2619, 2619, 2619, 2619, - 2665, 2665, 2665, 2665, 2708, 2708, 2708, 2708, 2749, 2749, 2749, 2749, 2789, 2789, 2789, 2789, - 2827, 2827, 2827, 2827, 2863, 2863, 2863, 2863, 2898, 2898, 2898, 2898, 2931, 2931, 2931, 2931, - 2964, 2964, 2964, 2964, 2995, 2995, 2995, 2995, 3025, 3025, 3025, 3025, 3054, 3054, 3054, 3054], - [3083, 3083, 3110, 3110, 3136, 3136, 3162, 3162, 3187, 3187, 3212, 3212, 3235, 3235, 3259, 3259, - 3281, 3281, 3303, 3303, 3324, 3324, 3345, 3345, 3366, 3366, 3386, 3386, 3405, 3405, 3424, 3424, - 3443, 3443, 3462, 3462, 3479, 3479, 3497, 3497, 3514, 3514, 3531, 3531, 3548, 3548, 3564, 3564, - 3580, 3580, 3596, 3596, 3612, 3612, 3627, 3627, 3642, 3642, 3656, 3656, 3671, 3671, 3685, 3685], - [3699, 3713, 3726, 3740, 3753, 3766, 3779, 3791, 3804, 3816, 3828, 3840, 3852, 3864, 3875, 3886, - 3898, 3909, 3919, 3930, 3941, 3951, 3962, 3972, 3982, 3992, 4002, 4012, 4022, 4031, 4041, 4050, - 4060, 4069, 4078, 4087, 4096, 4105, 4114, 4122, 4131, 4139, 4148, 4156, 4164, 4173, 4181, 4189, - 4197, 4205, 4213, 4220, 4228, 4236, 4243, 4251, 4258, 4266, 4273, 4280, 4287, 4294, 4302, 4309], - [4316, 4329, 4343, 4356, 4369, 4382, 4395, 4408, 4420, 4433, 4445, 4457, 4468, 4480, 4492, 4503, - 4514, 4525, 4536, 4547, 4557, 4568, 4578, 4589, 4599, 4609, 4619, 4629, 4638, 4648, 4657, 4667, - 4676, 4685, 4695, 4704, 4713, 4721, 4730, 4739, 4747, 4756, 4764, 4773, 4781, 4789, 4797, 4805, - 4813, 4821, 4829, 4837, 4845, 4852, 4860, 4867, 4875, 4882, 4889, 4897, 4904, 4911, 4918, 4925], - [4932, 4946, 4959, 4973, 4986, 4999, 5012, 5024, 5037, 5049, 5061, 5073, 5085, 5097, 5108, 5119, - 5131, 5142, 5153, 5163, 5174, 5184, 5195, 5205, 5215, 5225, 5235, 5245, 5255, 5264, 5274, 5283, - 5293, 5302, 5311, 5320, 5329, 5338, 5347, 5355, 5364, 5372, 5381, 5389, 5397, 5406, 5414, 5422, - 5430, 5438, 5446, 5453, 5461, 5469, 5476, 5484, 5491, 5499, 5506, 5513, 5520, 5527, 5535, 5542], - [5549, 5562, 5576, 5589, 5603, 5615, 5628, 5641, 5653, 5666, 5678, 5690, 5701, 5713, 5725, 5736, - 5747, 5758, 5769, 5780, 5790, 5801, 5811, 5822, 5832, 5842, 5852, 5862, 5871, 5881, 5890, 5900, - 5909, 5918, 5928, 5937, 5946, 5954, 5963, 5972, 5980, 5989, 5997, 6006, 6014, 6022, 6030, 6038, - 6046, 6054, 6062, 6070, 6078, 6085, 6093, 6100, 6108, 6115, 6122, 6130, 6137, 6144, 6151, 6158], - [6165, 6179, 6192, 6206, 6219, 6232, 6245, 6257, 6270, 6282, 6294, 6306, 6318, 6330, 6341, 6352, - 6364, 6375, 6386, 6396, 6407, 6417, 6428, 6438, 6448, 6458, 6468, 6478, 6488, 6497, 6507, 6516, - 6526, 6535, 6544, 6553, 6562, 6571, 6580, 6588, 6597, 6605, 6614, 6622, 6630, 6639, 6647, 6655, - 6663, 6671, 6679, 6686, 6694, 6702, 6709, 6717, 6724, 6732, 6739, 6746, 6753, 6761, 6768, 6775], - [6782, 6795, 6809, 6822, 6836, 6849, 6861, 6874, 6886, 6899, 6911, 6923, 6934, 6946, 6958, 6969, - 6980, 6991, 7002, 7013, 7023, 7034, 7044, 7055, 7065, 7075, 7085, 7095, 7104, 7114, 7124, 7133, - 7142, 7151, 7161, 7170, 7179, 7187, 7196, 7205, 7213, 7222, 7230, 7239, 7247, 7255, 7263, 7271, - 7279, 7287, 7295, 7303, 7311, 7318, 7326, 7333, 7341, 7348, 7355, 7363, 7370, 7377, 7384, 7391], - [7398, 7412, 7425, 7439, 7452, 7465, 7478, 7490, 7503, 7515, 7527, 7539, 7551, 7563, 7574, 7585, - 7597, 7608, 7619, 7629, 7640, 7651, 7661, 7671, 7681, 7691, 7701, 7711, 7721, 7731, 7740, 7749, - 7759, 7768, 7777, 7786, 7795, 7804, 7813, 7821, 7830, 7838, 7847, 7855, 7864, 7872, 7880, 7888, - 7896, 7904, 7912, 7919, 7927, 7935, 7942, 7950, 7957, 7965, 7972, 7979, 7986, 7994, 8001, 8008], - [8015, 8028, 8042, 8055, 8069, 8082, 8094, 8107, 8119, 8132, 8144, 8156, 8167, 8179, 8191, 8202, - 8213, 8224, 8235, 8246, 8256, 8267, 8277, 8288, 8298, 8308, 8318, 8328, 8337, 8347, 8357, 8366, - 8375, 8384, 8394, 8403, 8412, 8420, 8429, 8438, 8446, 8455, 8463, 8472, 8480, 8488, 8496, 8504, - 8512, 8520, 8528, 8536, 8544, 8551, 8559, 8566, 8574, 8581, 8588, 8596, 8603, 8610, 8617, 8624], - [8631, 8645, 8659, 8672, 8685, 8698, 8711, 8723, 8736, 8748, 8760, 8772, 8784, 8796, 8807, 8818, - 8830, 8841, 8852, 8862, 8873, 8884, 8894, 8904, 8914, 8924, 8934, 8944, 8954, 8964, 8973, 8982, - 8992, 9001, 9010, 9019, 9028, 9037, 9046, 9054, 9063, 9071, 9080, 9088, 9097, 9105, 9113, 9121, - 9129, 9137, 9145, 9152, 9160, 9168, 9175, 9183, 9190, 9198, 9205, 9212, 9219, 9227, 9234, 9241], - [9248, 9261, 9275, 9288, 9302, 9315, 9327, 9340, 9352, 9365, 9377, 9389, 9400, 9412, 9424, 9435, - 9446, 9457, 9468, 9479, 9490, 9500, 9510, 9521, 9531, 9541, 9551, 9561, 9570, 9580, 9590, 9599, - 9608, 9617, 9627, 9636, 9645, 9653, 9662, 9671, 9679, 9688, 9696, 9705, 9713, 9721, 9729, 9737, - 9745, 9753, 9761, 9769, 9777, 9784, 9792, 9799, 9807, 9814, 9821, 9829, 9836, 9843, 9850, 9857], - [9864, 9878, 9892, 9905, 9918, 9931, 9944, 9956, 9969, 9981, 9993, 10005, 10017, 10029, 10040, 10051, - 10063, 10074, 10085, 10095, 10106, 10117, 10127, 10137, 10147, 10157, 10167, 10177, 10187, 10197, 10206, 10215, - 10225, 10234, 10243, 10252, 10261, 10270, 10279, 10287, 10296, 10304, 10313, 10321, 10330, 10338, 10346, 10354, - 10362, 10370, 10378, 10385, 10393, 10401, 10408, 10416, 10423, 10431, 10438, 10445, 10452, 10460, 10467, 10474], - [10481, 10494, 10508, 10521, 10535, 10548, 10560, 10573, 10585, 10598, 10610, 10622, 10634, 10645, 10657, 10668, - 10679, 10690, 10701, 10712, 10723, 10733, 10743, 10754, 10764, 10774, 10784, 10794, 10803, 10813, 10823, 10832, - 10841, 10851, 10860, 10869, 10878, 10886, 10895, 10904, 10912, 10921, 10929, 10938, 10946, 10954, 10962, 10970, - 10978, 10986, 10994, 11002, 11010, 11017, 11025, 11032, 11040, 11047, 11054, 11062, 11069, 11076, 11083, 11090], - [11097, 11111, 11125, 11138, 11151, 11164, 11177, 11189, 11202, 11214, 11226, 11238, 11250, 11262, 11273, 11284, - 11296, 11307, 11318, 11328, 11339, 11350, 11360, 11370, 11380, 11390, 11400, 11410, 11420, 11430, 11439, 11448, - 11458, 11467, 11476, 11485, 11494, 11503, 11512, 11520, 11529, 11538, 11546, 11554, 11563, 11571, 11579, 11587, - 11595, 11603, 11611, 11618, 11626, 11634, 11641, 11649, 11656, 11664, 11671, 11678, 11685, 11693, 11700, 11707], - [11714, 11727, 11741, 11754, 11768, 11781, 11793, 11806, 11818, 11831, 11843, 11855, 11867, 11878, 11890, 11901, - 11912, 11923, 11934, 11945, 11956, 11966, 11976, 11987, 11997, 12007, 12017, 12027, 12036, 12046, 12056, 12065, - 12074, 12084, 12093, 12102, 12111, 12119, 12128, 12137, 12146, 12154, 12162, 12171, 12179, 12187, 12195, 12203, - 12211, 12219, 12227, 12235, 12243, 12250, 12258, 12265, 12273, 12280, 12287, 12295, 12302, 12309, 12316, 12323], - [12330, 12344, 12358, 12371, 12384, 12397, 12410, 12423, 12435, 12447, 12459, 12471, 12483, 12495, 12506, 12517, - 12529, 12540, 12551, 12561, 12572, 12583, 12593, 12603, 12613, 12623, 12633, 12643, 12653, 12663, 12672, 12682, - 12691, 12700, 12709, 12718, 12727, 12736, 12745, 12753, 12762, 12771, 12779, 12787, 12796, 12804, 12812, 12820, - 12828, 12836, 12844, 12851, 12859, 12867, 12874, 12882, 12889, 12897, 12904, 12911, 12918, 12926, 12933, 12940], - [12947, 12960, 12974, 12987, 13001, 13014, 13026, 13039, 13051, 13064, 13076, 13088, 13100, 13111, 13123, 13134, - 13145, 13156, 13167, 13178, 13189, 13199, 13209, 13220, 13230, 13240, 13250, 13260, 13269, 13279, 13289, 13298, - 13307, 13317, 13326, 13335, 13344, 13352, 13361, 13370, 13379, 13387, 13395, 13404, 13412, 13420, 13428, 13436, - 13444, 13452, 13460, 13468, 13476, 13483, 13491, 13498, 13506, 13513, 13521, 13528, 13535, 13542, 13549, 13556], - [13563, 13577, 13591, 13604, 13617, 13630, 13643, 13656, 13668, 13680, 13692, 13704, 13716, 13728, 13739, 13750, - 13762, 13773, 13784, 13794, 13805, 13816, 13826, 13836, 13846, 13857, 13866, 13876, 13886, 13896, 13905, 13915, - 13924, 13933, 13942, 13951, 13960, 13969, 13978, 13986, 13995, 14004, 14012, 14020, 14029, 14037, 14045, 14053, - 14061, 14069, 14077, 14084, 14092, 14100, 14107, 14115, 14122, 14130, 14137, 14144, 14151, 14159, 14166, 14173], - [14180, 14194, 14207, 14220, 14234, 14247, 14259, 14272, 14284, 14297, 14309, 14321, 14333, 14344, 14356, 14367, - 14378, 14389, 14400, 14411, 14422, 14432, 14443, 14453, 14463, 14473, 14483, 14493, 14502, 14512, 14522, 14531, - 14540, 14550, 14559, 14568, 14577, 14586, 14594, 14603, 14612, 14620, 14628, 14637, 14645, 14653, 14661, 14669, - 14677, 14685, 14693, 14701, 14709, 14716, 14724, 14731, 14739, 14746, 14754, 14761, 14768, 14775, 14782, 14789], - [14796, 14810, 14824, 14837, 14850, 14863, 14876, 14889, 14901, 14913, 14925, 14937, 14949, 14961, 14972, 14984, - 14995, 15006, 15017, 15027, 15038, 15049, 15059, 15069, 15079, 15090, 15099, 15109, 15119, 15129, 15138, 15148, - 15157, 15166, 15175, 15184, 15193, 15202, 15211, 15219, 15228, 15237, 15245, 15253, 15262, 15270, 15278, 15286, - 15294, 15302, 15310, 15317, 15325, 15333, 15340, 15348, 15355, 15363, 15370, 15377, 15384, 15392, 15399, 15406], - [15413, 15427, 15440, 15453, 15467, 15480, 15492, 15505, 15517, 15530, 15542, 15554, 15566, 15577, 15589, 15600, - 15611, 15622, 15633, 15644, 15655, 15665, 15676, 15686, 15696, 15706, 15716, 15726, 15736, 15745, 15755, 15764, - 15773, 15783, 15792, 15801, 15810, 15819, 15827, 15836, 15845, 15853, 15862, 15870, 15878, 15886, 15894, 15903, - 15910, 15918, 15926, 15934, 15942, 15949, 15957, 15964, 15972, 15979, 15987, 15994, 16001, 16008, 16015, 16022], - [16029, 16043, 16057, 16070, 16083, 16096, 16109, 16122, 16134, 16146, 16158, 16170, 16182, 16194, 16205, 16217, - 16228, 16239, 16250, 16260, 16271, 16282, 16292, 16302, 16312, 16323, 16332, 16342, 16352, 16362, 16371, 16381, - 16390, 16399, 16408, 16417, 16426, 16435, 16444, 16452, 16461, 16470, 16478, 16486, 16495, 16503, 16511, 16519, - 16527, 16535, 16543, 16550, 16558, 16566, 16573, 16581, 16588, 16596, 16603, 16610, 16618, 16625, 16632, 16639], - [16646, 16660, 16673, 16686, 16700, 16713, 16725, 16738, 16751, 16763, 16775, 16787, 16799, 16810, 16822, 16833, - 16844, 16855, 16866, 16877, 16888, 16898, 16909, 16919, 16929, 16939, 16949, 16959, 16969, 16978, 16988, 16997, - 17006, 17016, 17025, 17034, 17043, 17052, 17060, 17069, 17078, 17086, 17095, 17103, 17111, 17119, 17127, 17136, - 17143, 17151, 17159, 17167, 17175, 17182, 17190, 17197, 17205, 17212, 17220, 17227, 17234, 17241, 17248, 17255], - [17262, 17276, 17290, 17303, 17316, 17329, 17342, 17355, 17367, 17379, 17391, 17403, 17415, 17427, 17438, 17450, - 17461, 17472, 17483, 17493, 17504, 17515, 17525, 17535, 17546, 17556, 17565, 17575, 17585, 17595, 17604, 17614, - 17623, 17632, 17641, 17650, 17659, 17668, 17677, 17685, 17694, 17703, 17711, 17719, 17728, 17736, 17744, 17752, - 17760, 17768, 17776, 17784, 17791, 17799, 17806, 17814, 17821, 17829, 17836, 17843, 17851, 17858, 17865, 17872], - [17879, 17893, 17906, 17920, 17933, 17946, 17958, 17971, 17984, 17996, 18008, 18020, 18032, 18043, 18055, 18066, - 18077, 18088, 18099, 18110, 18121, 18131, 18142, 18152, 18162, 18172, 18182, 18192, 18202, 18211, 18221, 18230, - 18239, 18249, 18258, 18267, 18276, 18285, 18293, 18302, 18311, 18319, 18328, 18336, 18344, 18352, 18360, 18369, - 18377, 18384, 18392, 18400, 18408, 18415, 18423, 18430, 18438, 18445, 18453, 18460, 18467, 18474, 18481, 18488], - [18495, 18509, 18523, 18536, 18549, 18562, 18575, 18588, 18600, 18612, 18624, 18636, 18648, 18660, 18671, 18683, - 18694, 18705, 18716, 18726, 18737, 18748, 18758, 18768, 18779, 18789, 18799, 18808, 18818, 18828, 18837, 18847, - 18856, 18865, 18874, 18883, 18892, 18901, 18910, 18919, 18927, 18936, 18944, 18952, 18961, 18969, 18977, 18985, - 18993, 19001, 19009, 19017, 19024, 19032, 19039, 19047, 19054, 19062, 19069, 19076, 19084, 19091, 19098, 19105], - [19112, 19126, 19139, 19153, 19166, 19179, 19191, 19204, 19217, 19229, 19241, 19253, 19265, 19276, 19288, 19299, - 19310, 19321, 19332, 19343, 19354, 19364, 19375, 19385, 19395, 19405, 19415, 19425, 19435, 19444, 19454, 19463, - 19472, 19482, 19491, 19500, 19509, 19518, 19526, 19535, 19544, 19552, 19561, 19569, 19577, 19585, 19594, 19602, - 19610, 19617, 19625, 19633, 19641, 19648, 19656, 19663, 19671, 19678, 19686, 19693, 19700, 19707, 19714, 19721], - [19728, 19742, 19756, 19769, 19782, 19795, 19808, 19821, 19833, 19845, 19857, 19869, 19881, 19893, 19904, 19916, - 19927, 19938, 19949, 19960, 19970, 19981, 19991, 20001, 20012, 20022, 20032, 20041, 20051, 20061, 20070, 20080, - 20089, 20098, 20107, 20116, 20125, 20134, 20143, 20152, 20160, 20169, 20177, 20185, 20194, 20202, 20210, 20218, - 20226, 20234, 20242, 20250, 20257, 20265, 20272, 20280, 20287, 20295, 20302, 20309, 20317, 20324, 20331, 20338], - [20345, 20359, 20372, 20386, 20399, 20412, 20425, 20437, 20450, 20462, 20474, 20486, 20498, 20509, 20521, 20532, - 20543, 20554, 20565, 20576, 20587, 20597, 20608, 20618, 20628, 20638, 20648, 20658, 20668, 20677, 20687, 20696, - 20705, 20715, 20724, 20733, 20742, 20751, 20759, 20768, 20777, 20785, 20794, 20802, 20810, 20818, 20827, 20835, - 20843, 20850, 20858, 20866, 20874, 20881, 20889, 20896, 20904, 20911, 20919, 20926, 20933, 20940, 20947, 20954], - [20961, 20975, 20989, 21002, 21015, 21028, 21041, 21054, 21066, 21078, 21090, 21102, 21114, 21126, 21137, 21149, - 21160, 21171, 21182, 21193, 21203, 21214, 21224, 21234, 21245, 21255, 21265, 21274, 21284, 21294, 21303, 21313, - 21322, 21331, 21340, 21349, 21358, 21367, 21376, 21385, 21393, 21402, 21410, 21418, 21427, 21435, 21443, 21451, - 21459, 21467, 21475, 21483, 21490, 21498, 21505, 21513, 21520, 21528, 21535, 21542, 21550, 21557, 21564, 21571], - [21578, 21592, 21605, 21619, 21632, 21645, 21658, 21670, 21683, 21695, 21707, 21719, 21731, 21742, 21754, 21765, - 21776, 21787, 21798, 21809, 21820, 21830, 21841, 21851, 21861, 21871, 21881, 21891, 21901, 21910, 21920, 21929, - 21938, 21948, 21957, 21966, 21975, 21984, 21992, 22001, 22010, 22018, 22027, 22035, 22043, 22051, 22060, 22068, - 22076, 22083, 22091, 22099, 22107, 22114, 22122, 22129, 22137, 22144, 22152, 22159, 22166, 22173, 22180, 22187], - [22194, 22208, 22222, 22235, 22248, 22261, 22274, 22287, 22299, 22311, 22323, 22335, 22347, 22359, 22370, 22382, - 22393, 22404, 22415, 22426, 22436, 22447, 22457, 22467, 22478, 22488, 22498, 22507, 22517, 22527, 22536, 22546, - 22555, 22564, 22573, 22582, 22591, 22600, 22609, 22618, 22626, 22635, 22643, 22651, 22660, 22668, 22676, 22684, - 22692, 22700, 22708, 22716, 22723, 22731, 22738, 22746, 22753, 22761, 22768, 22775, 22783, 22790, 22797, 22804], - [22811, 22825, 22838, 22852, 22865, 22878, 22891, 22903, 22916, 22928, 22940, 22952, 22964, 22975, 22987, 22998, - 23009, 23020, 23031, 23042, 23053, 23063, 23074, 23084, 23094, 23104, 23114, 23124, 23134, 23143, 23153, 23162, - 23171, 23181, 23190, 23199, 23208, 23217, 23225, 23234, 23243, 23251, 23260, 23268, 23276, 23284, 23293, 23301, - 23309, 23316, 23324, 23332, 23340, 23347, 23355, 23363, 23370, 23377, 23385, 23392, 23399, 23406, 23413, 23420], - [23427, 23441, 23455, 23468, 23481, 23494, 23507, 23520, 23532, 23544, 23556, 23568, 23580, 23592, 23603, 23615, - 23626, 23637, 23648, 23659, 23669, 23680, 23690, 23700, 23711, 23721, 23731, 23740, 23750, 23760, 23769, 23779, - 23788, 23797, 23806, 23815, 23824, 23833, 23842, 23851, 23859, 23868, 23876, 23884, 23893, 23901, 23909, 23917, - 23925, 23933, 23941, 23949, 23956, 23964, 23972, 23979, 23986, 23994, 24001, 24008, 24016, 24023, 24030, 24037], - [24044, 24058, 24071, 24085, 24098, 24111, 24124, 24136, 24149, 24161, 24173, 24185, 24197, 24208, 24220, 24231, - 24242, 24253, 24264, 24275, 24286, 24296, 24307, 24317, 24327, 24337, 24347, 24357, 24367, 24376, 24386, 24395, - 24405, 24414, 24423, 24432, 24441, 24450, 24458, 24467, 24476, 24484, 24493, 24501, 24509, 24517, 24526, 24534, - 24542, 24550, 24557, 24565, 24573, 24580, 24588, 24596, 24603, 24610, 24618, 24625, 24632, 24639, 24646, 24653], - [24660, 24674, 24688, 24701, 24714, 24727, 24740, 24753, 24765, 24777, 24790, 24801, 24813, 24825, 24836, 24848, - 24859, 24870, 24881, 24892, 24902, 24913, 24923, 24933, 24944, 24954, 24964, 24973, 24983, 24993, 25002, 25012, - 25021, 25030, 25039, 25048, 25057, 25066, 25075, 25084, 25092, 25101, 25109, 25117, 25126, 25134, 25142, 25150, - 25158, 25166, 25174, 25182, 25189, 25197, 25205, 25212, 25219, 25227, 25234, 25241, 25249, 25256, 25263, 25270], - [25277, 25291, 25304, 25318, 25331, 25344, 25357, 25369, 25382, 25394, 25406, 25418, 25430, 25441, 25453, 25464, - 25475, 25486, 25497, 25508, 25519, 25529, 25540, 25550, 25560, 25570, 25580, 25590, 25600, 25609, 25619, 25628, - 25638, 25647, 25656, 25665, 25674, 25683, 25691, 25700, 25709, 25717, 25726, 25734, 25742, 25750, 25759, 25767, - 25775, 25783, 25790, 25798, 25806, 25813, 25821, 25829, 25836, 25843, 25851, 25858, 25865, 25872, 25879, 25886], - [25893, 25907, 25921, 25934, 25947, 25960, 25973, 25986, 25998, 26010, 26023, 26034, 26046, 26058, 26069, 26081, - 26092, 26103, 26114, 26125, 26135, 26146, 26156, 26166, 26177, 26187, 26197, 26206, 26216, 26226, 26235, 26245, - 26254, 26263, 26272, 26281, 26290, 26299, 26308, 26317, 26325, 26334, 26342, 26351, 26359, 26367, 26375, 26383, - 26391, 26399, 26407, 26415, 26422, 26430, 26438, 26445, 26453, 26460, 26467, 26474, 26482, 26489, 26496, 26503], - [26510, 26524, 26537, 26551, 26564, 26577, 26590, 26602, 26615, 26627, 26639, 26651, 26663, 26674, 26686, 26697, - 26708, 26719, 26730, 26741, 26752, 26762, 26773, 26783, 26793, 26803, 26813, 26823, 26833, 26842, 26852, 26861, - 26871, 26880, 26889, 26898, 26907, 26916, 26924, 26933, 26942, 26950, 26959, 26967, 26975, 26983, 26992, 27000, - 27008, 27016, 27023, 27031, 27039, 27046, 27054, 27062, 27069, 27076, 27084, 27091, 27098, 27105, 27112, 27119], - [27126, 27140, 27154, 27167, 27180, 27193, 27206, 27219, 27231, 27243, 27256, 27267, 27279, 27291, 27302, 27314, - 27325, 27336, 27347, 27358, 27368, 27379, 27389, 27399, 27410, 27420, 27430, 27439, 27449, 27459, 27468, 27478, - 27487, 27496, 27505, 27514, 27523, 27532, 27541, 27550, 27558, 27567, 27575, 27584, 27592, 27600, 27608, 27616, - 27624, 27632, 27640, 27648, 27655, 27663, 27671, 27678, 27686, 27693, 27700, 27707, 27715, 27722, 27729, 27736], - [27743, 27757, 27770, 27784, 27797, 27810, 27823, 27835, 27848, 27860, 27872, 27884, 27896, 27907, 27919, 27930, - 27941, 27952, 27963, 27974, 27985, 27995, 28006, 28016, 28026, 28036, 28046, 28056, 28066, 28075, 28085, 28094, - 28104, 28113, 28122, 28131, 28140, 28149, 28157, 28166, 28175, 28183, 28192, 28200, 28208, 28217, 28225, 28233, - 28241, 28249, 28256, 28264, 28272, 28280, 28287, 28295, 28302, 28309, 28317, 28324, 28331, 28338, 28345, 28352], - [28359, 28373, 28387, 28400, 28413, 28426, 28439, 28452, 28464, 28476, 28489, 28501, 28512, 28524, 28535, 28547, - 28558, 28569, 28580, 28591, 28601, 28612, 28622, 28633, 28643, 28653, 28663, 28672, 28682, 28692, 28701, 28711, - 28720, 28729, 28738, 28747, 28756, 28765, 28774, 28783, 28791, 28800, 28808, 28817, 28825, 28833, 28841, 28849, - 28857, 28865, 28873, 28881, 28888, 28896, 28904, 28911, 28919, 28926, 28933, 28941, 28948, 28955, 28962, 28969], - [28976, 28990, 29003, 29017, 29030, 29043, 29056, 29068, 29081, 29093, 29105, 29117, 29129, 29140, 29152, 29163, - 29174, 29185, 29196, 29207, 29218, 29228, 29239, 29249, 29259, 29269, 29279, 29289, 29299, 29308, 29318, 29327, - 29337, 29346, 29355, 29364, 29373, 29382, 29390, 29399, 29408, 29416, 29425, 29433, 29441, 29450, 29458, 29466, - 29474, 29482, 29489, 29497, 29505, 29513, 29520, 29528, 29535, 29542, 29550, 29557, 29564, 29571, 29578, 29585], - [29592, 29606, 29620, 29633, 29646, 29659, 29672, 29685, 29697, 29709, 29722, 29734, 29745, 29757, 29768, 29780, - 29791, 29802, 29813, 29824, 29834, 29845, 29855, 29866, 29876, 29886, 29896, 29906, 29915, 29925, 29934, 29944, - 29953, 29962, 29971, 29980, 29989, 29998, 30007, 30016, 30024, 30033, 30041, 30050, 30058, 30066, 30074, 30082, - 30090, 30098, 30106, 30114, 30121, 30129, 30137, 30144, 30152, 30159, 30166, 30174, 30181, 30188, 30195, 30202], - [30209, 30223, 30236, 30250, 30263, 30276, 30289, 30301, 30314, 30326, 30338, 30350, 30362, 30373, 30385, 30396, - 30407, 30418, 30429, 30440, 30451, 30461, 30472, 30482, 30492, 30502, 30512, 30522, 30532, 30541, 30551, 30560, - 30570, 30579, 30588, 30597, 30606, 30615, 30624, 30632, 30641, 30649, 30658, 30666, 30674, 30683, 30691, 30699, - 30707, 30715, 30722, 30730, 30738, 30746, 30753, 30761, 30768, 30775, 30783, 30790, 30797, 30804, 30811, 30818], - [30825, 30839, 30853, 30866, 30879, 30892, 30905, 30918, 30930, 30943, 30955, 30967, 30978, 30990, 31001, 31013, - 31024, 31035, 31046, 31057, 31067, 31078, 31088, 31099, 31109, 31119, 31129, 31139, 31148, 31158, 31167, 31177, - 31186, 31195, 31204, 31213, 31222, 31231, 31240, 31249, 31257, 31266, 31274, 31283, 31291, 31299, 31307, 31315, - 31323, 31331, 31339, 31347, 31354, 31362, 31370, 31377, 31385, 31392, 31399, 31407, 31414, 31421, 31428, 31435], - [31442, 31456, 31469, 31483, 31496, 31509, 31522, 31534, 31547, 31559, 31571, 31583, 31595, 31606, 31618, 31629, - 31640, 31652, 31662, 31673, 31684, 31694, 31705, 31715, 31725, 31735, 31745, 31755, 31765, 31774, 31784, 31793, - 31803, 31812, 31821, 31830, 31839, 31848, 31857, 31865, 31874, 31882, 31891, 31899, 31907, 31916, 31924, 31932, - 31940, 31948, 31955, 31963, 31971, 31979, 31986, 31994, 32001, 32008, 32016, 32023, 32030, 32037, 32044, 32052], - [32058, 32072, 32086, 32099, 32112, 32125, 32138, 32151, 32163, 32176, 32188, 32200, 32211, 32223, 32234, 32246, - 32257, 32268, 32279, 32290, 32300, 32311, 32321, 32332, 32342, 32352, 32362, 32372, 32381, 32391, 32400, 32410, - 32419, 32428, 32437, 32446, 32455, 32464, 32473, 32482, 32490, 32499, 32507, 32516, 32524, 32532, 32540, 32548, - 32556, 32564, 32572, 32580, 32587, 32595, 32603, 32610, 32618, 32625, 32632, 32640, 32647, 32654, 32661, 32668], - [32675, 32689, 32702, 32716, 32729, 32742, 32755, 32767, 32780, 32792, 32804, 32816, 32828, 32839, 32851, 32862, - 32873, 32885, 32895, 32906, 32917, 32927, 32938, 32948, 32958, 32968, 32978, 32988, 32998, 33007, 33017, 33026, - 33036, 33045, 33054, 33063, 33072, 33081, 33090, 33098, 33107, 33115, 33124, 33132, 33140, 33149, 33157, 33165, - 33173, 33181, 33188, 33196, 33204, 33212, 33219, 33227, 33234, 33241, 33249, 33256, 33263, 33270, 33278, 33285], - [33292, 33305, 33319, 33332, 33345, 33358, 33371, 33384, 33396, 33409, 33421, 33433, 33444, 33456, 33467, 33479, - 33490, 33501, 33512, 33523, 33533, 33544, 33554, 33565, 33575, 33585, 33595, 33605, 33614, 33624, 33633, 33643, - 33652, 33661, 33670, 33680, 33688, 33697, 33706, 33715, 33723, 33732, 33740, 33749, 33757, 33765, 33773, 33781, - 33789, 33797, 33805, 33813, 33820, 33828, 33836, 33843, 33851, 33858, 33865, 33873, 33880, 33887, 33894, 33901], - [33908, 33922, 33935, 33949, 33962, 33975, 33988, 34000, 34013, 34025, 34037, 34049, 34061, 34072, 34084, 34095, - 34106, 34118, 34128, 34139, 34150, 34160, 34171, 34181, 34191, 34201, 34211, 34221, 34231, 34240, 34250, 34259, - 34269, 34278, 34287, 34296, 34305, 34314, 34323, 34331, 34340, 34348, 34357, 34365, 34373, 34382, 34390, 34398, - 34406, 34414, 34422, 34429, 34437, 34445, 34452, 34460, 34467, 34475, 34482, 34489, 34496, 34503, 34511, 34518], - [34525, 34538, 34552, 34565, 34578, 34591, 34604, 34617, 34629, 34642, 34654, 34666, 34677, 34689, 34700, 34712, - 34723, 34734, 34745, 34756, 34766, 34777, 34787, 34798, 34808, 34818, 34828, 34838, 34847, 34857, 34866, 34876, - 34885, 34894, 34904, 34913, 34921, 34930, 34939, 34948, 34956, 34965, 34973, 34982, 34990, 34998, 35006, 35014, - 35022, 35030, 35038, 35046, 35053, 35061, 35069, 35076, 35084, 35091, 35098, 35106, 35113, 35120, 35127, 35134], - [35141, 35155, 35168, 35182, 35195, 35208, 35221, 35233, 35246, 35258, 35270, 35282, 35294, 35306, 35317, 35328, - 35340, 35351, 35361, 35372, 35383, 35393, 35404, 35414, 35424, 35434, 35444, 35454, 35464, 35473, 35483, 35492, - 35502, 35511, 35520, 35529, 35538, 35547, 35556, 35564, 35573, 35581, 35590, 35598, 35606, 35615, 35623, 35631, - 35639, 35647, 35655, 35662, 35670, 35678, 35685, 35693, 35700, 35708, 35715, 35722, 35729, 35736, 35744, 35751], - [35758, 35771, 35785, 35798, 35811, 35824, 35837, 35850, 35862, 35875, 35887, 35899, 35910, 35922, 35934, 35945, - 35956, 35967, 35978, 35989, 35999, 36010, 36020, 36031, 36041, 36051, 36061, 36071, 36080, 36090, 36099, 36109, - 36118, 36127, 36137, 36146, 36154, 36163, 36172, 36181, 36189, 36198, 36206, 36215, 36223, 36231, 36239, 36247, - 36255, 36263, 36271, 36279, 36287, 36294, 36302, 36309, 36317, 36324, 36331, 36339, 36346, 36353, 36360, 36367], - [36374, 36388, 36401, 36415, 36428, 36441, 36454, 36466, 36479, 36491, 36503, 36515, 36527, 36539, 36550, 36561, - 36573, 36584, 36594, 36605, 36616, 36626, 36637, 36647, 36657, 36667, 36677, 36687, 36697, 36706, 36716, 36725, - 36735, 36744, 36753, 36762, 36771, 36780, 36789, 36797, 36806, 36814, 36823, 36831, 36839, 36848, 36856, 36864, - 36872, 36880, 36888, 36895, 36903, 36911, 36918, 36926, 36933, 36941, 36948, 36955, 36962, 36969, 36977, 36984], - [36991, 37004, 37018, 37031, 37044, 37057, 37070, 37083, 37095, 37108, 37120, 37132, 37143, 37155, 37167, 37178, - 37189, 37200, 37211, 37222, 37232, 37243, 37253, 37264, 37274, 37284, 37294, 37304, 37313, 37323, 37332, 37342, - 37351, 37360, 37370, 37379, 37388, 37396, 37405, 37414, 37422, 37431, 37439, 37448, 37456, 37464, 37472, 37480, - 37488, 37496, 37504, 37512, 37520, 37527, 37535, 37542, 37550, 37557, 37564, 37572, 37579, 37586, 37593, 37600], - [37607, 37621, 37634, 37648, 37661, 37674, 37687, 37699, 37712, 37724, 37736, 37748, 37760, 37772, 37783, 37794, - 37806, 37817, 37828, 37838, 37849, 37859, 37870, 37880, 37890, 37900, 37910, 37920, 37930, 37939, 37949, 37958, - 37968, 37977, 37986, 37995, 38004, 38013, 38022, 38030, 38039, 38047, 38056, 38064, 38072, 38081, 38089, 38097, - 38105, 38113, 38121, 38128, 38136, 38144, 38151, 38159, 38166, 38174, 38181, 38188, 38195, 38202, 38210, 38217], - [38224, 38237, 38251, 38264, 38278, 38290, 38303, 38316, 38328, 38341, 38353, 38365, 38376, 38388, 38400, 38411, - 38422, 38433, 38444, 38455, 38465, 38476, 38486, 38497, 38507, 38517, 38527, 38537, 38546, 38556, 38565, 38575, - 38584, 38593, 38603, 38612, 38621, 38629, 38638, 38647, 38655, 38664, 38672, 38681, 38689, 38697, 38705, 38713, - 38721, 38729, 38737, 38745, 38753, 38760, 38768, 38775, 38783, 38790, 38797, 38805, 38812, 38819, 38826, 38833], - [38840, 38854, 38867, 38881, 38894, 38907, 38920, 38932, 38945, 38957, 38969, 38981, 38993, 39005, 39016, 39027, - 39039, 39050, 39061, 39071, 39082, 39092, 39103, 39113, 39123, 39133, 39143, 39153, 39163, 39172, 39182, 39191, - 39201, 39210, 39219, 39228, 39237, 39246, 39255, 39263, 39272, 39280, 39289, 39297, 39305, 39314, 39322, 39330, - 39338, 39346, 39354, 39361, 39369, 39377, 39384, 39392, 39399, 39407, 39414, 39421, 39428, 39436, 39443, 39450], + [ + 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, 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, + ], + [ + 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, + 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 977, 977, + 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, + 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, + ], + [ + 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, + 1233, 1233, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, + 1431, 1431, 1431, 1431, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, + 1594, 1594, 1594, 1594, 1594, 1594, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, + 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, + ], + [ + 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1954, 1954, 1954, 1954, 1954, 1954, + 1954, 1954, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2133, 2133, 2133, 2133, + 2133, 2133, 2133, 2133, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2281, 2281, + 2281, 2281, 2281, 2281, 2281, 2281, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, + 2409, 2409, 2409, 2409, 2409, 2409, 2409, 2409, + ], + [ + 2466, 2466, 2466, 2466, 2520, 2520, 2520, 2520, 2571, 2571, 2571, 2571, 2619, 2619, + 2619, 2619, 2665, 2665, 2665, 2665, 2708, 2708, 2708, 2708, 2749, 2749, 2749, 2749, + 2789, 2789, 2789, 2789, 2827, 2827, 2827, 2827, 2863, 2863, 2863, 2863, 2898, 2898, + 2898, 2898, 2931, 2931, 2931, 2931, 2964, 2964, 2964, 2964, 2995, 2995, 2995, 2995, + 3025, 3025, 3025, 3025, 3054, 3054, 3054, 3054, + ], + [ + 3083, 3083, 3110, 3110, 3136, 3136, 3162, 3162, 3187, 3187, 3212, 3212, 3235, 3235, + 3259, 3259, 3281, 3281, 3303, 3303, 3324, 3324, 3345, 3345, 3366, 3366, 3386, 3386, + 3405, 3405, 3424, 3424, 3443, 3443, 3462, 3462, 3479, 3479, 3497, 3497, 3514, 3514, + 3531, 3531, 3548, 3548, 3564, 3564, 3580, 3580, 3596, 3596, 3612, 3612, 3627, 3627, + 3642, 3642, 3656, 3656, 3671, 3671, 3685, 3685, + ], + [ + 3699, 3713, 3726, 3740, 3753, 3766, 3779, 3791, 3804, 3816, 3828, 3840, 3852, 3864, + 3875, 3886, 3898, 3909, 3919, 3930, 3941, 3951, 3962, 3972, 3982, 3992, 4002, 4012, + 4022, 4031, 4041, 4050, 4060, 4069, 4078, 4087, 4096, 4105, 4114, 4122, 4131, 4139, + 4148, 4156, 4164, 4173, 4181, 4189, 4197, 4205, 4213, 4220, 4228, 4236, 4243, 4251, + 4258, 4266, 4273, 4280, 4287, 4294, 4302, 4309, + ], + [ + 4316, 4329, 4343, 4356, 4369, 4382, 4395, 4408, 4420, 4433, 4445, 4457, 4468, 4480, + 4492, 4503, 4514, 4525, 4536, 4547, 4557, 4568, 4578, 4589, 4599, 4609, 4619, 4629, + 4638, 4648, 4657, 4667, 4676, 4685, 4695, 4704, 4713, 4721, 4730, 4739, 4747, 4756, + 4764, 4773, 4781, 4789, 4797, 4805, 4813, 4821, 4829, 4837, 4845, 4852, 4860, 4867, + 4875, 4882, 4889, 4897, 4904, 4911, 4918, 4925, + ], + [ + 4932, 4946, 4959, 4973, 4986, 4999, 5012, 5024, 5037, 5049, 5061, 5073, 5085, 5097, + 5108, 5119, 5131, 5142, 5153, 5163, 5174, 5184, 5195, 5205, 5215, 5225, 5235, 5245, + 5255, 5264, 5274, 5283, 5293, 5302, 5311, 5320, 5329, 5338, 5347, 5355, 5364, 5372, + 5381, 5389, 5397, 5406, 5414, 5422, 5430, 5438, 5446, 5453, 5461, 5469, 5476, 5484, + 5491, 5499, 5506, 5513, 5520, 5527, 5535, 5542, + ], + [ + 5549, 5562, 5576, 5589, 5603, 5615, 5628, 5641, 5653, 5666, 5678, 5690, 5701, 5713, + 5725, 5736, 5747, 5758, 5769, 5780, 5790, 5801, 5811, 5822, 5832, 5842, 5852, 5862, + 5871, 5881, 5890, 5900, 5909, 5918, 5928, 5937, 5946, 5954, 5963, 5972, 5980, 5989, + 5997, 6006, 6014, 6022, 6030, 6038, 6046, 6054, 6062, 6070, 6078, 6085, 6093, 6100, + 6108, 6115, 6122, 6130, 6137, 6144, 6151, 6158, + ], + [ + 6165, 6179, 6192, 6206, 6219, 6232, 6245, 6257, 6270, 6282, 6294, 6306, 6318, 6330, + 6341, 6352, 6364, 6375, 6386, 6396, 6407, 6417, 6428, 6438, 6448, 6458, 6468, 6478, + 6488, 6497, 6507, 6516, 6526, 6535, 6544, 6553, 6562, 6571, 6580, 6588, 6597, 6605, + 6614, 6622, 6630, 6639, 6647, 6655, 6663, 6671, 6679, 6686, 6694, 6702, 6709, 6717, + 6724, 6732, 6739, 6746, 6753, 6761, 6768, 6775, + ], + [ + 6782, 6795, 6809, 6822, 6836, 6849, 6861, 6874, 6886, 6899, 6911, 6923, 6934, 6946, + 6958, 6969, 6980, 6991, 7002, 7013, 7023, 7034, 7044, 7055, 7065, 7075, 7085, 7095, + 7104, 7114, 7124, 7133, 7142, 7151, 7161, 7170, 7179, 7187, 7196, 7205, 7213, 7222, + 7230, 7239, 7247, 7255, 7263, 7271, 7279, 7287, 7295, 7303, 7311, 7318, 7326, 7333, + 7341, 7348, 7355, 7363, 7370, 7377, 7384, 7391, + ], + [ + 7398, 7412, 7425, 7439, 7452, 7465, 7478, 7490, 7503, 7515, 7527, 7539, 7551, 7563, + 7574, 7585, 7597, 7608, 7619, 7629, 7640, 7651, 7661, 7671, 7681, 7691, 7701, 7711, + 7721, 7731, 7740, 7749, 7759, 7768, 7777, 7786, 7795, 7804, 7813, 7821, 7830, 7838, + 7847, 7855, 7864, 7872, 7880, 7888, 7896, 7904, 7912, 7919, 7927, 7935, 7942, 7950, + 7957, 7965, 7972, 7979, 7986, 7994, 8001, 8008, + ], + [ + 8015, 8028, 8042, 8055, 8069, 8082, 8094, 8107, 8119, 8132, 8144, 8156, 8167, 8179, + 8191, 8202, 8213, 8224, 8235, 8246, 8256, 8267, 8277, 8288, 8298, 8308, 8318, 8328, + 8337, 8347, 8357, 8366, 8375, 8384, 8394, 8403, 8412, 8420, 8429, 8438, 8446, 8455, + 8463, 8472, 8480, 8488, 8496, 8504, 8512, 8520, 8528, 8536, 8544, 8551, 8559, 8566, + 8574, 8581, 8588, 8596, 8603, 8610, 8617, 8624, + ], + [ + 8631, 8645, 8659, 8672, 8685, 8698, 8711, 8723, 8736, 8748, 8760, 8772, 8784, 8796, + 8807, 8818, 8830, 8841, 8852, 8862, 8873, 8884, 8894, 8904, 8914, 8924, 8934, 8944, + 8954, 8964, 8973, 8982, 8992, 9001, 9010, 9019, 9028, 9037, 9046, 9054, 9063, 9071, + 9080, 9088, 9097, 9105, 9113, 9121, 9129, 9137, 9145, 9152, 9160, 9168, 9175, 9183, + 9190, 9198, 9205, 9212, 9219, 9227, 9234, 9241, + ], + [ + 9248, 9261, 9275, 9288, 9302, 9315, 9327, 9340, 9352, 9365, 9377, 9389, 9400, 9412, + 9424, 9435, 9446, 9457, 9468, 9479, 9490, 9500, 9510, 9521, 9531, 9541, 9551, 9561, + 9570, 9580, 9590, 9599, 9608, 9617, 9627, 9636, 9645, 9653, 9662, 9671, 9679, 9688, + 9696, 9705, 9713, 9721, 9729, 9737, 9745, 9753, 9761, 9769, 9777, 9784, 9792, 9799, + 9807, 9814, 9821, 9829, 9836, 9843, 9850, 9857, + ], + [ + 9864, 9878, 9892, 9905, 9918, 9931, 9944, 9956, 9969, 9981, 9993, 10005, 10017, 10029, + 10040, 10051, 10063, 10074, 10085, 10095, 10106, 10117, 10127, 10137, 10147, 10157, + 10167, 10177, 10187, 10197, 10206, 10215, 10225, 10234, 10243, 10252, 10261, 10270, + 10279, 10287, 10296, 10304, 10313, 10321, 10330, 10338, 10346, 10354, 10362, 10370, + 10378, 10385, 10393, 10401, 10408, 10416, 10423, 10431, 10438, 10445, 10452, 10460, + 10467, 10474, + ], + [ + 10481, 10494, 10508, 10521, 10535, 10548, 10560, 10573, 10585, 10598, 10610, 10622, + 10634, 10645, 10657, 10668, 10679, 10690, 10701, 10712, 10723, 10733, 10743, 10754, + 10764, 10774, 10784, 10794, 10803, 10813, 10823, 10832, 10841, 10851, 10860, 10869, + 10878, 10886, 10895, 10904, 10912, 10921, 10929, 10938, 10946, 10954, 10962, 10970, + 10978, 10986, 10994, 11002, 11010, 11017, 11025, 11032, 11040, 11047, 11054, 11062, + 11069, 11076, 11083, 11090, + ], + [ + 11097, 11111, 11125, 11138, 11151, 11164, 11177, 11189, 11202, 11214, 11226, 11238, + 11250, 11262, 11273, 11284, 11296, 11307, 11318, 11328, 11339, 11350, 11360, 11370, + 11380, 11390, 11400, 11410, 11420, 11430, 11439, 11448, 11458, 11467, 11476, 11485, + 11494, 11503, 11512, 11520, 11529, 11538, 11546, 11554, 11563, 11571, 11579, 11587, + 11595, 11603, 11611, 11618, 11626, 11634, 11641, 11649, 11656, 11664, 11671, 11678, + 11685, 11693, 11700, 11707, + ], + [ + 11714, 11727, 11741, 11754, 11768, 11781, 11793, 11806, 11818, 11831, 11843, 11855, + 11867, 11878, 11890, 11901, 11912, 11923, 11934, 11945, 11956, 11966, 11976, 11987, + 11997, 12007, 12017, 12027, 12036, 12046, 12056, 12065, 12074, 12084, 12093, 12102, + 12111, 12119, 12128, 12137, 12146, 12154, 12162, 12171, 12179, 12187, 12195, 12203, + 12211, 12219, 12227, 12235, 12243, 12250, 12258, 12265, 12273, 12280, 12287, 12295, + 12302, 12309, 12316, 12323, + ], + [ + 12330, 12344, 12358, 12371, 12384, 12397, 12410, 12423, 12435, 12447, 12459, 12471, + 12483, 12495, 12506, 12517, 12529, 12540, 12551, 12561, 12572, 12583, 12593, 12603, + 12613, 12623, 12633, 12643, 12653, 12663, 12672, 12682, 12691, 12700, 12709, 12718, + 12727, 12736, 12745, 12753, 12762, 12771, 12779, 12787, 12796, 12804, 12812, 12820, + 12828, 12836, 12844, 12851, 12859, 12867, 12874, 12882, 12889, 12897, 12904, 12911, + 12918, 12926, 12933, 12940, + ], + [ + 12947, 12960, 12974, 12987, 13001, 13014, 13026, 13039, 13051, 13064, 13076, 13088, + 13100, 13111, 13123, 13134, 13145, 13156, 13167, 13178, 13189, 13199, 13209, 13220, + 13230, 13240, 13250, 13260, 13269, 13279, 13289, 13298, 13307, 13317, 13326, 13335, + 13344, 13352, 13361, 13370, 13379, 13387, 13395, 13404, 13412, 13420, 13428, 13436, + 13444, 13452, 13460, 13468, 13476, 13483, 13491, 13498, 13506, 13513, 13521, 13528, + 13535, 13542, 13549, 13556, + ], + [ + 13563, 13577, 13591, 13604, 13617, 13630, 13643, 13656, 13668, 13680, 13692, 13704, + 13716, 13728, 13739, 13750, 13762, 13773, 13784, 13794, 13805, 13816, 13826, 13836, + 13846, 13857, 13866, 13876, 13886, 13896, 13905, 13915, 13924, 13933, 13942, 13951, + 13960, 13969, 13978, 13986, 13995, 14004, 14012, 14020, 14029, 14037, 14045, 14053, + 14061, 14069, 14077, 14084, 14092, 14100, 14107, 14115, 14122, 14130, 14137, 14144, + 14151, 14159, 14166, 14173, + ], + [ + 14180, 14194, 14207, 14220, 14234, 14247, 14259, 14272, 14284, 14297, 14309, 14321, + 14333, 14344, 14356, 14367, 14378, 14389, 14400, 14411, 14422, 14432, 14443, 14453, + 14463, 14473, 14483, 14493, 14502, 14512, 14522, 14531, 14540, 14550, 14559, 14568, + 14577, 14586, 14594, 14603, 14612, 14620, 14628, 14637, 14645, 14653, 14661, 14669, + 14677, 14685, 14693, 14701, 14709, 14716, 14724, 14731, 14739, 14746, 14754, 14761, + 14768, 14775, 14782, 14789, + ], + [ + 14796, 14810, 14824, 14837, 14850, 14863, 14876, 14889, 14901, 14913, 14925, 14937, + 14949, 14961, 14972, 14984, 14995, 15006, 15017, 15027, 15038, 15049, 15059, 15069, + 15079, 15090, 15099, 15109, 15119, 15129, 15138, 15148, 15157, 15166, 15175, 15184, + 15193, 15202, 15211, 15219, 15228, 15237, 15245, 15253, 15262, 15270, 15278, 15286, + 15294, 15302, 15310, 15317, 15325, 15333, 15340, 15348, 15355, 15363, 15370, 15377, + 15384, 15392, 15399, 15406, + ], + [ + 15413, 15427, 15440, 15453, 15467, 15480, 15492, 15505, 15517, 15530, 15542, 15554, + 15566, 15577, 15589, 15600, 15611, 15622, 15633, 15644, 15655, 15665, 15676, 15686, + 15696, 15706, 15716, 15726, 15736, 15745, 15755, 15764, 15773, 15783, 15792, 15801, + 15810, 15819, 15827, 15836, 15845, 15853, 15862, 15870, 15878, 15886, 15894, 15903, + 15910, 15918, 15926, 15934, 15942, 15949, 15957, 15964, 15972, 15979, 15987, 15994, + 16001, 16008, 16015, 16022, + ], + [ + 16029, 16043, 16057, 16070, 16083, 16096, 16109, 16122, 16134, 16146, 16158, 16170, + 16182, 16194, 16205, 16217, 16228, 16239, 16250, 16260, 16271, 16282, 16292, 16302, + 16312, 16323, 16332, 16342, 16352, 16362, 16371, 16381, 16390, 16399, 16408, 16417, + 16426, 16435, 16444, 16452, 16461, 16470, 16478, 16486, 16495, 16503, 16511, 16519, + 16527, 16535, 16543, 16550, 16558, 16566, 16573, 16581, 16588, 16596, 16603, 16610, + 16618, 16625, 16632, 16639, + ], + [ + 16646, 16660, 16673, 16686, 16700, 16713, 16725, 16738, 16751, 16763, 16775, 16787, + 16799, 16810, 16822, 16833, 16844, 16855, 16866, 16877, 16888, 16898, 16909, 16919, + 16929, 16939, 16949, 16959, 16969, 16978, 16988, 16997, 17006, 17016, 17025, 17034, + 17043, 17052, 17060, 17069, 17078, 17086, 17095, 17103, 17111, 17119, 17127, 17136, + 17143, 17151, 17159, 17167, 17175, 17182, 17190, 17197, 17205, 17212, 17220, 17227, + 17234, 17241, 17248, 17255, + ], + [ + 17262, 17276, 17290, 17303, 17316, 17329, 17342, 17355, 17367, 17379, 17391, 17403, + 17415, 17427, 17438, 17450, 17461, 17472, 17483, 17493, 17504, 17515, 17525, 17535, + 17546, 17556, 17565, 17575, 17585, 17595, 17604, 17614, 17623, 17632, 17641, 17650, + 17659, 17668, 17677, 17685, 17694, 17703, 17711, 17719, 17728, 17736, 17744, 17752, + 17760, 17768, 17776, 17784, 17791, 17799, 17806, 17814, 17821, 17829, 17836, 17843, + 17851, 17858, 17865, 17872, + ], + [ + 17879, 17893, 17906, 17920, 17933, 17946, 17958, 17971, 17984, 17996, 18008, 18020, + 18032, 18043, 18055, 18066, 18077, 18088, 18099, 18110, 18121, 18131, 18142, 18152, + 18162, 18172, 18182, 18192, 18202, 18211, 18221, 18230, 18239, 18249, 18258, 18267, + 18276, 18285, 18293, 18302, 18311, 18319, 18328, 18336, 18344, 18352, 18360, 18369, + 18377, 18384, 18392, 18400, 18408, 18415, 18423, 18430, 18438, 18445, 18453, 18460, + 18467, 18474, 18481, 18488, + ], + [ + 18495, 18509, 18523, 18536, 18549, 18562, 18575, 18588, 18600, 18612, 18624, 18636, + 18648, 18660, 18671, 18683, 18694, 18705, 18716, 18726, 18737, 18748, 18758, 18768, + 18779, 18789, 18799, 18808, 18818, 18828, 18837, 18847, 18856, 18865, 18874, 18883, + 18892, 18901, 18910, 18919, 18927, 18936, 18944, 18952, 18961, 18969, 18977, 18985, + 18993, 19001, 19009, 19017, 19024, 19032, 19039, 19047, 19054, 19062, 19069, 19076, + 19084, 19091, 19098, 19105, + ], + [ + 19112, 19126, 19139, 19153, 19166, 19179, 19191, 19204, 19217, 19229, 19241, 19253, + 19265, 19276, 19288, 19299, 19310, 19321, 19332, 19343, 19354, 19364, 19375, 19385, + 19395, 19405, 19415, 19425, 19435, 19444, 19454, 19463, 19472, 19482, 19491, 19500, + 19509, 19518, 19526, 19535, 19544, 19552, 19561, 19569, 19577, 19585, 19594, 19602, + 19610, 19617, 19625, 19633, 19641, 19648, 19656, 19663, 19671, 19678, 19686, 19693, + 19700, 19707, 19714, 19721, + ], + [ + 19728, 19742, 19756, 19769, 19782, 19795, 19808, 19821, 19833, 19845, 19857, 19869, + 19881, 19893, 19904, 19916, 19927, 19938, 19949, 19960, 19970, 19981, 19991, 20001, + 20012, 20022, 20032, 20041, 20051, 20061, 20070, 20080, 20089, 20098, 20107, 20116, + 20125, 20134, 20143, 20152, 20160, 20169, 20177, 20185, 20194, 20202, 20210, 20218, + 20226, 20234, 20242, 20250, 20257, 20265, 20272, 20280, 20287, 20295, 20302, 20309, + 20317, 20324, 20331, 20338, + ], + [ + 20345, 20359, 20372, 20386, 20399, 20412, 20425, 20437, 20450, 20462, 20474, 20486, + 20498, 20509, 20521, 20532, 20543, 20554, 20565, 20576, 20587, 20597, 20608, 20618, + 20628, 20638, 20648, 20658, 20668, 20677, 20687, 20696, 20705, 20715, 20724, 20733, + 20742, 20751, 20759, 20768, 20777, 20785, 20794, 20802, 20810, 20818, 20827, 20835, + 20843, 20850, 20858, 20866, 20874, 20881, 20889, 20896, 20904, 20911, 20919, 20926, + 20933, 20940, 20947, 20954, + ], + [ + 20961, 20975, 20989, 21002, 21015, 21028, 21041, 21054, 21066, 21078, 21090, 21102, + 21114, 21126, 21137, 21149, 21160, 21171, 21182, 21193, 21203, 21214, 21224, 21234, + 21245, 21255, 21265, 21274, 21284, 21294, 21303, 21313, 21322, 21331, 21340, 21349, + 21358, 21367, 21376, 21385, 21393, 21402, 21410, 21418, 21427, 21435, 21443, 21451, + 21459, 21467, 21475, 21483, 21490, 21498, 21505, 21513, 21520, 21528, 21535, 21542, + 21550, 21557, 21564, 21571, + ], + [ + 21578, 21592, 21605, 21619, 21632, 21645, 21658, 21670, 21683, 21695, 21707, 21719, + 21731, 21742, 21754, 21765, 21776, 21787, 21798, 21809, 21820, 21830, 21841, 21851, + 21861, 21871, 21881, 21891, 21901, 21910, 21920, 21929, 21938, 21948, 21957, 21966, + 21975, 21984, 21992, 22001, 22010, 22018, 22027, 22035, 22043, 22051, 22060, 22068, + 22076, 22083, 22091, 22099, 22107, 22114, 22122, 22129, 22137, 22144, 22152, 22159, + 22166, 22173, 22180, 22187, + ], + [ + 22194, 22208, 22222, 22235, 22248, 22261, 22274, 22287, 22299, 22311, 22323, 22335, + 22347, 22359, 22370, 22382, 22393, 22404, 22415, 22426, 22436, 22447, 22457, 22467, + 22478, 22488, 22498, 22507, 22517, 22527, 22536, 22546, 22555, 22564, 22573, 22582, + 22591, 22600, 22609, 22618, 22626, 22635, 22643, 22651, 22660, 22668, 22676, 22684, + 22692, 22700, 22708, 22716, 22723, 22731, 22738, 22746, 22753, 22761, 22768, 22775, + 22783, 22790, 22797, 22804, + ], + [ + 22811, 22825, 22838, 22852, 22865, 22878, 22891, 22903, 22916, 22928, 22940, 22952, + 22964, 22975, 22987, 22998, 23009, 23020, 23031, 23042, 23053, 23063, 23074, 23084, + 23094, 23104, 23114, 23124, 23134, 23143, 23153, 23162, 23171, 23181, 23190, 23199, + 23208, 23217, 23225, 23234, 23243, 23251, 23260, 23268, 23276, 23284, 23293, 23301, + 23309, 23316, 23324, 23332, 23340, 23347, 23355, 23363, 23370, 23377, 23385, 23392, + 23399, 23406, 23413, 23420, + ], + [ + 23427, 23441, 23455, 23468, 23481, 23494, 23507, 23520, 23532, 23544, 23556, 23568, + 23580, 23592, 23603, 23615, 23626, 23637, 23648, 23659, 23669, 23680, 23690, 23700, + 23711, 23721, 23731, 23740, 23750, 23760, 23769, 23779, 23788, 23797, 23806, 23815, + 23824, 23833, 23842, 23851, 23859, 23868, 23876, 23884, 23893, 23901, 23909, 23917, + 23925, 23933, 23941, 23949, 23956, 23964, 23972, 23979, 23986, 23994, 24001, 24008, + 24016, 24023, 24030, 24037, + ], + [ + 24044, 24058, 24071, 24085, 24098, 24111, 24124, 24136, 24149, 24161, 24173, 24185, + 24197, 24208, 24220, 24231, 24242, 24253, 24264, 24275, 24286, 24296, 24307, 24317, + 24327, 24337, 24347, 24357, 24367, 24376, 24386, 24395, 24405, 24414, 24423, 24432, + 24441, 24450, 24458, 24467, 24476, 24484, 24493, 24501, 24509, 24517, 24526, 24534, + 24542, 24550, 24557, 24565, 24573, 24580, 24588, 24596, 24603, 24610, 24618, 24625, + 24632, 24639, 24646, 24653, + ], + [ + 24660, 24674, 24688, 24701, 24714, 24727, 24740, 24753, 24765, 24777, 24790, 24801, + 24813, 24825, 24836, 24848, 24859, 24870, 24881, 24892, 24902, 24913, 24923, 24933, + 24944, 24954, 24964, 24973, 24983, 24993, 25002, 25012, 25021, 25030, 25039, 25048, + 25057, 25066, 25075, 25084, 25092, 25101, 25109, 25117, 25126, 25134, 25142, 25150, + 25158, 25166, 25174, 25182, 25189, 25197, 25205, 25212, 25219, 25227, 25234, 25241, + 25249, 25256, 25263, 25270, + ], + [ + 25277, 25291, 25304, 25318, 25331, 25344, 25357, 25369, 25382, 25394, 25406, 25418, + 25430, 25441, 25453, 25464, 25475, 25486, 25497, 25508, 25519, 25529, 25540, 25550, + 25560, 25570, 25580, 25590, 25600, 25609, 25619, 25628, 25638, 25647, 25656, 25665, + 25674, 25683, 25691, 25700, 25709, 25717, 25726, 25734, 25742, 25750, 25759, 25767, + 25775, 25783, 25790, 25798, 25806, 25813, 25821, 25829, 25836, 25843, 25851, 25858, + 25865, 25872, 25879, 25886, + ], + [ + 25893, 25907, 25921, 25934, 25947, 25960, 25973, 25986, 25998, 26010, 26023, 26034, + 26046, 26058, 26069, 26081, 26092, 26103, 26114, 26125, 26135, 26146, 26156, 26166, + 26177, 26187, 26197, 26206, 26216, 26226, 26235, 26245, 26254, 26263, 26272, 26281, + 26290, 26299, 26308, 26317, 26325, 26334, 26342, 26351, 26359, 26367, 26375, 26383, + 26391, 26399, 26407, 26415, 26422, 26430, 26438, 26445, 26453, 26460, 26467, 26474, + 26482, 26489, 26496, 26503, + ], + [ + 26510, 26524, 26537, 26551, 26564, 26577, 26590, 26602, 26615, 26627, 26639, 26651, + 26663, 26674, 26686, 26697, 26708, 26719, 26730, 26741, 26752, 26762, 26773, 26783, + 26793, 26803, 26813, 26823, 26833, 26842, 26852, 26861, 26871, 26880, 26889, 26898, + 26907, 26916, 26924, 26933, 26942, 26950, 26959, 26967, 26975, 26983, 26992, 27000, + 27008, 27016, 27023, 27031, 27039, 27046, 27054, 27062, 27069, 27076, 27084, 27091, + 27098, 27105, 27112, 27119, + ], + [ + 27126, 27140, 27154, 27167, 27180, 27193, 27206, 27219, 27231, 27243, 27256, 27267, + 27279, 27291, 27302, 27314, 27325, 27336, 27347, 27358, 27368, 27379, 27389, 27399, + 27410, 27420, 27430, 27439, 27449, 27459, 27468, 27478, 27487, 27496, 27505, 27514, + 27523, 27532, 27541, 27550, 27558, 27567, 27575, 27584, 27592, 27600, 27608, 27616, + 27624, 27632, 27640, 27648, 27655, 27663, 27671, 27678, 27686, 27693, 27700, 27707, + 27715, 27722, 27729, 27736, + ], + [ + 27743, 27757, 27770, 27784, 27797, 27810, 27823, 27835, 27848, 27860, 27872, 27884, + 27896, 27907, 27919, 27930, 27941, 27952, 27963, 27974, 27985, 27995, 28006, 28016, + 28026, 28036, 28046, 28056, 28066, 28075, 28085, 28094, 28104, 28113, 28122, 28131, + 28140, 28149, 28157, 28166, 28175, 28183, 28192, 28200, 28208, 28217, 28225, 28233, + 28241, 28249, 28256, 28264, 28272, 28280, 28287, 28295, 28302, 28309, 28317, 28324, + 28331, 28338, 28345, 28352, + ], + [ + 28359, 28373, 28387, 28400, 28413, 28426, 28439, 28452, 28464, 28476, 28489, 28501, + 28512, 28524, 28535, 28547, 28558, 28569, 28580, 28591, 28601, 28612, 28622, 28633, + 28643, 28653, 28663, 28672, 28682, 28692, 28701, 28711, 28720, 28729, 28738, 28747, + 28756, 28765, 28774, 28783, 28791, 28800, 28808, 28817, 28825, 28833, 28841, 28849, + 28857, 28865, 28873, 28881, 28888, 28896, 28904, 28911, 28919, 28926, 28933, 28941, + 28948, 28955, 28962, 28969, + ], + [ + 28976, 28990, 29003, 29017, 29030, 29043, 29056, 29068, 29081, 29093, 29105, 29117, + 29129, 29140, 29152, 29163, 29174, 29185, 29196, 29207, 29218, 29228, 29239, 29249, + 29259, 29269, 29279, 29289, 29299, 29308, 29318, 29327, 29337, 29346, 29355, 29364, + 29373, 29382, 29390, 29399, 29408, 29416, 29425, 29433, 29441, 29450, 29458, 29466, + 29474, 29482, 29489, 29497, 29505, 29513, 29520, 29528, 29535, 29542, 29550, 29557, + 29564, 29571, 29578, 29585, + ], + [ + 29592, 29606, 29620, 29633, 29646, 29659, 29672, 29685, 29697, 29709, 29722, 29734, + 29745, 29757, 29768, 29780, 29791, 29802, 29813, 29824, 29834, 29845, 29855, 29866, + 29876, 29886, 29896, 29906, 29915, 29925, 29934, 29944, 29953, 29962, 29971, 29980, + 29989, 29998, 30007, 30016, 30024, 30033, 30041, 30050, 30058, 30066, 30074, 30082, + 30090, 30098, 30106, 30114, 30121, 30129, 30137, 30144, 30152, 30159, 30166, 30174, + 30181, 30188, 30195, 30202, + ], + [ + 30209, 30223, 30236, 30250, 30263, 30276, 30289, 30301, 30314, 30326, 30338, 30350, + 30362, 30373, 30385, 30396, 30407, 30418, 30429, 30440, 30451, 30461, 30472, 30482, + 30492, 30502, 30512, 30522, 30532, 30541, 30551, 30560, 30570, 30579, 30588, 30597, + 30606, 30615, 30624, 30632, 30641, 30649, 30658, 30666, 30674, 30683, 30691, 30699, + 30707, 30715, 30722, 30730, 30738, 30746, 30753, 30761, 30768, 30775, 30783, 30790, + 30797, 30804, 30811, 30818, + ], + [ + 30825, 30839, 30853, 30866, 30879, 30892, 30905, 30918, 30930, 30943, 30955, 30967, + 30978, 30990, 31001, 31013, 31024, 31035, 31046, 31057, 31067, 31078, 31088, 31099, + 31109, 31119, 31129, 31139, 31148, 31158, 31167, 31177, 31186, 31195, 31204, 31213, + 31222, 31231, 31240, 31249, 31257, 31266, 31274, 31283, 31291, 31299, 31307, 31315, + 31323, 31331, 31339, 31347, 31354, 31362, 31370, 31377, 31385, 31392, 31399, 31407, + 31414, 31421, 31428, 31435, + ], + [ + 31442, 31456, 31469, 31483, 31496, 31509, 31522, 31534, 31547, 31559, 31571, 31583, + 31595, 31606, 31618, 31629, 31640, 31652, 31662, 31673, 31684, 31694, 31705, 31715, + 31725, 31735, 31745, 31755, 31765, 31774, 31784, 31793, 31803, 31812, 31821, 31830, + 31839, 31848, 31857, 31865, 31874, 31882, 31891, 31899, 31907, 31916, 31924, 31932, + 31940, 31948, 31955, 31963, 31971, 31979, 31986, 31994, 32001, 32008, 32016, 32023, + 32030, 32037, 32044, 32052, + ], + [ + 32058, 32072, 32086, 32099, 32112, 32125, 32138, 32151, 32163, 32176, 32188, 32200, + 32211, 32223, 32234, 32246, 32257, 32268, 32279, 32290, 32300, 32311, 32321, 32332, + 32342, 32352, 32362, 32372, 32381, 32391, 32400, 32410, 32419, 32428, 32437, 32446, + 32455, 32464, 32473, 32482, 32490, 32499, 32507, 32516, 32524, 32532, 32540, 32548, + 32556, 32564, 32572, 32580, 32587, 32595, 32603, 32610, 32618, 32625, 32632, 32640, + 32647, 32654, 32661, 32668, + ], + [ + 32675, 32689, 32702, 32716, 32729, 32742, 32755, 32767, 32780, 32792, 32804, 32816, + 32828, 32839, 32851, 32862, 32873, 32885, 32895, 32906, 32917, 32927, 32938, 32948, + 32958, 32968, 32978, 32988, 32998, 33007, 33017, 33026, 33036, 33045, 33054, 33063, + 33072, 33081, 33090, 33098, 33107, 33115, 33124, 33132, 33140, 33149, 33157, 33165, + 33173, 33181, 33188, 33196, 33204, 33212, 33219, 33227, 33234, 33241, 33249, 33256, + 33263, 33270, 33278, 33285, + ], + [ + 33292, 33305, 33319, 33332, 33345, 33358, 33371, 33384, 33396, 33409, 33421, 33433, + 33444, 33456, 33467, 33479, 33490, 33501, 33512, 33523, 33533, 33544, 33554, 33565, + 33575, 33585, 33595, 33605, 33614, 33624, 33633, 33643, 33652, 33661, 33670, 33680, + 33688, 33697, 33706, 33715, 33723, 33732, 33740, 33749, 33757, 33765, 33773, 33781, + 33789, 33797, 33805, 33813, 33820, 33828, 33836, 33843, 33851, 33858, 33865, 33873, + 33880, 33887, 33894, 33901, + ], + [ + 33908, 33922, 33935, 33949, 33962, 33975, 33988, 34000, 34013, 34025, 34037, 34049, + 34061, 34072, 34084, 34095, 34106, 34118, 34128, 34139, 34150, 34160, 34171, 34181, + 34191, 34201, 34211, 34221, 34231, 34240, 34250, 34259, 34269, 34278, 34287, 34296, + 34305, 34314, 34323, 34331, 34340, 34348, 34357, 34365, 34373, 34382, 34390, 34398, + 34406, 34414, 34422, 34429, 34437, 34445, 34452, 34460, 34467, 34475, 34482, 34489, + 34496, 34503, 34511, 34518, + ], + [ + 34525, 34538, 34552, 34565, 34578, 34591, 34604, 34617, 34629, 34642, 34654, 34666, + 34677, 34689, 34700, 34712, 34723, 34734, 34745, 34756, 34766, 34777, 34787, 34798, + 34808, 34818, 34828, 34838, 34847, 34857, 34866, 34876, 34885, 34894, 34904, 34913, + 34921, 34930, 34939, 34948, 34956, 34965, 34973, 34982, 34990, 34998, 35006, 35014, + 35022, 35030, 35038, 35046, 35053, 35061, 35069, 35076, 35084, 35091, 35098, 35106, + 35113, 35120, 35127, 35134, + ], + [ + 35141, 35155, 35168, 35182, 35195, 35208, 35221, 35233, 35246, 35258, 35270, 35282, + 35294, 35306, 35317, 35328, 35340, 35351, 35361, 35372, 35383, 35393, 35404, 35414, + 35424, 35434, 35444, 35454, 35464, 35473, 35483, 35492, 35502, 35511, 35520, 35529, + 35538, 35547, 35556, 35564, 35573, 35581, 35590, 35598, 35606, 35615, 35623, 35631, + 35639, 35647, 35655, 35662, 35670, 35678, 35685, 35693, 35700, 35708, 35715, 35722, + 35729, 35736, 35744, 35751, + ], + [ + 35758, 35771, 35785, 35798, 35811, 35824, 35837, 35850, 35862, 35875, 35887, 35899, + 35910, 35922, 35934, 35945, 35956, 35967, 35978, 35989, 35999, 36010, 36020, 36031, + 36041, 36051, 36061, 36071, 36080, 36090, 36099, 36109, 36118, 36127, 36137, 36146, + 36154, 36163, 36172, 36181, 36189, 36198, 36206, 36215, 36223, 36231, 36239, 36247, + 36255, 36263, 36271, 36279, 36287, 36294, 36302, 36309, 36317, 36324, 36331, 36339, + 36346, 36353, 36360, 36367, + ], + [ + 36374, 36388, 36401, 36415, 36428, 36441, 36454, 36466, 36479, 36491, 36503, 36515, + 36527, 36539, 36550, 36561, 36573, 36584, 36594, 36605, 36616, 36626, 36637, 36647, + 36657, 36667, 36677, 36687, 36697, 36706, 36716, 36725, 36735, 36744, 36753, 36762, + 36771, 36780, 36789, 36797, 36806, 36814, 36823, 36831, 36839, 36848, 36856, 36864, + 36872, 36880, 36888, 36895, 36903, 36911, 36918, 36926, 36933, 36941, 36948, 36955, + 36962, 36969, 36977, 36984, + ], + [ + 36991, 37004, 37018, 37031, 37044, 37057, 37070, 37083, 37095, 37108, 37120, 37132, + 37143, 37155, 37167, 37178, 37189, 37200, 37211, 37222, 37232, 37243, 37253, 37264, + 37274, 37284, 37294, 37304, 37313, 37323, 37332, 37342, 37351, 37360, 37370, 37379, + 37388, 37396, 37405, 37414, 37422, 37431, 37439, 37448, 37456, 37464, 37472, 37480, + 37488, 37496, 37504, 37512, 37520, 37527, 37535, 37542, 37550, 37557, 37564, 37572, + 37579, 37586, 37593, 37600, + ], + [ + 37607, 37621, 37634, 37648, 37661, 37674, 37687, 37699, 37712, 37724, 37736, 37748, + 37760, 37772, 37783, 37794, 37806, 37817, 37828, 37838, 37849, 37859, 37870, 37880, + 37890, 37900, 37910, 37920, 37930, 37939, 37949, 37958, 37968, 37977, 37986, 37995, + 38004, 38013, 38022, 38030, 38039, 38047, 38056, 38064, 38072, 38081, 38089, 38097, + 38105, 38113, 38121, 38128, 38136, 38144, 38151, 38159, 38166, 38174, 38181, 38188, + 38195, 38202, 38210, 38217, + ], + [ + 38224, 38237, 38251, 38264, 38278, 38290, 38303, 38316, 38328, 38341, 38353, 38365, + 38376, 38388, 38400, 38411, 38422, 38433, 38444, 38455, 38465, 38476, 38486, 38497, + 38507, 38517, 38527, 38537, 38546, 38556, 38565, 38575, 38584, 38593, 38603, 38612, + 38621, 38629, 38638, 38647, 38655, 38664, 38672, 38681, 38689, 38697, 38705, 38713, + 38721, 38729, 38737, 38745, 38753, 38760, 38768, 38775, 38783, 38790, 38797, 38805, + 38812, 38819, 38826, 38833, + ], + [ + 38840, 38854, 38867, 38881, 38894, 38907, 38920, 38932, 38945, 38957, 38969, 38981, + 38993, 39005, 39016, 39027, 39039, 39050, 39061, 39071, 39082, 39092, 39103, 39113, + 39123, 39133, 39143, 39153, 39163, 39172, 39182, 39191, 39201, 39210, 39219, 39228, + 39237, 39246, 39255, 39263, 39272, 39280, 39289, 39297, 39305, 39314, 39322, 39330, + 39338, 39346, 39354, 39361, 39369, 39377, 39384, 39392, 39399, 39407, 39414, 39421, + 39428, 39436, 39443, 39450, + ], ]; /// Approximate `log10(numerator / denominator) * 2048` using a look-up table. @@ -1782,7 +2215,8 @@ mod approx { fn prints_negative_log10_times_2048_lookup_table() { for msb in 0..BITS { for i in 0..LOWER_BITS_BOUND { - let x = ((LOWER_BITS_BOUND + i) << (HIGHEST_BIT - LOWER_BITS)) >> (HIGHEST_BIT - msb); + let x = ((LOWER_BITS_BOUND + i) << (HIGHEST_BIT - LOWER_BITS)) + >> (HIGHEST_BIT - msb); let log10_times_2048 = ((x as f64).log10() * 2048.0).round() as u16; assert_eq!(log10_times_2048, LOG10_TIMES_2048[msb as usize][i as usize]); @@ -1790,7 +2224,7 @@ mod approx { print!("\t\t[{}, ", log10_times_2048); } else if i % LOWER_BITS_BOUND == LOWER_BITS_BOUND - 1 { println!("{}],", log10_times_2048); - } else if i % (LOWER_BITS_BOUND/4) == LOWER_BITS_BOUND/4 - 1 { + } else if i % (LOWER_BITS_BOUND / 4) == LOWER_BITS_BOUND / 4 - 1 { print!("{},\n\t\t\t", log10_times_2048); } else { print!("{}, ", log10_times_2048); @@ -1819,12 +2253,12 @@ mod bucketed_history { const BUCKET_START_POS: [u16; 33] = [ 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, + 13312, 14336, 15360, 15872, 16128, 16256, 16320, 16352, 16368, 16376, 16380, 16382, 16383, + 16384, ]; - 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; @@ -1842,8 +2276,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; @@ -1856,7 +2291,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; } @@ -1869,14 +2307,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 @@ -1920,7 +2360,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] } + } pub(super) 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. @@ -1971,8 +2413,7 @@ mod bucketed_history { impl> HistoricalMinMaxBuckets { #[inline] pub(super) fn calculate_success_probability_times_billion( - &self, params: &ProbabilisticScoringFeeParameters, amount_msat: u64, - capacity_msat: u64 + &self, params: &ProbabilisticScoringFeeParameters, amount_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. @@ -1982,11 +2423,17 @@ 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(amount_msat, capacity_msat); - if payment_pos >= POSITION_TICKS { return None; } + if payment_pos >= POSITION_TICKS { + return None; + } let mut total_valid_points_tracked = 0; - 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) + { total_valid_points_tracked += (*min_bucket as u64) * (*max_bucket as u64); } } @@ -2009,43 +2456,63 @@ mod bucketed_history { if self.min_liquidity_offset_history.buckets[0] != 0 { let mut highest_max_bucket_with_points = 0; // The highest max-bucket with any data let mut total_max_points = 0; // Total points in max-buckets to consider - for (max_idx, max_bucket) in self.max_liquidity_offset_history.buckets.iter().enumerate() { + for (max_idx, max_bucket) in + self.max_liquidity_offset_history.buckets.iter().enumerate() + { if *max_bucket >= BUCKET_FIXED_POINT_ONE { - 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); } total_max_points += *max_bucket as u64; } let max_bucket_end_pos = BUCKET_START_POS[32 - highest_max_bucket_with_points] - 1; if payment_pos < max_bucket_end_pos { - let (numerator, denominator) = success_probability(payment_pos as u64, 0, - max_bucket_end_pos as u64, POSITION_TICKS as u64 - 1, params, true); - let bucket_prob_times_billion = - (self.min_liquidity_offset_history.buckets[0] as u64) * total_max_points - * 1024 * 1024 * 1024 / total_valid_points_tracked; - cumulative_success_prob_times_billion += bucket_prob_times_billion * - numerator / denominator; + let (numerator, denominator) = success_probability( + payment_pos as u64, + 0, + max_bucket_end_pos as u64, + POSITION_TICKS as u64 - 1, + params, + true, + ); + let bucket_prob_times_billion = (self.min_liquidity_offset_history.buckets[0] + as u64) * total_max_points + * 1024 * 1024 * 1024 + / total_valid_points_tracked; + cumulative_success_prob_times_billion += + bucket_prob_times_billion * numerator / denominator; } } - for (min_idx, min_bucket) in self.min_liquidity_offset_history.buckets.iter().enumerate().skip(1) { + for (min_idx, min_bucket) in + self.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 self.max_liquidity_offset_history.buckets.iter().enumerate().take(32 - min_idx) { + for (max_idx, max_bucket) in + self.max_liquidity_offset_history.buckets.iter().enumerate().take(32 - min_idx) + { let max_bucket_end_pos = BUCKET_START_POS[32 - max_idx] - 1; // Note that this multiply can only barely not overflow - two 16 bit ints plus // 30 bits is 62 bits. - let bucket_prob_times_billion = (*min_bucket as u64) * (*max_bucket as u64) - * 1024 * 1024 * 1024 / total_valid_points_tracked; + let bucket_prob_times_billion = (*min_bucket as u64) + * (*max_bucket as u64) * 1024 + * 1024 * 1024 / total_valid_points_tracked; if payment_pos >= max_bucket_end_pos { // Success probability 0, the payment amount may be above the max liquidity break; } else if payment_pos < min_bucket_start_pos { cumulative_success_prob_times_billion += bucket_prob_times_billion; } else { - let (numerator, denominator) = success_probability(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_times_billion += bucket_prob_times_billion * - numerator / denominator; + let (numerator, denominator) = success_probability( + 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_times_billion += + bucket_prob_times_billion * numerator / denominator; } } } @@ -2054,9 +2521,14 @@ mod bucketed_history { } } } -use bucketed_history::{LegacyHistoricalBucketRangeTracker, HistoricalBucketRangeTracker, HistoricalMinMaxBuckets}; +use bucketed_history::{ + HistoricalBucketRangeTracker, HistoricalMinMaxBuckets, LegacyHistoricalBucketRangeTracker, +}; -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> { write_tlv_fields!(w, { @@ -2067,22 +2539,20 @@ 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 mut channel_liquidities = HashMap::new(); read_tlv_fields!(r, { (0, channel_liquidities, required), }); - Ok(Self { - decay_params, - network_graph, - logger, - channel_liquidities, - }) + Ok(Self { decay_params, network_graph, logger, channel_liquidities }) } } @@ -2152,25 +2622,32 @@ impl Readable for ChannelLiquidity { #[cfg(test)] mod tests { - use super::{ChannelLiquidity, HistoricalBucketRangeTracker, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters, ProbabilisticScorer}; + use super::{ + ChannelLiquidity, HistoricalBucketRangeTracker, ProbabilisticScorer, + ProbabilisticScoringDecayParameters, ProbabilisticScoringFeeParameters, + }; use crate::blinded_path::{BlindedHop, BlindedPath}; 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::router::{ + BlindedTail, CandidateRouteHop, Path, PublicHopCandidate, RouteHop, + }; use crate::routing::scoring::{ChannelUsage, ScoreLookUp, ScoreUpdate}; use crate::util::ser::{ReadableArgs, Writeable}; use crate::util::test_utils::{self, TestLogger}; + use crate::io; use bitcoin::blockdata::constants::ChainHash; - use bitcoin::hashes::Hash; use bitcoin::hashes::sha256d::Hash as Sha256dHash; + use bitcoin::hashes::Hash; use bitcoin::network::constants::Network; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use core::time::Duration; - use crate::io; fn source_privkey() -> SecretKey { SecretKey::from_slice(&[42; 32]).unwrap() @@ -2231,8 +2708,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(); @@ -2244,8 +2721,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()[..])[..]); @@ -2257,8 +2740,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); } @@ -2308,7 +2792,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, } } @@ -2320,20 +2805,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, + min_liquidity_offset_msat: 700, + max_liquidity_offset_msat: 100, + last_updated, + offset_history_last_updated, min_liquidity_offset_history: HistoricalBucketRangeTracker::new(), max_liquidity_offset_history: HistoricalBucketRangeTracker::new(), - }) - .with_channel(43, + }, + ) + .with_channel( + 43, ChannelLiquidity { - min_liquidity_offset_msat: 700, max_liquidity_offset_msat: 100, - last_updated, offset_history_last_updated, + min_liquidity_offset_msat: 700, + max_liquidity_offset_msat: 100, + last_updated, + offset_history_last_updated, min_liquidity_offset_history: HistoricalBucketRangeTracker::new(), max_liquidity_offset_history: HistoricalBucketRangeTracker::new(), - }); + }, + ); let source = source_node_id(); let target = target_node_id(); let recipient = recipient_node_id(); @@ -2342,53 +2835,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); } @@ -2401,55 +2900,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, + min_liquidity_offset_msat: 200, + max_liquidity_offset_msat: 400, + last_updated, + offset_history_last_updated, min_liquidity_offset_history: HistoricalBucketRangeTracker::new(), max_liquidity_offset_history: HistoricalBucketRangeTracker::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); } @@ -2462,55 +2971,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, + min_liquidity_offset_msat: 200, + max_liquidity_offset_msat: 400, + last_updated, + offset_history_last_updated, min_liquidity_offset_history: HistoricalBucketRangeTracker::new(), max_liquidity_offset_history: HistoricalBucketRangeTracker::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); } @@ -2530,15 +3049,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); @@ -2550,7 +3070,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 }; @@ -2581,27 +3104,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, - min_liquidity_offset_history: HistoricalBucketRangeTracker::new(), - max_liquidity_offset_history: HistoricalBucketRangeTracker::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, + min_liquidity_offset_history: HistoricalBucketRangeTracker::new(), + max_liquidity_offset_history: HistoricalBucketRangeTracker::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); @@ -2618,21 +3145,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); @@ -2651,21 +3183,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); @@ -2691,21 +3228,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); @@ -2745,11 +3287,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); @@ -2759,59 +3297,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); } @@ -2823,31 +3356,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); @@ -2878,14 +3412,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); @@ -2967,14 +3502,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); @@ -3020,16 +3556,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)); @@ -3042,8 +3579,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); } @@ -3064,16 +3604,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 { @@ -3084,8 +3625,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)); @@ -3112,59 +3656,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), 11497); 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), 7408); 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), 6151); 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), 5427); 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), 4955); 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), 4736); 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), 4484); 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), 4484); 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), 4263); 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), 4263); 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), 4044); } @@ -3177,36 +3766,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); } @@ -3218,7 +3824,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 { @@ -3226,13 +3835,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 { @@ -3240,7 +3851,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); } @@ -3261,10 +3876,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); } @@ -3277,21 +3890,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 }; @@ -3303,7 +3921,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; @@ -3315,10 +3937,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 }; @@ -3348,53 +3968,71 @@ 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), 168); } - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - None); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms), - None); + assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); + assert_eq!( + scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms), + 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), 249); } // 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) - .unwrap() > 0.35); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 500, ¶ms), - 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) + .unwrap() > 0.35 + ); + assert_eq!( + scorer.historical_estimated_payment_success_probability(42, &target, 500, ¶ms), + 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. @@ -3403,26 +4041,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), 105); } // 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).unwrap(); + let five_hundred_prob = scorer + .historical_estimated_payment_success_probability(42, &target, 500, ¶ms) + .unwrap(); assert!(five_hundred_prob > 0.59); assert!(five_hundred_prob < 0.60); - let one_prob = - scorer.historical_estimated_payment_success_probability(42, &target, 1, ¶ms).unwrap(); + let one_prob = scorer + .historical_estimated_payment_success_probability(42, &target, 1, ¶ms) + .unwrap(); assert!(one_prob < 0.85); assert!(one_prob > 0.84); @@ -3433,33 +4081,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), 168); } // 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), 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), + 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), 2050); @@ -3476,8 +4128,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. @@ -3486,7 +4137,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] @@ -3498,28 +4153,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); @@ -3527,7 +4190,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); @@ -3535,7 +4201,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); } @@ -3555,14 +4224,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, 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); @@ -3570,9 +4240,10 @@ mod tests { let blinded_path = BlindedPath { introduction_node_id: path.hops.last().as_ref().unwrap().pubkey, blinding_point: test_utils::pubkey(42), - blinded_hops: vec![ - BlindedHop { blinded_node_id: test_utils::pubkey(44), encrypted_payload: Vec::new() } - ], + blinded_hops: vec![BlindedHop { + blinded_node_id: test_utils::pubkey(44), + encrypted_payload: Vec::new(), + }], }; path.blinded_tail = Some(BlindedTail { hops: blinded_path.blinded_hops, @@ -3589,8 +4260,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); } @@ -3624,63 +4295,108 @@ 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 ~75%. assert_eq!(scorer.channel_penalty_msat(&candidate, usage, ¶ms), 1269); - assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), - None); - assert_eq!(scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms), - None); + assert_eq!(scorer.historical_estimated_channel_liquidity_probabilities(42, &target), None); + assert_eq!( + scorer.historical_estimated_payment_success_probability(42, &target, 42, ¶ms), + 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), - Some(0.0)); + assert_eq!( + scorer.historical_estimated_payment_success_probability( + 42, + &target, + amount_msat, + ¶ms + ), + 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), - Some(0.5)); + assert_eq!( + scorer.historical_estimated_payment_success_probability( + 42, + &target, + amount_msat, + ¶ms + ), + 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), - 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 + ), + Some(0.0) + ); } } #[cfg(ldk_bench)] pub mod benches { use super::*; - use criterion::Criterion; + use crate::ln::features::{ChannelFeatures, NodeFeatures}; use crate::routing::router::{bench_utils, RouteHop}; use crate::util::test_utils::TestLogger; - use crate::ln::features::{ChannelFeatures, NodeFeatures}; + use criterion::Criterion; pub fn decay_100k_channel_bounds(bench: &mut Criterion) { let logger = TestLogger::new(); @@ -3693,14 +4409,21 @@ pub mod benches { let (victim, victim_dst, amt) = { let rong = network_graph.read_only(); let channels = rong.channels(); - let chan = channels.unordered_iter() + let chan = channels + .unordered_iter() .skip((seed as usize) % channels.len()) - .next().unwrap(); + .next() + .unwrap(); seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0; - let amt = seed % chan.1.capacity_sats.map(|c| c * 1000) - .or(chan.1.one_to_two.as_ref().map(|info| info.htlc_maximum_msat)) - .or(chan.1.two_to_one.as_ref().map(|info| info.htlc_maximum_msat)) - .unwrap_or(1_000_000_000).saturating_add(1); + let amt = seed + % chan + .1 + .capacity_sats + .map(|c| c * 1000) + .or(chan.1.one_to_two.as_ref().map(|info| info.htlc_maximum_msat)) + .or(chan.1.two_to_one.as_ref().map(|info| info.htlc_maximum_msat)) + .unwrap_or(1_000_000_000) + .saturating_add(1); (*chan.0, chan.1.node_two, amt) }; let path = Path { @@ -3713,7 +4436,7 @@ pub mod benches { cltv_expiry_delta: 42, maybe_announced_channel: true, }], - blinded_tail: None + blinded_tail: None, }; seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0; if seed % 1 == 0 { @@ -3723,11 +4446,13 @@ pub mod benches { } } 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 3c0ef85fd7e..c2305a2a0ad 100644 --- a/lightning/src/routing/test_utils.rs +++ b/lightning/src/routing/test_utils.rs @@ -7,20 +7,22 @@ // You may not use this file except in accordance with one or both of these // licenses. -use crate::routing::gossip::{NetworkGraph, NodeAlias, P2PGossipSync}; use crate::ln::features::{ChannelFeatures, NodeFeatures}; -use crate::ln::msgs::{UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler, - NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate, MAX_VALUE_MSAT}; -use crate::util::test_utils; +use crate::ln::msgs::{ + ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, RoutingMessageHandler, + UnsignedChannelAnnouncement, UnsignedChannelUpdate, UnsignedNodeAnnouncement, MAX_VALUE_MSAT, +}; +use crate::routing::gossip::{NetworkGraph, NodeAlias, P2PGossipSync}; use crate::util::ser::Writeable; +use crate::util::test_utils; use bitcoin::blockdata::constants::ChainHash; +use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hashes::Hash; -use bitcoin::hashes::hex::FromHex; use bitcoin::network::constants::Network; -use bitcoin::secp256k1::{PublicKey,SecretKey}; -use bitcoin::secp256k1::{Secp256k1, All}; +use bitcoin::secp256k1::{All, Secp256k1}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use crate::prelude::*; use crate::sync::{self, Arc}; @@ -29,8 +31,13 @@ use crate::routing::gossip::NodeId; // Using the same keys for LN and BTC ids pub(super) 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 node_id_1 = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_1_privkey)); let node_id_2 = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_2_privkey)); @@ -56,13 +63,17 @@ pub(super) fn add_channel( }; match gossip_sync.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(res), - _ => panic!() + _ => panic!(), }; } pub(super) 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_id = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_privkey)); let unsigned_announcement = UnsignedNodeAnnouncement { @@ -78,39 +89,52 @@ pub(super) 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(&valid_announcement) { Ok(_) => (), - Err(_) => panic!() + Err(_) => panic!(), }; } pub(super) 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 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(&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(&>::from_hex(&format!("{:02x}", i).repeat(32)).unwrap()[..]).unwrap() - }).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(); +pub(super) fn get_nodes( + secp_ctx: &Secp256k1, +) -> (SecretKey, PublicKey, Vec, Vec) { + let privkeys: Vec = (2..22) + .map(|i| { + SecretKey::from_slice( + &>::from_hex(&format!("{:02x}", i).repeat(32)).unwrap()[..], + ) + .unwrap() + }) + .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_id = PublicKey::from_secret_key(&secp_ctx, &our_privkey); (our_privkey, our_id, privkeys, pubkeys) @@ -120,21 +144,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()); @@ -146,12 +176,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, @@ -161,23 +202,34 @@ 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, 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, &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) } @@ -185,7 +237,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, ) { @@ -255,241 +311,431 @@ 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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 e190d4258ae..6e55b6df24c 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::blockdata::constants::ChainHash; +use bitcoin::TxOut; use hex::DisplayHex; use crate::events::MessageSendEvent; use crate::ln::chan_utils::make_funding_redeemscript_from_slices; -use crate::ln::msgs::{self, LightningError, ErrorAction}; +use crate::ln::msgs::{self, ErrorAction, LightningError}; 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: HashMap::new(), nodes: HashMap::new(), - }) } + PendingChecks { + internal: Mutex::new(PendingChecksContext { + channels: HashMap::new(), + nodes: HashMap::new(), + }), + } } /// 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_v0_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_v0_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_insert(Vec::new()).push(Arc::downgrade(&future.state)); - pending_checks.nodes.entry(msg.node_id_2) - .or_insert(Vec::new()).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_insert(Vec::new()) + .push(Arc::downgrade(&future.state)); + pending_checks + .nodes + .entry(msg.node_id_2) + .or_insert(Vec::new()) + .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() @@ -561,9 +627,9 @@ impl PendingChecks { #[cfg(test)] mod tests { use super::*; + use crate::ln::msgs; use crate::routing::gossip::tests::*; use crate::util::test_utils::{TestChainSource, TestLogger}; - use crate::ln::msgs; use bitcoin::secp256k1::{Secp256k1, SecretKey}; @@ -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.flags = 0, node_1_privkey, &secp_ctx); - let chan_update_b = get_signed_channel_update(|msg| msg.flags = 1, node_2_privkey, &secp_ctx); - let chan_update_c = get_signed_channel_update(|msg| { - msg.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.flags = 0, node_1_privkey, &secp_ctx); + let chan_update_b = + get_signed_channel_update(|msg| msg.flags = 1, node_2_privkey, &secp_ctx); + let chan_update_c = get_signed_channel_update( + |msg| { + msg.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: 1_000_000, script_pubkey: good_script })); + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { value: 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: 0, 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: 0, 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,27 @@ 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: 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: 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 +822,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: 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: 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: 1_000_000, script_pubkey: good_script })); + future.resolve_without_forwarding( + &network_graph, + Ok(TxOut { value: 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 +1012,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 +1037,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: 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: 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 +1082,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 +1120,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/lightning/src/sign/ecdsa.rs b/lightning/src/sign/ecdsa.rs index 2e98213c182..dc177e7540d 100644 --- a/lightning/src/sign/ecdsa.rs +++ b/lightning/src/sign/ecdsa.rs @@ -2,14 +2,16 @@ use bitcoin::blockdata::transaction::Transaction; -use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; -use bitcoin::secp256k1::ecdsa::Signature; use bitcoin::secp256k1; +use bitcoin::secp256k1::ecdsa::Signature; +use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; -use crate::util::ser::Writeable; -use crate::ln::PaymentPreimage; -use crate::ln::chan_utils::{HTLCOutputInCommitment, HolderCommitmentTransaction, CommitmentTransaction, ClosingTransaction}; +use crate::ln::chan_utils::{ + ClosingTransaction, CommitmentTransaction, HTLCOutputInCommitment, HolderCommitmentTransaction, +}; use crate::ln::msgs::UnsignedChannelAnnouncement; +use crate::ln::PaymentPreimage; +use crate::util::ser::Writeable; use crate::prelude::*; use crate::sign::{ChannelSigner, HTLCDescriptor}; @@ -38,8 +40,8 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// irrelevant or duplicate preimages. // // TODO: Document the things someone using this interface should enforce before signing. - fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, - inbound_htlc_preimages: Vec, + fn sign_counterparty_commitment( + &self, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1, ) -> Result<(Signature, Vec), ()>; /// Creates a signature for a holder's commitment transaction. @@ -53,15 +55,17 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// An external signer implementation should check that the commitment has not been revoked. // // TODO: Document the things someone using this interface should enforce before signing. - fn sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, - secp_ctx: &Secp256k1) -> Result; + fn sign_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1, + ) -> Result; /// Same as [`sign_holder_commitment`], but exists only for tests to get access to holder /// commitment transactions which will be broadcasted later, after the channel has moved on to a /// newer state. Thus, needs its own method as [`sign_holder_commitment`] may enforce that we /// only ever get called once. - #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] - fn unsafe_sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, - secp_ctx: &Secp256k1) -> Result; + #[cfg(any(test, feature = "unsafe_revoked_tx_signing"))] + fn unsafe_sign_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1, + ) -> Result; /// Create a signature for the given input in a transaction spending an HTLC transaction output /// or a commitment transaction `to_local` output when our counterparty broadcasts an old state. /// @@ -76,8 +80,9 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// revoked the state which they eventually broadcast. It's not a _holder_ secret key and does /// not allow the spending of any funds by itself (you need our holder `revocation_secret` to do /// so). - fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, - per_commitment_key: &SecretKey, secp_ctx: &Secp256k1 + fn sign_justice_revoked_output( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + secp_ctx: &Secp256k1, ) -> Result; /// Create a signature for the given input in a transaction spending a commitment transaction /// HTLC output when our counterparty broadcasts an old state. @@ -97,9 +102,10 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// /// `htlc` holds HTLC elements (hash, timelock), thus changing the format of the witness script /// (which is committed to in the BIP 143 signatures). - fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, - per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, - secp_ctx: &Secp256k1) -> Result; + fn sign_justice_revoked_htlc( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result; /// Computes the signature for a commitment transaction's HTLC output used as an input within /// `htlc_tx`, which spends the commitment transaction at index `input`. The signature returned /// must be be computed using [`EcdsaSighashType::All`]. @@ -110,8 +116,9 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// /// [`EcdsaSighashType::All`]: bitcoin::sighash::EcdsaSighashType::All /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor - fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, - htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1 + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1, ) -> Result; /// Create a signature for a claiming transaction for a HTLC output on a counterparty's commitment /// transaction, either offered or received. @@ -130,15 +137,17 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// detected onchain. It has been generated by our counterparty and is used to derive /// channel state keys, which are then included in the witness script and committed to in the /// BIP 143 signature. - fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, - per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, - secp_ctx: &Secp256k1) -> Result; + fn sign_counterparty_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result; /// Create a signature for a (proposed) closing transaction. /// /// Note that, due to rounding, there may be one "missing" satoshi, and either party may have /// chosen to forgo their output as dust. - fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, - secp_ctx: &Secp256k1) -> Result; + fn sign_closing_transaction( + &self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1, + ) -> Result; /// Computes the signature for a commitment transaction's anchor output used as an /// input within `anchor_tx`, which spends the commitment transaction, at index `input`. fn sign_holder_anchor_input( @@ -156,7 +165,7 @@ pub trait EcdsaChannelSigner: ChannelSigner { /// /// [`NodeSigner::sign_gossip_message`]: crate::sign::NodeSigner::sign_gossip_message fn sign_channel_announcement_with_funding_key( - &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 + &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1, ) -> Result; } diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index e2a89d8485f..bb5d7df43e4 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -12,61 +12,67 @@ //! The provided output descriptors follow a custom LDK data format and are currently not fully //! compatible with Bitcoin Core output descriptors. +use bitcoin::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey}; use bitcoin::blockdata::locktime::absolute::LockTime; -use bitcoin::blockdata::transaction::{Transaction, TxOut, TxIn}; -use bitcoin::blockdata::script::{Script, ScriptBuf, Builder}; use bitcoin::blockdata::opcodes; +use bitcoin::blockdata::script::{Builder, Script, ScriptBuf}; +use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; use bitcoin::ecdsa::Signature as EcdsaSignature; use bitcoin::network::constants::Network; use bitcoin::psbt::PartiallySignedTransaction; -use bitcoin::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber}; use bitcoin::sighash; use bitcoin::sighash::EcdsaSighashType; use bitcoin::bech32::u5; -use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::hash_types::WPubkeyHash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256d::Hash as Sha256dHash; -use bitcoin::hash_types::WPubkeyHash; +use bitcoin::hashes::{Hash, HashEngine}; -#[cfg(taproot)] -use bitcoin::secp256k1::All; -use bitcoin::secp256k1::{KeyPair, PublicKey, Scalar, Secp256k1, SecretKey, Signing}; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use bitcoin::secp256k1::schnorr; -use bitcoin::{secp256k1, Sequence, Witness, Txid}; +#[cfg(taproot)] +use bitcoin::secp256k1::All; +use bitcoin::secp256k1::{KeyPair, PublicKey, Scalar, Secp256k1, SecretKey, Signing}; +use bitcoin::{secp256k1, Sequence, Txid, Witness}; -use crate::util::transaction_utils; -use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand}; -use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs}; use crate::chain::transaction::OutPoint; +use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand}; +use crate::ln::chan_utils::{ + make_funding_redeemscript, ChannelPublicKeys, ChannelTransactionParameters, ClosingTransaction, + CommitmentTransaction, HTLCOutputInCommitment, HolderCommitmentTransaction, +}; use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI; -use crate::ln::{chan_utils, PaymentPreimage}; -use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction}; -use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint}; -use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage}; +use crate::ln::channel_keys::{ + DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, HtlcKey, RevocationBasepoint, + RevocationKey, +}; #[cfg(taproot)] use crate::ln::msgs::PartialSignatureWithNonce; +use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage}; use crate::ln::script::ShutdownScript; +use crate::ln::{chan_utils, PaymentPreimage}; use crate::offers::invoice::UnsignedBolt12Invoice; use crate::offers::invoice_request::UnsignedInvoiceRequest; +use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; +use crate::util::transaction_utils; -use crate::prelude::*; -use core::convert::TryInto; -use core::ops::Deref; -use core::sync::atomic::{AtomicUsize, Ordering}; -#[cfg(taproot)] -use musig2::types::{PartialSignature, PublicNonce}; +use crate::crypto::chacha20::ChaCha20; use crate::io::{self, Error}; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; +use crate::prelude::*; use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; #[cfg(taproot)] use crate::sign::taproot::TaprootChannelSigner; use crate::util::atomic_counter::AtomicCounter; -use crate::crypto::chacha20::ChaCha20; use crate::util::invoice::construct_invoice_preimage; +use core::convert::TryInto; +use core::ops::Deref; +use core::sync::atomic::{AtomicUsize, Ordering}; +#[cfg(taproot)] +use musig2::types::{PartialSignature, PublicNonce}; pub(crate) mod type_resolver; @@ -110,7 +116,8 @@ impl DelayedPaymentOutputDescriptor { /// shorter. // Calculated as 1 byte length + 73 byte signature, 1 byte empty vec push, 1 byte length plus // redeemscript push length. - pub const MAX_WITNESS_LENGTH: u64 = 1 + 73 + 1 + chan_utils::REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH as u64 + 1; + pub const MAX_WITNESS_LENGTH: u64 = + 1 + 73 + 1 + chan_utils::REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH as u64 + 1; } impl_writeable_tlv_based!(DelayedPaymentOutputDescriptor, { @@ -155,23 +162,26 @@ impl StaticPaymentOutputDescriptor { /// Note that this will only return `Some` for [`StaticPaymentOutputDescriptor`]s that /// originated from an anchor outputs channel, as they take the form of a P2WSH script. pub fn witness_script(&self) -> Option { - self.channel_transaction_parameters.as_ref() - .and_then(|channel_params| - if channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() { - let payment_point = channel_params.holder_pubkeys.payment_point; - Some(chan_utils::get_to_countersignatory_with_anchors_redeemscript(&payment_point)) - } else { - None - } - ) + self.channel_transaction_parameters.as_ref().and_then(|channel_params| { + if channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() { + let payment_point = channel_params.holder_pubkeys.payment_point; + Some(chan_utils::get_to_countersignatory_with_anchors_redeemscript(&payment_point)) + } else { + None + } + }) } /// The maximum length a well-formed witness spending one of these should have. /// Note: If you have the grind_signatures feature enabled, this will be at least 1 byte /// shorter. pub fn max_witness_length(&self) -> u64 { - if self.channel_transaction_parameters.as_ref() - .map(|channel_params| channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx()) + if self + .channel_transaction_parameters + .as_ref() + .map(|channel_params| { + channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() + }) .unwrap_or(false) { let witness_script_weight = 1 /* pubkey push */ + 33 /* pubkey */ + @@ -223,7 +233,7 @@ pub enum SpendableOutputDescriptor { /// /// For channels which were generated prior to LDK 0.0.119, no such argument existed, /// however this field may still be filled in if such data is available. - channel_keys_id: Option<[u8; 32]> + channel_keys_id: Option<[u8; 32]>, }, /// An output to a P2WSH script which can be spent with a single signature after an `OP_CSV` /// delay. @@ -308,10 +318,7 @@ impl SpendableOutputDescriptor { match self { SpendableOutputDescriptor::StaticOutput { output, .. } => { // Is a standard P2WPKH, no need for witness script - bitcoin::psbt::Input { - witness_utxo: Some(output.clone()), - ..Default::default() - } + bitcoin::psbt::Input { witness_utxo: Some(output.clone()), ..Default::default() } }, SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) => { // TODO we could add the witness script as well @@ -346,7 +353,11 @@ impl SpendableOutputDescriptor { /// does not match the one we can spend. /// /// We do not enforce that outputs meet the dust limit or that any output scripts are standard. - pub fn create_spendable_outputs_psbt(descriptors: &[&SpendableOutputDescriptor], outputs: Vec, change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32, locktime: Option) -> Result<(PartiallySignedTransaction, u64), ()> { + pub fn create_spendable_outputs_psbt( + descriptors: &[&SpendableOutputDescriptor], outputs: Vec, + change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32, + locktime: Option, + ) -> Result<(PartiallySignedTransaction, u64), ()> { let mut input = Vec::with_capacity(descriptors.len()); let mut input_value = 0; let mut witness_weight = 0; @@ -354,16 +365,21 @@ impl SpendableOutputDescriptor { for outp in descriptors { match outp { SpendableOutputDescriptor::StaticPaymentOutput(descriptor) => { - if !output_set.insert(descriptor.outpoint) { return Err(()); } - let sequence = - if descriptor.channel_transaction_parameters.as_ref() - .map(|channel_params| channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx()) - .unwrap_or(false) - { - Sequence::from_consensus(1) - } else { - Sequence::ZERO - }; + if !output_set.insert(descriptor.outpoint) { + return Err(()); + } + let sequence = if descriptor + .channel_transaction_parameters + .as_ref() + .map(|channel_params| { + channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() + }) + .unwrap_or(false) + { + Sequence::from_consensus(1) + } else { + Sequence::ZERO + }; input.push(TxIn { previous_output: descriptor.outpoint.into_bitcoin_outpoint(), script_sig: ScriptBuf::new(), @@ -372,11 +388,15 @@ impl SpendableOutputDescriptor { }); witness_weight += descriptor.max_witness_length(); #[cfg(feature = "grind_signatures")] - { witness_weight -= 1; } // Guarantees a low R signature + { + witness_weight -= 1; + } // Guarantees a low R signature input_value += descriptor.output.value; }, SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) => { - if !output_set.insert(descriptor.outpoint) { return Err(()); } + if !output_set.insert(descriptor.outpoint) { + return Err(()); + } input.push(TxIn { previous_output: descriptor.outpoint.into_bitcoin_outpoint(), script_sig: ScriptBuf::new(), @@ -385,11 +405,15 @@ impl SpendableOutputDescriptor { }); witness_weight += DelayedPaymentOutputDescriptor::MAX_WITNESS_LENGTH; #[cfg(feature = "grind_signatures")] - { witness_weight -= 1; } // Guarantees a low R signature + { + witness_weight -= 1; + } // Guarantees a low R signature input_value += descriptor.output.value; }, SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output, .. } => { - if !output_set.insert(*outpoint) { return Err(()); } + if !output_set.insert(*outpoint) { + return Err(()); + } input.push(TxIn { previous_output: outpoint.into_bitcoin_outpoint(), script_sig: ScriptBuf::new(), @@ -398,11 +422,15 @@ impl SpendableOutputDescriptor { }); witness_weight += 1 + 73 + 34; #[cfg(feature = "grind_signatures")] - { witness_weight -= 1; } // Guarantees a low R signature + { + witness_weight -= 1; + } // Guarantees a low R signature input_value += output.value; - } + }, + } + if input_value > MAX_VALUE_MSAT / 1000 { + return Err(()); } - if input_value > MAX_VALUE_MSAT / 1000 { return Err(()); } } let mut tx = Transaction { version: 2, @@ -410,8 +438,13 @@ impl SpendableOutputDescriptor { input, output: outputs, }; - let expected_max_weight = - transaction_utils::maybe_add_change_output(&mut tx, input_value, witness_weight, feerate_sat_per_1000_weight, change_destination_script)?; + let expected_max_weight = transaction_utils::maybe_add_change_output( + &mut tx, + input_value, + witness_weight, + feerate_sat_per_1000_weight, + change_destination_script, + )?; let psbt_inputs = descriptors.iter().map(|d| d.to_psbt_input()).collect::>(); let psbt = PartiallySignedTransaction { @@ -440,9 +473,9 @@ pub struct ChannelDerivationParameters { } impl_writeable_tlv_based!(ChannelDerivationParameters, { - (0, value_satoshis, required), - (2, keys_id, required), - (4, transaction_parameters, required), + (0, value_satoshis, required), + (2, keys_id, required), + (4, transaction_parameters, required), }); /// A descriptor used to sign for a commitment transaction's HTLC output. @@ -470,7 +503,7 @@ pub struct HTLCDescriptor { /// taken. pub preimage: Option, /// The counterparty's signature required to spend the HTLC output. - pub counterparty_sig: Signature + pub counterparty_sig: Signature, } impl_writeable_tlv_based!(HTLCDescriptor, { @@ -496,7 +529,9 @@ impl HTLCDescriptor { /// Returns the UTXO to be spent by the HTLC input, which can be obtained via /// [`Self::unsigned_tx_input`]. - pub fn previous_utxo(&self, secp: &Secp256k1) -> TxOut { + pub fn previous_utxo( + &self, secp: &Secp256k1, + ) -> TxOut { TxOut { script_pubkey: self.witness_script(secp).to_v0_p2wsh(), value: self.htlc.amount_msat / 1000, @@ -507,40 +542,69 @@ impl HTLCDescriptor { /// transaction. pub fn unsigned_tx_input(&self) -> TxIn { chan_utils::build_htlc_input( - &self.commitment_txid, &self.htlc, &self.channel_derivation_parameters.transaction_parameters.channel_type_features + &self.commitment_txid, + &self.htlc, + &self.channel_derivation_parameters.transaction_parameters.channel_type_features, ) } /// Returns the delayed output created as a result of spending the HTLC output in the commitment /// transaction. - pub fn tx_output(&self, secp: &Secp256k1) -> TxOut { - let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); + pub fn tx_output( + &self, secp: &Secp256k1, + ) -> TxOut { + let channel_params = + self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); let broadcaster_keys = channel_params.broadcaster_pubkeys(); let counterparty_keys = channel_params.countersignatory_pubkeys(); let broadcaster_delayed_key = DelayedPaymentKey::from_basepoint( - secp, &broadcaster_keys.delayed_payment_basepoint, &self.per_commitment_point + secp, + &broadcaster_keys.delayed_payment_basepoint, + &self.per_commitment_point, + ); + let counterparty_revocation_key = &RevocationKey::from_basepoint( + &secp, + &counterparty_keys.revocation_basepoint, + &self.per_commitment_point, ); - let counterparty_revocation_key = &RevocationKey::from_basepoint(&secp, &counterparty_keys.revocation_basepoint, &self.per_commitment_point); chan_utils::build_htlc_output( - self.feerate_per_kw, channel_params.contest_delay(), &self.htlc, - channel_params.channel_type_features(), &broadcaster_delayed_key, &counterparty_revocation_key + self.feerate_per_kw, + channel_params.contest_delay(), + &self.htlc, + channel_params.channel_type_features(), + &broadcaster_delayed_key, + &counterparty_revocation_key, ) } /// Returns the witness script of the HTLC output in the commitment transaction. - pub fn witness_script(&self, secp: &Secp256k1) -> ScriptBuf { - let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); + pub fn witness_script( + &self, secp: &Secp256k1, + ) -> ScriptBuf { + let channel_params = + self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable(); let broadcaster_keys = channel_params.broadcaster_pubkeys(); let counterparty_keys = channel_params.countersignatory_pubkeys(); let broadcaster_htlc_key = HtlcKey::from_basepoint( - secp, &broadcaster_keys.htlc_basepoint, &self.per_commitment_point + secp, + &broadcaster_keys.htlc_basepoint, + &self.per_commitment_point, ); let counterparty_htlc_key = HtlcKey::from_basepoint( - secp, &counterparty_keys.htlc_basepoint, &self.per_commitment_point, + secp, + &counterparty_keys.htlc_basepoint, + &self.per_commitment_point, + ); + let counterparty_revocation_key = &RevocationKey::from_basepoint( + &secp, + &counterparty_keys.revocation_basepoint, + &self.per_commitment_point, ); - let counterparty_revocation_key = &RevocationKey::from_basepoint(&secp, &counterparty_keys.revocation_basepoint, &self.per_commitment_point); chan_utils::get_htlc_redeemscript_with_explicit_keys( - &self.htlc, channel_params.channel_type_features(), &broadcaster_htlc_key, &counterparty_htlc_key, + &self.htlc, + channel_params.channel_type_features(), + &broadcaster_htlc_key, + &counterparty_htlc_key, &counterparty_revocation_key, ) } @@ -549,21 +613,27 @@ impl HTLCDescriptor { /// transaction. pub fn tx_input_witness(&self, signature: &Signature, witness_script: &Script) -> Witness { chan_utils::build_htlc_input_witness( - signature, &self.counterparty_sig, &self.preimage, witness_script, - &self.channel_derivation_parameters.transaction_parameters.channel_type_features + signature, + &self.counterparty_sig, + &self.preimage, + witness_script, + &self.channel_derivation_parameters.transaction_parameters.channel_type_features, ) } /// Derives the channel signer required to sign the HTLC input. - pub fn derive_channel_signer(&self, signer_provider: &SP) -> S + pub fn derive_channel_signer( + &self, signer_provider: &SP, + ) -> S where - SP::Target: SignerProvider + SP::Target: SignerProvider, { let mut signer = signer_provider.derive_channel_signer( self.channel_derivation_parameters.value_satoshis, self.channel_derivation_parameters.keys_id, ); - signer.provide_channel_parameters(&self.channel_derivation_parameters.transaction_parameters); + signer + .provide_channel_parameters(&self.channel_derivation_parameters.transaction_parameters); signer } } @@ -574,7 +644,8 @@ pub trait ChannelSigner { /// Gets the per-commitment point for a specific commitment number /// /// Note that the commitment number starts at `(1 << 48) - 1` and counts backwards. - fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) -> PublicKey; + fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) + -> PublicKey; /// Gets the commitment secret for a specific commitment number as part of the revocation process /// @@ -600,8 +671,10 @@ pub trait ChannelSigner { /// /// Note that all the relevant preimages will be provided, but there may also be additional /// irrelevant or duplicate preimages. - fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, - outbound_htlc_preimages: Vec) -> Result<(), ()>; + fn validate_holder_commitment( + &self, holder_tx: &HolderCommitmentTransaction, + outbound_htlc_preimages: Vec, + ) -> Result<(), ()>; /// Validate the counterparty's revocation. /// @@ -682,7 +755,9 @@ pub trait NodeSigner { /// should be resolved to allow LDK to resume forwarding HTLCs. /// /// Errors if the [`Recipient`] variant is not supported by the implementation. - fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result; + fn ecdh( + &self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>, + ) -> Result; /// Sign an invoice. /// @@ -695,7 +770,9 @@ pub trait NodeSigner { /// The secret key used to sign the invoice is dependent on the [`Recipient`]. /// /// Errors if the [`Recipient`] variant is not supported by the implementation. - fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result; + fn sign_invoice( + &self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient, + ) -> Result; /// Signs the [`TaggedHash`] of a BOLT 12 invoice request. /// @@ -709,7 +786,7 @@ pub trait NodeSigner { /// /// [`TaggedHash`]: crate::offers::merkle::TaggedHash fn sign_bolt12_invoice_request( - &self, invoice_request: &UnsignedInvoiceRequest + &self, invoice_request: &UnsignedInvoiceRequest, ) -> Result; /// Signs the [`TaggedHash`] of a BOLT 12 invoice. @@ -724,7 +801,7 @@ pub trait NodeSigner { /// /// [`TaggedHash`]: crate::offers::merkle::TaggedHash fn sign_bolt12_invoice( - &self, invoice: &UnsignedBolt12Invoice + &self, invoice: &UnsignedBolt12Invoice, ) -> Result; /// Sign a gossip message. @@ -750,7 +827,9 @@ pub trait SignerProvider { /// `channel_keys_id`. /// /// This method must return a different value each time it is called. - fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32]; + fn generate_channel_keys_id( + &self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128, + ) -> [u8; 32]; /// Derives the private key material backing a `Signer`. /// @@ -758,7 +837,9 @@ pub trait SignerProvider { /// [`SignerProvider::generate_channel_keys_id`]. Otherwise, an existing `Signer` can be /// re-derived from its `channel_keys_id`, which can be obtained through its trait method /// [`ChannelSigner::channel_keys_id`]. - fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::EcdsaSigner; + fn derive_channel_signer( + &self, channel_value_satoshis: u64, channel_keys_id: [u8; 32], + ) -> Self::EcdsaSigner; /// Reads a [`Signer`] for this [`SignerProvider`] from the given input stream. /// This is only called during deserialization of other objects which contain @@ -828,16 +909,16 @@ pub struct InMemorySigner { impl PartialEq for InMemorySigner { fn eq(&self, other: &Self) -> bool { - self.funding_key == other.funding_key && - self.revocation_base_key == other.revocation_base_key && - self.payment_key == other.payment_key && - self.delayed_payment_base_key == other.delayed_payment_base_key && - self.htlc_base_key == other.htlc_base_key && - self.commitment_seed == other.commitment_seed && - self.holder_channel_pubkeys == other.holder_channel_pubkeys && - self.channel_parameters == other.channel_parameters && - self.channel_value_satoshis == other.channel_value_satoshis && - self.channel_keys_id == other.channel_keys_id + self.funding_key == other.funding_key + && self.revocation_base_key == other.revocation_base_key + && self.payment_key == other.payment_key + && self.delayed_payment_base_key == other.delayed_payment_base_key + && self.htlc_base_key == other.htlc_base_key + && self.commitment_seed == other.commitment_seed + && self.holder_channel_pubkeys == other.holder_channel_pubkeys + && self.channel_parameters == other.channel_parameters + && self.channel_value_satoshis == other.channel_value_satoshis + && self.channel_keys_id == other.channel_keys_id } } @@ -862,21 +943,19 @@ impl Clone for InMemorySigner { impl InMemorySigner { /// Creates a new [`InMemorySigner`]. pub fn new( - secp_ctx: &Secp256k1, - funding_key: SecretKey, - revocation_base_key: SecretKey, - payment_key: SecretKey, - delayed_payment_base_key: SecretKey, - htlc_base_key: SecretKey, - commitment_seed: [u8; 32], - channel_value_satoshis: u64, - channel_keys_id: [u8; 32], + secp_ctx: &Secp256k1, funding_key: SecretKey, revocation_base_key: SecretKey, + payment_key: SecretKey, delayed_payment_base_key: SecretKey, htlc_base_key: SecretKey, + commitment_seed: [u8; 32], channel_value_satoshis: u64, channel_keys_id: [u8; 32], rand_bytes_unique_start: [u8; 32], ) -> InMemorySigner { - let holder_channel_pubkeys = - InMemorySigner::make_holder_keys(secp_ctx, &funding_key, &revocation_base_key, - &payment_key, &delayed_payment_base_key, - &htlc_base_key); + let holder_channel_pubkeys = InMemorySigner::make_holder_keys( + secp_ctx, + &funding_key, + &revocation_base_key, + &payment_key, + &delayed_payment_base_key, + &htlc_base_key, + ); InMemorySigner { funding_key, revocation_base_key, @@ -892,18 +971,18 @@ impl InMemorySigner { } } - fn make_holder_keys(secp_ctx: &Secp256k1, - funding_key: &SecretKey, - revocation_base_key: &SecretKey, - payment_key: &SecretKey, - delayed_payment_base_key: &SecretKey, - htlc_base_key: &SecretKey) -> ChannelPublicKeys { + fn make_holder_keys( + secp_ctx: &Secp256k1, funding_key: &SecretKey, revocation_base_key: &SecretKey, + payment_key: &SecretKey, delayed_payment_base_key: &SecretKey, htlc_base_key: &SecretKey, + ) -> ChannelPublicKeys { let from_secret = |s: &SecretKey| PublicKey::from_secret_key(secp_ctx, s); ChannelPublicKeys { funding_pubkey: from_secret(&funding_key), revocation_basepoint: RevocationBasepoint::from(from_secret(&revocation_base_key)), payment_point: from_secret(&payment_key), - delayed_payment_basepoint: DelayedPaymentBasepoint::from(from_secret(&delayed_payment_base_key)), + delayed_payment_basepoint: DelayedPaymentBasepoint::from(from_secret( + &delayed_payment_base_key, + )), htlc_basepoint: HtlcBasepoint::from(from_secret(&htlc_base_key)), } } @@ -913,8 +992,9 @@ impl InMemorySigner { /// Will return `None` if [`ChannelSigner::provide_channel_parameters`] has not been called. /// In general, this is safe to `unwrap` only in [`ChannelSigner`] implementation. pub fn counterparty_pubkeys(&self) -> Option<&ChannelPublicKeys> { - self.get_channel_parameters() - .and_then(|params| params.counterparty_parameters.as_ref().map(|params| ¶ms.pubkeys)) + self.get_channel_parameters().and_then(|params| { + params.counterparty_parameters.as_ref().map(|params| ¶ms.pubkeys) + }) } /// Returns the `contest_delay` value specified by our counterparty and applied on holder-broadcastable @@ -924,8 +1004,9 @@ impl InMemorySigner { /// Will return `None` if [`ChannelSigner::provide_channel_parameters`] has not been called. /// In general, this is safe to `unwrap` only in [`ChannelSigner`] implementation. pub fn counterparty_selected_contest_delay(&self) -> Option { - self.get_channel_parameters() - .and_then(|params| params.counterparty_parameters.as_ref().map(|params| params.selected_contest_delay)) + self.get_channel_parameters().and_then(|params| { + params.counterparty_parameters.as_ref().map(|params| params.selected_contest_delay) + }) } /// Returns the `contest_delay` value specified by us and applied on transactions broadcastable @@ -980,19 +1061,30 @@ impl InMemorySigner { /// or if an output descriptor `script_pubkey` does not match the one we can spend. /// /// [`descriptor.outpoint`]: StaticPaymentOutputDescriptor::outpoint - pub fn sign_counterparty_payment_input(&self, spend_tx: &Transaction, input_idx: usize, descriptor: &StaticPaymentOutputDescriptor, secp_ctx: &Secp256k1) -> Result { + pub fn sign_counterparty_payment_input( + &self, spend_tx: &Transaction, input_idx: usize, + descriptor: &StaticPaymentOutputDescriptor, secp_ctx: &Secp256k1, + ) -> Result { // TODO: We really should be taking the SigHashCache as a parameter here instead of // spend_tx, but ideally the SigHashCache would expose the transaction's inputs read-only // so that we can check them. This requires upstream rust-bitcoin changes (as well as // bindings updates to support SigHashCache objects). - if spend_tx.input.len() <= input_idx { return Err(()); } - if !spend_tx.input[input_idx].script_sig.is_empty() { return Err(()); } - if spend_tx.input[input_idx].previous_output != descriptor.outpoint.into_bitcoin_outpoint() { return Err(()); } + if spend_tx.input.len() <= input_idx { + return Err(()); + } + if !spend_tx.input[input_idx].script_sig.is_empty() { + return Err(()); + } + if spend_tx.input[input_idx].previous_output != descriptor.outpoint.into_bitcoin_outpoint() + { + return Err(()); + } let remotepubkey = bitcoin::PublicKey::new(self.pubkeys().payment_point); // We cannot always assume that `channel_parameters` is set, so can't just call // `self.channel_parameters()` or anything that relies on it - let supports_anchors_zero_fee_htlc_tx = self.channel_type_features() + let supports_anchors_zero_fee_htlc_tx = self + .channel_type_features() .map(|features| features.supports_anchors_zero_fee_htlc_tx()) .unwrap_or(false); @@ -1001,7 +1093,16 @@ impl InMemorySigner { } else { ScriptBuf::new_p2pkh(&remotepubkey.pubkey_hash()) }; - let sighash = hash_to_message!(&sighash::SighashCache::new(spend_tx).segwit_signature_hash(input_idx, &witness_script, descriptor.output.value, EcdsaSighashType::All).unwrap()[..]); + let sighash = hash_to_message!( + &sighash::SighashCache::new(spend_tx) + .segwit_signature_hash( + input_idx, + &witness_script, + descriptor.output.value, + EcdsaSighashType::All + ) + .unwrap()[..] + ); let remotesig = sign_with_aux_rand(secp_ctx, &sighash, &self.payment_key, &self); let payment_script = if supports_anchors_zero_fee_htlc_tx { witness_script.to_v0_p2wsh() @@ -1009,7 +1110,9 @@ impl InMemorySigner { ScriptBuf::new_v0_p2wpkh(&remotepubkey.wpubkey_hash().unwrap()) }; - if payment_script != descriptor.output.script_pubkey { return Err(()); } + if payment_script != descriptor.output.script_pubkey { + return Err(()); + } let mut witness = Vec::with_capacity(2); witness.push(remotesig.serialize_der().to_vec()); @@ -1032,27 +1135,60 @@ impl InMemorySigner { /// /// [`descriptor.outpoint`]: DelayedPaymentOutputDescriptor::outpoint /// [`descriptor.to_self_delay`]: DelayedPaymentOutputDescriptor::to_self_delay - pub fn sign_dynamic_p2wsh_input(&self, spend_tx: &Transaction, input_idx: usize, descriptor: &DelayedPaymentOutputDescriptor, secp_ctx: &Secp256k1) -> Result { + pub fn sign_dynamic_p2wsh_input( + &self, spend_tx: &Transaction, input_idx: usize, + descriptor: &DelayedPaymentOutputDescriptor, secp_ctx: &Secp256k1, + ) -> Result { // TODO: We really should be taking the SigHashCache as a parameter here instead of // spend_tx, but ideally the SigHashCache would expose the transaction's inputs read-only // so that we can check them. This requires upstream rust-bitcoin changes (as well as // bindings updates to support SigHashCache objects). - if spend_tx.input.len() <= input_idx { return Err(()); } - if !spend_tx.input[input_idx].script_sig.is_empty() { return Err(()); } - if spend_tx.input[input_idx].previous_output != descriptor.outpoint.into_bitcoin_outpoint() { return Err(()); } - if spend_tx.input[input_idx].sequence.0 != descriptor.to_self_delay as u32 { return Err(()); } - - let delayed_payment_key = chan_utils::derive_private_key(&secp_ctx, &descriptor.per_commitment_point, &self.delayed_payment_base_key); - let delayed_payment_pubkey = DelayedPaymentKey::from_secret_key(&secp_ctx, &delayed_payment_key); - let witness_script = chan_utils::get_revokeable_redeemscript(&descriptor.revocation_pubkey, descriptor.to_self_delay, &delayed_payment_pubkey); - let sighash = hash_to_message!(&sighash::SighashCache::new(spend_tx).segwit_signature_hash(input_idx, &witness_script, descriptor.output.value, EcdsaSighashType::All).unwrap()[..]); + if spend_tx.input.len() <= input_idx { + return Err(()); + } + if !spend_tx.input[input_idx].script_sig.is_empty() { + return Err(()); + } + if spend_tx.input[input_idx].previous_output != descriptor.outpoint.into_bitcoin_outpoint() + { + return Err(()); + } + if spend_tx.input[input_idx].sequence.0 != descriptor.to_self_delay as u32 { + return Err(()); + } + + let delayed_payment_key = chan_utils::derive_private_key( + &secp_ctx, + &descriptor.per_commitment_point, + &self.delayed_payment_base_key, + ); + let delayed_payment_pubkey = + DelayedPaymentKey::from_secret_key(&secp_ctx, &delayed_payment_key); + let witness_script = chan_utils::get_revokeable_redeemscript( + &descriptor.revocation_pubkey, + descriptor.to_self_delay, + &delayed_payment_pubkey, + ); + let sighash = hash_to_message!( + &sighash::SighashCache::new(spend_tx) + .segwit_signature_hash( + input_idx, + &witness_script, + descriptor.output.value, + EcdsaSighashType::All + ) + .unwrap()[..] + ); let local_delayedsig = EcdsaSignature { sig: sign_with_aux_rand(secp_ctx, &sighash, &delayed_payment_key, &self), hash_ty: EcdsaSighashType::All, }; - let payment_script = bitcoin::Address::p2wsh(&witness_script, Network::Bitcoin).script_pubkey(); + let payment_script = + bitcoin::Address::p2wsh(&witness_script, Network::Bitcoin).script_pubkey(); - if descriptor.output.script_pubkey != payment_script { return Err(()); } + if descriptor.output.script_pubkey != payment_script { + return Err(()); + } Ok(Witness::from_slice(&[ &local_delayedsig.serialize()[..], @@ -1069,8 +1205,12 @@ impl EntropySource for InMemorySigner { } impl ChannelSigner for InMemorySigner { - fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) -> PublicKey { - let commitment_secret = SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx)).unwrap(); + fn get_per_commitment_point( + &self, idx: u64, secp_ctx: &Secp256k1, + ) -> PublicKey { + let commitment_secret = + SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx)) + .unwrap(); PublicKey::from_secret_key(secp_ctx, &commitment_secret) } @@ -1078,7 +1218,10 @@ impl ChannelSigner for InMemorySigner { chan_utils::build_commitment_secret(&self.commitment_seed, idx) } - fn validate_holder_commitment(&self, _holder_tx: &HolderCommitmentTransaction, _outbound_htlc_preimages: Vec) -> Result<(), ()> { + fn validate_holder_commitment( + &self, _holder_tx: &HolderCommitmentTransaction, + _outbound_htlc_preimages: Vec, + ) -> Result<(), ()> { Ok(()) } @@ -1086,12 +1229,19 @@ impl ChannelSigner for InMemorySigner { Ok(()) } - fn pubkeys(&self) -> &ChannelPublicKeys { &self.holder_channel_pubkeys } + fn pubkeys(&self) -> &ChannelPublicKeys { + &self.holder_channel_pubkeys + } - fn channel_keys_id(&self) -> [u8; 32] { self.channel_keys_id } + fn channel_keys_id(&self) -> [u8; 32] { + self.channel_keys_id + } fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) { - assert!(self.channel_parameters.is_none() || self.channel_parameters.as_ref().unwrap() == channel_parameters); + assert!( + self.channel_parameters.is_none() + || self.channel_parameters.as_ref().unwrap() == channel_parameters + ); if self.channel_parameters.is_some() { // The channel parameters were already set and they match, return early. return; @@ -1101,19 +1251,30 @@ impl ChannelSigner for InMemorySigner { } } -const MISSING_PARAMS_ERR: &'static str = "ChannelSigner::provide_channel_parameters must be called before signing operations"; +const MISSING_PARAMS_ERR: &'static str = + "ChannelSigner::provide_channel_parameters must be called before signing operations"; impl EcdsaChannelSigner for InMemorySigner { - fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, _inbound_htlc_preimages: Vec, _outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { + fn sign_counterparty_commitment( + &self, commitment_tx: &CommitmentTransaction, + _inbound_htlc_preimages: Vec, + _outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1, + ) -> Result<(Signature, Vec), ()> { let trusted_tx = commitment_tx.trust(); let keys = trusted_tx.keys(); let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR); - let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey); + let channel_funding_redeemscript = + make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey); let built_tx = trusted_tx.built_transaction(); - let commitment_sig = built_tx.sign_counterparty_commitment(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx); + let commitment_sig = built_tx.sign_counterparty_commitment( + &self.funding_key, + &channel_funding_redeemscript, + self.channel_value_satoshis, + secp_ctx, + ); let commitment_txid = built_tx.txid; let mut htlc_sigs = Vec::with_capacity(commitment_tx.htlcs().len()); @@ -1122,124 +1283,260 @@ impl EcdsaChannelSigner for InMemorySigner { let holder_selected_contest_delay = self.holder_selected_contest_delay().expect(MISSING_PARAMS_ERR); let chan_type = &channel_parameters.channel_type_features; - let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_tx.feerate_per_kw(), holder_selected_contest_delay, htlc, chan_type, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + let htlc_tx = chan_utils::build_htlc_transaction( + &commitment_txid, + commitment_tx.feerate_per_kw(), + holder_selected_contest_delay, + htlc, + chan_type, + &keys.broadcaster_delayed_payment_key, + &keys.revocation_key, + ); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, chan_type, &keys); - let htlc_sighashtype = if chan_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; - let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]); - let holder_htlc_key = chan_utils::derive_private_key(&secp_ctx, &keys.per_commitment_point, &self.htlc_base_key); + let htlc_sighashtype = if chan_type.supports_anchors_zero_fee_htlc_tx() { + EcdsaSighashType::SinglePlusAnyoneCanPay + } else { + EcdsaSighashType::All + }; + let htlc_sighash = hash_to_message!( + &sighash::SighashCache::new(&htlc_tx) + .segwit_signature_hash( + 0, + &htlc_redeemscript, + htlc.amount_msat / 1000, + htlc_sighashtype + ) + .unwrap()[..] + ); + let holder_htlc_key = chan_utils::derive_private_key( + &secp_ctx, + &keys.per_commitment_point, + &self.htlc_base_key, + ); htlc_sigs.push(sign(secp_ctx, &htlc_sighash, &holder_htlc_key)); } Ok((commitment_sig, htlc_sigs)) } - fn sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result { + fn sign_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1, + ) -> Result { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR); - let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey); + let funding_redeemscript = + make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey); let trusted_tx = commitment_tx.trust(); - Ok(trusted_tx.built_transaction().sign_holder_commitment(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, &self, secp_ctx)) - } - - #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] - fn unsafe_sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result { + Ok(trusted_tx.built_transaction().sign_holder_commitment( + &self.funding_key, + &funding_redeemscript, + self.channel_value_satoshis, + &self, + secp_ctx, + )) + } + + #[cfg(any(test, feature = "unsafe_revoked_tx_signing"))] + fn unsafe_sign_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1, + ) -> Result { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR); - let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey); + let funding_redeemscript = + make_funding_redeemscript(&funding_pubkey, &counterparty_keys.funding_pubkey); let trusted_tx = commitment_tx.trust(); - Ok(trusted_tx.built_transaction().sign_holder_commitment(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, &self, secp_ctx)) - } - - fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1) -> Result { - let revocation_key = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key); + Ok(trusted_tx.built_transaction().sign_holder_commitment( + &self.funding_key, + &funding_redeemscript, + self.channel_value_satoshis, + &self, + secp_ctx, + )) + } + + fn sign_justice_revoked_output( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + secp_ctx: &Secp256k1, + ) -> Result { + let revocation_key = chan_utils::derive_private_revocation_key( + &secp_ctx, + &per_commitment_key, + &self.revocation_base_key, + ); let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key); let revocation_pubkey = RevocationKey::from_basepoint( - &secp_ctx, &self.pubkeys().revocation_basepoint, &per_commitment_point, + &secp_ctx, + &self.pubkeys().revocation_basepoint, + &per_commitment_point, ); let witness_script = { let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR); let holder_selected_contest_delay = self.holder_selected_contest_delay().expect(MISSING_PARAMS_ERR); - let counterparty_delayedpubkey = DelayedPaymentKey::from_basepoint(&secp_ctx, &counterparty_keys.delayed_payment_basepoint, &per_commitment_point); - chan_utils::get_revokeable_redeemscript(&revocation_pubkey, holder_selected_contest_delay, &counterparty_delayedpubkey) + let counterparty_delayedpubkey = DelayedPaymentKey::from_basepoint( + &secp_ctx, + &counterparty_keys.delayed_payment_basepoint, + &per_commitment_point, + ); + chan_utils::get_revokeable_redeemscript( + &revocation_pubkey, + holder_selected_contest_delay, + &counterparty_delayedpubkey, + ) }; let mut sighash_parts = sighash::SighashCache::new(justice_tx); - let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)) + let sighash = hash_to_message!( + &sighash_parts + .segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All) + .unwrap()[..] + ); + return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)); } - fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { - let revocation_key = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key); + fn sign_justice_revoked_htlc( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { + let revocation_key = chan_utils::derive_private_revocation_key( + &secp_ctx, + &per_commitment_key, + &self.revocation_base_key, + ); let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key); let revocation_pubkey = RevocationKey::from_basepoint( - &secp_ctx, &self.pubkeys().revocation_basepoint, &per_commitment_point, + &secp_ctx, + &self.pubkeys().revocation_basepoint, + &per_commitment_point, ); let witness_script = { let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR); let counterparty_htlcpubkey = HtlcKey::from_basepoint( - &secp_ctx, &counterparty_keys.htlc_basepoint, &per_commitment_point, + &secp_ctx, + &counterparty_keys.htlc_basepoint, + &per_commitment_point, ); let holder_htlcpubkey = HtlcKey::from_basepoint( - &secp_ctx, &self.pubkeys().htlc_basepoint, &per_commitment_point, + &secp_ctx, + &self.pubkeys().htlc_basepoint, + &per_commitment_point, ); let chan_type = self.channel_type_features().expect(MISSING_PARAMS_ERR); - chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, chan_type, &counterparty_htlcpubkey, &holder_htlcpubkey, &revocation_pubkey) + chan_utils::get_htlc_redeemscript_with_explicit_keys( + &htlc, + chan_type, + &counterparty_htlcpubkey, + &holder_htlcpubkey, + &revocation_pubkey, + ) }; let mut sighash_parts = sighash::SighashCache::new(justice_tx); - let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); - return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)) + let sighash = hash_to_message!( + &sighash_parts + .segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All) + .unwrap()[..] + ); + return Ok(sign_with_aux_rand(secp_ctx, &sighash, &revocation_key, &self)); } fn sign_holder_htlc_transaction( &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result { let witness_script = htlc_descriptor.witness_script(secp_ctx); - let sighash = &sighash::SighashCache::new(&*htlc_tx).segwit_signature_hash( - input, &witness_script, htlc_descriptor.htlc.amount_msat / 1000, EcdsaSighashType::All - ).map_err(|_| ())?; + let sighash = &sighash::SighashCache::new(&*htlc_tx) + .segwit_signature_hash( + input, + &witness_script, + htlc_descriptor.htlc.amount_msat / 1000, + EcdsaSighashType::All, + ) + .map_err(|_| ())?; let our_htlc_private_key = chan_utils::derive_private_key( - &secp_ctx, &htlc_descriptor.per_commitment_point, &self.htlc_base_key + &secp_ctx, + &htlc_descriptor.per_commitment_point, + &self.htlc_base_key, ); - Ok(sign_with_aux_rand(&secp_ctx, &hash_to_message!(sighash.as_byte_array()), &our_htlc_private_key, &self)) + Ok(sign_with_aux_rand( + &secp_ctx, + &hash_to_message!(sighash.as_byte_array()), + &our_htlc_private_key, + &self, + )) } - fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { - let htlc_key = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.htlc_base_key); + fn sign_counterparty_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { + let htlc_key = + chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.htlc_base_key); let revocation_pubkey = RevocationKey::from_basepoint( - &secp_ctx, &self.pubkeys().revocation_basepoint, &per_commitment_point, + &secp_ctx, + &self.pubkeys().revocation_basepoint, + &per_commitment_point, ); let counterparty_keys = self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR); let counterparty_htlcpubkey = HtlcKey::from_basepoint( - &secp_ctx, &counterparty_keys.htlc_basepoint, &per_commitment_point, + &secp_ctx, + &counterparty_keys.htlc_basepoint, + &per_commitment_point, + ); + let htlcpubkey = HtlcKey::from_basepoint( + &secp_ctx, + &self.pubkeys().htlc_basepoint, + &per_commitment_point, ); - let htlcpubkey = HtlcKey::from_basepoint(&secp_ctx, &self.pubkeys().htlc_basepoint, &per_commitment_point); let chan_type = self.channel_type_features().expect(MISSING_PARAMS_ERR); - let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, chan_type, &counterparty_htlcpubkey, &htlcpubkey, &revocation_pubkey); + let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys( + &htlc, + chan_type, + &counterparty_htlcpubkey, + &htlcpubkey, + &revocation_pubkey, + ); let mut sighash_parts = sighash::SighashCache::new(htlc_tx); - let sighash = hash_to_message!(&sighash_parts.segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All).unwrap()[..]); + let sighash = hash_to_message!( + &sighash_parts + .segwit_signature_hash(input, &witness_script, amount, EcdsaSighashType::All) + .unwrap()[..] + ); Ok(sign_with_aux_rand(secp_ctx, &sighash, &htlc_key, &self)) } - fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { + fn sign_closing_transaction( + &self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1, + ) -> Result { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); - let counterparty_funding_key = &self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR).funding_pubkey; - let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, counterparty_funding_key); - Ok(closing_tx.trust().sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx)) + let counterparty_funding_key = + &self.counterparty_pubkeys().expect(MISSING_PARAMS_ERR).funding_pubkey; + let channel_funding_redeemscript = + make_funding_redeemscript(&funding_pubkey, counterparty_funding_key); + Ok(closing_tx.trust().sign( + &self.funding_key, + &channel_funding_redeemscript, + self.channel_value_satoshis, + secp_ctx, + )) } fn sign_holder_anchor_input( &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1, ) -> Result { - let witness_script = chan_utils::get_anchor_redeemscript(&self.holder_channel_pubkeys.funding_pubkey); - let sighash = sighash::SighashCache::new(&*anchor_tx).segwit_signature_hash( - input, &witness_script, ANCHOR_OUTPUT_VALUE_SATOSHI, EcdsaSighashType::All, - ).unwrap(); + let witness_script = + chan_utils::get_anchor_redeemscript(&self.holder_channel_pubkeys.funding_pubkey); + let sighash = sighash::SighashCache::new(&*anchor_tx) + .segwit_signature_hash( + input, + &witness_script, + ANCHOR_OUTPUT_VALUE_SATOSHI, + EcdsaSighashType::All, + ) + .unwrap(); Ok(sign_with_aux_rand(secp_ctx, &hash_to_message!(&sighash[..]), &self.funding_key, &self)) } fn sign_channel_announcement_with_funding_key( - &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 + &self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1, ) -> Result { let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); Ok(secp_ctx.sign_ecdsa(&msghash, &self.funding_key)) @@ -1248,39 +1545,64 @@ impl EcdsaChannelSigner for InMemorySigner { #[cfg(taproot)] impl TaprootChannelSigner for InMemorySigner { - fn generate_local_nonce_pair(&self, commitment_number: u64, secp_ctx: &Secp256k1) -> PublicNonce { + fn generate_local_nonce_pair( + &self, commitment_number: u64, secp_ctx: &Secp256k1, + ) -> PublicNonce { todo!() } - fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1) -> Result<(PartialSignatureWithNonce, Vec), ()> { + fn partially_sign_counterparty_commitment( + &self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, + inbound_htlc_preimages: Vec, + outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1, + ) -> Result<(PartialSignatureWithNonce, Vec), ()> { todo!() } - fn finalize_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1) -> Result { + fn finalize_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, + counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1) -> Result { + fn sign_justice_revoked_output( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { + fn sign_justice_revoked_htlc( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1) -> Result { + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { + fn sign_counterparty_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn partially_sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { + fn partially_sign_closing_transaction( + &self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_holder_anchor_input(&self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1) -> Result { + fn sign_holder_anchor_input( + &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1, + ) -> Result { todo!() } } @@ -1311,7 +1633,10 @@ impl Writeable for InMemorySigner { } } -impl ReadableArgs for InMemorySigner where ES::Target: EntropySource { +impl ReadableArgs for InMemorySigner +where + ES::Target: EntropySource, +{ fn read(reader: &mut R, entropy_source: ES) -> Result { let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION); @@ -1324,9 +1649,14 @@ impl ReadableArgs for InMemorySigner where ES::Target: EntropySou let counterparty_channel_data = Readable::read(reader)?; let channel_value_satoshis = Readable::read(reader)?; let secp_ctx = Secp256k1::signing_only(); - let holder_channel_pubkeys = - InMemorySigner::make_holder_keys(&secp_ctx, &funding_key, &revocation_base_key, - &payment_key, &delayed_payment_base_key, &htlc_base_key); + let holder_channel_pubkeys = InMemorySigner::make_holder_keys( + &secp_ctx, + &funding_key, + &revocation_base_key, + &payment_key, + &delayed_payment_base_key, + &htlc_base_key, + ); let keys_id = Readable::read(reader)?; read_tlv_fields!(reader, {}); @@ -1400,23 +1730,42 @@ impl KeysManager { // Note that when we aren't serializing the key, network doesn't matter match ExtendedPrivKey::new_master(Network::Testnet, seed) { Ok(master_key) => { - let node_secret = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0).unwrap()).expect("Your RNG is busted").private_key; + let node_secret = master_key + .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0).unwrap()) + .expect("Your RNG is busted") + .private_key; let node_id = PublicKey::from_secret_key(&secp_ctx, &node_secret); - let destination_script = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1).unwrap()) { + let destination_script = match master_key + .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1).unwrap()) + { Ok(destination_key) => { - let wpubkey_hash = WPubkeyHash::hash(&ExtendedPubKey::from_priv(&secp_ctx, &destination_key).to_pub().to_bytes()); - Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0) + let wpubkey_hash = WPubkeyHash::hash( + &ExtendedPubKey::from_priv(&secp_ctx, &destination_key) + .to_pub() + .to_bytes(), + ); + Builder::new() + .push_opcode(opcodes::all::OP_PUSHBYTES_0) .push_slice(&wpubkey_hash.to_byte_array()) .into_script() }, Err(_) => panic!("Your RNG is busted"), }; - let shutdown_pubkey = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(2).unwrap()) { - Ok(shutdown_key) => ExtendedPubKey::from_priv(&secp_ctx, &shutdown_key).public_key, + let shutdown_pubkey = match master_key + .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(2).unwrap()) + { + Ok(shutdown_key) => { + ExtendedPubKey::from_priv(&secp_ctx, &shutdown_key).public_key + }, Err(_) => panic!("Your RNG is busted"), }; - let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3).unwrap()).expect("Your RNG is busted"); - let inbound_payment_key: SecretKey = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap()).expect("Your RNG is busted").private_key; + let channel_master_key = master_key + .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3).unwrap()) + .expect("Your RNG is busted"); + let inbound_payment_key: SecretKey = master_key + .ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(5).unwrap()) + .expect("Your RNG is busted") + .private_key; let mut inbound_pmt_key_bytes = [0; 32]; inbound_pmt_key_bytes.copy_from_slice(&inbound_payment_key[..]); @@ -1425,7 +1774,8 @@ impl KeysManager { rand_bytes_engine.input(&starting_time_nanos.to_be_bytes()); rand_bytes_engine.input(seed); rand_bytes_engine.input(b"LDK PRNG Seed"); - let rand_bytes_unique_start = Sha256::from_engine(rand_bytes_engine).to_byte_array(); + let rand_bytes_unique_start = + Sha256::from_engine(rand_bytes_engine).to_byte_array(); let mut res = KeysManager { secp_ctx, @@ -1459,7 +1809,9 @@ impl KeysManager { } /// Derive an old [`WriteableEcdsaChannelSigner`] containing per-channel secrets based on a key derivation parameters. - pub fn derive_channel_keys(&self, channel_value_satoshis: u64, params: &[u8; 32]) -> InMemorySigner { + pub fn derive_channel_keys( + &self, channel_value_satoshis: u64, params: &[u8; 32], + ) -> InMemorySigner { let chan_id = u64::from_be_bytes(params[0..8].try_into().unwrap()); let mut unique_start = Sha256::engine(); unique_start.input(params); @@ -1468,9 +1820,14 @@ impl KeysManager { // We only seriously intend to rely on the channel_master_key for true secure // entropy, everything else just ensures uniqueness. We rely on the unique_start (ie // starting_time provided in the constructor) to be unique. - let child_privkey = self.channel_master_key.ckd_priv(&self.secp_ctx, - ChildNumber::from_hardened_idx((chan_id as u32) % (1 << 31)).expect("key space exhausted") - ).expect("Your RNG is busted"); + let child_privkey = self + .channel_master_key + .ckd_priv( + &self.secp_ctx, + ChildNumber::from_hardened_idx((chan_id as u32) % (1 << 31)) + .expect("key space exhausted"), + ) + .expect("Your RNG is busted"); unique_start.input(&child_privkey.private_key[..]); let seed = Sha256::from_engine(unique_start).to_byte_array(); @@ -1487,8 +1844,9 @@ impl KeysManager { sha.input(&seed); sha.input(&$prev_key[..]); sha.input(&$info[..]); - SecretKey::from_slice(&Sha256::from_engine(sha).to_byte_array()).expect("SHA-256 is busted") - }} + SecretKey::from_slice(&Sha256::from_engine(sha).to_byte_array()) + .expect("SHA-256 is busted") + }}; } let funding_key = key_step!(b"funding key", commitment_seed); let revocation_base_key = key_step!(b"revocation base key", funding_key); @@ -1519,48 +1877,94 @@ impl KeysManager { /// /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used /// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`]. - pub fn sign_spendable_outputs_psbt(&self, descriptors: &[&SpendableOutputDescriptor], mut psbt: PartiallySignedTransaction, secp_ctx: &Secp256k1) -> Result { + pub fn sign_spendable_outputs_psbt( + &self, descriptors: &[&SpendableOutputDescriptor], mut psbt: PartiallySignedTransaction, + secp_ctx: &Secp256k1, + ) -> Result { let mut keys_cache: Option<(InMemorySigner, [u8; 32])> = None; for outp in descriptors { match outp { SpendableOutputDescriptor::StaticPaymentOutput(descriptor) => { - let input_idx = psbt.unsigned_tx.input.iter().position(|i| i.previous_output == descriptor.outpoint.into_bitcoin_outpoint()).ok_or(())?; - if keys_cache.is_none() || keys_cache.as_ref().unwrap().1 != descriptor.channel_keys_id { - let mut signer = self.derive_channel_keys(descriptor.channel_value_satoshis, &descriptor.channel_keys_id); - if let Some(channel_params) = descriptor.channel_transaction_parameters.as_ref() { + let input_idx = psbt + .unsigned_tx + .input + .iter() + .position(|i| { + i.previous_output == descriptor.outpoint.into_bitcoin_outpoint() + }) + .ok_or(())?; + if keys_cache.is_none() + || keys_cache.as_ref().unwrap().1 != descriptor.channel_keys_id + { + let mut signer = self.derive_channel_keys( + descriptor.channel_value_satoshis, + &descriptor.channel_keys_id, + ); + if let Some(channel_params) = + descriptor.channel_transaction_parameters.as_ref() + { signer.provide_channel_parameters(channel_params); } keys_cache = Some((signer, descriptor.channel_keys_id)); } - let witness = keys_cache.as_ref().unwrap().0.sign_counterparty_payment_input(&psbt.unsigned_tx, input_idx, &descriptor, &secp_ctx)?; + let witness = keys_cache.as_ref().unwrap().0.sign_counterparty_payment_input( + &psbt.unsigned_tx, + input_idx, + &descriptor, + &secp_ctx, + )?; psbt.inputs[input_idx].final_script_witness = Some(witness); }, SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) => { - let input_idx = psbt.unsigned_tx.input.iter().position(|i| i.previous_output == descriptor.outpoint.into_bitcoin_outpoint()).ok_or(())?; - if keys_cache.is_none() || keys_cache.as_ref().unwrap().1 != descriptor.channel_keys_id { + let input_idx = psbt + .unsigned_tx + .input + .iter() + .position(|i| { + i.previous_output == descriptor.outpoint.into_bitcoin_outpoint() + }) + .ok_or(())?; + if keys_cache.is_none() + || keys_cache.as_ref().unwrap().1 != descriptor.channel_keys_id + { keys_cache = Some(( - self.derive_channel_keys(descriptor.channel_value_satoshis, &descriptor.channel_keys_id), - descriptor.channel_keys_id)); + self.derive_channel_keys( + descriptor.channel_value_satoshis, + &descriptor.channel_keys_id, + ), + descriptor.channel_keys_id, + )); } - let witness = keys_cache.as_ref().unwrap().0.sign_dynamic_p2wsh_input(&psbt.unsigned_tx, input_idx, &descriptor, &secp_ctx)?; + let witness = keys_cache.as_ref().unwrap().0.sign_dynamic_p2wsh_input( + &psbt.unsigned_tx, + input_idx, + &descriptor, + &secp_ctx, + )?; psbt.inputs[input_idx].final_script_witness = Some(witness); }, SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output, .. } => { - let input_idx = psbt.unsigned_tx.input.iter().position(|i| i.previous_output == outpoint.into_bitcoin_outpoint()).ok_or(())?; - let derivation_idx = if output.script_pubkey == self.destination_script { - 1 - } else { - 2 - }; + let input_idx = psbt + .unsigned_tx + .input + .iter() + .position(|i| i.previous_output == outpoint.into_bitcoin_outpoint()) + .ok_or(())?; + let derivation_idx = + if output.script_pubkey == self.destination_script { 1 } else { 2 }; let secret = { // Note that when we aren't serializing the key, network doesn't matter match ExtendedPrivKey::new_master(Network::Testnet, &self.seed) { Ok(master_key) => { - match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(derivation_idx).expect("key space exhausted")) { + match master_key.ckd_priv( + &secp_ctx, + ChildNumber::from_hardened_idx(derivation_idx) + .expect("key space exhausted"), + ) { Ok(key) => key, Err(_) => panic!("Your RNG is busted"), } - } + }, Err(_) => panic!("Your rng is busted"), } }; @@ -1568,16 +1972,31 @@ impl KeysManager { if derivation_idx == 2 { assert_eq!(pubkey.inner, self.shutdown_pubkey); } - let witness_script = bitcoin::Address::p2pkh(&pubkey, Network::Testnet).script_pubkey(); - let payment_script = bitcoin::Address::p2wpkh(&pubkey, Network::Testnet).expect("uncompressed key found").script_pubkey(); - - if payment_script != output.script_pubkey { return Err(()); }; + let witness_script = + bitcoin::Address::p2pkh(&pubkey, Network::Testnet).script_pubkey(); + let payment_script = bitcoin::Address::p2wpkh(&pubkey, Network::Testnet) + .expect("uncompressed key found") + .script_pubkey(); + + if payment_script != output.script_pubkey { + return Err(()); + }; - let sighash = hash_to_message!(&sighash::SighashCache::new(&psbt.unsigned_tx).segwit_signature_hash(input_idx, &witness_script, output.value, EcdsaSighashType::All).unwrap()[..]); + let sighash = hash_to_message!( + &sighash::SighashCache::new(&psbt.unsigned_tx) + .segwit_signature_hash( + input_idx, + &witness_script, + output.value, + EcdsaSighashType::All + ) + .unwrap()[..] + ); let sig = sign_with_aux_rand(secp_ctx, &sighash, &secret.private_key, &self); let mut sig_ser = sig.serialize_der().to_vec(); sig_ser.push(EcdsaSighashType::All as u8); - let witness = Witness::from_slice(&[&sig_ser, &pubkey.inner.serialize().to_vec()]); + let witness = + Witness::from_slice(&[&sig_ser, &pubkey.inner.serialize().to_vec()]); psbt.inputs[input_idx].final_script_witness = Some(witness); }, } @@ -1603,8 +2022,19 @@ impl KeysManager { /// /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used /// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`]. - pub fn spend_spendable_outputs(&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec, change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32, locktime: Option, secp_ctx: &Secp256k1) -> Result { - let (mut psbt, expected_max_weight) = SpendableOutputDescriptor::create_spendable_outputs_psbt(descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, locktime)?; + pub fn spend_spendable_outputs( + &self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec, + change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32, + locktime: Option, secp_ctx: &Secp256k1, + ) -> Result { + let (mut psbt, expected_max_weight) = + SpendableOutputDescriptor::create_spendable_outputs_psbt( + descriptors, + outputs, + change_destination_script, + feerate_sat_per_1000_weight, + locktime, + )?; psbt = self.sign_spendable_outputs_psbt(descriptors, psbt, secp_ctx)?; let spend_tx = psbt.extract_tx(); @@ -1612,7 +2042,9 @@ impl KeysManager { debug_assert!(expected_max_weight >= spend_tx.weight().to_wu()); // Note that witnesses with a signature vary somewhat in size, so allow // `expected_max_weight` to overshoot by up to 3 bytes per input. - debug_assert!(expected_max_weight <= spend_tx.weight().to_wu() + descriptors.len() as u64 * 3); + debug_assert!( + expected_max_weight <= spend_tx.weight().to_wu() + descriptors.len() as u64 * 3 + ); Ok(spend_tx) } @@ -1628,14 +2060,16 @@ impl NodeSigner for KeysManager { fn get_node_id(&self, recipient: Recipient) -> Result { match recipient { Recipient::Node => Ok(self.node_id.clone()), - Recipient::PhantomNode => Err(()) + Recipient::PhantomNode => Err(()), } } - fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result { + fn ecdh( + &self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>, + ) -> Result { let mut node_secret = match recipient { Recipient::Node => Ok(self.node_secret.clone()), - Recipient::PhantomNode => Err(()) + Recipient::PhantomNode => Err(()), }?; if let Some(tweak) = tweak { node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?; @@ -1647,17 +2081,22 @@ impl NodeSigner for KeysManager { self.inbound_payment_key.clone() } - fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { + fn sign_invoice( + &self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient, + ) -> Result { let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data); let secret = match recipient { Recipient::Node => Ok(&self.node_secret), - Recipient::PhantomNode => Err(()) + Recipient::PhantomNode => Err(()), }?; - Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage).to_byte_array()), secret)) + Ok(self.secp_ctx.sign_ecdsa_recoverable( + &hash_to_message!(&Sha256::hash(&preimage).to_byte_array()), + secret, + )) } fn sign_bolt12_invoice_request( - &self, invoice_request: &UnsignedInvoiceRequest + &self, invoice_request: &UnsignedInvoiceRequest, ) -> Result { let message = invoice_request.tagged_hash().as_digest(); let keys = KeyPair::from_secret_key(&self.secp_ctx, &self.node_secret); @@ -1666,7 +2105,7 @@ impl NodeSigner for KeysManager { } fn sign_bolt12_invoice( - &self, invoice: &UnsignedBolt12Invoice + &self, invoice: &UnsignedBolt12Invoice, ) -> Result { let message = invoice.tagged_hash().as_digest(); let keys = KeyPair::from_secret_key(&self.secp_ctx, &self.node_secret); @@ -1685,7 +2124,9 @@ impl SignerProvider for KeysManager { #[cfg(taproot)] type TaprootSigner = InMemorySigner; - fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] { + fn generate_channel_keys_id( + &self, _inbound: bool, _channel_value_satoshis: u64, user_channel_id: u128, + ) -> [u8; 32] { let child_idx = self.channel_child_index.fetch_add(1, Ordering::AcqRel); // `child_idx` is the only thing guaranteed to make each channel unique without a restart // (though `user_channel_id` should help, depending on user behavior). If it manages to @@ -1701,7 +2142,9 @@ impl SignerProvider for KeysManager { id } - fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::EcdsaSigner { + fn derive_channel_signer( + &self, channel_value_satoshis: u64, channel_keys_id: [u8; 32], + ) -> Self::EcdsaSigner { self.derive_channel_keys(channel_value_satoshis, &channel_keys_id) } @@ -1760,7 +2203,9 @@ impl NodeSigner for PhantomKeysManager { } } - fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result { + fn ecdh( + &self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>, + ) -> Result { let mut node_secret = match recipient { Recipient::Node => self.inner.node_secret.clone(), Recipient::PhantomNode => self.phantom_secret.clone(), @@ -1775,23 +2220,28 @@ impl NodeSigner for PhantomKeysManager { self.inbound_payment_key.clone() } - fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { + fn sign_invoice( + &self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient, + ) -> Result { let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data); let secret = match recipient { Recipient::Node => &self.inner.node_secret, Recipient::PhantomNode => &self.phantom_secret, }; - Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage).to_byte_array()), secret)) + Ok(self.inner.secp_ctx.sign_ecdsa_recoverable( + &hash_to_message!(&Sha256::hash(&preimage).to_byte_array()), + secret, + )) } fn sign_bolt12_invoice_request( - &self, invoice_request: &UnsignedInvoiceRequest + &self, invoice_request: &UnsignedInvoiceRequest, ) -> Result { self.inner.sign_bolt12_invoice_request(invoice_request) } fn sign_bolt12_invoice( - &self, invoice: &UnsignedBolt12Invoice + &self, invoice: &UnsignedBolt12Invoice, ) -> Result { self.inner.sign_bolt12_invoice(invoice) } @@ -1806,11 +2256,15 @@ impl SignerProvider for PhantomKeysManager { #[cfg(taproot)] type TaprootSigner = InMemorySigner; - fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] { + fn generate_channel_keys_id( + &self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128, + ) -> [u8; 32] { self.inner.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id) } - fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::EcdsaSigner { + fn derive_channel_signer( + &self, channel_value_satoshis: u64, channel_keys_id: [u8; 32], + ) -> Self::EcdsaSigner { self.inner.derive_channel_signer(channel_value_satoshis, channel_keys_id) } @@ -1839,9 +2293,15 @@ impl PhantomKeysManager { /// same across restarts, or else inbound payments may fail. /// /// [phantom node payments]: PhantomKeysManager - pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32, cross_node_seed: &[u8; 32]) -> Self { + pub fn new( + seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32, + cross_node_seed: &[u8; 32], + ) -> Self { let inner = KeysManager::new(seed, starting_time_secs, starting_time_nanos); - let (inbound_key, phantom_key) = hkdf_extract_expand_twice(b"LDK Inbound and Phantom Payment Key Expansion", cross_node_seed); + let (inbound_key, phantom_key) = hkdf_extract_expand_twice( + b"LDK Inbound and Phantom Payment Key Expansion", + cross_node_seed, + ); let phantom_secret = SecretKey::from_slice(&phantom_key).unwrap(); let phantom_node_id = PublicKey::from_secret_key(&inner.secp_ctx, &phantom_secret); Self { @@ -1853,12 +2313,25 @@ impl PhantomKeysManager { } /// See [`KeysManager::spend_spendable_outputs`] for documentation on this method. - pub fn spend_spendable_outputs(&self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec, change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32, locktime: Option, secp_ctx: &Secp256k1) -> Result { - self.inner.spend_spendable_outputs(descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, locktime, secp_ctx) + pub fn spend_spendable_outputs( + &self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec, + change_destination_script: ScriptBuf, feerate_sat_per_1000_weight: u32, + locktime: Option, secp_ctx: &Secp256k1, + ) -> Result { + self.inner.spend_spendable_outputs( + descriptors, + outputs, + change_destination_script, + feerate_sat_per_1000_weight, + locktime, + secp_ctx, + ) } /// See [`KeysManager::derive_channel_keys`] for documentation on this method. - pub fn derive_channel_keys(&self, channel_value_satoshis: u64, params: &[u8; 32]) -> InMemorySigner { + pub fn derive_channel_keys( + &self, channel_value_satoshis: u64, params: &[u8; 32], + ) -> InMemorySigner { self.inner.derive_channel_keys(channel_value_satoshis, params) } @@ -1887,10 +2360,7 @@ pub struct RandomBytes { impl RandomBytes { /// Creates a new instance using the given seed. pub fn new(seed: [u8; 32]) -> Self { - Self { - seed, - index: AtomicCounter::new(), - } + Self { seed, index: AtomicCounter::new() } } } @@ -1911,13 +2381,13 @@ pub fn dyn_sign() { #[cfg(ldk_bench)] pub mod benches { - use std::sync::{Arc, mpsc}; + use crate::sign::{EntropySource, KeysManager}; + use bitcoin::blockdata::constants::genesis_block; + use bitcoin::Network; use std::sync::mpsc::TryRecvError; + use std::sync::{mpsc, Arc}; use std::thread; use std::time::Duration; - use bitcoin::blockdata::constants::genesis_block; - use bitcoin::Network; - use crate::sign::{EntropySource, KeysManager}; use criterion::Criterion; @@ -1931,24 +2401,23 @@ pub mod benches { for _ in 1..5 { let keys_manager_clone = Arc::clone(&keys_manager); let (stop_sender, stop_receiver) = mpsc::channel(); - let handle = thread::spawn(move || { - loop { - keys_manager_clone.get_secure_random_bytes(); - match stop_receiver.try_recv() { - Ok(_) | Err(TryRecvError::Disconnected) => { - println!("Terminating."); - break; - } - Err(TryRecvError::Empty) => {} - } + let handle = thread::spawn(move || loop { + keys_manager_clone.get_secure_random_bytes(); + match stop_receiver.try_recv() { + Ok(_) | Err(TryRecvError::Disconnected) => { + println!("Terminating."); + break; + }, + Err(TryRecvError::Empty) => {}, } }); handles.push(handle); stops.push(stop_sender); } - bench.bench_function("get_secure_random_bytes", |b| b.iter(|| - keys_manager.get_secure_random_bytes())); + bench.bench_function("get_secure_random_bytes", |b| { + b.iter(|| keys_manager.get_secure_random_bytes()) + }); for stop in stops { let _ = stop.send(()); diff --git a/lightning/src/sign/taproot.rs b/lightning/src/sign/taproot.rs index 230383f4f7d..7536b68a879 100644 --- a/lightning/src/sign/taproot.rs +++ b/lightning/src/sign/taproot.rs @@ -3,11 +3,13 @@ use alloc::vec::Vec; use bitcoin::blockdata::transaction::Transaction; use bitcoin::secp256k1; -use bitcoin::secp256k1::{PublicKey, schnorr::Signature, Secp256k1, SecretKey}; +use bitcoin::secp256k1::{schnorr::Signature, PublicKey, Secp256k1, SecretKey}; use musig2::types::{PartialSignature, PublicNonce}; -use crate::ln::chan_utils::{ClosingTransaction, CommitmentTransaction, HolderCommitmentTransaction, HTLCOutputInCommitment}; +use crate::ln::chan_utils::{ + ClosingTransaction, CommitmentTransaction, HTLCOutputInCommitment, HolderCommitmentTransaction, +}; use crate::ln::msgs::PartialSignatureWithNonce; use crate::ln::PaymentPreimage; use crate::sign::{ChannelSigner, HTLCDescriptor}; @@ -18,7 +20,9 @@ use crate::sign::{ChannelSigner, HTLCDescriptor}; pub trait TaprootChannelSigner: ChannelSigner { /// Generate a local nonce pair, which requires committing to ahead of time. /// The counterparty needs the public nonce generated herein to compute a partial signature. - fn generate_local_nonce_pair(&self, commitment_number: u64, secp_ctx: &Secp256k1) -> PublicNonce; + fn generate_local_nonce_pair( + &self, commitment_number: u64, secp_ctx: &Secp256k1, + ) -> PublicNonce; /// Create a signature for a counterparty's commitment transaction and associated HTLC transactions. /// @@ -36,8 +40,8 @@ pub trait TaprootChannelSigner: ChannelSigner { /// irrelevant or duplicate preimages. // // TODO: Document the things someone using this interface should enforce before signing. - fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, - commitment_tx: &CommitmentTransaction, + fn partially_sign_counterparty_commitment( + &self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1, ) -> Result<(PartialSignatureWithNonce, Vec), ()>; @@ -53,9 +57,10 @@ pub trait TaprootChannelSigner: ChannelSigner { /// An external signer implementation should check that the commitment has not been revoked. /// // TODO: Document the things someone using this interface should enforce before signing. - fn finalize_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, + fn finalize_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, counterparty_partial_signature: PartialSignatureWithNonce, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result; /// Create a signature for the given input in a transaction spending an HTLC transaction output @@ -72,8 +77,9 @@ pub trait TaprootChannelSigner: ChannelSigner { /// revoked the state which they eventually broadcast. It's not a _holder_ secret key and does /// not allow the spending of any funds by itself (you need our holder `revocation_secret` to do /// so). - fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, - per_commitment_key: &SecretKey, secp_ctx: &Secp256k1, + fn sign_justice_revoked_output( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + secp_ctx: &Secp256k1, ) -> Result; /// Create a signature for the given input in a transaction spending a commitment transaction @@ -94,9 +100,10 @@ pub trait TaprootChannelSigner: ChannelSigner { /// /// `htlc` holds HTLC elements (hash, timelock), thus changing the format of the witness script /// (which is committed to in the BIP 341 signatures). - fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, - per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, - secp_ctx: &Secp256k1) -> Result; + fn sign_justice_revoked_htlc( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result; /// Computes the signature for a commitment transaction's HTLC output used as an input within /// `htlc_tx`, which spends the commitment transaction at index `input`. The signature returned @@ -109,8 +116,9 @@ pub trait TaprootChannelSigner: ChannelSigner { /// /// [`TapSighashType::Default`]: bitcoin::sighash::TapSighashType::Default /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor - fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, - htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1, + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1, ) -> Result; /// Create a signature for a claiming transaction for a HTLC output on a counterparty's commitment @@ -130,16 +138,18 @@ pub trait TaprootChannelSigner: ChannelSigner { /// detected onchain. It has been generated by our counterparty and is used to derive /// channel state keys, which are then included in the witness script and committed to in the /// BIP 341 signature. - fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, - per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, - secp_ctx: &Secp256k1) -> Result; + fn sign_counterparty_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result; /// Create a signature for a (proposed) closing transaction. /// /// Note that, due to rounding, there may be one "missing" satoshi, and either party may have /// chosen to forgo their output as dust. - fn partially_sign_closing_transaction(&self, closing_tx: &ClosingTransaction, - secp_ctx: &Secp256k1) -> Result; + fn partially_sign_closing_transaction( + &self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1, + ) -> Result; /// Computes the signature for a commitment transaction's anchor output used as an /// input within `anchor_tx`, which spends the commitment transaction, at index `input`. diff --git a/lightning/src/sign/type_resolver.rs b/lightning/src/sign/type_resolver.rs index 2a122da3447..fad8c0ac96c 100644 --- a/lightning/src/sign/type_resolver.rs +++ b/lightning/src/sign/type_resolver.rs @@ -1,14 +1,20 @@ -use core::ops::Deref; use crate::sign::{ChannelSigner, SignerProvider}; +use core::ops::Deref; -pub(crate) enum ChannelSignerType where SP::Target: SignerProvider { +pub(crate) enum ChannelSignerType +where + SP::Target: SignerProvider, +{ // in practice, this will only ever be an EcdsaChannelSigner (specifically, Writeable) Ecdsa(::EcdsaSigner), #[cfg(taproot)] Taproot(::TaprootSigner), } -impl ChannelSignerType where SP::Target: SignerProvider { +impl ChannelSignerType +where + SP::Target: SignerProvider, +{ pub(crate) fn as_ref(&self) -> &dyn ChannelSigner { match self { ChannelSignerType::Ecdsa(ecs) => ecs, @@ -29,15 +35,17 @@ impl ChannelSignerType where SP::Target: SignerProvider { pub(crate) fn as_ecdsa(&self) -> Option<&::EcdsaSigner> { match self { ChannelSignerType::Ecdsa(ecs) => Some(ecs), - _ => None + _ => None, } } #[allow(unused)] - pub(crate) fn as_mut_ecdsa(&mut self) -> Option<&mut ::EcdsaSigner> { + pub(crate) fn as_mut_ecdsa( + &mut self, + ) -> Option<&mut ::EcdsaSigner> { match self { ChannelSignerType::Ecdsa(ecs) => Some(ecs), - _ => None + _ => None, } } } diff --git a/lightning/src/sync/debug_sync.rs b/lightning/src/sync/debug_sync.rs index b9f015af656..ef62e700d66 100644 --- a/lightning/src/sync/debug_sync.rs +++ b/lightning/src/sync/debug_sync.rs @@ -5,26 +5,30 @@ use core::time::Duration; use std::cell::RefCell; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Condvar as StdCondvar; use std::sync::Mutex as StdMutex; use std::sync::MutexGuard as StdMutexGuard; use std::sync::RwLock as StdRwLock; use std::sync::RwLockReadGuard as StdRwLockReadGuard; use std::sync::RwLockWriteGuard as StdRwLockWriteGuard; -use std::sync::Condvar as StdCondvar; pub use std::sync::WaitTimeoutResult; use crate::prelude::HashMap; -use super::{LockTestExt, LockHeldState}; +use super::{LockHeldState, LockTestExt}; #[cfg(feature = "backtrace")] use {crate::prelude::hash_map, backtrace::Backtrace, std::sync::Once}; #[cfg(not(feature = "backtrace"))] -struct Backtrace{} +struct Backtrace {} #[cfg(not(feature = "backtrace"))] -impl Backtrace { fn new() -> Backtrace { Backtrace {} } } +impl Backtrace { + fn new() -> Backtrace { + Backtrace {} + } +} pub type LockResult = Result; @@ -37,22 +41,30 @@ impl Condvar { Condvar { inner: StdCondvar::new() } } - pub fn wait_while<'a, T, F: FnMut(&mut T) -> bool>(&'a self, guard: MutexGuard<'a, T>, condition: F) - -> LockResult> { + pub fn wait_while<'a, T, F: FnMut(&mut T) -> bool>( + &'a self, guard: MutexGuard<'a, T>, condition: F, + ) -> LockResult> { let mutex: &'a Mutex = guard.mutex; - self.inner.wait_while(guard.into_inner(), condition).map(|lock| MutexGuard { mutex, lock }) + self.inner + .wait_while(guard.into_inner(), condition) + .map(|lock| MutexGuard { mutex, lock }) .map_err(|_| ()) } #[allow(unused)] - pub fn wait_timeout_while<'a, T, F: FnMut(&mut T) -> bool>(&'a self, guard: MutexGuard<'a, T>, dur: Duration, condition: F) - -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> { + pub fn wait_timeout_while<'a, T, F: FnMut(&mut T) -> bool>( + &'a self, guard: MutexGuard<'a, T>, dur: Duration, condition: F, + ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> { let mutex = guard.mutex; - self.inner.wait_timeout_while(guard.into_inner(), dur, condition).map_err(|_| ()) + self.inner + .wait_timeout_while(guard.into_inner(), dur, condition) + .map_err(|_| ()) .map(|(lock, e)| (MutexGuard { mutex, lock }, e)) } - pub fn notify_all(&self) { self.inner.notify_all(); } + pub fn notify_all(&self) { + self.inner.notify_all(); + } } thread_local! { @@ -99,12 +111,17 @@ fn locate_call_symbol(backtrace: &Backtrace) -> (String, Option) { symbol_after_latest_debug_sync = Some(symbol); found_debug_sync = false; } - } else { found_debug_sync = true; } + } else { + found_debug_sync = true; + } } } } let symbol = symbol_after_latest_debug_sync.expect("Couldn't find lock call symbol"); - (format!("{}:{}", symbol.filename().unwrap().display(), symbol.lineno().unwrap()), symbol.colno()) + ( + format!("{}:{}", symbol.filename().unwrap().display(), symbol.lineno().unwrap()), + symbol.colno(), + ) } impl LockMetadata { @@ -122,16 +139,20 @@ impl LockMetadata { { let (lock_constr_location, lock_constr_colno) = locate_call_symbol(&res._lock_construction_bt); - LOCKS_INIT.call_once(|| { unsafe { LOCKS = Some(StdMutex::new(HashMap::new())); } }); + LOCKS_INIT.call_once(|| unsafe { + LOCKS = Some(StdMutex::new(HashMap::new())); + }); let mut locks = unsafe { LOCKS.as_ref() }.unwrap().lock().unwrap(); match locks.entry(lock_constr_location) { hash_map::Entry::Occupied(e) => { assert_eq!(lock_constr_colno, locate_call_symbol(&e.get()._lock_construction_bt).1, "Because Windows doesn't support column number results in backtraces, we cannot construct two mutexes on the same line or we risk lockorder detection false positives."); - return Arc::clone(e.get()) + return Arc::clone(e.get()); + }, + hash_map::Entry::Vacant(e) => { + e.insert(Arc::clone(&res)); }, - hash_map::Entry::Vacant(e) => { e.insert(Arc::clone(&res)); }, } } res @@ -211,7 +232,8 @@ impl LockMetadata { let mut locked_before = this.locked_before.lock().unwrap(); for (locked_idx, locked) in held.borrow().iter() { if !locked_before.contains_key(locked_idx) { - let lockdep = LockDep { lock: Arc::clone(locked), _lockdep_trace: Backtrace::new() }; + let lockdep = + LockDep { lock: Arc::clone(locked), _lockdep_trace: Backtrace::new() }; locked_before.insert(*locked_idx, lockdep); } } @@ -280,7 +302,8 @@ impl Mutex { } pub fn try_lock<'a>(&'a self) -> LockResult> { - let res = self.inner.try_lock().map(|lock| MutexGuard { mutex: self, lock }).map_err(|_| ()); + let res = + self.inner.try_lock().map(|lock| MutexGuard { mutex: self, lock }).map_err(|_| ()); if res.is_ok() { LockMetadata::try_locked(&self.deps); } @@ -374,7 +397,11 @@ impl RwLock { } pub fn try_write<'a>(&'a self) -> LockResult> { - let res = self.inner.try_write().map(|guard| RwLockWriteGuard { lock: self, guard }).map_err(|_| ()); + let res = self + .inner + .try_write() + .map(|guard| RwLockWriteGuard { lock: self, guard }) + .map_err(|_| ()); if res.is_ok() { LockMetadata::try_locked(&self.deps); } diff --git a/lightning/src/sync/fairrwlock.rs b/lightning/src/sync/fairrwlock.rs index 23b8c23db28..d97370090cd 100644 --- a/lightning/src/sync/fairrwlock.rs +++ b/lightning/src/sync/fairrwlock.rs @@ -1,6 +1,6 @@ -use std::sync::{LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockResult}; -use std::sync::atomic::{AtomicUsize, Ordering}; use super::{LockHeldState, LockTestExt}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockResult}; /// Rust libstd's RwLock does not provide any fairness guarantees (and, in fact, when used on /// Linux with pthreads under the hood, readers trivially and completely starve writers). diff --git a/lightning/src/sync/mod.rs b/lightning/src/sync/mod.rs index 348bd90274a..0d0a76e3f2e 100644 --- a/lightning/src/sync/mod.rs +++ b/lightning/src/sync/mod.rs @@ -31,24 +31,35 @@ mod test_lockorder_checks; #[cfg(all(feature = "std", any(ldk_bench, not(test))))] pub(crate) mod fairrwlock; #[cfg(all(feature = "std", any(ldk_bench, not(test))))] -pub use {std::sync::{Arc, Mutex, Condvar, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}, fairrwlock::FairRwLock}; +pub use { + fairrwlock::FairRwLock, + std::sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}, +}; #[cfg(all(feature = "std", any(ldk_bench, not(test))))] mod ext_impl { use super::*; impl<'a, T: 'a> LockTestExt<'a> for Mutex { #[inline] - fn held_by_thread(&self) -> LockHeldState { LockHeldState::Unsupported } + fn held_by_thread(&self) -> LockHeldState { + LockHeldState::Unsupported + } type ExclLock = MutexGuard<'a, T>; #[inline] - fn unsafe_well_ordered_double_lock_self(&'a self) -> MutexGuard { self.lock().unwrap() } + fn unsafe_well_ordered_double_lock_self(&'a self) -> MutexGuard { + self.lock().unwrap() + } } impl<'a, T: 'a> LockTestExt<'a> for RwLock { #[inline] - fn held_by_thread(&self) -> LockHeldState { LockHeldState::Unsupported } + fn held_by_thread(&self) -> LockHeldState { + LockHeldState::Unsupported + } type ExclLock = RwLockWriteGuard<'a, T>; #[inline] - fn unsafe_well_ordered_double_lock_self(&'a self) -> RwLockWriteGuard { self.write().unwrap() } + fn unsafe_well_ordered_double_lock_self(&'a self) -> RwLockWriteGuard { + self.write().unwrap() + } } } diff --git a/lightning/src/sync/nostd_sync.rs b/lightning/src/sync/nostd_sync.rs index 0f92bd6caa3..2ce8d16d7ea 100644 --- a/lightning/src/sync/nostd_sync.rs +++ b/lightning/src/sync/nostd_sync.rs @@ -1,12 +1,12 @@ +use super::{LockHeldState, LockTestExt}; pub use ::alloc::sync::Arc; +use core::cell::{Ref, RefCell, RefMut}; use core::ops::{Deref, DerefMut}; -use core::cell::{RefCell, Ref, RefMut}; -use super::{LockTestExt, LockHeldState}; pub type LockResult = Result; pub struct Mutex { - inner: RefCell + inner: RefCell, } #[must_use = "if unused the Mutex will immediately unlock"] @@ -45,16 +45,21 @@ impl Mutex { impl<'a, T: 'a> LockTestExt<'a> for Mutex { #[inline] fn held_by_thread(&self) -> LockHeldState { - if self.inner.try_borrow_mut().is_err() { return LockHeldState::HeldByThread; } - else { return LockHeldState::NotHeldByThread; } + if self.inner.try_borrow_mut().is_err() { + return LockHeldState::HeldByThread; + } else { + return LockHeldState::NotHeldByThread; + } } type ExclLock = MutexGuard<'a, T>; #[inline] - fn unsafe_well_ordered_double_lock_self(&'a self) -> MutexGuard { self.lock().unwrap() } + fn unsafe_well_ordered_double_lock_self(&'a self) -> MutexGuard { + self.lock().unwrap() + } } pub struct RwLock { - inner: RefCell + inner: RefCell, } pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { @@ -103,7 +108,7 @@ impl RwLock { pub fn try_write<'a>(&'a self) -> LockResult> { match self.inner.try_borrow_mut() { Ok(lock) => Ok(RwLockWriteGuard { lock }), - Err(_) => Err(()) + Err(_) => Err(()), } } } @@ -111,12 +116,17 @@ impl RwLock { impl<'a, T: 'a> LockTestExt<'a> for RwLock { #[inline] fn held_by_thread(&self) -> LockHeldState { - if self.inner.try_borrow_mut().is_err() { return LockHeldState::HeldByThread; } - else { return LockHeldState::NotHeldByThread; } + if self.inner.try_borrow_mut().is_err() { + return LockHeldState::HeldByThread; + } else { + return LockHeldState::NotHeldByThread; + } } type ExclLock = RwLockWriteGuard<'a, T>; #[inline] - fn unsafe_well_ordered_double_lock_self(&'a self) -> RwLockWriteGuard { self.write().unwrap() } + fn unsafe_well_ordered_double_lock_self(&'a self) -> RwLockWriteGuard { + self.write().unwrap() + } } pub type FairRwLock = RwLock; diff --git a/lightning/src/sync/test_lockorder_checks.rs b/lightning/src/sync/test_lockorder_checks.rs index 96e497d4439..91826342f8a 100644 --- a/lightning/src/sync/test_lockorder_checks.rs +++ b/lightning/src/sync/test_lockorder_checks.rs @@ -1,4 +1,4 @@ -use crate::sync::debug_sync::{RwLock, Mutex}; +use crate::sync::debug_sync::{Mutex, RwLock}; use super::{LockHeldState, LockTestExt}; diff --git a/lightning/src/util/atomic_counter.rs b/lightning/src/util/atomic_counter.rs index d2e01411313..5207403018d 100644 --- a/lightning/src/util/atomic_counter.rs +++ b/lightning/src/util/atomic_counter.rs @@ -1,7 +1,9 @@ //! A simple atomic counter that uses AtomicUsize to give a u64 counter. #[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))] -compile_error!("We need at least 32-bit pointers for atomic counter (and to have enough memory to run LDK)"); +compile_error!( + "We need at least 32-bit pointers for atomic counter (and to have enough memory to run LDK)" +); use core::sync::atomic::{AtomicUsize, Ordering}; @@ -15,10 +17,7 @@ pub(crate) struct AtomicCounter { impl AtomicCounter { pub(crate) fn new() -> Self { - Self { - counter_low: AtomicUsize::new(0), - counter_high: AtomicUsize::new(0), - } + Self { counter_low: AtomicUsize::new(0), counter_high: AtomicUsize::new(0) } } pub(crate) fn get_increment(&self) -> u64 { let low = self.counter_low.fetch_add(1, Ordering::AcqRel) as u64; diff --git a/lightning/src/util/base32.rs b/lightning/src/util/base32.rs index 2e66d59383f..22c2679904f 100644 --- a/lightning/src/util/base32.rs +++ b/lightning/src/util/base32.rs @@ -6,7 +6,6 @@ // Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or // MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT) at your option. - use crate::prelude::*; /// RFC4648 encoding table @@ -33,10 +32,10 @@ pub enum Alphabet { /// RFC4648 encoding. RFC4648 { /// Whether to use padding. - padding: bool + padding: bool, }, /// Zbase32 encoding. - ZBase32 + ZBase32, } impl Alphabet { @@ -60,9 +59,7 @@ impl Alphabet { } ret }, - Self::ZBase32 => { - Self::encode_data(data, ZBASE_ALPHABET) - }, + Self::ZBase32 => Self::encode_data(data, ZBASE_ALPHABET), }; ret.truncate(output_length); @@ -79,7 +76,9 @@ impl Alphabet { Self::RFC4648 { padding } => { let mut unpadded_data_length = data.len(); if *padding { - if data.len() % 8 != 0 { return Err(()); } + if data.len() % 8 != 0 { + return Err(()); + } data.iter().rev().take(6).for_each(|&c| { if c == b'=' { unpadded_data_length -= 1; @@ -88,13 +87,14 @@ impl Alphabet { } (&data[..unpadded_data_length], RFC4648_INV_ALPHABET) }, - Self::ZBase32 => { - (data, ZBASE_INV_ALPHABET) - } + Self::ZBase32 => (data, ZBASE_INV_ALPHABET), }; // If the string has more characters than are required to alphabet_encode the number of bytes // decodable, treat the string as invalid. - match data.len() % 8 { 1|3|6 => return Err(()), _ => {} } + match data.len() % 8 { + 1 | 3 | 6 => return Err(()), + _ => {}, + } Ok(Self::decode_data(data, alphabet)?) } @@ -175,9 +175,13 @@ mod tests { ("6n9hq", &[0xf0, 0xbf, 0xc7]), ("4t7ye", &[0xd4, 0x7a, 0x04]), ("6im5sdy", &[0xf5, 0x57, 0xbb, 0x0c]), - ("ybndrfg8ejkmcpqxot1uwisza345h769", &[0x00, 0x44, 0x32, 0x14, 0xc7, 0x42, 0x54, 0xb6, - 0x35, 0xcf, 0x84, 0x65, 0x3a, 0x56, 0xd7, 0xc6, - 0x75, 0xbe, 0x77, 0xdf]) + ( + "ybndrfg8ejkmcpqxot1uwisza345h769", + &[ + 0x00, 0x44, 0x32, 0x14, 0xc7, 0x42, 0x54, 0xb6, 0x35, 0xcf, 0x84, 0x65, 0x3a, 0x56, + 0xd7, 0xc6, 0x75, 0xbe, 0x77, 0xdf, + ], + ), ]; #[test] @@ -242,7 +246,9 @@ mod tests { } for (input, encoded) in RFC4648_NON_PADDED_TEST_VECTORS { - let res = &Alphabet::RFC4648 { padding: false }.decode(std::str::from_utf8(encoded).unwrap()).unwrap(); + let res = &Alphabet::RFC4648 { padding: false } + .decode(std::str::from_utf8(encoded).unwrap()) + .unwrap(); assert_eq!(&res[..], &input[..]); } } @@ -251,9 +257,8 @@ mod tests { fn padding() { let num_padding = [0, 6, 4, 3, 1]; for i in 1..6 { - let encoded = Alphabet::RFC4648 { padding: true }.encode( - (0..(i as u8)).collect::>().as_ref() - ); + let encoded = Alphabet::RFC4648 { padding: true } + .encode((0..(i as u8)).collect::>().as_ref()); assert_eq!(encoded.len(), 8); for j in 0..(num_padding[i % 5]) { assert_eq!(encoded.as_bytes()[encoded.len() - j - 1], b'='); diff --git a/lightning/src/util/byte_utils.rs b/lightning/src/util/byte_utils.rs index 419a6b73a69..9e023ffeb97 100644 --- a/lightning/src/util/byte_utils.rs +++ b/lightning/src/util/byte_utils.rs @@ -9,23 +9,23 @@ #[inline] pub fn slice_to_be48(v: &[u8]) -> u64 { - ((v[0] as u64) << 8*5) | - ((v[1] as u64) << 8*4) | - ((v[2] as u64) << 8*3) | - ((v[3] as u64) << 8*2) | - ((v[4] as u64) << 8*1) | - ((v[5] as u64) << 8*0) + ((v[0] as u64) << 8 * 5) + | ((v[1] as u64) << 8 * 4) + | ((v[2] as u64) << 8 * 3) + | ((v[3] as u64) << 8 * 2) + | ((v[4] as u64) << 8 * 1) + | ((v[5] as u64) << 8 * 0) } #[inline] pub fn be48_to_array(u: u64) -> [u8; 6] { assert!(u & 0xffff_0000_0000_0000 == 0); let mut v = [0; 6]; - v[0] = ((u >> 8*5) & 0xff) as u8; - v[1] = ((u >> 8*4) & 0xff) as u8; - v[2] = ((u >> 8*3) & 0xff) as u8; - v[3] = ((u >> 8*2) & 0xff) as u8; - v[4] = ((u >> 8*1) & 0xff) as u8; - v[5] = ((u >> 8*0) & 0xff) as u8; + v[0] = ((u >> 8 * 5) & 0xff) as u8; + v[1] = ((u >> 8 * 4) & 0xff) as u8; + v[2] = ((u >> 8 * 3) & 0xff) as u8; + v[3] = ((u >> 8 * 2) & 0xff) as u8; + v[4] = ((u >> 8 * 1) & 0xff) as u8; + v[5] = ((u >> 8 * 0) & 0xff) as u8; v } diff --git a/lightning/src/util/config.rs b/lightning/src/util/config.rs index 13284113d2c..a95d002c543 100644 --- a/lightning/src/util/config.rs +++ b/lightning/src/util/config.rs @@ -295,7 +295,7 @@ pub struct ChannelHandshakeLimits { /// /// Default value: 2016, which we also enforce as a maximum value so you can tweak config to /// reduce the loss of having useless locked funds (if your peer accepts) - pub their_to_self_delay: u16 + pub their_to_self_delay: u16, } impl Default for ChannelHandshakeLimits { @@ -491,7 +491,9 @@ pub struct ChannelConfig { impl ChannelConfig { /// Applies the given [`ChannelConfigUpdate`] as a partial update to the [`ChannelConfig`]. pub fn apply(&mut self, update: &ChannelConfigUpdate) { - if let Some(forwarding_fee_proportional_millionths) = update.forwarding_fee_proportional_millionths { + if let Some(forwarding_fee_proportional_millionths) = + update.forwarding_fee_proportional_millionths + { self.forwarding_fee_proportional_millionths = forwarding_fee_proportional_millionths; } if let Some(forwarding_fee_base_msat) = update.forwarding_fee_base_msat { @@ -503,7 +505,9 @@ impl ChannelConfig { if let Some(max_dust_htlc_exposure_msat) = update.max_dust_htlc_exposure_msat { self.max_dust_htlc_exposure = max_dust_htlc_exposure_msat; } - if let Some(force_close_avoidance_max_fee_satoshis) = update.force_close_avoidance_max_fee_satoshis { + if let Some(force_close_avoidance_max_fee_satoshis) = + update.force_close_avoidance_max_fee_satoshis + { self.force_close_avoidance_max_fee_satoshis = force_close_avoidance_max_fee_satoshis; } } @@ -603,11 +607,15 @@ impl Default for ChannelConfigUpdate { impl From for ChannelConfigUpdate { fn from(config: ChannelConfig) -> ChannelConfigUpdate { ChannelConfigUpdate { - forwarding_fee_proportional_millionths: Some(config.forwarding_fee_proportional_millionths), + forwarding_fee_proportional_millionths: Some( + config.forwarding_fee_proportional_millionths, + ), forwarding_fee_base_msat: Some(config.forwarding_fee_base_msat), cltv_expiry_delta: Some(config.cltv_expiry_delta), max_dust_htlc_exposure_msat: Some(config.max_dust_htlc_exposure), - force_close_avoidance_max_fee_satoshis: Some(config.force_close_avoidance_max_fee_satoshis), + force_close_avoidance_max_fee_satoshis: Some( + config.force_close_avoidance_max_fee_satoshis, + ), } } } @@ -680,8 +688,9 @@ impl crate::util::ser::Readable for LegacyChannelConfig { }); let max_dust_htlc_exposure_msat_fixed_limit = max_dust_htlc_exposure_msat_fixed_limit.unwrap_or(5_000_000); - let max_dust_htlc_exposure_msat = max_dust_htlc_exposure_enum - .unwrap_or(MaxDustHTLCExposure::FixedLimitMsat(max_dust_htlc_exposure_msat_fixed_limit)); + let max_dust_htlc_exposure_msat = max_dust_htlc_exposure_enum.unwrap_or( + MaxDustHTLCExposure::FixedLimitMsat(max_dust_htlc_exposure_msat_fixed_limit), + ); Ok(Self { options: ChannelConfig { forwarding_fee_proportional_millionths, diff --git a/lightning/src/util/errors.rs b/lightning/src/util/errors.rs index 4ffde9a72d2..30d255de3af 100644 --- a/lightning/src/util/errors.rs +++ b/lightning/src/util/errors.rs @@ -22,7 +22,7 @@ pub enum APIError { /// are documented, but generally indicates some precondition of a function was violated. APIMisuseError { /// A human-readable error message - err: String + err: String, }, /// Due to a high feerate, we were unable to complete the request. /// For example, this may be returned if the feerate implies we cannot open a channel at the @@ -31,20 +31,20 @@ pub enum APIError { /// A human-readable error message err: String, /// The feerate which was too high. - feerate: u32 + feerate: u32, }, /// A malformed Route was provided (eg overflowed value, node id mismatch, overly-looped route, /// too-many-hops, etc). InvalidRoute { /// A human-readable error message - err: String + err: String, }, /// We were unable to complete the request as the Channel required to do so is unable to /// complete the request (or was not found). This can take many forms, including disconnected /// peer, channel at capacity, channel shutting down, etc. ChannelUnavailable { /// A human-readable error message - err: String + err: String, }, /// An attempt to call [`chain::Watch::watch_channel`]/[`chain::Watch::update_channel`] /// returned a [`ChannelMonitorUpdateStatus::InProgress`] indicating the persistence of a @@ -72,11 +72,15 @@ pub enum APIError { impl fmt::Debug for APIError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - APIError::APIMisuseError {ref err} => write!(f, "Misuse error: {}", err), - APIError::FeeRateTooHigh {ref err, ref feerate} => write!(f, "{} feerate: {}", err, feerate), - APIError::InvalidRoute {ref err} => write!(f, "Invalid route provided: {}", err), - APIError::ChannelUnavailable {ref err} => write!(f, "Channel unavailable: {}", err), - APIError::MonitorUpdateInProgress => f.write_str("Client indicated a channel monitor update is in progress but not yet complete"), + APIError::APIMisuseError { ref err } => write!(f, "Misuse error: {}", err), + APIError::FeeRateTooHigh { ref err, ref feerate } => { + write!(f, "{} feerate: {}", err, feerate) + }, + APIError::InvalidRoute { ref err } => write!(f, "Invalid route provided: {}", err), + APIError::ChannelUnavailable { ref err } => write!(f, "Channel unavailable: {}", err), + APIError::MonitorUpdateInProgress => f.write_str( + "Client indicated a channel monitor update is in progress but not yet complete", + ), APIError::IncompatibleShutdownScript { ref script } => { write!(f, "Provided a scriptpubkey format not accepted by peer: {}", script) }, @@ -99,9 +103,9 @@ impl_writeable_tlv_based_enum_upgradable!(APIError, #[inline] pub(crate) fn get_onion_debug_field(error_code: u16) -> (&'static str, usize) { match error_code & 0xff { - 4|5|6 => ("sha256_of_onion", 32), - 11|12 => ("htlc_msat", 8), - 13|18 => ("cltv_expiry", 4), + 4 | 5 | 6 => ("sha256_of_onion", 32), + 11 | 12 => ("htlc_msat", 8), + 13 | 18 => ("cltv_expiry", 4), 19 => ("incoming_htlc_msat", 8), 20 => ("flags", 2), _ => ("", 0), diff --git a/lightning/src/util/fuzz_wrappers.rs b/lightning/src/util/fuzz_wrappers.rs index afe9c402c71..74c3e01cd27 100644 --- a/lightning/src/util/fuzz_wrappers.rs +++ b/lightning/src/util/fuzz_wrappers.rs @@ -8,19 +8,17 @@ // licenses. macro_rules! hash_to_message { - ($slice: expr) => { + ($slice: expr) => {{ + #[cfg(not(fuzzing))] { - #[cfg(not(fuzzing))] - { - ::bitcoin::secp256k1::Message::from_slice($slice).unwrap() - } - #[cfg(fuzzing)] - { - match ::bitcoin::secp256k1::Message::from_slice($slice) { - Ok(msg) => msg, - Err(_) => ::bitcoin::secp256k1::Message::from_slice(&[1; 32]).unwrap() - } + ::bitcoin::secp256k1::Message::from_slice($slice).unwrap() + } + #[cfg(fuzzing)] + { + match ::bitcoin::secp256k1::Message::from_slice($slice) { + Ok(msg) => msg, + Err(_) => ::bitcoin::secp256k1::Message::from_slice(&[1; 32]).unwrap(), } } - } + }}; } diff --git a/lightning/src/util/indexed_map.rs b/lightning/src/util/indexed_map.rs index 39565f048c0..7ff92cda3f4 100644 --- a/lightning/src/util/indexed_map.rs +++ b/lightning/src/util/indexed_map.rs @@ -1,10 +1,10 @@ //! This module has a map which can be iterated in a deterministic order. See the [`IndexedMap`]. -use crate::prelude::{HashMap, hash_map}; -use alloc::vec::Vec; +use crate::prelude::{hash_map, HashMap}; use alloc::slice::Iter; -use core::hash::Hash; +use alloc::vec::Vec; use core::cmp::Ord; +use core::hash::Hash; use core::ops::{Bound, RangeBounds}; /// A map which can be iterated in a deterministic order. @@ -33,18 +33,12 @@ pub struct IndexedMap { impl IndexedMap { /// Constructs a new, empty map pub fn new() -> Self { - Self { - map: HashMap::new(), - keys: Vec::new(), - } + Self { map: HashMap::new(), keys: Vec::new() } } /// Constructs a new, empty map with the given capacity pre-allocated pub fn with_capacity(capacity: usize) -> Self { - Self { - map: HashMap::with_capacity(capacity), - keys: Vec::with_capacity(capacity), - } + Self { map: HashMap::with_capacity(capacity), keys: Vec::with_capacity(capacity) } } #[inline(always)] @@ -68,7 +62,8 @@ impl IndexedMap { pub fn remove(&mut self, key: &K) -> Option { let ret = self.map.remove(key); if let Some(_) = ret { - let idx = self.keys.iter().position(|k| k == key).expect("map and keys must be consistent"); + let idx = + self.keys.iter().position(|k| k == key).expect("map and keys must be consistent"); self.keys.remove(idx); } ret @@ -88,18 +83,11 @@ impl IndexedMap { pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { match self.map.entry(key.clone()) { hash_map::Entry::Vacant(entry) => { - Entry::Vacant(VacantEntry { - underlying_entry: entry, - key, - keys: &mut self.keys, - }) + Entry::Vacant(VacantEntry { underlying_entry: entry, key, keys: &mut self.keys }) }, hash_map::Entry::Occupied(entry) => { - Entry::Occupied(OccupiedEntry { - underlying_entry: entry, - keys: &mut self.keys, - }) - } + Entry::Occupied(OccupiedEntry { underlying_entry: entry, keys: &mut self.keys }) + }, } } @@ -125,18 +113,23 @@ impl IndexedMap { let start = match range.start_bound() { Bound::Unbounded => 0, Bound::Included(key) => self.keys.binary_search(key).unwrap_or_else(|index| index), - Bound::Excluded(key) => self.keys.binary_search(key).and_then(|index| Ok(index + 1)).unwrap_or_else(|index| index), + Bound::Excluded(key) => self + .keys + .binary_search(key) + .and_then(|index| Ok(index + 1)) + .unwrap_or_else(|index| index), }; let end = match range.end_bound() { Bound::Unbounded => self.keys.len(), - Bound::Included(key) => self.keys.binary_search(key).and_then(|index| Ok(index + 1)).unwrap_or_else(|index| index), + Bound::Included(key) => self + .keys + .binary_search(key) + .and_then(|index| Ok(index + 1)) + .unwrap_or_else(|index| index), Bound::Excluded(key) => self.keys.binary_search(key).unwrap_or_else(|index| index), }; - Range { - inner_range: self.keys[start..end].iter(), - map: &self.map, - } + Range { inner_range: self.keys[start..end].iter(), map: &self.map } } /// Returns the number of `key`/`value` pairs in the map @@ -166,9 +159,9 @@ pub struct Range<'a, K: Hash + Ord, V> { impl<'a, K: Hash + Ord, V: 'a> Iterator for Range<'a, K, V> { type Item = (&'a K, &'a V); fn next(&mut self) -> Option<(&'a K, &'a V)> { - self.inner_range.next().map(|k| { - (k, self.map.get(k).expect("map and keys must be consistent")) - }) + self.inner_range + .next() + .map(|k| (k, self.map.get(k).expect("map and keys must be consistent"))) } } @@ -218,7 +211,8 @@ impl<'a, K: Hash + Ord, V> OccupiedEntry<'a, K, V> { /// Remove the value at the position described by this entry. pub fn remove_entry(self) -> (K, V) { let res = self.underlying_entry.remove_entry(); - let idx = self.keys.iter().position(|k| k == &res.0).expect("map and keys must be consistent"); + let idx = + self.keys.iter().position(|k| k == &res.0).expect("map and keys must be consistent"); self.keys.remove(idx); res } diff --git a/lightning/src/util/invoice.rs b/lightning/src/util/invoice.rs index 8c22200b9b2..1c7b1653d88 100644 --- a/lightning/src/util/invoice.rs +++ b/lightning/src/util/invoice.rs @@ -1,7 +1,7 @@ //! Low level invoice utilities. -use bitcoin::bech32::{u5, FromBase32}; use crate::prelude::*; +use bitcoin::bech32::{u5, FromBase32}; /// Construct the invoice's HRP and signatureless data into a preimage to be hashed. pub fn construct_invoice_preimage(hrp_bytes: &[u8], data_without_signature: &[u5]) -> Vec { @@ -19,8 +19,9 @@ pub fn construct_invoice_preimage(hrp_bytes: &[u8], data_without_signature: &[u5 } } - preimage.extend_from_slice(&Vec::::from_base32(&data_part) - .expect("No padding error may occur due to appended zero above.")); + preimage.extend_from_slice( + &Vec::::from_base32(&data_part) + .expect("No padding error may occur due to appended zero above."), + ); preimage } - diff --git a/lightning/src/util/logger.rs b/lightning/src/util/logger.rs index 92ea8ffed55..887867146a0 100644 --- a/lightning/src/util/logger.rs +++ b/lightning/src/util/logger.rs @@ -132,7 +132,7 @@ impl<'a> Record<'a> { #[inline] pub fn new( level: Level, peer_id: Option, channel_id: Option, - args: fmt::Arguments<'a>, module_path: &'static str, file: &'static str, line: u32 + args: fmt::Arguments<'a>, module_path: &'static str, file: &'static str, line: u32, ) -> Record<'a> { Record { level, @@ -158,7 +158,10 @@ pub trait Logger { } /// Adds relevant context to a [`Record`] before passing it to the wrapped [`Logger`]. -pub struct WithContext<'a, L: Deref> where L::Target: Logger { +pub struct WithContext<'a, L: Deref> +where + L::Target: Logger, +{ /// The logger to delegate to after adding context to the record. logger: &'a L, /// The node id of the peer pertaining to the logged record. @@ -167,7 +170,10 @@ pub struct WithContext<'a, L: Deref> where L::Target: Logger { channel_id: Option, } -impl<'a, L: Deref> Logger for WithContext<'a, L> where L::Target: Logger { +impl<'a, L: Deref> Logger for WithContext<'a, L> +where + L::Target: Logger, +{ fn log(&self, mut record: Record) { if self.peer_id.is_some() { record.peer_id = self.peer_id @@ -179,14 +185,13 @@ impl<'a, L: Deref> Logger for WithContext<'a, L> where L::Target: Logger { } } -impl<'a, L: Deref> WithContext<'a, L> where L::Target: Logger { +impl<'a, L: Deref> WithContext<'a, L> +where + L::Target: Logger, +{ /// Wraps the given logger, providing additional context to any logged records. pub fn from(logger: &'a L, peer_id: Option, channel_id: Option) -> Self { - WithContext { - logger, - peer_id, - channel_id, - } + WithContext { logger, peer_id, channel_id } } } @@ -240,11 +245,11 @@ impl + Clone> fmt::Display fo #[cfg(test)] mod tests { - use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1}; use crate::ln::ChannelId; - use crate::util::logger::{Logger, Level, WithContext}; - use crate::util::test_utils::TestLogger; use crate::sync::Arc; + use crate::util::logger::{Level, Logger, WithContext}; + use crate::util::test_utils::TestLogger; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; #[test] fn test_level_show() { @@ -254,14 +259,12 @@ mod tests { } struct WrapperLog { - logger: Arc + logger: Arc, } impl WrapperLog { fn new(logger: Arc) -> WrapperLog { - WrapperLog { - logger, - } + WrapperLog { logger } } fn call_macros(&self) { @@ -278,7 +281,7 @@ mod tests { fn test_logging_macros() { let mut logger = TestLogger::new(); logger.enable(Level::Gossip); - let logger : Arc = Arc::new(logger); + let logger: Arc = Arc::new(logger); let wrapper = WrapperLog::new(Arc::clone(&logger)); wrapper.call_macros(); } @@ -296,7 +299,10 @@ mod tests { log_gossip!(context_logger, "This is an error"); log_info!(context_logger, "This is an error"); logger.assert_log_context_contains( - "lightning::util::logger::tests", Some(pk), Some(ChannelId([0;32])), 6 + "lightning::util::logger::tests", + Some(pk), + Some(ChannelId([0; 32])), + 6, ); } @@ -314,7 +320,10 @@ mod tests { log_gossip!(full_context_logger, "This is an error"); log_info!(full_context_logger, "This is an error"); logger.assert_log_context_contains( - "lightning::util::logger::tests", Some(pk), Some(ChannelId([0;32])), 6 + "lightning::util::logger::tests", + Some(pk), + Some(ChannelId([0; 32])), + 6, ); } diff --git a/lightning/src/util/macro_logger.rs b/lightning/src/util/macro_logger.rs index 55b11604d94..c34cb884003 100644 --- a/lightning/src/util/macro_logger.rs +++ b/lightning/src/util/macro_logger.rs @@ -11,16 +11,16 @@ use crate::chain::transaction::OutPoint; use crate::ln::ChannelId; use crate::sign::SpendableOutputDescriptor; -use bitcoin::hash_types::Txid; use bitcoin::blockdata::transaction::Transaction; +use bitcoin::hash_types::Txid; -use crate::routing::router::Route; use crate::ln::chan_utils::HTLCClaim; +use crate::routing::router::Route; macro_rules! log_iter { ($obj: expr) => { $crate::util::logger::DebugIter($obj) - } + }; } /// Logs a pubkey in hex format. @@ -28,7 +28,7 @@ macro_rules! log_iter { macro_rules! log_pubkey { ($obj: expr) => { $crate::util::logger::DebugPubKey(&$obj) - } + }; } /// Logs a byte slice in hex format. @@ -36,7 +36,7 @@ macro_rules! log_pubkey { macro_rules! log_bytes { ($obj: expr) => { $crate::util::logger::DebugBytes(&$obj) - } + }; } pub(crate) struct DebugFundingChannelId<'a>(pub &'a Txid, pub u16); @@ -54,10 +54,8 @@ impl<'a> core::fmt::Display for DebugFundingInfo<'a> { } macro_rules! log_funding_info { ($key_storage: expr) => { - $crate::util::macro_logger::DebugFundingInfo( - &$key_storage.channel_id() - ) - } + $crate::util::macro_logger::DebugFundingInfo(&$key_storage.channel_id()) + }; } pub(crate) struct DebugRoute<'a>(pub &'a Route); @@ -66,7 +64,14 @@ impl<'a> core::fmt::Display for DebugRoute<'a> { for (idx, p) in self.0.paths.iter().enumerate() { writeln!(f, "path {}:", idx)?; for h in p.hops.iter() { - writeln!(f, " node_id: {}, short_channel_id: {}, fee_msat: {}, cltv_expiry_delta: {}", log_pubkey!(h.pubkey), h.short_channel_id, h.fee_msat, h.cltv_expiry_delta)?; + writeln!( + f, + " node_id: {}, short_channel_id: {}, fee_msat: {}, cltv_expiry_delta: {}", + log_pubkey!(h.pubkey), + h.short_channel_id, + h.fee_msat, + h.cltv_expiry_delta + )?; } writeln!(f, " blinded_tail: {:?}", p.blinded_tail)?; } @@ -76,7 +81,7 @@ impl<'a> core::fmt::Display for DebugRoute<'a> { macro_rules! log_route { ($obj: expr) => { $crate::util::macro_logger::DebugRoute(&$obj) - } + }; } pub(crate) struct DebugTx<'a>(pub &'a Transaction); @@ -85,14 +90,21 @@ impl<'a> core::fmt::Display for DebugTx<'a> { if self.0.input.len() >= 1 && self.0.input.iter().any(|i| !i.witness.is_empty()) { let first_input = &self.0.input[0]; let witness_script_len = first_input.witness.last().unwrap_or(&[]).len(); - if self.0.input.len() == 1 && witness_script_len == 71 && - (first_input.sequence.0 >> 8*3) as u8 == 0x80 { + if self.0.input.len() == 1 + && witness_script_len == 71 + && (first_input.sequence.0 >> 8 * 3) as u8 == 0x80 + { write!(f, "commitment tx ")?; } else if self.0.input.len() == 1 && witness_script_len == 71 { write!(f, "closing tx ")?; - } else if self.0.input.len() == 1 && HTLCClaim::from_witness(&first_input.witness) == Some(HTLCClaim::OfferedTimeout) { + } else if self.0.input.len() == 1 + && HTLCClaim::from_witness(&first_input.witness) == Some(HTLCClaim::OfferedTimeout) + { write!(f, "HTLC-timeout tx ")?; - } else if self.0.input.len() == 1 && HTLCClaim::from_witness(&first_input.witness) == Some(HTLCClaim::AcceptedPreimage) { + } else if self.0.input.len() == 1 + && HTLCClaim::from_witness(&first_input.witness) + == Some(HTLCClaim::AcceptedPreimage) + { write!(f, "HTLC-success tx ")?; } else { let mut num_preimage = 0; @@ -101,15 +113,22 @@ impl<'a> core::fmt::Display for DebugTx<'a> { for inp in &self.0.input { let htlc_claim = HTLCClaim::from_witness(&inp.witness); match htlc_claim { - Some(HTLCClaim::AcceptedPreimage)|Some(HTLCClaim::OfferedPreimage) => num_preimage += 1, - Some(HTLCClaim::AcceptedTimeout)|Some(HTLCClaim::OfferedTimeout) => num_timeout += 1, + Some(HTLCClaim::AcceptedPreimage) | Some(HTLCClaim::OfferedPreimage) => { + num_preimage += 1 + }, + Some(HTLCClaim::AcceptedTimeout) | Some(HTLCClaim::OfferedTimeout) => { + num_timeout += 1 + }, Some(HTLCClaim::Revocation) => num_revoked += 1, None => continue, } } if num_preimage > 0 || num_timeout > 0 || num_revoked > 0 { - write!(f, "HTLC claim tx ({} preimage, {} timeout, {} revoked) ", - num_preimage, num_timeout, num_revoked)?; + write!( + f, + "HTLC claim tx ({} preimage, {} timeout, {} revoked) ", + num_preimage, num_timeout, num_revoked + )?; } } } else { @@ -124,7 +143,7 @@ impl<'a> core::fmt::Display for DebugTx<'a> { macro_rules! log_tx { ($obj: expr) => { $crate::util::macro_logger::DebugTx(&$obj) - } + }; } pub(crate) struct DebugSpendable<'a>(pub &'a SpendableOutputDescriptor); @@ -133,13 +152,21 @@ impl<'a> core::fmt::Display for DebugSpendable<'a> { match self.0 { &SpendableOutputDescriptor::StaticOutput { ref outpoint, .. } => { write!(f, "StaticOutput {}:{} marked for spending", outpoint.txid, outpoint.index)?; - } + }, &SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor) => { - write!(f, "DelayedPaymentOutput {}:{} marked for spending", descriptor.outpoint.txid, descriptor.outpoint.index)?; - } + write!( + f, + "DelayedPaymentOutput {}:{} marked for spending", + descriptor.outpoint.txid, descriptor.outpoint.index + )?; + }, &SpendableOutputDescriptor::StaticPaymentOutput(ref descriptor) => { - write!(f, "StaticPaymentOutput {}:{} marked for spending", descriptor.outpoint.txid, descriptor.outpoint.index)?; - } + write!( + f, + "StaticPaymentOutput {}:{} marked for spending", + descriptor.outpoint.txid, descriptor.outpoint.index + )?; + }, } Ok(()) } @@ -148,7 +175,7 @@ impl<'a> core::fmt::Display for DebugSpendable<'a> { macro_rules! log_spendable { ($obj: expr) => { $crate::util::macro_logger::DebugSpendable(&$obj) - } + }; } /// Create a new Record and log it. You probably don't want to use this macro directly, diff --git a/lightning/src/util/message_signing.rs b/lightning/src/util/message_signing.rs index 88ff18ff204..616d87d3e2f 100644 --- a/lightning/src/util/message_signing.rs +++ b/lightning/src/util/message_signing.rs @@ -46,7 +46,7 @@ fn sigrec_decode(sig_rec: Vec) -> Result { match RecoveryId::from_i32(rid) { Ok(x) => RecoverableSignature::from_compact(rsig, x), - Err(e) => Err(e) + Err(e) => Err(e), } } @@ -62,18 +62,18 @@ pub fn sign(msg: &[u8], sk: &SecretKey) -> Result { } /// Recovers the PublicKey of the signer of the message given the message and the signature. -pub fn recover_pk(msg: &[u8], sig: &str) -> Result { +pub fn recover_pk(msg: &[u8], sig: &str) -> Result { let secp_ctx = Secp256k1::verification_only(); let msg_hash = sha256d::Hash::hash(&[LN_MESSAGE_PREFIX, msg].concat()); match base32::Alphabet::ZBase32.decode(&sig) { - Ok(sig_rec) => { - match sigrec_decode(sig_rec) { - Ok(sig) => secp_ctx.recover_ecdsa(&Message::from_slice(msg_hash.as_byte_array())?, &sig), - Err(e) => Err(e) - } + Ok(sig_rec) => match sigrec_decode(sig_rec) { + Ok(sig) => { + secp_ctx.recover_ecdsa(&Message::from_slice(msg_hash.as_byte_array())?, &sig) + }, + Err(e) => Err(e), }, - Err(_) => Err(Error::InvalidSignature) + Err(_) => Err(Error::InvalidSignature), } } @@ -82,16 +82,16 @@ pub fn recover_pk(msg: &[u8], sig: &str) -> Result { pub fn verify(msg: &[u8], sig: &str, pk: &PublicKey) -> bool { match recover_pk(msg, sig) { Ok(x) => x == *pk, - Err(_) => false + Err(_) => false, } } #[cfg(test)] mod test { - use core::str::FromStr; - use crate::util::message_signing::{sign, recover_pk, verify}; + use crate::util::message_signing::{recover_pk, sign, verify}; use bitcoin::secp256k1::constants::ONE; - use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1}; + use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; + use core::str::FromStr; #[test] fn test_sign() { @@ -147,4 +147,3 @@ mod test { } } } - diff --git a/lightning/src/util/mod.rs b/lightning/src/util/mod.rs index 6ce00acab45..f040bb28117 100644 --- a/lightning/src/util/mod.rs +++ b/lightning/src/util/mod.rs @@ -15,23 +15,23 @@ pub(crate) mod fuzz_wrappers; #[macro_use] pub mod ser_macros; +#[cfg(fuzzing)] +pub mod base32; +#[cfg(not(fuzzing))] +pub(crate) mod base32; pub mod errors; -pub mod ser; -pub mod message_signing; pub mod invoice; +pub mod message_signing; pub mod persist; pub mod scid_utils; +pub mod ser; pub mod string; pub mod wakers; -#[cfg(fuzzing)] -pub mod base32; -#[cfg(not(fuzzing))] -pub(crate) mod base32; pub(crate) mod atomic_counter; pub(crate) mod byte_utils; -pub(crate) mod transaction_utils; pub(crate) mod time; +pub(crate) mod transaction_utils; pub mod indexed_map; @@ -40,8 +40,8 @@ pub mod indexed_map; pub(crate) mod macro_logger; // These have to come after macro_logger to build -pub mod logger; pub mod config; +pub mod logger; #[cfg(any(test, feature = "_test_utils"))] pub mod test_utils; @@ -50,4 +50,3 @@ pub mod test_utils; /// machine errors and used in fuzz targets and tests. #[cfg(any(test, feature = "_test_utils"))] pub mod test_channel_signer; - diff --git a/lightning/src/util/persist.rs b/lightning/src/util/persist.rs index 7d501345c3c..ad7f3b1fe27 100644 --- a/lightning/src/util/persist.rs +++ b/lightning/src/util/persist.rs @@ -8,31 +8,34 @@ //! allows one to implement the persistence for [`ChannelManager`], [`NetworkGraph`], //! and [`ChannelMonitor`] all in one place. +use bitcoin::{BlockHash, Txid}; use core::cmp; use core::convert::{TryFrom, TryInto}; use core::ops::Deref; use core::str::FromStr; -use bitcoin::{BlockHash, Txid}; -use crate::{io, log_error}; use crate::alloc::string::ToString; use crate::prelude::*; +use crate::{io, log_error}; use crate::chain; use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use crate::chain::chainmonitor::{Persist, MonitorUpdateId}; -use crate::sign::{EntropySource, NodeSigner, ecdsa::WriteableEcdsaChannelSigner, SignerProvider}; +use crate::chain::chainmonitor::{MonitorUpdateId, Persist}; +use crate::chain::channelmonitor::{ + ChannelMonitor, ChannelMonitorUpdate, CLOSED_CHANNEL_UPDATE_ID, +}; use crate::chain::transaction::OutPoint; -use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, CLOSED_CHANNEL_UPDATE_ID}; use crate::ln::channelmanager::ChannelManager; -use crate::routing::router::Router; use crate::routing::gossip::NetworkGraph; +use crate::routing::router::Router; use crate::routing::scoring::WriteableScore; +use crate::sign::{ecdsa::WriteableEcdsaChannelSigner, EntropySource, NodeSigner, SignerProvider}; use crate::util::logger::Logger; use crate::util::ser::{Readable, ReadableArgs, Writeable}; /// The alphabet of characters allowed for namespaces and keys. -pub const KVSTORE_NAMESPACE_KEY_ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; +pub const KVSTORE_NAMESPACE_KEY_ALPHABET: &str = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; /// The maximum number of characters namespaces and keys may have. pub const KVSTORE_NAMESPACE_KEY_MAX_LEN: usize = 120; @@ -100,12 +103,16 @@ pub trait KVStore { /// `primary_namespace` and `secondary_namespace`. /// /// [`ErrorKind::NotFound`]: io::ErrorKind::NotFound - fn read(&self, primary_namespace: &str, secondary_namespace: &str, key: &str) -> Result, io::Error>; + fn read( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, + ) -> Result, io::Error>; /// Persists the given data under the given `key`. /// /// Will create the given `primary_namespace` and `secondary_namespace` if not already present /// in the store. - fn write(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8]) -> Result<(), io::Error>; + fn write( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8], + ) -> Result<(), io::Error>; /// Removes any data that had previously been persisted under the given `key`. /// /// If the `lazy` flag is set to `true`, the backend implementation might choose to lazily @@ -121,28 +128,45 @@ pub trait KVStore { /// Returns successfully if no data will be stored for the given `primary_namespace`, /// `secondary_namespace`, and `key`, independently of whether it was present before its /// invokation or not. - fn remove(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool) -> Result<(), io::Error>; + fn remove( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool, + ) -> Result<(), io::Error>; /// Returns a list of keys that are stored under the given `secondary_namespace` in /// `primary_namespace`. /// /// Returns the keys in arbitrary order, so users requiring a particular order need to sort the /// returned keys. Returns an empty list if `primary_namespace` or `secondary_namespace` is unknown. - fn list(&self, primary_namespace: &str, secondary_namespace: &str) -> Result, io::Error>; + fn list( + &self, primary_namespace: &str, secondary_namespace: &str, + ) -> Result, io::Error>; } /// Trait that handles persisting a [`ChannelManager`], [`NetworkGraph`], and [`WriteableScore`] to disk. -pub trait Persister<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref, S: WriteableScore<'a>> - where M::Target: 'static + chain::Watch<::EcdsaSigner>, - T::Target: 'static + BroadcasterInterface, - ES::Target: 'static + EntropySource, - NS::Target: 'static + NodeSigner, - SP::Target: 'static + SignerProvider, - F::Target: 'static + FeeEstimator, - R::Target: 'static + Router, - L::Target: 'static + Logger, +pub trait Persister< + 'a, + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, + S: WriteableScore<'a>, +> where + M::Target: 'static + chain::Watch<::EcdsaSigner>, + T::Target: 'static + BroadcasterInterface, + ES::Target: 'static + EntropySource, + NS::Target: 'static + NodeSigner, + SP::Target: 'static + SignerProvider, + F::Target: 'static + FeeEstimator, + R::Target: 'static + Router, + L::Target: 'static + Logger, { /// Persist the given ['ChannelManager'] to disk, returning an error if persistence failed. - fn persist_manager(&self, channel_manager: &ChannelManager) -> Result<(), io::Error>; + fn persist_manager( + &self, channel_manager: &ChannelManager, + ) -> Result<(), io::Error>; /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed. fn persist_graph(&self, network_graph: &NetworkGraph) -> Result<(), io::Error>; @@ -151,39 +175,59 @@ pub trait Persister<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error>; } - -impl<'a, A: KVStore, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, M, T, ES, NS, SP, F, R, L, S> for A - where M::Target: 'static + chain::Watch<::EcdsaSigner>, - T::Target: 'static + BroadcasterInterface, - ES::Target: 'static + EntropySource, - NS::Target: 'static + NodeSigner, - SP::Target: 'static + SignerProvider, - F::Target: 'static + FeeEstimator, - R::Target: 'static + Router, - L::Target: 'static + Logger, +impl< + 'a, + A: KVStore, + M: Deref, + T: Deref, + ES: Deref, + NS: Deref, + SP: Deref, + F: Deref, + R: Deref, + L: Deref, + S: WriteableScore<'a>, + > Persister<'a, M, T, ES, NS, SP, F, R, L, S> for A +where + M::Target: 'static + chain::Watch<::EcdsaSigner>, + T::Target: 'static + BroadcasterInterface, + ES::Target: 'static + EntropySource, + NS::Target: 'static + NodeSigner, + SP::Target: 'static + SignerProvider, + F::Target: 'static + FeeEstimator, + R::Target: 'static + Router, + L::Target: 'static + Logger, { /// Persist the given [`ChannelManager`] to disk, returning an error if persistence failed. - fn persist_manager(&self, channel_manager: &ChannelManager) -> Result<(), io::Error> { - self.write(CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE, + fn persist_manager( + &self, channel_manager: &ChannelManager, + ) -> Result<(), io::Error> { + self.write( + CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_KEY, - &channel_manager.encode()) + &channel_manager.encode(), + ) } /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed. fn persist_graph(&self, network_graph: &NetworkGraph) -> Result<(), io::Error> { - self.write(NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE, + self.write( + NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_KEY, - &network_graph.encode()) + &network_graph.encode(), + ) } /// Persist the given [`WriteableScore`] to disk, returning an error if persistence failed. fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error> { - self.write(SCORER_PERSISTENCE_PRIMARY_NAMESPACE, + self.write( + SCORER_PERSISTENCE_PRIMARY_NAMESPACE, SCORER_PERSISTENCE_SECONDARY_NAMESPACE, SCORER_PERSISTENCE_KEY, - &scorer.encode()) + &scorer.encode(), + ) } } @@ -193,27 +237,35 @@ impl Persist, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { + fn persist_new_channel( + &self, funding_txo: OutPoint, monitor: &ChannelMonitor, + _update_id: MonitorUpdateId, + ) -> chain::ChannelMonitorUpdateStatus { let key = format!("{}_{}", funding_txo.txid.to_string(), funding_txo.index); match self.write( CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE, - &key, &monitor.encode()) - { + &key, + &monitor.encode(), + ) { Ok(()) => chain::ChannelMonitorUpdateStatus::Completed, - Err(_) => chain::ChannelMonitorUpdateStatus::UnrecoverableError + Err(_) => chain::ChannelMonitorUpdateStatus::UnrecoverableError, } } - fn update_persisted_channel(&self, funding_txo: OutPoint, _update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { + fn update_persisted_channel( + &self, funding_txo: OutPoint, _update: Option<&ChannelMonitorUpdate>, + monitor: &ChannelMonitor, _update_id: MonitorUpdateId, + ) -> chain::ChannelMonitorUpdateStatus { let key = format!("{}_{}", funding_txo.txid.to_string(), funding_txo.index); match self.write( CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE, - &key, &monitor.encode()) - { + &key, + &monitor.encode(), + ) { Ok(()) => chain::ChannelMonitorUpdateStatus::Completed, - Err(_) => chain::ChannelMonitorUpdateStatus::UnrecoverableError + Err(_) => chain::ChannelMonitorUpdateStatus::UnrecoverableError, } } } @@ -230,12 +282,14 @@ where let mut res = Vec::new(); for stored_key in kv_store.list( - CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE)? - { + CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, + CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE, + )? { if stored_key.len() < 66 { return Err(io::Error::new( io::ErrorKind::InvalidData, - "Stored key has invalid length")); + "Stored key has invalid length", + )); } let txid = Txid::from_str(stored_key.split_at(64).0).map_err(|_| { @@ -247,8 +301,11 @@ where })?; match <(BlockHash, ChannelMonitor<::EcdsaSigner>)>::read( - &mut io::Cursor::new( - kv_store.read(CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE, &stored_key)?), + &mut io::Cursor::new(kv_store.read( + CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, + CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE, + &stored_key, + )?), (&*entropy_source, &*signer_provider), ) { Ok((block_hash, channel_monitor)) => { @@ -261,13 +318,13 @@ where )); } res.push((block_hash, channel_monitor)); - } + }, Err(_) => { return Err(io::Error::new( io::ErrorKind::InvalidData, - "Failed to read ChannelMonitor" + "Failed to read ChannelMonitor", )) - } + }, } } Ok(res) @@ -371,8 +428,7 @@ where } #[allow(dead_code)] -impl - MonitorUpdatingPersister +impl MonitorUpdatingPersister where K::Target: KVStore, L::Target: Logger, @@ -415,7 +471,10 @@ where /// documentation for [`MonitorUpdatingPersister`]. pub fn read_all_channel_monitors_with_updates( &self, broadcaster: &B, fee_estimator: &F, - ) -> Result::EcdsaSigner>)>, io::Error> + ) -> Result< + Vec<(BlockHash, ChannelMonitor<::EcdsaSigner>)>, + io::Error, + > where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -473,12 +532,12 @@ where Err(err) if err.kind() == io::ErrorKind::NotFound => { // We can't find any more updates, so we are done. break; - } + }, Err(err) => return Err(err), }; - monitor.update_monitor(&update, broadcaster, fee_estimator, &self.logger) - .map_err(|e| { + monitor.update_monitor(&update, broadcaster, fee_estimator, &self.logger).map_err( + |e| { log_error!( self.logger, "Monitor update failed. monitor: {} update: {} reason: {:?}", @@ -487,7 +546,8 @@ where e ); io::Error::new(io::ErrorKind::Other, "Monitor update failed") - })?; + }, + )?; } Ok((block_hash, monitor)) } @@ -495,7 +555,8 @@ where /// Read a channel monitor. fn read_monitor( &self, monitor_name: &MonitorName, - ) -> Result<(BlockHash, ChannelMonitor<::EcdsaSigner>), io::Error> { + ) -> Result<(BlockHash, ChannelMonitor<::EcdsaSigner>), io::Error> + { let outpoint: OutPoint = monitor_name.try_into()?; let mut monitor_cursor = io::Cursor::new(self.kv_store.read( CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE, @@ -526,7 +587,7 @@ where } else { Ok((blockhash, channel_monitor)) } - } + }, Err(e) => { log_error!( self.logger, @@ -535,7 +596,7 @@ where e, ); Err(io::Error::new(io::ErrorKind::InvalidData, "Failed to read ChannelMonitor")) - } + }, } } @@ -575,9 +636,10 @@ where for monitor_key in monitor_keys { let monitor_name = MonitorName::new(monitor_key)?; let (_, current_monitor) = self.read_monitor(&monitor_name)?; - let updates = self - .kv_store - .list(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str())?; + let updates = self.kv_store.list( + CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, + monitor_name.as_str(), + )?; for update in updates { let update_name = UpdateName::new(update)?; // if the update_id is lower than the stored monitor, delete @@ -623,9 +685,7 @@ where monitor_name.as_str(), &monitor_bytes, ) { - Ok(_) => { - chain::ChannelMonitorUpdateStatus::Completed - } + Ok(_) => chain::ChannelMonitorUpdateStatus::Completed, Err(e) => { log_error!( self.logger, @@ -636,7 +696,7 @@ where e ); chain::ChannelMonitorUpdateStatus::UnrecoverableError - } + }, } } @@ -678,7 +738,7 @@ where e ); chain::ChannelMonitorUpdateStatus::UnrecoverableError - } + }, } } else { let monitor_name = MonitorName::from(funding_txo); @@ -686,29 +746,31 @@ where // the new one in order to determine the cleanup range. let maybe_old_monitor = match monitor.get_latest_update_id() { CLOSED_CHANNEL_UPDATE_ID => self.read_monitor(&monitor_name).ok(), - _ => None + _ => None, }; // We could write this update, but it meets criteria of our design that calls for a full monitor write. - let monitor_update_status = self.persist_new_channel(funding_txo, monitor, monitor_update_call_id); + let monitor_update_status = + self.persist_new_channel(funding_txo, monitor, monitor_update_call_id); if let chain::ChannelMonitorUpdateStatus::Completed = monitor_update_status { - let cleanup_range = if monitor.get_latest_update_id() == CLOSED_CHANNEL_UPDATE_ID { - // If there is an error while reading old monitor, we skip clean up. - maybe_old_monitor.map(|(_, ref old_monitor)| { - let start = old_monitor.get_latest_update_id(); - // We never persist an update with update_id = CLOSED_CHANNEL_UPDATE_ID - let end = cmp::min( - start.saturating_add(self.maximum_pending_updates), - CLOSED_CHANNEL_UPDATE_ID - 1, - ); - (start, end) - }) - } else { - let end = monitor.get_latest_update_id(); - let start = end.saturating_sub(self.maximum_pending_updates); - Some((start, end)) - }; + let cleanup_range = + if monitor.get_latest_update_id() == CLOSED_CHANNEL_UPDATE_ID { + // If there is an error while reading old monitor, we skip clean up. + maybe_old_monitor.map(|(_, ref old_monitor)| { + let start = old_monitor.get_latest_update_id(); + // We never persist an update with update_id = CLOSED_CHANNEL_UPDATE_ID + let end = cmp::min( + start.saturating_add(self.maximum_pending_updates), + CLOSED_CHANNEL_UPDATE_ID - 1, + ); + (start, end) + }) + } else { + let end = monitor.get_latest_update_id(); + let start = end.saturating_sub(self.maximum_pending_updates); + Some((start, end)) + }; if let Some((start, end)) = cleanup_range { self.cleanup_in_range(monitor_name, start, end); @@ -729,7 +791,7 @@ where ES::Target: EntropySource + Sized, K::Target: KVStore, L::Target: Logger, - SP::Target: SignerProvider + Sized + SP::Target: SignerProvider + Sized, { // Cleans up monitor updates for given monitor in range `start..=end`. fn cleanup_in_range(&self, monitor_name: MonitorName, start: u64, end: u64) { @@ -820,7 +882,7 @@ impl UpdateName { Ok(u) => Ok(u.into()), Err(_) => { Err(io::Error::new(io::ErrorKind::InvalidData, "cannot parse u64 from update name")) - } + }, } } @@ -864,23 +926,44 @@ mod tests { #[test] fn monitor_from_outpoint_works() { let monitor_name1 = MonitorName::from(OutPoint { - txid: Txid::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef").unwrap(), + txid: Txid::from_str( + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", + ) + .unwrap(), index: 1, }); - assert_eq!(monitor_name1.as_str(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1"); + assert_eq!( + monitor_name1.as_str(), + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1" + ); let monitor_name2 = MonitorName::from(OutPoint { - txid: Txid::from_str("f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef").unwrap(), + txid: Txid::from_str( + "f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef", + ) + .unwrap(), index: u16::MAX, }); - assert_eq!(monitor_name2.as_str(), "f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef_65535"); + assert_eq!( + monitor_name2.as_str(), + "f33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeeff33dbeef_65535" + ); } #[test] fn bad_monitor_string_fails() { - assert!(MonitorName::new("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string()).is_err()); - assert!(MonitorName::new("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_65536".to_string()).is_err()); - assert!(MonitorName::new("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_21".to_string()).is_err()); + assert!(MonitorName::new( + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string() + ) + .is_err()); + assert!(MonitorName::new( + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_65536".to_string() + ) + .is_err()); + assert!(MonitorName::new( + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_21".to_string() + ) + .is_err()); } // Exercise the `MonitorUpdatingPersister` with real channels and payments. @@ -931,18 +1014,24 @@ mod tests { // Check that the persisted channel data is empty before any channels are // open. - let mut persisted_chan_data_0 = persister_0.read_all_channel_monitors_with_updates( - &broadcaster_0, &&chanmon_cfgs[0].fee_estimator).unwrap(); + let mut persisted_chan_data_0 = persister_0 + .read_all_channel_monitors_with_updates(&broadcaster_0, &&chanmon_cfgs[0].fee_estimator) + .unwrap(); assert_eq!(persisted_chan_data_0.len(), 0); - let mut persisted_chan_data_1 = persister_1.read_all_channel_monitors_with_updates( - &broadcaster_1, &&chanmon_cfgs[1].fee_estimator).unwrap(); + let mut persisted_chan_data_1 = persister_1 + .read_all_channel_monitors_with_updates(&broadcaster_1, &&chanmon_cfgs[1].fee_estimator) + .unwrap(); assert_eq!(persisted_chan_data_1.len(), 0); // Helper to make sure the channel is on the expected update ID. macro_rules! check_persisted_data { ($expected_update_id: expr) => { - persisted_chan_data_0 = persister_0.read_all_channel_monitors_with_updates( - &broadcaster_0, &&chanmon_cfgs[0].fee_estimator).unwrap(); + persisted_chan_data_0 = persister_0 + .read_all_channel_monitors_with_updates( + &broadcaster_0, + &&chanmon_cfgs[0].fee_estimator, + ) + .unwrap(); // check that we stored only one monitor assert_eq!(persisted_chan_data_0.len(), 1); for (_, mon) in persisted_chan_data_0.iter() { @@ -952,27 +1041,45 @@ mod tests { // if the CM is at consolidation threshold, ensure no updates are stored. let monitor_name = MonitorName::from(mon.get_funding_txo().0); if mon.get_latest_update_id() % persister_0_max_pending_updates == 0 - || mon.get_latest_update_id() == CLOSED_CHANNEL_UPDATE_ID { + || mon.get_latest_update_id() == CLOSED_CHANNEL_UPDATE_ID + { assert_eq!( - persister_0.kv_store.list(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, - monitor_name.as_str()).unwrap().len(), + persister_0 + .kv_store + .list( + CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, + monitor_name.as_str() + ) + .unwrap() + .len(), 0, "updates stored when they shouldn't be in persister 0" ); } } - persisted_chan_data_1 = persister_1.read_all_channel_monitors_with_updates( - &broadcaster_1, &&chanmon_cfgs[1].fee_estimator).unwrap(); + persisted_chan_data_1 = persister_1 + .read_all_channel_monitors_with_updates( + &broadcaster_1, + &&chanmon_cfgs[1].fee_estimator, + ) + .unwrap(); assert_eq!(persisted_chan_data_1.len(), 1); for (_, mon) in persisted_chan_data_1.iter() { assert_eq!(mon.get_latest_update_id(), $expected_update_id); let monitor_name = MonitorName::from(mon.get_funding_txo().0); // if the CM is at consolidation threshold, ensure no updates are stored. if mon.get_latest_update_id() % persister_1_max_pending_updates == 0 - || mon.get_latest_update_id() == CLOSED_CHANNEL_UPDATE_ID { + || mon.get_latest_update_id() == CLOSED_CHANNEL_UPDATE_ID + { assert_eq!( - persister_1.kv_store.list(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, - monitor_name.as_str()).unwrap().len(), + persister_1 + .kv_store + .list( + CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, + monitor_name.as_str() + ) + .unwrap() + .len(), 0, "updates stored when they shouldn't be in persister 1" ); @@ -1009,31 +1116,74 @@ mod tests { // Force close because cooperative close doesn't result in any persisted // updates. - nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); let node_txn = nodes[0].tx_broadcaster.txn_broadcast(); assert_eq!(node_txn.len(), 1); - connect_block(&nodes[1], &create_dummy_block(nodes[0].best_block_hash(), 42, vec![node_txn[0].clone(), node_txn[0].clone()])); + connect_block( + &nodes[1], + &create_dummy_block( + nodes[0].best_block_hash(), + 42, + vec![node_txn[0].clone(), node_txn[0].clone()], + ), + ); check_closed_broadcast!(nodes[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, + ); check_added_monitors!(nodes[1], 1); // Make sure everything is persisted as expected after close. check_persisted_data!(CLOSED_CHANNEL_UPDATE_ID); // Make sure the expected number of stale updates is present. - let persisted_chan_data = persister_0.read_all_channel_monitors_with_updates(&broadcaster_0, &&chanmon_cfgs[0].fee_estimator).unwrap(); + let persisted_chan_data = persister_0 + .read_all_channel_monitors_with_updates(&broadcaster_0, &&chanmon_cfgs[0].fee_estimator) + .unwrap(); let (_, monitor) = &persisted_chan_data[0]; let monitor_name = MonitorName::from(monitor.get_funding_txo().0); // The channel should have 0 updates, as it wrote a full monitor and consolidated. - assert_eq!(persister_0.kv_store.list(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str()).unwrap().len(), 0); - assert_eq!(persister_1.kv_store.list(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str()).unwrap().len(), 0); + assert_eq!( + persister_0 + .kv_store + .list(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str()) + .unwrap() + .len(), + 0 + ); + assert_eq!( + persister_1 + .kv_store + .list(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str()) + .unwrap() + .len(), + 0 + ); } // Test that if the `MonitorUpdatingPersister`'s can't actually write, trying to persist a @@ -1047,15 +1197,31 @@ mod tests { 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); - nodes[1].node.force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()).unwrap(); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000); + nodes[1] + .node + .force_close_broadcasting_latest_txn(&chan.2, &nodes[0].node.get_our_node_id()) + .unwrap(); + check_closed_event( + &nodes[1], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[0].node.get_our_node_id()], + 100000, + ); { let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap(); let update_id = update_map.get(&added_monitors[0].1.channel_id()).unwrap(); let cmu_map = nodes[1].chain_monitor.monitor_updates.lock().unwrap(); let cmu = &cmu_map.get(&added_monitors[0].1.channel_id()).unwrap()[0]; - let test_txo = OutPoint { txid: Txid::from_str("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), index: 0 }; + let test_txo = OutPoint { + txid: Txid::from_str( + "8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be", + ) + .unwrap(), + index: 0, + }; let ro_persister = MonitorUpdatingPersister { kv_store: &TestStore::new(true), @@ -1067,24 +1233,29 @@ mod tests { match ro_persister.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) { ChannelMonitorUpdateStatus::UnrecoverableError => { // correct result - } + }, ChannelMonitorUpdateStatus::Completed => { panic!("Completed persisting new channel when shouldn't have") - } + }, ChannelMonitorUpdateStatus::InProgress => { panic!("Returned InProgress when shouldn't have") - } + }, } - match ro_persister.update_persisted_channel(test_txo, Some(cmu), &added_monitors[0].1, update_id.2) { + match ro_persister.update_persisted_channel( + test_txo, + Some(cmu), + &added_monitors[0].1, + update_id.2, + ) { ChannelMonitorUpdateStatus::UnrecoverableError => { // correct result - } + }, ChannelMonitorUpdateStatus::Completed => { panic!("Completed persisting new channel when shouldn't have") - } + }, ChannelMonitorUpdateStatus::InProgress => { panic!("Returned InProgress when shouldn't have") - } + }, } added_monitors.clear(); } @@ -1136,7 +1307,9 @@ mod tests { // Check that the persisted channel data is empty before any channels are // open. - let persisted_chan_data = persister_0.read_all_channel_monitors_with_updates(&broadcaster_0, &&chanmon_cfgs[0].fee_estimator).unwrap(); + let persisted_chan_data = persister_0 + .read_all_channel_monitors_with_updates(&broadcaster_0, &&chanmon_cfgs[0].fee_estimator) + .unwrap(); assert_eq!(persisted_chan_data.len(), 0); // Create some initial channel @@ -1147,12 +1320,19 @@ mod tests { send_payment(&nodes[1], &vec![&nodes[0]][..], 4_000_000); // Get the monitor and make a fake stale update at update_id=1 (lowest height of an update possible) - let persisted_chan_data = persister_0.read_all_channel_monitors_with_updates(&broadcaster_0, &&chanmon_cfgs[0].fee_estimator).unwrap(); + let persisted_chan_data = persister_0 + .read_all_channel_monitors_with_updates(&broadcaster_0, &&chanmon_cfgs[0].fee_estimator) + .unwrap(); let (_, monitor) = &persisted_chan_data[0]; let monitor_name = MonitorName::from(monitor.get_funding_txo().0); persister_0 .kv_store - .write(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str(), UpdateName::from(1).as_str(), &[0u8; 1]) + .write( + CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, + monitor_name.as_str(), + UpdateName::from(1).as_str(), + &[0u8; 1], + ) .unwrap(); // Do the stale update cleanup @@ -1161,19 +1341,41 @@ mod tests { // Confirm the stale update is unreadable/gone assert!(persister_0 .kv_store - .read(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str(), UpdateName::from(1).as_str()) + .read( + CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, + monitor_name.as_str(), + UpdateName::from(1).as_str() + ) .is_err()); // Force close. - nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap(); - check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000); + nodes[0] + .node + .force_close_broadcasting_latest_txn( + &nodes[0].node.list_channels()[0].channel_id, + &nodes[1].node.get_our_node_id(), + ) + .unwrap(); + check_closed_event( + &nodes[0], + 1, + ClosureReason::HolderForceClosed, + false, + &[nodes[1].node.get_our_node_id()], + 100000, + ); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); // Write an update near u64::MAX persister_0 .kv_store - .write(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str(), UpdateName::from(u64::MAX - 1).as_str(), &[0u8; 1]) + .write( + CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, + monitor_name.as_str(), + UpdateName::from(u64::MAX - 1).as_str(), + &[0u8; 1], + ) .unwrap(); // Do the stale update cleanup @@ -1182,7 +1384,11 @@ mod tests { // Confirm the stale update is unreadable/gone assert!(persister_0 .kv_store - .read(CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, monitor_name.as_str(), UpdateName::from(u64::MAX - 1).as_str()) + .read( + CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE, + monitor_name.as_str(), + UpdateName::from(u64::MAX - 1).as_str() + ) .is_err()); } } diff --git a/lightning/src/util/scid_utils.rs b/lightning/src/util/scid_utils.rs index 9d943b4d466..832c201d562 100644 --- a/lightning/src/util/scid_utils.rs +++ b/lightning/src/util/scid_utils.rs @@ -49,7 +49,9 @@ pub fn vout_from_scid(short_channel_id: &u64) -> u16 { /// Constructs a `short_channel_id` using the components pieces. Results in an error /// if the block height, tx index, or vout index overflow the maximum sizes. -pub fn scid_from_parts(block: u64, tx_index: u64, vout_index: u64) -> Result { +pub fn scid_from_parts( + block: u64, tx_index: u64, vout_index: u64, +) -> Result { if block > MAX_SCID_BLOCK { return Err(ShortChannelIdError::BlockOverflow); } @@ -71,11 +73,11 @@ pub fn scid_from_parts(block: u64, tx_index: u64, vout_index: u64) -> Result(&self, highest_seen_blockheight: u32, chain_hash: &ChainHash, fake_scid_rand_bytes: &[u8; 32], entropy_source: &ES) -> u64 - where ES::Target: EntropySource, + pub(crate) fn get_fake_scid( + &self, highest_seen_blockheight: u32, chain_hash: &ChainHash, + fake_scid_rand_bytes: &[u8; 32], entropy_source: &ES, + ) -> u64 + where + ES::Target: EntropySource, { // Ensure we haven't created a namespace that doesn't fit into the 3 bits we've allocated for // namespaces. @@ -118,27 +123,38 @@ pub(crate) mod fake_scid { let rand_bytes = entropy_source.get_secure_random_bytes(); let segwit_activation_height = segwit_activation_height(chain_hash); - let mut blocks_since_segwit_activation = highest_seen_blockheight.saturating_sub(segwit_activation_height); + let mut blocks_since_segwit_activation = + highest_seen_blockheight.saturating_sub(segwit_activation_height); // We want to ensure that this fake channel won't conflict with any transactions we haven't // seen yet, in case `highest_seen_blockheight` is updated before we get full information // about transactions confirmed in the given block. - blocks_since_segwit_activation = blocks_since_segwit_activation.saturating_sub(MAX_SCID_BLOCKS_FROM_NOW); + blocks_since_segwit_activation = + blocks_since_segwit_activation.saturating_sub(MAX_SCID_BLOCKS_FROM_NOW); let rand_for_height = u32::from_be_bytes(rand_bytes[..4].try_into().unwrap()); - let fake_scid_height = segwit_activation_height + rand_for_height % (blocks_since_segwit_activation + 1); + let fake_scid_height = + segwit_activation_height + rand_for_height % (blocks_since_segwit_activation + 1); let rand_for_tx_index = u32::from_be_bytes(rand_bytes[4..8].try_into().unwrap()); let fake_scid_tx_index = rand_for_tx_index % MAX_TX_INDEX; // Put the scid in the given namespace. - let fake_scid_vout = self.get_encrypted_vout(fake_scid_height, fake_scid_tx_index, fake_scid_rand_bytes); - scid_utils::scid_from_parts(fake_scid_height as u64, fake_scid_tx_index as u64, fake_scid_vout as u64).unwrap() + let fake_scid_vout = + self.get_encrypted_vout(fake_scid_height, fake_scid_tx_index, fake_scid_rand_bytes); + scid_utils::scid_from_parts( + fake_scid_height as u64, + fake_scid_tx_index as u64, + fake_scid_vout as u64, + ) + .unwrap() } /// We want to ensure that a 3rd party can't identify a payment as belong to a given /// `Namespace`. Therefore, we encrypt it using a random bytes provided by `ChannelManager`. - fn get_encrypted_vout(&self, block_height: u32, tx_index: u32, fake_scid_rand_bytes: &[u8; 32]) -> u8 { + fn get_encrypted_vout( + &self, block_height: u32, tx_index: u32, fake_scid_rand_bytes: &[u8; 32], + ) -> u8 { let mut salt = [0 as u8; 8]; let block_height_bytes = block_height.to_be_bytes(); salt[0..4].copy_from_slice(&block_height_bytes); @@ -161,7 +177,9 @@ pub(crate) mod fake_scid { } /// Returns whether the given fake scid falls into the phantom namespace. - pub fn is_valid_phantom(fake_scid_rand_bytes: &[u8; 32], scid: u64, chain_hash: &ChainHash) -> bool { + pub fn is_valid_phantom( + fake_scid_rand_bytes: &[u8; 32], scid: u64, chain_hash: &ChainHash, + ) -> bool { let block_height = scid_utils::block_from_scid(&scid); let tx_index = scid_utils::tx_index_from_scid(&scid); let namespace = Namespace::Phantom; @@ -171,7 +189,9 @@ pub(crate) mod fake_scid { } /// Returns whether the given fake scid falls into the intercept namespace. - pub fn is_valid_intercept(fake_scid_rand_bytes: &[u8; 32], scid: u64, chain_hash: &ChainHash) -> bool { + pub fn is_valid_intercept( + fake_scid_rand_bytes: &[u8; 32], scid: u64, chain_hash: &ChainHash, + ) -> bool { let block_height = scid_utils::block_from_scid(&scid); let tx_index = scid_utils::tx_index_from_scid(&scid); let namespace = Namespace::Intercept; @@ -182,12 +202,16 @@ pub(crate) mod fake_scid { #[cfg(test)] mod tests { - use bitcoin::blockdata::constants::ChainHash; - use bitcoin::network::constants::Network; - use crate::util::scid_utils::fake_scid::{is_valid_intercept, is_valid_phantom, MAINNET_SEGWIT_ACTIVATION_HEIGHT, MAX_TX_INDEX, MAX_NAMESPACES, Namespace, NAMESPACE_ID_BITMASK, segwit_activation_height, TEST_SEGWIT_ACTIVATION_HEIGHT}; + use crate::sync::Arc; use crate::util::scid_utils; + use crate::util::scid_utils::fake_scid::{ + is_valid_intercept, is_valid_phantom, segwit_activation_height, Namespace, + MAINNET_SEGWIT_ACTIVATION_HEIGHT, MAX_NAMESPACES, MAX_TX_INDEX, NAMESPACE_ID_BITMASK, + TEST_SEGWIT_ACTIVATION_HEIGHT, + }; use crate::util::test_utils; - use crate::sync::Arc; + use bitcoin::blockdata::constants::ChainHash; + use bitcoin::network::constants::Network; #[test] fn namespace_identifier_is_within_range() { @@ -203,7 +227,10 @@ pub(crate) mod fake_scid { #[test] fn test_segwit_activation_height() { let mainnet_genesis = ChainHash::using_genesis_block(Network::Bitcoin); - assert_eq!(segwit_activation_height(&mainnet_genesis), MAINNET_SEGWIT_ACTIVATION_HEIGHT); + assert_eq!( + segwit_activation_height(&mainnet_genesis), + MAINNET_SEGWIT_ACTIVATION_HEIGHT + ); let testnet_genesis = ChainHash::using_genesis_block(Network::Testnet); assert_eq!(segwit_activation_height(&testnet_genesis), TEST_SEGWIT_ACTIVATION_HEIGHT); @@ -221,7 +248,8 @@ pub(crate) mod fake_scid { let fake_scid_rand_bytes = [0; 32]; let testnet_genesis = ChainHash::using_genesis_block(Network::Testnet); let valid_encrypted_vout = namespace.get_encrypted_vout(0, 0, &fake_scid_rand_bytes); - let valid_fake_scid = scid_utils::scid_from_parts(1, 0, valid_encrypted_vout as u64).unwrap(); + let valid_fake_scid = + scid_utils::scid_from_parts(1, 0, valid_encrypted_vout as u64).unwrap(); assert!(is_valid_phantom(&fake_scid_rand_bytes, valid_fake_scid, &testnet_genesis)); let invalid_fake_scid = scid_utils::scid_from_parts(1, 0, 12).unwrap(); assert!(!is_valid_phantom(&fake_scid_rand_bytes, invalid_fake_scid, &testnet_genesis)); @@ -233,10 +261,15 @@ pub(crate) mod fake_scid { let fake_scid_rand_bytes = [0; 32]; let testnet_genesis = ChainHash::using_genesis_block(Network::Testnet); let valid_encrypted_vout = namespace.get_encrypted_vout(0, 0, &fake_scid_rand_bytes); - let valid_fake_scid = scid_utils::scid_from_parts(1, 0, valid_encrypted_vout as u64).unwrap(); + let valid_fake_scid = + scid_utils::scid_from_parts(1, 0, valid_encrypted_vout as u64).unwrap(); assert!(is_valid_intercept(&fake_scid_rand_bytes, valid_fake_scid, &testnet_genesis)); let invalid_fake_scid = scid_utils::scid_from_parts(1, 0, 12).unwrap(); - assert!(!is_valid_intercept(&fake_scid_rand_bytes, invalid_fake_scid, &testnet_genesis)); + assert!(!is_valid_intercept( + &fake_scid_rand_bytes, + invalid_fake_scid, + &testnet_genesis + )); } #[test] @@ -244,9 +277,15 @@ pub(crate) mod fake_scid { let mainnet_genesis = ChainHash::using_genesis_block(Network::Bitcoin); let seed = [0; 32]; let fake_scid_rand_bytes = [1; 32]; - let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet)); + let keys_manager = + Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet)); let namespace = Namespace::Phantom; - let fake_scid = namespace.get_fake_scid(500_000, &mainnet_genesis, &fake_scid_rand_bytes, &keys_manager); + let fake_scid = namespace.get_fake_scid( + 500_000, + &mainnet_genesis, + &fake_scid_rand_bytes, + &keys_manager, + ); let fake_height = scid_utils::block_from_scid(&fake_scid); assert!(fake_height >= MAINNET_SEGWIT_ACTIVATION_HEIGHT); @@ -298,8 +337,17 @@ mod tests { assert_eq!(scid_from_parts(0x00000001, 0x00000002, 0x0003).unwrap(), 0x000001_000002_0003); assert_eq!(scid_from_parts(0x00111111, 0x00222222, 0x3333).unwrap(), 0x111111_222222_3333); assert_eq!(scid_from_parts(0x00ffffff, 0x00ffffff, 0xffff).unwrap(), 0xffffff_ffffff_ffff); - assert_eq!(scid_from_parts(0x01ffffff, 0x00000000, 0x0000).err().unwrap(), ShortChannelIdError::BlockOverflow); - assert_eq!(scid_from_parts(0x00000000, 0x01ffffff, 0x0000).err().unwrap(), ShortChannelIdError::TxIndexOverflow); - assert_eq!(scid_from_parts(0x00000000, 0x00000000, 0x010000).err().unwrap(), ShortChannelIdError::VoutIndexOverflow); + assert_eq!( + scid_from_parts(0x01ffffff, 0x00000000, 0x0000).err().unwrap(), + ShortChannelIdError::BlockOverflow + ); + assert_eq!( + scid_from_parts(0x00000000, 0x01ffffff, 0x0000).err().unwrap(), + ShortChannelIdError::TxIndexOverflow + ); + assert_eq!( + scid_from_parts(0x00000000, 0x00000000, 0x010000).err().unwrap(), + ShortChannelIdError::VoutIndexOverflow + ); } } diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 484d6034042..6a40db662f4 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -13,35 +13,37 @@ //! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager //! [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor -use crate::prelude::*; use crate::io::{self, Read, Seek, Write}; use crate::io_extras::{copy, sink}; -use core::hash::Hash; +use crate::prelude::*; use crate::sync::{Mutex, RwLock}; use core::cmp; use core::convert::TryFrom; +use core::hash::Hash; use core::ops::Deref; use alloc::collections::BTreeMap; -use bitcoin::secp256k1::{PublicKey, SecretKey}; -use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, COMPACT_SIGNATURE_SIZE, SCHNORR_SIGNATURE_SIZE}; -use bitcoin::secp256k1::ecdsa; -use bitcoin::secp256k1::schnorr; +use crate::chain::ClaimId; +use crate::ln::msgs::DecodeError; +#[cfg(taproot)] +use crate::ln::msgs::PartialSignatureWithNonce; +use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::script::{self, ScriptBuf}; use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut}; -use bitcoin::{consensus, Witness}; use bitcoin::consensus::Encodable; +use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::hashes::sha256d::Hash as Sha256dHash; -use bitcoin::hash_types::{Txid, BlockHash}; +use bitcoin::secp256k1::constants::{ + COMPACT_SIGNATURE_SIZE, PUBLIC_KEY_SIZE, SCHNORR_SIGNATURE_SIZE, SECRET_KEY_SIZE, +}; +use bitcoin::secp256k1::ecdsa; +use bitcoin::secp256k1::schnorr; +use bitcoin::secp256k1::{PublicKey, SecretKey}; +use bitcoin::{consensus, Witness}; use core::marker::Sized; use core::time::Duration; -use crate::chain::ClaimId; -use crate::ln::msgs::DecodeError; -#[cfg(taproot)] -use crate::ln::msgs::PartialSignatureWithNonce; -use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use crate::util::byte_utils::{be48_to_array, slice_to_be48}; use crate::util::string::UntrustedString; @@ -234,14 +236,17 @@ pub trait Writeable { } impl<'a, T: Writeable> Writeable for &'a T { - fn write(&self, writer: &mut W) -> Result<(), io::Error> { (*self).write(writer) } + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + (*self).write(writer) + } } /// A trait that various LDK types implement allowing them to be read in from a [`Read`]. /// /// This is not exported to bindings users as we only export serialization to/from byte arrays instead pub trait Readable - where Self: Sized +where + Self: Sized, { /// Reads a `Self` in from the given [`Read`]. fn read(reader: &mut R) -> Result; @@ -249,7 +254,10 @@ pub trait Readable /// A trait that various LDK types implement allowing them to be read in from a /// [`Read`]` + `[`Seek`]. -pub(crate) trait SeekReadable where Self: Sized { +pub(crate) trait SeekReadable +where + Self: Sized, +{ /// Reads a `Self` in from the given [`Read`]. fn read(reader: &mut R) -> Result; } @@ -259,7 +267,8 @@ pub(crate) trait SeekReadable where Self: Sized { /// /// This is not exported to bindings users as we only export serialization to/from byte arrays instead pub trait ReadableArgs

- where Self: Sized +where + Self: Sized, { /// Reads a `Self` in from the given [`Read`]. fn read(reader: &mut R, params: P) -> Result; @@ -274,7 +283,9 @@ pub(crate) trait LengthRead: Read { /// A trait that various higher-level LDK types implement allowing them to be read in /// from a Read given some additional set of arguments which is required to deserialize, requiring /// the implementer to provide the total length of the read. -pub(crate) trait LengthReadableArgs

where Self: Sized +pub(crate) trait LengthReadableArgs

+where + Self: Sized, { /// Reads a `Self` in from the given [`LengthRead`]. fn read(reader: &mut R, params: P) -> Result; @@ -282,7 +293,9 @@ pub(crate) trait LengthReadableArgs

where Self: Sized /// A trait that various higher-level LDK types implement allowing them to be read in /// from a [`Read`], requiring the implementer to provide the total length of the read. -pub(crate) trait LengthReadable where Self: Sized +pub(crate) trait LengthReadable +where + Self: Sized, { /// Reads a `Self` in from the given [`LengthRead`]. fn read(reader: &mut R) -> Result; @@ -292,7 +305,8 @@ pub(crate) trait LengthReadable where Self: Sized /// /// This is not exported to bindings users as we only export serialization to/from byte arrays instead pub trait MaybeReadable - where Self: Sized +where + Self: Sized, { /// Reads a `Self` in from the given [`Read`]. fn read(reader: &mut R) -> Result, DecodeError>; @@ -325,7 +339,9 @@ impl> ReadableArgs for RequiredWrapper { /// to a `RequiredWrapper` in a way that works for `field: T = t;` as /// well. Thus, we assume `Into for T` does nothing and use that. impl From for RequiredWrapper { - fn from(t: T) -> RequiredWrapper { RequiredWrapper(Some(t)) } + fn from(t: T) -> RequiredWrapper { + RequiredWrapper(Some(t)) + } } /// Wrapper to read a required (non-optional) TLV record that may have been upgraded without @@ -337,7 +353,9 @@ impl MaybeReadable for UpgradableRequired { #[inline] fn read(reader: &mut R) -> Result, DecodeError> { let tlv = MaybeReadable::read(reader)?; - if let Some(tlv) = tlv { return Ok(Some(Self(Some(tlv)))) } + if let Some(tlv) = tlv { + return Ok(Some(Self(Some(tlv)))); + } Ok(None) } } @@ -371,9 +389,7 @@ impl Writeable for BigSize { #[inline] fn write(&self, writer: &mut W) -> Result<(), io::Error> { match self.0 { - 0..=0xFC => { - (self.0 as u8).write(writer) - }, + 0..=0xFC => (self.0 as u8).write(writer), 0xFD..=0xFFFF => { 0xFDu8.write(writer)?; (self.0 as u16).write(writer) @@ -401,7 +417,7 @@ impl Readable for BigSize { } else { Ok(BigSize(x)) } - } + }, 0xFE => { let x: u32 = Readable::read(reader)?; if x < 0x10000 { @@ -409,7 +425,7 @@ impl Readable for BigSize { } else { Ok(BigSize(x as u64)) } - } + }, 0xFD => { let x: u16 = Readable::read(reader)?; if x < 0xFD { @@ -417,8 +433,8 @@ impl Readable for BigSize { } else { Ok(BigSize(x as u64)) } - } - n => Ok(BigSize(n as u64)) + }, + n => Ok(BigSize(n as u64)), } } } @@ -450,8 +466,8 @@ impl Readable for CollectionLength { fn read(r: &mut R) -> Result { let mut val: u64 = ::read(r)? as u64; if val == 0xffff { - val = ::read(r)? - .checked_add(0xffff).ok_or(DecodeError::InvalidValue)?; + val = + ::read(r)?.checked_add(0xffff).ok_or(DecodeError::InvalidValue)?; } Ok(CollectionLength(val)) } @@ -475,7 +491,7 @@ macro_rules! impl_writeable_primitive { #[inline] fn write(&self, writer: &mut W) -> Result<(), io::Error> { // Skip any full leading 0 bytes when writing (in BE): - writer.write_all(&self.0.to_be_bytes()[(self.0.leading_zeros()/8) as usize..$len]) + writer.write_all(&self.0.to_be_bytes()[(self.0.leading_zeros() / 8) as usize..$len]) } } impl Readable for $val_type { @@ -488,12 +504,14 @@ macro_rules! impl_writeable_primitive { } impl Readable for HighZeroBytesDroppedBigSize<$val_type> { #[inline] - fn read(reader: &mut R) -> Result, DecodeError> { + fn read( + reader: &mut R, + ) -> Result, DecodeError> { // We need to accept short reads (read_len == 0) as "EOF" and handle them as simply // the high bytes being dropped. To do so, we start reading into the middle of buf // and then convert the appropriate number of bytes with extra high bytes out of // buf. - let mut buf = [0; $len*2]; + let mut buf = [0; $len * 2]; let mut read_len = reader.read(&mut buf[$len..])?; let mut total_read_len = read_len; while read_len != 0 && total_read_len != $len { @@ -513,9 +531,11 @@ macro_rules! impl_writeable_primitive { } } impl From<$val_type> for HighZeroBytesDroppedBigSize<$val_type> { - fn from(val: $val_type) -> Self { Self(val) } + fn from(val: $val_type) -> Self { + Self(val) + } } - } + }; } impl_writeable_primitive!(u128, 16); @@ -545,7 +565,7 @@ impl Readable for u8 { impl Writeable for bool { #[inline] fn write(&self, writer: &mut W) -> Result<(), io::Error> { - writer.write_all(&[if *self {1} else {0}]) + writer.write_all(&[if *self { 1 } else { 0 }]) } } impl Readable for bool { @@ -561,14 +581,15 @@ impl Readable for bool { } macro_rules! impl_array { - ($size:expr, $ty: ty) => ( + ($size:expr, $ty: ty) => { impl Writeable for [$ty; $size] { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { let mut out = [0; $size * core::mem::size_of::<$ty>()]; for (idx, v) in self.iter().enumerate() { let startpos = idx * core::mem::size_of::<$ty>(); - out[startpos..startpos + core::mem::size_of::<$ty>()].copy_from_slice(&v.to_be_bytes()); + out[startpos..startpos + core::mem::size_of::<$ty>()] + .copy_from_slice(&v.to_be_bytes()); } w.write_all(&out) } @@ -589,7 +610,7 @@ macro_rules! impl_array { Ok(res) } } - ); + }; } impl_array!(3, u8); // for rgb, ISO 4712 code @@ -625,14 +646,15 @@ impl Readable for WithoutLength { } } impl<'a> From<&'a String> for WithoutLength<&'a String> { - fn from(s: &'a String) -> Self { Self(s) } + fn from(s: &'a String) -> Self { + Self(s) + } } - impl Writeable for WithoutLength<&UntrustedString> { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { - WithoutLength(&self.0.0).write(w) + WithoutLength(&self.0 .0).write(w) } } impl Readable for WithoutLength { @@ -660,8 +682,10 @@ impl Readable for WithoutLength> { loop { let mut track_read = ReadTrackingReader::new(&mut reader); match MaybeReadable::read(&mut track_read) { - Ok(Some(v)) => { values.push(v); }, - Ok(None) => { }, + Ok(Some(v)) => { + values.push(v); + }, + Ok(None) => {}, // If we failed to read any bytes at all, we reached the end of our TLV // stream and have simply exhausted all entries. Err(ref e) if e == &DecodeError::ShortRead && !track_read.have_read => break, @@ -672,7 +696,9 @@ impl Readable for WithoutLength> { } } impl<'a, T> From<&'a Vec> for WithoutLength<&'a Vec> { - fn from(v: &'a Vec) -> Self { Self(v) } + fn from(v: &'a Vec) -> Self { + Self(v) + } } impl Writeable for WithoutLength<&ScriptBuf> { @@ -713,7 +739,9 @@ impl<'a, I: Iterator + Clone, T: 'a + PartialEq> PartialEq for Ite macro_rules! impl_for_map { ($ty: ident, $keybound: ident, $constr: expr) => { impl Writeable for $ty - where K: Writeable + Eq + $keybound, V: Writeable + where + K: Writeable + Eq + $keybound, + V: Writeable, { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { @@ -727,7 +755,9 @@ macro_rules! impl_for_map { } impl Readable for $ty - where K: Readable + Eq + $keybound, V: MaybeReadable + where + K: Readable + Eq + $keybound, + V: MaybeReadable, { #[inline] fn read(r: &mut R) -> Result { @@ -745,7 +775,7 @@ macro_rules! impl_for_map { Ok(ret) } } - } + }; } impl_for_map!(BTreeMap, Ord, |_| BTreeMap::new()); @@ -753,7 +783,8 @@ impl_for_map!(HashMap, Hash, |len| HashMap::with_capacity(len)); // HashSet impl Writeable for HashSet -where T: Writeable + Eq + Hash +where + T: Writeable + Eq + Hash, { #[inline] fn write(&self, w: &mut W) -> Result<(), io::Error> { @@ -766,15 +797,19 @@ where T: Writeable + Eq + Hash } impl Readable for HashSet -where T: Readable + Eq + Hash +where + T: Readable + Eq + Hash, { #[inline] fn read(r: &mut R) -> Result { let len: CollectionLength = Readable::read(r)?; - let mut ret = HashSet::with_capacity(cmp::min(len.0 as usize, MAX_BUF_SIZE / core::mem::size_of::())); + let mut ret = HashSet::with_capacity(cmp::min( + len.0 as usize, + MAX_BUF_SIZE / core::mem::size_of::(), + )); for _ in 0..len.0 { if !ret.insert(T::read(r)?) { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } } Ok(ret) @@ -970,7 +1005,8 @@ impl Writeable for PartialSignatureWithNonce { impl Readable for PartialSignatureWithNonce { fn read(r: &mut R) -> Result { let partial_signature_buf: [u8; SECRET_KEY_SIZE] = Readable::read(r)?; - let partial_signature = musig2::types::PartialSignature::from_slice(&partial_signature_buf).map_err(|_| DecodeError::InvalidValue)?; + let partial_signature = musig2::types::PartialSignature::from_slice(&partial_signature_buf) + .map_err(|_| DecodeError::InvalidValue)?; let public_nonce: musig2::types::PublicNonce = Readable::read(r)?; Ok(PartialSignatureWithNonce(partial_signature, public_nonce)) } @@ -1081,14 +1117,13 @@ impl Writeable for Option { Some(ref data) => { BigSize(data.serialized_length() as u64 + 1).write(w)?; data.write(w)?; - } + }, } Ok(()) } } -impl Readable for Option -{ +impl Readable for Option { fn read(r: &mut R) -> Result { let len: BigSize = Readable::read(r)?; match len.0 { @@ -1096,7 +1131,7 @@ impl Readable for Option len => { let mut reader = FixedLengthReader::new(r, len - 1); Ok(Some(Readable::read(&mut reader)?)) - } + }, } } } @@ -1156,10 +1191,7 @@ impl Readable for OutPoint { fn read(r: &mut R) -> Result { let txid = Readable::read(r)?; let vout = Readable::read(r)?; - Ok(OutPoint { - txid, - vout, - }) + Ok(OutPoint { txid, vout }) } } @@ -1178,13 +1210,17 @@ macro_rules! impl_consensus_ser { fn read(r: &mut R) -> Result { match consensus::encode::Decodable::consensus_decode(r) { Ok(t) => Ok(t), - Err(consensus::encode::Error::Io(ref e)) if e.kind() == io::ErrorKind::UnexpectedEof => Err(DecodeError::ShortRead), + Err(consensus::encode::Error::Io(ref e)) + if e.kind() == io::ErrorKind::UnexpectedEof => + { + Err(DecodeError::ShortRead) + }, Err(consensus::encode::Error::Io(e)) => Err(DecodeError::Io(e.kind())), Err(_) => Err(DecodeError::InvalidValue), } } } - } + }; } impl_consensus_ser!(Transaction); impl_consensus_ser!(TxOut); @@ -1338,11 +1374,7 @@ impl TryFrom for Hostname { type Error = (); fn try_from(s: String) -> Result { - if s.len() <= 255 && s.chars().all(|c| - c.is_ascii_alphanumeric() || - c == '.' || - c == '-' - ) { + if s.len() <= 255 && s.chars().all(|c| c.is_ascii_alphanumeric() || c == '.' || c == '-') { Ok(Hostname(s)) } else { Err(()) @@ -1443,10 +1475,10 @@ impl Readable for ClaimId { #[cfg(test)] mod tests { - use core::convert::TryFrom; + use crate::util::ser::{Hostname, Readable, Writeable}; use bitcoin::hashes::hex::FromHex; use bitcoin::secp256k1::ecdsa; - use crate::util::ser::{Readable, Hostname, Writeable}; + use core::convert::TryFrom; #[test] fn hostname_conversion() { @@ -1490,7 +1522,7 @@ mod tests { "fe00010000", "feffffffff", "ff0000000100000000", - "ffffffffffffffffff" + "ffffffffffffffffff", ]; for i in 0..=7 { let mut stream = crate::io::Cursor::new(>::from_hex(bytes[i]).unwrap()); @@ -1509,14 +1541,20 @@ mod tests { "fd", "fe", "ff", - "" + "", ]; for i in 0..=9 { let mut stream = crate::io::Cursor::new(>::from_hex(err_bytes[i]).unwrap()); if i < 3 { - assert_eq!(super::BigSize::read(&mut stream).err(), Some(crate::ln::msgs::DecodeError::InvalidValue)); + assert_eq!( + super::BigSize::read(&mut stream).err(), + Some(crate::ln::msgs::DecodeError::InvalidValue) + ); } else { - assert_eq!(super::BigSize::read(&mut stream).err(), Some(crate::ln::msgs::DecodeError::ShortRead)); + assert_eq!( + super::BigSize::read(&mut stream).err(), + Some(crate::ln::msgs::DecodeError::ShortRead) + ); } } } diff --git a/lightning/src/util/ser_macros.rs b/lightning/src/util/ser_macros.rs index 84d9f7a180b..ce56c6882b2 100644 --- a/lightning/src/util/ser_macros.rs +++ b/lightning/src/util/ser_macros.rs @@ -82,10 +82,11 @@ macro_rules! _encode_tlv { #[doc(hidden)] #[macro_export] macro_rules! _check_encoded_tlv_order { - ($last_type: expr, $type: expr, (static_value, $value: expr)) => { }; + ($last_type: expr, $type: expr, (static_value, $value: expr)) => {}; ($last_type: expr, $type: expr, $fieldty: tt) => { if let Some(t) = $last_type { - #[allow(unused_comparisons)] // Note that $type may be 0 making the following comparison always false + #[allow(unused_comparisons)] + // Note that $type may be 0 making the following comparison always false (debug_assert!(t < $type)) } $last_type = Some($type); @@ -187,22 +188,32 @@ macro_rules! _get_varint_length_prefixed_tlv_length { ($len: expr, $type: expr, $field: expr, (default_value, $default: expr)) => { $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required) }; - ($len: expr, $type: expr, $field: expr, (static_value, $value: expr)) => { - }; + ($len: expr, $type: expr, $field: expr, (static_value, $value: expr)) => {}; ($len: expr, $type: expr, $field: expr, required) => { BigSize($type).write(&mut $len).expect("No in-memory data may fail to serialize"); let field_len = $field.serialized_length(); - BigSize(field_len as u64).write(&mut $len).expect("No in-memory data may fail to serialize"); + BigSize(field_len as u64) + .write(&mut $len) + .expect("No in-memory data may fail to serialize"); $len.0 += field_len; }; ($len: expr, $type: expr, $field: expr, required_vec) => { - $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $crate::util::ser::WithoutLength(&$field), required); + $crate::_get_varint_length_prefixed_tlv_length!( + $len, + $type, + $crate::util::ser::WithoutLength(&$field), + required + ); }; ($len: expr, $optional_type: expr, $optional_field: expr, option) => { if let Some(ref field) = $optional_field { - BigSize($optional_type).write(&mut $len).expect("No in-memory data may fail to serialize"); + BigSize($optional_type) + .write(&mut $len) + .expect("No in-memory data may fail to serialize"); let field_len = field.serialized_length(); - BigSize(field_len as u64).write(&mut $len).expect("No in-memory data may fail to serialize"); + BigSize(field_len as u64) + .write(&mut $len) + .expect("No in-memory data may fail to serialize"); $len.0 += field_len; } }; @@ -215,7 +226,12 @@ macro_rules! _get_varint_length_prefixed_tlv_length { $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, option); }; ($len: expr, $type: expr, $field: expr, (option, encoding: ($fieldty: ty, $encoding: ident))) => { - $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field.map(|f| $encoding(f)), option); + $crate::_get_varint_length_prefixed_tlv_length!( + $len, + $type, + $field.map(|f| $encoding(f)), + option + ); }; ($len: expr, $type: expr, $field: expr, upgradable_required) => { $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required); @@ -260,17 +276,20 @@ macro_rules! _encode_varint_length_prefixed_tlv { #[macro_export] macro_rules! _check_decoded_tlv_order { ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (default_value, $default: expr)) => {{ - #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always false - let invalid_order = ($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type; + #[allow(unused_comparisons)] + // Note that $type may be 0 making the second comparison always false + let invalid_order = + ($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type; if invalid_order { $field = $default.into(); } }}; - ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (static_value, $value: expr)) => { - }; + ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (static_value, $value: expr)) => {}; ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, required) => {{ - #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always false - let invalid_order = ($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type; + #[allow(unused_comparisons)] + // Note that $type may be 0 making the second comparison always false + let invalid_order = + ($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type; if invalid_order { return Err(DecodeError::InvalidValue); } @@ -307,7 +326,8 @@ macro_rules! _check_decoded_tlv_order { #[macro_export] macro_rules! _check_missing_tlv { ($last_seen_type: expr, $type: expr, $field: ident, (default_value, $default: expr)) => {{ - #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always false + #[allow(unused_comparisons)] + // Note that $type may be 0 making the second comparison always false let missing_req_type = $last_seen_type.is_none() || $last_seen_type.unwrap() < $type; if missing_req_type { $field = $default.into(); @@ -317,7 +337,8 @@ macro_rules! _check_missing_tlv { $field = $value; }; ($last_seen_type: expr, $type: expr, $field: ident, required) => {{ - #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always false + #[allow(unused_comparisons)] + // Note that $type may be 0 making the second comparison always false let missing_req_type = $last_seen_type.is_none() || $last_seen_type.unwrap() < $type; if missing_req_type { return Err(DecodeError::InvalidValue); @@ -414,8 +435,12 @@ macro_rules! _decode_tlv { #[doc(hidden)] #[macro_export] macro_rules! _decode_tlv_stream_match_check { - ($val: ident, $type: expr, (static_value, $value: expr)) => { false }; - ($val: ident, $type: expr, $fieldty: tt) => { $val == $type } + ($val: ident, $type: expr, (static_value, $value: expr)) => { + false + }; + ($val: ident, $type: expr, $fieldty: tt) => { + $val == $type + }; } /// Implements the TLVs deserialization part in a [`Readable`] implementation of a struct. @@ -666,7 +691,7 @@ macro_rules! write_ver_prefix { ($stream: expr, $this_version: expr, $min_version_that_can_read_this: expr) => { $stream.write_all(&[$this_version; 1])?; $stream.write_all(&[$min_version_that_can_read_this; 1])?; - } + }; } /// Writes out a suffix to an object as a length-prefixed TLV stream which contains potentially @@ -690,14 +715,14 @@ macro_rules! write_tlv_fields { /// serialization logic for this object. This is compared against the /// `$min_version_that_can_read_this` added by [`write_ver_prefix`]. macro_rules! read_ver_prefix { - ($stream: expr, $this_version: expr) => { { + ($stream: expr, $this_version: expr) => {{ let ver: u8 = Readable::read($stream)?; let min_ver: u8 = Readable::read($stream)?; if min_ver > $this_version { return Err(DecodeError::UnknownVersion); } ver - } } + }}; } /// Reads a suffix added by [`write_tlv_fields`]. @@ -955,9 +980,15 @@ macro_rules! tlv_stream { } macro_rules! tlv_record_type { - (($type:ty, $wrapper:ident)) => { $type }; - (($type:ty, $wrapper:ident, $encoder:ty)) => { $type }; - ($type:ty) => { $type }; + (($type:ty, $wrapper:ident)) => { + $type + }; + (($type:ty, $wrapper:ident, $encoder:ty)) => { + $type + }; + ($type:ty) => { + $type + }; } macro_rules! tlv_record_ref_type { @@ -1113,9 +1144,9 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable { #[cfg(test)] mod tests { use crate::io::{self, Cursor}; - use crate::prelude::*; use crate::ln::msgs::DecodeError; - use crate::util::ser::{Writeable, HighZeroBytesDroppedBigSize, VecWriter}; + use crate::prelude::*; + use crate::util::ser::{HighZeroBytesDroppedBigSize, VecWriter, Writeable}; use bitcoin::hashes::hex::FromHex; use bitcoin::secp256k1::PublicKey; @@ -1134,54 +1165,81 @@ mod tests { #[test] fn tlv_v_short_read() { // We only expect a u32 for type 3 (which we are given), but the L says its 8 bytes. - if let Err(DecodeError::ShortRead) = tlv_reader(&>::from_hex( - concat!("0100", "0208deadbeef1badbeef", "0308deadbeef") - ).unwrap()[..]) { - } else { panic!(); } + if let Err(DecodeError::ShortRead) = tlv_reader( + &>::from_hex(concat!("0100", "0208deadbeef1badbeef", "0308deadbeef")).unwrap() + [..], + ) { + } else { + panic!(); + } } #[test] fn tlv_types_out_of_order() { - if let Err(DecodeError::InvalidValue) = tlv_reader(&>::from_hex( - concat!("0100", "0304deadbeef", "0208deadbeef1badbeef") - ).unwrap()[..]) { - } else { panic!(); } + if let Err(DecodeError::InvalidValue) = tlv_reader( + &>::from_hex(concat!("0100", "0304deadbeef", "0208deadbeef1badbeef")).unwrap() + [..], + ) { + } else { + panic!(); + } // ...even if its some field we don't understand - if let Err(DecodeError::InvalidValue) = tlv_reader(&>::from_hex( - concat!("0208deadbeef1badbeef", "0100", "0304deadbeef") - ).unwrap()[..]) { - } else { panic!(); } + if let Err(DecodeError::InvalidValue) = tlv_reader( + &>::from_hex(concat!("0208deadbeef1badbeef", "0100", "0304deadbeef")).unwrap() + [..], + ) { + } else { + panic!(); + } } #[test] fn tlv_req_type_missing_or_extra() { // It's also bad if they included even fields we don't understand - if let Err(DecodeError::UnknownRequiredFeature) = tlv_reader(&>::from_hex( - concat!("0100", "0208deadbeef1badbeef", "0304deadbeef", "0600") - ).unwrap()[..]) { - } else { panic!(); } + if let Err(DecodeError::UnknownRequiredFeature) = tlv_reader( + &>::from_hex(concat!("0100", "0208deadbeef1badbeef", "0304deadbeef", "0600")) + .unwrap()[..], + ) { + } else { + panic!(); + } // ... or if they're missing fields we need - if let Err(DecodeError::InvalidValue) = tlv_reader(&>::from_hex( - concat!("0100", "0208deadbeef1badbeef") - ).unwrap()[..]) { - } else { panic!(); } + if let Err(DecodeError::InvalidValue) = + tlv_reader(&>::from_hex(concat!("0100", "0208deadbeef1badbeef")).unwrap()[..]) + { + } else { + panic!(); + } // ... even if that field is even - if let Err(DecodeError::InvalidValue) = tlv_reader(&>::from_hex( - concat!("0304deadbeef", "0500") - ).unwrap()[..]) { - } else { panic!(); } + if let Err(DecodeError::InvalidValue) = + tlv_reader(&>::from_hex(concat!("0304deadbeef", "0500")).unwrap()[..]) + { + } else { + panic!(); + } } #[test] fn tlv_simple_good_cases() { - assert_eq!(tlv_reader(&>::from_hex( - concat!("0208deadbeef1badbeef", "03041bad1dea") - ).unwrap()[..]).unwrap(), - (0xdeadbeef1badbeef, 0x1bad1dea, None)); - assert_eq!(tlv_reader(&>::from_hex( - concat!("0208deadbeef1badbeef", "03041bad1dea", "040401020304") - ).unwrap()[..]).unwrap(), - (0xdeadbeef1badbeef, 0x1bad1dea, Some(0x01020304))); + assert_eq!( + tlv_reader( + &>::from_hex(concat!("0208deadbeef1badbeef", "03041bad1dea")).unwrap()[..] + ) + .unwrap(), + (0xdeadbeef1badbeef, 0x1bad1dea, None) + ); + assert_eq!( + tlv_reader( + &>::from_hex(concat!( + "0208deadbeef1badbeef", + "03041bad1dea", + "040401020304" + )) + .unwrap()[..] + ) + .unwrap(), + (0xdeadbeef1badbeef, 0x1bad1dea, Some(0x01020304)) + ); } #[derive(Debug, PartialEq)] @@ -1197,36 +1255,57 @@ mod tests { let mut b = 0; let mut c: Option = None; decode_tlv_stream!(&mut s, {(2, a, upgradable_required), (3, b, upgradable_required), (4, c, upgradable_option)}); - Ok(Some(TestUpgradable { a, b, c, })) + Ok(Some(TestUpgradable { a, b, c })) } #[test] fn upgradable_tlv_simple_good_cases() { - assert_eq!(upgradable_tlv_reader(&>::from_hex( - concat!("0204deadbeef", "03041bad1dea", "0404deadbeef") - ).unwrap()[..]).unwrap(), - Some(TestUpgradable { a: 0xdeadbeef, b: 0x1bad1dea, c: Some(0xdeadbeef) })); - - assert_eq!(upgradable_tlv_reader(&>::from_hex( - concat!("0204deadbeef", "03041bad1dea") - ).unwrap()[..]).unwrap(), - Some(TestUpgradable { a: 0xdeadbeef, b: 0x1bad1dea, c: None})); + assert_eq!( + upgradable_tlv_reader( + &>::from_hex(concat!("0204deadbeef", "03041bad1dea", "0404deadbeef")) + .unwrap()[..] + ) + .unwrap(), + Some(TestUpgradable { a: 0xdeadbeef, b: 0x1bad1dea, c: Some(0xdeadbeef) }) + ); + + assert_eq!( + upgradable_tlv_reader( + &>::from_hex(concat!("0204deadbeef", "03041bad1dea")).unwrap()[..] + ) + .unwrap(), + Some(TestUpgradable { a: 0xdeadbeef, b: 0x1bad1dea, c: None }) + ); } #[test] fn missing_required_upgradable() { - if let Err(DecodeError::InvalidValue) = upgradable_tlv_reader(&>::from_hex( - concat!("0100", "0204deadbeef") - ).unwrap()[..]) { - } else { panic!(); } - if let Err(DecodeError::InvalidValue) = upgradable_tlv_reader(&>::from_hex( - concat!("0100", "03041bad1dea") - ).unwrap()[..]) { - } else { panic!(); } + if let Err(DecodeError::InvalidValue) = upgradable_tlv_reader( + &>::from_hex(concat!("0100", "0204deadbeef")).unwrap()[..], + ) { + } else { + panic!(); + } + if let Err(DecodeError::InvalidValue) = upgradable_tlv_reader( + &>::from_hex(concat!("0100", "03041bad1dea")).unwrap()[..], + ) { + } else { + panic!(); + } } // BOLT TLV test cases - fn tlv_reader_n1(s: &[u8]) -> Result<(Option>, Option, Option<(PublicKey, u64, u64)>, Option), DecodeError> { + fn tlv_reader_n1( + s: &[u8], + ) -> Result< + ( + Option>, + Option, + Option<(PublicKey, u64, u64)>, + Option, + ), + DecodeError, + > { let mut s = Cursor::new(s); let mut tlv1: Option> = None; let mut tlv2: Option = None; @@ -1240,9 +1319,13 @@ mod tests { fn bolt_tlv_bogus_stream() { macro_rules! do_test { ($stream: expr, $reason: ident) => { - if let Err(DecodeError::$reason) = tlv_reader_n1(&>::from_hex($stream).unwrap()[..]) { - } else { panic!(); } - } + if let Err(DecodeError::$reason) = + tlv_reader_n1(&>::from_hex($stream).unwrap()[..]) + { + } else { + panic!(); + } + }; } // TLVs from the BOLT test cases which should not decode as either n1 or n2 @@ -1265,9 +1348,13 @@ mod tests { fn bolt_tlv_bogus_n1_stream() { macro_rules! do_test { ($stream: expr, $reason: ident) => { - if let Err(DecodeError::$reason) = tlv_reader_n1(&>::from_hex($stream).unwrap()[..]) { - } else { panic!(); } - } + if let Err(DecodeError::$reason) = + tlv_reader_n1(&>::from_hex($stream).unwrap()[..]) + { + } else { + panic!(); + } + }; } // TLVs from the BOLT test cases which should not decode as n1 @@ -1282,7 +1369,14 @@ mod tests { do_test!(concat!("01", "08", "0001000000000000"), InvalidValue); do_test!(concat!("02", "07", "01010101010101"), ShortRead); do_test!(concat!("02", "09", "010101010101010101"), InvalidValue); - do_test!(concat!("03", "21", "023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb"), ShortRead); + do_test!( + concat!( + "03", + "21", + "023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb" + ), + ShortRead + ); do_test!(concat!("03", "29", "023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb0000000000000001"), ShortRead); do_test!(concat!("03", "30", "023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb000000000000000100000000000001"), ShortRead); do_test!(concat!("03", "31", "043da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002"), InvalidValue); @@ -1293,7 +1387,10 @@ mod tests { do_test!(concat!("00", "00"), UnknownRequiredFeature); do_test!(concat!("02", "08", "0000000000000226", "01", "01", "2a"), InvalidValue); - do_test!(concat!("02", "08", "0000000000000231", "02", "08", "0000000000000451"), InvalidValue); + do_test!( + concat!("02", "08", "0000000000000231", "02", "08", "0000000000000451"), + InvalidValue + ); do_test!(concat!("1f", "00", "0f", "01", "2a"), InvalidValue); do_test!(concat!("1f", "00", "1f", "01", "2a"), InvalidValue); @@ -1305,13 +1402,17 @@ mod tests { fn bolt_tlv_valid_n1_stream() { macro_rules! do_test { ($stream: expr, $tlv1: expr, $tlv2: expr, $tlv3: expr, $tlv4: expr) => { - if let Ok((tlv1, tlv2, tlv3, tlv4)) = tlv_reader_n1(&>::from_hex($stream).unwrap()[..]) { + if let Ok((tlv1, tlv2, tlv3, tlv4)) = + tlv_reader_n1(&>::from_hex($stream).unwrap()[..]) + { assert_eq!(tlv1.map(|v| v.0), $tlv1); assert_eq!(tlv2, $tlv2); assert_eq!(tlv3, $tlv3); assert_eq!(tlv4, $tlv4); - } else { panic!(); } - } + } else { + panic!(); + } + }; } do_test!(concat!(""), None, None, None, None); @@ -1330,8 +1431,20 @@ mod tests { do_test!(concat!("01", "05", "0100000000"), Some(4294967296), None, None, None); do_test!(concat!("01", "06", "010000000000"), Some(1099511627776), None, None, None); do_test!(concat!("01", "07", "01000000000000"), Some(281474976710656), None, None, None); - do_test!(concat!("01", "08", "0100000000000000"), Some(72057594037927936), None, None, None); - do_test!(concat!("02", "08", "0000000000000226"), None, Some((0 << 30) | (0 << 5) | (550 << 0)), None, None); + do_test!( + concat!("01", "08", "0100000000000000"), + Some(72057594037927936), + None, + None, + None + ); + do_test!( + concat!("02", "08", "0000000000000226"), + None, + Some((0 << 30) | (0 << 5) | (550 << 0)), + None, + None + ); do_test!(concat!("03", "31", "023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002"), None, None, Some(( PublicKey::from_slice(&>::from_hex("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]).unwrap(), 1, 2)), @@ -1347,7 +1460,7 @@ mod tests { assert_eq!(stream.0, >::from_hex("03010101").unwrap()); stream.0.clear(); - _encode_varint_length_prefixed_tlv!(&mut stream, {(1, Some(1u8), option)}); + _encode_varint_length_prefixed_tlv!(&mut stream, { (1, Some(1u8), option) }); assert_eq!(stream.0, >::from_hex("03010101").unwrap()); stream.0.clear(); diff --git a/lightning/src/util/string.rs b/lightning/src/util/string.rs index 6949c936e00..cba3a829e7b 100644 --- a/lightning/src/util/string.rs +++ b/lightning/src/util/string.rs @@ -9,11 +9,11 @@ //! Utilities for strings. -use alloc::string::String; -use core::fmt; use crate::io::{self, Read}; use crate::ln::msgs; -use crate::util::ser::{Writeable, Writer, Readable}; +use crate::util::ser::{Readable, Writeable, Writer}; +use alloc::string::String; +use core::fmt; /// Struct to `Display` fields in a safe way using `PrintableString` #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] diff --git a/lightning/src/util/test_channel_signer.rs b/lightning/src/util/test_channel_signer.rs index a2cbf78b700..de9c91ec5dd 100644 --- a/lightning/src/util/test_channel_signer.rs +++ b/lightning/src/util/test_channel_signer.rs @@ -7,38 +7,42 @@ // You may not use this file except in accordance with one or both of these // licenses. +use crate::ln::chan_utils::{ + ChannelPublicKeys, ChannelTransactionParameters, ClosingTransaction, CommitmentTransaction, + HTLCOutputInCommitment, HolderCommitmentTransaction, TrustedCommitmentTransaction, +}; use crate::ln::channel::{ANCHOR_OUTPUT_VALUE_SATOSHI, MIN_CHAN_DUST_LIMIT_SATOSHIS}; -use crate::ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, HolderCommitmentTransaction, CommitmentTransaction, ChannelTransactionParameters, TrustedCommitmentTransaction, ClosingTransaction}; -use crate::ln::channel_keys::{HtlcKey}; +use crate::ln::channel_keys::HtlcKey; use crate::ln::{msgs, PaymentPreimage}; -use crate::sign::{InMemorySigner, ChannelSigner}; use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner}; +use crate::sign::{ChannelSigner, InMemorySigner}; use crate::prelude::*; +#[cfg(test)] +use crate::sync::MutexGuard; +use crate::sync::{Arc, Mutex}; use core::cmp; -use crate::sync::{Mutex, Arc}; -#[cfg(test)] use crate::sync::MutexGuard; use bitcoin::blockdata::transaction::Transaction; use bitcoin::hashes::Hash; use bitcoin::sighash; use bitcoin::sighash::EcdsaSighashType; -use bitcoin::secp256k1; -#[cfg(taproot)] -use bitcoin::secp256k1::All; -use bitcoin::secp256k1::{SecretKey, PublicKey}; -use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; -#[cfg(taproot)] -use musig2::types::{PartialSignature, PublicNonce, SecretNonce}; -use crate::sign::HTLCDescriptor; -use crate::util::ser::{Writeable, Writer}; use crate::io::Error; use crate::ln::features::ChannelTypeFeatures; #[cfg(taproot)] use crate::ln::msgs::PartialSignatureWithNonce; #[cfg(taproot)] use crate::sign::taproot::TaprootChannelSigner; +use crate::sign::HTLCDescriptor; +use crate::util::ser::{Writeable, Writer}; +use bitcoin::secp256k1; +#[cfg(taproot)] +use bitcoin::secp256k1::All; +use bitcoin::secp256k1::{ecdsa::Signature, Secp256k1}; +use bitcoin::secp256k1::{PublicKey, SecretKey}; +#[cfg(taproot)] +use musig2::types::{PartialSignature, PublicNonce, SecretNonce}; /// Initial value for revoked commitment downward counter pub const INITIAL_REVOKED_COMMITMENT_NUMBER: u64 = 1 << 48; @@ -96,7 +100,10 @@ impl TestChannelSigner { /// Since there are multiple copies of this struct for each channel, some coordination is needed /// so that all copies are aware of enforcement state. A pointer to this state is provided /// here, usually by an implementation of KeysInterface. - pub fn new_with_revoked(inner: InMemorySigner, state: Arc>, disable_revocation_policy_check: bool) -> Self { + pub fn new_with_revoked( + inner: InMemorySigner, state: Arc>, + disable_revocation_policy_check: bool, + ) -> Self { Self { inner, state, @@ -105,7 +112,9 @@ impl TestChannelSigner { } } - pub fn channel_type_features(&self) -> &ChannelTypeFeatures { self.inner.channel_type_features().unwrap() } + pub fn channel_type_features(&self) -> &ChannelTypeFeatures { + self.inner.channel_type_features().unwrap() + } #[cfg(test)] pub fn get_enforcement_state(&self) -> MutexGuard { @@ -124,7 +133,9 @@ impl TestChannelSigner { } impl ChannelSigner for TestChannelSigner { - fn get_per_commitment_point(&self, idx: u64, secp_ctx: &Secp256k1) -> PublicKey { + fn get_per_commitment_point( + &self, idx: u64, secp_ctx: &Secp256k1, + ) -> PublicKey { self.inner.get_per_commitment_point(idx, secp_ctx) } @@ -138,10 +149,18 @@ impl ChannelSigner for TestChannelSigner { self.inner.release_commitment_secret(idx) } - fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, _outbound_htlc_preimages: Vec) -> Result<(), ()> { + fn validate_holder_commitment( + &self, holder_tx: &HolderCommitmentTransaction, + _outbound_htlc_preimages: Vec, + ) -> Result<(), ()> { let mut state = self.state.lock().unwrap(); let idx = holder_tx.commitment_number(); - assert!(idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, "expecting to validate the current or next holder commitment - trying {}, current {}", idx, state.last_holder_commitment); + assert!( + idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, + "expecting to validate the current or next holder commitment - trying {}, current {}", + idx, + state.last_holder_commitment + ); state.last_holder_commitment = idx; Ok(()) } @@ -156,9 +175,13 @@ impl ChannelSigner for TestChannelSigner { Ok(()) } - fn pubkeys(&self) -> &ChannelPublicKeys { self.inner.pubkeys() } + fn pubkeys(&self) -> &ChannelPublicKeys { + self.inner.pubkeys() + } - fn channel_keys_id(&self) -> [u8; 32] { self.inner.channel_keys_id() } + fn channel_keys_id(&self) -> [u8; 32] { + self.inner.channel_keys_id() + } fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters) { self.inner.provide_channel_parameters(channel_parameters) @@ -166,7 +189,10 @@ impl ChannelSigner for TestChannelSigner { } impl EcdsaChannelSigner for TestChannelSigner { - fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1) -> Result<(Signature, Vec), ()> { + fn sign_counterparty_commitment( + &self, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, + outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1, + ) -> Result<(Signature, Vec), ()> { self.verify_counterparty_commitment_tx(commitment_tx, secp_ctx); { @@ -178,24 +204,48 @@ impl EcdsaChannelSigner for TestChannelSigner { let last_commitment_number = state.last_counterparty_commitment; // These commitment numbers are backwards counting. We expect either the same as the previously encountered, // or the next one. - assert!(last_commitment_number == actual_commitment_number || last_commitment_number - 1 == actual_commitment_number, "{} doesn't come after {}", actual_commitment_number, last_commitment_number); + assert!( + last_commitment_number == actual_commitment_number + || last_commitment_number - 1 == actual_commitment_number, + "{} doesn't come after {}", + actual_commitment_number, + last_commitment_number + ); // Ensure that the counterparty doesn't get more than two broadcastable commitments - // the last and the one we are trying to sign - assert!(actual_commitment_number >= state.last_counterparty_revoked_commitment - 2, "cannot sign a commitment if second to last wasn't revoked - signing {} revoked {}", actual_commitment_number, state.last_counterparty_revoked_commitment); - state.last_counterparty_commitment = cmp::min(last_commitment_number, actual_commitment_number) + assert!( + actual_commitment_number >= state.last_counterparty_revoked_commitment - 2, + "cannot sign a commitment if second to last wasn't revoked - signing {} revoked {}", + actual_commitment_number, + state.last_counterparty_revoked_commitment + ); + state.last_counterparty_commitment = + cmp::min(last_commitment_number, actual_commitment_number) } - Ok(self.inner.sign_counterparty_commitment(commitment_tx, inbound_htlc_preimages, outbound_htlc_preimages, secp_ctx).unwrap()) + Ok(self + .inner + .sign_counterparty_commitment( + commitment_tx, + inbound_htlc_preimages, + outbound_htlc_preimages, + secp_ctx, + ) + .unwrap()) } - fn sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result { + fn sign_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1, + ) -> Result { if !*self.available.lock().unwrap() { return Err(()); } let trusted_tx = self.verify_holder_commitment_tx(commitment_tx, secp_ctx); let state = self.state.lock().unwrap(); let commitment_number = trusted_tx.commitment_number(); - if state.last_holder_revoked_commitment - 1 != commitment_number && state.last_holder_revoked_commitment - 2 != commitment_number { + if state.last_holder_revoked_commitment - 1 != commitment_number + && state.last_holder_revoked_commitment - 2 != commitment_number + { if !self.disable_revocation_policy_check { panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", state.last_holder_revoked_commitment, commitment_number, self.inner.commitment_seed[0]) @@ -204,26 +254,51 @@ impl EcdsaChannelSigner for TestChannelSigner { Ok(self.inner.sign_holder_commitment(commitment_tx, secp_ctx).unwrap()) } - #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] - fn unsafe_sign_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result { + #[cfg(any(test, feature = "unsafe_revoked_tx_signing"))] + fn unsafe_sign_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1, + ) -> Result { Ok(self.inner.unsafe_sign_holder_commitment(commitment_tx, secp_ctx).unwrap()) } - fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1) -> Result { - Ok(EcdsaChannelSigner::sign_justice_revoked_output(&self.inner, justice_tx, input, amount, per_commitment_key, secp_ctx).unwrap()) - } - - fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { - Ok(EcdsaChannelSigner::sign_justice_revoked_htlc(&self.inner, justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap()) + fn sign_justice_revoked_output( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + secp_ctx: &Secp256k1, + ) -> Result { + Ok(EcdsaChannelSigner::sign_justice_revoked_output( + &self.inner, + justice_tx, + input, + amount, + per_commitment_key, + secp_ctx, + ) + .unwrap()) + } + + fn sign_justice_revoked_htlc( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { + Ok(EcdsaChannelSigner::sign_justice_revoked_htlc( + &self.inner, + justice_tx, + input, + amount, + per_commitment_key, + htlc, + secp_ctx, + ) + .unwrap()) } fn sign_holder_htlc_transaction( &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result { let state = self.state.lock().unwrap(); - if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number && - state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number + if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number + && state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number { if !self.disable_revocation_policy_check { panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}", @@ -239,26 +314,59 @@ impl EcdsaChannelSigner for TestChannelSigner { } else { EcdsaSighashType::All }; - let sighash = &sighash::SighashCache::new(&*htlc_tx).segwit_signature_hash( - input, &witness_script, htlc_descriptor.htlc.amount_msat / 1000, sighash_type - ).unwrap(); + let sighash = &sighash::SighashCache::new(&*htlc_tx) + .segwit_signature_hash( + input, + &witness_script, + htlc_descriptor.htlc.amount_msat / 1000, + sighash_type, + ) + .unwrap(); let countersignatory_htlc_key = HtlcKey::from_basepoint( - &secp_ctx, &self.inner.counterparty_pubkeys().unwrap().htlc_basepoint, &htlc_descriptor.per_commitment_point, + &secp_ctx, + &self.inner.counterparty_pubkeys().unwrap().htlc_basepoint, + &htlc_descriptor.per_commitment_point, ); - secp_ctx.verify_ecdsa( - &hash_to_message!(sighash.as_byte_array()), &htlc_descriptor.counterparty_sig, &countersignatory_htlc_key.to_public_key() - ).unwrap(); + secp_ctx + .verify_ecdsa( + &hash_to_message!(sighash.as_byte_array()), + &htlc_descriptor.counterparty_sig, + &countersignatory_htlc_key.to_public_key(), + ) + .unwrap(); } - Ok(EcdsaChannelSigner::sign_holder_htlc_transaction(&self.inner, htlc_tx, input, htlc_descriptor, secp_ctx).unwrap()) - } - - fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { - Ok(EcdsaChannelSigner::sign_counterparty_htlc_transaction(&self.inner, htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap()) - } - - fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { - closing_tx.verify(self.inner.funding_outpoint().unwrap().into_bitcoin_outpoint()) + Ok(EcdsaChannelSigner::sign_holder_htlc_transaction( + &self.inner, + htlc_tx, + input, + htlc_descriptor, + secp_ctx, + ) + .unwrap()) + } + + fn sign_counterparty_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { + Ok(EcdsaChannelSigner::sign_counterparty_htlc_transaction( + &self.inner, + htlc_tx, + input, + amount, + per_commitment_point, + htlc, + secp_ctx, + ) + .unwrap()) + } + + fn sign_closing_transaction( + &self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1, + ) -> Result { + closing_tx + .verify(self.inner.funding_outpoint().unwrap().into_bitcoin_outpoint()) .expect("derived different closing transaction"); Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap()) } @@ -269,12 +377,15 @@ impl EcdsaChannelSigner for TestChannelSigner { debug_assert!(MIN_CHAN_DUST_LIMIT_SATOSHIS > ANCHOR_OUTPUT_VALUE_SATOSHI); // As long as our minimum dust limit is enforced and is greater than our anchor output // value, an anchor output can only have an index within [0, 1]. - assert!(anchor_tx.input[input].previous_output.vout == 0 || anchor_tx.input[input].previous_output.vout == 1); + assert!( + anchor_tx.input[input].previous_output.vout == 0 + || anchor_tx.input[input].previous_output.vout == 1 + ); EcdsaChannelSigner::sign_holder_anchor_input(&self.inner, anchor_tx, input, secp_ctx) } fn sign_channel_announcement_with_funding_key( - &self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1 + &self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1, ) -> Result { self.inner.sign_channel_announcement_with_funding_key(msg, secp_ctx) } @@ -284,39 +395,64 @@ impl WriteableEcdsaChannelSigner for TestChannelSigner {} #[cfg(taproot)] impl TaprootChannelSigner for TestChannelSigner { - fn generate_local_nonce_pair(&self, commitment_number: u64, secp_ctx: &Secp256k1) -> PublicNonce { + fn generate_local_nonce_pair( + &self, commitment_number: u64, secp_ctx: &Secp256k1, + ) -> PublicNonce { todo!() } - fn partially_sign_counterparty_commitment(&self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec, outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1) -> Result<(PartialSignatureWithNonce, Vec), ()> { + fn partially_sign_counterparty_commitment( + &self, counterparty_nonce: PublicNonce, commitment_tx: &CommitmentTransaction, + inbound_htlc_preimages: Vec, + outbound_htlc_preimages: Vec, secp_ctx: &Secp256k1, + ) -> Result<(PartialSignatureWithNonce, Vec), ()> { todo!() } - fn finalize_holder_commitment(&self, commitment_tx: &HolderCommitmentTransaction, counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1) -> Result { + fn finalize_holder_commitment( + &self, commitment_tx: &HolderCommitmentTransaction, + counterparty_partial_signature: PartialSignatureWithNonce, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_justice_revoked_output(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, secp_ctx: &Secp256k1) -> Result { + fn sign_justice_revoked_output( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_justice_revoked_htlc(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { + fn sign_justice_revoked_htlc( + &self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1) -> Result { + fn sign_holder_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, + secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_counterparty_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { + fn sign_counterparty_htlc_transaction( + &self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, + htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn partially_sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { + fn partially_sign_closing_transaction( + &self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1, + ) -> Result { todo!() } - fn sign_holder_anchor_input(&self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1) -> Result { + fn sign_holder_anchor_input( + &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1, + ) -> Result { todo!() } } @@ -333,18 +469,30 @@ impl Writeable for TestChannelSigner { } impl TestChannelSigner { - fn verify_counterparty_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1) -> TrustedCommitmentTransaction<'a> { - commitment_tx.verify( - &self.inner.get_channel_parameters().unwrap().as_counterparty_broadcastable(), - self.inner.counterparty_pubkeys().unwrap(), self.inner.pubkeys(), secp_ctx - ).expect("derived different per-tx keys or built transaction") - } - - fn verify_holder_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1) -> TrustedCommitmentTransaction<'a> { - commitment_tx.verify( - &self.inner.get_channel_parameters().unwrap().as_holder_broadcastable(), - self.inner.pubkeys(), self.inner.counterparty_pubkeys().unwrap(), secp_ctx - ).expect("derived different per-tx keys or built transaction") + fn verify_counterparty_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>( + &self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1, + ) -> TrustedCommitmentTransaction<'a> { + commitment_tx + .verify( + &self.inner.get_channel_parameters().unwrap().as_counterparty_broadcastable(), + self.inner.counterparty_pubkeys().unwrap(), + self.inner.pubkeys(), + secp_ctx, + ) + .expect("derived different per-tx keys or built transaction") + } + + fn verify_holder_commitment_tx<'a, T: secp256k1::Signing + secp256k1::Verification>( + &self, commitment_tx: &'a CommitmentTransaction, secp_ctx: &Secp256k1, + ) -> TrustedCommitmentTransaction<'a> { + commitment_tx + .verify( + &self.inner.get_channel_parameters().unwrap().as_holder_broadcastable(), + self.inner.pubkeys(), + self.inner.counterparty_pubkeys().unwrap(), + secp_ctx, + ) + .expect("derived different per-tx keys or built transaction") } } diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index a96711d144c..494abae76c0 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -7,10 +7,9 @@ // You may not use this file except in accordance with one or both of these // licenses. -use crate::blinded_path::BlindedPath; use crate::blinded_path::payment::ReceiveTlvs; +use crate::blinded_path::BlindedPath; use crate::chain; -use crate::chain::WatchedOutput; use crate::chain::chaininterface; use crate::chain::chaininterface::ConfirmationTarget; use crate::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW; @@ -19,63 +18,71 @@ use crate::chain::chainmonitor::{MonitorUpdateId, UpdateOrigin}; use crate::chain::channelmonitor; use crate::chain::channelmonitor::MonitorEvent; use crate::chain::transaction::OutPoint; -use crate::routing::router::{CandidateRouteHop, FirstHopCandidate, PublicHopCandidate, PrivateHopCandidate}; -use crate::sign; +use crate::chain::WatchedOutput; use crate::events; -use crate::events::bump_transaction::{WalletSource, Utxo}; -use crate::ln::ChannelId; -use crate::ln::channelmanager::{ChannelDetails, self}; +use crate::events::bump_transaction::{Utxo, WalletSource}; use crate::ln::chan_utils::CommitmentTransaction; +use crate::ln::channelmanager::{self, ChannelDetails}; use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; -use crate::ln::{msgs, wire}; use crate::ln::msgs::LightningError; use crate::ln::script::ShutdownScript; +use crate::ln::ChannelId; +use crate::ln::{msgs, wire}; use crate::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice}; use crate::offers::invoice_request::UnsignedInvoiceRequest; -use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath}; +use crate::onion_message::messenger::{ + DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath, +}; use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees}; +use crate::routing::router::{ + CandidateRouteHop, FirstHopCandidate, PrivateHopCandidate, PublicHopCandidate, +}; +use crate::routing::router::{ + DefaultRouter, InFlightHtlcs, Path, Route, RouteHintHop, RouteParameters, Router, + ScorerAccountingForInFlightHtlcs, +}; +use crate::routing::scoring::{ChannelUsage, ScoreLookUp, ScoreUpdate}; use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult}; -use crate::routing::router::{DefaultRouter, InFlightHtlcs, Path, Route, RouteParameters, RouteHintHop, Router, ScorerAccountingForInFlightHtlcs}; -use crate::routing::scoring::{ChannelUsage, ScoreUpdate, ScoreLookUp}; +use crate::sign; use crate::sync::RwLock; use crate::util::config::UserConfig; -use crate::util::test_channel_signer::{TestChannelSigner, EnforcementState}; -use crate::util::logger::{Logger, Level, Record}; -use crate::util::ser::{Readable, ReadableArgs, Writer, Writeable}; +use crate::util::logger::{Level, Logger, Record}; use crate::util::persist::KVStore; +use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; +use crate::util::test_channel_signer::{EnforcementState, TestChannelSigner}; -use bitcoin::blockdata::constants::ChainHash; +use bitcoin::blockdata::block::Block; use bitcoin::blockdata::constants::genesis_block; -use bitcoin::blockdata::transaction::{Transaction, TxOut}; -use bitcoin::blockdata::script::{Builder, Script, ScriptBuf}; +use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::opcodes; -use bitcoin::blockdata::block::Block; -use bitcoin::network::constants::Network; +use bitcoin::blockdata::script::{Builder, Script, ScriptBuf}; +use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::hash_types::{BlockHash, Txid}; -use bitcoin::sighash::{SighashCache, EcdsaSighashType}; +use bitcoin::network::constants::Network; +use bitcoin::sighash::{EcdsaSighashType, SighashCache}; -use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, self}; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use bitcoin::secp256k1::schnorr; +use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey}; #[cfg(any(test, feature = "_test_utils"))] use regex; use crate::io; use crate::prelude::*; +use crate::sign::{EntropySource, InMemorySigner, NodeSigner, Recipient, SignerProvider}; +use crate::sync::{Arc, Mutex}; +use bitcoin::bech32::u5; use core::cell::RefCell; -use core::time::Duration; -use crate::sync::{Mutex, Arc}; -use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use core::mem; -use bitcoin::bech32::u5; -use crate::sign::{InMemorySigner, Recipient, EntropySource, NodeSigner, SignerProvider}; +use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use core::time::Duration; -#[cfg(feature = "std")] -use std::time::{SystemTime, UNIX_EPOCH}; use bitcoin::psbt::PartiallySignedTransaction; use bitcoin::Sequence; +#[cfg(feature = "std")] +use std::time::{SystemTime, UNIX_EPOCH}; pub fn pubkey(byte: u8) -> PublicKey { let secp_ctx = Secp256k1::new(); @@ -119,7 +126,7 @@ pub struct TestRouter<'a> { impl<'a> TestRouter<'a> { pub fn new( network_graph: Arc>, logger: &'a TestLogger, - scorer: &'a RwLock + scorer: &'a RwLock, ) -> Self { Self { router: DefaultRouter::new(network_graph.clone(), logger, [42u8; 32], scorer, ()), @@ -138,9 +145,11 @@ impl<'a> TestRouter<'a> { impl<'a> Router for TestRouter<'a> { fn find_route( &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, - inflight_htlcs: InFlightHtlcs + inflight_htlcs: InFlightHtlcs, ) -> Result { - if let Some((find_route_query, find_route_res)) = self.next_routes.lock().unwrap().pop_front() { + if let Some((find_route_query, find_route_res)) = + self.next_routes.lock().unwrap().pop_front() + { assert_eq!(find_route_query, *params); if let Ok(ref route) = find_route_res { assert_eq!(route.route_params, Some(find_route_query)); @@ -159,12 +168,15 @@ impl<'a> Router for TestRouter<'a> { if idx == path.hops.len() - 1 { if let Some(first_hops) = first_hops { - if let Some(idx) = first_hops.iter().position(|h| h.get_outbound_payment_scid() == Some(hop.short_channel_id)) { + if let Some(idx) = first_hops.iter().position(|h| { + h.get_outbound_payment_scid() == Some(hop.short_channel_id) + }) { let node_id = NodeId::from_pubkey(payer); - let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate { - details: first_hops[idx], - payer_node_id: &node_id, - }); + let candidate = + CandidateRouteHop::FirstHop(FirstHopCandidate { + details: first_hops[idx], + payer_node_id: &node_id, + }); scorer.channel_penalty_msat(&candidate, usage, &()); continue; } @@ -172,7 +184,8 @@ impl<'a> Router for TestRouter<'a> { } let network_graph = self.network_graph.read_only(); if let Some(channel) = network_graph.channel(hop.short_channel_id) { - let (directed, _) = channel.as_directed_to(&NodeId::from_pubkey(&hop.pubkey)).unwrap(); + let (directed, _) = + channel.as_directed_to(&NodeId::from_pubkey(&hop.pubkey)).unwrap(); let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate { info: directed, short_channel_id: hop.short_channel_id, @@ -205,29 +218,36 @@ impl<'a> Router for TestRouter<'a> { } fn create_blinded_payment_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, first_hops: Vec, tlvs: ReceiveTlvs, - amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1 + amount_msats: u64, entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result, ()> { self.router.create_blinded_payment_paths( - recipient, first_hops, tlvs, amount_msats, entropy_source, secp_ctx + recipient, + first_hops, + tlvs, + amount_msats, + entropy_source, + secp_ctx, ) } } impl<'a> MessageRouter for TestRouter<'a> { fn find_path( - &self, sender: PublicKey, peers: Vec, destination: Destination + &self, sender: PublicKey, peers: Vec, destination: Destination, ) -> Result { self.router.find_path(sender, peers, destination) } fn create_blinded_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, peers: Vec, entropy_source: &ES, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result, ()> { self.router.create_blinded_paths(recipient, peers, entropy_source, secp_ctx) } @@ -235,7 +255,8 @@ impl<'a> MessageRouter for TestRouter<'a> { impl<'a> Drop for TestRouter<'a> { fn drop(&mut self) { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if std::thread::panicking() { return; } @@ -256,16 +277,17 @@ impl<'a> TestMessageRouter<'a> { impl<'a> MessageRouter for TestMessageRouter<'a> { fn find_path( - &self, sender: PublicKey, peers: Vec, destination: Destination + &self, sender: PublicKey, peers: Vec, destination: Destination, ) -> Result { self.inner.find_path(sender, peers, destination) } fn create_blinded_paths< - ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + ES: EntropySource + ?Sized, + T: secp256k1::Signing + secp256k1::Verification, >( &self, recipient: PublicKey, peers: Vec, entropy_source: &ES, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result, ()> { self.inner.create_blinded_paths(recipient, peers, entropy_source, secp_ctx) } @@ -274,37 +296,55 @@ impl<'a> MessageRouter for TestMessageRouter<'a> { pub struct OnlyReadsKeysInterface {} impl EntropySource for OnlyReadsKeysInterface { - fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }} + fn get_secure_random_bytes(&self) -> [u8; 32] { + [0; 32] + } +} impl SignerProvider for OnlyReadsKeysInterface { type EcdsaSigner = TestChannelSigner; #[cfg(taproot)] type TaprootSigner = TestChannelSigner; - fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!(); } + fn generate_channel_keys_id( + &self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128, + ) -> [u8; 32] { + unreachable!(); + } - fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::EcdsaSigner { unreachable!(); } + fn derive_channel_signer( + &self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32], + ) -> Self::EcdsaSigner { + unreachable!(); + } fn read_chan_signer(&self, mut reader: &[u8]) -> Result { let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = Arc::new(Mutex::new(EnforcementState::new())); - Ok(TestChannelSigner::new_with_revoked( - inner, - state, - false - )) + Ok(TestChannelSigner::new_with_revoked(inner, state, false)) } - fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result { Err(()) } - fn get_shutdown_scriptpubkey(&self) -> Result { Err(()) } + fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result { + Err(()) + } + fn get_shutdown_scriptpubkey(&self) -> Result { + Err(()) + } } pub struct TestChainMonitor<'a> { pub added_monitors: Mutex)>>, pub monitor_updates: Mutex>>, pub latest_monitor_update_id: Mutex>, - pub chain_monitor: chainmonitor::ChainMonitor>, + pub chain_monitor: chainmonitor::ChainMonitor< + TestChannelSigner, + &'a TestChainSource, + &'a dyn chaininterface::BroadcasterInterface, + &'a TestFeeEstimator, + &'a TestLogger, + &'a dyn chainmonitor::Persist, + >, pub keys_manager: &'a TestKeysInterface, /// If this is set to Some(), the next update_channel call (not watch_channel) must be a /// ChannelForceClosed event for the given channel_id with should_broadcast set to the given @@ -315,12 +355,24 @@ pub struct TestChainMonitor<'a> { pub expect_monitor_round_trip_fail: Mutex>, } impl<'a> TestChainMonitor<'a> { - pub fn new(chain_source: Option<&'a TestChainSource>, broadcaster: &'a dyn chaininterface::BroadcasterInterface, logger: &'a TestLogger, fee_estimator: &'a TestFeeEstimator, persister: &'a dyn chainmonitor::Persist, keys_manager: &'a TestKeysInterface) -> Self { + pub fn new( + chain_source: Option<&'a TestChainSource>, + broadcaster: &'a dyn chaininterface::BroadcasterInterface, logger: &'a TestLogger, + fee_estimator: &'a TestFeeEstimator, + persister: &'a dyn chainmonitor::Persist, + keys_manager: &'a TestKeysInterface, + ) -> Self { Self { added_monitors: Mutex::new(Vec::new()), monitor_updates: Mutex::new(HashMap::new()), latest_monitor_update_id: Mutex::new(HashMap::new()), - chain_monitor: chainmonitor::ChainMonitor::new(chain_source, broadcaster, logger, fee_estimator, persister), + chain_monitor: chainmonitor::ChainMonitor::new( + chain_source, + broadcaster, + logger, + fee_estimator, + persister, + ), keys_manager, expect_channel_force_closed: Mutex::new(None), expect_monitor_round_trip_fail: Mutex::new(None), @@ -328,45 +380,75 @@ impl<'a> TestChainMonitor<'a> { } pub fn complete_sole_pending_chan_update(&self, channel_id: &ChannelId) { - let (outpoint, _, latest_update) = self.latest_monitor_update_id.lock().unwrap().get(channel_id).unwrap().clone(); + let (outpoint, _, latest_update) = + self.latest_monitor_update_id.lock().unwrap().get(channel_id).unwrap().clone(); self.chain_monitor.channel_monitor_updated(outpoint, latest_update).unwrap(); } } impl<'a> chain::Watch for TestChainMonitor<'a> { - fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result { + fn watch_channel( + &self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor, + ) -> Result { // At every point where we get a monitor update, we should be able to send a useful monitor // to a watchtower and disk... let mut w = TestVecWriter(Vec::new()); monitor.write(&mut w).unwrap(); let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( - &mut io::Cursor::new(&w.0), (self.keys_manager, self.keys_manager)).unwrap().1; + &mut io::Cursor::new(&w.0), + (self.keys_manager, self.keys_manager), + ) + .unwrap() + .1; assert!(new_monitor == monitor); - self.latest_monitor_update_id.lock().unwrap().insert(monitor.channel_id(), - (funding_txo, monitor.get_latest_update_id(), MonitorUpdateId::from_new_monitor(&monitor))); + self.latest_monitor_update_id.lock().unwrap().insert( + monitor.channel_id(), + ( + funding_txo, + monitor.get_latest_update_id(), + MonitorUpdateId::from_new_monitor(&monitor), + ), + ); self.added_monitors.lock().unwrap().push((funding_txo, monitor)); self.chain_monitor.watch_channel(funding_txo, new_monitor) } - fn update_channel(&self, funding_txo: OutPoint, update: &channelmonitor::ChannelMonitorUpdate) -> chain::ChannelMonitorUpdateStatus { + fn update_channel( + &self, funding_txo: OutPoint, update: &channelmonitor::ChannelMonitorUpdate, + ) -> chain::ChannelMonitorUpdateStatus { // Every monitor update should survive roundtrip let mut w = TestVecWriter(Vec::new()); update.write(&mut w).unwrap(); - assert!(channelmonitor::ChannelMonitorUpdate::read( - &mut io::Cursor::new(&w.0)).unwrap() == *update); - let channel_id = update.channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(funding_txo)); - - self.monitor_updates.lock().unwrap().entry(channel_id).or_insert(Vec::new()).push(update.clone()); + assert!( + channelmonitor::ChannelMonitorUpdate::read(&mut io::Cursor::new(&w.0)).unwrap() + == *update + ); + let channel_id = + update.channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(funding_txo)); + + self.monitor_updates + .lock() + .unwrap() + .entry(channel_id) + .or_insert(Vec::new()) + .push(update.clone()); if let Some(exp) = self.expect_channel_force_closed.lock().unwrap().take() { assert_eq!(channel_id, exp.0); assert_eq!(update.updates.len(), 1); - if let channelmonitor::ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } = update.updates[0] { + if let channelmonitor::ChannelMonitorUpdateStep::ChannelForceClosed { + should_broadcast, + } = update.updates[0] + { assert_eq!(should_broadcast, exp.1); - } else { panic!(); } + } else { + panic!(); + } } - self.latest_monitor_update_id.lock().unwrap().insert(channel_id, - (funding_txo, update.update_id, MonitorUpdateId::from_monitor_update(update))); + self.latest_monitor_update_id.lock().unwrap().insert( + channel_id, + (funding_txo, update.update_id, MonitorUpdateId::from_monitor_update(update)), + ); let update_res = self.chain_monitor.update_channel(funding_txo, update); // At every point where we get a monitor update, we should be able to send a useful monitor // to a watchtower and disk... @@ -374,7 +456,11 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { w.0.clear(); monitor.write(&mut w).unwrap(); let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( - &mut io::Cursor::new(&w.0), (self.keys_manager, self.keys_manager)).unwrap().1; + &mut io::Cursor::new(&w.0), + (self.keys_manager, self.keys_manager), + ) + .unwrap() + .1; if let Some(chan_id) = self.expect_monitor_round_trip_fail.lock().unwrap().take() { assert_eq!(chan_id, channel_id); assert!(new_monitor != *monitor); @@ -385,7 +471,9 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { update_res } - fn release_pending_monitor_events(&self) -> Vec<(OutPoint, ChannelId, Vec, Option)> { + fn release_pending_monitor_events( + &self, + ) -> Vec<(OutPoint, ChannelId, Vec, Option)> { return self.chain_monitor.release_pending_monitor_events(); } } @@ -421,41 +509,68 @@ impl WatchtowerPersister { } #[cfg(test)] - pub(crate) fn justice_tx(&self, funding_txo: OutPoint, commitment_txid: &Txid) - -> Option { - self.watchtower_state.lock().unwrap().get(&funding_txo).unwrap().get(commitment_txid).cloned() - } - - fn form_justice_data_from_commitment(&self, counterparty_commitment_tx: &CommitmentTransaction) - -> Option { + pub(crate) fn justice_tx( + &self, funding_txo: OutPoint, commitment_txid: &Txid, + ) -> Option { + self.watchtower_state + .lock() + .unwrap() + .get(&funding_txo) + .unwrap() + .get(commitment_txid) + .cloned() + } + + fn form_justice_data_from_commitment( + &self, counterparty_commitment_tx: &CommitmentTransaction, + ) -> Option { let trusted_tx = counterparty_commitment_tx.trust(); let output_idx = trusted_tx.revokeable_output_index()?; let built_tx = trusted_tx.built_transaction(); let value = built_tx.transaction.output[output_idx as usize].value; - let justice_tx = trusted_tx.build_to_local_justice_tx( - FEERATE_FLOOR_SATS_PER_KW as u64, self.destination_script.clone()).ok()?; + let justice_tx = trusted_tx + .build_to_local_justice_tx( + FEERATE_FLOOR_SATS_PER_KW as u64, + self.destination_script.clone(), + ) + .ok()?; let commitment_number = counterparty_commitment_tx.commitment_number(); Some(JusticeTxData { justice_tx, value, commitment_number }) } } -impl chainmonitor::Persist for WatchtowerPersister { - fn persist_new_channel(&self, funding_txo: OutPoint, - data: &channelmonitor::ChannelMonitor, id: MonitorUpdateId +impl chainmonitor::Persist + for WatchtowerPersister +{ + fn persist_new_channel( + &self, funding_txo: OutPoint, data: &channelmonitor::ChannelMonitor, + id: MonitorUpdateId, ) -> chain::ChannelMonitorUpdateStatus { let res = self.persister.persist_new_channel(funding_txo, data, id); - assert!(self.unsigned_justice_tx_data.lock().unwrap() - .insert(funding_txo, VecDeque::new()).is_none()); - assert!(self.watchtower_state.lock().unwrap() - .insert(funding_txo, HashMap::new()).is_none()); - - let initial_counterparty_commitment_tx = data.initial_counterparty_commitment_tx() - .expect("First and only call expects Some"); - if let Some(justice_data) - = self.form_justice_data_from_commitment(&initial_counterparty_commitment_tx) { - self.unsigned_justice_tx_data.lock().unwrap() - .get_mut(&funding_txo).unwrap() + assert!(self + .unsigned_justice_tx_data + .lock() + .unwrap() + .insert(funding_txo, VecDeque::new()) + .is_none()); + assert!(self + .watchtower_state + .lock() + .unwrap() + .insert(funding_txo, HashMap::new()) + .is_none()); + + let initial_counterparty_commitment_tx = + data.initial_counterparty_commitment_tx().expect("First and only call expects Some"); + if let Some(justice_data) = + self.form_justice_data_from_commitment(&initial_counterparty_commitment_tx) + { + self.unsigned_justice_tx_data + .lock() + .unwrap() + .get_mut(&funding_txo) + .unwrap() .push_back(justice_data); } res @@ -463,25 +578,37 @@ impl chainmonitor::Persist, - data: &channelmonitor::ChannelMonitor, update_id: MonitorUpdateId + data: &channelmonitor::ChannelMonitor, update_id: MonitorUpdateId, ) -> chain::ChannelMonitorUpdateStatus { let res = self.persister.update_persisted_channel(funding_txo, update, data, update_id); if let Some(update) = update { let commitment_txs = data.counterparty_commitment_txs_from_update(update); - let justice_datas = commitment_txs.into_iter() + let justice_datas = commitment_txs + .into_iter() .filter_map(|commitment_tx| self.form_justice_data_from_commitment(&commitment_tx)); let mut channels_justice_txs = self.unsigned_justice_tx_data.lock().unwrap(); let channel_state = channels_justice_txs.get_mut(&funding_txo).unwrap(); channel_state.extend(justice_datas); - while let Some(JusticeTxData { justice_tx, value, commitment_number }) = channel_state.front() { + while let Some(JusticeTxData { justice_tx, value, commitment_number }) = + channel_state.front() + { let input_idx = 0; let commitment_txid = justice_tx.input[input_idx].previous_output.txid; - match data.sign_to_local_justice_tx(justice_tx.clone(), input_idx, *value, *commitment_number) { + match data.sign_to_local_justice_tx( + justice_tx.clone(), + input_idx, + *value, + *commitment_number, + ) { Ok(signed_justice_tx) => { - let dup = self.watchtower_state.lock().unwrap() - .get_mut(&funding_txo).unwrap() + let dup = self + .watchtower_state + .lock() + .unwrap() + .get_mut(&funding_txo) + .unwrap() .insert(commitment_txid, signed_justice_tx); assert!(dup.is_none()); channel_state.pop_front(); @@ -519,24 +646,43 @@ impl TestPersister { self.update_rets.lock().unwrap().push_back(next_ret); } } -impl chainmonitor::Persist for TestPersister { - fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor, _id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { +impl chainmonitor::Persist + for TestPersister +{ + fn persist_new_channel( + &self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor, + _id: MonitorUpdateId, + ) -> chain::ChannelMonitorUpdateStatus { if let Some(update_ret) = self.update_rets.lock().unwrap().pop_front() { - return update_ret + return update_ret; } chain::ChannelMonitorUpdateStatus::Completed } - fn update_persisted_channel(&self, funding_txo: OutPoint, _update: Option<&channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor, update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateStatus { + fn update_persisted_channel( + &self, funding_txo: OutPoint, _update: Option<&channelmonitor::ChannelMonitorUpdate>, + _data: &channelmonitor::ChannelMonitor, update_id: MonitorUpdateId, + ) -> chain::ChannelMonitorUpdateStatus { let mut ret = chain::ChannelMonitorUpdateStatus::Completed; if let Some(update_ret) = self.update_rets.lock().unwrap().pop_front() { ret = update_ret; } - let is_chain_sync = if let UpdateOrigin::ChainSync(_) = update_id.contents { true } else { false }; + let is_chain_sync = + if let UpdateOrigin::ChainSync(_) = update_id.contents { true } else { false }; if is_chain_sync { - self.chain_sync_monitor_persistences.lock().unwrap().entry(funding_txo).or_insert(HashSet::new()).insert(update_id); + self.chain_sync_monitor_persistences + .lock() + .unwrap() + .entry(funding_txo) + .or_insert(HashSet::new()) + .insert(update_id); } else { - self.offchain_monitor_updates.lock().unwrap().entry(funding_txo).or_insert(HashSet::new()).insert(update_id); + self.offchain_monitor_updates + .lock() + .unwrap() + .entry(funding_txo) + .or_insert(HashSet::new()) + .insert(update_id); } ret } @@ -555,7 +701,9 @@ impl TestStore { } impl KVStore for TestStore { - fn read(&self, primary_namespace: &str, secondary_namespace: &str, key: &str) -> io::Result> { + fn read( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, + ) -> io::Result> { let persisted_lock = self.persisted_bytes.lock().unwrap(); let prefixed = if secondary_namespace.is_empty() { primary_namespace.to_string() @@ -575,7 +723,9 @@ impl KVStore for TestStore { } } - fn write(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8]) -> io::Result<()> { + fn write( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8], + ) -> io::Result<()> { if self.read_only { return Err(io::Error::new( io::ErrorKind::PermissionDenied, @@ -596,7 +746,9 @@ impl KVStore for TestStore { Ok(()) } - fn remove(&self, primary_namespace: &str, secondary_namespace: &str, key: &str, _lazy: bool) -> io::Result<()> { + fn remove( + &self, primary_namespace: &str, secondary_namespace: &str, key: &str, _lazy: bool, + ) -> io::Result<()> { if self.read_only { return Err(io::Error::new( io::ErrorKind::PermissionDenied, @@ -612,7 +764,7 @@ impl KVStore for TestStore { format!("{}/{}", primary_namespace, secondary_namespace) }; if let Some(outer_ref) = persisted_lock.get_mut(&prefixed) { - outer_ref.remove(&key.to_string()); + outer_ref.remove(&key.to_string()); } Ok(()) @@ -667,10 +819,15 @@ impl chaininterface::BroadcasterInterface for TestBroadcaster { for tx in txs { let lock_time = tx.lock_time.to_consensus_u32(); assert!(lock_time < 1_500_000_000); - if tx.lock_time.is_block_height() && lock_time > self.blocks.lock().unwrap().last().unwrap().1 { + if tx.lock_time.is_block_height() + && lock_time > self.blocks.lock().unwrap().last().unwrap().1 + { for inp in tx.input.iter() { if inp.sequence != Sequence::MAX { - panic!("We should never broadcast a transaction before its locktime ({})!", tx.lock_time); + panic!( + "We should never broadcast a transaction before its locktime ({})!", + tx.lock_time + ); } } } @@ -702,14 +859,21 @@ impl TestChannelMessageHandler { #[cfg(test)] pub(crate) fn expect_receive_msg(&self, ev: wire::Message<()>) { let mut expected_msgs = self.expected_recv_msgs.lock().unwrap(); - if expected_msgs.is_none() { *expected_msgs = Some(Vec::new()); } + if expected_msgs.is_none() { + *expected_msgs = Some(Vec::new()); + } expected_msgs.as_mut().unwrap().push(ev); } fn received_msg(&self, _ev: wire::Message<()>) { let mut msgs = self.expected_recv_msgs.lock().unwrap(); - if msgs.is_none() { return; } - assert!(!msgs.as_ref().unwrap().is_empty(), "Received message when we weren't expecting one"); + if msgs.is_none() { + return; + } + assert!( + !msgs.as_ref().unwrap().is_empty(), + "Received message when we weren't expecting one" + ); #[cfg(test)] assert_eq!(msgs.as_ref().unwrap()[0], _ev); msgs.as_mut().unwrap().remove(0); @@ -765,13 +929,17 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler { fn handle_update_add_htlc(&self, _their_node_id: &PublicKey, msg: &msgs::UpdateAddHTLC) { self.received_msg(wire::Message::UpdateAddHTLC(msg.clone())); } - fn handle_update_fulfill_htlc(&self, _their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) { + fn handle_update_fulfill_htlc( + &self, _their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC, + ) { self.received_msg(wire::Message::UpdateFulfillHTLC(msg.clone())); } fn handle_update_fail_htlc(&self, _their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) { self.received_msg(wire::Message::UpdateFailHTLC(msg.clone())); } - 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, + ) { self.received_msg(wire::Message::UpdateFailMalformedHTLC(msg.clone())); } fn handle_commitment_signed(&self, _their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) { @@ -786,16 +954,22 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler { fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &msgs::ChannelUpdate) { // Don't call `received_msg` here as `TestRoutingMessageHandler` generates these sometimes } - fn handle_announcement_signatures(&self, _their_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures) { + fn handle_announcement_signatures( + &self, _their_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures, + ) { self.received_msg(wire::Message::AnnouncementSignatures(msg.clone())); } - fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, msg: &msgs::ChannelReestablish) { + fn handle_channel_reestablish( + &self, _their_node_id: &PublicKey, msg: &msgs::ChannelReestablish, + ) { self.received_msg(wire::Message::ChannelReestablish(msg.clone())); } fn peer_disconnected(&self, their_node_id: &PublicKey) { assert!(self.connected_peers.lock().unwrap().remove(their_node_id)); } - fn peer_connected(&self, their_node_id: &PublicKey, _msg: &msgs::Init, _inbound: bool) -> Result<(), ()> { + fn peer_connected( + &self, their_node_id: &PublicKey, _msg: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { assert!(self.connected_peers.lock().unwrap().insert(their_node_id.clone())); // Don't bother with `received_msg` for Init as its auto-generated and we don't want to // bother re-generating the expected Init message in all tests. @@ -916,7 +1090,7 @@ fn get_dummy_channel_update(short_chan_id: u64) -> msgs::ChannelUpdate { fee_base_msat: 0, fee_proportional_millionths: 0, excess_data: vec![], - } + }, } } @@ -938,18 +1112,27 @@ impl TestRoutingMessageHandler { } } impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { - fn handle_node_announcement(&self, _msg: &msgs::NodeAnnouncement) -> Result { + fn handle_node_announcement( + &self, _msg: &msgs::NodeAnnouncement, + ) -> Result { Err(msgs::LightningError { err: "".to_owned(), action: msgs::ErrorAction::IgnoreError }) } - fn handle_channel_announcement(&self, _msg: &msgs::ChannelAnnouncement) -> Result { + fn handle_channel_announcement( + &self, _msg: &msgs::ChannelAnnouncement, + ) -> Result { self.chan_anns_recvd.fetch_add(1, Ordering::AcqRel); Err(msgs::LightningError { err: "".to_owned(), action: msgs::ErrorAction::IgnoreError }) } - fn handle_channel_update(&self, _msg: &msgs::ChannelUpdate) -> Result { + fn handle_channel_update( + &self, _msg: &msgs::ChannelUpdate, + ) -> Result { self.chan_upds_recvd.fetch_add(1, Ordering::AcqRel); Err(msgs::LightningError { err: "".to_owned(), action: msgs::ErrorAction::IgnoreError }) } - fn get_next_channel_announcement(&self, starting_point: u64) -> Option<(msgs::ChannelAnnouncement, Option, Option)> { + fn get_next_channel_announcement( + &self, starting_point: u64, + ) -> Option<(msgs::ChannelAnnouncement, Option, Option)> + { let chan_upd_1 = get_dummy_channel_update(starting_point); let chan_upd_2 = get_dummy_channel_update(starting_point); let chan_ann = get_dummy_channel_announcement(starting_point); @@ -957,11 +1140,15 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { Some((chan_ann, Some(chan_upd_1), Some(chan_upd_2))) } - fn get_next_node_announcement(&self, _starting_point: Option<&NodeId>) -> Option { + fn get_next_node_announcement( + &self, _starting_point: Option<&NodeId>, + ) -> Option { None } - fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init, _inbound: bool) -> Result<(), ()> { + fn peer_connected( + &self, their_node_id: &PublicKey, init_msg: &msgs::Init, _inbound: bool, + ) -> Result<(), ()> { if !init_msg.features.supports_gossip_queries() { return Ok(()); } @@ -970,7 +1157,10 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { let mut gossip_start_time = 0; #[cfg(feature = "std")] { - gossip_start_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time must be > 1970").as_secs(); + gossip_start_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time must be > 1970") + .as_secs(); if self.request_full_sync.load(Ordering::Acquire) { gossip_start_time -= 60 * 60 * 24 * 7 * 2; // 2 weeks ago } else { @@ -990,19 +1180,27 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { Ok(()) } - fn handle_reply_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyChannelRange) -> Result<(), msgs::LightningError> { + fn handle_reply_channel_range( + &self, _their_node_id: &PublicKey, _msg: msgs::ReplyChannelRange, + ) -> Result<(), msgs::LightningError> { Ok(()) } - fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyShortChannelIdsEnd) -> Result<(), msgs::LightningError> { + fn handle_reply_short_channel_ids_end( + &self, _their_node_id: &PublicKey, _msg: msgs::ReplyShortChannelIdsEnd, + ) -> Result<(), msgs::LightningError> { Ok(()) } - fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::QueryChannelRange) -> Result<(), msgs::LightningError> { + fn handle_query_channel_range( + &self, _their_node_id: &PublicKey, _msg: msgs::QueryChannelRange, + ) -> Result<(), msgs::LightningError> { Ok(()) } - fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: msgs::QueryShortChannelIds) -> Result<(), msgs::LightningError> { + fn handle_query_short_channel_ids( + &self, _their_node_id: &PublicKey, _msg: msgs::QueryShortChannelIds, + ) -> Result<(), msgs::LightningError> { Ok(()) } @@ -1018,7 +1216,9 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { features } - fn processing_queue_high(&self) -> bool { false } + fn processing_queue_high(&self) -> bool { + false + } } impl events::MessageSendEventsProvider for TestRoutingMessageHandler { @@ -1063,9 +1263,11 @@ impl TestLogger { /// And asserts if the number of occurrences is the same with the given `count` pub fn assert_log_contains(&self, module: &str, line: &str, count: usize) { let log_entries = self.lines.lock().unwrap(); - let l: usize = log_entries.iter().filter(|&(&(ref m, ref l), _c)| { - *m == module && l.contains(line) - }).map(|(_, c) | { c }).sum(); + let l: usize = log_entries + .iter() + .filter(|&(&(ref m, ref l), _c)| *m == module && l.contains(line)) + .map(|(_, c)| c) + .sum(); assert_eq!(l, count) } @@ -1076,14 +1278,17 @@ impl TestLogger { #[cfg(any(test, feature = "_test_utils"))] pub fn assert_log_regex(&self, module: &str, pattern: regex::Regex, count: usize) { let log_entries = self.lines.lock().unwrap(); - let l: usize = log_entries.iter().filter(|&(&(ref m, ref l), _c)| { - *m == module && pattern.is_match(&l) - }).map(|(_, c) | { c }).sum(); + let l: usize = log_entries + .iter() + .filter(|&(&(ref m, ref l), _c)| *m == module && pattern.is_match(&l)) + .map(|(_, c)| c) + .sum(); assert_eq!(l, count) } pub fn assert_log_context_contains( - &self, module: &str, peer_id: Option, channel_id: Option, count: usize + &self, module: &str, peer_id: Option, channel_id: Option, + count: usize, ) { let context_entries = self.context.lock().unwrap(); let l = context_entries.get(&(module, peer_id, channel_id)).unwrap(); @@ -1093,11 +1298,28 @@ impl TestLogger { impl Logger for TestLogger { fn log(&self, record: Record) { - *self.lines.lock().unwrap().entry((record.module_path, format!("{}", record.args))).or_insert(0) += 1; - *self.context.lock().unwrap().entry((record.module_path, record.peer_id, record.channel_id)).or_insert(0) += 1; + *self + .lines + .lock() + .unwrap() + .entry((record.module_path, format!("{}", record.args))) + .or_insert(0) += 1; + *self + .context + .lock() + .unwrap() + .entry((record.module_path, record.peer_id, record.channel_id)) + .or_insert(0) += 1; if record.level >= self.level { - #[cfg(all(not(ldk_bench), feature = "std"))] { - let pfx = format!("{} {} [{}:{}]", self.id, record.level.to_string(), record.module_path, record.line); + #[cfg(all(not(ldk_bench), feature = "std"))] + { + let pfx = format!( + "{} {} [{}:{}]", + self.id, + record.level.to_string(), + record.module_path, + record.line + ); println!("{:<55}{}", pfx, record.args); } } @@ -1122,15 +1344,18 @@ impl NodeSigner for TestNodeSigner { fn get_node_id(&self, recipient: Recipient) -> Result { let node_secret = match recipient { Recipient::Node => Ok(&self.node_secret), - Recipient::PhantomNode => Err(()) + Recipient::PhantomNode => Err(()), }?; Ok(PublicKey::from_secret_key(&Secp256k1::signing_only(), node_secret)) } - fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&bitcoin::secp256k1::Scalar>) -> Result { + fn ecdh( + &self, recipient: Recipient, other_key: &PublicKey, + tweak: Option<&bitcoin::secp256k1::Scalar>, + ) -> Result { let mut node_secret = match recipient { Recipient::Node => Ok(self.node_secret.clone()), - Recipient::PhantomNode => Err(()) + Recipient::PhantomNode => Err(()), }?; if let Some(tweak) = tweak { node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?; @@ -1138,12 +1363,14 @@ impl NodeSigner for TestNodeSigner { Ok(SharedSecret::new(other_key, &node_secret)) } - fn sign_invoice(&self, _: &[u8], _: &[bitcoin::bech32::u5], _: Recipient) -> Result { + fn sign_invoice( + &self, _: &[u8], _: &[bitcoin::bech32::u5], _: Recipient, + ) -> Result { unreachable!() } fn sign_bolt12_invoice_request( - &self, _invoice_request: &UnsignedInvoiceRequest + &self, _invoice_request: &UnsignedInvoiceRequest, ) -> Result { unreachable!() } @@ -1163,7 +1390,7 @@ pub struct TestKeysInterface { pub backing: sign::PhantomKeysManager, pub override_random_bytes: Mutex>, pub disable_revocation_policy_check: bool, - enforcement_states: Mutex>>>, + enforcement_states: Mutex>>>, expectations: Mutex>>, } @@ -1182,7 +1409,9 @@ impl NodeSigner for TestKeysInterface { self.backing.get_node_id(recipient) } - fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result { + fn ecdh( + &self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>, + ) -> Result { self.backing.ecdh(recipient, other_key, tweak) } @@ -1190,12 +1419,14 @@ impl NodeSigner for TestKeysInterface { self.backing.get_inbound_payment_key_material() } - fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { + fn sign_invoice( + &self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient, + ) -> Result { self.backing.sign_invoice(hrp_bytes, invoice_data, recipient) } fn sign_bolt12_invoice_request( - &self, invoice_request: &UnsignedInvoiceRequest + &self, invoice_request: &UnsignedInvoiceRequest, ) -> Result { self.backing.sign_bolt12_invoice_request(invoice_request) } @@ -1216,11 +1447,15 @@ impl SignerProvider for TestKeysInterface { #[cfg(taproot)] type TaprootSigner = TestChannelSigner; - fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] { + fn generate_channel_keys_id( + &self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128, + ) -> [u8; 32] { self.backing.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id) } - fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> TestChannelSigner { + fn derive_channel_signer( + &self, channel_value_satoshis: u64, channel_keys_id: [u8; 32], + ) -> TestChannelSigner { let keys = self.backing.derive_channel_signer(channel_value_satoshis, channel_keys_id); let state = self.make_enforcement_state_cell(keys.commitment_seed); TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check) @@ -1232,14 +1467,12 @@ impl SignerProvider for TestKeysInterface { let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); - Ok(TestChannelSigner::new_with_revoked( - inner, - state, - self.disable_revocation_policy_check - )) + Ok(TestChannelSigner::new_with_revoked(inner, state, self.disable_revocation_policy_check)) } - fn get_destination_script(&self, channel_keys_id: [u8; 32]) -> Result { self.backing.get_destination_script(channel_keys_id) } + fn get_destination_script(&self, channel_keys_id: [u8; 32]) -> Result { + self.backing.get_destination_script(channel_keys_id) + } fn get_shutdown_scriptpubkey(&self) -> Result { match &mut *self.expectations.lock().unwrap() { @@ -1267,19 +1500,25 @@ impl TestKeysInterface { /// Sets an expectation that [`sign::SignerProvider::get_shutdown_scriptpubkey`] is /// called. pub fn expect(&self, expectation: OnGetShutdownScriptpubkey) -> &Self { - self.expectations.lock().unwrap() + self.expectations + .lock() + .unwrap() .get_or_insert_with(|| VecDeque::new()) .push_back(expectation); self } - pub fn derive_channel_keys(&self, channel_value_satoshis: u64, id: &[u8; 32]) -> TestChannelSigner { + pub fn derive_channel_keys( + &self, channel_value_satoshis: u64, id: &[u8; 32], + ) -> TestChannelSigner { let keys = self.backing.derive_channel_keys(channel_value_satoshis, id); let state = self.make_enforcement_state_cell(keys.commitment_seed); TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check) } - fn make_enforcement_state_cell(&self, commitment_seed: [u8; 32]) -> Arc> { + fn make_enforcement_state_cell( + &self, commitment_seed: [u8; 32], + ) -> Arc> { let mut states = self.enforcement_states.lock().unwrap(); if !states.contains_key(&commitment_seed) { let state = EnforcementState::new(); @@ -1338,7 +1577,10 @@ impl TestChainSource { let script_pubkey = Builder::new().push_opcode(opcodes::OP_TRUE).into_script(); Self { chain_hash: ChainHash::using_genesis_block(network), - utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { value: u64::max_value(), script_pubkey }))), + utxo_ret: Mutex::new(UtxoResult::Sync(Ok(TxOut { + value: u64::max_value(), + script_pubkey, + }))), get_utxo_call_count: AtomicUsize::new(0), watched_txn: Mutex::new(HashSet::new()), watched_outputs: Mutex::new(HashSet::new()), @@ -1382,25 +1624,29 @@ pub struct TestScorer { impl TestScorer { pub fn new() -> Self { - Self { - scorer_expectations: RefCell::new(None), - } + Self { scorer_expectations: RefCell::new(None) } } pub fn expect_usage(&self, scid: u64, expectation: ChannelUsage) { - self.scorer_expectations.borrow_mut().get_or_insert_with(|| VecDeque::new()).push_back((scid, expectation)); + self.scorer_expectations + .borrow_mut() + .get_or_insert_with(|| VecDeque::new()) + .push_back((scid, expectation)); } } #[cfg(c_bindings)] impl crate::util::ser::Writeable for TestScorer { - fn write(&self, _: &mut W) -> Result<(), crate::io::Error> { unreachable!(); } + fn write(&self, _: &mut W) -> Result<(), crate::io::Error> { + unreachable!(); + } } impl ScoreLookUp for TestScorer { type ScoreParams = (); fn channel_penalty_msat( - &self, candidate: &CandidateRouteHop, usage: ChannelUsage, _score_params: &Self::ScoreParams + &self, candidate: &CandidateRouteHop, usage: ChannelUsage, + _score_params: &Self::ScoreParams, ) -> u64 { let short_channel_id = match candidate.globally_unique_short_channel_id() { Some(scid) => scid, @@ -1420,7 +1666,11 @@ impl ScoreLookUp for TestScorer { } impl ScoreUpdate for TestScorer { - fn payment_path_failed(&mut self, _actual_path: &Path, _actual_short_channel_id: u64, _duration_since_epoch: Duration) {} + fn payment_path_failed( + &mut self, _actual_path: &Path, _actual_short_channel_id: u64, + _duration_since_epoch: Duration, + ) { + } fn payment_path_successful(&mut self, _actual_path: &Path, _duration_since_epoch: Duration) {} @@ -1436,7 +1686,8 @@ impl crate::routing::scoring::Score for TestScorer {} impl Drop for TestScorer { fn drop(&mut self) { - #[cfg(feature = "std")] { + #[cfg(feature = "std")] + { if std::thread::panicking() { return; } @@ -1458,11 +1709,7 @@ pub struct TestWalletSource { impl TestWalletSource { pub fn new(secret_key: SecretKey) -> Self { - Self { - secret_key, - utxos: RefCell::new(Vec::new()), - secp: Secp256k1::new(), - } + Self { secret_key, utxos: RefCell::new(Vec::new()), secp: Secp256k1::new() } } pub fn add_utxo(&self, outpoint: bitcoin::OutPoint, value: u64) -> TxOut { @@ -1497,9 +1744,15 @@ impl WalletSource for TestWalletSource { let mut tx = psbt.extract_tx(); let utxos = self.utxos.borrow(); for i in 0..tx.input.len() { - if let Some(utxo) = utxos.iter().find(|utxo| utxo.outpoint == tx.input[i].previous_output) { + if let Some(utxo) = + utxos.iter().find(|utxo| utxo.outpoint == tx.input[i].previous_output) + { let sighash = SighashCache::new(&tx) - .legacy_signature_hash(i, &utxo.output.script_pubkey, EcdsaSighashType::All as u32) + .legacy_signature_hash( + i, + &utxo.output.script_pubkey, + EcdsaSighashType::All as u32, + ) .map_err(|_| ())?; let sig = self.secp.sign_ecdsa(&(*sighash.as_raw_hash()).into(), &self.secret_key); let bitcoin_sig = bitcoin::ecdsa::Signature { sig, hash_ty: EcdsaSighashType::All }; diff --git a/lightning/src/util/time.rs b/lightning/src/util/time.rs index a6e6f4d1fda..1fa6eccfec6 100644 --- a/lightning/src/util/time.rs +++ b/lightning/src/util/time.rs @@ -12,7 +12,10 @@ use core::ops::Sub; use core::time::Duration; /// A measurement of time. -pub trait Time: Copy + Sub where Self: Sized { +pub trait Time: Copy + Sub +where + Self: Sized, +{ /// Returns an instance corresponding to the current moment. fn now() -> Self; @@ -70,7 +73,9 @@ const SHIFT: Duration = Duration::from_secs(10 * 365 * 24 * 60 * 60); // 10 year #[cfg(feature = "std")] impl Time for MonotonicTime { fn now() -> Self { - let instant = std::time::Instant::now().checked_add(SHIFT).expect("Overflow on MonotonicTime instantiation"); + let instant = std::time::Instant::now() + .checked_add(SHIFT) + .expect("Overflow on MonotonicTime instantiation"); Self(instant) } @@ -80,7 +85,11 @@ impl Time for MonotonicTime { // clocks" that go backwards in practice (likely relatively ancient kernels/etc). Thus, we // manually check for time going backwards here and return a duration of zero in that case. let now = Self::now(); - if now.0 > earlier.0 { now.0 - earlier.0 } else { Duration::from_secs(0) } + if now.0 > earlier.0 { + now.0 - earlier.0 + } else { + Duration::from_secs(0) + } } fn duration_since_epoch() -> Duration { @@ -98,18 +107,21 @@ impl Sub for MonotonicTime { type Output = Self; fn sub(self, other: Duration) -> Self { - let instant = self.0.checked_sub(other).expect("MonotonicTime is not supposed to go backward futher than 10 years"); + let instant = self + .0 + .checked_sub(other) + .expect("MonotonicTime is not supposed to go backward futher than 10 years"); Self(instant) } } #[cfg(test)] pub mod tests { - use super::{Time, Eternity}; + use super::{Eternity, Time}; - use core::time::Duration; - use core::ops::Sub; use core::cell::Cell; + use core::ops::Sub; + use core::time::Duration; /// Time that can be advanced manually in tests. #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/lightning/src/util/transaction_utils.rs b/lightning/src/util/transaction_utils.rs index 12b504a69ef..9e0370da6b0 100644 --- a/lightning/src/util/transaction_utils.rs +++ b/lightning/src/util/transaction_utils.rs @@ -7,23 +7,21 @@ // You may not use this file except in accordance with one or both of these // licenses. -use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::blockdata::script::ScriptBuf; -use bitcoin::consensus::Encodable; +use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::consensus::encode::VarInt; +use bitcoin::consensus::Encodable; use crate::ln::msgs::MAX_VALUE_MSAT; -use crate::prelude::*; use crate::io_extras::sink; +use crate::prelude::*; use core::cmp::Ordering; -pub fn sort_outputs Ordering>(outputs: &mut Vec<(TxOut, T)>, tie_breaker: C) { +pub fn sort_outputs Ordering>(outputs: &mut Vec<(TxOut, T)>, tie_breaker: C) { outputs.sort_unstable_by(|a, b| { a.0.value.cmp(&b.0.value).then_with(|| { - a.0.script_pubkey[..].cmp(&b.0.script_pubkey[..]).then_with(|| { - tie_breaker(&a.1, &b.1) - }) + a.0.script_pubkey[..].cmp(&b.0.script_pubkey[..]).then_with(|| tie_breaker(&a.1, &b.1)) }) }); } @@ -33,34 +31,44 @@ pub fn sort_outputs Ordering>(outputs: &mut Vec<(TxOut, T)> /// Assumes at least one input will have a witness (ie spends a segwit output). /// Returns an Err(()) if the requested feerate cannot be met. /// Returns the expected maximum weight of the fully signed transaction on success. -pub(crate) fn maybe_add_change_output(tx: &mut Transaction, input_value: u64, witness_max_weight: u64, feerate_sat_per_1000_weight: u32, change_destination_script: ScriptBuf) -> Result { - if input_value > MAX_VALUE_MSAT / 1000 { return Err(()); } +pub(crate) fn maybe_add_change_output( + tx: &mut Transaction, input_value: u64, witness_max_weight: u64, + feerate_sat_per_1000_weight: u32, change_destination_script: ScriptBuf, +) -> Result { + if input_value > MAX_VALUE_MSAT / 1000 { + return Err(()); + } const WITNESS_FLAG_BYTES: u64 = 2; let mut output_value = 0; for output in tx.output.iter() { output_value += output.value; - if output_value >= input_value { return Err(()); } + if output_value >= input_value { + return Err(()); + } } let dust_value = change_destination_script.dust_value(); - let mut change_output = TxOut { - script_pubkey: change_destination_script, - value: 0, - }; + let mut change_output = TxOut { script_pubkey: change_destination_script, value: 0 }; let change_len = change_output.consensus_encode(&mut sink()).unwrap(); let starting_weight = tx.weight().to_wu() + WITNESS_FLAG_BYTES + witness_max_weight as u64; let mut weight_with_change: i64 = starting_weight as i64 + change_len as i64 * 4; // Include any extra bytes required to push an extra output. - weight_with_change += (VarInt(tx.output.len() as u64 + 1).len() - VarInt(tx.output.len() as u64).len()) as i64 * 4; + weight_with_change += (VarInt(tx.output.len() as u64 + 1).len() + - VarInt(tx.output.len() as u64).len()) as i64 + * 4; // When calculating weight, add two for the flag bytes - let change_value: i64 = (input_value - output_value) as i64 - weight_with_change * feerate_sat_per_1000_weight as i64 / 1000; + let change_value: i64 = (input_value - output_value) as i64 + - weight_with_change * feerate_sat_per_1000_weight as i64 / 1000; if change_value >= dust_value.to_sat() as i64 { change_output.value = change_value as u64; tx.output.push(change_output); Ok(weight_with_change as u64) - } else if (input_value - output_value) as i64 - (starting_weight as i64) * feerate_sat_per_1000_weight as i64 / 1000 < 0 { + } else if (input_value - output_value) as i64 + - (starting_weight as i64) * feerate_sat_per_1000_weight as i64 / 1000 + < 0 + { Err(()) } else { Ok(starting_weight) @@ -72,59 +80,48 @@ mod tests { use super::*; use bitcoin::blockdata::locktime::absolute::LockTime; - use bitcoin::blockdata::transaction::{Transaction, TxOut, TxIn, OutPoint}; - use bitcoin::blockdata::script::{ScriptBuf, Builder}; + use bitcoin::blockdata::script::{Builder, ScriptBuf}; + use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; use bitcoin::hash_types::{PubkeyHash, Txid}; - use bitcoin::hashes::Hash; use bitcoin::hashes::hex::FromHex; + use bitcoin::hashes::Hash; use bitcoin::{Sequence, Witness}; use alloc::vec; #[test] fn sort_output_by_value() { - let txout1 = TxOut { - value: 100, - script_pubkey: Builder::new().push_int(0).into_script() - }; + let txout1 = TxOut { value: 100, script_pubkey: Builder::new().push_int(0).into_script() }; let txout1_ = txout1.clone(); - let txout2 = TxOut { - value: 99, - script_pubkey: Builder::new().push_int(0).into_script() - }; + let txout2 = TxOut { value: 99, script_pubkey: Builder::new().push_int(0).into_script() }; let txout2_ = txout2.clone(); let mut outputs = vec![(txout1, "ignore"), (txout2, "ignore")]; - sort_outputs(&mut outputs, |_, _| { unreachable!(); }); + sort_outputs(&mut outputs, |_, _| { + unreachable!(); + }); - assert_eq!( - &outputs, - &vec![(txout2_, "ignore"), (txout1_, "ignore")] - ); + assert_eq!(&outputs, &vec![(txout2_, "ignore"), (txout1_, "ignore")]); } #[test] fn sort_output_by_script_pubkey() { - let txout1 = TxOut { - value: 100, - script_pubkey: Builder::new().push_int(3).into_script(), - }; + let txout1 = TxOut { value: 100, script_pubkey: Builder::new().push_int(3).into_script() }; let txout1_ = txout1.clone(); let txout2 = TxOut { value: 100, - script_pubkey: Builder::new().push_int(1).push_int(2).into_script() + script_pubkey: Builder::new().push_int(1).push_int(2).into_script(), }; let txout2_ = txout2.clone(); let mut outputs = vec![(txout1, "ignore"), (txout2, "ignore")]; - sort_outputs(&mut outputs, |_, _| { unreachable!(); }); + sort_outputs(&mut outputs, |_, _| { + unreachable!(); + }); - assert_eq!( - &outputs, - &vec![(txout2_, "ignore"), (txout1_, "ignore")] - ); + assert_eq!(&outputs, &vec![(txout2_, "ignore"), (txout1_, "ignore")]); } #[test] @@ -143,7 +140,9 @@ mod tests { let txout2_ = txout2.clone(); let mut outputs = vec![(txout1, "ignore"), (txout2, "ignore")]; - sort_outputs(&mut outputs, |_, _| { unreachable!(); }); + sort_outputs(&mut outputs, |_, _| { + unreachable!(); + }); assert_eq!(&outputs, &vec![(txout1_, "ignore"), (txout2_, "ignore")]); } @@ -151,8 +150,8 @@ mod tests { #[test] fn sort_output_tie_breaker_test() { let txout1 = TxOut { - value: 100, - script_pubkey: Builder::new().push_int(1).push_int(2).into_script() + value: 100, + script_pubkey: Builder::new().push_int(1).push_int(2).into_script(), }; let txout1_ = txout1.clone(); @@ -160,12 +159,9 @@ mod tests { let txout2_ = txout1.clone(); let mut outputs = vec![(txout1, 420), (txout2, 69)]; - sort_outputs(&mut outputs, |a, b| { a.cmp(b) }); + sort_outputs(&mut outputs, |a, b| a.cmp(b)); - assert_eq!( - &outputs, - &vec![(txout2_, 69), (txout1_, 420)] - ); + assert_eq!(&outputs, &vec![(txout2_, 69), (txout1_, 420)]); } fn script_from_hex(hex_str: &str) -> ScriptBuf { @@ -213,10 +209,14 @@ mod tests { #[test] fn test_tx_value_overrun() { // If we have a bogus input amount or outputs valued more than inputs, we should fail - let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - script_pubkey: ScriptBuf::new(), value: 1000 - }] }; - assert!(maybe_add_change_output(&mut tx, 21_000_000_0000_0001, 0, 253, ScriptBuf::new()).is_err()); + let mut tx = Transaction { + version: 2, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: vec![TxOut { script_pubkey: ScriptBuf::new(), value: 1000 }], + }; + assert!(maybe_add_change_output(&mut tx, 21_000_000_0000_0001, 0, 253, ScriptBuf::new()) + .is_err()); assert!(maybe_add_change_output(&mut tx, 400, 0, 253, ScriptBuf::new()).is_err()); assert!(maybe_add_change_output(&mut tx, 4000, 0, 253, ScriptBuf::new()).is_ok()); } @@ -224,7 +224,12 @@ mod tests { #[test] fn test_tx_change_edge() { // Check that we never add dust outputs - let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; + let mut tx = Transaction { + version: 2, + lock_time: LockTime::ZERO, + input: Vec::new(), + output: Vec::new(), + }; let orig_wtxid = tx.wtxid(); let output_spk = ScriptBuf::new_p2pkh(&PubkeyHash::hash(&[0; 0])); assert_eq!(output_spk.dust_value().to_sat(), 546); @@ -232,24 +237,24 @@ mod tests { assert_eq!(tx.weight().to_wu(), 40); // ie 10 vbytes assert!(maybe_add_change_output(&mut tx, 9, 0, 250, output_spk.clone()).is_err()); assert_eq!(tx.wtxid(), orig_wtxid); // Failure doesn't change the transaction - // but 10-564 is, just not enough to add a change output... + // but 10-564 is, just not enough to add a change output... assert!(maybe_add_change_output(&mut tx, 10, 0, 250, output_spk.clone()).is_ok()); assert_eq!(tx.output.len(), 0); assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction assert!(maybe_add_change_output(&mut tx, 549, 0, 250, output_spk.clone()).is_ok()); assert_eq!(tx.output.len(), 0); assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction - // 590 is also not enough, if we anticipate 2 more weight units pushing us up to the next vbyte - // (considering the two bytes for segwit flags) + // 590 is also not enough, if we anticipate 2 more weight units pushing us up to the next vbyte + // (considering the two bytes for segwit flags) assert!(maybe_add_change_output(&mut tx, 590, 2, 250, output_spk.clone()).is_ok()); assert_eq!(tx.output.len(), 0); assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction - // at 590 we can afford the change output at the dust limit (546) + // at 590 we can afford the change output at the dust limit (546) assert!(maybe_add_change_output(&mut tx, 590, 0, 250, output_spk.clone()).is_ok()); assert_eq!(tx.output.len(), 1); assert_eq!(tx.output[0].value, 546); assert_eq!(tx.output[0].script_pubkey, output_spk); - assert_eq!(tx.weight().to_wu() / 4, 590-546); // New weight is exactly the fee we wanted. + assert_eq!(tx.weight().to_wu() / 4, 590 - 546); // New weight is exactly the fee we wanted. tx.output.pop(); assert_eq!(tx.wtxid(), orig_wtxid); // The only change is the addition of one output. @@ -258,11 +263,20 @@ mod tests { #[test] fn test_tx_extra_outputs() { // Check that we correctly handle existing outputs - let mut tx = Transaction { version: 2, lock_time: LockTime::ZERO, input: vec![TxIn { - previous_output: OutPoint::new(Txid::all_zeros(), 0), script_sig: ScriptBuf::new(), witness: Witness::new(), sequence: Sequence::ZERO, - }], output: vec![TxOut { - script_pubkey: Builder::new().push_int(1).into_script(), value: 1000 - }] }; + let mut tx = Transaction { + version: 2, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: OutPoint::new(Txid::all_zeros(), 0), + script_sig: ScriptBuf::new(), + witness: Witness::new(), + sequence: Sequence::ZERO, + }], + output: vec![TxOut { + script_pubkey: Builder::new().push_int(1).into_script(), + value: 1000, + }], + }; let orig_wtxid = tx.wtxid(); let orig_weight = tx.weight().to_wu(); assert_eq!(orig_weight / 4, 61); @@ -270,16 +284,44 @@ mod tests { assert_eq!(Builder::new().push_int(2).into_script().dust_value().to_sat(), 474); // Input value of the output value + fee - 1 should fail: - assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100 - 1, 400, 250, Builder::new().push_int(2).into_script()).is_err()); + assert!(maybe_add_change_output( + &mut tx, + 1000 + 61 + 100 - 1, + 400, + 250, + Builder::new().push_int(2).into_script() + ) + .is_err()); assert_eq!(tx.wtxid(), orig_wtxid); // Failure doesn't change the transaction - // but one more input sat should succeed, without changing the transaction - assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100, 400, 250, Builder::new().push_int(2).into_script()).is_ok()); + // but one more input sat should succeed, without changing the transaction + assert!(maybe_add_change_output( + &mut tx, + 1000 + 61 + 100, + 400, + 250, + Builder::new().push_int(2).into_script() + ) + .is_ok()); assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction - // In order to get a change output, we need to add 474 plus the output's weight / 4 (10)... - assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100 + 474 + 9, 400, 250, Builder::new().push_int(2).into_script()).is_ok()); + // In order to get a change output, we need to add 474 plus the output's weight / 4 (10)... + assert!(maybe_add_change_output( + &mut tx, + 1000 + 61 + 100 + 474 + 9, + 400, + 250, + Builder::new().push_int(2).into_script() + ) + .is_ok()); assert_eq!(tx.wtxid(), orig_wtxid); // If we don't add an output, we don't change the transaction - assert!(maybe_add_change_output(&mut tx, 1000 + 61 + 100 + 474 + 10, 400, 250, Builder::new().push_int(2).into_script()).is_ok()); + assert!(maybe_add_change_output( + &mut tx, + 1000 + 61 + 100 + 474 + 10, + 400, + 250, + Builder::new().push_int(2).into_script() + ) + .is_ok()); assert_eq!(tx.output.len(), 2); assert_eq!(tx.output[1].value, 474); assert_eq!(tx.output[1].script_pubkey, Builder::new().push_int(2).into_script()); diff --git a/lightning/src/util/wakers.rs b/lightning/src/util/wakers.rs index 14e6bbe64a2..b2448aac743 100644 --- a/lightning/src/util/wakers.rs +++ b/lightning/src/util/wakers.rs @@ -13,9 +13,9 @@ //! //! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager +use crate::sync::Mutex; use alloc::sync::Arc; use core::mem; -use crate::sync::Mutex; use crate::prelude::*; @@ -25,9 +25,8 @@ use crate::sync::Condvar; use std::time::Duration; use core::future::Future as StdFuture; -use core::task::{Context, Poll}; use core::pin::Pin; - +use core::task::{Context, Poll}; /// Used to signal to one of many waiters that the condition they're waiting on has happened. pub(crate) struct Notifier { @@ -36,9 +35,7 @@ pub(crate) struct Notifier { impl Notifier { pub(crate) fn new() -> Self { - Self { - notify_pending: Mutex::new((false, None)), - } + Self { notify_pending: Mutex::new((false, None)) } } /// Wake waiters, tracking that wake needs to occur even if there are currently no waiters. @@ -187,14 +184,18 @@ impl Future { if state.complete { state.callbacks_made = true; true - } else { false } + } else { + false + } } } use core::task::Waker; struct StdWaker(pub Waker); impl FutureCallback for StdWaker { - fn call(&self) { self.0.wake_by_ref() } + fn call(&self) { + self.0.wake_by_ref() + } } /// This is not exported to bindings users as Rust Futures aren't usable in language bindings. @@ -251,10 +252,13 @@ impl Sleeper { *notified_fut_mtx.lock().unwrap() = Some(Arc::clone(¬ifier_mtx)); break; } - notifier.callbacks_with_state.push((false, Box::new(move |notifier_ref| { - *notified_fut_ref.lock().unwrap() = Some(Arc::clone(notifier_ref)); - cv_ref.notify_all(); - }))); + notifier.callbacks_with_state.push(( + false, + Box::new(move |notifier_ref| { + *notified_fut_ref.lock().unwrap() = Some(Arc::clone(notifier_ref)); + cv_ref.notify_all(); + }), + )); } } (cv, notified_fut_mtx) @@ -263,8 +267,11 @@ impl Sleeper { /// Wait until one of the [`Future`]s registered with this [`Sleeper`] has completed. pub fn wait(&self) { let (cv, notified_fut_mtx) = self.setup_wait(); - let notified_fut = cv.wait_while(notified_fut_mtx.lock().unwrap(), |fut_opt| fut_opt.is_none()) - .unwrap().take().expect("CV wait shouldn't have returned until the notifying future was set"); + let notified_fut = cv + .wait_while(notified_fut_mtx.lock().unwrap(), |fut_opt| fut_opt.is_none()) + .unwrap() + .take() + .expect("CV wait shouldn't have returned until the notifying future was set"); notified_fut.lock().unwrap().callbacks_made = true; } @@ -274,10 +281,13 @@ impl Sleeper { pub fn wait_timeout(&self, max_wait: Duration) -> bool { let (cv, notified_fut_mtx) = self.setup_wait(); let notified_fut = - match cv.wait_timeout_while(notified_fut_mtx.lock().unwrap(), max_wait, |fut_opt| fut_opt.is_none()) { + match cv.wait_timeout_while(notified_fut_mtx.lock().unwrap(), max_wait, |fut_opt| { + fut_opt.is_none() + }) { Ok((_, e)) if e.timed_out() => return false, - Ok((mut notified_fut, _)) => - notified_fut.take().expect("CV wait shouldn't have returned until the notifying future was set"), + Ok((mut notified_fut, _)) => notified_fut + .take() + .expect("CV wait shouldn't have returned until the notifying future was set"), Err(_) => panic!("Previous panic while a lock was held led to a lock panic"), }; notified_fut.lock().unwrap().callbacks_made = true; @@ -288,8 +298,8 @@ impl Sleeper { #[cfg(test)] mod tests { use super::*; - use core::sync::atomic::{AtomicBool, Ordering}; use core::future::Future as FutureTrait; + use core::sync::atomic::{AtomicBool, Ordering}; use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; #[test] @@ -302,7 +312,9 @@ mod tests { let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - notifier.get_future().register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + notifier.get_future().register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(callback.load(Ordering::SeqCst)); } @@ -317,7 +329,9 @@ mod tests { // a second `notify`. let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - notifier.get_future().register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + notifier.get_future().register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(!callback.load(Ordering::SeqCst)); notifier.notify(); @@ -325,7 +339,9 @@ mod tests { let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - notifier.get_future().register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + notifier.get_future().register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(!callback.load(Ordering::SeqCst)); notifier.notify(); @@ -339,12 +355,16 @@ mod tests { let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - future.register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + future.register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(callback.load(Ordering::SeqCst)); let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - notifier.get_future().register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + notifier.get_future().register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(!callback.load(Ordering::SeqCst)); } @@ -358,12 +378,16 @@ mod tests { let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - notifier.get_future().register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + notifier.get_future().register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(callback.load(Ordering::SeqCst)); let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - notifier.get_future().register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + notifier.get_future().register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(!callback.load(Ordering::SeqCst)); notifier.notify(); @@ -381,12 +405,10 @@ mod tests { let exit_thread = Arc::new(AtomicBool::new(false)); let exit_thread_clone = exit_thread.clone(); - thread::spawn(move || { - loop { - thread_notifier.notify(); - if exit_thread_clone.load(Ordering::SeqCst) { - break - } + thread::spawn(move || loop { + thread_notifier.notify(); + if exit_thread_clone.load(Ordering::SeqCst) { + break; } }); @@ -397,7 +419,7 @@ mod tests { // available. loop { if persistence_notifier.get_future().wait_timeout(Duration::from_millis(100)) { - break + break; } } @@ -407,7 +429,7 @@ mod tests { // are available. loop { if !persistence_notifier.get_future().wait_timeout(Duration::from_millis(100)) { - break + break; } } } @@ -458,11 +480,13 @@ mod tests { callbacks_with_state: Vec::new(), complete: false, callbacks_made: false, - })) + })), }; let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - future.register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + future.register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(!callback.load(Ordering::SeqCst)); complete_future(&future.state); @@ -478,13 +502,15 @@ mod tests { callbacks_with_state: Vec::new(), complete: false, callbacks_made: false, - })) + })), }; complete_future(&future.state); let callback = Arc::new(AtomicBool::new(false)); let callback_ref = Arc::clone(&callback); - future.register_callback(Box::new(move || assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)))); + future.register_callback(Box::new(move || { + assert!(!callback_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(callback.load(Ordering::SeqCst)); assert!(future.state.lock().unwrap().callbacks.is_empty()); @@ -495,9 +521,18 @@ mod tests { // compared to a raw VTable). Instead, we have to write out a lot of boilerplate to build a // waker, which we do here with a trivial Arc data element to track woke-ness. const WAKER_V_TABLE: RawWakerVTable = RawWakerVTable::new(waker_clone, wake, wake_by_ref, drop); - unsafe fn wake_by_ref(ptr: *const ()) { let p = ptr as *const Arc; assert!(!(*p).fetch_or(true, Ordering::SeqCst)); } - unsafe fn drop(ptr: *const ()) { let p = ptr as *mut Arc; let _freed = Box::from_raw(p); } - unsafe fn wake(ptr: *const ()) { wake_by_ref(ptr); drop(ptr); } + unsafe fn wake_by_ref(ptr: *const ()) { + let p = ptr as *const Arc; + assert!(!(*p).fetch_or(true, Ordering::SeqCst)); + } + unsafe fn drop(ptr: *const ()) { + let p = ptr as *mut Arc; + let _freed = Box::from_raw(p); + } + unsafe fn wake(ptr: *const ()) { + wake_by_ref(ptr); + drop(ptr); + } unsafe fn waker_clone(ptr: *const ()) -> RawWaker { let p = ptr as *const Arc; RawWaker::new(Box::into_raw(Box::new(Arc::clone(&*p))) as *const (), &WAKER_V_TABLE) @@ -505,7 +540,8 @@ mod tests { fn create_waker() -> (Arc, Waker) { let a = Arc::new(AtomicBool::new(false)); - let waker = unsafe { Waker::from_raw(waker_clone((&a as *const Arc) as *const ())) }; + let waker = + unsafe { Waker::from_raw(waker_clone((&a as *const Arc) as *const ())) }; (a, waker) } @@ -517,7 +553,7 @@ mod tests { callbacks_with_state: Vec::new(), complete: false, callbacks_made: false, - })) + })), }; let mut second_future = Future { state: Arc::clone(&future.state) }; @@ -526,14 +562,20 @@ mod tests { assert!(!woken.load(Ordering::SeqCst)); let (second_woken, second_waker) = create_waker(); - assert_eq!(Pin::new(&mut second_future).poll(&mut Context::from_waker(&second_waker)), Poll::Pending); + assert_eq!( + Pin::new(&mut second_future).poll(&mut Context::from_waker(&second_waker)), + Poll::Pending + ); assert!(!second_woken.load(Ordering::SeqCst)); complete_future(&future.state); assert!(woken.load(Ordering::SeqCst)); assert!(second_woken.load(Ordering::SeqCst)); assert_eq!(Pin::new(&mut future).poll(&mut Context::from_waker(&waker)), Poll::Ready(())); - assert_eq!(Pin::new(&mut second_future).poll(&mut Context::from_waker(&second_waker)), Poll::Ready(())); + assert_eq!( + Pin::new(&mut second_future).poll(&mut Context::from_waker(&second_waker)), + Poll::Ready(()) + ); } #[test] @@ -676,8 +718,12 @@ mod tests { let callback_b = Arc::new(AtomicBool::new(false)); let callback_a_ref = Arc::clone(&callback_a); let callback_b_ref = Arc::clone(&callback_b); - notifier_a.get_future().register_callback(Box::new(move || assert!(!callback_a_ref.fetch_or(true, Ordering::SeqCst)))); - notifier_b.get_future().register_callback(Box::new(move || assert!(!callback_b_ref.fetch_or(true, Ordering::SeqCst)))); + notifier_a.get_future().register_callback(Box::new(move || { + assert!(!callback_a_ref.fetch_or(true, Ordering::SeqCst)) + })); + notifier_b.get_future().register_callback(Box::new(move || { + assert!(!callback_b_ref.fetch_or(true, Ordering::SeqCst)) + })); assert!(callback_a.load(Ordering::SeqCst) ^ callback_b.load(Ordering::SeqCst)); // If we now notify both notifiers again, the other callback will fire, completing the diff --git a/rustfmt.toml b/rustfmt.toml index 91b80232866..4f88472bec5 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1,12 @@ -disable_all_formatting = true \ No newline at end of file +use_small_heuristics = "Max" +fn_params_layout = "Compressed" +hard_tabs = true +use_field_init_shorthand = true +max_width = 100 +match_block_trailing_comma = true +# UNSTABLE: format_code_in_doc_comments = true +# UNSTABLE: overflow_delimited_expr = true +# UNSTABLE: comment_width = 100 +# UNSTABLE: format_macro_matchers = true +# UNSTABLE: format_strings = true +# UNSTABLE: group_imports = "StdExternalCrate"