-f Matt's comments
[rust-lightning] / lightning / src / util / events.rs
index 876dfe6abb551f359a6c67c60fe05c1d104b81ed..d4453d9f26921d5d0ff86c6bbadead84634cd76e 100644 (file)
 //! future, as well as generate and broadcast funding transactions handle payment preimages and a
 //! few other things.
 
+use chain::keysinterface::SpendableOutputDescriptor;
 use ln::msgs;
+use ln::msgs::DecodeError;
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
-use chain::keysinterface::SpendableOutputDescriptor;
+use routing::network_graph::NetworkUpdate;
 use util::ser::{Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
 
 use bitcoin::blockdata::script::Script;
 
 use bitcoin::secp256k1::key::PublicKey;
 
+use io;
 use prelude::*;
 use core::time::Duration;
 use core::ops::Deref;
@@ -66,6 +69,95 @@ pub enum PaymentPurpose {
        SpontaneousPayment(PaymentPreimage),
 }
 
+#[derive(Clone, Debug)]
+pub enum ClosureDescriptor {
+       /// Closure generated from ChannelManager::force_close_channel or receiving a peer error
+       /// message by ChannelManager::handle_error
+       ForceClosed {
+               /// If the error is coming from the peer, there should be a human-readable msg
+               peer_msg: Option<String>,
+       },
+       /// Closure generated from receiving a peer's ClosingSigned message. Note the shutdown
+       /// sequence might have been initially initiated by us.
+       CooperativeClosure,
+       /// Closure generated from receiving chain::Watch's CommitmentTxBroadcast event.
+       CommitmentTxBroadcasted,
+       /// Closure generated from processing an event, likely a HTLC forward/relay/reception.
+       ProcessingError {
+               err: String,
+       },
+       /// Closure generated from ChannelManager::peer_disconnected.
+       DisconnectedPeer,
+}
+
+impl Writeable for ClosureDescriptor {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+               match self {
+                       ClosureDescriptor::ForceClosed { peer_msg } => {
+                               0u8.write(writer)?;
+                               if let Some(peer_msg) = peer_msg {
+                                       0u8.write(writer)?;
+                                       let bytes = peer_msg.clone().into_bytes();
+                                       (bytes.len() as u64).write(writer)?;
+                                       for b in bytes.iter() {
+                                               b.write(writer)?;
+                                       }
+                               } else {
+                                       1u8.write(writer)?;
+                               }
+                       }
+                       ClosureDescriptor::CooperativeClosure => 1u8.write(writer)?,
+                       ClosureDescriptor::CommitmentTxBroadcasted => 2u8.write(writer)?,
+                       ClosureDescriptor::ProcessingError { err } => {
+                               3u8.write(writer)?;
+                               let bytes = err.clone().into_bytes();
+                               (bytes.len() as u64).write(writer)?;
+                               for b in bytes.iter() {
+                                       b.write(writer)?;
+                               }
+                       },
+                       ClosureDescriptor::DisconnectedPeer => 4u8.write(writer)?,
+               }
+               Ok(())
+       }
+}
+
+impl Readable for ClosureDescriptor {
+       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               Ok(match <u8 as Readable>::read(reader)? {
+                       0 => {
+                               let peer_msg = match <u8 as Readable>::read(reader)? {
+                                       0 => {
+                                               let bytes_len: u64 = Readable::read(reader)?;
+                                               let mut bytes: Vec<u8> = Vec::with_capacity(bytes_len as usize);
+                                               for _ in 0..bytes_len {
+                                                       bytes.push(Readable::read(reader)?);
+                                               }
+                                               let err = String::from_utf8(bytes).unwrap();
+                                               Some(err)
+                                       },
+                                       1 => None,
+                                       _ => return Err(DecodeError::InvalidValue),
+                               };
+                               ClosureDescriptor::ForceClosed { peer_msg }
+                       },
+                       1 => ClosureDescriptor::CooperativeClosure,
+                       2 => ClosureDescriptor::CommitmentTxBroadcasted,
+                       3 => {
+                               let bytes_len: u64 = Readable::read(reader)?;
+                               let mut bytes: Vec<u8> = Vec::with_capacity(bytes_len as usize);
+                               for _ in 0..bytes_len {
+                                       bytes.push(Readable::read(reader)?);
+                               }
+                               let err = String::from_utf8(bytes).unwrap();
+                               ClosureDescriptor::ProcessingError { err }
+                       },
+                       4 => ClosureDescriptor::DisconnectedPeer,
+                       _ => return Err(DecodeError::InvalidValue),
+               })
+       }
+}
+
 /// 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
