Merge pull request #1004 from TheBlueMatt/2021-07-forward-event
[rust-lightning] / lightning / src / util / events.rs
index 1bdbff0333a520e0aced1526272d64bb94e75c40..1780483cb8b9e01bcab8d5f0c18e812522d27a7f 100644 (file)
@@ -23,10 +23,50 @@ use bitcoin::blockdata::script::Script;
 
 use bitcoin::secp256k1::key::PublicKey;
 
+use io;
 use prelude::*;
 use core::time::Duration;
 use core::ops::Deref;
 
+/// 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)]
+pub enum PaymentPurpose {
+       /// Information for receiving a payment that we generated an invoice for.
+       InvoicePayment {
+               /// 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`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+               /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+               payment_preimage: Option<PaymentPreimage>,
+               /// The "payment secret". This authenticates the sender to the recipient, preventing a
+               /// number of deanonymization attacks during the routing process.
+               /// It is provided here for your reference, however its accuracy is enforced directly by
+               /// [`ChannelManager`] using the values you previously provided to
+               /// [`ChannelManager::create_inbound_payment`] or
+               /// [`ChannelManager::create_inbound_payment_for_hash`].
+               ///
+               /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
+               payment_secret: PaymentSecret,
+               /// This is the `user_payment_id` which was provided to
+               /// [`ChannelManager::create_inbound_payment_for_hash`] or
+               /// [`ChannelManager::create_inbound_payment`]. It has no meaning inside of LDK and is
+               /// simply copied here. It may be used to correlate PaymentReceived events with invoice
+               /// metadata stored elsewhere.
+               ///
+               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
+               user_payment_id: u64,
+       },
+       /// Because this is a spontaneous payment, the payer generated their own preimage rather than us
+       /// (the payee) providing a preimage.
+       SpontaneousPayment(PaymentPreimage),
+}
+
 /// An Event which you should probably take some action in response to.
 ///
 /// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
@@ -63,37 +103,13 @@ pub enum Event {
        PaymentReceived {
                /// The hash for which the preimage should be handed to the ChannelManager.
                payment_hash: PaymentHash,
-               /// 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`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
-               /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
-               payment_preimage: Option<PaymentPreimage>,
-               /// The "payment secret". This authenticates the sender to the recipient, preventing a
-               /// number of deanonymization attacks during the routing process.
-               /// It is provided here for your reference, however its accuracy is enforced directly by
-               /// [`ChannelManager`] using the values you previously provided to
-               /// [`ChannelManager::create_inbound_payment`] or
-               /// [`ChannelManager::create_inbound_payment_for_hash`].
-               ///
-               /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
-               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
-               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
-               payment_secret: PaymentSecret,
                /// The value, in thousandths of a satoshi, that this payment is for. Note that you must
                /// compare this to the expected value before accepting the payment (as otherwise you are
                /// providing proof-of-payment for less than the value you expected!).
                amt: u64,
-               /// This is the `user_payment_id` which was provided to
-               /// [`ChannelManager::create_inbound_payment_for_hash`] or
-               /// [`ChannelManager::create_inbound_payment`]. It has no meaning inside of LDK and is
-               /// simply copied here. It may be used to correlate PaymentReceived events with invoice
-               /// metadata stored elsewhere.
-               ///
-               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
-               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
-               user_payment_id: u64,
+               /// Information for claiming this received payment, based on whether the purpose of the
+               /// payment is to pay an invoice or to send a spontaneous payment.
+               purpose: PaymentPurpose,
        },
        /// Indicates an outbound payment we made succeeded (ie it made it all the way to its target
        /// and we got back the payment preimage for it).
@@ -135,23 +151,57 @@ pub enum Event {
                /// The outputs which you should store as spendable by you.
                outputs: Vec<SpendableOutputDescriptor>,
        },
+       /// This event is generated when a payment has been successfully forwarded through us and a
+       /// forwarding fee earned.
+       PaymentForwarded {
+               /// The fee, in milli-satoshis, which was earned as a result of the payment.
+               ///
+               /// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC
+               /// was pending, the amount the next hop claimed will have been rounded down to the nearest
+               /// whole satoshi. Thus, the fee calculated here may be higher than expected as we still
+               /// claimed the full value in millisatoshis from the source. In this case,
+               /// `claim_from_onchain_tx` will be set.
+               ///
+               /// If the channel which sent us the payment has been force-closed, we will claim the funds
+               /// via an on-chain transaction. In that case we do not yet know the on-chain transaction
+               /// fees which we will spend and will instead set this to `None`. It is possible duplicate
+               /// `PaymentForwarded` events are generated for the same payment iff `fee_earned_msat` is
+               /// `None`.
+               fee_earned_msat: Option<u64>,
+               /// If this is `true`, the forwarded HTLC was claimed by our counterparty via an on-chain
+               /// transaction.
+               claim_from_onchain_tx: bool,
+       },
 }
 
 impl Writeable for Event {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                match self {
                        &Event::FundingGenerationReady { .. } => {
                                0u8.write(writer)?;
                                // We never write out FundingGenerationReady events as, upon disconnection, peers
                                // drop any channels which have not yet exchanged funding_signed.
                        },
-                       &Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, ref amt, ref user_payment_id } => {
+                       &Event::PaymentReceived { ref payment_hash, ref amt, ref purpose } => {
                                1u8.write(writer)?;
+                               let mut payment_secret = None;
+                               let mut user_payment_id = None;
+                               let payment_preimage;
+                               match &purpose {
+                                       PaymentPurpose::InvoicePayment { payment_preimage: preimage, payment_secret: secret, user_payment_id: id } => {
+                                               payment_secret = Some(secret);
+                                               payment_preimage = *preimage;
+                                               user_payment_id = Some(id);
+                                       },
+                                       PaymentPurpose::SpontaneousPayment(preimage) => {
+                                               payment_preimage = Some(*preimage);
+                                       }
+                               }
                                write_tlv_fields!(writer, {
                                        (0, payment_hash, required),
-                                       (2, payment_secret, required),
+                                       (2, payment_secret, option),
                                        (4, amt, required),
-                                       (6, user_payment_id, required),
+                                       (6, user_payment_id, option),
                                        (8, payment_preimage, option),
                                });
                        },
@@ -160,7 +210,6 @@ impl Writeable for Event {
                                write_tlv_fields!(writer, {
                                        (0, payment_preimage, required),
                                });
-                               payment_preimage.write(writer)?;
                        },
                        &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest,
                                #[cfg(test)]
@@ -190,34 +239,50 @@ impl Writeable for Event {
                                        (0, VecWriteWrapper(outputs), required),
                                });
                        },
