Merge pull request #2973 from valentinewallace/2024-03-om-mailbox
[rust-lightning] / lightning / src / ln / channelmanager.rs
index f33df2bd797e5eb07453614aa6a206cae78b86f0..6ae78ec9ced4c45a7189237b2ca91640c97ddd68 100644 (file)
@@ -42,7 +42,8 @@ use crate::events;
 use crate::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination, PaymentFailureReason};
 // Since this struct is returned in `list_channels` methods, expose it here in case users want to
 // construct one themselves.
-use crate::ln::{inbound_payment, ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
+use crate::ln::inbound_payment;
+use crate::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
 use crate::ln::channel::{self, Channel, ChannelPhase, ChannelContext, ChannelError, ChannelUpdateStatus, ShutdownResult, UnfundedChannelContext, UpdateFulfillCommitFetch, OutboundV1Channel, InboundV1Channel, WithChannelContext};
 pub use crate::ln::channel::{InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails};
 use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
@@ -1388,7 +1389,7 @@ where
 ///
 /// ```
 /// # use bitcoin::secp256k1::PublicKey;
-/// # use lightning::ln::ChannelId;
+/// # use lightning::ln::types::ChannelId;
 /// # use lightning::ln::channelmanager::AChannelManager;
 /// # use lightning::events::{Event, EventsProvider};
 /// #
@@ -1491,7 +1492,7 @@ where
 ///
 /// ```
 /// # use lightning::events::{Event, EventsProvider};
-/// # use lightning::ln::PaymentHash;
+/// # use lightning::ln::types::PaymentHash;
 /// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry};
 /// # use lightning::routing::router::RouteParameters;
 /// #
@@ -1550,11 +1551,12 @@ where
 /// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
 /// # let channel_manager = channel_manager.get_cm();
 /// let offer = channel_manager
-///     .create_offer_builder("coffee".to_string())?
+///     .create_offer_builder()?
 /// # ;
 /// # // Needed for compiling for c_bindings
 /// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into();
 /// # let offer = builder
+///     .description("coffee".to_string())
 ///     .amount_msats(10_000_000)
 ///     .build()?;
 /// let bech32_offer = offer.to_string();
@@ -1653,13 +1655,13 @@ where
 /// let payment_id = PaymentId([42; 32]);
 /// let refund = channel_manager
 ///     .create_refund_builder(
-///         "coffee".to_string(), amount_msats, absolute_expiry, payment_id, retry,
-///         max_total_routing_fee_msat
+///         amount_msats, absolute_expiry, payment_id, retry, max_total_routing_fee_msat
 ///     )?
 /// # ;
 /// # // Needed for compiling for c_bindings
 /// # let builder: lightning::offers::refund::RefundBuilder<_> = refund.into();
 /// # let refund = builder
+///     .description("coffee".to_string())
 ///     .payer_note("refund for order 1234".to_string())
 ///     .build()?;
 /// let bech32_refund = refund.to_string();
@@ -4481,7 +4483,7 @@ where
 
        /// Handles the generation of a funding transaction, optionally (for tests) with a function
        /// which checks the correctness of the funding transaction given the associated channel.
-       fn funding_transaction_generated_intern<FundingOutput: FnMut(&OutboundV1Channel<SP>, &Transaction) -> Result<OutPoint, APIError>>(
+       fn funding_transaction_generated_intern<FundingOutput: FnMut(&OutboundV1Channel<SP>, &Transaction) -> Result<OutPoint, &'static str>>(
                &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, funding_transaction: Transaction, is_batch_funding: bool,
                mut find_funding_output: FundingOutput,
        ) -> Result<(), APIError> {
@@ -4494,26 +4496,38 @@ where
                let funding_txo;
                let (mut chan, msg_opt) = match peer_state.channel_by_id.remove(temporary_channel_id) {
                        Some(ChannelPhase::UnfundedOutboundV1(mut chan)) => {
-                               funding_txo = find_funding_output(&chan, &funding_transaction)?;
+                               macro_rules! close_chan { ($err: expr, $api_err: expr, $chan: expr) => { {
+                                       let counterparty;
+                                       let err = if let ChannelError::Close(msg) = $err {
+                                               let channel_id = $chan.context.channel_id();
+                                               counterparty = chan.context.get_counterparty_node_id();
+                                               let reason = ClosureReason::ProcessingError { err: msg.clone() };
+                                               let shutdown_res = $chan.context.force_shutdown(false, reason);
+                                               MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None)
+                                       } else { unreachable!(); };
+
+                                       mem::drop(peer_state_lock);
+                                       mem::drop(per_peer_state);
+                                       let _: Result<(), _> = handle_error!(self, Err(err), counterparty);
+                                       Err($api_err)
+                               } } }
+                               match find_funding_output(&chan, &funding_transaction) {
+                                       Ok(found_funding_txo) => funding_txo = found_funding_txo,
+                                       Err(err) => {
+                                               let chan_err = ChannelError::Close(err.to_owned());
+                                               let api_err = APIError::APIMisuseError { err: err.to_owned() };
+                                               return close_chan!(chan_err, api_err, chan);
+                                       },
+                               }
 
                                let logger = WithChannelContext::from(&self.logger, &chan.context);
-                               let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger)
-                                       .map_err(|(mut chan, e)| if let ChannelError::Close(msg) = e {
-                                               let channel_id = chan.context.channel_id();
-                                               let reason = ClosureReason::ProcessingError { err: msg.clone() };
-                                               let shutdown_res = chan.context.force_shutdown(false, reason);
-                                               (chan, MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None))
-                                       } else { unreachable!(); });
+                               let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger);
                                match funding_res {
                                        Ok(funding_msg) => (chan, funding_msg),
-                                       Err((chan, err)) => {
-                                               mem::drop(peer_state_lock);
-                                               mem::drop(per_peer_state);
-                                               let _: Result<(), _> = handle_error!(self, Err(err), chan.context.get_counterparty_node_id());
-                                               return Err(APIError::ChannelUnavailable {
-                                                       err: "Signer refused to sign the initial commitment transaction".to_owned()
-                                               });
-                                       },
+                                       Err((mut chan, chan_err)) => {
+                                               let api_err = APIError::ChannelUnavailable { err: "Signer refused to sign the initial commitment transaction".to_owned() };
+                                               return close_chan!(chan_err, api_err, chan);
+                                       }
                                }
                        },
                        Some(phase) => {
@@ -4678,17 +4692,13 @@ where
                                        for (idx, outp) in tx.output.iter().enumerate() {
                                                if outp.script_pubkey == expected_spk && outp.value == chan.context.get_value_satoshis() {
                                                        if output_index.is_some() {
-                                                               return Err(APIError::APIMisuseError {
-                                                                       err: "Multiple outputs matched the expected script and value".to_owned()
-                                                               });
+                                                               return Err("Multiple outputs matched the expected script and value");
                                                        }
                                                        output_index = Some(idx as u16);
                                                }
                                        }
                                        if output_index.is_none() {
-                                               return Err(APIError::APIMisuseError {
-                                                       err: "No output matched the script_pubkey and value in the FundingGenerationReady event".to_owned()
-                                               });
+                                               return Err("No output matched the script_pubkey and value in the FundingGenerationReady event");
                                        }
                                        let outpoint = OutPoint { txid: tx.txid(), index: output_index.unwrap() };
                                        if let Some(funding_batch_state) = funding_batch_state.as_mut() {
@@ -4719,11 +4729,20 @@ where
                                for (channel_id, counterparty_node_id) in channels_to_remove {
                                        per_peer_state.get(&counterparty_node_id)
                                                .map(|peer_state_mutex| peer_state_mutex.lock().unwrap())
-                                               .and_then(|mut peer_state| peer_state.channel_by_id.remove(&channel_id))
-                                               .map(|mut chan| {
+                                               .and_then(|mut peer_state| peer_state.channel_by_id.remove(&channel_id).map(|chan| (chan, peer_state)))
+                                               .map(|(mut chan, mut peer_state)| {
                                                        update_maps_on_chan_removal!(self, &chan.context());
                                                        let closure_reason = ClosureReason::ProcessingError { err: e.clone() };
                                                        shutdown_results.push(chan.context_mut().force_shutdown(false, closure_reason));
+                                                       peer_state.pending_msg_events.push(events::MessageSendEvent::HandleError {
+                                                               node_id: counterparty_node_id,
+                                                               action: msgs::ErrorAction::SendErrorMessage {
+                                                                       msg: msgs::ErrorMessage {
+                                                                               channel_id,
+                                                                               data: "Failed to fund channel".to_owned(),
+                                                                       }
+                                                               },
+                                                       });
                                                });
                                }
                        }
@@ -7666,7 +7685,7 @@ where
                                                        }
                                                }
                                        }
