Skip to content

Commit 278296c

Browse files
committed
Always release MonitorEvents to ChannelManager after 3 blocks
If we have a `ChannelMonitor` update from an on-chain event which returns a `TemporaryFailure`, we block `MonitorEvent`s from that `ChannelMonitor` until the update is persisted. This prevents duplicate payment send events to the user after payments get reloaded from monitors on restart. However, if the event being avoided isn't going to generate a PaymentSent, but instead result in us claiming an HTLC from an upstream channel (ie the HTLC was forwarded), then the result of a user delaying the event is that we delay getting our money, not a duplicate event. Because user persistence may take an arbitrary amount of time, we need to bound the amount of time we can possibly wait to return events, which we do here by bounding it to 3 blocks. Thanks to Val for catching this in review.
1 parent 8c8ece8 commit 278296c

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

lightning/src/chain/chainmonitor.rs

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use bitcoin::hash_types::Txid;
2929
use chain;
3030
use chain::{ChannelMonitorUpdateErr, Filter, WatchedOutput};
3131
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
32-
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, Balance, MonitorEvent, TransactionOutputs};
32+
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, Balance, MonitorEvent, TransactionOutputs, LATENCY_GRACE_PERIOD_BLOCKS};
3333
use chain::transaction::{OutPoint, TransactionData};
3434
use chain::keysinterface::Sign;
3535
use util::atomic_counter::AtomicCounter;
@@ -42,7 +42,7 @@ use ln::channelmanager::ChannelDetails;
4242
use prelude::*;
4343
use sync::{RwLock, RwLockReadGuard, Mutex, MutexGuard};
4444
use core::ops::Deref;
45-
use core::sync::atomic::{AtomicBool, Ordering};
45+
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
4646

4747
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
4848
/// A specific update's ID stored in a `MonitorUpdateId`, separated out to make the contents
@@ -168,6 +168,13 @@ struct MonitorHolder<ChannelSigner: Sign> {
168168
/// processed the closure event, we set this to true and return PermanentFailure for any other
169169
/// chain::Watch events.
170170
channel_perm_failed: AtomicBool,
171+
/// The last block height at which no [`UpdateOrigin::ChainSync`] monitor updates were present
172+
/// in `pending_monitor_updates`.
173+
/// If it's been more than [`LATENCY_GRACE_PERIOD_BLOCKS`] since we started waiting on a chain
174+
/// sync event, we let monitor events return to `ChannelManager` because we cannot hold them up
175+
/// forever or we'll end up with HTLC preimages waiting to feed back into an upstream channel
176+
/// forever, risking funds loss.
177+
last_chain_persist_height: AtomicUsize,
171178
}
172179

173180
impl<ChannelSigner: Sign> MonitorHolder<ChannelSigner> {
@@ -226,6 +233,8 @@ pub struct ChainMonitor<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: De
226233
/// "User-provided" (ie persistence-completion/-failed) [`MonitorEvent`]s. These came directly
227234
/// from the user and not from a [`ChannelMonitor`].
228235
pending_monitor_events: Mutex<Vec<MonitorEvent>>,
236+
/// The best block height seen, used as a proxy for the passage of time.
237+
highest_chain_height: AtomicUsize,
229238
}
230239

231240
impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref> ChainMonitor<ChannelSigner, C, T, F, L, P>
@@ -244,11 +253,16 @@ where C::Target: chain::Filter,
244253
/// calls must not exclude any transactions matching the new outputs nor any in-block
245254
/// descendants of such transactions. It is not necessary to re-fetch the block to obtain
246255
/// updated `txdata`.
247-
fn process_chain_data<FN>(&self, header: &BlockHeader, txdata: &TransactionData, process: FN)
256+
///
257+
/// Calls which represent a new blockchain tip height should set `best_height`.
258+
fn process_chain_data<FN>(&self, header: &BlockHeader, best_height: Option<u32>, txdata: &TransactionData, process: FN)
248259
where
249260
FN: Fn(&ChannelMonitor<ChannelSigner>, &TransactionData) -> Vec<TransactionOutputs>
250261
{
251262
let mut dependent_txdata = Vec::new();
263+
if let Some(height) = best_height {
264+
self.highest_chain_height.store(height as usize, Ordering::Release);
265+
}
252266
{
253267
let monitor_states = self.monitors.write().unwrap();
254268
for (funding_outpoint, monitor_state) in monitor_states.iter() {
@@ -260,6 +274,14 @@ where C::Target: chain::Filter,
260274
contents: UpdateOrigin::ChainSync(self.sync_persistence_id.get_increment()),
261275
};
262276
let mut pending_monitor_updates = monitor_state.pending_monitor_updates.lock().unwrap();
277+
if let Some(height) = best_height {
278+
if !monitor_state.has_pending_chainsync_updates(&pending_monitor_updates) {
279+
// If there are not ChainSync persists awaiting completion, go ahead and
280+
// set last_chain_persist_height here - we wouldn't want the first
281+
// TemporaryFailure to always immediately be considered "overly delayed".
282+
monitor_state.last_chain_persist_height.store(height as usize, Ordering::Release);
283+
}
284+
}
263285

264286
log_trace!(self.logger, "Syncing Channel Monitor for channel {}", log_funding_info!(monitor));
265287
match self.persister.update_persisted_channel(*funding_outpoint, &None, monitor, update_id) {
@@ -304,7 +326,7 @@ where C::Target: chain::Filter,
304326
dependent_txdata.sort_unstable_by_key(|(index, _tx)| *index);
305327
dependent_txdata.dedup_by_key(|(index, _tx)| *index);
306328
let txdata: Vec<_> = dependent_txdata.iter().map(|(index, tx)| (*index, tx)).collect();
307-
self.process_chain_data(header, &txdata, process);
329+
self.process_chain_data(header, None, &txdata, process); // We skip the best height the second go-around
308330
}
309331
}
310332

@@ -325,6 +347,7 @@ where C::Target: chain::Filter,
325347
fee_estimator: feeest,
326348
persister,
327349
pending_monitor_events: Mutex::new(Vec::new()),
350+
highest_chain_height: AtomicUsize::new(0),
328351
}
329352
}
330353

