Construct ShutdownResult as a struct in Channel
[rust-lightning] / lightning / src / ln / channelmanager.rs
index d1a1208c8091fed6b5ffad403f41160dcc75ba99..9620e793ec4a549f8aaebe14479330c7f14dce35 100644 (file)
@@ -30,6 +30,7 @@ use bitcoin::secp256k1::{SecretKey,PublicKey};
 use bitcoin::secp256k1::Secp256k1;
 use bitcoin::{LockTime, secp256k1, Sequence};
 
+use crate::blinded_path::BlindedPath;
 use crate::chain;
 use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
 use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
@@ -55,6 +56,9 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
 use crate::ln::outbound_payment;
 use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs};
 use crate::ln::wire::Encode;
+use crate::offers::offer::{DerivedMetadata, OfferBuilder};
+use crate::offers::parse::Bolt12SemanticError;
+use crate::offers::refund::RefundBuilder;
 use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, WriteableEcdsaChannelSigner};
 use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
 use crate::util::wakers::{Future, Notifier};
@@ -448,7 +452,7 @@ impl MsgHandleErrInternal {
        #[inline]
        fn from_finish_shutdown(err: String, channel_id: ChannelId, user_channel_id: u128, shutdown_res: ShutdownResult, channel_update: Option<msgs::ChannelUpdate>, channel_capacity: u64) -> Self {
                let err_msg = msgs::ErrorMessage { channel_id, data: err.clone() };
-               let action = if let (Some(_), ..) = &shutdown_res {
+               let action = if shutdown_res.monitor_update.is_some() {
                        // We have a closing `ChannelMonitorUpdate`, which means the channel was funded and we
                        // should disconnect our peer such that we force them to broadcast their latest
                        // commitment upon reconnecting.
@@ -2560,7 +2564,7 @@ where
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
 
                let mut failed_htlcs: Vec<(HTLCSource, PaymentHash)>;
-               let mut shutdown_result = None;
+               let shutdown_result;
                loop {
                        let per_peer_state = self.per_peer_state.read().unwrap();
 
@@ -2575,10 +2579,11 @@ where
                                        if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
                                                let funding_txo_opt = chan.context.get_funding_txo();
                                                let their_features = &peer_state.latest_features;
-                                               let unbroadcasted_batch_funding_txid = chan.context.unbroadcasted_batch_funding_txid();
-                                               let (shutdown_msg, mut monitor_update_opt, htlcs) =
+                                               let (shutdown_msg, mut monitor_update_opt, htlcs, local_shutdown_result) =
                                                        chan.get_shutdown(&self.signer_provider, their_features, target_feerate_sats_per_1000_weight, override_shutdown_script)?;
                                                failed_htlcs = htlcs;
+                                               shutdown_result = local_shutdown_result;
+                                               debug_assert_eq!(shutdown_result.is_some(), chan.is_shutdown());
 
                                                // We can send the `shutdown` message before updating the `ChannelMonitor`
                                                // here as we don't need the monitor update to complete until we send a
@@ -2606,7 +2611,6 @@ where
                                                                        });
                                                                }
                                                                self.issue_channel_close_events(&chan.context, ClosureReason::HolderForceClosed);
-                                                               shutdown_result = Some((None, Vec::new(), unbroadcasted_batch_funding_txid));
                                                        }
                                                }
                                                break;
@@ -2698,22 +2702,21 @@ where
                self.close_channel_internal(channel_id, counterparty_node_id, target_feerate_sats_per_1000_weight, shutdown_script)
        }
 
