X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fevents.rs;h=4d68d01f6ed9301661145b222cf5b0aea2dba870;hb=30b9d9fbeaa62537beb8d3ea0b2866703d0d7c92;hp=a9687d28802266dfe0aa89868d1cf9aef61e845d;hpb=f1428fdf129ad8a850af8481b2eb6a04119a41ea;p=rust-lightning diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index a9687d28..4d68d01f 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -16,8 +16,8 @@ use crate::chain::keysinterface::SpendableOutputDescriptor; #[cfg(anchors)] -use crate::ln::chan_utils::HTLCOutputInCommitment; -use crate::ln::channelmanager::PaymentId; +use crate::ln::chan_utils::{self, ChannelTransactionParameters, HTLCOutputInCommitment}; +use crate::ln::channelmanager::{InterceptId, PaymentId}; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs; @@ -29,11 +29,15 @@ use crate::routing::router::{RouteHop, RouteParameters}; use bitcoin::{PackedLockTime, Transaction}; #[cfg(anchors)] -use bitcoin::OutPoint; +use bitcoin::{OutPoint, Txid, TxIn, TxOut, Witness}; use bitcoin::blockdata::script::Script; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::PublicKey; +#[cfg(anchors)] +use bitcoin::secp256k1::{self, Secp256k1}; +#[cfg(anchors)] +use bitcoin::secp256k1::ecdsa::Signature; use crate::io; use crate::prelude::*; use core::time::Duration; @@ -42,7 +46,7 @@ use crate::sync::Arc; /// Some information provided on receipt of payment depends on whether the payment received is a /// spontaneous payment or a "conventional" lightning payment that's paying an invoice. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum PaymentPurpose { /// Information for receiving a payment that we generated an invoice for. InvoicePayment { @@ -182,6 +186,12 @@ pub enum HTLCDestination { /// Short channel id we are requesting to forward an HTLC to. requested_forward_scid: u64, }, + /// We couldn't forward to the outgoing scid. An example would be attempting to send a duplicate + /// intercept HTLC. + InvalidForward { + /// Short channel id we are requesting to forward an HTLC to. + requested_forward_scid: u64 + }, /// Failure scenario where an HTLC may have been forwarded to be intended for us, /// but is invalid for some reason, so we reject it. /// @@ -200,12 +210,15 @@ impl_writeable_tlv_based_enum_upgradable!(HTLCDestination, (0, node_id, required), (2, channel_id, required), }, + (1, InvalidForward) => { + (0, requested_forward_scid, required), + }, (2, UnknownNextHop) => { (0, requested_forward_scid, required), }, (4, FailedPayment) => { (0, payment_hash, required), - } + }, ); #[cfg(anchors)] @@ -228,6 +241,99 @@ pub struct AnchorDescriptor { pub outpoint: OutPoint, } +#[cfg(anchors)] +/// A descriptor used to sign for a commitment transaction's HTLC output. +#[derive(Clone, Debug)] +pub struct HTLCDescriptor { + /// A unique identifier used along with `channel_value_satoshis` to re-derive the + /// [`InMemorySigner`] required to sign `input`. + /// + /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner + pub channel_keys_id: [u8; 32], + /// The value in satoshis of the channel we're attempting to spend the anchor output of. This is + /// used along with `channel_keys_id` to re-derive the [`InMemorySigner`] required to sign + /// `input`. + /// + /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner + pub channel_value_satoshis: u64, + /// The necessary channel parameters that need to be provided to the re-derived + /// [`InMemorySigner`] through [`BaseSign::provide_channel_parameters`]. + /// + /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner + /// [`BaseSign::provide_channel_parameters`]: crate::chain::keysinterface::BaseSign::provide_channel_parameters + pub channel_parameters: ChannelTransactionParameters, + /// The txid of the commitment transaction in which the HTLC output lives. + pub commitment_txid: Txid, + /// The number of the commitment transaction in which the HTLC output lives. + pub per_commitment_number: u64, + /// The details of the HTLC as it appears in the commitment transaction. + pub htlc: HTLCOutputInCommitment, + /// The preimage, if `Some`, to claim the HTLC output with. If `None`, the timeout path must be + /// taken. + pub preimage: Option, + /// The counterparty's signature required to spend the HTLC output. + pub counterparty_sig: Signature +} + +#[cfg(anchors)] +impl HTLCDescriptor { + /// Returns the unsigned transaction input spending the HTLC output in the commitment + /// transaction. + pub fn unsigned_tx_input(&self) -> TxIn { + chan_utils::build_htlc_input(&self.commitment_txid, &self.htlc, true /* opt_anchors */) + } + + /// Returns the delayed output created as a result of spending the HTLC output in the commitment + /// transaction. + pub fn tx_output( + &self, per_commitment_point: &PublicKey, secp: &Secp256k1 + ) -> TxOut { + let channel_params = self.channel_parameters.as_holder_broadcastable(); + let broadcaster_keys = channel_params.broadcaster_pubkeys(); + let counterparty_keys = channel_params.countersignatory_pubkeys(); + let broadcaster_delayed_key = chan_utils::derive_public_key( + secp, per_commitment_point, &broadcaster_keys.delayed_payment_basepoint + ); + let counterparty_revocation_key = chan_utils::derive_public_revocation_key( + secp, per_commitment_point, &counterparty_keys.revocation_basepoint + ); + chan_utils::build_htlc_output( + 0 /* feerate_per_kw */, channel_params.contest_delay(), &self.htlc, true /* opt_anchors */, + false /* use_non_zero_fee_anchors */, &broadcaster_delayed_key, &counterparty_revocation_key + ) + } + + /// Returns the witness script of the HTLC output in the commitment transaction. + pub fn witness_script( + &self, per_commitment_point: &PublicKey, secp: &Secp256k1 + ) -> Script { + let channel_params = self.channel_parameters.as_holder_broadcastable(); + let broadcaster_keys = channel_params.broadcaster_pubkeys(); + let counterparty_keys = channel_params.countersignatory_pubkeys(); + let broadcaster_htlc_key = chan_utils::derive_public_key( + secp, per_commitment_point, &broadcaster_keys.htlc_basepoint + ); + let counterparty_htlc_key = chan_utils::derive_public_key( + secp, per_commitment_point, &counterparty_keys.htlc_basepoint + ); + let counterparty_revocation_key = chan_utils::derive_public_revocation_key( + secp, per_commitment_point, &counterparty_keys.revocation_basepoint + ); + chan_utils::get_htlc_redeemscript_with_explicit_keys( + &self.htlc, true /* opt_anchors */, &broadcaster_htlc_key, &counterparty_htlc_key, + &counterparty_revocation_key, + ) + } + + /// Returns the fully signed witness required to spend the HTLC output in the commitment + /// transaction. + pub fn tx_input_witness(&self, signature: &Signature, witness_script: &Script) -> Witness { + chan_utils::build_htlc_input_witness( + signature, &self.counterparty_sig, &self.preimage, witness_script, true /* opt_anchors */ + ) + } +} + #[cfg(anchors)] /// Represents the different types of transactions, originating from LDK, to be bumped. #[derive(Clone, Debug)] @@ -240,14 +346,17 @@ pub enum BumpTransactionEvent { /// with additional inputs to meet the target feerate. Failure to meet the target feerate /// decreases the confirmation odds of the transaction package (which includes the commitment /// and child anchor transactions), possibly resulting in a loss of funds. Once the transaction - /// is constructed, it must be fully signed for and broadcasted by the consumer of the event + /// is constructed, it must be fully signed for and broadcast by the consumer of the event /// along with the `commitment_tx` enclosed. Note that the `commitment_tx` must always be /// broadcast first, as the child anchor transaction depends on it. /// /// The consumer should be able to sign for any of the additional inputs included within the /// child anchor transaction. To sign its anchor input, an [`InMemorySigner`] should be /// re-derived through [`KeysManager::derive_channel_keys`] with the help of - /// [`AnchorDescriptor::channel_keys_id`] and [`AnchorDescriptor::channel_value_satoshis`]. + /// [`AnchorDescriptor::channel_keys_id`] and [`AnchorDescriptor::channel_value_satoshis`]. The + /// anchor input signature can be computed with [`BaseSign::sign_holder_anchor_input`], + /// which can then be provided to [`build_anchor_input_witness`] along with the `funding_pubkey` + /// to obtain the full witness required to spend. /// /// It is possible to receive more than one instance of this event if a valid child anchor /// transaction is never broadcast or is but not with a sufficient fee to be mined. Care should @@ -268,6 +377,8 @@ pub enum BumpTransactionEvent { /// /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner /// [`KeysManager::derive_channel_keys`]: crate::chain::keysinterface::KeysManager::derive_channel_keys + /// [`BaseSign::sign_holder_anchor_input`]: crate::chain::keysinterface::BaseSign::sign_holder_anchor_input + /// [`build_anchor_input_witness`]: crate::ln::chan_utils::build_anchor_input_witness ChannelClose { /// The target feerate that the transaction package, which consists of the commitment /// transaction and the to-be-crafted child anchor transaction, must meet. @@ -286,14 +397,65 @@ pub enum BumpTransactionEvent { /// commitment transaction confirms. pending_htlcs: Vec, }, + /// Indicates that a channel featuring anchor outputs has unilaterally closed on-chain by a + /// holder commitment transaction and its HTLC(s) need to be resolved on-chain. With the + /// zero-HTLC-transaction-fee variant of anchor outputs, the pre-signed HTLC + /// transactions have a zero fee, thus requiring additional inputs and/or outputs to be attached + /// for a timely confirmation within the chain. These additional inputs and/or outputs must be + /// appended to the resulting HTLC transaction to meet the target feerate. Failure to meet the + /// target feerate decreases the confirmation odds of the transaction, possibly resulting in a + /// loss of funds. Once the transaction meets the target feerate, it must be signed for and + /// broadcast by the consumer of the event. + /// + /// The consumer should be able to sign for any of the non-HTLC inputs added to the resulting + /// HTLC transaction. To sign HTLC inputs, an [`InMemorySigner`] should be re-derived through + /// [`KeysManager::derive_channel_keys`] with the help of `channel_keys_id` and + /// `channel_value_satoshis`. Each HTLC input's signature can be computed with + /// [`BaseSign::sign_holder_htlc_transaction`], which can then be provided to + /// [`HTLCDescriptor::tx_input_witness`] to obtain the fully signed witness required to spend. + /// + /// It is possible to receive more than one instance of this event if a valid HTLC transaction + /// is never broadcast or is but not with a sufficient fee to be mined. Care should be taken by + /// the consumer of the event to ensure any future iterations of the HTLC transaction adhere to + /// the [Replace-By-Fee + /// rules](https://github.com/bitcoin/bitcoin/blob/master/doc/policy/mempool-replacements.md) + /// for fee bumps to be accepted into the mempool, and eventually the chain. As the frequency of + /// these events is not user-controlled, users may ignore/drop the event if either they are no + /// longer able to commit external confirmed funds to the HTLC transaction or the fee committed + /// to the HTLC transaction is greater in value than the HTLCs being claimed. + /// + /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner + /// [`KeysManager::derive_channel_keys`]: crate::chain::keysinterface::KeysManager::derive_channel_keys + /// [`BaseSign::sign_holder_htlc_transaction`]: crate::chain::keysinterface::BaseSign::sign_holder_htlc_transaction + /// [`HTLCDescriptor::tx_input_witness`]: HTLCDescriptor::tx_input_witness + HTLCResolution { + target_feerate_sat_per_1000_weight: u32, + htlc_descriptors: Vec, + }, +} + +/// Will be used in [`Event::HTLCIntercepted`] to identify the next hop in the HTLC's path. +/// Currently only used in serialization for the sake of maintaining compatibility. More variants +/// will be added for general-purpose HTLC forward intercepts as well as trampoline forward +/// intercepts in upcoming work. +enum InterceptNextHop { + FakeScid { + requested_next_hop_scid: u64, + }, } +impl_writeable_tlv_based_enum!(InterceptNextHop, + (0, FakeScid) => { + (0, requested_next_hop_scid, required), + }; +); + /// 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 /// them directly as they don't round-trip exactly (for example FundingGenerationReady is never /// written as it makes no sense to respond to it after reconnecting to peers). -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { /// Used to indicate that the client should generate a funding transaction with the given /// parameters and then call [`ChannelManager::funding_transaction_generated`]. @@ -318,29 +480,41 @@ pub enum Event { channel_value_satoshis: u64, /// The script which should be used in the transaction output. output_script: Script, - /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`], or 0 for - /// an inbound channel. + /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`], or a + /// random value for an inbound channel. This may be zero for objects serialized with LDK + /// versions prior to 0.0.113. /// /// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel - user_channel_id: u64, + user_channel_id: u128, }, - /// Indicates we've received (an offer of) money! Just gotta dig out that payment preimage and - /// feed it to [`ChannelManager::claim_funds`] to get it.... + /// Indicates that we've been offered a payment and it needs to be claimed via calling + /// [`ChannelManager::claim_funds`] with the preimage given in [`PaymentPurpose`]. /// /// Note that if the preimage is not known, you should call - /// [`ChannelManager::fail_htlc_backwards`] to free up resources for this HTLC and avoid - /// network congestion. - /// If you fail to call either [`ChannelManager::claim_funds`] or - /// [`ChannelManager::fail_htlc_backwards`] within the HTLC's timeout, the HTLC will be + /// [`ChannelManager::fail_htlc_backwards`] or [`ChannelManager::fail_htlc_backwards_with_reason`] + /// to free up resources for this HTLC and avoid network congestion. + /// If you fail to call either [`ChannelManager::claim_funds`], [`ChannelManager::fail_htlc_backwards`], + /// or [`ChannelManager::fail_htlc_backwards_with_reason`] within the HTLC's timeout, the HTLC will be /// automatically failed. /// /// # Note /// LDK will not stop an inbound payment from being paid multiple times, so multiple - /// `PaymentReceived` events may be generated for the same payment. + /// `PaymentClaimable` events may be generated for the same payment. + /// + /// # Note + /// This event used to be called `PaymentReceived` in LDK versions 0.0.112 and earlier. /// /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds /// [`ChannelManager::fail_htlc_backwards`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards - PaymentReceived { + /// [`ChannelManager::fail_htlc_backwards_with_reason`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards_with_reason + PaymentClaimable { + /// The node that will receive the payment after it has been claimed. + /// This is useful to identify payments received via [phantom nodes]. + /// 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 + receiver_node_id: Option, /// 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, @@ -349,28 +523,39 @@ pub enum Event { /// Information for claiming this received payment, based on whether the purpose of the /// payment is to pay an invoice or to send a spontaneous payment. purpose: PaymentPurpose, + /// The `channel_id` indicating over which channel we received the payment. + via_channel_id: Option<[u8; 32]>, + /// The `user_channel_id` indicating over which channel we received the payment. + via_user_channel_id: Option, }, /// Indicates a payment has been claimed and we've received money! /// /// This most likely occurs when [`ChannelManager::claim_funds`] has been called in response - /// to an [`Event::PaymentReceived`]. However, if we previously crashed during a + /// to an [`Event::PaymentClaimable`]. However, if we previously crashed during a /// [`ChannelManager::claim_funds`] call you may see this event without a corresponding - /// [`Event::PaymentReceived`] event. + /// [`Event::PaymentClaimable`] event. /// /// # Note /// LDK will not stop an inbound payment from being paid multiple times, so multiple - /// `PaymentReceived` events may be generated for the same payment. If you then call - /// [`ChannelManager::claim_funds`] twice for the same [`Event::PaymentReceived`] you may get + /// `PaymentClaimable` events may be generated for the same payment. If you then call + /// [`ChannelManager::claim_funds`] twice for the same [`Event::PaymentClaimable`] you may get /// multiple `PaymentClaimed` events. /// /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds PaymentClaimed { + /// The node that received the payment. + /// This is useful to identify payments which were received via [phantom nodes]. + /// 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 + receiver_node_id: Option, /// The payment hash of the claimed payment. Note that LDK will not stop you from /// registering duplicate payment hashes for inbound payments. payment_hash: PaymentHash, /// The value, in thousandths of a satoshi, that this payment is for. amount_msat: u64, - /// The purpose of this claimed payment, i.e. whether the payment was for an invoice or a + /// The purpose of the claimed payment, i.e. whether the payment was for an invoice or a /// spontaneous payment. purpose: PaymentPurpose, }, @@ -380,11 +565,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 @@ -409,16 +592,16 @@ pub enum Event { /// provide failure information for each MPP part in the payment. /// /// 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`]. @@ -431,11 +614,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`]. /// @@ -446,24 +627,22 @@ 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`]. /// + /// 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`]. @@ -471,8 +650,8 @@ 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. @@ -485,20 +664,6 @@ pub enum Event { /// 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, /// The payment path that failed. path: Vec, @@ -511,12 +676,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, @@ -566,6 +728,38 @@ pub enum Event { /// now + 5*time_forwardable). time_forwardable: Duration, }, + /// Used to indicate that we've intercepted an HTLC forward. This event will only be generated if + /// you've encoded an intercept scid in the receiver's invoice route hints using + /// [`ChannelManager::get_intercept_scid`] and have set [`UserConfig::accept_intercept_htlcs`]. + /// + /// [`ChannelManager::forward_intercepted_htlc`] or + /// [`ChannelManager::fail_intercepted_htlc`] MUST be called in response to this event. See + /// their docs for more information. + /// + /// [`ChannelManager::get_intercept_scid`]: crate::ln::channelmanager::ChannelManager::get_intercept_scid + /// [`UserConfig::accept_intercept_htlcs`]: crate::util::config::UserConfig::accept_intercept_htlcs + /// [`ChannelManager::forward_intercepted_htlc`]: crate::ln::channelmanager::ChannelManager::forward_intercepted_htlc + /// [`ChannelManager::fail_intercepted_htlc`]: crate::ln::channelmanager::ChannelManager::fail_intercepted_htlc + HTLCIntercepted { + /// An id to help LDK identify which HTLC is being forwarded or failed. + intercept_id: InterceptId, + /// The fake scid that was programmed as the next hop's scid, generated using + /// [`ChannelManager::get_intercept_scid`]. + /// + /// [`ChannelManager::get_intercept_scid`]: crate::ln::channelmanager::ChannelManager::get_intercept_scid + requested_next_hop_scid: u64, + /// The payment hash used for this HTLC. + payment_hash: PaymentHash, + /// How many msats were received on the inbound edge of this HTLC. + inbound_amount_msat: u64, + /// How many msats the payer intended to route to the next node. Depending on the reason you are + /// intercepting this payment, you might take a fee by forwarding less than this amount. + /// + /// Note that LDK will NOT check that expected fees were factored into this value. You MUST + /// check that whatever fee you want has been included here or subtract it as required. Further, + /// LDK will not stop you from forwarding more than you received. + expected_outbound_amount_msat: u64, + }, /// Used to indicate that an output which you should know how to spend was confirmed on chain /// and is now spendable. /// Such an output will *not* ever be spent by rust-lightning, and are not at risk of your @@ -612,12 +806,12 @@ pub enum Event { /// 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 0 for an inbound channel. + /// `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: u64, + user_channel_id: u128, /// The node_id of the channel counterparty. counterparty_node_id: PublicKey, /// The features that this channel will operate with. @@ -632,13 +826,14 @@ pub enum Event { /// 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 0 for an inbound channel. - /// This will always be zero for objects serialized with LDK versions prior to 0.0.102. + /// `user_channel_id` will be randomized for inbound channels. + /// This may be zero for inbound channels serialized prior to 0.0.113 and will always be + /// zero for objects serialized with LDK versions prior to 0.0.102. /// /// [`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: u64, + user_channel_id: u128, /// The reason the channel was closed. reason: ClosureReason }, @@ -737,7 +932,7 @@ 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::PaymentReceived { ref payment_hash, ref amount_msat, ref purpose } => { + &Event::PaymentClaimable { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id, ref via_channel_id, ref via_user_channel_id } => { 1u8.write(writer)?; let mut payment_secret = None; let payment_preimage; @@ -752,8 +947,11 @@ impl Writeable for Event { } write_tlv_fields!(writer, { (0, payment_hash, required), + (1, receiver_node_id, option), (2, payment_secret, option), + (3, via_channel_id, option), (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 (8, payment_preimage, option), }); @@ -802,6 +1000,17 @@ impl Writeable for Event { (0, WithoutLength(outputs), required), }); }, + &Event::HTLCIntercepted { requested_next_hop_scid, payment_hash, inbound_amount_msat, expected_outbound_amount_msat, intercept_id } => { + 6u8.write(writer)?; + let intercept_scid = InterceptNextHop::FakeScid { requested_next_hop_scid }; + write_tlv_fields!(writer, { + (0, intercept_id, required), + (2, intercept_scid, required), + (4, payment_hash, required), + (6, inbound_amount_msat, required), + (8, expected_outbound_amount_msat, required), + }); + } &Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id } => { 7u8.write(writer)?; write_tlv_fields!(writer, { @@ -813,10 +1022,16 @@ impl Writeable for Event { }, &Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason } => { 9u8.write(writer)?; + // `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 as two + // separate u64 values. + let user_channel_id_low = *user_channel_id as u64; + let user_channel_id_high = (*user_channel_id >> 64) as u64; write_tlv_fields!(writer, { (0, channel_id, required), - (1, user_channel_id, required), - (2, reason, required) + (1, user_channel_id_low, required), + (2, reason, required), + (3, user_channel_id_high, required), }); }, &Event::DiscardFunding { ref channel_id, ref transaction } => { @@ -846,10 +1061,11 @@ impl Writeable for Event { // We never write the OpenChannelRequest events as, upon disconnection, peers // drop any channels which have not yet exchanged funding_signed. }, - &Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose } => { + &Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id } => { 19u8.write(writer)?; write_tlv_fields!(writer, { (0, payment_hash, required), + (1, receiver_node_id, option), (2, purpose, required), (4, amount_msat, required), }); @@ -882,10 +1098,12 @@ impl Writeable for Event { &Event::BumpTransaction(ref event)=> { 27u8.write(writer)?; match event { - // We never write the ChannelClose events as they'll be replayed upon restarting - // anyway if the commitment transaction remains unconfirmed. + // We never write the ChannelClose|HTLCResolution events as they'll be replayed + // upon restarting anyway if they remain unresolved. BumpTransactionEvent::ChannelClose { .. } => {} + BumpTransactionEvent::HTLCResolution { .. } => {} } + write_tlv_fields!(writer, {}); // Write a length field for forwards compat } &Event::ChannelReady { ref channel_id, ref user_channel_id, ref counterparty_node_id, ref channel_type } => { 29u8.write(writer)?; @@ -915,11 +1133,17 @@ impl MaybeReadable for Event { let mut payment_preimage = None; let mut payment_secret = None; let mut amount_msat = 0; + let mut receiver_node_id = None; let mut _user_payment_id = None::; // For compatibility with 0.0.103 and earlier + let mut via_channel_id = None; + let mut via_user_channel_id = None; read_tlv_fields!(reader, { (0, payment_hash, required), + (1, receiver_node_id, option), (2, payment_secret, option), + (3, via_channel_id, option), (4, amount_msat, required), + (5, via_user_channel_id, option), (6, _user_payment_id, option), (8, payment_preimage, option), }); @@ -931,10 +1155,13 @@ impl MaybeReadable for Event { None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()), None => return Err(msgs::DecodeError::InvalidValue), }; - Ok(Some(Event::PaymentReceived { + Ok(Some(Event::PaymentClaimable { + receiver_node_id, payment_hash, amount_msat, purpose, + via_channel_id, + via_user_channel_id, })) }; f() @@ -1015,6 +1242,30 @@ impl MaybeReadable for Event { }; f() }, + 6u8 => { + let mut payment_hash = PaymentHash([0; 32]); + let mut intercept_id = InterceptId([0; 32]); + let mut requested_next_hop_scid = InterceptNextHop::FakeScid { requested_next_hop_scid: 0 }; + let mut inbound_amount_msat = 0; + let mut expected_outbound_amount_msat = 0; + read_tlv_fields!(reader, { + (0, intercept_id, required), + (2, requested_next_hop_scid, required), + (4, payment_hash, required), + (6, inbound_amount_msat, required), + (8, expected_outbound_amount_msat, required), + }); + let next_scid = match requested_next_hop_scid { + InterceptNextHop::FakeScid { requested_next_hop_scid: scid } => scid + }; + Ok(Some(Event::HTLCIntercepted { + payment_hash, + requested_next_hop_scid: next_scid, + inbound_amount_msat, + expected_outbound_amount_msat, + intercept_id, + })) + }, 7u8 => { let f = || { let mut fee_earned_msat = None; @@ -1035,14 +1286,22 @@ impl MaybeReadable for Event { let f = || { let mut channel_id = [0; 32]; let mut reason = None; - let mut user_channel_id_opt = 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_opt, option), + (1, user_channel_id_low_opt, option), (2, reason, ignorable), + (3, user_channel_id_high_opt, option), }); if reason.is_none() { return Ok(None); } - let user_channel_id = if let Some(id) = user_channel_id_opt { id } else { 0 }; + + // `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 + // as two separate u64 values. + 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() })) }; f() @@ -1101,13 +1360,16 @@ impl MaybeReadable for Event { let mut payment_hash = PaymentHash([0; 32]); let mut purpose = 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), (4, amount_msat, required), }); if purpose.is_none() { return Ok(None); } Ok(Some(Event::PaymentClaimed { + receiver_node_id, payment_hash, purpose: purpose.unwrap(), amount_msat, @@ -1180,7 +1442,7 @@ impl MaybeReadable for Event { 29u8 => { let f = || { let mut channel_id = [0; 32]; - let mut user_channel_id: u64 = 0; + let mut user_channel_id: u128 = 0; let mut counterparty_node_id = OptionDeserWrapper(None); let mut channel_type = OptionDeserWrapper(None); read_tlv_fields!(reader, { @@ -1327,13 +1589,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. @@ -1400,6 +1667,10 @@ pub trait OnionMessageProvider { /// /// Events are processed by passing an [`EventHandler`] to [`process_pending_events`]. /// +/// Implementations of this trait may also feature an async version of event handling, as shown with +/// [`ChannelManager::process_pending_events_async`] and +/// [`ChainMonitor::process_pending_events_async`]. +/// /// # Requirements /// /// When using this trait, [`process_pending_events`] will call [`handle_event`] for each pending @@ -1426,6 +1697,8 @@ pub trait OnionMessageProvider { /// [`handle_event`]: EventHandler::handle_event /// [`ChannelManager::process_pending_events`]: crate::ln::channelmanager::ChannelManager#method.process_pending_events /// [`ChainMonitor::process_pending_events`]: crate::chain::chainmonitor::ChainMonitor#method.process_pending_events +/// [`ChannelManager::process_pending_events_async`]: crate::ln::channelmanager::ChannelManager::process_pending_events_async +/// [`ChainMonitor::process_pending_events_async`]: crate::chain::chainmonitor::ChainMonitor::process_pending_events_async pub trait EventsProvider { /// Processes any events generated since the last call using the given event handler. /// @@ -1434,21 +1707,25 @@ pub trait EventsProvider { } /// A trait implemented for objects handling events from [`EventsProvider`]. +/// +/// An async variation also exists for implementations of [`EventsProvider`] that support async +/// event handling. The async event handler should satisfy the generic bounds: `F: +/// core::future::Future, H: Fn(Event) -> F`. 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 EventHandler for F where F: Fn(&Event) { - fn handle_event(&self, event: &Event) { +impl EventHandler for F where F: Fn(Event) { + fn handle_event(&self, event: Event) { self(event) } } impl EventHandler for Arc { - fn handle_event(&self, event: &Event) { + fn handle_event(&self, event: Event) { self.deref().handle_event(event) } }