-                                       try_chan_phase_entry!(self, chan.update_add_htlc(&msg, pending_forward_info), chan_phase_entry);
+                                       try_chan_phase_entry!(self, chan.update_add_htlc(&msg, pending_forward_info, &self.fee_estimator), chan_phase_entry);
                                } else {
                                        return try_chan_phase_entry!(self, Err(ChannelError::Close(
                                                "Got an update_add_htlc message for an unfunded channel!".into())), chan_phase_entry);
@@ -8546,9 +8565,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
        ///
        /// [`Offer`]: crate::offers::offer::Offer
        /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
-       pub fn create_offer_builder(
-               &$self, description: String
-       ) -> Result<$builder, Bolt12SemanticError> {
+       pub fn create_offer_builder(&$self) -> Result<$builder, Bolt12SemanticError> {
                let node_id = $self.get_our_node_id();
                let expanded_key = &$self.inbound_payment_key;
                let entropy = &*$self.entropy_source;
@@ -8556,7 +8573,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
 
                let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
                let builder = OfferBuilder::deriving_signing_pubkey(
-                       description, node_id, expanded_key, entropy, secp_ctx
+                       node_id, expanded_key, entropy, secp_ctx
                )
                        .chain_hash($self.chain_hash)
                        .path(path);
@@ -8615,8 +8632,8 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
        /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
        /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
        pub fn create_refund_builder(
-               &$self, description: String, amount_msats: u64, absolute_expiry: Duration,
-               payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
+               &$self, amount_msats: u64, absolute_expiry: Duration, payment_id: PaymentId,
+               retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
        ) -> Result<$builder, Bolt12SemanticError> {
                let node_id = $self.get_our_node_id();
                let expanded_key = &$self.inbound_payment_key;
@@ -8625,7 +8642,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
 
                let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
                let builder = RefundBuilder::deriving_payer_id(
-                       description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
+                       node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
                )?
                        .chain_hash($self.chain_hash)
                        .absolute_expiry(absolute_expiry)
@@ -12370,8 +12387,7 @@ mod tests {
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
        use core::sync::atomic::Ordering;
        use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
-       use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
-       use crate::ln::ChannelId;
+       use crate::ln::types::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
        use crate::ln::channelmanager::{create_recv_pending_htlc_info, HTLCForwardInfo, inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId};
        use crate::ln::functional_test_utils::*;
        use crate::ln::msgs::{self, ErrorAction};