Add Event::ChannelClosed generation at channel shutdown
authorAntoine Riard <dev@ariard.me>
Tue, 13 Jul 2021 17:04:54 +0000 (13:04 -0400)
committerAntoine Riard <dev@ariard.me>
Tue, 21 Sep 2021 19:46:40 +0000 (15:46 -0400)
lightning/src/util/events.rs
lightning/src/util/ser.rs

index df4d9037307c30cb20e32c9b36a07ff6c10cd4b5..ca4e96d60f73e4f44d0c5ce01a82d80671d4943a 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,60 @@ pub enum PaymentPurpose {
        SpontaneousPayment(PaymentPreimage),
 }
 
+#[derive(Clone, Debug, PartialEq)]
+/// The reason the channel was closed. See individual variants more details.
+pub enum ClosureReason {
+       /// Closure generated from receiving a peer error message.
+       ///
+       /// Our counterparty may have broadcasted their latest commitment state, and we have
+       /// as well.
+       CounterpartyForceClosed {
+               /// The error which the peer sent us.
+               ///
+               /// The string should be sanitized before it is used (e.g emitted to logs
+               /// or printed to stdout). Otherwise, a well crafted error message may exploit
+               /// a security vulnerability in the terminal emulator or the logging subsystem.
+               peer_msg: String,
+       },
+       /// Closure generated from [`ChannelManager::force_close_channel`], called by the user.
+       ///
+       /// [`ChannelManager::force_close_channel`]: crate::ln::channelmanager::ChannelManager::force_close_channel.
+       HolderForceClosed,
+       /// The channel was closed after negotiating a cooperative close and we've now broadcasted
+       /// the cooperative close transaction. Note the shutdown may have been initiated by us.
+       //TODO: split between CounterpartyInitiated/LocallyInitiated
+       CooperativeClosure,
+       /// A commitment transaction was confirmed on chain, closing the channel. Most likely this
+       /// commitment transaction came from our counterparty, but it may also have come from
+       /// a copy of our own `ChannelMonitor`.
+       CommitmentTxConfirmed,
+       /// Closure generated from processing an event, likely a HTLC forward/relay/reception.
+       ProcessingError {
+               /// A developer-readable error message which we generated.
+               err: String,
+       },
+       /// The `PeerManager` informed us that we've disconnected from the peer. We close channels
+       /// if the `PeerManager` informed us that it is unlikely we'll be able to connect to the
+       /// peer again in the future or if the peer disconnected before we finished negotiating
+       /// the channel open. The first case may be caused by incompatible features which our
+       /// counterparty, or we, require.
+       //TODO: split between PeerUnconnectable/PeerDisconnected ?
+       DisconnectedPeer,
+       /// Closure generated from `ChannelManager::read` if the ChannelMonitor is newer than
+       /// the ChannelManager deserialized.
+       OutdatedChannelManager
+}
+
+impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
+       (0, CounterpartyForceClosed) => { (1, peer_msg, required) },
+       (2, HolderForceClosed) => {},
+       (6, CommitmentTxConfirmed) => {},
+       (4, CooperativeClosure) => {},
+       (8, ProcessingError) => { (1, err, required) },
+       (10, DisconnectedPeer) => {},
+       (12, OutdatedChannelManager) => {},
+);
+
 /// 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
@@ -189,6 +244,14 @@ pub enum Event {
                /// transaction.
                claim_from_onchain_tx: bool,
        },
+       /// Used to indicate that a channel with the given `channel_id` is in the process of closure.
+       ChannelClosed  {
+               /// The channel_id of the channel which has been closed. Note that on-chain transactions
+               /// resolving the channel are likely still awaiting confirmation.
+               channel_id: [u8; 32],
+               /// The reason the channel was closed.
+               reason: ClosureReason
+       }
 }
 
 impl Writeable for Event {
@@ -265,6 +328,13 @@ impl Writeable for Event {
                                        (2, claim_from_onchain_tx, required),
                                });
                        },
+                       &Event::ChannelClosed { ref channel_id, ref reason } => {
+                               9u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, channel_id, required),
+                                       (2, reason, required)
+                               });
+                       },
                }
                Ok(())
        }
@@ -378,6 +448,16 @@ impl MaybeReadable for Event {
                                };
                                f()
                        },
+                       9u8 => {
+                               let mut channel_id = [0; 32];
+                               let mut reason = None;
+                               read_tlv_fields!(reader, {
+                                       (0, channel_id, required),
+                                       (2, reason, ignorable),
+                               });
+                               if reason.is_none() { return Ok(None); }
+                               Ok(Some(Event::ChannelClosed { channel_id, reason: reason.unwrap() }))
+                       },
                        // 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)
index c76b701817b5d9eb1a5c2645f705241fe86e3ad9..83059620ed3f3382be4b349197efa1b357de72cf 100644 (file)
@@ -897,3 +897,20 @@ impl Readable for () {
                Ok(())
        }
 }
+
+impl Writeable for String {
+       #[inline]
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               (self.len() as u16).write(w)?;
+               w.write_all(self.as_bytes())
+       }
+}
+
+impl Readable for String {
+       #[inline]
+       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let v: Vec<u8> = Readable::read(r)?;
+               let ret = String::from_utf8(v).map_err(|_| DecodeError::InvalidValue)?;
+               Ok(ret)
+       }
+}