X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=8053f9c32cc2410651e5cef2c686310e4238a8d9;hb=7ed7a7d22e6b7bb047db5a7fbbd1f19036b7e06f;hp=f89aef6163c5d526f25fd52a446a87de34963a14;hpb=14e52cd7a6382fdd71ce090a81eac9da3b9318de;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index f89aef61..8053f9c3 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -93,6 +93,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 { @@ -136,6 +138,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, @@ -149,6 +153,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], @@ -963,9 +968,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`] @@ -1083,6 +1104,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 @@ -1281,7 +1312,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_funding_locked: 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[..])); @@ -1319,13 +1350,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_funding_locked, $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_funding_locked: 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_funding_locked, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key()); if drop { $entry.remove_entry(); } @@ -1333,16 +1364,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_funding_locked: expr, OPTIONALLY_RESEND_FUNDING_LOCKED) => { + handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, $resend_funding_locked, 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()) }; } @@ -1398,7 +1432,7 @@ 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)); } @@ -1706,6 +1740,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, @@ -2285,6 +2320,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) } @@ -2296,7 +2334,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, }; @@ -2686,8 +2724,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) => { @@ -2728,8 +2767,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 }) }) } @@ -2756,7 +2795,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() { @@ -2766,7 +2805,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() { @@ -3957,7 +3996,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); @@ -4048,12 +4087,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, }); } } @@ -4108,18 +4149,45 @@ 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. + /// [`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. /// - /// For inbound channels, the `user_channel_id` parameter will be provided back in + /// 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(); @@ -4129,6 +4197,10 @@ 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(); } 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), @@ -4220,7 +4292,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 funding_locked), 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; @@ -4255,7 +4327,8 @@ impl ChannelMana // 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 // until we have persisted our monitor. - chan.monitor_update_failed(false, false, Vec::new(), Vec::new(), Vec::new()); + chan.monitor_update_failed(false, false, funding_locked.is_some(), Vec::new(), Vec::new(), Vec::new()); + funding_locked = None; // Don't send the funding_locked now }, } } @@ -4270,6 +4343,9 @@ impl ChannelMana node_id: counterparty_node_id.clone(), msg: funding_msg, }); + if let Some(msg) = funding_locked { + send_funding_locked!(channel_state.short_to_id, channel_state.pending_msg_events, chan, msg); + } e.insert(chan); } } @@ -4286,12 +4362,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, funding_locked) = 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, funding_locked.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 @@ -4302,6 +4378,9 @@ impl ChannelMana } return res } + if let Some(msg) = funding_locked { + send_funding_locked!(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)) @@ -4507,7 +4586,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(()) } @@ -4652,7 +4731,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); @@ -4668,7 +4747,7 @@ 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)) @@ -4827,48 +4906,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.onchain_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); + }, + } } } @@ -5505,6 +5586,19 @@ where } } } + if channel.is_our_funding_locked() { + if let Some(real_scid) = channel.get_short_channel_id() { + // If we sent a 0conf funding_locked, 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 @@ -5698,39 +5792,21 @@ 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 + no_channels_remain = false; } - }); - } 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; - } - } - true - }) - } + } + true + }); pending_msg_events.retain(|msg| { match msg { &events::MessageSendEvent::SendAcceptChannel { ref node_id, .. } => node_id != counterparty_node_id, @@ -5935,6 +6011,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), @@ -7424,7 +7501,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()));