Return confirmation height via `Confirm::get_relevant_txids`
authorElias Rohrer <dev@tnull.de>
Mon, 13 Nov 2023 10:00:41 +0000 (11:00 +0100)
committerElias Rohrer <dev@tnull.de>
Thu, 23 Nov 2023 08:30:56 +0000 (09:30 +0100)
We previously included the block hash, but it's also useful to include
the height under which we expect the respective transaction to be
confirmed.

lightning-transaction-sync/src/esplora.rs
lightning-transaction-sync/tests/integration_tests.rs
lightning/src/chain/chainmonitor.rs
lightning/src/chain/channelmonitor.rs
lightning/src/chain/mod.rs
lightning/src/chain/onchaintx.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/reorg_tests.rs
pending_changelog/electrum.txt [new file with mode: 0644]

index f68be08a5a6c648e9c61a07aa1171ea420453365..91787c629ce7752419172fbacf2cd10ebb8aea2e 100644 (file)
@@ -316,11 +316,11 @@ where
                let relevant_txids = confirmables
                        .iter()
                        .flat_map(|c| c.get_relevant_txids())
-                       .collect::<HashSet<(Txid, Option<BlockHash>)>>();
+                       .collect::<HashSet<(Txid, u32, Option<BlockHash>)>>();
 
                let mut unconfirmed_txs = Vec::new();
 
-               for (txid, block_hash_opt) in relevant_txids {
+               for (txid, _conf_height, block_hash_opt) in relevant_txids {
                        if let Some(block_hash) = block_hash_opt {
                                let block_status = maybe_await!(self.client.get_block_status(&block_hash))?;
                                if block_status.in_best_chain {
index 8a69dce3f3db1d4f7003193e0b039bb4b9d8836d..218d187a441c647d618ca3ced0cc631e8bc7d915 100644 (file)
@@ -143,8 +143,8 @@ impl Confirm for TestConfirmable {
                self.events.lock().unwrap().push(TestConfirmableEvent::BestBlockUpdated(block_hash, height));
        }
 
-       fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)> {
-               self.confirmed_txs.lock().unwrap().iter().map(|(&txid, (hash, _))| (txid, Some(*hash))).collect::<Vec<_>>()
+       fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
+               self.confirmed_txs.lock().unwrap().iter().map(|(&txid, (hash, height))| (txid, *height, Some(*hash))).collect::<Vec<_>>()
        }
 }
 
index 0186ac374884c82bdbfe4f0d63e1bc4ba0c37343..800bee8e3b397433a70c2d03e6a83ae2fccc6436 100644 (file)
@@ -689,15 +689,15 @@ where
                });
        }
 
-       fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)> {
+       fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
                let mut txids = Vec::new();
                let monitor_states = self.monitors.read().unwrap();
                for monitor_state in monitor_states.values() {
                        txids.append(&mut monitor_state.monitor.get_relevant_txids());
                }
 
-               txids.sort_unstable();
-               txids.dedup();
+               txids.sort_unstable_by(|a, b| a.0.cmp(&b.0).then(b.1.cmp(&a.1)));
+               txids.dedup_by_key(|(txid, _, _)| *txid);
                txids
        }
 }
index d78f40f3facf3bccec9ced5e483e74bb4bea969d..65b58722762087035cfb43573b87c05050e3abbb 100644 (file)
@@ -1634,15 +1634,15 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
        }
 
        /// Returns the set of txids that should be monitored for re-organization out of the chain.
-       pub fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)> {
+       pub fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
                let inner = self.inner.lock().unwrap();
-               let mut txids: Vec<(Txid, Option<BlockHash>)> = inner.onchain_events_awaiting_threshold_conf
+               let mut txids: Vec<(Txid, u32, Option<BlockHash>)> = inner.onchain_events_awaiting_threshold_conf
                        .iter()
-                       .map(|entry| (entry.txid, entry.block_hash))
+                       .map(|entry| (entry.txid, entry.height, entry.block_hash))
                        .chain(inner.onchain_tx_handler.get_relevant_txids().into_iter())
                        .collect();
-               txids.sort_unstable();
-               txids.dedup();
+               txids.sort_unstable_by(|a, b| a.0.cmp(&b.0).then(b.1.cmp(&a.1)));
+               txids.dedup_by_key(|(txid, _, _)| *txid);
                txids
        }
 
@@ -4171,7 +4171,7 @@ where
                self.0.best_block_updated(header, height, &*self.1, &*self.2, &*self.3);
        }
 
-       fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)> {
+       fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
                self.0.get_relevant_txids()
        }
 }
index 239f7c91dbc5d09c433db0ccf53306ca43385034..a7c3a6d88badf6d41f9e4873b26eb4e2e4b2db86 100644 (file)
@@ -152,7 +152,7 @@ pub trait Confirm {
        /// blocks.
        fn best_block_updated(&self, header: &Header, height: u32);
        /// Returns transactions that must be monitored for reorganization out of the chain along
-       /// with the hash of the block as part of which it had been previously confirmed.
+       /// with the height and the hash of the block as part of which it had been previously confirmed.
        ///
        /// Note that the returned `Option<BlockHash>` might be `None` for channels created with LDK
        /// 0.0.112 and prior, in which case you need to manually track previous confirmations.
@@ -167,12 +167,12 @@ pub trait Confirm {
        /// given to [`transaction_unconfirmed`].
        ///
        /// If any of the returned transactions are confirmed in a block other than the one with the
-       /// given hash, they need to be unconfirmed and reconfirmed via [`transaction_unconfirmed`] and
-       /// [`transactions_confirmed`], respectively.
+       /// given hash at the given height, they need to be unconfirmed and reconfirmed via
+       /// [`transaction_unconfirmed`] and [`transactions_confirmed`], respectively.
        ///
        /// [`transactions_confirmed`]: Self::transactions_confirmed
        /// [`transaction_unconfirmed`]: Self::transaction_unconfirmed
-       fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)>;
+       fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)>;
 }
 
 /// An enum representing the status of a channel monitor update persistence.