-       fn finish_close_channel(&self, shutdown_res: ShutdownResult) {
+       fn finish_close_channel(&self, mut shutdown_res: ShutdownResult) {
                debug_assert_ne!(self.per_peer_state.held_by_thread(), LockHeldState::HeldByThread);
                #[cfg(debug_assertions)]
                for (_, peer) in self.per_peer_state.read().unwrap().iter() {
                        debug_assert_ne!(peer.held_by_thread(), LockHeldState::HeldByThread);
                }
 
-               let (monitor_update_option, mut failed_htlcs, unbroadcasted_batch_funding_txid) = shutdown_res;
-               log_debug!(self.logger, "Finishing force-closure of channel with {} HTLCs to fail", failed_htlcs.len());
-               for htlc_source in failed_htlcs.drain(..) {
+               log_debug!(self.logger, "Finishing closure of channel with {} HTLCs to fail", shutdown_res.dropped_outbound_htlcs.len());
+               for htlc_source in shutdown_res.dropped_outbound_htlcs.drain(..) {
                        let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source;
                        let reason = HTLCFailReason::from_failure_code(0x4000 | 8);
                        let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
                        self.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver);
                }
-               if let Some((_, funding_txo, monitor_update)) = monitor_update_option {
+               if let Some((_, funding_txo, monitor_update)) = shutdown_res.monitor_update {
                        // There isn't anything we can do if we get an update failure - we're already
                        // force-closing. The monitor update on the required in-memory copy should broadcast
                        // the latest local state, which is the best we can do anyway. Thus, it is safe to
@@ -2721,7 +2724,7 @@ where
                        let _ = self.chain_monitor.update_channel(funding_txo, &monitor_update);
                }
                let mut shutdown_results = Vec::new();
-               if let Some(txid) = unbroadcasted_batch_funding_txid {
+               if let Some(txid) = shutdown_res.unbroadcasted_batch_funding_txid {
                        let mut funding_batch_states = self.funding_batch_states.lock().unwrap();
                        let affected_channels = funding_batch_states.remove(&txid).into_iter().flatten();
                        let per_peer_state = self.per_peer_state.read().unwrap();
@@ -3845,7 +3848,7 @@ where
        /// Return values are identical to [`Self::funding_transaction_generated`], respective to
        /// each individual channel and transaction output.
        ///
-       /// Do NOT broadcast the funding transaction yourself. This batch funding transcaction
+       /// Do NOT broadcast the funding transaction yourself. This batch funding transaction
        /// will only be broadcast when we have safely received and persisted the counterparty's
        /// signature for each channel.
        ///
@@ -3899,7 +3902,7 @@ where
                                btree_map::Entry::Vacant(vacant) => Some(vacant.insert(Vec::new())),
                        }
                });
-               for &(temporary_channel_id, counterparty_node_id) in temporary_channels.iter() {
+               for &(temporary_channel_id, counterparty_node_id) in temporary_channels {
                        result = result.and_then(|_| self.funding_transaction_generated_intern(
                                temporary_channel_id,
                                counterparty_node_id,
@@ -4791,6 +4794,10 @@ where
        ///    with the current [`ChannelConfig`].
        ///  * Removing peers which have disconnected but and no longer have any channels.
        ///  * Force-closing and removing channels which have not completed establishment in a timely manner.
+       ///  * Forgetting about stale outbound payments, either those that have already been fulfilled
+       ///    or those awaiting an invoice that hasn't been delivered in the necessary amount of time.
+       ///    The latter is determined using the system clock in `std` and the block time minus two
+       ///    hours in `no-std`.
        ///
        /// Note that this may cause reentrancy through [`chain::Watch::update_channel`] calls or feerate
        /// estimate fetches.
@@ -5019,7 +5026,18 @@ where
                                self.finish_close_channel(shutdown_res);
                        }
 
-                       self.pending_outbound_payments.remove_stale_payments(&self.pending_events);
+                       #[cfg(feature = "std")]
+                       let duration_since_epoch = std::time::SystemTime::now()
+                               .duration_since(std::time::SystemTime::UNIX_EPOCH)
+                               .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
+                       #[cfg(not(feature = "std"))]
+                       let duration_since_epoch = Duration::from_secs(
+                               self.highest_seen_timestamp.load(Ordering::Acquire).saturating_sub(7200) as u64
+                       );
+
+                       self.pending_outbound_payments.remove_stale_payments(
+                               duration_since_epoch, &self.pending_events
+                       );
 
                        // Technically we don't need to do this here, but if we have holding cell entries in a
                        // channel that need freeing, it's better to do that here and block a background task
@@ -6249,22 +6267,20 @@ where
        }
 
        fn internal_closing_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::ClosingSigned) -> Result<(), MsgHandleErrInternal> {
-               let mut shutdown_result = None;
-               let unbroadcasted_batch_funding_txid;
                let per_peer_state = self.per_peer_state.read().unwrap();
                let peer_state_mutex = per_peer_state.get(counterparty_node_id)
                        .ok_or_else(|| {
                                debug_assert!(false);
                                MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
                        })?;
-               let (tx, chan_option) = {
+               let (tx, chan_option, shutdown_result) = {
                        let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        match peer_state.channel_by_id.entry(msg.channel_id.clone()) {
                                hash_map::Entry::Occupied(mut chan_phase_entry) => {
                                        if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
-                                               unbroadcasted_batch_funding_txid = chan.context.unbroadcasted_batch_funding_txid();
-                                               let (closing_signed, tx) = try_chan_phase_entry!(self, chan.closing_signed(&self.fee_estimator, &msg), chan_phase_entry);
+                                               let (closing_signed, tx, shutdown_result) = try_chan_phase_entry!(self, chan.closing_signed(&self.fee_estimator, &msg), chan_phase_entry);
+                                               debug_assert_eq!(shutdown_result.is_some(), chan.is_shutdown());
                                                if let Some(msg) = closing_signed {
                                                        peer_state.pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
                                                                node_id: counterparty_node_id.clone(),
@@ -6277,8 +6293,8 @@ where
                                                        // also implies there are no pending HTLCs left on the channel, so we can
                                                        // fully delete it from tracking (the channel monitor is still around to
                                                        // watch for old state broadcasts)!
-                                                       (tx, Some(remove_channel_phase!(self, chan_phase_entry)))
-                                               } else { (tx, None) }
+                                                       (tx, Some(remove_channel_phase!(self, chan_phase_entry)), shutdown_result)
+                                               } else { (tx, None, shutdown_result) }
                                        } else {
                                                return try_chan_phase_entry!(self, Err(ChannelError::Close(
                                                        "Got a closing_signed message for an unfunded channel!".into())), chan_phase_entry);
@@ -6300,7 +6316,6 @@ where
                                });
                        }
                        self.issue_channel_close_events(&chan.context, ClosureReason::CooperativeClosure);
-                       shutdown_result = Some((None, Vec::new(), unbroadcasted_batch_funding_txid));
                }
                mem::drop(per_peer_state);
                if let Some(shutdown_result) = shutdown_result {
@@ -7030,15 +7045,18 @@ where
                                peer_state.channel_by_id.retain(|channel_id, phase| {
                                        match phase {
                                                ChannelPhase::Funded(chan) => {
-                                                       let unbroadcasted_batch_funding_txid = chan.context.unbroadcasted_batch_funding_txid();
                                                        match chan.maybe_propose_closing_signed(&self.fee_estimator, &self.logger) {
-                                                               Ok((msg_opt, tx_opt)) => {
+                                                               Ok((msg_opt, tx_opt, shutdown_result_opt)) => {
                                                                        if let Some(msg) = msg_opt {
                                                                                has_update = true;
                                                                                pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
                                                                                        node_id: chan.context.get_counterparty_node_id(), msg,
                                                                                });
                                                                        }
+                                                                       debug_assert_eq!(shutdown_result_opt.is_some(), chan.is_shutdown());
+                                                                       if let Some(shutdown_result) = shutdown_result_opt {
+                                                                               shutdown_results.push(shutdown_result);
+                                                                       }
                                                                        if let Some(tx) = tx_opt {
                                                                                // We're done with this channel. We got a closing_signed and sent back
                                                                                // a closing_signed with a closing transaction to broadcast.
@@ -7053,7 +7071,6 @@ where
                                                                                log_info!(self.logger, "Broadcasting {}", log_tx!(tx));
                                                                                self.tx_broadcaster.broadcast_transactions(&[&tx]);
                                                                                update_maps_on_chan_removal!(self, &chan.context);
-                                                                               shutdown_results.push((None, Vec::new(), unbroadcasted_batch_funding_txid));
                                                                                false
                                                                        } else { true }
                                                                },
@@ -7094,7 +7111,7 @@ where
                        // Channel::force_shutdown tries to make us do) as we may still be in initialization,
                        // so we track the update internally and handle it when the user next calls
                        // timer_tick_occurred, guaranteeing we're running normally.
-                       if let Some((counterparty_node_id, funding_txo, update)) = failure.0.take() {
+                       if let Some((counterparty_node_id, funding_txo, update)) = failure.monitor_update.take() {
                                assert_eq!(update.updates.len(), 1);
                                if let ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } = update.updates[0] {
                                        assert!(should_broadcast);
@@ -7108,6 +7125,71 @@ where
                }
        }
 
+       /// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
+       /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer will
+       /// not have an expiration unless otherwise set on the builder.
+       ///
+       /// Uses a one-hop [`BlindedPath`] for the offer with [`ChannelManager::get_our_node_id`] as the
+       /// introduction node and a derived signing pubkey for recipient privacy. As such, currently,
+       /// the node must be announced. Otherwise, there is no way to find a path to the introduction
+       /// node in order to send the [`InvoiceRequest`].
+       ///
+       /// [`Offer`]: crate::offers::offer::Offer
+       /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
+       pub fn create_offer_builder(
+               &self, description: String
+       ) -> OfferBuilder<DerivedMetadata, secp256k1::All> {
+               let node_id = self.get_our_node_id();
+               let expanded_key = &self.inbound_payment_key;
+               let entropy = &*self.entropy_source;
+               let secp_ctx = &self.secp_ctx;
+               let path = self.create_one_hop_blinded_path();
+
+               OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, entropy, secp_ctx)
+                       .chain_hash(self.chain_hash)
+                       .path(path)
+       }
+
+       /// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
+       /// [`ChannelManager`] when handling [`Bolt12Invoice`] messages for the refund. The builder will
+       /// have the provided expiration set. Any changes to the expiration on the returned builder will
+       /// not be honored by [`ChannelManager`].
+       ///
+       /// The provided `payment_id` is used to ensure that only one invoice is paid for the refund.
+       ///
+       /// Uses a one-hop [`BlindedPath`] for the refund with [`ChannelManager::get_our_node_id`] as
+       /// the introduction node and a derived payer id for sender privacy. As such, currently, the
+       /// node must be announced. Otherwise, there is no way to find a path to the introduction node
+       /// in order to send the [`Bolt12Invoice`].
+       ///
+       /// [`Refund`]: crate::offers::refund::Refund
+       /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
+       pub fn create_refund_builder(
+               &self, description: String, amount_msats: u64, absolute_expiry: Duration,
+               payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
+       ) -> Result<RefundBuilder<secp256k1::All>, Bolt12SemanticError> {
+               let node_id = self.get_our_node_id();
+               let expanded_key = &self.inbound_payment_key;
+               let entropy = &*self.entropy_source;
+               let secp_ctx = &self.secp_ctx;
+               let path = self.create_one_hop_blinded_path();
+
+               let builder = RefundBuilder::deriving_payer_id(
+                       description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
+               )?
+                       .chain_hash(self.chain_hash)
+                       .absolute_expiry(absolute_expiry)
+                       .path(path);
+
+               self.pending_outbound_payments
+                       .add_new_awaiting_invoice(
+                               payment_id, absolute_expiry, retry_strategy, max_total_routing_fee_msat,
+                       )
+                       .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
+
+               Ok(builder)
+       }
+
        /// Gets a payment secret and payment hash for use in an invoice given to a third party wishing
        /// to pay us.
        ///
@@ -7208,6 +7290,14 @@ where
                inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
        }
 
+       /// Creates a one-hop blinded path with [`ChannelManager::get_our_node_id`] as the introduction
+       /// node.
+       fn create_one_hop_blinded_path(&self) -> BlindedPath {
+               let entropy_source = self.entropy_source.deref();
+               let secp_ctx = &self.secp_ctx;
+               BlindedPath::one_hop_for_message(self.get_our_node_id(), entropy_source, secp_ctx).unwrap()
+       }
+
        /// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
        /// are used when constructing the phantom invoice's route hints.
        ///
@@ -9313,16 +9403,16 @@ where
                                                log_error!(args.logger, " The ChannelMonitor for channel {} is at counterparty commitment transaction number {} but the ChannelManager is at counterparty commitment transaction number {}.",
                                                        &channel.context.channel_id(), monitor.get_cur_counterparty_commitment_number(), channel.get_cur_counterparty_commitment_transaction_number());
                                        }
-                                       let (monitor_update, mut new_failed_htlcs, batch_funding_txid) = channel.context.force_shutdown(true);
-                                       if batch_funding_txid.is_some() {
+                                       let mut shutdown_result = channel.context.force_shutdown(true);
+                                       if shutdown_result.unbroadcasted_batch_funding_txid.is_some() {
                                                return Err(DecodeError::InvalidValue);
                                        }
-                                       if let Some((counterparty_node_id, funding_txo, update)) = monitor_update {
+                                       if let Some((counterparty_node_id, funding_txo, update)) = shutdown_result.monitor_update {
                                                close_background_events.push(BackgroundEvent::MonitorUpdateRegeneratedOnStartup {
                                                        counterparty_node_id, funding_txo, update
                                                });
                                        }
-                                       failed_htlcs.append(&mut new_failed_htlcs);
+                                       failed_htlcs.append(&mut shutdown_result.dropped_outbound_htlcs);
                                        channel_closures.push_back((events::Event::ChannelClosed {
                                                channel_id: channel.context.channel_id(),
                                                user_channel_id: channel.context.get_user_id(),