diff --git a/bindings/ldk_node.udl b/bindings/ldk_node.udl index 19e23ada9..e2bc28ad5 100644 --- a/bindings/ldk_node.udl +++ b/bindings/ldk_node.udl @@ -511,9 +511,32 @@ enum BalanceSource { [Enum] interface PendingSweepBalance { - PendingBroadcast ( ChannelId? channel_id, u64 amount_satoshis ); - BroadcastAwaitingConfirmation ( ChannelId? channel_id, u32 latest_broadcast_height, Txid latest_spending_txid, u64 amount_satoshis ); - AwaitingThresholdConfirmations ( ChannelId? channel_id, Txid latest_spending_txid, BlockHash confirmation_hash, u32 confirmation_height, u64 amount_satoshis); + PendingBroadcast ( + ChannelId? channel_id, + u64 amount_satoshis, + PublicKey? counterparty_node_id, + Txid? funding_tx_id, + u16? funding_tx_index + ); + BroadcastAwaitingConfirmation ( + ChannelId? channel_id, + u32 latest_broadcast_height, + Txid latest_spending_txid, + u64 amount_satoshis, + PublicKey? counterparty_node_id, + Txid? funding_tx_id, + u16? funding_tx_index + ); + AwaitingThresholdConfirmations ( + ChannelId? channel_id, + Txid latest_spending_txid, + BlockHash confirmation_hash, + u32 confirmation_height, + u64 amount_satoshis, + PublicKey? counterparty_node_id, + Txid? funding_tx_id, + u16? funding_tx_index + ); }; dictionary BalanceDetails { diff --git a/src/balance.rs b/src/balance.rs index 43f7b0731..5a2b0e7bd 100644 --- a/src/balance.rs +++ b/src/balance.rs @@ -348,6 +348,12 @@ pub enum PendingSweepBalance { channel_id: Option, /// The amount, in satoshis, of the output being swept. amount_satoshis: u64, + /// Alby: the identifier of our channel counterparty. + counterparty_node_id: Option, + /// Alby: funding transaction ID. + funding_tx_id: Option, + /// Alby: funding transaction output index. + funding_tx_index: Option, }, /// A spending transaction has been generated and broadcast and is awaiting confirmation /// on-chain. @@ -360,6 +366,12 @@ pub enum PendingSweepBalance { latest_spending_txid: Txid, /// The amount, in satoshis, of the output being swept. amount_satoshis: u64, + /// Alby: the identifier of our channel counterparty. + counterparty_node_id: Option, + /// Alby: funding transaction ID. + funding_tx_id: Option, + /// Alby: funding transaction output index. + funding_tx_index: Option, }, /// A spending transaction has been confirmed on-chain and is awaiting threshold confirmations. /// @@ -377,16 +389,31 @@ pub enum PendingSweepBalance { confirmation_height: u32, /// The amount, in satoshis, of the output being swept. amount_satoshis: u64, + /// Alby: the identifier of our channel counterparty. + counterparty_node_id: Option, + /// Alby: funding transaction ID. + funding_tx_id: Option, + /// Alby: funding transaction output index. + funding_tx_index: Option, }, } impl PendingSweepBalance { - pub(crate) fn from_tracked_spendable_output(output_info: TrackedSpendableOutput) -> Self { + pub(crate) fn from_tracked_spendable_output( + output_info: TrackedSpendableOutput, counterparty_node_id: Option, + funding_txo: Option, + ) -> Self { match output_info.status { OutputSpendStatus::PendingInitialBroadcast { .. } => { let channel_id = output_info.channel_id; let amount_satoshis = value_from_descriptor(&output_info.descriptor).to_sat(); - Self::PendingBroadcast { channel_id, amount_satoshis } + Self::PendingBroadcast { + channel_id, + amount_satoshis, + counterparty_node_id, + funding_tx_id: funding_txo.map(|funding_txo| funding_txo.txid), + funding_tx_index: funding_txo.map(|funding_txo| funding_txo.index), + } }, OutputSpendStatus::PendingFirstConfirmation { latest_broadcast_height, @@ -401,6 +428,9 @@ impl PendingSweepBalance { latest_broadcast_height, latest_spending_txid, amount_satoshis, + counterparty_node_id, + funding_tx_id: funding_txo.map(|funding_txo| funding_txo.txid), + funding_tx_index: funding_txo.map(|funding_txo| funding_txo.index), } }, OutputSpendStatus::PendingThresholdConfirmations { @@ -418,6 +448,9 @@ impl PendingSweepBalance { confirmation_hash, confirmation_height, amount_satoshis, + counterparty_node_id, + funding_tx_id: funding_txo.map(|funding_txo| funding_txo.txid), + funding_tx_index: funding_txo.map(|funding_txo| funding_txo.index), } }, } diff --git a/src/lib.rs b/src/lib.rs index 622fa922b..3128750de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,6 +100,7 @@ pub use bip39; pub use bitcoin; pub use lightning; pub use lightning_invoice; +use std::collections::HashMap; pub use vss_client; pub use balance::{BalanceDetails, LightningBalance, PendingSweepBalance}; @@ -1436,11 +1437,16 @@ impl Node { let total_anchor_channels_reserve_sats = std::cmp::min(cur_anchor_reserve_sats, total_onchain_balance_sats); + // Alby: build a map of funding TXOs by channel ID. + let mut funding_txo_by_channel_id = HashMap::new(); + let mut total_lightning_balance_sats = 0; let mut lightning_balances = Vec::new(); for (funding_txo, channel_id) in self.chain_monitor.list_monitors() { match self.chain_monitor.get_monitor(funding_txo) { Ok(monitor) => { + funding_txo_by_channel_id.insert(channel_id, funding_txo); + // unwrap safety: `get_counterparty_node_id` will always be `Some` after 0.0.110 and // LDK Node 0.1 depended on 0.0.115 already. let counterparty_node_id = monitor.get_counterparty_node_id().unwrap(); @@ -1464,7 +1470,20 @@ impl Node { .output_sweeper .tracked_spendable_outputs() .into_iter() - .map(PendingSweepBalance::from_tracked_spendable_output) + .map(|out| { + // Alby: try to fetch channel details. After the channel is closed, its monitor is kept around + // by LDK for a while (4032 blocks since balances become empty), so we can still try to access it. + // See [`periodically_archive_fully_resolved_monitors`] for details. + let funding_txo = + out.channel_id.and_then(|c| funding_txo_by_channel_id.get(&c)).cloned(); + let chmon = funding_txo.and_then(|txo| self.chain_monitor.get_monitor(txo).ok()); + let counterparty_node_id = chmon.and_then(|m| m.get_counterparty_node_id()); + PendingSweepBalance::from_tracked_spendable_output( + out, + counterparty_node_id, + funding_txo, + ) + }) .collect(); BalanceDetails {