pub use bump_transaction::BumpTransactionEvent;
+use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext, PaymentContextRef};
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;
-use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
+use crate::ln::types::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
+use crate::chain::transaction;
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::{BlindedTail, Path, RouteHop, RouteParameters};
-use bitcoin::{PackedLockTime, Transaction, OutPoint};
-use bitcoin::blockdata::script::Script;
+use bitcoin::{Transaction, OutPoint};
+use bitcoin::blockdata::locktime::absolute::LockTime;
+use bitcoin::blockdata::script::ScriptBuf;
use bitcoin::hashes::Hash;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::PublicKey;
use crate::io;
-use crate::prelude::*;
use core::time::Duration;
use core::ops::Deref;
use crate::sync::Arc;
+#[allow(unused_imports)]
+use crate::prelude::*;
+
/// 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, PartialEq, Eq)]
pub enum PaymentPurpose {
- /// Information for receiving a payment that we generated an invoice for.
- InvoicePayment {
+ /// A payment for a BOLT 11 invoice.
+ Bolt11InvoicePayment {
/// The preimage to the payment_hash, if the payment hash (and secret) were fetched via
- /// [`ChannelManager::create_inbound_payment`]. If provided, this can be handed directly to
- /// [`ChannelManager::claim_funds`].
+ /// [`ChannelManager::create_inbound_payment`]. When handling [`Event::PaymentClaimable`],
+ /// this can be passed directly to [`ChannelManager::claim_funds`] to claim the payment. No
+ /// action is needed when seen in [`Event::PaymentClaimed`].
///
/// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
/// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
/// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
payment_secret: PaymentSecret,
},
+ /// A payment for a BOLT 12 [`Offer`].
+ ///
+ /// [`Offer`]: crate::offers::offer::Offer
+ Bolt12OfferPayment {
+ /// The preimage to the payment hash. When handling [`Event::PaymentClaimable`], this can be
+ /// passed directly to [`ChannelManager::claim_funds`], if provided. No action is needed
+ /// when seen in [`Event::PaymentClaimed`].
+ ///
+ /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+ payment_preimage: Option<PaymentPreimage>,
+ /// The secret used to authenticate the sender to the recipient, preventing a number of
+ /// de-anonymization attacks while routing a payment.
+ ///
+ /// See [`PaymentPurpose::Bolt11InvoicePayment::payment_secret`] for further details.
+ payment_secret: PaymentSecret,
+ /// The context of the payment such as information about the corresponding [`Offer`] and
+ /// [`InvoiceRequest`].
+ ///
+ /// [`Offer`]: crate::offers::offer::Offer
+ /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
+ payment_context: Bolt12OfferContext,
+ },
+ /// A payment for a BOLT 12 [`Refund`].
+ ///
+ /// [`Refund`]: crate::offers::refund::Refund
+ Bolt12RefundPayment {
+ /// The preimage to the payment hash. When handling [`Event::PaymentClaimable`], this can be
+ /// passed directly to [`ChannelManager::claim_funds`], if provided. No action is needed
+ /// when seen in [`Event::PaymentClaimed`].
+ ///
+ /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+ payment_preimage: Option<PaymentPreimage>,
+ /// The secret used to authenticate the sender to the recipient, preventing a number of
+ /// de-anonymization attacks while routing a payment.
+ ///
+ /// See [`PaymentPurpose::Bolt11InvoicePayment::payment_secret`] for further details.
+ payment_secret: PaymentSecret,
+ /// The context of the payment such as information about the corresponding [`Refund`].
+ ///
+ /// [`Refund`]: crate::offers::refund::Refund
+ payment_context: Bolt12RefundContext,
+ },
/// Because this is a spontaneous payment, the payer generated their own preimage rather than us
/// (the payee) providing a preimage.
SpontaneousPayment(PaymentPreimage),
}
+impl PaymentPurpose {
+ /// Returns the preimage for this payment, if it is known.
+ pub fn preimage(&self) -> Option<PaymentPreimage> {
+ match self {
+ PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => *payment_preimage,
+ PaymentPurpose::Bolt12OfferPayment { payment_preimage, .. } => *payment_preimage,
+ PaymentPurpose::Bolt12RefundPayment { payment_preimage, .. } => *payment_preimage,
+ PaymentPurpose::SpontaneousPayment(preimage) => Some(*preimage),
+ }
+ }
+
+ pub(crate) fn is_keysend(&self) -> bool {
+ match self {
+ PaymentPurpose::Bolt11InvoicePayment { .. } => false,
+ PaymentPurpose::Bolt12OfferPayment { .. } => false,
+ PaymentPurpose::Bolt12RefundPayment { .. } => false,
+ PaymentPurpose::SpontaneousPayment(..) => true,
+ }
+ }
+
+ pub(crate) fn from_parts(
+ payment_preimage: Option<PaymentPreimage>, payment_secret: PaymentSecret,
+ payment_context: Option<PaymentContext>,
+ ) -> Self {
+ match payment_context {
+ Some(PaymentContext::Unknown(_)) | None => {
+ PaymentPurpose::Bolt11InvoicePayment {
+ payment_preimage,
+ payment_secret,
+ }
+ },
+ Some(PaymentContext::Bolt12Offer(context)) => {
+ PaymentPurpose::Bolt12OfferPayment {
+ payment_preimage,
+ payment_secret,
+ payment_context: context,
+ }
+ },
+ Some(PaymentContext::Bolt12Refund(context)) => {
+ PaymentPurpose::Bolt12RefundPayment {
+ payment_preimage,
+ payment_secret,
+ payment_context: context,
+ }
+ },
+ }
+ }
+}
+
impl_writeable_tlv_based_enum!(PaymentPurpose,
- (0, InvoicePayment) => {
+ (0, Bolt11InvoicePayment) => {
(0, payment_preimage, option),
(2, payment_secret, required),
- };
+ },
+ (4, Bolt12OfferPayment) => {
+ (0, payment_preimage, option),
+ (2, payment_secret, required),
+ (4, payment_context, required),
+ },
+ (6, Bolt12RefundPayment) => {
+ (0, payment_preimage, option),
+ (2, payment_secret, required),
+ (4, payment_context, required),
+ },
+ ;
(2, SpontaneousPayment)
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClaimedHTLC {
/// The `channel_id` of the channel over which the HTLC was received.
- pub channel_id: [u8; 32],
+ pub channel_id: ChannelId,
/// The `user_channel_id` of the channel over which the HTLC was received. This is the value
/// passed in to [`ChannelManager::create_channel`] for outbound channels, or to
/// [`ChannelManager::accept_inbound_channel`] for inbound channels if
pub cltv_expiry: u32,
/// The amount (in msats) of this part of an MPP.
pub value_msat: u64,
+ /// The extra fee our counterparty skimmed off the top of this HTLC, if any.
+ ///
+ /// This value will always be 0 for [`ClaimedHTLC`]s serialized with LDK versions prior to
+ /// 0.0.119.
+ pub counterparty_skimmed_fee_msat: u64,
}
impl_writeable_tlv_based!(ClaimedHTLC, {
(0, channel_id, required),
+ (1, counterparty_skimmed_fee_msat, (default_value, 0u64)),
(2, user_channel_id, required),
(4, cltv_expiry, required),
(6, value_msat, required),
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,
+ ///
+ /// This was only set in versions of LDK prior to 0.0.122.
+ // Can be removed once we disallow downgrading to 0.0.121
+ LegacyCooperativeClosure,
+ /// The channel was closed after negotiating a cooperative close and we've now broadcasted
+ /// the cooperative close transaction. This indicates that the shutdown was initiated by our
+ /// counterparty.
+ ///
+ /// In rare cases where we initiated closure immediately prior to shutting down without
+ /// persisting, this value may be provided for channels we initiated closure for.
+ CounterpartyInitiatedCooperativeClosure,
+ /// The channel was closed after negotiating a cooperative close and we've now broadcasted
+ /// the cooperative close transaction. This indicates that the shutdown was initiated by us.
+ LocallyInitiatedCooperativeClosure,
/// 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`.
/// The counterparty requested a cooperative close of a channel that had not been funded yet.
/// The channel has been immediately closed.
CounterpartyCoopClosedUnfundedChannel,
+ /// Another channel in the same funding batch closed before the funding transaction
+ /// was ready to be broadcast.
+ FundingBatchClosure,
+ /// One of our HTLCs timed out in a channel, causing us to force close the channel.
+ HTLCsTimedOut,
}
impl core::fmt::Display for ClosureReason {
ClosureReason::CounterpartyForceClosed { peer_msg } => {
f.write_fmt(format_args!("counterparty force-closed with message: {}", peer_msg))
},
- ClosureReason::HolderForceClosed => f.write_str("user manually force-closed the channel"),
- ClosureReason::CooperativeClosure => f.write_str("the channel was cooperatively closed"),
+ ClosureReason::HolderForceClosed => f.write_str("user force-closed the channel"),
+ ClosureReason::LegacyCooperativeClosure => f.write_str("the channel was cooperatively closed"),
+ ClosureReason::CounterpartyInitiatedCooperativeClosure => f.write_str("the channel was cooperatively closed by our peer"),
+ ClosureReason::LocallyInitiatedCooperativeClosure => f.write_str("the channel was cooperatively closed by us"),
ClosureReason::CommitmentTxConfirmed => f.write_str("commitment or closing transaction was confirmed on chain."),
ClosureReason::FundingTimedOut => write!(f, "funding transaction failed to confirm within {} blocks", FUNDING_CONF_DEADLINE_BLOCKS),
ClosureReason::ProcessingError { err } => {
ClosureReason::DisconnectedPeer => f.write_str("the peer disconnected prior to the channel being funded"),
ClosureReason::OutdatedChannelManager => f.write_str("the ChannelManager read from disk was stale compared to ChannelMonitor(s)"),
ClosureReason::CounterpartyCoopClosedUnfundedChannel => f.write_str("the peer requested the unfunded channel be closed"),
+ ClosureReason::FundingBatchClosure => f.write_str("another channel in the same funding batch closed"),
+ ClosureReason::HTLCsTimedOut => f.write_str("htlcs on the channel timed out"),
}
}
}
(1, FundingTimedOut) => {},
(2, HolderForceClosed) => {},
(6, CommitmentTxConfirmed) => {},
- (4, CooperativeClosure) => {},
+ (4, LegacyCooperativeClosure) => {},
(8, ProcessingError) => { (1, err, required) },
(10, DisconnectedPeer) => {},
(12, OutdatedChannelManager) => {},
(13, CounterpartyCoopClosedUnfundedChannel) => {},
+ (15, FundingBatchClosure) => {},
+ (17, CounterpartyInitiatedCooperativeClosure) => {},
+ (19, LocallyInitiatedCooperativeClosure) => {},
+ (21, HTLCsTimedOut) => {},
);
/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`].
/// counterparty node information.
node_id: Option<PublicKey>,
/// The outgoing `channel_id` between us and the next node.
- channel_id: [u8; 32],
+ channel_id: ChannelId,
},
/// Scenario where we are unsure of the next node to forward the HTLC to.
UnknownNextHop {
/// Short channel id we are requesting to forward an HTLC to.
requested_forward_scid: u64
},
+ /// We couldn't decode the incoming onion to obtain the forwarding details.
+ InvalidOnion,
/// Failure scenario where an HTLC may have been forwarded to be intended for us,
/// but is invalid for some reason, so we reject it.
///
(2, UnknownNextHop) => {
(0, requested_forward_scid, required),
},
+ (3, InvalidOnion) => {},
(4, FailedPayment) => {
(0, payment_hash, required),
},
/// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time
PaymentExpired,
/// We failed to find a route while retrying the payment.
+ ///
+ /// Note that this generally indicates that we've exhausted the available set of possible
+ /// routes - we tried the payment over a few routes but were not able to find any further
+ /// candidate routes beyond those.
RouteNotFound,
/// This error should generally never happen. This likely means that there is a problem with
/// your router.
/// [`ChannelManager::funding_transaction_generated`].
///
/// [`ChannelManager::funding_transaction_generated`]: crate::ln::channelmanager::ChannelManager::funding_transaction_generated
- temporary_channel_id: [u8; 32],
+ temporary_channel_id: ChannelId,
/// The counterparty's node_id, which you'll need to pass back into
/// [`ChannelManager::funding_transaction_generated`].
///
/// The value, in satoshis, that the output should have.
channel_value_satoshis: u64,
/// The script which should be used in the transaction output.
- output_script: Script,
+ output_script: ScriptBuf,
/// 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
/// 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]>,
+ via_channel_id: Option<ChannelId>,
/// 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
/// serialized prior to LDK version 0.0.117.
sender_intended_total_msat: Option<u64>,
},
+ /// Indicates that a peer connection with a node is needed in order to send an [`OnionMessage`].
+ ///
+ /// Typically, this happens when a [`MessageRouter`] is unable to find a complete path to a
+ /// [`Destination`]. Once a connection is established, any messages buffered by an
+ /// [`OnionMessageHandler`] may be sent.
+ ///
+ /// This event will not be generated for onion message forwards; only for sends including
+ /// replies. Handlers should connect to the node otherwise any buffered messages may be lost.
+ ///
+ /// [`OnionMessage`]: msgs::OnionMessage
+ /// [`MessageRouter`]: crate::onion_message::messenger::MessageRouter
+ /// [`Destination`]: crate::onion_message::messenger::Destination
+ /// [`OnionMessageHandler`]: crate::ln::msgs::OnionMessageHandler
+ ConnectionNeeded {
+ /// The node id for the node needing a connection.
+ node_id: PublicKey,
+ /// Sockets for connecting to the node.
+ addresses: Vec<msgs::SocketAddress>,
+ },
+ /// Indicates a request for an invoice failed to yield a response in a reasonable amount of time
+ /// or was explicitly abandoned by [`ChannelManager::abandon_payment`]. This may be for an
+ /// [`InvoiceRequest`] sent for an [`Offer`] or for a [`Refund`] that hasn't been redeemed.
+ ///
+ /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
+ /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
+ /// [`Offer`]: crate::offers::offer::Offer
+ /// [`Refund`]: crate::offers::refund::Refund
+ InvoiceRequestFailed {
+ /// The `payment_id` to have been associated with payment for the requested invoice.
+ payment_id: PaymentId,
+ },
/// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target
/// and we got back the payment preimage for it).
///
},
/// 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
+ ///
+ /// Such an output will *never* be spent directly by LDK, and are not at risk of your
/// counterparty spending them due to some kind of timeout. Thus, you need to store them
/// somewhere and spend them when you create on-chain transactions.
+ ///
+ /// You may hand them to the [`OutputSweeper`] utility which will store and (re-)generate spending
+ /// transactions for you.
+ ///
+ /// [`OutputSweeper`]: crate::util::sweep::OutputSweeper
SpendableOutputs {
/// The outputs which you should store as spendable by you.
outputs: Vec<SpendableOutputDescriptor>,
+ /// The `channel_id` indicating which channel the spendable outputs belong to.
+ ///
+ /// This will always be `Some` for events generated by LDK versions 0.0.117 and above.
+ channel_id: Option<ChannelId>,
},
/// This event is generated when a payment has been successfully forwarded through us and a
/// forwarding fee earned.
PaymentForwarded {
- /// The incoming channel between the previous node and us. This is only `None` for events
- /// generated or serialized by versions prior to 0.0.107.
- prev_channel_id: Option<[u8; 32]>,
- /// The outgoing channel between the next node and us. This is only `None` for events
- /// generated or serialized by versions prior to 0.0.107.
- next_channel_id: Option<[u8; 32]>,
- /// The fee, in milli-satoshis, which was earned as a result of the payment.
+ /// The channel id of the incoming channel between the previous node and us.
+ ///
+ /// This is only `None` for events generated or serialized by versions prior to 0.0.107.
+ prev_channel_id: Option<ChannelId>,
+ /// The channel id of the outgoing channel between the next node and us.
+ ///
+ /// This is only `None` for events generated or serialized by versions prior to 0.0.107.
+ next_channel_id: Option<ChannelId>,
+ /// The `user_channel_id` of the incoming channel between the previous node and us.
+ ///
+ /// This is only `None` for events generated or serialized by versions prior to 0.0.122.
+ prev_user_channel_id: Option<u128>,
+ /// The `user_channel_id` of the outgoing channel between the next node and us.
+ ///
+ /// This will be `None` if the payment was settled via an on-chain transaction. See the
+ /// caveat described for the `total_fee_earned_msat` field. Moreover it will be `None` for
+ /// events generated or serialized by versions prior to 0.0.122.
+ next_user_channel_id: Option<u128>,
+ /// The total fee, in milli-satoshis, which was earned as a result of the payment.
///
/// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC
/// was pending, the amount the next hop claimed will have been rounded down to the nearest
/// If the channel which sent us the payment has been force-closed, we will claim the funds
/// via an on-chain transaction. In that case we do not yet know the on-chain transaction
/// fees which we will spend and will instead set this to `None`. It is possible duplicate
- /// `PaymentForwarded` events are generated for the same payment iff `fee_earned_msat` is
+ /// `PaymentForwarded` events are generated for the same payment iff `total_fee_earned_msat` is
/// `None`.
- fee_earned_msat: Option<u64>,
+ total_fee_earned_msat: Option<u64>,
+ /// The share of the total fee, in milli-satoshis, which was withheld in addition to the
+ /// forwarding fee.
+ ///
+ /// This will only be `Some` if we forwarded an intercepted HTLC with less than the
+ /// expected amount. This means our counterparty accepted to receive less than the invoice
+ /// amount, e.g., by claiming the payment featuring a corresponding
+ /// [`PaymentClaimable::counterparty_skimmed_fee_msat`].
+ ///
+ /// Will also always be `None` for events serialized with LDK prior to version 0.0.122.
+ ///
+ /// The caveat described above the `total_fee_earned_msat` field applies here as well.
+ ///
+ /// [`PaymentClaimable::counterparty_skimmed_fee_msat`]: Self::PaymentClaimable::counterparty_skimmed_fee_msat
+ skimmed_fee_msat: Option<u64>,
/// If this is `true`, the forwarded HTLC was claimed by our counterparty via an on-chain
/// transaction.
claim_from_onchain_tx: bool,
/// The final amount forwarded, in milli-satoshis, after the fee is deducted.
///
- /// The caveat described above the `fee_earned_msat` field applies here as well.
+ /// The caveat described above the `total_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
/// [`Event::ChannelReady`] event.
ChannelPending {
/// The `channel_id` of the channel that is pending confirmation.
- channel_id: [u8; 32],
+ channel_id: ChannelId,
/// 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
/// 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]>,
+ former_temporary_channel_id: Option<ChannelId>,
/// The `node_id` of the channel counterparty.
counterparty_node_id: PublicKey,
/// The outpoint of the channel's funding transaction.
funding_txo: OutPoint,
+ /// The features that this channel will operate with.
+ ///
+ /// Will be `None` for channels created prior to LDK version 0.0.122.
+ channel_type: Option<ChannelTypeFeatures>,
},
/// 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
/// establishment.
ChannelReady {
/// The `channel_id` of the channel that is ready.
- channel_id: [u8; 32],
+ channel_id: ChannelId,
/// 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
/// The features that this channel will operate with.
channel_type: ChannelTypeFeatures,
},
- /// Used to indicate that a previously opened channel with the given `channel_id` is in the
- /// process of closure.
+ /// Used to indicate that a channel that got past the initial handshake with the given `channel_id` is in the
+ /// process of closure. This includes previously opened channels, and channels that time out from not being funded.
///
/// Note that this event is only triggered for accepted channels: if the
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true and the channel is
///
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
- ChannelClosed {
+ 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],
+ channel_id: ChannelId,
/// 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
///
/// This field will be `None` for objects serialized prior to LDK 0.0.117.
channel_capacity_sats: Option<u64>,
+ /// The original channel funding TXO; this helps checking for the existence and confirmation
+ /// status of the closing tx.
+ /// Note that for instances serialized in v0.0.119 or prior this will be missing (None).
+ channel_funding_txo: Option<transaction::OutPoint>,
},
/// Used to indicate to the user that they can abandon the funding transaction and recycle the
/// inputs for another purpose.
+ ///
+ /// This event is not guaranteed to be generated for channels that are closed due to a restart.
DiscardFunding {
/// The channel_id of the channel which has been closed.
- channel_id: [u8; 32],
+ channel_id: ChannelId,
/// The full transaction received from the user
transaction: Transaction
},
///
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
- temporary_channel_id: [u8; 32],
+ temporary_channel_id: ChannelId,
/// The node_id of the counterparty requesting to open the channel.
///
/// When responding to the request, the `counterparty_node_id` should be passed
/// requirements (i.e. insufficient fees paid, or a CLTV that is too soon).
HTLCHandlingFailed {
/// The channel over which the HTLC was received.
- prev_channel_id: [u8; 32],
+ prev_channel_id: ChannelId,
/// Destination of the HTLC that failed to be processed.
failed_next_destination: HTLCDestination,
},
///
/// [`ChannelHandshakeConfig::negotiate_anchors_zero_fee_htlc_tx`]: crate::util::config::ChannelHandshakeConfig::negotiate_anchors_zero_fee_htlc_tx
BumpTransaction(BumpTransactionEvent),
+ /// We received an onion message that is intended to be forwarded to a peer
+ /// that is currently offline. This event will only be generated if the
+ /// `OnionMessenger` was initialized with
+ /// [`OnionMessenger::new_with_offline_peer_interception`], see its docs.
+ ///
+ /// [`OnionMessenger::new_with_offline_peer_interception`]: crate::onion_message::messenger::OnionMessenger::new_with_offline_peer_interception
+ OnionMessageIntercepted {
+ /// The node id of the offline peer.
+ peer_node_id: PublicKey,
+ /// The onion message intended to be forwarded to `peer_node_id`.
+ message: msgs::OnionMessage,
+ },
+ /// Indicates that an onion message supporting peer has come online and it may
+ /// be time to forward any onion messages that were previously intercepted for
+ /// them. This event will only be generated if the `OnionMessenger` was
+ /// initialized with
+ /// [`OnionMessenger::new_with_offline_peer_interception`], see its docs.
+ ///
+ /// [`OnionMessenger::new_with_offline_peer_interception`]: crate::onion_message::messenger::OnionMessenger::new_with_offline_peer_interception
+ OnionMessagePeerConnected {
+ /// The node id of the peer we just connected to, who advertises support for
+ /// onion messages.
+ peer_node_id: PublicKey,
+ }
}
impl Writeable for Event {
1u8.write(writer)?;
let mut payment_secret = None;
let payment_preimage;
+ let mut payment_context = None;
match &purpose {
- PaymentPurpose::InvoicePayment { payment_preimage: preimage, payment_secret: secret } => {
+ PaymentPurpose::Bolt11InvoicePayment {
+ payment_preimage: preimage, payment_secret: secret
+ } => {
payment_secret = Some(secret);
payment_preimage = *preimage;
},
+ PaymentPurpose::Bolt12OfferPayment {
+ payment_preimage: preimage, payment_secret: secret, payment_context: context
+ } => {
+ payment_secret = Some(secret);
+ payment_preimage = *preimage;
+ payment_context = Some(PaymentContextRef::Bolt12Offer(context));
+ },
+ PaymentPurpose::Bolt12RefundPayment {
+ payment_preimage: preimage, payment_secret: secret, payment_context: context
+ } => {
+ payment_secret = Some(secret);
+ payment_preimage = *preimage;
+ payment_context = Some(PaymentContextRef::Bolt12Refund(context));
+ },
PaymentPurpose::SpontaneousPayment(preimage) => {
payment_preimage = Some(*preimage);
}
(8, payment_preimage, option),
(9, onion_fields, option),
(10, skimmed_fee_opt, option),
+ (11, payment_context, option),
});
},
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => {
// Note that we now ignore these on the read end as we'll re-generate them in
// ChannelManager, we write them here only for backwards compatibility.
},
- &Event::SpendableOutputs { ref outputs } => {
+ &Event::SpendableOutputs { ref outputs, channel_id } => {
5u8.write(writer)?;
write_tlv_fields!(writer, {
(0, WithoutLength(outputs), required),
+ (1, channel_id, option),
});
},
&Event::HTLCIntercepted { requested_next_hop_scid, payment_hash, inbound_amount_msat, expected_outbound_amount_msat, intercept_id } => {
});
}
&Event::PaymentForwarded {
- fee_earned_msat, prev_channel_id, claim_from_onchain_tx,
- next_channel_id, outbound_amount_forwarded_msat
+ prev_channel_id, next_channel_id, prev_user_channel_id, next_user_channel_id,
+ total_fee_earned_msat, skimmed_fee_msat, claim_from_onchain_tx,
+ outbound_amount_forwarded_msat,
} => {
7u8.write(writer)?;
write_tlv_fields!(writer, {
- (0, fee_earned_msat, option),
+ (0, total_fee_earned_msat, option),
(1, prev_channel_id, option),
(2, claim_from_onchain_tx, required),
(3, next_channel_id, option),
(5, outbound_amount_forwarded_msat, option),
+ (7, skimmed_fee_msat, option),
+ (9, prev_user_channel_id, option),
+ (11, next_user_channel_id, option),
});
},
&Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason,
- ref counterparty_node_id, ref channel_capacity_sats
+ ref counterparty_node_id, ref channel_capacity_sats, ref channel_funding_txo
} => {
9u8.write(writer)?;
// `user_channel_id` used to be a single u64 value. In order to remain backwards
(3, user_channel_id_high, required),
(5, counterparty_node_id, option),
(7, channel_capacity_sats, option),
+ (9, channel_funding_txo, option),
});
},
&Event::DiscardFunding { ref channel_id, ref transaction } => {
(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 } => {
+ &Event::ChannelPending { ref channel_id, ref user_channel_id,
+ ref former_temporary_channel_id, ref counterparty_node_id, ref funding_txo,
+ ref channel_type
+ } => {
31u8.write(writer)?;
write_tlv_fields!(writer, {
(0, channel_id, required),
+ (1, channel_type, option),
(2, user_channel_id, required),
(4, former_temporary_channel_id, required),
(6, counterparty_node_id, required),
(8, funding_txo, required),
});
},
+ &Event::InvoiceRequestFailed { ref payment_id } => {
+ 33u8.write(writer)?;
+ write_tlv_fields!(writer, {
+ (0, payment_id, required),
+ })
+ },
+ &Event::ConnectionNeeded { .. } => {
+ 35u8.write(writer)?;
+ // Never write ConnectionNeeded events as buffered onion messages aren't serialized.
+ },
+ &Event::OnionMessageIntercepted { ref peer_node_id, ref message } => {
+ 37u8.write(writer)?;
+ write_tlv_fields!(writer, {
+ (0, peer_node_id, required),
+ (2, message, required),
+ });
+ },
+ &Event::OnionMessagePeerConnected { ref peer_node_id } => {
+ 39u8.write(writer)?;
+ write_tlv_fields!(writer, {
+ (0, peer_node_id, 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`.
impl MaybeReadable for Event {
fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
match Readable::read(reader)? {
- // Note that we do not write a length-prefixed TLV for FundingGenerationReady events,
- // unlike all other events, thus we return immediately here.
+ // Note that we do not write a length-prefixed TLV for FundingGenerationReady events.
0u8 => Ok(None),
1u8 => {
- let f = || {
+ let mut f = || {
let mut payment_hash = PaymentHash([0; 32]);
let mut payment_preimage = None;
let mut payment_secret = None;
let mut claim_deadline = None;
let mut via_user_channel_id = None;
let mut onion_fields = None;
+ let mut payment_context = None;
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, receiver_node_id, option),
(8, payment_preimage, option),
(9, onion_fields, option),
(10, counterparty_skimmed_fee_msat_opt, option),
+ (11, payment_context, option),
});
let purpose = match payment_secret {
- Some(secret) => PaymentPurpose::InvoicePayment {
- payment_preimage,
- payment_secret: secret
- },
+ Some(secret) => PaymentPurpose::from_parts(payment_preimage, secret, payment_context),
None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()),
None => return Err(msgs::DecodeError::InvalidValue),
};
f()
},
2u8 => {
- let f = || {
+ let mut f = || {
let mut payment_preimage = PaymentPreimage([0; 32]);
let mut payment_hash = None;
let mut payment_id = None;
(5, fee_paid_msat, option),
});
if payment_hash.is_none() {
- payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()));
+ payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()));
}
Ok(Some(Event::PaymentSent {
payment_id,
f()
},
3u8 => {
- let f = || {
+ let mut f = || {
#[cfg(test)]
let error_code = Readable::read(reader)?;
#[cfg(test)]
},
4u8 => Ok(None),
5u8 => {
- let f = || {
+ let mut f = || {
let mut outputs = WithoutLength(Vec::new());
+ let mut channel_id: Option<ChannelId> = None;
read_tlv_fields!(reader, {
(0, outputs, required),
+ (1, channel_id, option),
});
- Ok(Some(Event::SpendableOutputs { outputs: outputs.0 }))
+ Ok(Some(Event::SpendableOutputs { outputs: outputs.0, channel_id }))
};
f()
},
}))
},
7u8 => {
- let f = || {
- let mut fee_earned_msat = None;
+ let mut f = || {
let mut prev_channel_id = None;
- let mut claim_from_onchain_tx = false;
let mut next_channel_id = None;
+ let mut prev_user_channel_id = None;
+ let mut next_user_channel_id = None;
+ let mut total_fee_earned_msat = None;
+ let mut skimmed_fee_msat = None;
+ let mut claim_from_onchain_tx = false;
let mut outbound_amount_forwarded_msat = None;
read_tlv_fields!(reader, {
- (0, fee_earned_msat, option),
+ (0, total_fee_earned_msat, option),
(1, prev_channel_id, option),
(2, claim_from_onchain_tx, required),
(3, next_channel_id, option),
(5, outbound_amount_forwarded_msat, option),
+ (7, skimmed_fee_msat, option),
+ (9, prev_user_channel_id, option),
+ (11, next_user_channel_id, option),
});
Ok(Some(Event::PaymentForwarded {
- fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
- outbound_amount_forwarded_msat
+ prev_channel_id, next_channel_id, prev_user_channel_id,
+ next_user_channel_id, total_fee_earned_msat, skimmed_fee_msat,
+ claim_from_onchain_tx, outbound_amount_forwarded_msat,
}))
};
f()
},
9u8 => {
- let f = || {
- let mut channel_id = [0; 32];
+ let mut f = || {
+ let mut channel_id = ChannelId::new_zero();
let mut reason = UpgradableRequired(None);
let mut user_channel_id_low_opt: Option<u64> = None;
let mut user_channel_id_high_opt: Option<u64> = None;
let mut counterparty_node_id = None;
let mut channel_capacity_sats = None;
+ let mut channel_funding_txo = None;
read_tlv_fields!(reader, {
(0, channel_id, required),
(1, user_channel_id_low_opt, option),
(3, user_channel_id_high_opt, option),
(5, counterparty_node_id, option),
(7, channel_capacity_sats, option),
+ (9, channel_funding_txo, option),
});
// `user_channel_id` used to be a single u64 value. In order to remain
((user_channel_id_high_opt.unwrap_or(0) as u128) << 64);
Ok(Some(Event::ChannelClosed { channel_id, user_channel_id, reason: _init_tlv_based_struct_field!(reason, upgradable_required),
- counterparty_node_id, channel_capacity_sats }))
+ counterparty_node_id, channel_capacity_sats, channel_funding_txo }))
};
f()
},
11u8 => {
- let f = || {
- let mut channel_id = [0; 32];
- let mut transaction = Transaction{ version: 2, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() };
+ let mut f = || {
+ let mut channel_id = ChannelId::new_zero();
+ let mut transaction = Transaction{ version: 2, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
read_tlv_fields!(reader, {
(0, channel_id, required),
(2, transaction, required),
f()
},
13u8 => {
- let f = || {
+ let mut f = || {
_init_and_read_len_prefixed_tlv_fields!(reader, {
(0, payment_id, required),
(2, payment_hash, option),
f()
},
15u8 => {
- let f = || {
+ let mut f = || {
let mut payment_hash = PaymentHash([0; 32]);
let mut payment_id = PaymentId([0; 32]);
let mut reason = None;
Ok(None)
},
19u8 => {
- let f = || {
+ let mut f = || {
let mut payment_hash = PaymentHash([0; 32]);
let mut purpose = UpgradableRequired(None);
let mut amount_msat = 0;
f()
},
21u8 => {
- let f = || {
+ let mut f = || {
_init_and_read_len_prefixed_tlv_fields!(reader, {
(0, payment_id, required),
(2, payment_hash, required),
f()
},
23u8 => {
- let f = || {
+ let mut f = || {
_init_and_read_len_prefixed_tlv_fields!(reader, {
(0, payment_id, required),
(2, payment_hash, required),
f()
},
25u8 => {
- let f = || {
- let mut prev_channel_id = [0; 32];
+ let mut f = || {
+ let mut prev_channel_id = ChannelId::new_zero();
let mut failed_next_destination_opt = UpgradableRequired(None);
read_tlv_fields!(reader, {
(0, prev_channel_id, required),
},
27u8 => Ok(None),
29u8 => {
- let f = || {
- let mut channel_id = [0; 32];
+ let mut f = || {
+ let mut channel_id = ChannelId::new_zero();
let mut user_channel_id: u128 = 0;
let mut counterparty_node_id = RequiredWrapper(None);
let mut channel_type = RequiredWrapper(None);
f()
},
31u8 => {
- let f = || {
- let mut channel_id = [0; 32];
+ let mut f = || {
+ let mut channel_id = ChannelId::new_zero();
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);
+ let mut channel_type = None;
read_tlv_fields!(reader, {
(0, channel_id, required),
+ (1, channel_type, option),
(2, user_channel_id, required),
(4, former_temporary_channel_id, required),
(6, counterparty_node_id, required),
user_channel_id,
former_temporary_channel_id,
counterparty_node_id: counterparty_node_id.0.unwrap(),
- funding_txo: funding_txo.0.unwrap()
+ funding_txo: funding_txo.0.unwrap(),
+ channel_type,
+ }))
+ };
+ f()
+ },
+ 33u8 => {
+ let mut f = || {
+ _init_and_read_len_prefixed_tlv_fields!(reader, {
+ (0, payment_id, required),
+ });
+ Ok(Some(Event::InvoiceRequestFailed {
+ payment_id: payment_id.0.unwrap(),
+ }))
+ };
+ f()
+ },
+ // Note that we do not write a length-prefixed TLV for ConnectionNeeded events.
+ 35u8 => Ok(None),
+ 37u8 => {
+ let mut f = || {
+ _init_and_read_len_prefixed_tlv_fields!(reader, {
+ (0, peer_node_id, required),
+ (2, message, required),
+ });
+ Ok(Some(Event::OnionMessageIntercepted {
+ peer_node_id: peer_node_id.0.unwrap(), message: message.0.unwrap()
+ }))
+ };
+ f()
+ },
+ 39u8 => {
+ let mut f = || {
+ _init_and_read_len_prefixed_tlv_fields!(reader, {
+ (0, peer_node_id, required),
+ });
+ Ok(Some(Event::OnionMessagePeerConnected {
+ peer_node_id: peer_node_id.0.unwrap()
}))
};
f()
/// The message which should be sent.
msg: msgs::FundingSigned,
},
+ /// Used to indicate that a stfu message should be sent to the peer with the given node id.
+ SendStfu {
+ /// The node_id of the node which should receive this message
+ node_id: PublicKey,
+ /// The message which should be sent.
+ msg: msgs::Stfu,
+ },
+ /// Used to indicate that a splice message should be sent to the peer with the given node id.
+ SendSplice {
+ /// The node_id of the node which should receive this message
+ node_id: PublicKey,
+ /// The message which should be sent.
+ msg: msgs::Splice,
+ },
+ /// Used to indicate that a splice_ack message should be sent to the peer with the given node id.
+ SendSpliceAck {
+ /// The node_id of the node which should receive this message
+ node_id: PublicKey,
+ /// The message which should be sent.
+ msg: msgs::SpliceAck,
+ },
+ /// Used to indicate that a splice_locked message should be sent to the peer with the given node id.
+ SendSpliceLocked {
+ /// The node_id of the node which should receive this message
+ node_id: PublicKey,
+ /// The message which should be sent.
+ msg: msgs::SpliceLocked,
+ },
/// Used to indicate that a tx_add_input message should be sent to the peer with the given node_id.
SendTxAddInput {
/// The node_id of the node which should receive this message
/// The node_id of the node which should receive this message
node_id: PublicKey,
/// The message which should be sent.
- msg: msgs::TxAddInput,
+ msg: msgs::TxAbort,
},
/// Used to indicate that a channel_ready message should be sent to the peer with the given node_id.
SendChannelReady {
fn get_and_clear_pending_msg_events(&self) -> Vec<MessageSendEvent>;
}
-/// A trait indicating an object may generate onion messages to send
-pub trait OnionMessageProvider {
- /// Gets the next pending onion message for the peer with the given node id.
- fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<msgs::OnionMessage>;
-}
-
/// A trait indicating an object may generate events.
///
/// Events are processed by passing an [`EventHandler`] to [`process_pending_events`].