Skip to content

Commit f59557f

Browse files
committed
Correctly track reloaded update_id in chanmon_consistency fuzzer
In the `chanmon_consistency` fuzzer, when reloading a node, we take a pending monitor update (or the latest persisted one) and put it in `persisted_monitor` as it is implicitly the latest persisted monitor on restart. However, we failed to update `persisted_monitor_id`. As a result, we may restart and write the loaded monitor to `persisted_monitor` (eg at ID 2) but have a later `persisted_monitor_id` (eg ID 3). Then, when we complete the monitor update for the `persisted_monitor_id` (here, 3) we will think that its not a new update and neglect to update `persisted_monitor`/`persisted_monitor_id`. As a result, later updates (e.g. ID 4) will fail as we're trying to apply them to the original persisted monitor (at ID 2). The fix is simply to ensure `persisted_monitor_id` is always updated in lock-step with `persisted_monitor` on reload.
1 parent 2efb009 commit f59557f

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,11 @@ impl Writer for VecWriter {
171171
/// Note that such "being persisted" `ChannelMonitor`s are stored in `ChannelManager` and will
172172
/// simply be replayed on startup.
173173
struct LatestMonitorState {
174-
/// The latest monitor id which we told LDK we've persisted
174+
/// The latest monitor id which we told LDK we've persisted.
175+
///
176+
/// Note that there may still be earlier pending monitor updates in [`Self::pending_monitors`]
177+
/// which we haven't yet completed. We're allowed to reload with those as well, at least until
178+
/// they're completed.
175179
persisted_monitor_id: u64,
176180
/// The latest serialized `ChannelMonitor` that we told LDK we persisted.
177181
persisted_monitor: Vec<u8>,
@@ -726,18 +730,18 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
726730
let mut monitors = new_hash_map();
727731
let mut old_monitors = old_monitors.latest_monitors.lock().unwrap();
728732
for (channel_id, mut prev_state) in old_monitors.drain() {
729-
let serialized_mon = if use_old_mons % 3 == 0 {
733+
let (mon_id, serialized_mon) = if use_old_mons % 3 == 0 {
730734
// Reload with the oldest `ChannelMonitor` (the one that we already told
731735
// `ChannelManager` we finished persisting).
732-
prev_state.persisted_monitor
736+
(prev_state.persisted_monitor_id, prev_state.persisted_monitor)
733737
} else if use_old_mons % 3 == 1 {
734738
// Reload with the second-oldest `ChannelMonitor`
735-
let old_mon = prev_state.persisted_monitor;
736-
prev_state.pending_monitors.drain(..).next().map(|(_, v)| v).unwrap_or(old_mon)
739+
let old_mon = (prev_state.persisted_monitor_id, prev_state.persisted_monitor);
740+
prev_state.pending_monitors.drain(..).next().unwrap_or(old_mon)
737741
} else {
738742
// Reload with the newest `ChannelMonitor`
739-
let old_mon = prev_state.persisted_monitor;
740-
prev_state.pending_monitors.pop().map(|(_, v)| v).unwrap_or(old_mon)
743+
let old_mon = (prev_state.persisted_monitor_id, prev_state.persisted_monitor);
744+
prev_state.pending_monitors.pop().unwrap_or(old_mon)
741745
};
742746
// Use a different value of `use_old_mons` if we have another monitor (only for node B)
743747
// by shifting `use_old_mons` one in base-3.
@@ -750,6 +754,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
750754
monitors.insert(channel_id, mon.1);
751755
// Update the latest `ChannelMonitor` state to match what we just told LDK.
752756
prev_state.persisted_monitor = serialized_mon;
757+
prev_state.persisted_monitor_id = mon_id;
753758
// Wipe any `ChannelMonitor`s which we never told LDK we finished persisting,
754759
// considering them discarded. LDK should replay these for us as they're stored in
755760
// the `ChannelManager`.

0 commit comments

Comments
 (0)