Implement block_disconnect for pruning of waiting-conf HTLC updates
authorAntoine Riard <ariard@student.42.fr>
Tue, 5 Feb 2019 02:21:11 +0000 (21:21 -0500)
committerAntoine Riard <ariard@student.42.fr>
Wed, 17 Jul 2019 19:26:33 +0000 (15:26 -0400)
Modify ChainListener API by adding height field to block_disconnect

fuzz/fuzz_targets/full_stack_target.rs
src/chain/chaininterface.rs
src/ln/channelmanager.rs
src/ln/channelmonitor.rs
src/ln/functional_tests.rs

index 16bebfbd01bde8b64908d5cbf58ab0645d67a794..8737f6c262bbb679cdd09e9bf01e4289fb544b70 100644 (file)
@@ -209,8 +209,8 @@ impl<'a> MoneyLossDetector<'a> {
                if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) {
                        self.height -= 1;
                        let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-                       self.manager.block_disconnected(&header);
-                       self.monitor.block_disconnected(&header);
+                       self.manager.block_disconnected(&header, self.height as u32);
+                       self.monitor.block_disconnected(&header, self.height as u32);
                        let removal_height = self.height;
                        self.txids_confirmed.retain(|_, height| {
                                removal_height != *height
index d1995b44221082bb5e9d668d63efbbb73bb81581..c0330fb2963ea868d753c16dd633d5cbbd8890c9 100644 (file)
@@ -78,7 +78,8 @@ pub trait ChainListener: Sync + Send {
        fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]);
        /// Notifies a listener that a block was disconnected.
        /// Unlike block_connected, this *must* never be called twice for the same disconnect event.
-       fn block_disconnected(&self, header: &BlockHeader);
+       /// Height must be the one of the block which was disconnected (not new height of the best chain)
+       fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32);
 }
 
 /// An enum that represents the speed at which we want a transaction to confirm used for feerate
@@ -279,11 +280,11 @@ impl ChainWatchInterfaceUtil {
        }
 
        /// Notify listeners that a block was disconnected.
-       pub fn block_disconnected(&self, header: &BlockHeader) {
+       pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
                let listeners = self.listeners.lock().unwrap().clone();
                for listener in listeners.iter() {
                        match listener.upgrade() {
-                               Some(arc) => arc.block_disconnected(header),
+                               Some(arc) => arc.block_disconnected(&header, disconnected_height),
                                None => ()
                        }
                }
index 3ffd080e9158f63625af30a1dcad3dda363154f7..201865d67386fc920b8c7c162f157eb049493779 100644 (file)
@@ -2474,7 +2474,7 @@ impl ChainListener for ChannelManager {
        }
 
        /// We force-close the channel without letting our counterparty participate in the shutdown
-       fn block_disconnected(&self, header: &BlockHeader) {
+       fn block_disconnected(&self, header: &BlockHeader, _: u32) {
                let _ = self.total_consistency_lock.read().unwrap();
                let mut failed_channels = Vec::new();
                {
index 178760e104352cfc21e90bec6a3952c6d186ffab..379ae31c3ebb68cdab7542a5295d54fbca852971 100644 (file)
@@ -201,7 +201,13 @@ impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonit
                pending_events.append(&mut new_events);
        }
 
-       fn block_disconnected(&self, _: &BlockHeader) { }
+       fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
+               let block_hash = header.bitcoin_hash();
+               let mut monitors = self.monitors.lock().unwrap();
+               for monitor in monitors.values_mut() {
+                       monitor.block_disconnected(disconnected_height, &block_hash);
+               }
+       }
 }
 
 impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key> {
@@ -1912,6 +1918,13 @@ impl ChannelMonitor {
                (watch_outputs, spendable_outputs, htlc_updated)
        }
 
+       fn block_disconnected(&mut self, height: u32, block_hash: &Sha256dHash) {
+               if let Some(_) = self.htlc_updated_waiting_threshold_conf.remove(&(height + HTLC_FAIL_ANTI_REORG_DELAY - 1)) {
+                       //We discard htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
+               }
+               self.last_block_hash = block_hash.clone();
+       }
+
        pub(super) fn would_broadcast_at_height(&self, height: u32) -> bool {
                // We need to consider all HTLCs which are:
                //  * in any unrevoked remote commitment transaction, as they could broadcast said
index 6d1209d996eafd84dbc94c1894bd6554f32eee44..ec3304b399ac53ccdc6e79663462dcdb94bac79e 100644 (file)
@@ -2674,8 +2674,10 @@ fn test_unconf_chan() {
                header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
                headers.push(header.clone());
        }
+       let mut height = 99;
        while !headers.is_empty() {
-               nodes[0].node.block_disconnected(&headers.pop().unwrap());
+               nodes[0].node.block_disconnected(&headers.pop().unwrap(), height);
+               height -= 1;
        }
        check_closed_broadcast!(nodes[0]);
        let channel_state = nodes[0].node.channel_state.lock().unwrap();