Skip to content

Commit

Permalink
feat: return additional details for pending sweep balances
Browse files Browse the repository at this point in the history
  • Loading branch information
rdmitr committed Feb 3, 2025
1 parent c3c6183 commit f075a53
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 6 deletions.
29 changes: 26 additions & 3 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
37 changes: 35 additions & 2 deletions src/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,12 @@ pub enum PendingSweepBalance {
channel_id: Option<ChannelId>,
/// The amount, in satoshis, of the output being swept.
amount_satoshis: u64,
/// Alby: the identifier of our channel counterparty.
counterparty_node_id: Option<PublicKey>,
/// Alby: funding transaction ID.
funding_tx_id: Option<Txid>,
/// Alby: funding transaction output index.
funding_tx_index: Option<u16>,
},
/// A spending transaction has been generated and broadcast and is awaiting confirmation
/// on-chain.
Expand All @@ -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<PublicKey>,
/// Alby: funding transaction ID.
funding_tx_id: Option<Txid>,
/// Alby: funding transaction output index.
funding_tx_index: Option<u16>,
},
/// A spending transaction has been confirmed on-chain and is awaiting threshold confirmations.
///
Expand All @@ -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<PublicKey>,
/// Alby: funding transaction ID.
funding_tx_id: Option<Txid>,
/// Alby: funding transaction output index.
funding_tx_index: Option<u16>,
},
}

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<PublicKey>,
funding_txo: Option<OutPoint>,
) -> 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,
Expand All @@ -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 {
Expand All @@ -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),
}
},
}
Expand Down
21 changes: 20 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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();
Expand All @@ -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 {
Expand Down

0 comments on commit f075a53

Please sign in to comment.