Merge pull request #2269 from TheBlueMatt/2023-05-doc-events-present
[rust-lightning] / lightning / src / events / mod.rs
index a96d36b645312e6efe854a8ddb4f272db3b94532..665fd0ed23a51ae27b7c260b33717ac9690f74db 100644 (file)
@@ -20,8 +20,8 @@ pub mod bump_transaction;
 #[cfg(anchors)]
 pub use bump_transaction::BumpTransactionEvent;
 
-use crate::chain::keysinterface::SpendableOutputDescriptor;
-use crate::ln::channelmanager::{InterceptId, PaymentId};
+use crate::sign::SpendableOutputDescriptor;
+use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields};
 use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
 use crate::ln::features::ChannelTypeFeatures;
 use crate::ln::msgs;
@@ -30,9 +30,11 @@ use crate::routing::gossip::NetworkUpdate;
 use crate::util::errors::APIError;
 use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired, WithoutLength};
 use crate::util::string::UntrustedString;
-use crate::routing::router::{RouteHop, RouteParameters};
+use crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters};
 
-use bitcoin::{PackedLockTime, Transaction};
+use bitcoin::{PackedLockTime, Transaction, OutPoint};
+#[cfg(anchors)]
+use bitcoin::{Txid, TxIn, TxOut, Witness};
 use bitcoin::blockdata::script::Script;
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
@@ -127,7 +129,7 @@ pub enum ClosureReason {
                /// Be careful about printing the peer_msg, a well-crafted message could exploit
                /// a security vulnerability in the terminal emulator or the logging subsystem.
                /// To be safe, use `Display` on `UntrustedString`
-               /// 
+               ///
                /// [`UntrustedString`]: crate::util::string::UntrustedString
                peer_msg: UntrustedString,
        },
