use crate::ln::features::ChannelTypeFeatures;
use crate::ln::msgs;
use crate::ln::{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 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)]
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`.
/// 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::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) => {}
+ (15, FundingBatchClosure) => {},
+ (17, CounterpartyInitiatedCooperativeClosure) => {},
+ (19, LocallyInitiatedCooperativeClosure) => {},
+ (21, HTLCsTimedOut) => {},
);
/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`].
/// 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.
/// replies. Handlers should connect to the node otherwise any buffered messages may be lost.
///
/// [`OnionMessage`]: msgs::OnionMessage
- /// [`MessageRouter`]: crate::onion_message::MessageRouter
- /// [`Destination`]: crate::onion_message::Destination
+ /// [`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.
/// 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.
+ /// 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 outgoing channel between the next node and us. This is only `None` for events
- /// generated or serialized by versions prior to 0.0.107.
+ /// 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 fee, in milli-satoshis, which was earned as a result of the payment.
+ /// 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
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
///
/// [`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: ChannelId,
///
/// 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.
});
}
&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),
// 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;
f()
},
2u8 => {
- let f = || {
+ let mut f = || {
let mut payment_preimage = PaymentPreimage([0; 32]);
let mut payment_hash = None;
let mut payment_id = None;
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, {
}))
},
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 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 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, {
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 f = || {
let mut prev_channel_id = ChannelId::new_zero();
let mut failed_next_destination_opt = UpgradableRequired(None);
read_tlv_fields!(reader, {
},
27u8 => Ok(None),
29u8 => {
- let f = || {
+ let mut f = || {
let mut channel_id = ChannelId::new_zero();
let mut user_channel_id: u128 = 0;
let mut counterparty_node_id = RequiredWrapper(None);
f()
},
31u8 => {
- let f = || {
+ 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 f = || {
+ let mut f = || {
_init_and_read_len_prefixed_tlv_fields!(reader, {
(0, payment_id, required),
});