+                       &Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx } => {
+                               7u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, fee_earned_msat, option),
+                                       (2, claim_from_onchain_tx, required),
+                               });
+                       },
                }
                Ok(())
        }
 }
 impl MaybeReadable for Event {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
                match Readable::read(reader)? {
                        0u8 => Ok(None),
                        1u8 => {
                                let f = || {
                                        let mut payment_hash = PaymentHash([0; 32]);
                                        let mut payment_preimage = None;
-                                       let mut payment_secret = PaymentSecret([0; 32]);
+                                       let mut payment_secret = None;
                                        let mut amt = 0;
-                                       let mut user_payment_id = 0;
+                                       let mut user_payment_id = None;
                                        read_tlv_fields!(reader, {
                                                (0, payment_hash, required),
-                                               (2, payment_secret, required),
+                                               (2, payment_secret, option),
                                                (4, amt, required),
-                                               (6, user_payment_id, required),
+                                               (6, user_payment_id, option),
                                                (8, payment_preimage, option),
                                        });
+                                       let purpose = match payment_secret {
+                                               Some(secret) => PaymentPurpose::InvoicePayment {
+                                                       payment_preimage,
+                                                       payment_secret: secret,
+                                                       user_payment_id: if let Some(id) = user_payment_id {
+                                                               id
+                                                       } else { return Err(msgs::DecodeError::InvalidValue) }
+                                               },
+                                               None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()),
+                                               None => return Err(msgs::DecodeError::InvalidValue),
+                                       };
                                        Ok(Some(Event::PaymentReceived {
                                                payment_hash,
-                                               payment_preimage,
-                                               payment_secret,
                                                amt,
-                                               user_payment_id,
+                                               purpose,
                                        }))
                                };
                                f()
@@ -276,6 +341,20 @@ impl MaybeReadable for Event {
                                };
                                f()
                        },
+                       7u8 => {
+                               let f = || {
+                                       let mut fee_earned_msat = None;
+                                       let mut claim_from_onchain_tx = false;
+                                       read_tlv_fields!(reader, {
+                                               (0, fee_earned_msat, option),
+                                               (2, claim_from_onchain_tx, required),
+                                       });
+                                       Ok(Some(Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx }))
+                               };
+                               f()
+                       },
+                       // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
+                       x if x % 2 == 1 => Ok(None),
                        _ => Err(msgs::DecodeError::InvalidValue)
                }
        }
@@ -390,6 +469,15 @@ pub enum MessageSendEvent {
                /// The channel_update which should be sent.
                msg: msgs::ChannelUpdate,
        },
+       /// Used to indicate that a channel_update should be sent to a single peer.
+       /// In contrast to [`Self::BroadcastChannelUpdate`], this is used when the channel is a
+       /// private channel and we shouldn't be informing all of our peers of channel parameters.
+       SendChannelUpdate {
+               /// The node_id of the node which should receive this message
+               node_id: PublicKey,
+               /// The channel_update which should be sent.
+               msg: msgs::ChannelUpdate,
+       },
        /// Broadcast an error downstream to be handled
        HandleError {
                /// The node_id of the node which should receive this message