ldk_node/
balance.rs

1// This file is Copyright its original authors, visible in version control history.
2//
3// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
6// accordance with one or both of these licenses.
7
8use crate::sweep::value_from_descriptor;
9
10use lightning::chain::channelmonitor::Balance as LdkBalance;
11use lightning::chain::channelmonitor::BalanceSource;
12use lightning::ln::types::ChannelId;
13use lightning::util::sweep::{OutputSpendStatus, TrackedSpendableOutput};
14
15use lightning_types::payment::{PaymentHash, PaymentPreimage};
16
17use bitcoin::secp256k1::PublicKey;
18use bitcoin::{BlockHash, Txid};
19
20/// Details of the known available balances returned by [`Node::list_balances`].
21///
22/// [`Node::list_balances`]: crate::Node::list_balances
23#[derive(Debug, Clone)]
24pub struct BalanceDetails {
25	/// The total balance of our on-chain wallet.
26	pub total_onchain_balance_sats: u64,
27	/// The currently spendable balance of our on-chain wallet.
28	///
29	/// This includes any sufficiently confirmed funds, minus
30	/// [`total_anchor_channels_reserve_sats`].
31	///
32	/// [`total_anchor_channels_reserve_sats`]: Self::total_anchor_channels_reserve_sats
33	pub spendable_onchain_balance_sats: u64,
34	/// The share of our total balance that we retain as an emergency reserve to (hopefully) be
35	/// able to spend the Anchor outputs when one of our channels is closed.
36	pub total_anchor_channels_reserve_sats: u64,
37	/// The total balance that we would be able to claim across all our Lightning channels.
38	///
39	/// Note this excludes balances that we are unsure if we are able to claim (e.g., as we are
40	/// waiting for a preimage or for a timeout to expire). These balances will however be included
41	/// as [`MaybePreimageClaimableHTLC`] and
42	/// [`MaybeTimeoutClaimableHTLC`] in [`lightning_balances`].
43	///
44	/// [`MaybePreimageClaimableHTLC`]: LightningBalance::MaybePreimageClaimableHTLC
45	/// [`MaybeTimeoutClaimableHTLC`]: LightningBalance::MaybeTimeoutClaimableHTLC
46	/// [`lightning_balances`]: Self::lightning_balances
47	pub total_lightning_balance_sats: u64,
48	/// A detailed list of all known Lightning balances that would be claimable on channel closure.
49	///
50	/// Note that less than the listed amounts are spendable over lightning as further reserve
51	/// restrictions apply. Please refer to [`ChannelDetails::outbound_capacity_msat`] and
52	/// [`ChannelDetails::next_outbound_htlc_limit_msat`] as returned by [`Node::list_channels`]
53	/// for a better approximation of the spendable amounts.
54	///
55	/// [`ChannelDetails::outbound_capacity_msat`]: crate::ChannelDetails::outbound_capacity_msat
56	/// [`ChannelDetails::next_outbound_htlc_limit_msat`]: crate::ChannelDetails::next_outbound_htlc_limit_msat
57	/// [`Node::list_channels`]: crate::Node::list_channels
58	pub lightning_balances: Vec<LightningBalance>,
59	/// A detailed list of balances currently being swept from the Lightning to the on-chain
60	/// wallet.
61	///
62	/// These are balances resulting from channel closures that may have been encumbered by a
63	/// delay, but are now being claimed and useable once sufficiently confirmed on-chain.
64	///
65	/// Note that, depending on the sync status of the wallets, swept balances listed here might or
66	/// might not already be accounted for in [`total_onchain_balance_sats`].
67	///
68	/// [`total_onchain_balance_sats`]: Self::total_onchain_balance_sats
69	pub pending_balances_from_channel_closures: Vec<PendingSweepBalance>,
70}
71
72/// Details about the status of a known Lightning balance.
73#[derive(Debug, Clone)]
74pub enum LightningBalance {
75	/// The channel is not yet closed (or the commitment or closing transaction has not yet
76	/// appeared in a block). The given balance is claimable (less on-chain fees) if the channel is
77	/// force-closed now.
78	ClaimableOnChannelClose {
79		/// The identifier of the channel this balance belongs to.
80		channel_id: ChannelId,
81		/// The identifier of our channel counterparty.
82		counterparty_node_id: PublicKey,
83		/// The amount available to claim, in satoshis, excluding the on-chain fees which will be
84		/// required to do so.
85		amount_satoshis: u64,
86		/// The transaction fee we pay for the closing commitment transaction. This amount is not
87		/// included in the `amount_satoshis` value.
88		///
89		/// Note that if this channel is inbound (and thus our counterparty pays the commitment
90		/// transaction fee) this value will be zero. For channels created prior to LDK Node 0.4
91		/// the channel is always treated as outbound (and thus this value is never zero).
92		transaction_fee_satoshis: u64,
93		/// The amount of millisatoshis which has been burned to fees from HTLCs which are outbound
94		/// from us and are related to a payment which was sent by us. This is the sum of the
95		/// millisatoshis part of all HTLCs which are otherwise represented by
96		/// [`LightningBalance::MaybeTimeoutClaimableHTLC`] with their
97		/// [`LightningBalance::MaybeTimeoutClaimableHTLC::outbound_payment`] flag set, as well as
98		/// any dust HTLCs which would otherwise be represented the same.
99		///
100		/// This amount (rounded up to a whole satoshi value) will not be included in `amount_satoshis`.
101		outbound_payment_htlc_rounded_msat: u64,
102		/// The amount of millisatoshis which has been burned to fees from HTLCs which are outbound
103		/// from us and are related to a forwarded HTLC. This is the sum of the millisatoshis part
104		/// of all HTLCs which are otherwise represented by
105		/// [`LightningBalance::MaybeTimeoutClaimableHTLC`] with their
106		/// [`LightningBalance::MaybeTimeoutClaimableHTLC::outbound_payment`] flag *not* set, as
107		/// well as any dust HTLCs which would otherwise be represented the same.
108		///
109		/// This amount (rounded up to a whole satoshi value) will not be included in `amount_satoshis`.
110		outbound_forwarded_htlc_rounded_msat: u64,
111		/// The amount of millisatoshis which has been burned to fees from HTLCs which are inbound
112		/// to us and for which we know the preimage. This is the sum of the millisatoshis part of
113		/// all HTLCs which would be represented by [`LightningBalance::ContentiousClaimable`] on
114		/// channel close, but whose current value is included in `amount_satoshis`, as well as any
115		/// dust HTLCs which would otherwise be represented the same.
116		///
117		/// This amount (rounded up to a whole satoshi value) will not be included in the counterparty's
118		/// `amount_satoshis`.
119		inbound_claiming_htlc_rounded_msat: u64,
120		/// The amount of millisatoshis which has been burned to fees from HTLCs which are inbound
121		/// to us and for which we do not know the preimage. This is the sum of the millisatoshis
122		/// part of all HTLCs which would be represented by
123		/// [`LightningBalance::MaybePreimageClaimableHTLC`] on channel close, as well as any dust
124		/// HTLCs which would otherwise be represented the same.
125		///
126		/// This amount (rounded up to a whole satoshi value) will not be included in the
127		/// counterparty's `amount_satoshis`.
128		inbound_htlc_rounded_msat: u64,
129	},
130	/// The channel has been closed, and the given balance is ours but awaiting confirmations until
131	/// we consider it spendable.
132	ClaimableAwaitingConfirmations {
133		/// The identifier of the channel this balance belongs to.
134		channel_id: ChannelId,
135		/// The identifier of our channel counterparty.
136		counterparty_node_id: PublicKey,
137		/// The amount available to claim, in satoshis, possibly excluding the on-chain fees which
138		/// were spent in broadcasting the transaction.
139		amount_satoshis: u64,
140		/// The height at which an [`Event::SpendableOutputs`] event will be generated for this
141		/// amount.
142		///
143		/// [`Event::SpendableOutputs`]: lightning::events::Event::SpendableOutputs
144		confirmation_height: u32,
145		/// Whether this balance is a result of cooperative close, a force-close, or an HTLC.
146		source: BalanceSource,
147	},
148	/// The channel has been closed, and the given balance should be ours but awaiting spending
149	/// transaction confirmation. If the spending transaction does not confirm in time, it is
150	/// possible our counterparty can take the funds by broadcasting an HTLC timeout on-chain.
151	///
152	/// Once the spending transaction confirms, before it has reached enough confirmations to be
153	/// considered safe from chain reorganizations, the balance will instead be provided via
154	/// [`LightningBalance::ClaimableAwaitingConfirmations`].
155	ContentiousClaimable {
156		/// The identifier of the channel this balance belongs to.
157		channel_id: ChannelId,
158		/// The identifier of our channel counterparty.
159		counterparty_node_id: PublicKey,
160		/// The amount available to claim, in satoshis, excluding the on-chain fees which will be
161		/// required to do so.
162		amount_satoshis: u64,
163		/// The height at which the counterparty may be able to claim the balance if we have not
164		/// done so.
165		timeout_height: u32,
166		/// The payment hash that locks this HTLC.
167		payment_hash: PaymentHash,
168		/// The preimage that can be used to claim this HTLC.
169		payment_preimage: PaymentPreimage,
170	},
171	/// HTLCs which we sent to our counterparty which are claimable after a timeout (less on-chain
172	/// fees) if the counterparty does not know the preimage for the HTLCs. These are somewhat
173	/// likely to be claimed by our counterparty before we do.
174	MaybeTimeoutClaimableHTLC {
175		/// The identifier of the channel this balance belongs to.
176		channel_id: ChannelId,
177		/// The identifier of our channel counterparty.
178		counterparty_node_id: PublicKey,
179		/// The amount potentially available to claim, in satoshis, excluding the on-chain fees
180		/// which will be required to do so.
181		amount_satoshis: u64,
182		/// The height at which we will be able to claim the balance if our counterparty has not
183		/// done so.
184		claimable_height: u32,
185		/// The payment hash whose preimage our counterparty needs to claim this HTLC.
186		payment_hash: PaymentHash,
187		/// Indicates whether this HTLC represents a payment which was sent outbound from us.
188		outbound_payment: bool,
189	},
190	/// HTLCs which we received from our counterparty which are claimable with a preimage which we
191	/// do not currently have. This will only be claimable if we receive the preimage from the node
192	/// to which we forwarded this HTLC before the timeout.
193	MaybePreimageClaimableHTLC {
194		/// The identifier of the channel this balance belongs to.
195		channel_id: ChannelId,
196		/// The identifier of our channel counterparty.
197		counterparty_node_id: PublicKey,
198		/// The amount potentially available to claim, in satoshis, excluding the on-chain fees
199		/// which will be required to do so.
200		amount_satoshis: u64,
201		/// The height at which our counterparty will be able to claim the balance if we have not
202		/// yet received the preimage and claimed it ourselves.
203		expiry_height: u32,
204		/// The payment hash whose preimage we need to claim this HTLC.
205		payment_hash: PaymentHash,
206	},
207	/// The channel has been closed, and our counterparty broadcasted a revoked commitment
208	/// transaction.
209	///
210	/// Thus, we're able to claim all outputs in the commitment transaction, one of which has the
211	/// following amount.
212	CounterpartyRevokedOutputClaimable {
213		/// The identifier of the channel this balance belongs to.
214		channel_id: ChannelId,
215		/// The identifier of our channel counterparty.
216		counterparty_node_id: PublicKey,
217		/// The amount, in satoshis, of the output which we can claim.
218		amount_satoshis: u64,
219	},
220}
221
222impl LightningBalance {
223	pub(crate) fn from_ldk_balance(
224		channel_id: ChannelId, counterparty_node_id: PublicKey, balance: LdkBalance,
225	) -> Self {
226		match balance {
227			LdkBalance::ClaimableOnChannelClose {
228				amount_satoshis,
229				transaction_fee_satoshis,
230				outbound_payment_htlc_rounded_msat,
231				outbound_forwarded_htlc_rounded_msat,
232				inbound_claiming_htlc_rounded_msat,
233				inbound_htlc_rounded_msat,
234			} => Self::ClaimableOnChannelClose {
235				channel_id,
236				counterparty_node_id,
237				amount_satoshis,
238				transaction_fee_satoshis,
239				outbound_payment_htlc_rounded_msat,
240				outbound_forwarded_htlc_rounded_msat,
241				inbound_claiming_htlc_rounded_msat,
242				inbound_htlc_rounded_msat,
243			},
244			LdkBalance::ClaimableAwaitingConfirmations {
245				amount_satoshis,
246				confirmation_height,
247				source,
248			} => Self::ClaimableAwaitingConfirmations {
249				channel_id,
250				counterparty_node_id,
251				amount_satoshis,
252				confirmation_height,
253				source,
254			},
255			LdkBalance::ContentiousClaimable {
256				amount_satoshis,
257				timeout_height,
258				payment_hash,
259				payment_preimage,
260			} => Self::ContentiousClaimable {
261				channel_id,
262				counterparty_node_id,
263				amount_satoshis,
264				timeout_height,
265				payment_hash,
266				payment_preimage,
267			},
268			LdkBalance::MaybeTimeoutClaimableHTLC {
269				amount_satoshis,
270				claimable_height,
271				payment_hash,
272				outbound_payment,
273			} => Self::MaybeTimeoutClaimableHTLC {
274				channel_id,
275				counterparty_node_id,
276				amount_satoshis,
277				claimable_height,
278				payment_hash,
279				outbound_payment,
280			},
281			LdkBalance::MaybePreimageClaimableHTLC {
282				amount_satoshis,
283				expiry_height,
284				payment_hash,
285			} => Self::MaybePreimageClaimableHTLC {
286				channel_id,
287				counterparty_node_id,
288				amount_satoshis,
289				expiry_height,
290				payment_hash,
291			},
292			LdkBalance::CounterpartyRevokedOutputClaimable { amount_satoshis } => {
293				Self::CounterpartyRevokedOutputClaimable {
294					channel_id,
295					counterparty_node_id,
296					amount_satoshis,
297				}
298			},
299		}
300	}
301}
302
303/// Details about the status of a known balance currently being swept to our on-chain wallet.
304#[derive(Debug, Clone)]
305pub enum PendingSweepBalance {
306	/// The spendable output is about to be swept, but a spending transaction has yet to be generated and
307	/// broadcast.
308	PendingBroadcast {
309		/// The identifier of the channel this balance belongs to.
310		channel_id: Option<ChannelId>,
311		/// The amount, in satoshis, of the output being swept.
312		amount_satoshis: u64,
313	},
314	/// A spending transaction has been generated and broadcast and is awaiting confirmation
315	/// on-chain.
316	BroadcastAwaitingConfirmation {
317		/// The identifier of the channel this balance belongs to.
318		channel_id: Option<ChannelId>,
319		/// The best height when we last broadcast a transaction spending the output being swept.
320		latest_broadcast_height: u32,
321		/// The identifier of the transaction spending the swept output we last broadcast.
322		latest_spending_txid: Txid,
323		/// The amount, in satoshis, of the output being swept.
324		amount_satoshis: u64,
325	},
326	/// A spending transaction has been confirmed on-chain and is awaiting threshold confirmations.
327	///
328	/// It will be pruned after reaching [`PRUNE_DELAY_BLOCKS`] confirmations.
329	///
330	/// [`PRUNE_DELAY_BLOCKS`]: lightning::util::sweep::PRUNE_DELAY_BLOCKS
331	AwaitingThresholdConfirmations {
332		/// The identifier of the channel this balance belongs to.
333		channel_id: Option<ChannelId>,
334		/// The identifier of the confirmed transaction spending the swept output.
335		latest_spending_txid: Txid,
336		/// The hash of the block in which the spending transaction was confirmed.
337		confirmation_hash: BlockHash,
338		/// The height at which the spending transaction was confirmed.
339		confirmation_height: u32,
340		/// The amount, in satoshis, of the output being swept.
341		amount_satoshis: u64,
342	},
343}
344
345impl PendingSweepBalance {
346	pub(crate) fn from_tracked_spendable_output(output_info: TrackedSpendableOutput) -> Self {
347		match output_info.status {
348			OutputSpendStatus::PendingInitialBroadcast { .. } => {
349				let channel_id = output_info.channel_id;
350				let amount_satoshis = value_from_descriptor(&output_info.descriptor).to_sat();
351				Self::PendingBroadcast { channel_id, amount_satoshis }
352			},
353			OutputSpendStatus::PendingFirstConfirmation {
354				latest_broadcast_height,
355				latest_spending_tx,
356				..
357			} => {
358				let channel_id = output_info.channel_id;
359				let amount_satoshis = value_from_descriptor(&output_info.descriptor).to_sat();
360				let latest_spending_txid = latest_spending_tx.compute_txid();
361				Self::BroadcastAwaitingConfirmation {
362					channel_id,
363					latest_broadcast_height,
364					latest_spending_txid,
365					amount_satoshis,
366				}
367			},
368			OutputSpendStatus::PendingThresholdConfirmations {
369				latest_spending_tx,
370				confirmation_height,
371				confirmation_hash,
372				..
373			} => {
374				let channel_id = output_info.channel_id;
375				let amount_satoshis = value_from_descriptor(&output_info.descriptor).to_sat();
376				let latest_spending_txid = latest_spending_tx.compute_txid();
377				Self::AwaitingThresholdConfirmations {
378					channel_id,
379					latest_spending_txid,
380					confirmation_hash,
381					confirmation_height,
382					amount_satoshis,
383				}
384			},
385		}
386	}
387}