@@ -230,8 +232,11 @@ pub enum HTLCDestination {
        ///
        /// Some of the reasons may include:
        /// * HTLC Timeouts
-       /// * Expected MPP amount has already been reached
-       /// * Claimable amount does not match expected amount
+       /// * Excess HTLCs for a payment that we have already fully received, over-paying for the
+       ///   payment,
+       /// * The counterparty node modified the HTLC in transit,
+       /// * A probing attack where an intermediary node is trying to detect if we are the ultimate
+       ///   recipient for a payment.
        FailedPayment {
                /// The payment hash of the payment we attempted to process.
                payment_hash: PaymentHash
@@ -270,6 +275,43 @@ impl_writeable_tlv_based_enum!(InterceptNextHop,
        };
 );
 
+/// The reason the payment failed. Used in [`Event::PaymentFailed`].
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum PaymentFailureReason {
+       /// The intended recipient rejected our payment.
+       RecipientRejected,
+       /// The user chose to abandon this payment by calling [`ChannelManager::abandon_payment`].
+       ///
+       /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
+       UserAbandoned,
+       /// We exhausted all of our retry attempts while trying to send the payment, or we
+       /// exhausted the [`Retry::Timeout`] if the user set one. If at any point a retry
+       /// attempt failed while being forwarded along the path, an [`Event::PaymentPathFailed`] will
+       /// have come before this.
+       ///
+       /// [`Retry::Timeout`]: crate::ln::channelmanager::Retry::Timeout
+       RetriesExhausted,
+       /// The payment expired while retrying, based on the provided
+       /// [`PaymentParameters::expiry_time`].
+       ///
+       /// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time
+       PaymentExpired,
+       /// We failed to find a route while retrying the payment.
+       RouteNotFound,
+       /// This error should generally never happen. This likely means that there is a problem with
+       /// your router.
+       UnexpectedError,
+}
+
+impl_writeable_tlv_based_enum!(PaymentFailureReason,
+       (0, RecipientRejected) => {},
+       (2, UserAbandoned) => {},
+       (4, RetriesExhausted) => {},
+       (6, PaymentExpired) => {},
+       (8, RouteNotFound) => {},
+       (10, UnexpectedError) => {}, ;
+);
+
 /// 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
@@ -319,7 +361,9 @@ pub enum Event {
        ///
        /// # Note
        /// LDK will not stop an inbound payment from being paid multiple times, so multiple
-       /// `PaymentClaimable` events may be generated for the same payment.
+       /// `PaymentClaimable` events may be generated for the same payment. In such a case it is
+       /// polite (and required in the lightning specification) to fail the payment the second time
+       /// and give the sender their money back rather than accepting double payment.
        ///
        /// # Note
        /// This event used to be called `PaymentReceived` in LDK versions 0.0.112 and earlier.
@@ -333,11 +377,16 @@ pub enum Event {
                /// This field will always be filled in when the event was generated by LDK versions
                /// 0.0.113 and above.
                ///
-               /// [phantom nodes]: crate::chain::keysinterface::PhantomKeysManager
+               /// [phantom nodes]: crate::sign::PhantomKeysManager
                receiver_node_id: Option<PublicKey>,
                /// The hash for which the preimage should be handed to the ChannelManager. Note that LDK will
                /// not stop you from registering duplicate payment hashes for inbound payments.
                payment_hash: PaymentHash,
+               /// The fields in the onion which were received with each HTLC. Only fields which were
+               /// identical in each HTLC involved in the payment will be included here.
+               ///
+               /// Payments received on LDK versions prior to 0.0.115 will have this field unset.
+               onion_fields: Option<RecipientOnionFields>,
                /// The value, in thousandths of a satoshi, that this payment is for.
                amount_msat: u64,
                /// Information for claiming this received payment, based on whether the purpose of the
@@ -347,6 +396,14 @@ pub enum Event {
                via_channel_id: Option<[u8; 32]>,
                /// The `user_channel_id` indicating over which channel we received the payment.
                via_user_channel_id: Option<u128>,
+               /// The block height at which this payment will be failed back and will no longer be
+               /// eligible for claiming.
+               ///
+               /// Prior to this height, a call to [`ChannelManager::claim_funds`] is guaranteed to
+               /// succeed, however you should wait for [`Event::PaymentClaimed`] to be sure.
+               ///
+               /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+               claim_deadline: Option<u32>,
        },
        /// Indicates a payment has been claimed and we've received money!
        ///
@@ -368,7 +425,7 @@ pub enum Event {
                /// This field will always be filled in when the event was generated by LDK versions
                /// 0.0.113 and above.
                ///
-               /// [phantom nodes]: crate::chain::keysinterface::PhantomKeysManager
+               /// [phantom nodes]: crate::sign::PhantomKeysManager
                receiver_node_id: Option<PublicKey>,
                /// The payment hash of the claimed payment. Note that LDK will not stop you from
                /// registering duplicate payment hashes for inbound payments.
@@ -385,7 +442,7 @@ pub enum Event {
        /// Note for MPP payments: in rare cases, this event may be preceded by a `PaymentPathFailed`
        /// event. In this situation, you SHOULD treat this payment as having succeeded.
        PaymentSent {
-               /// The id returned by [`ChannelManager::send_payment`].
+               /// The `payment_id` passed to [`ChannelManager::send_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
                payment_id: Option<PaymentId>,
@@ -418,34 +475,37 @@ pub enum Event {
        /// [`Retry`]: crate::ln::channelmanager::Retry
        /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
        PaymentFailed {
-               /// The id returned by [`ChannelManager::send_payment`] and used with
-               /// [`ChannelManager::abandon_payment`].
+               /// The `payment_id` passed to [`ChannelManager::send_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
-               /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
                payment_id: PaymentId,
                /// The hash that was given to [`ChannelManager::send_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
                payment_hash: PaymentHash,
+               /// The reason the payment failed. This is only `None` for events generated or serialized
+               /// by versions prior to 0.0.115.
+               reason: Option<PaymentFailureReason>,
        },
        /// Indicates that a path for an outbound payment was successful.
        ///
        /// Always generated after [`Event::PaymentSent`] and thus useful for scoring channels. See
        /// [`Event::PaymentSent`] for obtaining the payment preimage.
        PaymentPathSuccessful {
-               /// The id returned by [`ChannelManager::send_payment`].
+               /// The `payment_id` passed to [`ChannelManager::send_payment`].
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
                payment_id: PaymentId,
                /// The hash that was given to [`ChannelManager::send_payment`].
                ///
+               /// This will be `Some` for all payments which completed on LDK 0.0.104 or later.
+               ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
                payment_hash: Option<PaymentHash>,
                /// The payment path that was successful.
                ///
                /// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
-               path: Vec<RouteHop>,
+               path: Path,
        },
        /// Indicates an outbound HTLC we sent failed, likely due to an intermediary node being unable to
        /// handle the HTLC.
@@ -458,8 +518,9 @@ pub enum Event {
        ///
        /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
        PaymentPathFailed {
-               /// The id returned by [`ChannelManager::send_payment`] and used with
-               /// [`ChannelManager::abandon_payment`].
+               /// The `payment_id` passed to [`ChannelManager::send_payment`].
+               ///
+               /// This will be `Some` for all payment paths which failed on LDK 0.0.103 or later.
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
                /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
@@ -478,7 +539,7 @@ pub enum Event {
                /// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph
                failure: PathFailure,
                /// The payment path that failed.
-               path: Vec<RouteHop>,
+               path: Path,
                /// The channel responsible for the failed payment path.
                ///
                /// Note that for route hints or for the first hop in a path this may be an SCID alias and
@@ -504,7 +565,7 @@ pub enum Event {
                /// [`ChannelManager::send_probe`]: crate::ln::channelmanager::ChannelManager::send_probe
                payment_hash: PaymentHash,
                /// The payment path that was successful.
-               path: Vec<RouteHop>,
+               path: Path,
        },
        /// Indicates that a probe payment we sent failed at an intermediary node on the path.
        ProbeFailed {
@@ -517,7 +578,7 @@ pub enum Event {
                /// [`ChannelManager::send_probe`]: crate::ln::channelmanager::ChannelManager::send_probe
                payment_hash: PaymentHash,
                /// The payment path that failed.
-               path: Vec<RouteHop>,
+               path: Path,
                /// The channel responsible for the failed probe.
                ///
                /// Note that for route hints or for the first hop in a path this may be an SCID alias and
@@ -608,12 +669,39 @@ pub enum Event {
                /// The caveat described above the `fee_earned_msat` field applies here as well.
                outbound_amount_forwarded_msat: Option<u64>,
        },
+       /// Used to indicate that a channel with the given `channel_id` is being opened and pending
+       /// confirmation on-chain.
+       ///
+       /// This event is emitted when the funding transaction has been signed and is broadcast to the
+       /// network. For 0conf channels it will be immediately followed by the corresponding
+       /// [`Event::ChannelReady`] event.
+       ChannelPending {
+               /// The `channel_id` of the channel that is pending confirmation.
+               channel_id: [u8; 32],
+               /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
+               /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
+               /// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
+               /// `user_channel_id` will be randomized for an inbound channel.
+               ///
+               /// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel
+               /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
+               /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
+               user_channel_id: u128,
+               /// The `temporary_channel_id` this channel used to be known by during channel establishment.
+               ///
+               /// Will be `None` for channels created prior to LDK version 0.0.115.
+               former_temporary_channel_id: Option<[u8; 32]>,
+               /// The `node_id` of the channel counterparty.
+               counterparty_node_id: PublicKey,
+               /// The outpoint of the channel's funding transaction.
+               funding_txo: OutPoint,
+       },
        /// Used to indicate that a channel with the given `channel_id` is ready to
        /// be used. This event is emitted either when the funding transaction has been confirmed
        /// on-chain, or, in case of a 0conf channel, when both parties have confirmed the channel
        /// establishment.
        ChannelReady {
-               /// The channel_id of the channel that is ready.
+               /// The `channel_id` of the channel that is ready.
                channel_id: [u8; 32],
                /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
                /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
@@ -624,7 +712,7 @@ pub enum Event {
                /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
                /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
                user_channel_id: u128,
-               /// The node_id of the channel counterparty.
+               /// The `node_id` of the channel counterparty.
                counterparty_node_id: PublicKey,
                /// The features that this channel will operate with.
                channel_type: ChannelTypeFeatures,
@@ -632,7 +720,7 @@ pub enum Event {
        /// Used to indicate that a previously opened 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
+               /// 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 `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
@@ -744,7 +832,10 @@ 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::PaymentClaimable { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id, ref via_channel_id, ref via_user_channel_id } => {
+                       &Event::PaymentClaimable { ref payment_hash, ref amount_msat, ref purpose,
+                               ref receiver_node_id, ref via_channel_id, ref via_user_channel_id,
+                               ref claim_deadline, ref onion_fields
+                       } => {
                                1u8.write(writer)?;
                                let mut payment_secret = None;
                                let payment_preimage;
@@ -765,7 +856,9 @@ impl Writeable for Event {
                                        (4, amount_msat, required),
                                        (5, via_user_channel_id, option),
                                        (6, 0u64, required), // user_payment_id required for compatibility with 0.0.103 and earlier
+                                       (7, claim_deadline, option),
                                        (8, payment_preimage, option),
+                                       (9, onion_fields, option),
                                });
                        },
                        &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => {
@@ -795,7 +888,8 @@ impl Writeable for Event {
                                        (1, None::<NetworkUpdate>, option), // network_update in LDK versions prior to 0.0.114
                                        (2, payment_failed_permanently, required),
                                        (3, false, required), // all_paths_failed in LDK versions prior to 0.0.114
-                                       (5, *path, vec_type),
+                                       (4, path.blinded_tail, option),
+                                       (5, path.hops, vec_type),
                                        (7, short_channel_id, option),
                                        (9, None::<RouteParameters>, option), // retry in LDK versions prior to 0.0.115
                                        (11, payment_id, option),
@@ -863,13 +957,15 @@ impl Writeable for Event {
                                write_tlv_fields!(writer, {
                                        (0, payment_id, required),
                                        (2, payment_hash, option),
-                                       (4, *path, vec_type)
+                                       (4, path.hops, vec_type),
+                                       (6, path.blinded_tail, option),
                                })
                        },
-                       &Event::PaymentFailed { ref payment_id, ref payment_hash } => {
+                       &Event::PaymentFailed { ref payment_id, ref payment_hash, ref reason } => {
                                15u8.write(writer)?;
                                write_tlv_fields!(writer, {
                                        (0, payment_id, required),
+                                       (1, reason, option),
                                        (2, payment_hash, required),
                                })
                        },
@@ -892,7 +988,8 @@ impl Writeable for Event {
                                write_tlv_fields!(writer, {
                                        (0, payment_id, required),
                                        (2, payment_hash, required),
-                                       (4, *path, vec_type)
+                                       (4, path.hops, vec_type),
+                                       (6, path.blinded_tail, option),
                                })
                        },
                        &Event::ProbeFailed { ref payment_id, ref payment_hash, ref path, ref short_channel_id } => {
@@ -900,8 +997,9 @@ impl Writeable for Event {
                                write_tlv_fields!(writer, {
                                        (0, payment_id, required),
                                        (2, payment_hash, required),
-                                       (4, *path, vec_type),
+                                       (4, path.hops, vec_type),
                                        (6, short_channel_id, option),
+                                       (8, path.blinded_tail, option),
                                })
                        },
                        &Event::HTLCHandlingFailed { ref prev_channel_id, ref failed_next_destination } => {
@@ -931,6 +1029,16 @@ impl Writeable for Event {
                                        (6, channel_type, required),
                                });
                        },
+                       &Event::ChannelPending { ref channel_id, ref user_channel_id, ref former_temporary_channel_id, ref counterparty_node_id, ref funding_txo } => {
+                               31u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, channel_id, required),
+                                       (2, user_channel_id, required),
+                                       (4, former_temporary_channel_id, required),
+                                       (6, counterparty_node_id, required),
+                                       (8, funding_txo, required),
+                               });
+                       },
                        // Note that, going forward, all new events must only write data inside of
                        // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
                        // data via `write_tlv_fields`.
@@ -953,7 +1061,9 @@ impl MaybeReadable for Event {
                                        let mut receiver_node_id = None;
                                        let mut _user_payment_id = None::<u64>; // For compatibility with 0.0.103 and earlier
                                        let mut via_channel_id = None;
+                                       let mut claim_deadline = None;
                                        let mut via_user_channel_id = None;
+                                       let mut onion_fields = None;
                                        read_tlv_fields!(reader, {
                                                (0, payment_hash, required),
                                                (1, receiver_node_id, option),
@@ -962,7 +1072,9 @@ impl MaybeReadable for Event {
                                                (4, amount_msat, required),
                                                (5, via_user_channel_id, option),
                                                (6, _user_payment_id, option),
+                                               (7, claim_deadline, option),
                                                (8, payment_preimage, option),
+                                               (9, onion_fields, option),
                                        });
                                        let purpose = match payment_secret {
                                                Some(secret) => PaymentPurpose::InvoicePayment {
@@ -979,6 +1091,8 @@ impl MaybeReadable for Event {
                                                purpose,
                                                via_channel_id,
                                                via_user_channel_id,
+                                               claim_deadline,
+                                               onion_fields,
                                        }))
                                };
                                f()
@@ -1016,6 +1130,7 @@ impl MaybeReadable for Event {
                                        let mut payment_hash = PaymentHash([0; 32]);
                                        let mut payment_failed_permanently = false;
                                        let mut network_update = None;
+                                       let mut blinded_tail: Option<BlindedTail> = None;
                                        let mut path: Option<Vec<RouteHop>> = Some(vec![]);
                                        let mut short_channel_id = None;
                                        let mut payment_id = None;
@@ -1024,6 +1139,7 @@ impl MaybeReadable for Event {
                                                (0, payment_hash, required),
                                                (1, network_update, upgradable_option),
                                                (2, payment_failed_permanently, required),
+                                               (4, blinded_tail, option),
                                                (5, path, vec_type),
                                                (7, short_channel_id, option),
                                                (11, payment_id, option),
@@ -1035,7 +1151,7 @@ impl MaybeReadable for Event {
                                                payment_hash,
                                                payment_failed_permanently,
                                                failure,
-                                               path: path.unwrap(),
+                                               path: Path { hops: path.unwrap(), blinded_tail },
                                                short_channel_id,
                                                #[cfg(test)]
                                                error_code,
@@ -1138,18 +1254,16 @@ impl MaybeReadable for Event {
                        },
                        13u8 => {
                                let f = || {
-                                       let mut payment_id = PaymentId([0; 32]);
-                                       let mut payment_hash = None;
-                                       let mut path: Option<Vec<RouteHop>> = Some(vec![]);
-                                       read_tlv_fields!(reader, {
+                                       _init_and_read_tlv_fields!(reader, {
                                                (0, payment_id, required),
                                                (2, payment_hash, option),
                                                (4, path, vec_type),
+                                               (6, blinded_tail, option),
                                        });
                                        Ok(Some(Event::PaymentPathSuccessful {
-                                               payment_id,
+                                               payment_id: payment_id.0.unwrap(),
                                                payment_hash,
-                                               path: path.unwrap(),
+                                               path: Path { hops: path.unwrap(), blinded_tail },
                                        }))
                                };
                                f()
@@ -1158,13 +1272,16 @@ impl MaybeReadable for Event {
                                let f = || {
                                        let mut payment_hash = PaymentHash([0; 32]);
                                        let mut payment_id = PaymentId([0; 32]);
+                                       let mut reason = None;
                                        read_tlv_fields!(reader, {
                                                (0, payment_id, required),
+                                               (1, reason, upgradable_option),
                                                (2, payment_hash, required),
                                        });
                                        Ok(Some(Event::PaymentFailed {
                                                payment_id,
                                                payment_hash,
+                                               reason,
                                        }))
                                };
                                f()
@@ -1196,38 +1313,33 @@ impl MaybeReadable for Event {
                        },
                        21u8 => {
                                let f = || {
-                                       let mut payment_id = PaymentId([0; 32]);
-                                       let mut payment_hash = PaymentHash([0; 32]);
-                                       let mut path: Option<Vec<RouteHop>> = Some(vec![]);
-                                       read_tlv_fields!(reader, {
+                                       _init_and_read_tlv_fields!(reader, {
                                                (0, payment_id, required),
                                                (2, payment_hash, required),
                                                (4, path, vec_type),
+                                               (6, blinded_tail, option),
                                        });
                                        Ok(Some(Event::ProbeSuccessful {
-                                               payment_id,
-                                               payment_hash,
-                                               path: path.unwrap(),
+                                               payment_id: payment_id.0.unwrap(),
+                                               payment_hash: payment_hash.0.unwrap(),
+                                               path: Path { hops: path.unwrap(), blinded_tail },
                                        }))
                                };
                                f()
                        },
                        23u8 => {
                                let f = || {
-                                       let mut payment_id = PaymentId([0; 32]);
-                                       let mut payment_hash = PaymentHash([0; 32]);
-                                       let mut path: Option<Vec<RouteHop>> = Some(vec![]);
-                                       let mut short_channel_id = None;
-                                       read_tlv_fields!(reader, {
+                                       _init_and_read_tlv_fields!(reader, {
                                                (0, payment_id, required),
                                                (2, payment_hash, required),
                                                (4, path, vec_type),
                                                (6, short_channel_id, option),
+                                               (8, blinded_tail, option),
                                        });
                                        Ok(Some(Event::ProbeFailed {
-                                               payment_id,
-                                               payment_hash,
-                                               path: path.unwrap(),
+                                               payment_id: payment_id.0.unwrap(),
+                                               payment_hash: payment_hash.0.unwrap(),
+                                               path: Path { hops: path.unwrap(), blinded_tail },
                                                short_channel_id,
                                        }))
                                };
@@ -1271,6 +1383,31 @@ impl MaybeReadable for Event {
                                };
                                f()
                        },
+                       31u8 => {
+                               let f = || {
+                                       let mut channel_id = [0; 32];
+                                       let mut user_channel_id: u128 = 0;
+                                       let mut former_temporary_channel_id = None;
+                                       let mut counterparty_node_id = RequiredWrapper(None);
+                                       let mut funding_txo = RequiredWrapper(None);
+                                       read_tlv_fields!(reader, {
+                                               (0, channel_id, required),
+                                               (2, user_channel_id, required),
+                                               (4, former_temporary_channel_id, required),
+                                               (6, counterparty_node_id, required),
+                                               (8, funding_txo, required),
+                                       });
+
+                                       Ok(Some(Event::ChannelPending {
+                                               channel_id,
+                                               user_channel_id,
+                                               former_temporary_channel_id,
+                                               counterparty_node_id: counterparty_node_id.0.unwrap(),
+                                               funding_txo: funding_txo.0.unwrap()
+                                       }))
+                               };
+                               f()
+                       },
                        // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
                        // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
                        // reads.