Skip to content

Commit f5db04c

Browse files
author
Antoine Riard
committed
Implement block_disconnect for pruning of waiting-conf HTLC updates
Modify ChainListener API by adding height field to block_disconnect
1 parent aeabd67 commit f5db04c

File tree

5 files changed

+27
-8
lines changed

5 files changed

+27
-8
lines changed

fuzz/fuzz_targets/full_stack_target.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ impl<'a> MoneyLossDetector<'a> {
208208
if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) {
209209
self.height -= 1;
210210
let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
211-
self.manager.block_disconnected(&header);
212-
self.monitor.block_disconnected(&header);
211+
self.manager.block_disconnected(&header, height);
212+
self.monitor.block_disconnected(&header, height);
213213
let removal_height = self.height;
214214
self.txids_confirmed.retain(|_, height| {
215215
removal_height != *height

src/chain/chaininterface.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,11 @@ pub trait ChainListener: Sync + Send {
7777
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]);
7878
/// Notifies a listener that a block was disconnected.
7979
/// Unlike block_connected, this *must* never be called twice for the same disconnect event.
80-
fn block_disconnected(&self, header: &BlockHeader);
80+
///
81+
/// Provide listeners with filtered txn previously registered as watched because channels are
82+
/// driven by onchain events (tx broadcast, height), a cancel of one of them may conduct to
83+
/// rollback state (ChannelMonitor or Channel).
84+
fn block_disconnected(&self, header: &BlockHeader, height: u32);
8185
}
8286

8387
/// An enum that represents the speed at which we want a transaction to confirm used for feerate
@@ -278,11 +282,11 @@ impl ChainWatchInterfaceUtil {
278282
}
279283

280284
/// Notify listeners that a block was disconnected.
281-
pub fn block_disconnected(&self, header: &BlockHeader) {
285+
pub fn block_disconnected(&self, block: &Block, height: u32) {
282286
let listeners = self.listeners.lock().unwrap().clone();
283287
for listener in listeners.iter() {
284288
match listener.upgrade() {
285-
Some(arc) => arc.block_disconnected(header),
289+
Some(arc) => arc.block_disconnected(&block.header, height),
286290
None => ()
287291
}
288292
}

src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2473,7 +2473,7 @@ impl ChainListener for ChannelManager {
24732473
}
24742474

24752475
/// We force-close the channel without letting our counterparty participate in the shutdown
2476-
fn block_disconnected(&self, header: &BlockHeader) {
2476+
fn block_disconnected(&self, header: &BlockHeader, _: u32) {
24772477
let _ = self.total_consistency_lock.read().unwrap();
24782478
let mut failed_channels = Vec::new();
24792479
{

src/ln/channelmonitor.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,13 @@ impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonit
195195
pending_events.append(&mut new_events);
196196
}
197197

198-
fn block_disconnected(&self, _: &BlockHeader) { }
198+
fn block_disconnected(&self, header: &BlockHeader, height: u32) {
199+
let block_hash = header.bitcoin_hash();
200+
let mut monitors = self.monitors.lock().unwrap();
201+
for monitor in monitors.values_mut() {
202+
monitor.block_disconnected(height, &block_hash);
203+
}
204+
}
199205
}
200206

201207
impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key> {
@@ -1811,6 +1817,13 @@ impl ChannelMonitor {
18111817
(watch_outputs, spendable_outputs, htlc_updated)
18121818
}
18131819

1820+
fn block_disconnected(&mut self, height: u32, block_hash: &Sha256dHash) {
1821+
if let Some(_) = self.htlc_updated_waiting_threshold_conf.remove(&(height + HTLC_FAIL_ANTI_REORG_DELAY - 1)) {
1822+
//We discard htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
1823+
}
1824+
self.last_block_hash = block_hash.clone();
1825+
}
1826+
18141827
pub(super) fn would_broadcast_at_height(&self, height: u32) -> bool {
18151828
// We need to consider all HTLCs which are:
18161829
// * in any unrevoked remote commitment transaction, as they could broadcast said

src/ln/functional_tests.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2526,8 +2526,10 @@ fn test_unconf_chan() {
25262526
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
25272527
headers.push(header.clone());
25282528
}
2529+
let mut height = 99;
25292530
while !headers.is_empty() {
2530-
nodes[0].node.block_disconnected(&headers.pop().unwrap());
2531+
nodes[0].node.block_disconnected(&headers.pop().unwrap(), height);
2532+
height -= 1;
25312533
}
25322534
check_closed_broadcast!(nodes[0]);
25332535
let channel_state = nodes[0].node.channel_state.lock().unwrap();

0 commit comments

Comments
 (0)