Expose `confirmations` via `ChannelDetails`
authorElias Rohrer <ero@tnull.de>
Thu, 17 Nov 2022 10:31:35 +0000 (11:31 +0100)
committerElias Rohrer <ero@tnull.de>
Tue, 29 Nov 2022 17:49:54 +0000 (18:49 +0100)
We expose the current number of confirmations in `ChannelDetails`.

fuzz/src/router.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/reorg_tests.rs
lightning/src/routing/router.rs

index a5cd91f2884a0a4e78eae3aa09114f3d417141b4..761f7bddc864706d39ebb44739f3dd2082cd365c 100644 (file)
@@ -225,6 +225,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                                user_channel_id: 0, inbound_capacity_msat: 0,
                                                                unspendable_punishment_reserve: None,
                                                                confirmations_required: None,
+                                                               confirmations: None,
                                                                force_close_spend_delay: None,
                                                                is_outbound: true, is_channel_ready: true,
                                                                is_usable: true, is_public: true,
index 70db91baf9a09c863442ab2c5628a62994e5a8db..5cc4f4a364bf3fe80ab15b896b51557a58acc5d1 100644 (file)
@@ -4495,6 +4495,16 @@ impl<Signer: Sign> Channel<Signer> {
                self.funding_tx_confirmed_in
        }
 
+       /// Returns the current number of confirmations on the funding transaction.
+       pub fn get_funding_tx_confirmations(&self, height: u32) -> u32 {
+               if self.funding_tx_confirmation_height == 0 {
+                       // We either haven't seen any confirmation yet, or observed a reorg.
+                       return 0;
+               }
+
+               height.checked_sub(self.funding_tx_confirmation_height).map_or(0, |c| c + 1)
+       }
+
        fn get_holder_selected_contest_delay(&self) -> u16 {
                self.channel_transaction_parameters.holder_selected_contest_delay
        }
