|
1 |
| -use bitcoin::secp256k1::PublicKey; |
2 | 1 | use lightning::chain::channelmonitor::Balance as LdkBalance;
|
3 | 2 | use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage};
|
4 | 3 |
|
| 4 | +use bitcoin::secp256k1::PublicKey; |
| 5 | +use bitcoin::{BlockHash, Txid}; |
| 6 | + |
| 7 | +use crate::sweep::SpendableOutputInfo; |
| 8 | + |
5 | 9 | /// Details of the known available balances returned by [`Node::list_balances`].
|
6 | 10 | ///
|
7 | 11 | /// [`Node::list_balances`]: crate::Node::list_balances
|
@@ -33,6 +37,17 @@ pub struct BalanceDetails {
|
33 | 37 | /// [`ChannelDetails::next_outbound_htlc_limit_msat`]: crate::ChannelDetails::next_outbound_htlc_limit_msat
|
34 | 38 | /// [`Node::list_channels`]: crate::Node::list_channels
|
35 | 39 | pub lightning_balances: Vec<LightningBalance>,
|
| 40 | + /// A detailed list of balances currently being swept from the Lightning to the on-chain |
| 41 | + /// wallet. |
| 42 | + /// |
| 43 | + /// These are balances resulting from channel closures that may have been encumbered by a |
| 44 | + /// delay, but are now being claimed and useable once sufficiently confirmed on-chain. |
| 45 | + /// |
| 46 | + /// Note that, depending on the sync status of the wallets, swept balances listed here might or |
| 47 | + /// might not already be accounted for in [`total_onchain_balance_sats`]. |
| 48 | + /// |
| 49 | + /// [`total_onchain_balance_sats`]: Self::total_onchain_balance_sats |
| 50 | + pub pending_balances_from_channel_closures: Vec<PendingSweepBalance>, |
36 | 51 | }
|
37 | 52 |
|
38 | 53 | /// Details about the status of a known Lightning balance.
|
@@ -199,3 +214,90 @@ impl LightningBalance {
|
199 | 214 | }
|
200 | 215 | }
|
201 | 216 | }
|
| 217 | + |
| 218 | +/// Details about the status of a known balance currently being swept to our on-chain wallet. |
| 219 | +#[derive(Debug, Clone)] |
| 220 | +pub enum PendingSweepBalance { |
| 221 | + /// The spendable output is about to be swept, but a spending transaction has yet to be generated and |
| 222 | + /// broadcast. |
| 223 | + PendingBroadcast { |
| 224 | + /// The identifier of the channel this balance belongs to. |
| 225 | + channel_id: Option<ChannelId>, |
| 226 | + /// The amount, in satoshis, of the output being swept. |
| 227 | + amount_satoshis: u64, |
| 228 | + }, |
| 229 | + /// A spending transaction has been generated and broadcast and is awaiting confirmation |
| 230 | + /// on-chain. |
| 231 | + BroadcastAwaitingConfirmation { |
| 232 | + /// The identifier of the channel this balance belongs to. |
| 233 | + channel_id: Option<ChannelId>, |
| 234 | + /// The best height when we last broadcast a transaction spending the output being swept. |
| 235 | + latest_broadcast_height: u32, |
| 236 | + /// The identifier of the transaction spending the swept output we last broadcast. |
| 237 | + latest_spending_txid: Txid, |
| 238 | + /// The amount, in satoshis, of the output being swept. |
| 239 | + amount_satoshis: u64, |
| 240 | + }, |
| 241 | + /// A spending transaction has been confirmed on-chain and is awaiting threshold confirmations. |
| 242 | + /// |
| 243 | + /// It will be considered irrevocably confirmed after reaching [`ANTI_REORG_DELAY`]. |
| 244 | + /// |
| 245 | + /// [`ANTI_REORG_DELAY`]: lightning::chain::channelmonitor::ANTI_REORG_DELAY |
| 246 | + AwaitingThresholdConfirmations { |
| 247 | + /// The identifier of the channel this balance belongs to. |
| 248 | + channel_id: Option<ChannelId>, |
| 249 | + /// The identifier of the confirmed transaction spending the swept output. |
| 250 | + latest_spending_txid: Txid, |
| 251 | + /// The hash of the block in which the spending transaction was confirmed. |
| 252 | + confirmation_hash: BlockHash, |
| 253 | + /// The height at which the spending transaction was confirmed. |
| 254 | + confirmation_height: u32, |
| 255 | + /// The amount, in satoshis, of the output being swept. |
| 256 | + amount_satoshis: u64, |
| 257 | + }, |
| 258 | +} |
| 259 | + |
| 260 | +impl PendingSweepBalance { |
| 261 | + pub(crate) fn from_tracked_spendable_output(output_info: SpendableOutputInfo) -> Self { |
| 262 | + if let Some(confirmation_hash) = output_info.confirmation_hash { |
| 263 | + debug_assert!(output_info.confirmation_height.is_some()); |
| 264 | + debug_assert!(output_info.latest_spending_tx.is_some()); |
| 265 | + let channel_id = output_info.channel_id; |
| 266 | + let confirmation_height = output_info |
| 267 | + .confirmation_height |
| 268 | + .expect("Height must be set if the output is confirmed"); |
| 269 | + let latest_spending_txid = output_info |
| 270 | + .latest_spending_tx |
| 271 | + .as_ref() |
| 272 | + .expect("Spending tx must be set if the output is confirmed") |
| 273 | + .txid(); |
| 274 | + let amount_satoshis = output_info.value_satoshis(); |
| 275 | + Self::AwaitingThresholdConfirmations { |
| 276 | + channel_id, |
| 277 | + latest_spending_txid, |
| 278 | + confirmation_hash, |
| 279 | + confirmation_height, |
| 280 | + amount_satoshis, |
| 281 | + } |
| 282 | + } else if let Some(latest_broadcast_height) = output_info.latest_broadcast_height { |
| 283 | + debug_assert!(output_info.latest_spending_tx.is_some()); |
| 284 | + let channel_id = output_info.channel_id; |
| 285 | + let latest_spending_txid = output_info |
| 286 | + .latest_spending_tx |
| 287 | + .as_ref() |
| 288 | + .expect("Spending tx must be set if the spend was broadcast") |
| 289 | + .txid(); |
| 290 | + let amount_satoshis = output_info.value_satoshis(); |
| 291 | + Self::BroadcastAwaitingConfirmation { |
| 292 | + channel_id, |
| 293 | + latest_broadcast_height, |
| 294 | + latest_spending_txid, |
| 295 | + amount_satoshis, |
| 296 | + } |
| 297 | + } else { |
| 298 | + let channel_id = output_info.channel_id; |
| 299 | + let amount_satoshis = output_info.value_satoshis(); |
| 300 | + Self::PendingBroadcast { channel_id, amount_satoshis } |
| 301 | + } |
| 302 | + } |
| 303 | +} |
0 commit comments