Skip to content

Commit 0fe1f28

Browse files
committed
Rework chain::Watch return types to make async updates less scary
When a `chain::Watch` `ChannelMonitor` update method is called, the user has three options: (a) persist the monitor update immediately and return success, (b) fail to persist the monitor update immediately and return failure, (c) return a flag indicating the monitor update is in progress and will complete in the future. (c) is rather harmless, and in some deployments should be expected to be the return value for all monitor update calls, but currently requires returning `Err(ChannelMonitorUpdateErr::TemporaryFailure)` which isn't very descriptive and sounds scarier than it is. Instead, here, we change the return type used to be a single enum (rather than a Result) and rename `TemporaryFailure` `UpdateInProgress`.
1 parent 1fdfc7f commit 0fe1f28

13 files changed

+396
-341
lines changed

lightning-persister/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ mod tests {
135135
use bitcoin::blockdata::block::{Block, BlockHeader};
136136
use bitcoin::hashes::hex::FromHex;
137137
use bitcoin::Txid;
138-
use lightning::chain::ChannelMonitorUpdateErr;
138+
use lightning::chain::ChannelMonitorUpdateResult;
139139
use lightning::chain::chainmonitor::Persist;
140140
use lightning::chain::transaction::OutPoint;
141141
use lightning::{check_closed_broadcast, check_closed_event, check_added_monitors};
@@ -266,7 +266,7 @@ mod tests {
266266
index: 0
267267
};
268268
match persister.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) {
269-
Err(ChannelMonitorUpdateErr::PermanentFailure) => {},
269+
ChannelMonitorUpdateResult::PermanentFailure => {},
270270
_ => panic!("unexpected result from persisting new channel")
271271
}
272272

@@ -303,7 +303,7 @@ mod tests {
303303
index: 0
304304
};
305305
match persister.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) {
306-
Err(ChannelMonitorUpdateErr::PermanentFailure) => {},
306+
ChannelMonitorUpdateResult::PermanentFailure => {},
307307
_ => panic!("unexpected result from persisting new channel")
308308
}
309309

lightning/src/chain/chainmonitor.rs

+55-43
Large diffs are not rendered by default.

lightning/src/chain/channelmonitor.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ pub struct ChannelMonitorUpdate {
6969
/// increasing and increase by one for each new update, with one exception specified below.
7070
///
7171
/// This sequence number is also used to track up to which points updates which returned
72-
/// [`ChannelMonitorUpdateErr::TemporaryFailure`] have been applied to all copies of a given
72+
/// [`ChannelMonitorUpdateResult::UpdateInProgress`] have been applied to all copies of a given
7373
/// ChannelMonitor when ChannelManager::channel_monitor_updated is called.
7474
///
7575
/// The only instance where update_id values are not strictly increasing is the case where we
7676
/// allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See
7777
/// its docs for more details.
7878
///
79-
/// [`ChannelMonitorUpdateErr::TemporaryFailure`]: super::ChannelMonitorUpdateErr::TemporaryFailure
79+
/// [`ChannelMonitorUpdateResult::UpdateInProgress`]: super::ChannelMonitorUpdateResult::UpdateInProgress
8080
pub update_id: u64,
8181
}
8282

