X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=d3add5dbab7207bd1f5d5fe15e34cbaa30ae3bb5;hb=refs%2Fheads%2F2022-06-no-ro-graph-bindings;hp=3aab92ad0f7f227ca4e2756aa8541fe5163abf7f;hpb=6587607c5144b8a4930a6cbe6e94b6dc0ceb2f78;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 3aab92ad..d3add5db 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -13,10 +13,11 @@ //! responsible for tracking which channels are open, HTLCs are in flight and reestablishing those //! upon reconnect to the relevant peer(s). //! -//! It does not manage routing logic (see routing::router::get_route for that) nor does it manage constructing +//! It does not manage routing logic (see [`find_route`] for that) nor does it manage constructing //! on-chain transactions (it only monitors the chain to watch for any force-closes that might //! imply it needs to fail HTLCs/payments/channels it manages). //! +//! [`find_route`]: crate::routing::router::find_route use bitcoin::blockdata::block::BlockHeader; use bitcoin::blockdata::transaction::Transaction; @@ -48,6 +49,7 @@ use ln::msgs; use ln::msgs::NetAddress; use ln::onion_utils; use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT, OptionalField}; +use ln::wire::Encode; use chain::keysinterface::{Sign, KeysInterface, KeysManager, InMemorySigner, Recipient}; use util::config::UserConfig; use util::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason}; @@ -92,6 +94,8 @@ use util::crypto::sign; pub(super) enum PendingHTLCRouting { Forward { onion_packet: msgs::OnionPacket, + /// The SCID from the onion that we should forward to. This could be a "real" SCID, an + /// outbound SCID alias, or a phantom node SCID. short_channel_id: u64, // This should be NonZero eventually when we bump MSRV }, Receive { @@ -135,6 +139,8 @@ pub(super) enum HTLCForwardInfo { // `process_pending_htlc_forwards()` for constructing the // `HTLCSource::PreviousHopData` for failed and forwarded // HTLCs. + // + // Note that this may be an outbound SCID alias for the associated channel. prev_short_channel_id: u64, prev_htlc_id: u64, prev_funding_outpoint: OutPoint, @@ -148,6 +154,7 @@ pub(super) enum HTLCForwardInfo { /// Tracks the inbound corresponding to an outbound HTLC #[derive(Clone, Hash, PartialEq, Eq)] pub(crate) struct HTLCPreviousHopData { + // Note that this may be an outbound SCID alias for the associated channel. short_channel_id: u64, htlc_id: u64, incoming_packet_shared_secret: [u8; 32], @@ -163,7 +170,7 @@ enum OnionPayload { Invoice { /// This is only here for backwards-compatibility in serialization, in the future it can be /// removed, breaking clients running 0.0.106 and earlier. - _legacy_hop_data: msgs::FinalOnionHopData, + _legacy_hop_data: Option, }, /// Contains the payer-provided preimage. Spontaneous(PaymentPreimage), @@ -413,11 +420,13 @@ pub(super) struct ChannelHolder { /// guarantees are made about the existence of a channel with the short id here, nor the short /// ids in the PendingHTLCInfo! pub(super) forward_htlcs: HashMap>, - /// Map from payment hash to any HTLCs which are to us and can be failed/claimed by the user. + /// Map from payment hash to the payment data and any HTLCs which are to us and can be + /// failed/claimed by the user. + /// /// Note that while this is held in the same mutex as the channels themselves, no consistency /// guarantees are made about the channels given here actually existing anymore by the time you /// go to read them! - claimable_htlcs: HashMap>, + claimable_htlcs: HashMap)>, /// Messages to send to peers - pushed to in the same lock that they are generated in (except /// for broadcast messages, where ordering isn't as strict). pub(super) pending_msg_events: Vec, @@ -962,9 +971,25 @@ pub struct ChannelDetails { /// Note that if [`inbound_scid_alias`] is set, it must be used for invoices and inbound /// payments instead of this. See [`get_inbound_payment_scid`]. /// + /// For channels with [`confirmations_required`] set to `Some(0)`, [`outbound_scid_alias`] may + /// be used in place of this in outbound routes. See [`get_outbound_payment_scid`]. + /// /// [`inbound_scid_alias`]: Self::inbound_scid_alias + /// [`outbound_scid_alias`]: Self::outbound_scid_alias /// [`get_inbound_payment_scid`]: Self::get_inbound_payment_scid + /// [`get_outbound_payment_scid`]: Self::get_outbound_payment_scid + /// [`confirmations_required`]: Self::confirmations_required pub short_channel_id: Option, + /// An optional [`short_channel_id`] alias for this channel, randomly generated by us and + /// usable in place of [`short_channel_id`] to reference the channel in outbound routes when + /// the channel has not yet been confirmed (as long as [`confirmations_required`] is + /// `Some(0)`). + /// + /// This will be `None` as long as the channel is not available for routing outbound payments. + /// + /// [`short_channel_id`]: Self::short_channel_id + /// [`confirmations_required`]: Self::confirmations_required + pub outbound_scid_alias: Option, /// An optional [`short_channel_id`] alias for this channel, randomly generated by our /// counterparty and usable in place of [`short_channel_id`] in invoice route hints. Our /// counterparty will recognize the alias provided here in place of the [`short_channel_id`] @@ -1050,18 +1075,18 @@ pub struct ChannelDetails { pub force_close_spend_delay: Option, /// True if the channel was initiated (and thus funded) by us. pub is_outbound: bool, - /// True if the channel is confirmed, funding_locked messages have been exchanged, and the - /// channel is not currently being shut down. `funding_locked` message exchange implies the + /// True if the channel is confirmed, channel_ready messages have been exchanged, and the + /// channel is not currently being shut down. `channel_ready` message exchange implies the /// required confirmation count has been reached (and we were connected to the peer at some /// point after the funding transaction received enough confirmations). The required /// confirmation count is provided in [`confirmations_required`]. /// /// [`confirmations_required`]: ChannelDetails::confirmations_required - pub is_funding_locked: bool, - /// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b) + pub is_channel_ready: bool, + /// True if the channel is (a) confirmed and channel_ready messages have been exchanged, (b) /// the peer is connected, and (c) the channel is not currently negotiating a shutdown. /// - /// This is a strict superset of `is_funding_locked`. + /// This is a strict superset of `is_channel_ready`. pub is_usable: bool, /// True if this channel is (or will be) publicly-announced. pub is_public: bool, @@ -1082,6 +1107,16 @@ impl ChannelDetails { pub fn get_inbound_payment_scid(&self) -> Option { self.inbound_scid_alias.or(self.short_channel_id) } + + /// Gets the current SCID which should be used to identify this channel for outbound payments. + /// This should be used in [`Route`]s to describe the first hop or in other contexts where + /// we're sending or forwarding a payment outbound over this channel. + /// + /// This is either the [`ChannelDetails::short_channel_id`], if set, or the + /// [`ChannelDetails::outbound_scid_alias`]. See those for more information. + pub fn get_outbound_payment_scid(&self) -> Option { + self.short_channel_id.or(self.outbound_scid_alias) + } } /// If a payment fails to send, it can be in one of several states. This enum is returned as the @@ -1280,7 +1315,7 @@ macro_rules! remove_channel { } macro_rules! handle_monitor_err { - ($self: ident, $err: expr, $short_to_id: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => { + ($self: ident, $err: expr, $short_to_id: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_channel_ready: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => { match $err { ChannelMonitorUpdateErr::PermanentFailure => { log_error!($self.logger, "Closing channel {} due to monitor update ChannelMonitorUpdateErr::PermanentFailure", log_bytes!($chan_id[..])); @@ -1318,13 +1353,13 @@ macro_rules! handle_monitor_err { if !$resend_raa { debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst || !$resend_commitment); } - $chan.monitor_update_failed($resend_raa, $resend_commitment, $failed_forwards, $failed_fails, $failed_finalized_fulfills); + $chan.monitor_update_failed($resend_raa, $resend_commitment, $resend_channel_ready, $failed_forwards, $failed_fails, $failed_finalized_fulfills); (Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore("Failed to update ChannelMonitor".to_owned()), *$chan_id)), false) }, } }; - ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr) => { { - let (res, drop) = handle_monitor_err!($self, $err, $channel_state.short_to_id, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key()); + ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_channel_ready: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr) => { { + let (res, drop) = handle_monitor_err!($self, $err, $channel_state.short_to_id, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $resend_channel_ready, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key()); if drop { $entry.remove_entry(); } @@ -1332,16 +1367,19 @@ macro_rules! handle_monitor_err { } }; ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, COMMITMENT_UPDATE_ONLY) => { { debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst); - handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, true, Vec::new(), Vec::new(), Vec::new(), $chan_id) + handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, true, false, Vec::new(), Vec::new(), Vec::new(), $chan_id) } }; ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, NO_UPDATE) => { - handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id) + handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id) + }; + ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_channel_ready: expr, OPTIONALLY_RESEND_FUNDING_LOCKED) => { + handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, $resend_channel_ready, Vec::new(), Vec::new(), Vec::new()) }; ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr) => { - handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, Vec::new(), Vec::new(), Vec::new()) + handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, false, Vec::new(), Vec::new(), Vec::new()) }; ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr) => { - handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, Vec::new()) + handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, false, $failed_forwards, $failed_fails, Vec::new()) }; } @@ -1366,13 +1404,13 @@ macro_rules! maybe_break_monitor_err { } } -macro_rules! send_funding_locked { - ($short_to_id: expr, $pending_msg_events: expr, $channel: expr, $funding_locked_msg: expr) => { - $pending_msg_events.push(events::MessageSendEvent::SendFundingLocked { +macro_rules! send_channel_ready { + ($short_to_id: expr, $pending_msg_events: expr, $channel: expr, $channel_ready_msg: expr) => { + $pending_msg_events.push(events::MessageSendEvent::SendChannelReady { node_id: $channel.get_counterparty_node_id(), - msg: $funding_locked_msg, + msg: $channel_ready_msg, }); - // Note that we may send a funding locked multiple times for a channel if we reconnect, so + // Note that we may send a `channel_ready` multiple times for a channel if we reconnect, so // we allow collisions, but we shouldn't ever be updating the channel ID pointed to. let outbound_alias_insert = $short_to_id.insert($channel.outbound_scid_alias(), $channel.channel_id()); assert!(outbound_alias_insert.is_none() || outbound_alias_insert.unwrap() == $channel.channel_id(), @@ -1388,7 +1426,7 @@ macro_rules! send_funding_locked { macro_rules! handle_chan_restoration_locked { ($self: ident, $channel_lock: expr, $channel_state: expr, $channel_entry: expr, $raa: expr, $commitment_update: expr, $order: expr, $chanmon_update: expr, - $pending_forwards: expr, $funding_broadcastable: expr, $funding_locked: expr, $announcement_sigs: expr) => { { + $pending_forwards: expr, $funding_broadcastable: expr, $channel_ready: expr, $announcement_sigs: expr) => { { let mut htlc_forwards = None; let chanmon_update: Option = $chanmon_update; // Force type-checking to resolve @@ -1397,29 +1435,29 @@ macro_rules! handle_chan_restoration_locked { let res = loop { let forwards: Vec<(PendingHTLCInfo, u64)> = $pending_forwards; // Force type-checking to resolve if !forwards.is_empty() { - htlc_forwards = Some(($channel_entry.get().get_short_channel_id().expect("We can't have pending forwards before funding confirmation"), + htlc_forwards = Some(($channel_entry.get().get_short_channel_id().unwrap_or($channel_entry.get().outbound_scid_alias()), $channel_entry.get().get_funding_txo().unwrap(), forwards)); } if chanmon_update.is_some() { - // On reconnect, we, by definition, only resend a funding_locked if there have been + // On reconnect, we, by definition, only resend a channel_ready if there have been // no commitment updates, so the only channel monitor update which could also be - // associated with a funding_locked would be the funding_created/funding_signed + // associated with a channel_ready would be the funding_created/funding_signed // monitor update. That monitor update failing implies that we won't send - // funding_locked until it's been updated, so we can't have a funding_locked and a + // channel_ready until it's been updated, so we can't have a channel_ready and a // monitor update here (so we don't bother to handle it correctly below). - assert!($funding_locked.is_none()); - // A channel monitor update makes no sense without either a funding_locked or a - // commitment update to process after it. Since we can't have a funding_locked, we + assert!($channel_ready.is_none()); + // A channel monitor update makes no sense without either a channel_ready or a + // commitment update to process after it. Since we can't have a channel_ready, we // only bother to handle the monitor-update + commitment_update case below. assert!($commitment_update.is_some()); } - if let Some(msg) = $funding_locked { - // Similar to the above, this implies that we're letting the funding_locked fly + if let Some(msg) = $channel_ready { + // Similar to the above, this implies that we're letting the channel_ready fly // before it should be allowed to. assert!(chanmon_update.is_none()); - send_funding_locked!($channel_state.short_to_id, $channel_state.pending_msg_events, $channel_entry.get(), msg); + send_channel_ready!($channel_state.short_to_id, $channel_state.pending_msg_events, $channel_entry.get(), msg); } if let Some(msg) = $announcement_sigs { $channel_state.pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures { @@ -1705,6 +1743,7 @@ impl ChannelMana // `have_received_message` indicates that type negotiation has completed. channel_type: if channel.have_received_message() { Some(channel.get_channel_type().clone()) } else { None }, short_channel_id: channel.get_short_channel_id(), + outbound_scid_alias: if channel.is_usable() { Some(channel.outbound_scid_alias()) } else { None }, inbound_scid_alias: channel.latest_inbound_scid_alias(), channel_value_satoshis: channel.get_value_satoshis(), unspendable_punishment_reserve: to_self_reserve_satoshis, @@ -1716,7 +1755,7 @@ impl ChannelMana confirmations_required: channel.minimum_depth(), force_close_spend_delay: channel.get_counterparty_selected_contest_delay(), is_outbound: channel.is_outbound(), - is_funding_locked: channel.is_usable(), + is_channel_ready: channel.is_usable(), is_usable: channel.is_live(), is_public: channel.should_announce(), inbound_htlc_minimum_msat: Some(channel.get_holder_htlc_minimum_msat()), @@ -1739,12 +1778,14 @@ impl ChannelMana self.list_channels_with_filter(|_| true) } - /// Gets the list of usable channels, in random order. Useful as an argument to - /// get_route to ensure non-announced channels are used. + /// Gets the list of usable channels, in random order. Useful as an argument to [`find_route`] + /// to ensure non-announced channels are used. /// /// These are guaranteed to have their [`ChannelDetails::is_usable`] value set to true, see the /// documentation for [`ChannelDetails::is_usable`] for more info on exactly what the criteria /// are. + /// + /// [`find_route`]: crate::routing::router::find_route pub fn list_usable_channels(&self) -> Vec { // Note we use is_live here instead of usable which leads to somewhat confused // internal/external nomenclature, but that's ok cause that's probably what the user @@ -1768,17 +1809,18 @@ impl ChannelMana }); } - fn close_channel_internal(&self, channel_id: &[u8; 32], target_feerate_sats_per_1000_weight: Option) -> Result<(), APIError> { + fn close_channel_internal(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - let counterparty_node_id; let mut failed_htlcs: Vec<(HTLCSource, PaymentHash)>; let result: Result<(), _> = loop { let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_state_lock; match channel_state.by_id.entry(channel_id.clone()) { hash_map::Entry::Occupied(mut chan_entry) => { - counterparty_node_id = chan_entry.get().get_counterparty_node_id(); + if *counterparty_node_id != chan_entry.get().get_counterparty_node_id(){ + return Err(APIError::APIMisuseError { err: "The passed counterparty_node_id doesn't match the channel's counterparty node_id".to_owned() }); + } let per_peer_state = self.per_peer_state.read().unwrap(); let (shutdown_msg, monitor_update, htlcs) = match per_peer_state.get(&counterparty_node_id) { Some(peer_state) => { @@ -1803,7 +1845,7 @@ impl ChannelMana } channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown { - node_id: counterparty_node_id, + node_id: *counterparty_node_id, msg: shutdown_msg }); @@ -1826,7 +1868,7 @@ impl ChannelMana self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source.0, &htlc_source.1, HTLCFailReason::Reason { failure_code: 0x4000 | 8, data: Vec::new() }); } - let _ = handle_error!(self, result, counterparty_node_id); + let _ = handle_error!(self, result, *counterparty_node_id); Ok(()) } @@ -1847,8 +1889,8 @@ impl ChannelMana /// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis /// [`Background`]: crate::chain::chaininterface::ConfirmationTarget::Background /// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal - pub fn close_channel(&self, channel_id: &[u8; 32]) -> Result<(), APIError> { - self.close_channel_internal(channel_id, None) + pub fn close_channel(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey) -> Result<(), APIError> { + self.close_channel_internal(channel_id, counterparty_node_id, None) } /// Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs @@ -1870,8 +1912,8 @@ impl ChannelMana /// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis /// [`Background`]: crate::chain::chaininterface::ConfirmationTarget::Background /// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal - pub fn close_channel_with_target_feerate(&self, channel_id: &[u8; 32], target_feerate_sats_per_1000_weight: u32) -> Result<(), APIError> { - self.close_channel_internal(channel_id, Some(target_feerate_sats_per_1000_weight)) + pub fn close_channel_with_target_feerate(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: u32) -> Result<(), APIError> { + self.close_channel_internal(channel_id, counterparty_node_id, Some(target_feerate_sats_per_1000_weight)) } #[inline] @@ -1890,22 +1932,18 @@ impl ChannelMana } } - /// `peer_node_id` should be set when we receive a message from a peer, but not set when the + /// `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: &[u8; 32], peer_node_id: Option<&PublicKey>, peer_msg: Option<&String>) -> Result { + fn force_close_channel_with_peer(&self, channel_id: &[u8; 32], peer_node_id: &PublicKey, peer_msg: Option<&String>) -> Result { let mut chan = { let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_state_lock; if let hash_map::Entry::Occupied(chan) = channel_state.by_id.entry(channel_id.clone()) { - if let Some(node_id) = peer_node_id { - if chan.get().get_counterparty_node_id() != *node_id { - return Err(APIError::ChannelUnavailable{err: "No such channel".to_owned()}); - } + if chan.get().get_counterparty_node_id() != *peer_node_id { + return Err(APIError::ChannelUnavailable{err: "No such channel".to_owned()}); } - if peer_node_id.is_some() { - if let Some(peer_msg) = peer_msg { - self.issue_channel_close_events(chan.get(),ClosureReason::CounterpartyForceClosed { peer_msg: peer_msg.to_string() }); - } + if let Some(peer_msg) = peer_msg { + self.issue_channel_close_events(chan.get(),ClosureReason::CounterpartyForceClosed { peer_msg: peer_msg.to_string() }); } else { self.issue_channel_close_events(chan.get(),ClosureReason::HolderForceClosed); } @@ -1927,10 +1965,12 @@ impl ChannelMana } /// Force closes a channel, immediately broadcasting the latest local commitment transaction to - /// the chain and rejecting new HTLCs on the given channel. Fails if channel_id is unknown to the manager. - pub fn force_close_channel(&self, channel_id: &[u8; 32]) -> Result<(), APIError> { + /// the chain and 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_channel(&self, channel_id: &[u8; 32], counterparty_node_id: &PublicKey) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - match self.force_close_channel_with_peer(channel_id, None, None) { + match self.force_close_channel_with_peer(channel_id, counterparty_node_id, None) { Ok(counterparty_node_id) => { self.channel_state.lock().unwrap().pending_msg_events.push( events::MessageSendEvent::HandleError { @@ -1950,7 +1990,7 @@ impl ChannelMana /// for each to the chain and rejecting new HTLCs on each. pub fn force_close_all_channels(&self) { for chan in self.list_channels() { - let _ = self.force_close_channel(&chan.channel_id); + let _ = self.force_close_channel(&chan.channel_id, &chan.counterparty.node_id); } } @@ -2249,7 +2289,7 @@ impl ChannelMana break None; } { - let mut res = VecWriter(Vec::with_capacity(chan_update.serialized_length() + 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"); @@ -2258,10 +2298,11 @@ impl ChannelMana msg.cltv_expiry.write(&mut res).expect("Writes cannot fail"); } else if code == 0x1000 | 20 { - // TODO: underspecified, follow https://github.com/lightningnetwork/lightning-rfc/issues/791 + // TODO: underspecified, follow https://github.com/lightning/bolts/issues/791 0u16.write(&mut res).expect("Writes cannot fail"); } - (chan_update.serialized_length() as u16).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"); } return_err!(err, code, &res.0[..]); @@ -2284,6 +2325,9 @@ impl ChannelMana action: msgs::ErrorAction::IgnoreError }); } + if chan.get_short_channel_id().is_none() { + return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}); + } log_trace!(self.logger, "Attempting to generate broadcast channel update for channel {}", log_bytes!(chan.channel_id())); self.get_channel_update_for_unicast(chan) } @@ -2295,7 +2339,7 @@ impl ChannelMana /// May be called with channel_state already locked! fn get_channel_update_for_unicast(&self, chan: &Channel) -> Result { log_trace!(self.logger, "Attempting to generate channel update for channel {}", log_bytes!(chan.channel_id())); - let short_channel_id = match chan.get_short_channel_id() { + let short_channel_id = match chan.get_short_channel_id().or(chan.latest_inbound_scid_alias()) { None => return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}), Some(id) => id, }; @@ -2685,8 +2729,9 @@ impl ChannelMana /// 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: &[u8; 32], funding_transaction: Transaction, find_funding_output: FundingOutput) -> Result<(), APIError> { + fn funding_transaction_generated_intern, &Transaction) -> Result>( + &self, temporary_channel_id: &[u8; 32], _counterparty_node_id: &PublicKey, funding_transaction: Transaction, find_funding_output: FundingOutput + ) -> Result<(), APIError> { let (chan, msg) = { let (res, chan) = match self.channel_state.lock().unwrap().by_id.remove(temporary_channel_id) { Some(mut chan) => { @@ -2727,8 +2772,8 @@ impl ChannelMana } #[cfg(test)] - pub(crate) fn funding_transaction_generated_unchecked(&self, temporary_channel_id: &[u8; 32], funding_transaction: Transaction, output_index: u16) -> Result<(), APIError> { - self.funding_transaction_generated_intern(temporary_channel_id, funding_transaction, |_, tx| { + pub(crate) fn funding_transaction_generated_unchecked(&self, temporary_channel_id: &[u8; 32], 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, |_, tx| { Ok(OutPoint { txid: tx.txid(), index: output_index }) }) } @@ -2755,7 +2800,7 @@ impl ChannelMana /// /// [`Event::FundingGenerationReady`]: crate::util::events::Event::FundingGenerationReady /// [`Event::ChannelClosed`]: crate::util::events::Event::ChannelClosed - pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_transaction: Transaction) -> Result<(), APIError> { + pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, funding_transaction: Transaction) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); for inp in funding_transaction.input.iter() { @@ -2765,7 +2810,7 @@ impl ChannelMana }); } } - self.funding_transaction_generated_intern(temporary_channel_id, funding_transaction, |chan, tx| { + self.funding_transaction_generated_intern(temporary_channel_id, counterparty_node_id, funding_transaction, |chan, tx| { let mut output_index = None; let expected_spk = chan.get_funding_redeemscript().to_v0_p2wsh(); for (idx, outp) in tx.output.iter().enumerate() { @@ -2859,7 +2904,7 @@ impl ChannelMana }); announced_chans = true; } else { - // If the channel is not public or has not yet reached funding_locked, check the + // If the channel is not public or has not yet reached channel_ready, check the // next channel. If we don't yet have any public channels, we'll skip the broadcast // below as peers may not accept it without channels on chain first. } @@ -3096,7 +3141,7 @@ impl ChannelMana prev_funding_outpoint } => { let (cltv_expiry, onion_payload, payment_data, phantom_shared_secret) = match routing { PendingHTLCRouting::Receive { payment_data, incoming_cltv_expiry, phantom_shared_secret } => { - let _legacy_hop_data = payment_data.clone(); + let _legacy_hop_data = Some(payment_data.clone()); (incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data }, Some(payment_data), phantom_shared_secret) }, PendingHTLCRouting::ReceiveKeysend { payment_preimage, incoming_cltv_expiry } => @@ -3141,8 +3186,14 @@ impl ChannelMana macro_rules! check_total_value { ($payment_data: expr, $payment_preimage: expr) => {{ let mut payment_received_generated = false; - let htlcs = channel_state.claimable_htlcs.entry(payment_hash) - .or_insert(Vec::new()); + let purpose = || { + events::PaymentPurpose::InvoicePayment { + payment_preimage: $payment_preimage, + payment_secret: $payment_data.payment_secret, + } + }; + let (_, htlcs) = channel_state.claimable_htlcs.entry(payment_hash) + .or_insert_with(|| (purpose(), Vec::new())); if htlcs.len() == 1 { if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload { log_trace!(self.logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash", log_bytes!(payment_hash.0)); @@ -3173,11 +3224,8 @@ impl ChannelMana htlcs.push(claimable_htlc); new_events.push(events::Event::PaymentReceived { payment_hash, - purpose: events::PaymentPurpose::InvoicePayment { - payment_preimage: $payment_preimage, - payment_secret: $payment_data.payment_secret, - }, - amt: total_value, + purpose: purpose(), + amount_msat: total_value, }); payment_received_generated = true; } else { @@ -3214,11 +3262,12 @@ impl ChannelMana OnionPayload::Spontaneous(preimage) => { match channel_state.claimable_htlcs.entry(payment_hash) { hash_map::Entry::Vacant(e) => { - e.insert(vec![claimable_htlc]); + let purpose = events::PaymentPurpose::SpontaneousPayment(preimage); + e.insert((purpose.clone(), vec![claimable_htlc])); new_events.push(events::Event::PaymentReceived { payment_hash, - amt: amt_to_forward, - purpose: events::PaymentPurpose::SpontaneousPayment(preimage), + amount_msat: amt_to_forward, + purpose, }); }, hash_map::Entry::Occupied(_) => { @@ -3457,7 +3506,7 @@ impl ChannelMana true }); - channel_state.claimable_htlcs.retain(|payment_hash, htlcs| { + channel_state.claimable_htlcs.retain(|payment_hash, (_, htlcs)| { if htlcs.is_empty() { // This should be unreachable debug_assert!(false); @@ -3494,14 +3543,22 @@ impl ChannelMana /// Indicates that the preimage for payment_hash is unknown or the received amount is incorrect /// after a PaymentReceived event, failing the HTLC back to its origin and freeing resources /// along the path (including in our own channel on which we received it). - /// Returns false if no payment was found to fail backwards, true if the process of failing the - /// HTLC backwards has been started. - pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) -> bool { + /// + /// Note that in some cases around unclean shutdown, it is possible the payment may have + /// already been claimed by you via [`ChannelManager::claim_funds`] prior to you seeing (a + /// second copy of) the [`events::Event::PaymentReceived`] event. Alternatively, the payment + /// may have already been failed automatically by LDK if it was nearing its expiration time. + /// + /// While LDK will never claim a payment automatically on your behalf (i.e. without you calling + /// [`ChannelManager::claim_funds`]), you should still monitor for + /// [`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) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); let mut channel_state = Some(self.channel_state.lock().unwrap()); let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(payment_hash); - if let Some(mut sources) = removed_source { + if let Some((_, mut sources)) = removed_source { for htlc in sources.drain(..) { if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); } let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec(); @@ -3511,8 +3568,7 @@ impl ChannelMana HTLCSource::PreviousHopData(htlc.prev_hop), payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 15, data: htlc_msat_height_data }); } - true - } else { false } + } } /// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code @@ -3543,12 +3599,13 @@ impl ChannelMana 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() + 4)); + let mut enc = VecWriter(Vec::with_capacity(upd.serialized_length() + 6)); if desired_err_code == 0x1000 | 20 { // TODO: underspecified, follow https://github.com/lightning/bolts/issues/791 0u16.write(&mut enc).expect("Writes cannot fail"); } - (upd.serialized_length() as u16).write(&mut enc).expect("Writes cannot fail"); + (upd.serialized_length() as u16 + 2).write(&mut enc).expect("Writes cannot fail"); + msgs::ChannelUpdate::TYPE.write(&mut enc).expect("Writes cannot fail"); upd.write(&mut enc).expect("Writes cannot fail"); (desired_err_code, enc.0) } else { @@ -3563,7 +3620,10 @@ impl ChannelMana // Fail a list of HTLCs that were just freed from the holding cell. The HTLCs need to be // failed backwards or, if they were one of our outgoing HTLCs, then their failure needs to // be surfaced to the user. - fn fail_holding_cell_htlcs(&self, mut htlcs_to_fail: Vec<(HTLCSource, PaymentHash)>, channel_id: [u8; 32]) { + fn fail_holding_cell_htlcs( + &self, mut htlcs_to_fail: Vec<(HTLCSource, PaymentHash)>, channel_id: [u8; 32], + _counterparty_node_id: &PublicKey + ) { for (htlc_src, payment_hash) in htlcs_to_fail.drain(..) { match htlc_src { HTLCSource::PreviousHopData(HTLCPreviousHopData { .. }) => { @@ -3711,7 +3771,7 @@ impl ChannelMana .. } => { // we get a fail_malformed_htlc from the first hop // TODO: We'd like to generate a NetworkUpdate for temporary - // failures here, but that would be insufficient as get_route + // failures here, but that would be insufficient as find_route // generally ignores its view of our own channels as we provide them via // ChannelDetails. // TODO: For non-temporary failures, we really should be closing the @@ -3781,26 +3841,29 @@ impl ChannelMana /// Provides a payment preimage in response to [`Event::PaymentReceived`], generating any /// [`MessageSendEvent`]s needed to claim the payment. /// + /// Note that calling this method does *not* guarantee that the payment has been claimed. You + /// *must* wait for an [`Event::PaymentClaimed`] event which upon a successful claim will be + /// provided to your [`EventHandler`] when [`process_pending_events`] is next called. + /// /// Note that if you did not set an `amount_msat` when calling [`create_inbound_payment`] or /// [`create_inbound_payment_for_hash`] you must check that the amount in the `PaymentReceived` /// event matches your expectation. If you fail to do so and call this method, you may provide /// the sender "proof-of-payment" when they did not fulfill the full expected payment. /// - /// Returns whether any HTLCs were claimed, and thus if any new [`MessageSendEvent`]s are now - /// pending for processing via [`get_and_clear_pending_msg_events`]. - /// /// [`Event::PaymentReceived`]: crate::util::events::Event::PaymentReceived + /// [`Event::PaymentClaimed`]: crate::util::events::Event::PaymentClaimed + /// [`process_pending_events`]: EventsProvider::process_pending_events /// [`create_inbound_payment`]: Self::create_inbound_payment /// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash /// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events - pub fn claim_funds(&self, payment_preimage: PaymentPreimage) -> bool { + pub fn claim_funds(&self, payment_preimage: PaymentPreimage) { let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner()); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); let mut channel_state = Some(self.channel_state.lock().unwrap()); let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash); - if let Some(mut sources) = removed_source { + if let Some((payment_purpose, mut sources)) = removed_source { assert!(!sources.is_empty()); // If we are claiming an MPP payment, we have to take special care to ensure that each @@ -3814,12 +3877,42 @@ impl ChannelMana // we got all the HTLCs and then a channel closed while we were waiting for the user to // provide the preimage, so worrying too much about the optimal handling isn't worth // it. + let mut claimable_amt_msat = 0; + let mut expected_amt_msat = None; let mut valid_mpp = true; for htlc in sources.iter() { if let None = channel_state.as_ref().unwrap().short_to_id.get(&htlc.prev_hop.short_channel_id) { valid_mpp = false; break; } + if expected_amt_msat.is_some() && expected_amt_msat != Some(htlc.total_msat) { + log_error!(self.logger, "Somehow ended up with an MPP payment with different total amounts - this should not be reachable!"); + debug_assert!(false); + valid_mpp = false; + break; + } + expected_amt_msat = Some(htlc.total_msat); + if let OnionPayload::Spontaneous(_) = &htlc.onion_payload { + // We don't currently support MPP for spontaneous payments, so just check + // that there's one payment here and move on. + if sources.len() != 1 { + log_error!(self.logger, "Somehow ended up with an MPP spontaneous payment - this should not be reachable!"); + debug_assert!(false); + valid_mpp = false; + break; + } + } + + claimable_amt_msat += htlc.value; + } + if sources.is_empty() || expected_amt_msat.is_none() { + 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() { + log_info!(self.logger, "Attempted to claim an incomplete payment, expected {} msat, had {} available to claim.", + expected_amt_msat.unwrap(), claimable_amt_msat); + return; } let mut errs = Vec::new(); @@ -3855,6 +3948,14 @@ impl ChannelMana } } + if claimed_any_htlcs { + self.pending_events.lock().unwrap().push(events::Event::PaymentClaimed { + payment_hash, + purpose: payment_purpose, + amount_msat: claimable_amt_msat, + }); + } + // Now that we've done the entire above loop in one lock, we can handle any errors // which were generated. channel_state.take(); @@ -3863,9 +3964,7 @@ impl ChannelMana let res: Result<(), _> = Err(err); let _ = handle_error!(self, res, counterparty_node_id); } - - claimed_any_htlcs - } else { false } + } } fn claim_funds_from_hop(&self, channel_state_lock: &mut MutexGuard>, prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage) -> ClaimFundsFromHop { @@ -3955,7 +4054,7 @@ impl ChannelMana } } - fn claim_funds_internal(&self, mut channel_state_lock: MutexGuard>, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option, from_onchain: bool) { + fn claim_funds_internal(&self, mut channel_state_lock: MutexGuard>, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option, from_onchain: bool, next_channel_id: [u8; 32]) { match source { HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => { mem::drop(channel_state_lock); @@ -4046,12 +4145,14 @@ impl ChannelMana } else { None }; let mut pending_events = self.pending_events.lock().unwrap(); + let prev_channel_id = Some(prev_outpoint.to_channel_id()); + let next_channel_id = Some(next_channel_id); - let source_channel_id = Some(prev_outpoint.to_channel_id()); pending_events.push(events::Event::PaymentForwarded { - source_channel_id, fee_earned_msat, claim_from_onchain_tx: from_onchain, + prev_channel_id, + next_channel_id, }); } } @@ -4080,9 +4181,9 @@ impl ChannelMana } let updates = channel.get_mut().monitor_updating_restored(&self.logger, self.get_our_node_id(), self.genesis_hash, self.best_block.read().unwrap().height()); - let channel_update = if updates.funding_locked.is_some() && channel.get().is_usable() { + let channel_update = if updates.channel_ready.is_some() && channel.get().is_usable() { // We only send a channel_update in the case where we are just now sending a - // funding_locked and the channel is in a usable state. We may re-send a + // channel_ready and the channel is in a usable state. We may re-send a // channel_update later through the announcement_signatures process for public // channels, but there's no reason not to just inform our counterparty of our fees // now. @@ -4093,7 +4194,7 @@ impl ChannelMana }) } else { None } } else { None }; - chan_restoration_res = handle_chan_restoration_locked!(self, channel_lock, channel_state, channel, updates.raa, updates.commitment_update, updates.order, None, updates.accepted_htlcs, updates.funding_broadcastable, updates.funding_locked, updates.announcement_sigs); + chan_restoration_res = handle_chan_restoration_locked!(self, channel_lock, channel_state, channel, updates.raa, updates.commitment_update, updates.order, None, updates.accepted_htlcs, updates.funding_broadcastable, updates.channel_ready, updates.announcement_sigs); if let Some(upd) = channel_update { channel_state.pending_msg_events.push(upd); } @@ -4106,18 +4207,49 @@ impl ChannelMana } } - /// Called to accept a request to open a channel after [`Event::OpenChannelRequest`] has been - /// triggered. + /// Accepts a request to open a channel after a [`Event::OpenChannelRequest`]. + /// + /// The `temporary_channel_id` parameter indicates which inbound channel should be accepted, + /// and the `counterparty_node_id` parameter is the id of the peer which has requested to open + /// the channel. + /// + /// The `user_channel_id` parameter will be provided back in + /// [`Event::ChannelClosed::user_channel_id`] to allow tracking of which events correspond + /// with which `accept_inbound_channel`/`accept_inbound_channel_from_trusted_peer_0conf` call. /// - /// The `temporary_channel_id` parameter indicates which inbound channel should be accepted. + /// Note that this method will return an error and reject the channel, if it requires support + /// for zero confirmations. Instead, `accept_inbound_channel_from_trusted_peer_0conf` must be + /// used to accept such channels. /// - /// For inbound channels, the `user_channel_id` parameter will be provided back in + /// [`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: &[u8; 32], counterparty_node_id: &PublicKey, user_channel_id: u64) -> 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 + /// it as confirmed immediately. + /// + /// The `user_channel_id` parameter will be provided back in /// [`Event::ChannelClosed::user_channel_id`] to allow tracking of which events correspond - /// with which `accept_inbound_channel` call. + /// with which `accept_inbound_channel`/`accept_inbound_channel_from_trusted_peer_0conf` call. + /// + /// Unlike [`ChannelManager::accept_inbound_channel`], this method accepts the incoming channel + /// and (if the counterparty agrees), enables forwarding of payments immediately. + /// + /// This fully trusts that the counterparty has honestly and correctly constructed the funding + /// transaction and blindly assumes that it will eventually confirm. + /// + /// If it does not confirm before we decide to close the channel, or if the funding transaction + /// does not pay to the correct script the correct amount, *you will lose funds*. /// /// [`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: &[u8; 32], user_channel_id: u64) -> Result<(), APIError> { + pub fn accept_inbound_channel_from_trusted_peer_0conf(&self, temporary_channel_id: &[u8; 32], counterparty_node_id: &PublicKey, user_channel_id: u64) -> 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: &[u8; 32], counterparty_node_id: &PublicKey, accept_0conf: bool, user_channel_id: u64) -> Result<(), APIError> { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); let mut channel_state_lock = self.channel_state.lock().unwrap(); @@ -4127,6 +4259,23 @@ impl ChannelMana if !channel.get().inbound_is_awaiting_accept() { return Err(APIError::APIMisuseError { err: "The channel isn't currently awaiting to be accepted.".to_owned() }); } + if *counterparty_node_id != channel.get().get_counterparty_node_id() { + return Err(APIError::APIMisuseError { err: "The passed counterparty_node_id doesn't match the channel's counterparty node_id".to_owned() }); + } + if accept_0conf { + channel.get_mut().set_0conf(); + } else if channel.get().get_channel_type().requires_zero_conf() { + let send_msg_err_event = events::MessageSendEvent::HandleError { + node_id: channel.get().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(), } + } + }; + channel_state.pending_msg_events.push(send_msg_err_event); + let _ = remove_channel!(self, channel_state, channel); + return Err(APIError::APIMisuseError { err: "Please use accept_inbound_channel_from_trusted_peer_0conf to accept channels with zero confirmations.".to_owned() }); + } + channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel { node_id: channel.get().get_counterparty_node_id(), msg: channel.get_mut().accept_inbound_channel(user_channel_id), @@ -4168,6 +4317,9 @@ impl ChannelMana }, hash_map::Entry::Vacant(entry) => { if !self.default_configuration.manually_accept_inbound_channels { + if channel.get_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())); + } channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel { node_id: counterparty_node_id.clone(), msg: channel.accept_inbound_channel(0), @@ -4209,6 +4361,7 @@ impl ChannelMana let mut pending_events = self.pending_events.lock().unwrap(); pending_events.push(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, @@ -4217,7 +4370,7 @@ impl ChannelMana } fn internal_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> { - let ((funding_msg, monitor), mut chan) = { + let ((funding_msg, monitor, mut channel_ready), mut chan) = { let best_block = *self.best_block.read().unwrap(); let mut channel_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_lock; @@ -4250,9 +4403,10 @@ impl ChannelMana ChannelMonitorUpdateErr::TemporaryFailure => { // There's no problem signing a counterparty's funding transaction if our monitor // hasn't persisted to disk yet - we can't lose money on a transaction that we haven't - // accepted payment from yet. We do, however, need to wait to send our funding_locked + // accepted payment from yet. We do, however, need to wait to send our channel_ready // until we have persisted our monitor. - chan.monitor_update_failed(false, false, Vec::new(), Vec::new(), Vec::new()); + chan.monitor_update_failed(false, false, channel_ready.is_some(), Vec::new(), Vec::new(), Vec::new()); + channel_ready = None; // Don't send the channel_ready now }, } } @@ -4267,6 +4421,9 @@ impl ChannelMana node_id: counterparty_node_id.clone(), msg: funding_msg, }); + if let Some(msg) = channel_ready { + send_channel_ready!(channel_state.short_to_id, channel_state.pending_msg_events, chan, msg); + } e.insert(chan); } } @@ -4283,12 +4440,12 @@ impl ChannelMana if chan.get().get_counterparty_node_id() != *counterparty_node_id { return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id)); } - let (monitor, funding_tx) = match chan.get_mut().funding_signed(&msg, best_block, &self.logger) { + let (monitor, funding_tx, channel_ready) = match chan.get_mut().funding_signed(&msg, best_block, &self.logger) { Ok(update) => update, Err(e) => try_chan_entry!(self, Err(e), channel_state, chan), }; if let Err(e) = self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor) { - let mut res = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, false, false); + let mut res = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, channel_ready.is_some(), OPTIONALLY_RESEND_FUNDING_LOCKED); if let Err(MsgHandleErrInternal { ref mut shutdown_finish, .. }) = res { // 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 @@ -4299,6 +4456,9 @@ impl ChannelMana } return res } + if let Some(msg) = channel_ready { + send_channel_ready!(channel_state.short_to_id, channel_state.pending_msg_events, chan.get(), msg); + } funding_tx }, hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id)) @@ -4309,7 +4469,7 @@ impl ChannelMana Ok(()) } - fn internal_funding_locked(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingLocked) -> Result<(), MsgHandleErrInternal> { + fn internal_channel_ready(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReady) -> Result<(), MsgHandleErrInternal> { let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_state_lock; match channel_state.by_id.entry(msg.channel_id) { @@ -4317,7 +4477,7 @@ impl ChannelMana if chan.get().get_counterparty_node_id() != *counterparty_node_id { return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id)); } - let announcement_sigs_opt = try_chan_entry!(self, chan.get_mut().funding_locked(&msg, self.get_our_node_id(), + let announcement_sigs_opt = try_chan_entry!(self, chan.get_mut().channel_ready(&msg, self.get_our_node_id(), self.genesis_hash.clone(), &self.best_block.read().unwrap(), &self.logger), channel_state, chan); if let Some(announcement_sigs) = announcement_sigs_opt { log_trace!(self.logger, "Sending announcement_signatures for channel {}", log_bytes!(chan.get().channel_id())); @@ -4504,7 +4664,7 @@ impl ChannelMana hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id)) } }; - self.claim_funds_internal(channel_lock, htlc_source, msg.payment_preimage.clone(), Some(forwarded_htlc_value), false); + self.claim_funds_internal(channel_lock, htlc_source, msg.payment_preimage.clone(), Some(forwarded_htlc_value), false, msg.channel_id); Ok(()) } @@ -4649,7 +4809,7 @@ impl ChannelMana } else { if let Err(e) = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, - raa_updates.commitment_update.is_some(), + raa_updates.commitment_update.is_some(), false, raa_updates.accepted_htlcs, raa_updates.failed_htlcs, raa_updates.finalized_claimed_htlcs) { break Err(e); @@ -4665,13 +4825,13 @@ impl ChannelMana break Ok((raa_updates.accepted_htlcs, raa_updates.failed_htlcs, raa_updates.finalized_claimed_htlcs, chan.get().get_short_channel_id() - .expect("RAA should only work on a short-id-available channel"), + .unwrap_or(chan.get().outbound_scid_alias()), chan.get().get_funding_txo().unwrap())) }, hash_map::Entry::Vacant(_) => break Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id)) } }; - self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id); + self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id, counterparty_node_id); match res { Ok((pending_forwards, mut pending_failures, finalized_claim_htlcs, short_channel_id, channel_outpoint)) => @@ -4801,7 +4961,7 @@ impl ChannelMana let need_lnd_workaround = chan.get_mut().workaround_lnd_bug_4006.take(); chan_restoration_res = handle_chan_restoration_locked!( self, channel_state_lock, channel_state, chan, responses.raa, responses.commitment_update, responses.order, - responses.mon_update, Vec::new(), None, responses.funding_locked, responses.announcement_sigs); + responses.mon_update, Vec::new(), None, responses.channel_ready, responses.announcement_sigs); if let Some(upd) = channel_update { channel_state.pending_msg_events.push(upd); } @@ -4811,10 +4971,10 @@ impl ChannelMana } }; post_handle_chan_restoration!(self, chan_restoration_res); - self.fail_holding_cell_htlcs(htlcs_failed_forward, msg.channel_id); + self.fail_holding_cell_htlcs(htlcs_failed_forward, msg.channel_id, counterparty_node_id); - if let Some(funding_locked_msg) = need_lnd_workaround { - self.internal_funding_locked(counterparty_node_id, &funding_locked_msg)?; + if let Some(channel_ready_msg) = need_lnd_workaround { + self.internal_channel_ready(counterparty_node_id, &channel_ready_msg)?; } Ok(()) } @@ -4824,48 +4984,50 @@ impl ChannelMana 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 monitor_event in pending_monitor_events.drain(..) { - match monitor_event { - MonitorEvent::HTLCEvent(htlc_update) => { - if let Some(preimage) = htlc_update.payment_preimage { - log_trace!(self.logger, "Claiming HTLC with preimage {} from our monitor", log_bytes!(preimage.0)); - self.claim_funds_internal(self.channel_state.lock().unwrap(), htlc_update.source, preimage, htlc_update.onchain_value_satoshis.map(|v| v * 1000), true); - } else { - log_trace!(self.logger, "Failing HTLC with hash {} from our monitor", log_bytes!(htlc_update.payment_hash.0)); - self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_update.source, &htlc_update.payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 8, data: Vec::new() }); - } - }, - MonitorEvent::CommitmentTxConfirmed(funding_outpoint) | - MonitorEvent::UpdateFailed(funding_outpoint) => { - let mut channel_lock = self.channel_state.lock().unwrap(); - let channel_state = &mut *channel_lock; - let by_id = &mut channel_state.by_id; - let pending_msg_events = &mut channel_state.pending_msg_events; - if let hash_map::Entry::Occupied(chan_entry) = by_id.entry(funding_outpoint.to_channel_id()) { - let mut chan = remove_channel!(self, channel_state, chan_entry); - failed_channels.push(chan.force_shutdown(false)); - if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { - pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update + for (funding_outpoint, mut monitor_events) in pending_monitor_events.drain(..) { + for monitor_event in monitor_events.drain(..) { + match monitor_event { + MonitorEvent::HTLCEvent(htlc_update) => { + if let Some(preimage) = htlc_update.payment_preimage { + log_trace!(self.logger, "Claiming HTLC with preimage {} from our monitor", log_bytes!(preimage.0)); + self.claim_funds_internal(self.channel_state.lock().unwrap(), htlc_update.source, preimage, htlc_update.htlc_value_satoshis.map(|v| v * 1000), true, funding_outpoint.to_channel_id()); + } else { + log_trace!(self.logger, "Failing HTLC with hash {} from our monitor", log_bytes!(htlc_update.payment_hash.0)); + self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_update.source, &htlc_update.payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 8, data: Vec::new() }); + } + }, + MonitorEvent::CommitmentTxConfirmed(funding_outpoint) | + MonitorEvent::UpdateFailed(funding_outpoint) => { + let mut channel_lock = self.channel_state.lock().unwrap(); + let channel_state = &mut *channel_lock; + let by_id = &mut channel_state.by_id; + let pending_msg_events = &mut channel_state.pending_msg_events; + if let hash_map::Entry::Occupied(chan_entry) = by_id.entry(funding_outpoint.to_channel_id()) { + let mut chan = remove_channel!(self, channel_state, chan_entry); + failed_channels.push(chan.force_shutdown(false)); + if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { + pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { + msg: update + }); + } + let reason = if let MonitorEvent::UpdateFailed(_) = monitor_event { + ClosureReason::ProcessingError { err: "Failed to persist ChannelMonitor update during chain sync".to_string() } + } else { + ClosureReason::CommitmentTxConfirmed + }; + self.issue_channel_close_events(&chan, reason); + pending_msg_events.push(events::MessageSendEvent::HandleError { + node_id: chan.get_counterparty_node_id(), + action: msgs::ErrorAction::SendErrorMessage { + msg: msgs::ErrorMessage { channel_id: chan.channel_id(), data: "Channel force-closed".to_owned() } + }, }); } - let reason = if let MonitorEvent::UpdateFailed(_) = monitor_event { - ClosureReason::ProcessingError { err: "Failed to persist ChannelMonitor update during chain sync".to_string() } - } else { - ClosureReason::CommitmentTxConfirmed - }; - self.issue_channel_close_events(&chan, reason); - pending_msg_events.push(events::MessageSendEvent::HandleError { - node_id: chan.get_counterparty_node_id(), - action: msgs::ErrorAction::SendErrorMessage { - msg: msgs::ErrorMessage { channel_id: chan.channel_id(), data: "Channel force-closed".to_owned() } - }, - }); - } - }, - MonitorEvent::UpdateCompleted { funding_txo, monitor_update_id } => { - self.channel_monitor_updated(&funding_txo, monitor_update_id); - }, + }, + MonitorEvent::UpdateCompleted { funding_txo, monitor_update_id } => { + self.channel_monitor_updated(&funding_txo, monitor_update_id); + }, + } } } @@ -4907,7 +5069,11 @@ impl ChannelMana match chan.maybe_free_holding_cell_htlcs(&self.logger) { Ok((commitment_opt, holding_cell_failed_htlcs)) => { if !holding_cell_failed_htlcs.is_empty() { - failed_htlcs.push((holding_cell_failed_htlcs, *channel_id)); + failed_htlcs.push(( + holding_cell_failed_htlcs, + *channel_id, + chan.get_counterparty_node_id() + )); } if let Some((commitment_update, monitor_update)) = commitment_opt { if let Err(e) = self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), monitor_update) { @@ -4935,8 +5101,8 @@ impl ChannelMana } let has_update = has_monitor_update || !failed_htlcs.is_empty() || !handle_errors.is_empty(); - for (failures, channel_id) in failed_htlcs.drain(..) { - self.fail_holding_cell_htlcs(failures, channel_id); + for (failures, channel_id, counterparty_node_id) in failed_htlcs.drain(..) { + self.fail_holding_cell_htlcs(failures, channel_id, &counterparty_node_id); } for (counterparty_node_id, err) in handle_errors.drain(..) { @@ -5449,7 +5615,7 @@ 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>> + fn do_chain_event) -> 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. @@ -5464,17 +5630,17 @@ where let pending_msg_events = &mut channel_state.pending_msg_events; channel_state.by_id.retain(|_, channel| { let res = f(channel); - if let Ok((funding_locked_opt, mut timed_out_pending_htlcs, announcement_sigs)) = res { + if let Ok((channel_ready_opt, mut timed_out_pending_htlcs, announcement_sigs)) = res { for (source, payment_hash) in timed_out_pending_htlcs.drain(..) { let (failure_code, data) = self.get_htlc_inbound_temp_fail_err_and_data(0x1000|14 /* expiry_too_soon */, &channel); timed_out_htlcs.push((source, payment_hash, HTLCFailReason::Reason { failure_code, data, })); } - if let Some(funding_locked) = funding_locked_opt { - send_funding_locked!(short_to_id, pending_msg_events, channel, funding_locked); + if let Some(channel_ready) = channel_ready_opt { + send_channel_ready!(short_to_id, pending_msg_events, channel, channel_ready); if channel.is_usable() { - log_trace!(self.logger, "Sending funding_locked with private initial channel_update for our counterparty on channel {}", log_bytes!(channel.channel_id())); + log_trace!(self.logger, "Sending channel_ready with private initial channel_update for our counterparty on channel {}", log_bytes!(channel.channel_id())); if let Ok(msg) = self.get_channel_update_for_unicast(channel) { pending_msg_events.push(events::MessageSendEvent::SendChannelUpdate { node_id: channel.get_counterparty_node_id(), @@ -5482,7 +5648,7 @@ where }); } } else { - log_trace!(self.logger, "Sending funding_locked WITHOUT channel_update for {}", log_bytes!(channel.channel_id())); + log_trace!(self.logger, "Sending channel_ready WITHOUT channel_update for {}", log_bytes!(channel.channel_id())); } } if let Some(announcement_sigs) = announcement_sigs { @@ -5502,6 +5668,19 @@ where } } } + if channel.is_our_channel_ready() { + if let Some(real_scid) = channel.get_short_channel_id() { + // If we sent a 0conf channel_ready, and now have an SCID, we add it + // to the short_to_id map here. Note that we check whether we can relay + // using the real SCID at relay-time (i.e. enforce option_scid_alias + // then), and if the funding tx is ever un-confirmed we force-close the + // channel, ensuring short_to_id is always consistent. + let scid_insert = short_to_id.insert(real_scid, channel.channel_id()); + assert!(scid_insert.is_none() || scid_insert.unwrap() == channel.channel_id(), + "SCIDs should never collide - ensure you weren't behind by a full {} blocks when creating channels", + fake_scid::MAX_SCID_BLOCKS_FROM_NOW); + } + } } else if let Err(reason) = res { update_maps_on_chan_removal!(self, short_to_id, channel); // It looks like our counterparty went on-chain or funding transaction was @@ -5527,7 +5706,7 @@ where }); if let Some(height) = height_opt { - channel_state.claimable_htlcs.retain(|payment_hash, htlcs| { + channel_state.claimable_htlcs.retain(|payment_hash, (_, htlcs)| { 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 @@ -5616,9 +5795,9 @@ impl let _ = handle_error!(self, self.internal_funding_signed(counterparty_node_id, msg), *counterparty_node_id); } - fn handle_funding_locked(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingLocked) { + fn handle_channel_ready(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReady) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - let _ = handle_error!(self, self.internal_funding_locked(counterparty_node_id, msg), *counterparty_node_id); + let _ = handle_error!(self, self.internal_channel_ready(counterparty_node_id, msg), *counterparty_node_id); } fn handle_shutdown(&self, counterparty_node_id: &PublicKey, their_features: &InitFeatures, msg: &msgs::Shutdown) { @@ -5695,46 +5874,28 @@ impl let channel_state = &mut *channel_state_lock; let pending_msg_events = &mut channel_state.pending_msg_events; let short_to_id = &mut channel_state.short_to_id; - if no_connection_possible { - log_debug!(self.logger, "Failing all channels with {} due to no_connection_possible", log_pubkey!(counterparty_node_id)); - channel_state.by_id.retain(|_, chan| { - if chan.get_counterparty_node_id() == *counterparty_node_id { + log_debug!(self.logger, "Marking channels with {} disconnected and generating channel_updates. We believe we {} make future connections to this peer.", + log_pubkey!(counterparty_node_id), if no_connection_possible { "cannot" } else { "can" }); + channel_state.by_id.retain(|_, chan| { + if chan.get_counterparty_node_id() == *counterparty_node_id { + chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger); + if chan.is_shutdown() { update_maps_on_chan_removal!(self, short_to_id, chan); - failed_channels.push(chan.force_shutdown(true)); - if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { - pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { - msg: update - }); - } self.issue_channel_close_events(chan, ClosureReason::DisconnectedPeer); - false + return false; } else { - true - } - }); - } else { - log_debug!(self.logger, "Marking channels with {} disconnected and generating channel_updates", log_pubkey!(counterparty_node_id)); - channel_state.by_id.retain(|_, chan| { - if chan.get_counterparty_node_id() == *counterparty_node_id { - chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger); - if chan.is_shutdown() { - update_maps_on_chan_removal!(self, short_to_id, chan); - self.issue_channel_close_events(chan, ClosureReason::DisconnectedPeer); - return false; - } else { - no_channels_remain = false; - } + no_channels_remain = false; } - true - }) - } + } + true + }); pending_msg_events.retain(|msg| { match msg { &events::MessageSendEvent::SendAcceptChannel { ref node_id, .. } => node_id != counterparty_node_id, &events::MessageSendEvent::SendOpenChannel { ref node_id, .. } => node_id != counterparty_node_id, &events::MessageSendEvent::SendFundingCreated { ref node_id, .. } => node_id != counterparty_node_id, &events::MessageSendEvent::SendFundingSigned { ref node_id, .. } => node_id != counterparty_node_id, - &events::MessageSendEvent::SendFundingLocked { ref node_id, .. } => node_id != counterparty_node_id, + &events::MessageSendEvent::SendChannelReady { ref node_id, .. } => node_id != counterparty_node_id, &events::MessageSendEvent::SendAnnouncementSignatures { ref node_id, .. } => node_id != counterparty_node_id, &events::MessageSendEvent::UpdateHTLCs { ref node_id, .. } => node_id != counterparty_node_id, &events::MessageSendEvent::SendRevokeAndACK { ref node_id, .. } => node_id != counterparty_node_id, @@ -5811,7 +5972,7 @@ impl for chan in self.list_channels() { if chan.counterparty.node_id == *counterparty_node_id { // Untrusted messages from peer, we throw away the error if id points to a non-existent channel - let _ = self.force_close_channel_with_peer(&chan.channel_id, Some(counterparty_node_id), Some(&msg.data)); + let _ = self.force_close_channel_with_peer(&chan.channel_id, counterparty_node_id, Some(&msg.data)); } } } else { @@ -5833,7 +5994,7 @@ impl } // 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, Some(counterparty_node_id), Some(&msg.data)); + let _ = self.force_close_channel_with_peer(&msg.channel_id, counterparty_node_id, Some(&msg.data)); } } } @@ -5932,6 +6093,7 @@ impl_writeable_tlv_based!(ChannelDetails, { (2, channel_id, required), (3, channel_type, option), (4, counterparty, required), + (5, outbound_scid_alias, option), (6, funding_txo, option), (8, short_channel_id, option), (10, channel_value_satoshis, required), @@ -5946,7 +6108,7 @@ impl_writeable_tlv_based!(ChannelDetails, { (22, confirmations_required, option), (24, force_close_spend_delay, option), (26, is_outbound, required), - (28, is_funding_locked, required), + (28, is_channel_ready, required), (30, is_usable, required), (32, is_public, required), (33, inbound_htlc_minimum_msat, option), @@ -6066,13 +6228,9 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, { impl Writeable for ClaimableHTLC { fn write(&self, writer: &mut W) -> Result<(), io::Error> { - let payment_data = match &self.onion_payload { - OnionPayload::Invoice { _legacy_hop_data } => Some(_legacy_hop_data), - _ => None, - }; - let keysend_preimage = match self.onion_payload { - OnionPayload::Invoice { .. } => None, - OnionPayload::Spontaneous(preimage) => Some(preimage.clone()), + let (payment_data, keysend_preimage) = match &self.onion_payload { + OnionPayload::Invoice { _legacy_hop_data } => (_legacy_hop_data.as_ref(), None), + OnionPayload::Spontaneous(preimage) => (None, Some(preimage)), }; write_tlv_fields!(writer, { (0, self.prev_hop, required), @@ -6113,13 +6271,13 @@ impl Readable for ClaimableHTLC { OnionPayload::Spontaneous(p) }, None => { - if payment_data.is_none() { - return Err(DecodeError::InvalidValue) - } if total_msat.is_none() { + if payment_data.is_none() { + return Err(DecodeError::InvalidValue) + } total_msat = Some(payment_data.as_ref().unwrap().total_msat); } - OnionPayload::Invoice { _legacy_hop_data: payment_data.unwrap() } + OnionPayload::Invoice { _legacy_hop_data: payment_data } }, }; Ok(Self { @@ -6292,13 +6450,15 @@ impl Writeable f } } + let mut htlc_purposes: Vec<&events::PaymentPurpose> = Vec::new(); (channel_state.claimable_htlcs.len() as u64).write(writer)?; - for (payment_hash, previous_hops) in channel_state.claimable_htlcs.iter() { + for (payment_hash, (purpose, previous_hops)) in channel_state.claimable_htlcs.iter() { payment_hash.write(writer)?; (previous_hops.len() as u64).write(writer)?; for htlc in previous_hops.iter() { htlc.write(writer)?; } + htlc_purposes.push(purpose); } let per_peer_state = self.per_peer_state.write().unwrap(); @@ -6375,6 +6535,7 @@ impl Writeable f (3, pending_outbound_payments, required), (5, self.our_network_pubkey, required), (7, self.fake_scid_rand_bytes, required), + (9, htlc_purposes, vec_type), }); Ok(()) @@ -6593,15 +6754,15 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> } let claimable_htlcs_count: u64 = Readable::read(reader)?; - let mut claimable_htlcs = HashMap::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::())); for _ in 0..previous_hops_len { - previous_hops.push(Readable::read(reader)?); + previous_hops.push(::read(reader)?); } - claimable_htlcs.insert(payment_hash, previous_hops); + claimable_htlcs_list.push((payment_hash, previous_hops)); } let peer_count: u64 = Readable::read(reader)?; @@ -6671,11 +6832,13 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> let mut pending_outbound_payments = None; let mut received_network_pubkey: Option = None; let mut fake_scid_rand_bytes: Option<[u8; 32]> = None; + let mut claimable_htlc_purposes = None; read_tlv_fields!(reader, { (1, pending_outbound_payments_no_retry, option), (3, pending_outbound_payments, option), (5, received_network_pubkey, option), (7, fake_scid_rand_bytes, option), + (9, claimable_htlc_purposes, vec_type), }); if fake_scid_rand_bytes.is_none() { fake_scid_rand_bytes = Some(args.keys_manager.get_secure_random_bytes()); @@ -6698,7 +6861,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> // payments which are still in-flight via their on-chain state. // We only rebuild the pending payments map if we were most recently serialized by // 0.0.102+ - for (_, monitor) in args.channel_monitors { + for (_, monitor) in args.channel_monitors.iter() { if by_id.get(&monitor.get_funding_txo().0.to_channel_id()).is_none() { for (htlc_source, htlc) in monitor.get_pending_outbound_htlcs() { if let HTLCSource::OutboundRoute { payment_id, session_priv, path, payment_secret, .. } = htlc_source { @@ -6736,6 +6899,49 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> } } + let inbound_pmt_key_material = args.keys_manager.get_inbound_payment_key_material(); + let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material); + + let mut claimable_htlcs = HashMap::with_capacity(claimable_htlcs_list.len()); + if let Some(mut purposes) = claimable_htlc_purposes { + if purposes.len() != claimable_htlcs_list.len() { + return Err(DecodeError::InvalidValue); + } + for (purpose, (payment_hash, previous_hops)) in purposes.drain(..).zip(claimable_htlcs_list.drain(..)) { + claimable_htlcs.insert(payment_hash, (purpose, previous_hops)); + } + } 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`. + for (payment_hash, previous_hops) in claimable_htlcs_list.drain(..) { + if previous_hops.is_empty() { + return Err(DecodeError::InvalidValue); + } + let purpose = match &previous_hops[0].onion_payload { + 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) { + Some(inbound_payment) => inbound_payment.payment_preimage, + 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", log_bytes!(payment_hash.0)); + return Err(DecodeError::InvalidValue); + } + } + }, + payment_secret: hop_data.payment_secret, + } + } else { return Err(DecodeError::InvalidValue); } + }, + OnionPayload::Spontaneous(payment_preimage) => + events::PaymentPurpose::SpontaneousPayment(*payment_preimage), + }; + claimable_htlcs.insert(payment_hash, (purpose, previous_hops)); + } + } + let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&args.keys_manager.get_secure_random_bytes()); @@ -6781,8 +6987,46 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> } } - let inbound_pmt_key_material = args.keys_manager.get_inbound_payment_key_material(); - let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material); + for (_, monitor) in args.channel_monitors.iter() { + for (payment_hash, payment_preimage) in monitor.get_stored_preimages() { + if let Some((payment_purpose, claimable_htlcs)) = claimable_htlcs.remove(&payment_hash) { + log_info!(args.logger, "Re-claiming HTLCs with payment hash {} as we've released the preimage to a ChannelMonitor!", log_bytes!(payment_hash.0)); + let mut claimable_amt_msat = 0; + for claimable_htlc in claimable_htlcs { + claimable_amt_msat += claimable_htlc.value; + + // Add a holding-cell claim of the payment to the Channel, which should be + // applied ~immediately on peer reconnection. Because it won't generate a + // new commitment transaction we can just provide the payment preimage to + // the corresponding ChannelMonitor and nothing else. + // + // We do so directly instead of via the normal ChannelMonitor update + // procedure as the ChainMonitor hasn't yet been initialized, implying + // we're not allowed to call it directly yet. Further, we do the update + // without incrementing the ChannelMonitor update ID as there isn't any + // reason to. + // If we were to generate a new ChannelMonitor update ID here and then + // crash before the user finishes block connect we'd end up force-closing + // this channel as well. On the flip side, there's no harm in restarting + // without the new monitor persisted - we'll end up right back here on + // restart. + let previous_channel_id = claimable_htlc.prev_hop.outpoint.to_channel_id(); + if let Some(channel) = by_id.get_mut(&previous_channel_id) { + channel.claim_htlc_while_disconnected_dropping_mon_update(claimable_htlc.prev_hop.htlc_id, payment_preimage, &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, &args.fee_estimator, &args.logger); + } + } + pending_events_read.push(events::Event::PaymentClaimed { + payment_hash, + purpose: payment_purpose, + amount_msat: claimable_amt_msat, + }); + } + } + } + let channel_manager = ChannelManager { genesis_hash, fee_estimator: args.fee_estimator, @@ -7036,8 +7280,10 @@ mod tests { // claim_funds_along_route because the ordering of the messages causes the second half of the // payment to be put in the holding cell, which confuses the test utilities. So we exchange the // lightning messages manually. - assert!(nodes[1].node.claim_funds(payment_preimage)); + nodes[1].node.claim_funds(payment_preimage); + expect_payment_claimed!(nodes[1], our_payment_hash, 200_000); 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_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_first_updates.commitment_signed); @@ -7119,8 +7365,8 @@ mod tests { final_cltv_expiry_delta: TEST_FINAL_CLTV, }; let route = find_route( - &nodes[0].node.get_our_node_id(), &route_params, nodes[0].network_graph, None, - nodes[0].logger, &scorer, &random_seed_bytes + &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, + None, nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); @@ -7150,8 +7396,8 @@ 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, &random_seed_bytes + &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph, + None, nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); @@ -7214,7 +7460,7 @@ mod tests { let scorer = test_utils::TestScorer::with_penalty(0); 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::>()), + &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::>()), nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); @@ -7258,7 +7504,7 @@ mod tests { let scorer = test_utils::TestScorer::with_penalty(0); 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::>()), + &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::>()), nodes[0].logger, &scorer, &random_seed_bytes ).unwrap(); @@ -7348,7 +7594,7 @@ pub mod bench { use ln::features::{InitFeatures, InvoiceFeatures}; use ln::functional_test_utils::*; use ln::msgs::{ChannelMessageHandler, Init}; - use routing::network_graph::NetworkGraph; + use routing::gossip::NetworkGraph; use routing::router::{PaymentParameters, get_route}; use util::test_utils; use util::config::UserConfig; @@ -7421,7 +7667,7 @@ pub mod bench { tx = Transaction { version: 2, lock_time: 0, input: Vec::new(), output: vec![TxOut { value: 8_000_000, script_pubkey: output_script, }]}; - node_a.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap(); + 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())); @@ -7436,12 +7682,12 @@ pub mod bench { Listen::block_connected(&node_a, &block, 1); Listen::block_connected(&node_b, &block, 1); - node_a.handle_funding_locked(&node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendFundingLocked, 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::SendFundingLocked { ref msg, .. } => { - node_b.handle_funding_locked(&node_a.get_our_node_id(), msg); + 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()); }, _ => panic!(), @@ -7451,7 +7697,7 @@ pub mod bench { _ => panic!(), } - let dummy_graph = NetworkGraph::new(genesis_hash); + let dummy_graph = NetworkGraph::new(genesis_hash, &logger_a); let mut payment_count: u64 = 0; macro_rules! send_payment { @@ -7483,7 +7729,8 @@ pub mod bench { expect_pending_htlcs_forwardable!(NodeHolder { node: &$node_b }); expect_payment_received!(NodeHolder { node: &$node_b }, payment_hash, payment_secret, 10_000); - assert!($node_b.claim_funds(payment_preimage)); + $node_b.claim_funds(payment_preimage); + expect_payment_claimed!(NodeHolder { node: &$node_b }, payment_hash, 10_000); match $node_b.get_and_clear_pending_msg_events().pop().unwrap() { MessageSendEvent::UpdateHTLCs { node_id, updates } => {