@@ -110,8 +202,11 @@ pub enum Event {
                /// 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
+       /// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target
        /// and we got back the payment preimage for it).
+       ///
+       /// Note for MPP payments: in rare cases, this event may be preceded by a `PaymentFailed` event.
+       /// In this situation, you SHOULD treat this payment as having succeeded.
        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
@@ -127,6 +222,19 @@ pub enum Event {
                /// the payment has failed, not just the route in question. If this is not set, you may
                /// retry the payment via a different route.
                rejected_by_dest: bool,
+               /// Any failure information conveyed via the Onion return packet by a node along the failed
+               /// payment route.
+               ///
+               /// Should be applied to the [`NetworkGraph`] so that routing decisions can take into
+               /// account the update. [`NetGraphMsgHandler`] is capable of doing this.
+               ///
+               /// [`NetworkGraph`]: crate::routing::network_graph::NetworkGraph
+               /// [`NetGraphMsgHandler`]: crate::routing::network_graph::NetGraphMsgHandler
+               network_update: Option<NetworkUpdate>,
+               /// For both single-path and multi-path payments, this is set if all paths of the payment have
+               /// failed. This will be set to false if (1) this is an MPP payment and (2) other parts of the
+               /// larger MPP payment were still in flight when this event was generated.
+               all_paths_failed: bool,
 #[cfg(test)]
                error_code: Option<u16>,
 #[cfg(test)]
@@ -150,10 +258,43 @@ 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,
+       },
+       /// Used to indicate that a channel with the given `channel_id` is in the process of closure.
+       /// Note that if you try to force-close multiple times a channel through
+       /// [`ChannelManager::force_close_channel`] before receiving the corresponding monitor
+       /// event for the broadcast of the commitment transaction, multiple `ChannelClosed` events
+       /// can be generated.
+       ChannelClosed  {
+               /// The channel_id which has been barren from further off-chain updates but
+               /// funding output might still be not resolved yet.
+               channel_id: [u8; 32],
+               /// A machine-readable error message
+               err: ClosureDescriptor
+       }
 }
 
 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)?;
@@ -189,7 +330,7 @@ impl Writeable for Event {
                                        (0, payment_preimage, required),
                                });
                        },
-                       &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest,
+                       &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref network_update, ref all_paths_failed,
                                #[cfg(test)]
                                ref error_code,
                                #[cfg(test)]
@@ -202,7 +343,9 @@ impl Writeable for Event {
                                error_data.write(writer)?;
                                write_tlv_fields!(writer, {
                                        (0, payment_hash, required),
+                                       (1, network_update, option),
                                        (2, rejected_by_dest, required),
+                                       (3, all_paths_failed, required),
                                });
                        },
                        &Event::PendingHTLCsForwardable { time_forwardable: _ } => {
@@ -217,12 +360,25 @@ 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),
+                               });
+                       },
+                       &Event::ChannelClosed { ref channel_id, ref err } => {
+                               9u8.write(writer)?;
+                               channel_id.write(writer)?;
+                               err.write(writer)?;
+                               write_tlv_fields!(writer, {});
+                       },
                }
                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 => {
@@ -278,13 +434,19 @@ impl MaybeReadable for Event {
                                        let error_data = Readable::read(reader)?;
                                        let mut payment_hash = PaymentHash([0; 32]);
                                        let mut rejected_by_dest = false;
+                                       let mut network_update = None;
+                                       let mut all_paths_failed = Some(true);
                                        read_tlv_fields!(reader, {
                                                (0, payment_hash, required),
+                                               (1, network_update, ignorable),
                                                (2, rejected_by_dest, required),
+                                               (3, all_paths_failed, option),
                                        });
                                        Ok(Some(Event::PaymentFailed {
                                                payment_hash,
                                                rejected_by_dest,
+                                               network_update,
+                                               all_paths_failed: all_paths_failed.unwrap(),
                                                #[cfg(test)]
                                                error_code,
                                                #[cfg(test)]
@@ -312,6 +474,26 @@ 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()
+                       },
+                       9u8 => {
+                               let channel_id = Readable::read(reader)?;
+                               let err = Readable::read(reader)?;
+                               read_tlv_fields!(reader, {});
+                               Ok(Some(Event::ChannelClosed { channel_id, err}))
+                       },
+                       // 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)
                }
        }
@@ -442,12 +624,6 @@ pub enum MessageSendEvent {
                /// The action which should be taken.
                action: msgs::ErrorAction
        },
-       /// When a payment fails we may receive updates back from the hop where it failed. In such
-       /// cases this event is generated so that we can inform the network graph of this information.
-       PaymentFailureNetworkUpdate {
-               /// The channel/node update which should be sent to NetGraphMsgHandler
-               update: msgs::HTLCFailChannelUpdate,
-       },
        /// Query a peer for channels with funding transaction UTXOs in a block range.
        SendChannelRangeQuery {
                /// The node_id of this message recipient
@@ -518,11 +694,11 @@ 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);
+       fn handle_event(&self, event: &Event);
 }
 
-impl<F> EventHandler for F where F: Fn(Event) {
-       fn handle_event(&self, event: Event) {
+impl<F> EventHandler for F where F: Fn(&Event) {
+       fn handle_event(&self, event: &Event) {
                self(event)
        }
 }