From 587af43eca7dc254bf0feb96d4732fd56cf6fcc3 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Mon, 4 Feb 2019 21:21:11 -0500 Subject: [PATCH] Implement block_disconnect for pruning of waiting-conf HTLC updates Modify ChainListener API by adding height field to block_disconnect --- fuzz/fuzz_targets/full_stack_target.rs | 4 ++-- src/chain/chaininterface.rs | 7 ++++--- src/ln/channelmanager.rs | 2 +- src/ln/channelmonitor.rs | 15 ++++++++++++++- src/ln/functional_tests.rs | 4 +++- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/fuzz/fuzz_targets/full_stack_target.rs b/fuzz/fuzz_targets/full_stack_target.rs index 16bebfbd0..8737f6c26 100644 --- a/fuzz/fuzz_targets/full_stack_target.rs +++ b/fuzz/fuzz_targets/full_stack_target.rs @@ -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 diff --git a/src/chain/chaininterface.rs b/src/chain/chaininterface.rs index d1995b442..c0330fb29 100644 --- a/src/chain/chaininterface.rs +++ b/src/chain/chaininterface.rs @@ -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 => () } } diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index 3ffd080e9..201865d67 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -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(); { diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index 178760e10..379ae31c3 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -201,7 +201,13 @@ impl 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 SimpleManyChannelMonitor { @@ -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 diff --git a/src/ln/functional_tests.rs b/src/ln/functional_tests.rs index 6d1209d99..ec3304b39 100644 --- a/src/ln/functional_tests.rs +++ b/src/ln/functional_tests.rs @@ -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(); -- 2.39.5