Generate a PaymentForwarded event when a forwarded HTLC is claimed
[rust-lightning] / lightning / src / util / events.rs
index 798f562526fa8acbba55e4353e94c08b03d50980..34b0b331e9e45d3512c6b65b41fd146904e735b0 100644 (file)
 use ln::msgs;
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
 use chain::keysinterface::SpendableOutputDescriptor;
-use util::ser::{Writeable, Writer, MaybeReadable, Readable};
+use util::ser::{Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
 
 use bitcoin::blockdata::script::Script;
 
 use bitcoin::secp256k1::key::PublicKey;
 
-use std::time::Duration;
+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.
 ///
@@ -61,42 +102,16 @@ 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).
-       /// Note that duplicative PaymentSent Events may be generated - it is your responsibility to
-       /// deduplicate them by payment_preimage (which MUST be unique)!
        PaymentSent {
                /// The preimage to the hash given to ChannelManager::send_payment.
                /// Note that this serves as a payment receipt, if you wish to have such a thing, you must
@@ -105,8 +120,6 @@ pub enum Event {
        },
        /// Indicates an outbound payment we made failed. Probably some intermediary node dropped
        /// something. You may wish to retry with a different route.
-       /// Note that duplicative PaymentFailed Events may be generated - it is your responsibility to
-       /// deduplicate them by payment_hash (which MUST be unique)!
        PaymentFailed {
                /// The hash which was given to ChannelManager::send_payment.
                payment_hash: PaymentHash,
@@ -128,7 +141,8 @@ pub enum Event {
                /// now + 5*time_forwardable).
                time_forwardable: Duration,
        },
-       /// Used to indicate that an output was generated on-chain which you should know how to spend.
+       /// Used to indicate that an output which you should know how to spend was confirmed on chain
+       /// and is now spendable.
        /// Such an output will *not* ever be spent by rust-lightning, and are not at risk of your
        /// counterparty spending them due to some kind of timeout. Thus, you need to store them
        /// somewhere and spend them when you create on-chain transactions.
@@ -136,6 +150,27 @@ 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 {
@@ -146,17 +181,34 @@ impl Writeable for Event {
                                // 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)?;
-                               payment_hash.write(writer)?;
-                               payment_preimage.write(writer)?;
-                               payment_secret.write(writer)?;
-                               amt.write(writer)?;
-                               user_payment_id.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, option),
+                                       (4, amt, required),
+                                       (6, user_payment_id, option),
+                                       (8, payment_preimage, option),
+                               });
                        },
                        &Event::PaymentSent { ref payment_preimage } => {
                                2u8.write(writer)?;
-                               payment_preimage.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_preimage, required),
+                               });
                        },
                        &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest,
                                #[cfg(test)]
@@ -165,24 +217,33 @@ impl Writeable for Event {
                                ref error_data,
                        } => {
                                3u8.write(writer)?;
-                               payment_hash.write(writer)?;
-                               rejected_by_dest.write(writer)?;
                                #[cfg(test)]
                                error_code.write(writer)?;
                                #[cfg(test)]
                                error_data.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_hash, required),
