X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fevents.rs;h=5bc8a5084f2924706bf812aad46f4c750f851bc0;hb=0512260898c21ae295e9754fec6e635b0a4d92ac;hp=475533c902a372fdb0bea1b86cb0e754dc90fbe4;hpb=b536d01702bf126f97470a48a6be4f3c97057848;p=rust-lightning diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index 475533c9..5bc8a508 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -21,10 +21,10 @@ use crate::ln::channelmanager::{InterceptId, PaymentId}; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs; -use crate::ln::msgs::DecodeError; use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use crate::routing::gossip::NetworkUpdate; -use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, WithoutLength, OptionDeserWrapper}; +use crate::util::errors::APIError; +use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired, WithoutLength}; use crate::routing::router::{RouteHop, RouteParameters}; use bitcoin::{PackedLockTime, Transaction}; @@ -82,6 +82,39 @@ impl_writeable_tlv_based_enum!(PaymentPurpose, (2, SpontaneousPayment) ); +/// When the payment path failure took place and extra details about it. [`PathFailure::OnPath`] may +/// contain a [`NetworkUpdate`] that needs to be applied to the [`NetworkGraph`]. +/// +/// [`NetworkUpdate`]: crate::routing::gossip::NetworkUpdate +/// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum PathFailure { + /// We failed to initially send the payment and no HTLC was committed to. Contains the relevant + /// error. + InitialSend { + /// The error surfaced from initial send. + err: APIError, + }, + /// A hop on the path failed to forward our payment. + OnPath { + /// If present, this [`NetworkUpdate`] should be applied to the [`NetworkGraph`] so that routing + /// decisions can take into account the update. + /// + /// [`NetworkUpdate`]: crate::routing::gossip::NetworkUpdate + /// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph + network_update: Option, + }, +} + +impl_writeable_tlv_based_enum_upgradable!(PathFailure, + (0, OnPath) => { + (0, network_update, upgradable_option), + }, + (2, InitialSend) => { + (0, err, upgradable_required), + }, +); + #[derive(Clone, Debug, PartialEq, Eq)] /// The reason the channel was closed. See individual variants more details. pub enum ClosureReason { @@ -565,11 +598,9 @@ 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`] and used with - /// [`ChannelManager::retry_payment`]. + /// The id returned by [`ChannelManager::send_payment`]. /// /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment - /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment payment_id: Option, /// 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 @@ -591,19 +622,19 @@ pub enum Event { fee_paid_msat: Option, }, /// Indicates an outbound payment failed. Individual [`Event::PaymentPathFailed`] events - /// provide failure information for each MPP part in the payment. + /// provide failure information for each path attempt in the payment, including retries. /// /// This event is provided once there are no further pending HTLCs for the payment and the - /// payment is no longer retryable due to [`ChannelManager::abandon_payment`] having been - /// called for the corresponding payment. + /// payment is no longer retryable, due either to the [`Retry`] provided or + /// [`ChannelManager::abandon_payment`] having been called for the corresponding payment. /// + /// [`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::retry_payment`] and [`ChannelManager::abandon_payment`]. + /// [`ChannelManager::abandon_payment`]. /// /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment - /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment payment_id: PaymentId, /// The hash that was given to [`ChannelManager::send_payment`]. @@ -616,11 +647,9 @@ pub enum Event { /// 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`] and used with - /// [`ChannelManager::retry_payment`]. + /// The id returned by [`ChannelManager::send_payment`]. /// /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment - /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment payment_id: PaymentId, /// The hash that was given to [`ChannelManager::send_payment`]. /// @@ -631,24 +660,21 @@ pub enum Event { /// May contain a closed channel if the HTLC sent along the path was fulfilled on chain. path: Vec, }, - /// Indicates an outbound HTLC we sent failed. Probably some intermediary node dropped - /// something. You may wish to retry with a different route. - /// - /// If you have given up retrying this payment and wish to fail it, you MUST call - /// [`ChannelManager::abandon_payment`] at least once for a given [`PaymentId`] or memory - /// related to payment tracking will leak. + /// Indicates an outbound HTLC we sent failed, likely due to an intermediary node being unable to + /// handle the HTLC. /// /// Note that this does *not* indicate that all paths for an MPP payment have failed, see - /// [`Event::PaymentFailed`] and [`all_paths_failed`]. + /// [`Event::PaymentFailed`]. + /// + /// See [`ChannelManager::abandon_payment`] for giving up on this payment before its retries have + /// been exhausted. /// /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment - /// [`all_paths_failed`]: Self::PaymentPathFailed::all_paths_failed PaymentPathFailed { /// The id returned by [`ChannelManager::send_payment`] and used with - /// [`ChannelManager::retry_payment`] and [`ChannelManager::abandon_payment`]. + /// [`ChannelManager::abandon_payment`]. /// /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment - /// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment payment_id: Option, /// The hash that was given to [`ChannelManager::send_payment`]. @@ -656,35 +682,14 @@ pub enum Event { /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment payment_hash: PaymentHash, /// Indicates the payment was rejected for some reason by the recipient. This implies that - /// the payment has failed, not just the route in question. If this is not set, you may - /// retry the payment via a different route. + /// the payment has failed, not just the route in question. If this is not set, the payment may + /// be retried via a different route. payment_failed_permanently: 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. + /// Extra error details based on the failure type. May contain an update that needs to be + /// applied to the [`NetworkGraph`]. /// /// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph - network_update: Option, - /// 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. - /// - /// Note that if you are retrying individual MPP parts, using this value to determine if a - /// payment has fully failed is race-y. Because multiple failures can happen prior to events - /// being processed, you may retry in response to a first failure, with a second failure - /// (with `all_paths_failed` set) still pending. Then, when the second failure is processed - /// you will see `all_paths_failed` set even though the retry of the first failure still - /// has an associated in-flight HTLC. See (1) for an example of such a failure. - /// - /// If you wish to retry individual MPP parts and learn when a payment has failed, you must - /// call [`ChannelManager::abandon_payment`] and wait for a [`Event::PaymentFailed`] event. - /// - /// (1) - /// - /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment - all_paths_failed: bool, + failure: PathFailure, /// The payment path that failed. path: Vec, /// The channel responsible for the failed payment path. @@ -696,12 +701,9 @@ pub enum Event { /// If this is `Some`, then the corresponding channel should be avoided when the payment is /// retried. May be `None` for older [`Event`] serializations. short_channel_id: Option, - /// Parameters needed to compute a new [`Route`] when retrying the failed payment path. - /// - /// See [`find_route`] for details. + /// Parameters used by LDK to compute a new [`Route`] when retrying the failed payment path. /// /// [`Route`]: crate::routing::router::Route - /// [`find_route`]: crate::routing::router::find_route retry: Option, #[cfg(test)] error_code: Option, @@ -989,8 +991,8 @@ impl Writeable for Event { }); }, &Event::PaymentPathFailed { - ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, - ref all_paths_failed, ref path, ref short_channel_id, ref retry, + ref payment_id, ref payment_hash, ref payment_failed_permanently, ref failure, + ref path, ref short_channel_id, ref retry, #[cfg(test)] ref error_code, #[cfg(test)] @@ -1003,13 +1005,14 @@ impl Writeable for Event { error_data.write(writer)?; write_tlv_fields!(writer, { (0, payment_hash, required), - (1, network_update, option), + (1, None::, option), // network_update in LDK versions prior to 0.0.114 (2, payment_failed_permanently, required), - (3, all_paths_failed, required), + (3, false, required), // all_paths_failed in LDK versions prior to 0.0.114 (5, *path, vec_type), (7, short_channel_id, option), (9, retry, option), (11, payment_id, option), + (13, failure, required), }); }, &Event::PendingHTLCsForwardable { time_forwardable: _ } => { @@ -1222,27 +1225,27 @@ impl MaybeReadable for Event { let mut payment_hash = PaymentHash([0; 32]); let mut payment_failed_permanently = false; let mut network_update = None; - let mut all_paths_failed = Some(true); let mut path: Option> = Some(vec![]); let mut short_channel_id = None; let mut retry = None; let mut payment_id = None; + let mut failure_opt = None; read_tlv_fields!(reader, { (0, payment_hash, required), - (1, network_update, ignorable), + (1, network_update, upgradable_option), (2, payment_failed_permanently, required), - (3, all_paths_failed, option), (5, path, vec_type), (7, short_channel_id, option), (9, retry, option), (11, payment_id, option), + (13, failure_opt, upgradable_option), }); + let failure = failure_opt.unwrap_or_else(|| PathFailure::OnPath { network_update }); Ok(Some(Event::PaymentPathFailed { payment_id, payment_hash, payment_failed_permanently, - network_update, - all_paths_failed: all_paths_failed.unwrap(), + failure, path: path.unwrap(), short_channel_id, retry, @@ -1308,16 +1311,15 @@ impl MaybeReadable for Event { 9u8 => { let f = || { let mut channel_id = [0; 32]; - let mut reason = None; + let mut reason = UpgradableRequired(None); let mut user_channel_id_low_opt: Option = None; let mut user_channel_id_high_opt: Option = None; read_tlv_fields!(reader, { (0, channel_id, required), (1, user_channel_id_low_opt, option), - (2, reason, ignorable), + (2, reason, upgradable_required), (3, user_channel_id_high_opt, option), }); - if reason.is_none() { return Ok(None); } // `user_channel_id` used to be a single u64 value. In order to remain // backwards compatible with versions prior to 0.0.113, the u128 is serialized @@ -1325,7 +1327,7 @@ impl MaybeReadable for Event { let user_channel_id = (user_channel_id_low_opt.unwrap_or(0) as u128) + ((user_channel_id_high_opt.unwrap_or(0) as u128) << 64); - Ok(Some(Event::ChannelClosed { channel_id, user_channel_id, reason: reason.unwrap() })) + Ok(Some(Event::ChannelClosed { channel_id, user_channel_id, reason: _init_tlv_based_struct_field!(reason, upgradable_required) })) }; f() }, @@ -1381,20 +1383,19 @@ impl MaybeReadable for Event { 19u8 => { let f = || { let mut payment_hash = PaymentHash([0; 32]); - let mut purpose = None; + let mut purpose = UpgradableRequired(None); let mut amount_msat = 0; let mut receiver_node_id = None; read_tlv_fields!(reader, { (0, payment_hash, required), (1, receiver_node_id, option), - (2, purpose, ignorable), + (2, purpose, upgradable_required), (4, amount_msat, required), }); - if purpose.is_none() { return Ok(None); } Ok(Some(Event::PaymentClaimed { receiver_node_id, payment_hash, - purpose: purpose.unwrap(), + purpose: _init_tlv_based_struct_field!(purpose, upgradable_required), amount_msat, })) }; @@ -1442,22 +1443,15 @@ impl MaybeReadable for Event { 25u8 => { let f = || { let mut prev_channel_id = [0; 32]; - let mut failed_next_destination_opt = None; + let mut failed_next_destination_opt = UpgradableRequired(None); read_tlv_fields!(reader, { (0, prev_channel_id, required), - (2, failed_next_destination_opt, ignorable), + (2, failed_next_destination_opt, upgradable_required), }); - if let Some(failed_next_destination) = failed_next_destination_opt { - Ok(Some(Event::HTLCHandlingFailed { - prev_channel_id, - failed_next_destination, - })) - } else { - // If we fail to read a `failed_next_destination` assume it's because - // `MaybeReadable::read` returned `Ok(None)`, though it's also possible we - // were simply missing the field. - Ok(None) - } + Ok(Some(Event::HTLCHandlingFailed { + prev_channel_id, + failed_next_destination: _init_tlv_based_struct_field!(failed_next_destination_opt, upgradable_required), + })) }; f() }, @@ -1466,8 +1460,8 @@ impl MaybeReadable for Event { let f = || { let mut channel_id = [0; 32]; let mut user_channel_id: u128 = 0; - let mut counterparty_node_id = OptionDeserWrapper(None); - let mut channel_type = OptionDeserWrapper(None); + let mut counterparty_node_id = RequiredWrapper(None); + let mut channel_type = RequiredWrapper(None); read_tlv_fields!(reader, { (0, channel_id, required), (2, user_channel_id, required), @@ -1612,13 +1606,18 @@ pub enum MessageSendEvent { /// The channel_announcement which should be sent. msg: msgs::ChannelAnnouncement, /// The followup channel_update which should be sent. - update_msg: msgs::ChannelUpdate, + update_msg: Option, }, /// Used to indicate that a channel_update should be broadcast to all peers. BroadcastChannelUpdate { /// The channel_update which should be sent. msg: msgs::ChannelUpdate, }, + /// Used to indicate that a node_announcement should be broadcast to all peers. + BroadcastNodeAnnouncement { + /// The node_announcement which should be sent. + msg: msgs::NodeAnnouncement, + }, /// 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.