index 2573854898cf278c7e63dbad331d531cc313c641..c28c572e6b5145980611a38bb4121188d4fcbbe9 100644 (file)
@@ -1076,13 +1076,13 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                self.claimable_outpoints.get(outpoint).is_some()
        }
 
-       pub(crate) fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)> {
-               let mut txids: Vec<(Txid, Option<BlockHash>)> = self.onchain_events_awaiting_threshold_conf
+       pub(crate) fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
+               let mut txids: Vec<(Txid, u32, Option<BlockHash>)> = self.onchain_events_awaiting_threshold_conf
                        .iter()
-                       .map(|entry| (entry.txid, entry.block_hash))
+                       .map(|entry| (entry.txid, entry.height, entry.block_hash))
                        .collect();
-               txids.sort_unstable_by_key(|(txid, _)| *txid);
-               txids.dedup();
+               txids.sort_unstable_by(|a, b| a.0.cmp(&b.0).then(b.1.cmp(&a.1)));
+               txids.dedup_by_key(|(txid, _, _)| *txid);
                txids
        }
 
index 6803b11284b95c1539a7585b5b0f0fced28bfe8e..740d26448073492e5fcaad20170231a8e9012681 100644 (file)
@@ -1111,6 +1111,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                self.channel_transaction_parameters.funding_outpoint
        }
 
+       /// Returns the height in which our funding transaction was confirmed.
+       pub fn get_funding_tx_confirmation_height(&self) -> Option<u32> {
+               let conf_height = self.funding_tx_confirmation_height;
+               if conf_height > 0 {
+                       Some(conf_height)
+               } else {
+                       None
+               }
+       }
+
        /// Returns the block hash in which our funding transaction was confirmed.
        pub fn get_funding_tx_confirmed_in(&self) -> Option<BlockHash> {
                self.funding_tx_confirmed_in
index c40ab4858b1a68921999ca7bddb44ee663d64c07..3f6277b44bbfc57cf38438b74540b0c295f187bf 100644 (file)
@@ -8336,14 +8336,17 @@ where
                });
        }
 
-       fn get_relevant_txids(&self) -> Vec<(Txid, Option<BlockHash>)> {
+       fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
                let mut res = Vec::with_capacity(self.short_to_chan_info.read().unwrap().len());
                for (_cp_id, peer_state_mutex) in self.per_peer_state.read().unwrap().iter() {
                        let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                        let peer_state = &mut *peer_state_lock;
                        for chan in peer_state.channel_by_id.values().filter_map(|phase| if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None }) {
-                               if let (Some(funding_txo), Some(block_hash)) = (chan.context.get_funding_txo(), chan.context.get_funding_tx_confirmed_in()) {
-                                       res.push((funding_txo.txid, Some(block_hash)));
+                               let txid_opt = chan.context.get_funding_txo();
+                               let height_opt = chan.context.get_funding_tx_confirmation_height();
+                               let hash_opt = chan.context.get_funding_tx_confirmed_in();
+                               if let (Some(funding_txo), Some(conf_height), Some(block_hash)) = (txid_opt, height_opt, hash_opt) {
+                                       res.push((funding_txo.txid, conf_height, Some(block_hash)));
                                }
                        }
                }
index b745453a3c6799e012ddf3368be4136ef4831653..badb78f245a6651be0abffc415565142e4c7bcf5 100644 (file)
@@ -270,8 +270,9 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
                if use_funding_unconfirmed {
                        let relevant_txids = nodes[0].node.get_relevant_txids();
                        assert_eq!(relevant_txids.len(), 1);
-                       let block_hash_opt = relevant_txids[0].1;
+                       let block_hash_opt = relevant_txids[0].2;
                        let expected_hash = nodes[0].get_block_header(chan_conf_height).block_hash();
+                       assert_eq!(relevant_txids[0].1, chan_conf_height);
                        assert_eq!(block_hash_opt, Some(expected_hash));
                        let txid = relevant_txids[0].0;
                        assert_eq!(txid, chan.3.txid());
@@ -315,8 +316,9 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
                if use_funding_unconfirmed {
                        let relevant_txids = nodes[0].node.get_relevant_txids();
                        assert_eq!(relevant_txids.len(), 1);
-                       let block_hash_opt = relevant_txids[0].1;
+                       let block_hash_opt = relevant_txids[0].2;
                        let expected_hash = nodes[0].get_block_header(chan_conf_height).block_hash();
+                       assert_eq!(chan_conf_height, relevant_txids[0].1);
                        assert_eq!(block_hash_opt, Some(expected_hash));
                        let txid = relevant_txids[0].0;
                        assert_eq!(txid, chan.3.txid());
diff --git a/pending_changelog/electrum.txt b/pending_changelog/electrum.txt
new file mode 100644 (file)
index 0000000..5171f5e
--- /dev/null
@@ -0,0 +1,3 @@
+## API Updates
+
+- The `Confirm::get_relevant_txids()` call now also returns the height under which LDK expects the respective transaction to be confirmed.