Add ChannelClosed generation at cooperative/force-close/error processing
[rust-lightning] / lightning / src / util / events.rs
index d63dd88b76163c86fd16410e468eb03f7d95fcc6..abd8f6b105fcdda900518efbd3c59ea2c52c14cf 100644 (file)
@@ -16,6 +16,7 @@
 
 use chain::keysinterface::SpendableOutputDescriptor;
 use ln::msgs;
+use ln::msgs::DecodeError;
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
 use routing::network_graph::NetworkUpdate;
 use util::ser::{Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
@@ -68,6 +69,47 @@ pub enum PaymentPurpose {
        SpontaneousPayment(PaymentPreimage),
 }
 
+#[derive(Clone, Debug)]
+pub enum ClosureDescriptor {
+       ForceClosed,
+       UserInitiated,
+       CounterpartyInitiated,
+       CooperativeClosure,
+       UnknownOnchainCommitment,
+       ProcessingError,
+       DisconnectedPeer,
+}
+
+impl Writeable for ClosureDescriptor {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+               match self {
+                       ClosureDescriptor::ForceClosed => 0u8.write(writer)?,
+                       ClosureDescriptor::UserInitiated => 1u8.write(writer)?,
+                       ClosureDescriptor::CounterpartyInitiated => 2u8.write(writer)?,
+                       ClosureDescriptor::CooperativeClosure => 3u8.write(writer)?,
+                       ClosureDescriptor::UnknownOnchainCommitment => 4u8.write(writer)?,
+                       ClosureDescriptor::ProcessingError => 5u8.write(writer)?,
+                       ClosureDescriptor::DisconnectedPeer => 6u8.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 => ClosureDescriptor::ForceClosed,
+                       1 => ClosureDescriptor::UserInitiated,
+                       2 => ClosureDescriptor::CounterpartyInitiated,
+                       3 => ClosureDescriptor::CooperativeClosure,
+                       4 => ClosureDescriptor::UnknownOnchainCommitment,
+                       5 => ClosureDescriptor::ProcessingError,
+                       6 => 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
@@ -112,8 +154,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
@@ -138,6 +183,10 @@ pub enum Event {
                /// [`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)]
@@ -182,6 +231,14 @@ pub enum Event {
                /// transaction.
                claim_from_onchain_tx: bool,
        },
+       /// Used to indicate that a channel was closed at the given timestamp.
+       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 {
@@ -221,7 +278,7 @@ impl Writeable for Event {
                                        (0, payment_preimage, required),
                                });
                        },
-                       &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref network_update,
+                       &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref network_update, ref all_paths_failed,
                                #[cfg(test)]
                                ref error_code,
                                #[cfg(test)]
@@ -236,6 +293,7 @@ impl Writeable for Event {
                                        (0, payment_hash, required),
                                        (1, network_update, option),
                                        (2, rejected_by_dest, required),
+                                       (3, all_paths_failed, required),
                                });
                        },
                        &Event::PendingHTLCsForwardable { time_forwardable: _ } => {
@@ -257,6 +315,12 @@ impl Writeable for Event {
                                        (2, claim_from_onchain_tx, required),
                                });
                        },
+                       &Event::ChannelClosed { ref channel_id, ref err } => {
+                               6u8.write(writer)?;
+                               channel_id.write(writer)?;
+                               err.write(writer)?;
+                               write_tlv_fields!(writer, {});
+                       },
                }
                Ok(())
        }
@@ -319,15 +383,18 @@ impl MaybeReadable for Event {
                                        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)]
@@ -369,6 +436,15 @@ impl MaybeReadable for Event {
                        },
                        // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
                        x if x % 2 == 1 => Ok(None),
+                       6u8 => {
+                               let f = || {
+                                       let channel_id = Readable::read(reader)?;
+                                       let err = Readable::read(reader)?;
+                                       read_tlv_fields!(reader, {});
+                                       Ok(Some(Event::ChannelClosed { channel_id, err}))
+                               };
+                               f()
+                       },
                        _ => Err(msgs::DecodeError::InvalidValue)
                }
        }