@@ -428,9 +451,11 @@ where C::Target: chain::Filter,
428451
});
429452
},
430453
MonitorUpdateId { contents: UpdateOrigin::ChainSync(_) } => {
431-
// We've already done everything we need to, the next time
432-
// release_pending_monitor_events is called, any events for this ChannelMonitor
433-
// will be returned if there's no more SyncPersistId events left.
454+
if !monitor_data.has_pending_chainsync_updates(&pending_monitor_updates) {
455+
monitor_data.last_chain_persist_height.store(self.highest_chain_height.load(Ordering::Acquire), Ordering::Release);
456+
// The next time release_pending_monitor_events is called, any events for this
457+
// ChannelMonitor will be returned.
458+
}
434459
},
435460
}
436461
Ok(())
@@ -470,7 +495,7 @@ where
470495
let header = &block.header;
471496
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
472497
log_debug!(self.logger, "New best block {} at height {} provided via block_connected", header.block_hash(), height);
473-
self.process_chain_data(header, &txdata, |monitor, txdata| {
498+
self.process_chain_data(header, Some(height), &txdata, |monitor, txdata| {
474499
monitor.block_connected(
475500
header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger)
476501
});
@@ -497,7 +522,7 @@ where
497522
{
498523
fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) {
499524
log_debug!(self.logger, "{} provided transactions confirmed at height {} in block {}", txdata.len(), height, header.block_hash());
500-
self.process_chain_data(header, txdata, |monitor, txdata| {
525+
self.process_chain_data(header, None, txdata, |monitor, txdata| {
501526
monitor.transactions_confirmed(
502527
header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger)
503528
});
@@ -513,7 +538,7 @@ where
513538

514539
fn best_block_updated(&self, header: &BlockHeader, height: u32) {
515540
log_debug!(self.logger, "New best block {} at height {} provided via best_block_updated", header.block_hash(), height);
516-
self.process_chain_data(header, &[], |monitor, txdata| {
541+
self.process_chain_data(header, Some(height), &[], |monitor, txdata| {
517542
// While in practice there shouldn't be any recursive calls when given empty txdata,
518543
// it's still possible if a chain::Filter implementation returns a transaction.
519544
debug_assert!(txdata.is_empty());
@@ -580,6 +605,7 @@ where C::Target: chain::Filter,
580605
monitor,
581606
pending_monitor_updates: Mutex::new(pending_monitor_updates),
582607
channel_perm_failed: AtomicBool::new(false),
608+
last_chain_persist_height: AtomicUsize::new(self.highest_chain_height.load(Ordering::Acquire)),
583609
});
584610
persist_res
585611
}
@@ -636,7 +662,10 @@ where C::Target: chain::Filter,
636662
let mut pending_monitor_events = self.pending_monitor_events.lock().unwrap().split_off(0);
637663
for monitor_state in self.monitors.read().unwrap().values() {
638664
let is_pending_monitor_update = monitor_state.has_pending_chainsync_updates(&monitor_state.pending_monitor_updates.lock().unwrap());
639-
if is_pending_monitor_update {
665+
if is_pending_monitor_update &&
666+
monitor_state.last_chain_persist_height.load(Ordering::Acquire) + LATENCY_GRACE_PERIOD_BLOCKS as usize
667+
> self.highest_chain_height.load(Ordering::Acquire)
668+
{
640669
log_info!(self.logger, "A Channel Monitor sync is still in progress, refusing to provide monitor events!");
641670
} else {
642671
if monitor_state.channel_perm_failed.load(Ordering::Acquire) {
@@ -650,6 +679,11 @@ where C::Target: chain::Filter,
650679
// updated.
651680
log_info!(self.logger, "A Channel Monitor sync returned PermanentFailure. Returning monitor events but duplicate events may appear after reload!");
652681
}
682+
if is_pending_monitor_update {
683+
log_error!(self.logger, "A ChannelMonitor sync took longer than {} blocks to complete.", LATENCY_GRACE_PERIOD_BLOCKS);
684+
log_error!(self.logger, " To avoid funds-loss, we are allowing monitor updates to be released.");
685+
log_error!(self.logger, " This may cause duplicate payment events to be generated.");
686+
}
653687
pending_monitor_events.append(&mut monitor_state.monitor.get_and_clear_pending_monitor_events());
654688
}
655689
}

0 commit comments

Comments
 (0)