index c6bb961d470d2bd39521e2ae6d993563f71f2573..7be667b921628588b2eab6c8a382eefbb9a0789d 100644 (file)
@@ -1146,6 +1146,10 @@ pub struct ChannelDetails {
        /// [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
        /// [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
        pub confirmations_required: Option<u32>,
+       /// The current number of confirmations on the funding transaction.
+       ///
+       /// This value will be `None` for objects serialized with LDK versions prior to 0.0.113.
+       pub confirmations: Option<u32>,
        /// The number of blocks (after our commitment transaction confirms) that we will need to wait
        /// until we can claim our funds after we force-close the channel. During this time our
        /// counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
@@ -1694,6 +1698,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
                let mut res = Vec::new();
                {
                        let channel_state = self.channel_state.lock().unwrap();
+                       let best_block_height = self.best_block.read().unwrap().height();
                        res.reserve(channel_state.by_id.len());
                        for (channel_id, channel) in channel_state.by_id.iter().filter(f) {
                                let balance = channel.get_available_balances();
@@ -1730,6 +1735,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
                                        next_outbound_htlc_limit_msat: balance.next_outbound_htlc_limit_msat,
                                        user_channel_id: channel.get_user_id(),
                                        confirmations_required: channel.minimum_depth(),
+                                       confirmations: Some(channel.get_funding_tx_confirmations(best_block_height)),
                                        force_close_spend_delay: channel.get_counterparty_selected_contest_delay(),
                                        is_outbound: channel.is_outbound(),
                                        is_channel_ready: channel.is_usable(),
@@ -6467,6 +6473,7 @@ impl Writeable for ChannelDetails {
                        (6, self.funding_txo, option),
                        (7, self.config, option),
                        (8, self.short_channel_id, option),
+                       (9, self.confirmations, option),
                        (10, self.channel_value_satoshis, required),
                        (12, self.unspendable_punishment_reserve, option),
                        (14, user_channel_id_low, required),
@@ -6501,6 +6508,7 @@ impl Readable for ChannelDetails {
                        (6, funding_txo, option),
                        (7, config, option),
                        (8, short_channel_id, option),
+                       (9, confirmations, option),
                        (10, channel_value_satoshis, required),
                        (12, unspendable_punishment_reserve, option),
                        (14, user_channel_id_low, required),
@@ -6544,6 +6552,7 @@ impl Readable for ChannelDetails {
                        next_outbound_htlc_limit_msat: next_outbound_htlc_limit_msat.0.unwrap(),
                        inbound_capacity_msat: inbound_capacity_msat.0.unwrap(),
                        confirmations_required,
+                       confirmations,
                        force_close_spend_delay,
                        is_outbound: is_outbound.0.unwrap(),
                        is_channel_ready: is_channel_ready.0.unwrap(),
index f6754e8bf2dc8d6e11f0a56370117436bddd57cb..91d5b3070610579474b39737b518c94932e9200d 100644 (file)
@@ -277,6 +277,9 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
        assert_eq!(nodes[0].node.short_to_chan_info.read().unwrap().len(), 2);
        mem::drop(channel_state);
 
+       assert_eq!(nodes[0].node.list_channels()[0].confirmations, Some(10));
+       assert_eq!(nodes[1].node.list_channels()[0].confirmations, Some(10));
+
        if !reorg_after_reload {
                if use_funding_unconfirmed {
                        let relevant_txids = nodes[0].node.get_relevant_txids();
@@ -287,12 +290,16 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
                        let txid = relevant_txids[0].0;
                        assert_eq!(txid, chan.3.txid());
                        nodes[0].node.transaction_unconfirmed(&txid);
+                       assert_eq!(nodes[0].node.list_usable_channels().len(), 0);
                } else if connect_style == ConnectStyle::FullBlockViaListen {
                        disconnect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH - 1);
                        assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
+                       assert_eq!(nodes[0].node.list_channels()[0].confirmations, Some(1));
                        disconnect_blocks(&nodes[0], 1);
+                       assert_eq!(nodes[0].node.list_usable_channels().len(), 0);
                } else {
                        disconnect_all_blocks(&nodes[0]);
+                       assert_eq!(nodes[0].node.list_usable_channels().len(), 0);
                }
 
                let relevant_txids = nodes[0].node.get_relevant_txids();
@@ -334,12 +341,16 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
                        let txid = relevant_txids[0].0;
                        assert_eq!(txid, chan.3.txid());
                        nodes[0].node.transaction_unconfirmed(&txid);
+                       assert_eq!(nodes[0].node.list_channels().len(), 0);
                } else if connect_style == ConnectStyle::FullBlockViaListen {
                        disconnect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH - 1);
                        assert_eq!(nodes[0].node.list_channels().len(), 1);
+                       assert_eq!(nodes[0].node.list_channels()[0].confirmations, Some(1));
                        disconnect_blocks(&nodes[0], 1);
+                       assert_eq!(nodes[0].node.list_usable_channels().len(), 0);
                } else {
                        disconnect_all_blocks(&nodes[0]);
+                       assert_eq!(nodes[0].node.list_usable_channels().len(), 0);
                }
 
                let relevant_txids = nodes[0].node.get_relevant_txids();
index 2d3eed6614543cfebf78f1915dc691a04c5d56b0..12306ac92ad13d68f4ee0be0f4c72b3b2161509a 100644 (file)
@@ -2048,6 +2048,7 @@ mod tests {
                        inbound_capacity_msat: 42,
                        unspendable_punishment_reserve: None,
                        confirmations_required: None,
+                       confirmations: None,
                        force_close_spend_delay: None,
                        is_outbound: true, is_channel_ready: true,
                        is_usable: true, is_public: true,
@@ -5562,6 +5563,7 @@ mod benches {
                        inbound_capacity_msat: 0,
                        unspendable_punishment_reserve: None,
                        confirmations_required: None,
+                       confirmations: None,
                        force_close_spend_delay: None,
                        is_outbound: true,
                        is_channel_ready: true,