+                                       (2, rejected_by_dest, required),
+                               });
                        },
                        &Event::PendingHTLCsForwardable { time_forwardable: _ } => {
                                4u8.write(writer)?;
+                               write_tlv_fields!(writer, {});
                                // We don't write the time_fordwardable out at all, as we presume when the user
                                // deserializes us at least that much time has elapsed.
                        },
                        &Event::SpendableOutputs { ref outputs } => {
                                5u8.write(writer)?;
-                               (outputs.len() as u64).write(writer)?;
-                               for output in outputs.iter() {
-                                       output.write(writer)?;
-                               }
+                               write_tlv_fields!(writer, {
+                                       (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(())
@@ -192,35 +253,107 @@ impl MaybeReadable for Event {
        fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
                match Readable::read(reader)? {
                        0u8 => Ok(None),
-                       1u8 => Ok(Some(Event::PaymentReceived {
-                                       payment_hash: Readable::read(reader)?,
-                                       payment_preimage: Readable::read(reader)?,
-                                       payment_secret: Readable::read(reader)?,
-                                       amt: Readable::read(reader)?,
-                                       user_payment_id: Readable::read(reader)?,
-                               })),
-                       2u8 => Ok(Some(Event::PaymentSent {
-                                       payment_preimage: Readable::read(reader)?,
-                               })),
-                       3u8 => Ok(Some(Event::PaymentFailed {
-                                       payment_hash: Readable::read(reader)?,
-                                       rejected_by_dest: Readable::read(reader)?,
+                       1u8 => {
+                               let f = || {
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut payment_preimage = None;
+                                       let mut payment_secret = None;
+                                       let mut amt = 0;
+                                       let mut user_payment_id = None;
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_hash, required),
+                                               (2, payment_secret, option),
+                                               (4, amt, 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,
+                                               amt,
+                                               purpose,
+                                       }))
+                               };
+                               f()
+                       },
+                       2u8 => {
+                               let f = || {
+                                       let mut payment_preimage = PaymentPreimage([0; 32]);
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_preimage, required),
+                                       });
+                                       Ok(Some(Event::PaymentSent {
+                                               payment_preimage,
+                                       }))
+                               };
+                               f()
+                       },
+                       3u8 => {
+                               let f = || {
                                        #[cfg(test)]
-                                       error_code: Readable::read(reader)?,
+                                       let error_code = Readable::read(reader)?;
                                        #[cfg(test)]
-                                       error_data: Readable::read(reader)?,
-                               })),
-                       4u8 => Ok(Some(Event::PendingHTLCsForwardable {
-                                       time_forwardable: Duration::from_secs(0)
-                               })),
+                                       let error_data = Readable::read(reader)?;
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut rejected_by_dest = false;
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_hash, required),
+                                               (2, rejected_by_dest, required),
+                                       });
+                                       Ok(Some(Event::PaymentFailed {
+                                               payment_hash,
+                                               rejected_by_dest,
+                                               #[cfg(test)]
+                                               error_code,
+                                               #[cfg(test)]
+                                               error_data,
+                                       }))
+                               };
+                               f()
+                       },
+                       4u8 => {
+                               let f = || {
+                                       read_tlv_fields!(reader, {});
+                                       Ok(Some(Event::PendingHTLCsForwardable {
+                                               time_forwardable: Duration::from_secs(0)
+                                       }))
+                               };
+                               f()
+                       },
                        5u8 => {
-                               let outputs_len: u64 = Readable::read(reader)?;
-                               let mut outputs = Vec::new();
-                               for _ in 0..outputs_len {
-                                       outputs.push(Readable::read(reader)?);
-                               }
-                               Ok(Some(Event::SpendableOutputs { outputs }))
+                               let f = || {
+                                       let mut outputs = VecReadWrapper(Vec::new());
+                                       read_tlv_fields!(reader, {
+                                               (0, outputs, required),
+                                       });
+                                       Ok(Some(Event::SpendableOutputs { outputs: outputs.0 }))
+                               };
+                               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)
                }
        }
@@ -335,6 +468,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
@@ -380,9 +522,49 @@ pub trait MessageSendEventsProvider {
        fn get_and_clear_pending_msg_events(&self) -> Vec<MessageSendEvent>;
 }
 
-/// A trait indicating an object may generate events
+/// A trait indicating an object may generate events.
+///
+/// Events are processed by passing an [`EventHandler`] to [`process_pending_events`].
+///
+/// # Requirements
+///
+/// See [`process_pending_events`] for requirements around event processing.
+///
+/// When using this trait, [`process_pending_events`] will call [`handle_event`] for each pending
+/// event since the last invocation. The handler must either act upon the event immediately
+/// or preserve it for later handling.
+///
+/// Note, handlers may call back into the provider and thus deadlocking must be avoided. Be sure to
+/// consult the provider's documentation on the implication of processing events and how a handler
+/// may safely use the provider (e.g., see [`ChannelManager::process_pending_events`] and
+/// [`ChainMonitor::process_pending_events`]).
+///
+/// (C-not implementable) As there is likely no reason for a user to implement this trait on their
+/// own type(s).
+///
+/// [`process_pending_events`]: Self::process_pending_events
+/// [`handle_event`]: EventHandler::handle_event
+/// [`ChannelManager::process_pending_events`]: crate::ln::channelmanager::ChannelManager#method.process_pending_events
+/// [`ChainMonitor::process_pending_events`]: crate::chain::chainmonitor::ChainMonitor#method.process_pending_events
 pub trait EventsProvider {
-       /// Gets the list of pending events which were generated by previous actions, clearing the list
-       /// in the process.
-       fn get_and_clear_pending_events(&self) -> Vec<Event>;
+       /// Processes any events generated since the last call using the given event handler.
+       ///
+       /// Subsequent calls must only process new events. However, handlers must be capable of handling
+       /// duplicate events across process restarts. This may occur if the provider was recovered from
+       /// an old state (i.e., it hadn't been successfully persisted after processing pending events).
+       fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler;
+}
+
+/// A trait implemented for objects handling events from [`EventsProvider`].
+pub trait EventHandler {
+       /// Handles the given [`Event`].
+       ///
+       /// See [`EventsProvider`] for details that must be considered when implementing this method.
+       fn handle_event(&self, event: Event);
+}
+
+impl<F> EventHandler for F where F: Fn(Event) {
+       fn handle_event(&self, event: Event) {
+               self(event)
+       }
 }