X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=51555c7a0ac6e199fe25f6ec17315edd48f2cb9b;hb=2b14cc40a6acf226aafaddd0efe67264c0df706f;hp=553ff853e7ef26b2f8494807b0e0fb14505d5cac;hpb=12c3a24bebe67ba406609fdfe6747da9c1449756;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 553ff853e..51555c7a0 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -32,7 +32,7 @@ use bitcoin::secp256k1::Secp256k1; use bitcoin::{secp256k1, Sequence}; use crate::blinded_path::{BlindedPath, NodeIdLookUp}; -use crate::blinded_path::payment::{PaymentConstraints, ReceiveTlvs}; +use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs}; use crate::chain; use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock}; use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator}; @@ -155,6 +155,11 @@ pub enum PendingHTLCRouting { /// [`Event::PaymentClaimable::onion_fields`] as /// [`RecipientOnionFields::payment_metadata`]. payment_metadata: Option>, + /// The context of the payment included by the recipient in a blinded path, or `None` if a + /// blinded path was not used. + /// + /// Used in part to determine the [`events::PaymentPurpose`]. + payment_context: Option, /// CLTV expiry of the received HTLC. /// /// Used to track when we should expire pending HTLCs that go unclaimed. @@ -917,9 +922,9 @@ impl PeerState where SP::Target: SignerProvider { match phase { ChannelPhase::Funded(_) | ChannelPhase::UnfundedOutboundV1(_) => true, ChannelPhase::UnfundedInboundV1(_) => false, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(_) => true, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedInboundV2(_) => false, } ) @@ -1454,12 +1459,12 @@ where /// // On the event processing thread /// channel_manager.process_pending_events(&|event| match event { /// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose { -/// PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { +/// PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { /// assert_eq!(payment_hash, known_payment_hash); /// println!("Claiming payment {}", payment_hash); /// channel_manager.claim_funds(payment_preimage); /// }, -/// PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => { +/// PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => { /// println!("Unknown payment hash: {}", payment_hash); /// }, /// PaymentPurpose::SpontaneousPayment(payment_preimage) => { @@ -1467,6 +1472,8 @@ where /// println!("Claiming spontaneous payment {}", payment_hash); /// channel_manager.claim_funds(payment_preimage); /// }, +/// // ... +/// # _ => {}, /// }, /// Event::PaymentClaimed { payment_hash, amount_msat, .. } => { /// assert_eq!(payment_hash, known_payment_hash); @@ -1554,11 +1561,11 @@ where /// // On the event processing thread /// channel_manager.process_pending_events(&|event| match event { /// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose { -/// PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { +/// PaymentPurpose::Bolt12OfferPayment { payment_preimage: Some(payment_preimage), .. } => { /// println!("Claiming payment {}", payment_hash); /// channel_manager.claim_funds(payment_preimage); /// }, -/// PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => { +/// PaymentPurpose::Bolt12OfferPayment { payment_preimage: None, .. } => { /// println!("Unknown payment hash: {}", payment_hash); /// }, /// // ... @@ -1706,12 +1713,12 @@ where /// // On the event processing thread /// channel_manager.process_pending_events(&|event| match event { /// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose { -/// PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { +/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(payment_preimage), .. } => { /// assert_eq!(payment_hash, known_payment_hash); /// println!("Claiming payment {}", payment_hash); /// channel_manager.claim_funds(payment_preimage); /// }, -/// PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => { +/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: None, .. } => { /// println!("Unknown payment hash: {}", payment_hash); /// }, /// // ... @@ -2779,11 +2786,11 @@ macro_rules! convert_chan_phase_err { ChannelPhase::UnfundedInboundV1(channel) => { convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL) }, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(channel) => { convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL) }, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedInboundV2(channel) => { convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL) }, @@ -3658,8 +3665,8 @@ where // Unfunded channel has no update (None, chan_phase.context().get_counterparty_node_id()) }, - // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. - #[cfg(dual_funding)] + // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed. + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => { self.finish_close_channel(chan_phase.context_mut().force_shutdown(false, closure_reason)); // Unfunded channel has no update @@ -5334,16 +5341,17 @@ where } }) => { let blinded_failure = routing.blinded_failure(); - let (cltv_expiry, onion_payload, payment_data, phantom_shared_secret, mut onion_fields) = match routing { + let (cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret, mut onion_fields) = match routing { PendingHTLCRouting::Receive { - payment_data, payment_metadata, incoming_cltv_expiry, phantom_shared_secret, - custom_tlvs, requires_blinded_error: _ + payment_data, payment_metadata, payment_context, + incoming_cltv_expiry, phantom_shared_secret, custom_tlvs, + requires_blinded_error: _ } => { let _legacy_hop_data = Some(payment_data.clone()); let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret), payment_metadata, custom_tlvs }; (incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data }, - Some(payment_data), phantom_shared_secret, onion_fields) + Some(payment_data), payment_context, phantom_shared_secret, onion_fields) }, PendingHTLCRouting::ReceiveKeysend { payment_data, payment_preimage, payment_metadata, @@ -5355,7 +5363,7 @@ where custom_tlvs, }; (incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage), - payment_data, None, onion_fields) + payment_data, None, None, onion_fields) }, _ => { panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive"); @@ -5420,10 +5428,7 @@ where macro_rules! check_total_value { ($purpose: expr) => {{ let mut payment_claimable_generated = false; - let is_keysend = match $purpose { - events::PaymentPurpose::SpontaneousPayment(_) => true, - events::PaymentPurpose::InvoicePayment { .. } => false, - }; + let is_keysend = $purpose.is_keysend(); let mut claimable_payments = self.claimable_payments.lock().unwrap(); if claimable_payments.pending_claiming_payments.contains_key(&payment_hash) { fail_htlc!(claimable_htlc, payment_hash); @@ -5537,10 +5542,11 @@ where fail_htlc!(claimable_htlc, payment_hash); } } - let purpose = events::PaymentPurpose::InvoicePayment { - payment_preimage: payment_preimage.clone(), - payment_secret: payment_data.payment_secret, - }; + let purpose = events::PaymentPurpose::from_parts( + payment_preimage, + payment_data.payment_secret, + payment_context, + ); check_total_value!(purpose); }, OnionPayload::Spontaneous(preimage) => { @@ -5563,10 +5569,11 @@ where &payment_hash, payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap()); fail_htlc!(claimable_htlc, payment_hash); } else { - let purpose = events::PaymentPurpose::InvoicePayment { - payment_preimage: inbound_payment.get().payment_preimage, - payment_secret: payment_data.payment_secret, - }; + let purpose = events::PaymentPurpose::from_parts( + inbound_payment.get().payment_preimage, + payment_data.payment_secret, + payment_context, + ); let payment_claimable_generated = check_total_value!(purpose); if payment_claimable_generated { inbound_payment.remove_entry(); @@ -5887,12 +5894,12 @@ where process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, pending_msg_events, counterparty_node_id) }, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedInboundV2(chan) => { process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, pending_msg_events, counterparty_node_id) }, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(chan) => { process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, pending_msg_events, counterparty_node_id) @@ -7064,8 +7071,8 @@ where num_unfunded_channels += 1; } }, - // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. - #[cfg(dual_funding)] + // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed. + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedInboundV2(chan) => { // Only inbound V2 channels that are not 0conf and that we do not contribute to will be // included in the unfunded count. @@ -7078,8 +7085,8 @@ where // Outbound channels don't contribute to the unfunded count in the DoS context. continue; }, - // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. - #[cfg(dual_funding)] + // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed. + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(_) => { // Outbound channels don't contribute to the unfunded count in the DoS context. continue; @@ -7506,7 +7513,7 @@ where finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel)); }, // TODO(dual_funding): Combine this match arm with above. - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedInboundV2(_) | ChannelPhase::UnfundedOutboundV2(_) => { let context = phase.context_mut(); log_error!(self.logger, "Immediately closing unfunded channel {} as peer asked to cooperatively shut it down (which is unnecessary)", &msg.channel_id); @@ -8750,14 +8757,7 @@ where .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?; let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap(); - if offer.paths().is_empty() { - let message = new_pending_onion_message( - OffersMessage::InvoiceRequest(invoice_request), - Destination::Node(offer.signing_pubkey()), - Some(reply_path), - ); - pending_offers_messages.push(message); - } else { + if !offer.paths().is_empty() { // Send as many invoice requests as there are paths in the offer (with an upper bound). // Using only one path could result in a failure if the path no longer exists. But only // one invoice for a given payment id will be paid, even if more than one is received. @@ -8770,6 +8770,16 @@ where ); pending_offers_messages.push(message); } + } else if let Some(signing_pubkey) = offer.signing_pubkey() { + let message = new_pending_onion_message( + OffersMessage::InvoiceRequest(invoice_request), + Destination::Node(signing_pubkey), + Some(reply_path), + ); + pending_offers_messages.push(message); + } else { + debug_assert!(false); + return Err(Bolt12SemanticError::MissingSigningPubkey); } Ok(()) @@ -8815,7 +8825,10 @@ where match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) { Ok((payment_hash, payment_secret)) => { - let payment_paths = self.create_blinded_payment_paths(amount_msats, payment_secret) + let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {}); + let payment_paths = self.create_blinded_payment_paths( + amount_msats, payment_secret, payment_context + ) .map_err(|_| Bolt12SemanticError::MissingPaths)?; #[cfg(feature = "std")] @@ -8866,10 +8879,9 @@ where /// This differs from [`create_inbound_payment_for_hash`] only in that it generates the /// [`PaymentHash`] and [`PaymentPreimage`] for you. /// - /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentClaimable`], which - /// will have the [`PaymentClaimable::purpose`] be [`PaymentPurpose::InvoicePayment`] with - /// its [`PaymentPurpose::InvoicePayment::payment_preimage`] field filled in. That should then be - /// passed directly to [`claim_funds`]. + /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentClaimable`] event, which + /// will have the [`PaymentClaimable::purpose`] return `Some` for [`PaymentPurpose::preimage`]. That + /// should then be passed directly to [`claim_funds`]. /// /// See [`create_inbound_payment_for_hash`] for detailed documentation on behavior and requirements. /// @@ -8889,8 +8901,7 @@ where /// [`claim_funds`]: Self::claim_funds /// [`PaymentClaimable`]: events::Event::PaymentClaimable /// [`PaymentClaimable::purpose`]: events::Event::PaymentClaimable::purpose - /// [`PaymentPurpose::InvoicePayment`]: events::PaymentPurpose::InvoicePayment - /// [`PaymentPurpose::InvoicePayment::payment_preimage`]: events::PaymentPurpose::InvoicePayment::payment_preimage + /// [`PaymentPurpose::preimage`]: events::PaymentPurpose::preimage /// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash pub fn create_inbound_payment(&self, min_value_msat: Option, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option) -> Result<(PaymentHash, PaymentSecret), ()> { @@ -8981,7 +8992,7 @@ where /// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to /// [`Router::create_blinded_payment_paths`]. fn create_blinded_payment_paths( - &self, amount_msats: u64, payment_secret: PaymentSecret + &self, amount_msats: u64, payment_secret: PaymentSecret, payment_context: PaymentContext ) -> Result, ()> { let secp_ctx = &self.secp_ctx; @@ -8995,6 +9006,7 @@ where max_cltv_expiry, htlc_minimum_msat: 1, }, + payment_context, }; self.router.create_blinded_payment_paths( payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx @@ -9457,7 +9469,7 @@ where // Retain unfunded channels. ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => true, // TODO(dual_funding): Combine this match arm with above. - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => true, ChannelPhase::Funded(channel) => { let res = f(channel); @@ -9763,18 +9775,21 @@ where msg.channel_id.clone())), *counterparty_node_id); } + #[cfg(splicing)] fn handle_splice(&self, counterparty_node_id: &PublicKey, msg: &msgs::Splice) { let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( "Splicing not supported".to_owned(), msg.channel_id.clone())), *counterparty_node_id); } + #[cfg(splicing)] fn handle_splice_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceAck) { let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( "Splicing not supported (splice_ack)".to_owned(), msg.channel_id.clone())), *counterparty_node_id); } + #[cfg(splicing)] fn handle_splice_locked(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceLocked) { let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( "Splicing not supported (splice_locked)".to_owned(), @@ -9932,11 +9947,11 @@ where ChannelPhase::UnfundedInboundV1(chan) => { &mut chan.context }, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(chan) => { &mut chan.context }, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedInboundV2(chan) => { &mut chan.context }, @@ -10097,8 +10112,8 @@ where }); } - // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. - #[cfg(dual_funding)] + // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed. + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedOutboundV2(chan) => { pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 { node_id: chan.context.get_counterparty_node_id(), @@ -10113,8 +10128,8 @@ where debug_assert!(false); } - // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. - #[cfg(dual_funding)] + // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed. + #[cfg(any(dual_funding, splicing))] ChannelPhase::UnfundedInboundV2(channel) => { // Since unfunded inbound channel maps are cleared upon disconnecting a peer, // they are not persisted and won't be recovered after a crash. @@ -10217,7 +10232,7 @@ where return; } }, - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] Some(ChannelPhase::UnfundedOutboundV2(ref mut chan)) => { if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) { peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 { @@ -10228,7 +10243,7 @@ where } }, None | Some(ChannelPhase::UnfundedInboundV1(_) | ChannelPhase::Funded(_)) => (), - #[cfg(dual_funding)] + #[cfg(any(dual_funding, splicing))] Some(ChannelPhase::UnfundedInboundV2(_)) => (), } } @@ -10348,8 +10363,12 @@ where }, }; + let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext { + offer_id: invoice_request.offer_id, + invoice_request: invoice_request.fields(), + }); let payment_paths = match self.create_blinded_payment_paths( - amount_msats, payment_secret + amount_msats, payment_secret, payment_context ) { Ok(payment_paths) => payment_paths, Err(()) => { @@ -10676,6 +10695,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting, (3, payment_metadata, option), (5, custom_tlvs, optional_vec), (7, requires_blinded_error, (default_value, false)), + (9, payment_context, option), }, (2, ReceiveKeysend) => { (0, payment_preimage, required), @@ -10791,7 +10811,9 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, { impl Writeable for ClaimableHTLC { fn write(&self, writer: &mut W) -> Result<(), io::Error> { let (payment_data, keysend_preimage) = match &self.onion_payload { - OnionPayload::Invoice { _legacy_hop_data } => (_legacy_hop_data.as_ref(), None), + OnionPayload::Invoice { _legacy_hop_data } => { + (_legacy_hop_data.as_ref(), None) + }, OnionPayload::Spontaneous(preimage) => (None, Some(preimage)), }; write_tlv_fields!(writer, { @@ -11036,9 +11058,10 @@ where best_block.block_hash.write(writer)?; } + let per_peer_state = self.per_peer_state.write().unwrap(); + let mut serializable_peer_count: u64 = 0; { - let per_peer_state = self.per_peer_state.read().unwrap(); let mut number_of_funded_channels = 0; for (_, peer_state_mutex) in per_peer_state.iter() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); @@ -11085,8 +11108,6 @@ where decode_update_add_htlcs_opt = Some(decode_update_add_htlcs); } - let per_peer_state = self.per_peer_state.write().unwrap(); - let pending_inbound_payments = self.pending_inbound_payments.lock().unwrap(); let claimable_payments = self.claimable_payments.lock().unwrap(); let pending_outbound_payments = self.pending_outbound_payments.pending_outbound_payments.lock().unwrap(); @@ -11533,9 +11554,10 @@ where } } } else { - log_info!(logger, "Successfully loaded channel {} at update_id {} against monitor at update id {}", + channel.on_startup_drop_completed_blocked_mon_updates_through(&logger, monitor.get_latest_update_id()); + log_info!(logger, "Successfully loaded channel {} at update_id {} against monitor at update id {} with {} blocked updates", &channel.context.channel_id(), channel.context.get_latest_monitor_update_id(), - monitor.get_latest_update_id()); + monitor.get_latest_update_id(), channel.blocked_monitor_updates_pending()); if let Some(short_channel_id) = channel.context.get_short_channel_id() { short_to_chan_info.insert(short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id())); } @@ -11860,6 +11882,7 @@ where log_error!(logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!"); log_error!(logger, " Without the latest ChannelMonitor we cannot continue without risking funds."); log_error!(logger, " Please ensure the chain::Watch API requirements are met and file a bug report at https://github.com/lightningdevkit/rust-lightning"); + log_error!(logger, " Pending in-flight updates are: {:?}", chan_in_flight_updates); return Err(DecodeError::InvalidValue); } } @@ -12080,7 +12103,7 @@ where let purpose = match &htlcs[0].onion_payload { OnionPayload::Invoice { _legacy_hop_data } => { if let Some(hop_data) = _legacy_hop_data { - events::PaymentPurpose::InvoicePayment { + events::PaymentPurpose::Bolt11InvoicePayment { 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) {