@@ -167,10 +167,17 @@ struct MonitorHolder<ChannelSigner: EcdsaChannelSigner> {
167
167
monitor : ChannelMonitor < ChannelSigner > ,
168
168
/// The full set of pending monitor updates for this Channel.
169
169
///
170
- /// Note that this lock must be held during updates to prevent a race where we call
171
- /// update_persisted_channel, the user returns a
170
+ /// Note that this lock must be held from [`ChannelMonitor::update_monitor`] through to
171
+ /// [`Persist::update_persisted_channel`] to prevent a race where we call
172
+ /// [`Persist::update_persisted_channel`], the user returns a
172
173
/// [`ChannelMonitorUpdateStatus::InProgress`], and then calls channel_monitor_updated
173
174
/// immediately, racing our insertion of the pending update into the contained Vec.
175
+ ///
176
+ /// This also avoids a race where we update a [`ChannelMonitor`], then while connecting a block
177
+ /// persist a full [`ChannelMonitor`] prior to persisting the [`ChannelMonitorUpdate`]. This
178
+ /// could cause users to have a full [`ChannelMonitor`] on disk as well as a
179
+ /// [`ChannelMonitorUpdate`] which was already applied. While this isn't an issue for the
180
+ /// LDK-provided update-based [`Persist`], its somewhat surprising for users so we avoid it.
174
181
pending_monitor_updates : Mutex < Vec < u64 > > ,
175
182
}
176
183
@@ -322,6 +329,11 @@ where C::Target: chain::Filter,
322
329
let has_pending_claims = monitor_state. monitor . has_pending_claims ( ) ;
323
330
if has_pending_claims || get_partition_key ( funding_outpoint) % partition_factor == 0 {
324
331
log_trace ! ( logger, "Syncing Channel Monitor for channel {}" , log_funding_info!( monitor) ) ;
332
+ // Even though we don't track monitor updates from chain-sync as pending, we still want
333
+ // updates per-channel to be well-ordered so that users don't see a
334
+ // `ChannelMonitorUpdate` after a channel persist for a channel with the same
335
+ // `latest_update_id`.
336
+ let _pending_monitor_updates = monitor_state. pending_monitor_updates . lock ( ) . unwrap ( ) ;
325
337
match self . persister . update_persisted_channel ( * funding_outpoint, None , monitor) {
326
338
ChannelMonitorUpdateStatus :: Completed =>
327
339
log_trace ! ( logger, "Finished syncing Channel Monitor for channel {} for block-data" ,
@@ -796,10 +808,14 @@ where C::Target: chain::Filter,
796
808
let monitor = & monitor_state. monitor ;
797
809
let logger = WithChannelMonitor :: from ( & self . logger , & monitor, None ) ;
798
810
log_trace ! ( logger, "Updating ChannelMonitor to id {} for channel {}" , update. update_id, log_funding_info!( monitor) ) ;
811
+
812
+ // We hold a `pending_monitor_updates` lock through `update_monitor` to ensure we
813
+ // have well-ordered updates from the users' point of view. See the
814
+ // `pending_monitor_updates` docs for more.
815
+ let mut pending_monitor_updates = monitor_state. pending_monitor_updates . lock ( ) . unwrap ( ) ;
799
816
let update_res = monitor. update_monitor ( update, & self . broadcaster , & self . fee_estimator , & self . logger ) ;
800
817
801
818
let update_id = update. update_id ;
802
- let mut pending_monitor_updates = monitor_state. pending_monitor_updates . lock ( ) . unwrap ( ) ;
803
819
let persist_res = if update_res. is_err ( ) {
804
820
// Even if updating the monitor returns an error, the monitor's state will
805
821
// still be changed. Therefore, we should persist the updated monitor despite the error.
0 commit comments