X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fevents%2Fmod.rs;h=d34db885f7c4e0d24ad52281f143f5fb08c385ad;hb=478911d42a8b47020511bdcb793756723f3801be;hp=fcd37914e3dd99d6340925629cb5d3dfa7553c7a;hpb=0cc08589b79fdb7998a581bb1ef978e2eaffc1ce;p=rust-lightning diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index fcd37914..d34db885 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -18,6 +18,7 @@ pub mod bump_transaction; pub use bump_transaction::BumpTransactionEvent; +use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext, PaymentContextRef}; use crate::sign::SpendableOutputDescriptor; use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; @@ -38,20 +39,23 @@ use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::PublicKey; use crate::io; -use crate::prelude::*; use core::time::Duration; use core::ops::Deref; use crate::sync::Arc; +#[allow(unused_imports)] +use crate::prelude::*; + /// Some information provided on receipt of payment depends on whether the payment received is a /// spontaneous payment or a "conventional" lightning payment that's paying an invoice. #[derive(Clone, Debug, PartialEq, Eq)] pub enum PaymentPurpose { - /// Information for receiving a payment that we generated an invoice for. - InvoicePayment { + /// A payment for a BOLT 11 invoice. + Bolt11InvoicePayment { /// The preimage to the payment_hash, if the payment hash (and secret) were fetched via - /// [`ChannelManager::create_inbound_payment`]. If provided, this can be handed directly to - /// [`ChannelManager::claim_funds`]. + /// [`ChannelManager::create_inbound_payment`]. When handling [`Event::PaymentClaimable`], + /// this can be passed directly to [`ChannelManager::claim_funds`] to claim the payment. No + /// action is needed when seen in [`Event::PaymentClaimed`]. /// /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds @@ -68,6 +72,48 @@ pub enum PaymentPurpose { /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash payment_secret: PaymentSecret, }, + /// A payment for a BOLT 12 [`Offer`]. + /// + /// [`Offer`]: crate::offers::offer::Offer + Bolt12OfferPayment { + /// The preimage to the payment hash. When handling [`Event::PaymentClaimable`], this can be + /// passed directly to [`ChannelManager::claim_funds`], if provided. No action is needed + /// when seen in [`Event::PaymentClaimed`]. + /// + /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds + payment_preimage: Option, + /// The secret used to authenticate the sender to the recipient, preventing a number of + /// de-anonymization attacks while routing a payment. + /// + /// See [`PaymentPurpose::Bolt11InvoicePayment::payment_secret`] for further details. + payment_secret: PaymentSecret, + /// The context of the payment such as information about the corresponding [`Offer`] and + /// [`InvoiceRequest`]. + /// + /// [`Offer`]: crate::offers::offer::Offer + /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest + payment_context: Bolt12OfferContext, + }, + /// A payment for a BOLT 12 [`Refund`]. + /// + /// [`Refund`]: crate::offers::refund::Refund + Bolt12RefundPayment { + /// The preimage to the payment hash. When handling [`Event::PaymentClaimable`], this can be + /// passed directly to [`ChannelManager::claim_funds`], if provided. No action is needed + /// when seen in [`Event::PaymentClaimed`]. + /// + /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds + payment_preimage: Option, + /// The secret used to authenticate the sender to the recipient, preventing a number of + /// de-anonymization attacks while routing a payment. + /// + /// See [`PaymentPurpose::Bolt11InvoicePayment::payment_secret`] for further details. + payment_secret: PaymentSecret, + /// The context of the payment such as information about the corresponding [`Refund`]. + /// + /// [`Refund`]: crate::offers::refund::Refund + payment_context: Bolt12RefundContext, + }, /// Because this is a spontaneous payment, the payer generated their own preimage rather than us /// (the payee) providing a preimage. SpontaneousPayment(PaymentPreimage), @@ -77,17 +123,67 @@ impl PaymentPurpose { /// Returns the preimage for this payment, if it is known. pub fn preimage(&self) -> Option { match self { - PaymentPurpose::InvoicePayment { payment_preimage, .. } => *payment_preimage, + PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => *payment_preimage, + PaymentPurpose::Bolt12OfferPayment { payment_preimage, .. } => *payment_preimage, + PaymentPurpose::Bolt12RefundPayment { payment_preimage, .. } => *payment_preimage, PaymentPurpose::SpontaneousPayment(preimage) => Some(*preimage), } } + + pub(crate) fn is_keysend(&self) -> bool { + match self { + PaymentPurpose::Bolt11InvoicePayment { .. } => false, + PaymentPurpose::Bolt12OfferPayment { .. } => false, + PaymentPurpose::Bolt12RefundPayment { .. } => false, + PaymentPurpose::SpontaneousPayment(..) => true, + } + } + + pub(crate) fn from_parts( + payment_preimage: Option, payment_secret: PaymentSecret, + payment_context: Option, + ) -> Self { + match payment_context { + Some(PaymentContext::Unknown(_)) | None => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage, + payment_secret, + } + }, + Some(PaymentContext::Bolt12Offer(context)) => { + PaymentPurpose::Bolt12OfferPayment { + payment_preimage, + payment_secret, + payment_context: context, + } + }, + Some(PaymentContext::Bolt12Refund(context)) => { + PaymentPurpose::Bolt12RefundPayment { + payment_preimage, + payment_secret, + payment_context: context, + } + }, + } + } } impl_writeable_tlv_based_enum!(PaymentPurpose, - (0, InvoicePayment) => { + (0, Bolt11InvoicePayment) => { (0, payment_preimage, option), (2, payment_secret, required), - }; + }, + (4, Bolt12OfferPayment) => { + (0, payment_preimage, option), + (2, payment_secret, required), + (4, payment_context, required), + }, + (6, Bolt12RefundPayment) => { + (0, payment_preimage, option), + (2, payment_secret, required), + (4, payment_context, required), + }, + ; (2, SpontaneousPayment) ); @@ -232,6 +328,8 @@ pub enum ClosureReason { /// Another channel in the same funding batch closed before the funding transaction /// was ready to be broadcast. FundingBatchClosure, + /// One of our HTLCs timed out in a channel, causing us to force close the channel. + HTLCsTimedOut, } impl core::fmt::Display for ClosureReason { @@ -241,7 +339,7 @@ impl core::fmt::Display for ClosureReason { ClosureReason::CounterpartyForceClosed { peer_msg } => { f.write_fmt(format_args!("counterparty force-closed with message: {}", peer_msg)) }, - ClosureReason::HolderForceClosed => f.write_str("user manually force-closed the channel"), + ClosureReason::HolderForceClosed => f.write_str("user force-closed the channel"), ClosureReason::LegacyCooperativeClosure => f.write_str("the channel was cooperatively closed"), ClosureReason::CounterpartyInitiatedCooperativeClosure => f.write_str("the channel was cooperatively closed by our peer"), ClosureReason::LocallyInitiatedCooperativeClosure => f.write_str("the channel was cooperatively closed by us"), @@ -255,6 +353,7 @@ impl core::fmt::Display for ClosureReason { ClosureReason::OutdatedChannelManager => f.write_str("the ChannelManager read from disk was stale compared to ChannelMonitor(s)"), ClosureReason::CounterpartyCoopClosedUnfundedChannel => f.write_str("the peer requested the unfunded channel be closed"), ClosureReason::FundingBatchClosure => f.write_str("another channel in the same funding batch closed"), + ClosureReason::HTLCsTimedOut => f.write_str("htlcs on the channel timed out"), } } } @@ -272,6 +371,7 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason, (15, FundingBatchClosure) => {}, (17, CounterpartyInitiatedCooperativeClosure) => {}, (19, LocallyInitiatedCooperativeClosure) => {}, + (21, HTLCsTimedOut) => {}, ); /// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`]. @@ -298,6 +398,8 @@ pub enum HTLCDestination { /// Short channel id we are requesting to forward an HTLC to. requested_forward_scid: u64 }, + /// We couldn't decode the incoming onion to obtain the forwarding details. + InvalidOnion, /// Failure scenario where an HTLC may have been forwarded to be intended for us, /// but is invalid for some reason, so we reject it. /// @@ -325,6 +427,7 @@ impl_writeable_tlv_based_enum_upgradable!(HTLCDestination, (2, UnknownNextHop) => { (0, requested_forward_scid, required), }, + (3, InvalidOnion) => {}, (4, FailedPayment) => { (0, payment_hash, required), }, @@ -1049,10 +1152,27 @@ impl Writeable for Event { 1u8.write(writer)?; let mut payment_secret = None; let payment_preimage; + let mut payment_context = None; match &purpose { - PaymentPurpose::InvoicePayment { payment_preimage: preimage, payment_secret: secret } => { + PaymentPurpose::Bolt11InvoicePayment { + payment_preimage: preimage, payment_secret: secret + } => { + payment_secret = Some(secret); + payment_preimage = *preimage; + }, + PaymentPurpose::Bolt12OfferPayment { + payment_preimage: preimage, payment_secret: secret, payment_context: context + } => { + payment_secret = Some(secret); + payment_preimage = *preimage; + payment_context = Some(PaymentContextRef::Bolt12Offer(context)); + }, + PaymentPurpose::Bolt12RefundPayment { + payment_preimage: preimage, payment_secret: secret, payment_context: context + } => { payment_secret = Some(secret); payment_preimage = *preimage; + payment_context = Some(PaymentContextRef::Bolt12Refund(context)); }, PaymentPurpose::SpontaneousPayment(preimage) => { payment_preimage = Some(*preimage); @@ -1072,6 +1192,7 @@ impl Writeable for Event { (8, payment_preimage, option), (9, onion_fields, option), (10, skimmed_fee_opt, option), + (11, payment_context, option), }); }, &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => { @@ -1290,7 +1411,7 @@ impl MaybeReadable for Event { // Note that we do not write a length-prefixed TLV for FundingGenerationReady events. 0u8 => Ok(None), 1u8 => { - let f = || { + let mut f = || { let mut payment_hash = PaymentHash([0; 32]); let mut payment_preimage = None; let mut payment_secret = None; @@ -1302,6 +1423,7 @@ impl MaybeReadable for Event { let mut claim_deadline = None; let mut via_user_channel_id = None; let mut onion_fields = None; + let mut payment_context = None; read_tlv_fields!(reader, { (0, payment_hash, required), (1, receiver_node_id, option), @@ -1314,12 +1436,10 @@ impl MaybeReadable for Event { (8, payment_preimage, option), (9, onion_fields, option), (10, counterparty_skimmed_fee_msat_opt, option), + (11, payment_context, option), }); let purpose = match payment_secret { - Some(secret) => PaymentPurpose::InvoicePayment { - payment_preimage, - payment_secret: secret - }, + Some(secret) => PaymentPurpose::from_parts(payment_preimage, secret, payment_context), None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()), None => return Err(msgs::DecodeError::InvalidValue), }; @@ -1338,7 +1458,7 @@ impl MaybeReadable for Event { f() }, 2u8 => { - let f = || { + let mut f = || { let mut payment_preimage = PaymentPreimage([0; 32]); let mut payment_hash = None; let mut payment_id = None; @@ -1362,7 +1482,7 @@ impl MaybeReadable for Event { f() }, 3u8 => { - let f = || { + let mut f = || { #[cfg(test)] let error_code = Readable::read(reader)?; #[cfg(test)] @@ -1405,7 +1525,7 @@ impl MaybeReadable for Event { }, 4u8 => Ok(None), 5u8 => { - let f = || { + let mut f = || { let mut outputs = WithoutLength(Vec::new()); let mut channel_id: Option = None; read_tlv_fields!(reader, { @@ -1441,7 +1561,7 @@ impl MaybeReadable for Event { })) }, 7u8 => { - let f = || { + let mut f = || { let mut prev_channel_id = None; let mut next_channel_id = None; let mut prev_user_channel_id = None; @@ -1469,7 +1589,7 @@ impl MaybeReadable for Event { f() }, 9u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut reason = UpgradableRequired(None); let mut user_channel_id_low_opt: Option = None; @@ -1499,7 +1619,7 @@ impl MaybeReadable for Event { f() }, 11u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut transaction = Transaction{ version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() }; read_tlv_fields!(reader, { @@ -1511,7 +1631,7 @@ impl MaybeReadable for Event { f() }, 13u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), (2, payment_hash, option), @@ -1527,7 +1647,7 @@ impl MaybeReadable for Event { f() }, 15u8 => { - let f = || { + let mut f = || { let mut payment_hash = PaymentHash([0; 32]); let mut payment_id = PaymentId([0; 32]); let mut reason = None; @@ -1549,7 +1669,7 @@ impl MaybeReadable for Event { Ok(None) }, 19u8 => { - let f = || { + let mut f = || { let mut payment_hash = PaymentHash([0; 32]); let mut purpose = UpgradableRequired(None); let mut amount_msat = 0; @@ -1576,7 +1696,7 @@ impl MaybeReadable for Event { f() }, 21u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), (2, payment_hash, required), @@ -1592,7 +1712,7 @@ impl MaybeReadable for Event { f() }, 23u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), (2, payment_hash, required), @@ -1610,7 +1730,7 @@ impl MaybeReadable for Event { f() }, 25u8 => { - let f = || { + let mut f = || { let mut prev_channel_id = ChannelId::new_zero(); let mut failed_next_destination_opt = UpgradableRequired(None); read_tlv_fields!(reader, { @@ -1626,7 +1746,7 @@ impl MaybeReadable for Event { }, 27u8 => Ok(None), 29u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut user_channel_id: u128 = 0; let mut counterparty_node_id = RequiredWrapper(None); @@ -1648,7 +1768,7 @@ impl MaybeReadable for Event { f() }, 31u8 => { - let f = || { + let mut f = || { let mut channel_id = ChannelId::new_zero(); let mut user_channel_id: u128 = 0; let mut former_temporary_channel_id = None; @@ -1676,7 +1796,7 @@ impl MaybeReadable for Event { f() }, 33u8 => { - let f = || { + let mut f = || { _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_id, required), });