@@ -127,9 +127,9 @@ pub enum MonitorEvent {
127127
CommitmentTxConfirmed(OutPoint),
128128

129129
/// Indicates a [`ChannelMonitor`] update has completed. See
130-
/// [`ChannelMonitorUpdateErr::TemporaryFailure`] for more information on how this is used.
130+
/// [`ChannelMonitorUpdateResult::UpdateInProgress`] for more information on how this is used.
131131
///
132-
/// [`ChannelMonitorUpdateErr::TemporaryFailure`]: super::ChannelMonitorUpdateErr::TemporaryFailure
132+
/// [`ChannelMonitorUpdateResult::UpdateInProgress`]: super::ChannelMonitorUpdateResult::UpdateInProgress
133133
UpdateCompleted {
134134
/// The funding outpoint of the [`ChannelMonitor`] that was updated
135135
funding_txo: OutPoint,
@@ -142,9 +142,9 @@ pub enum MonitorEvent {
142142
},
143143

144144
/// Indicates a [`ChannelMonitor`] update has failed. See
145-
/// [`ChannelMonitorUpdateErr::PermanentFailure`] for more information on how this is used.
145+
/// [`ChannelMonitorUpdateResult::PermanentFailure`] for more information on how this is used.
146146
///
147-
/// [`ChannelMonitorUpdateErr::PermanentFailure`]: super::ChannelMonitorUpdateErr::PermanentFailure
147+
/// [`ChannelMonitorUpdateResult::PermanentFailure`]: super::ChannelMonitorUpdateResult::PermanentFailure
148148
UpdateFailed(OutPoint),
149149
}
150150
impl_writeable_tlv_based_enum_upgradable!(MonitorEvent,
@@ -1215,7 +1215,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
12151215
/// the Channel was out-of-date.
12161216
///
12171217
/// You may also use this to broadcast the latest local commitment transaction, either because
1218-
/// a monitor update failed with [`ChannelMonitorUpdateErr::PermanentFailure`] or because we've
1218+
/// a monitor update failed with [`ChannelMonitorUpdateResult::PermanentFailure`] or because we've
12191219
/// fallen behind (i.e we've received proof that our counterparty side knows a revocation
12201220
/// secret we gave them that they shouldn't know).
12211221
///
@@ -1225,7 +1225,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
12251225
/// may be to contact the other node operator out-of-band to coordinate other options available
12261226
/// to you. In any-case, the choice is up to you.
12271227
///
1228-
/// [`ChannelMonitorUpdateErr::PermanentFailure`]: super::ChannelMonitorUpdateErr::PermanentFailure
1228+
/// [`ChannelMonitorUpdateResult::PermanentFailure`]: super::ChannelMonitorUpdateResult::PermanentFailure
12291229
pub fn get_latest_holder_commitment_txn<L: Deref>(&self, logger: &L) -> Vec<Transaction>
12301230
where L::Target: Logger {
12311231
self.inner.lock().unwrap().get_latest_holder_commitment_txn(logger)

lightning/src/chain/mod.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,13 @@ pub trait Confirm {
188188

189189
/// An error enum representing a failure to persist a channel monitor update.
190190
#[derive(Clone, Copy, Debug, PartialEq)]
191-
pub enum ChannelMonitorUpdateErr {
191+
pub enum ChannelMonitorUpdateResult {
192+
/// The update has been durably persisted and all copies of the relevant [`ChannelMonitor`]
193+
/// have been updated.
194+
///
195+
/// This includes performing any `fsync()` calls required to ensure the update is guaranteed to
196+
/// be available on restart even if the application crashes.
197+
UpdateComplete,
192198
/// Used to indicate a temporary failure (eg connection to a watchtower or remote backup of
193199
/// our state failed, but is expected to succeed at some point in the future).
194200
///
@@ -211,11 +217,12 @@ pub enum ChannelMonitorUpdateErr {
211217
///
212218
/// For deployments where a copy of ChannelMonitors and other local state are backed up in a
213219
/// remote location (with local copies persisted immediately), it is anticipated that all
214-
/// updates will return TemporaryFailure until the remote copies could be updated.
220+
/// updates will return [`UpdateInProgress`] until the remote copies could be updated.
215221
///
216-
/// [`PermanentFailure`]: ChannelMonitorUpdateErr::PermanentFailure
222+
/// [`PermanentFailure`]: ChannelMonitorUpdateResult::PermanentFailure
223+
/// [`UpdateInProgress`]: ChannelMonitorUpdateResult::UpdateInProgress
217224
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
218-
TemporaryFailure,
225+
UpdateInProgress,
219226
/// Used to indicate no further channel monitor updates will be allowed (likely a disk failure
220227
/// or a remote copy of this [`ChannelMonitor`] is no longer reachable and thus not updatable).
221228
///
@@ -252,7 +259,7 @@ pub enum ChannelMonitorUpdateErr {
252259
/// storage is used to claim outputs of rejected state confirmed onchain by another watchtower,
253260
/// lagging behind on block processing.
254261
///
255-
/// [`PermanentFailure`]: ChannelMonitorUpdateErr::PermanentFailure
262+
/// [`PermanentFailure`]: ChannelMonitorUpdateResult::PermanentFailure
256263
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
257264
PermanentFailure,
258265
}
@@ -272,32 +279,32 @@ pub enum ChannelMonitorUpdateErr {
272279
/// If an implementation maintains multiple instances of a channel's monitor (e.g., by storing
273280
/// backup copies), then it must ensure that updates are applied across all instances. Otherwise, it
274281
/// could result in a revoked transaction being broadcast, allowing the counterparty to claim all
275-
/// funds in the channel. See [`ChannelMonitorUpdateErr`] for more details about how to handle
282+
/// funds in the channel. See [`ChannelMonitorUpdateResult`] for more details about how to handle
276283
/// multiple instances.
277284
///
278-
/// [`PermanentFailure`]: ChannelMonitorUpdateErr::PermanentFailure
285+
/// [`PermanentFailure`]: ChannelMonitorUpdateResult::PermanentFailure
279286
pub trait Watch<ChannelSigner: Sign> {
280287
/// Watches a channel identified by `funding_txo` using `monitor`.
281288
///
282289
/// Implementations are responsible for watching the chain for the funding transaction along
283290
/// with any spends of outputs returned by [`get_outputs_to_watch`]. In practice, this means
284291
/// calling [`block_connected`] and [`block_disconnected`] on the monitor.
285292
///
286-
/// Note: this interface MUST error with [`ChannelMonitorUpdateErr::PermanentFailure`] if
293+
/// Note: this interface MUST error with [`ChannelMonitorUpdateResult::PermanentFailure`] if
287294
/// the given `funding_txo` has previously been registered via `watch_channel`.
288295
///
289296
/// [`get_outputs_to_watch`]: channelmonitor::ChannelMonitor::get_outputs_to_watch
290297
/// [`block_connected`]: channelmonitor::ChannelMonitor::block_connected
291298
/// [`block_disconnected`]: channelmonitor::ChannelMonitor::block_disconnected
292-
fn watch_channel(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChannelSigner>) -> Result<(), ChannelMonitorUpdateErr>;
299+
fn watch_channel(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChannelSigner>) -> ChannelMonitorUpdateResult;
293300

294301
/// Updates a channel identified by `funding_txo` by applying `update` to its monitor.
295302
///
296303
/// Implementations must call [`update_monitor`] with the given update. See
297-
/// [`ChannelMonitorUpdateErr`] for invariants around returning an error.
304+
/// [`ChannelMonitorUpdateResult`] for invariants around returning an error.
298305
///
299306
/// [`update_monitor`]: channelmonitor::ChannelMonitor::update_monitor
300-
fn update_channel(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>;
307+
fn update_channel(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> ChannelMonitorUpdateResult;
301308

302309
/// Returns any monitor events since the last call. Subsequent calls must only return new
303310
/// events.
@@ -307,7 +314,7 @@ pub trait Watch<ChannelSigner: Sign> {
307314
/// to disk.
308315
///
309316
/// For details on asynchronous [`ChannelMonitor`] updating and returning
310-
/// [`MonitorEvent::UpdateCompleted`] here, see [`ChannelMonitorUpdateErr::TemporaryFailure`].
317+
/// [`MonitorEvent::UpdateCompleted`] here, see [`ChannelMonitorUpdateResult::UpdateInProgress`].
311318
fn release_pending_monitor_events(&self) -> Vec<(OutPoint, Vec<MonitorEvent>)>;
312319
}
313320

@@ -326,9 +333,9 @@ pub trait Watch<ChannelSigner: Sign> {
326333
/// Note that use as part of a [`Watch`] implementation involves reentrancy. Therefore, the `Filter`
327334
/// should not block on I/O. Implementations should instead queue the newly monitored data to be
328335
/// processed later. Then, in order to block until the data has been processed, any [`Watch`]
329-
/// invocation that has called the `Filter` must return [`TemporaryFailure`].
336+
/// invocation that has called the `Filter` must return [`UpdateInProgress`].
330337
///
331-
/// [`TemporaryFailure`]: ChannelMonitorUpdateErr::TemporaryFailure
338+
/// [`UpdateInProgress`]: ChannelMonitorUpdateResult::UpdateInProgress
332339
/// [BIP 157]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki
333340
/// [BIP 158]: https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
334341
pub trait Filter {

0 commit comments

Comments
 (0)