Skip to content

Commit 53cd7c9

Browse files
committed
fuzz: add deferred chanmon checkpoints
Enable deferred ChainMonitor writes in chanmon_consistency. Checkpoint the ChannelManager before flushing captured monitor writes. Treat checkpoint-only progress as progress during settle_all.
1 parent 029ca75 commit 53cd7c9

1 file changed

Lines changed: 95 additions & 34 deletions

File tree

fuzz/src/chanmon_consistency.rs

Lines changed: 95 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ struct HarnessNode<'a> {
817817
fee_estimator: Arc<FuzzEstimator>,
818818
wallet: TestWalletSource,
819819
persistence_style: ChannelMonitorUpdateStatus,
820+
deferred: bool,
820821
serialized_manager: Vec<u8>,
821822
height: u32,
822823
last_htlc_clear_fee: u32,
@@ -847,7 +848,7 @@ impl<'a> HarnessNode<'a> {
847848
fn build_chain_monitor(
848849
broadcaster: &Arc<TestBroadcaster>, fee_estimator: &Arc<FuzzEstimator>,
849850
keys_manager: &Arc<KeyProvider>, logger: Arc<dyn Logger + MaybeSend + MaybeSync>,
850-
persister: &Arc<HarnessPersister>,
851+
persister: &Arc<HarnessPersister>, deferred: bool,
851852
) -> Arc<TestChainMonitor> {
852853
Arc::new(chainmonitor::ChainMonitor::new(
853854
None,
@@ -857,14 +858,14 @@ impl<'a> HarnessNode<'a> {
857858
Arc::clone(persister),
858859
Arc::clone(keys_manager),
859860
keys_manager.get_peer_storage_key(),
860-
false,
861+
deferred,
861862
))
862863
}
863864

864865
fn new<Out: Output + MaybeSend + MaybeSync>(
865866
node_id: u8, wallet: TestWalletSource, fee_estimator: Arc<FuzzEstimator>,
866867
broadcaster: Arc<TestBroadcaster>, persistence_style: ChannelMonitorUpdateStatus,
867-
out: &Out, router: &'a FuzzRouter, chan_type: ChanType,
868+
deferred: bool, out: &Out, router: &'a FuzzRouter, chan_type: ChanType,
868869
) -> Self {
869870
let logger = Self::build_logger(node_id, out);
870871
let node_secret = SecretKey::from_slice(&[
@@ -884,6 +885,7 @@ impl<'a> HarnessNode<'a> {
884885
&keys_manager,
885886
Arc::clone(&logger),
886887
&persister,
888+
deferred,
887889
);
888890
let network = Network::Bitcoin;
889891
let best_block_timestamp = genesis_block(network).header.time;
@@ -913,6 +915,7 @@ impl<'a> HarnessNode<'a> {
913915
fee_estimator,
914916
wallet,
915917
persistence_style,
918+
deferred,
916919
serialized_manager: Vec::new(),
917920
height: 0,
918921
last_htlc_clear_fee: 253,
@@ -930,19 +933,25 @@ impl<'a> HarnessNode<'a> {
930933
self.persister.mark_update_completed(chan_id, monitor_id, data);
931934
}
932935

933-
fn complete_all_monitor_updates(&self, chan_id: &ChannelId) {
934-
for (monitor_id, data) in self.persister.drain_pending_updates(chan_id) {
936+
fn complete_all_monitor_updates(&self, chan_id: &ChannelId) -> bool {
937+
assert_eq!(self.monitor.pending_operation_count(), 0);
938+
let completed_updates = self.persister.drain_pending_updates(chan_id);
939+
let completed_any = !completed_updates.is_empty();
940+
for (monitor_id, data) in completed_updates {
935941
self.finish_monitor_update(*chan_id, monitor_id, data);
936942
}
943+
completed_any
937944
}
938945

939946
fn complete_all_pending_monitor_updates(&self) {
947+
assert_eq!(self.monitor.pending_operation_count(), 0);
940948
for (channel_id, monitor_id, data) in self.persister.drain_all_pending_updates() {
941949
self.finish_monitor_update(channel_id, monitor_id, data);
942950
}
943951
}
944952

945953
fn complete_monitor_update(&self, chan_id: &ChannelId, selector: MonitorUpdateSelector) {
954+
assert_eq!(self.monitor.pending_operation_count(), 0);
946955
if let Some((monitor_id, data)) = self.persister.take_pending_update(chan_id, selector) {
947956
self.finish_monitor_update(*chan_id, monitor_id, data);
948957
}
@@ -966,9 +975,30 @@ impl<'a> HarnessNode<'a> {
966975
}
967976
}
968977

969-
fn refresh_serialized_manager(&mut self) {
978+
fn checkpoint_manager_persistence(&mut self) -> bool {
970979
if self.node.get_and_clear_needs_persistence() {
980+
let pending_monitor_writes = self.monitor.pending_operation_count();
971981
self.serialized_manager = self.node.encode();
982+
if self.deferred {
983+
self.monitor.flush(pending_monitor_writes, &self.logger);
984+
} else {
985+
assert_eq!(pending_monitor_writes, 0);
986+
}
987+
true
988+
} else {
989+
assert_eq!(self.monitor.pending_operation_count(), 0);
990+
false
991+
}
992+
}
993+
994+
fn force_checkpoint_manager_persistence(&mut self) {
995+
let pending_monitor_writes = self.monitor.pending_operation_count();
996+
self.serialized_manager = self.node.encode();
997+
self.node.get_and_clear_needs_persistence();
998+
if self.deferred {
999+
self.monitor.flush(pending_monitor_writes, &self.logger);
1000+
} else {
1001+
assert_eq!(pending_monitor_writes, 0);
9721002
}
9731003
}
9741004

@@ -1082,6 +1112,7 @@ impl<'a> HarnessNode<'a> {
10821112
&self.keys_manager,
10831113
Arc::clone(&logger),
10841114
&persister,
1115+
self.deferred,
10851116
);
10861117

10871118
let mut monitors = new_hash_map();
@@ -1126,21 +1157,27 @@ impl<'a> HarnessNode<'a> {
11261157
channel_monitors: monitor_refs,
11271158
};
11281159

1129-
let manager = <(BlockLocator, ChanMan)>::read(&mut &self.serialized_manager[..], read_args)
1130-
.expect("Failed to read manager");
1160+
let (_block_locator, manager) =
1161+
<(BlockLocator, ChanMan)>::read(&mut &self.serialized_manager[..], read_args)
1162+
.expect("Failed to read manager");
1163+
let expected_status = if self.deferred {
1164+
ChannelMonitorUpdateStatus::InProgress
1165+
} else {
1166+
ChannelMonitorUpdateStatus::Completed
1167+
};
11311168
for (channel_id, mon) in monitors.drain() {
1132-
assert_eq!(
1133-
chain_monitor.watch_channel(channel_id, mon),
1134-
Ok(ChannelMonitorUpdateStatus::Completed)
1135-
);
1169+
assert_eq!(chain_monitor.watch_channel(channel_id, mon), Ok(expected_status));
11361170
}
11371171
// Future monitor writes should follow the node's configured persistence style; only the
11381172
// startup watch_channel registration above is forced to Completed.
11391173
*persister.update_ret.lock().unwrap() = self.persistence_style;
1140-
self.node = manager.1;
1174+
self.node = manager;
11411175
self.monitor = chain_monitor;
11421176
self.persister = persister;
11431177
self.logger = logger;
1178+
if self.deferred {
1179+
self.force_checkpoint_manager_persistence();
1180+
}
11441181
}
11451182
}
11461183

@@ -1362,11 +1399,13 @@ impl PeerLink {
13621399
|| (self.node_a == node_b && self.node_b == node_a)
13631400
}
13641401

1365-
fn complete_all_monitor_updates(&self, nodes: &[HarnessNode<'_>; 3]) {
1402+
fn complete_all_monitor_updates(&self, nodes: &[HarnessNode<'_>; 3]) -> bool {
1403+
let mut completed_updates = false;
13661404
for id in &self.channel_ids {
1367-
nodes[self.node_a].complete_all_monitor_updates(id);
1368-
nodes[self.node_b].complete_all_monitor_updates(id);
1405+
completed_updates |= nodes[self.node_a].complete_all_monitor_updates(id);
1406+
completed_updates |= nodes[self.node_b].complete_all_monitor_updates(id);
13691407
}
1408+
completed_updates
13701409
}
13711410

13721411
fn complete_monitor_updates_for_node(
@@ -1937,9 +1976,12 @@ fn connect_peers(source: &ChanMan<'_>, dest: &ChanMan<'_>) {
19371976
}
19381977

19391978
fn make_channel(
1940-
source: &HarnessNode<'_>, dest: &HarnessNode<'_>, chan_id: i32, trusted_open: bool,
1941-
trusted_accept: bool, chain_state: &mut ChainState,
1979+
nodes: &mut [HarnessNode<'_>; 3], source_idx: usize, dest_idx: usize, chan_id: i32,
1980+
trusted_open: bool, trusted_accept: bool, chain_state: &mut ChainState,
19421981
) {
1982+
assert!(source_idx < dest_idx);
1983+
let (left, right) = nodes.split_at_mut(dest_idx);
1984+
let (source, dest) = (&mut left[source_idx], &mut right[0]);
19431985
if trusted_open {
19441986
source
19451987
.create_channel_to_trusted_peer_0reserve(
@@ -2050,7 +2092,8 @@ fn make_channel(
20502092
}
20512093
};
20522094
dest.handle_funding_created(source.get_our_node_id(), &funding_created);
2053-
// Complete any pending monitor persistence callbacks for dest after watch_channel.
2095+
dest.checkpoint_manager_persistence();
2096+
// Complete any monitor persistence callbacks made available for dest after watch_channel.
20542097
dest.complete_all_pending_monitor_updates();
20552098

20562099
let (funding_signed, channel_id) = {
@@ -2071,7 +2114,8 @@ fn make_channel(
20712114
}
20722115

20732116
source.handle_funding_signed(dest.get_our_node_id(), &funding_signed);
2074-
// Complete any pending monitor persistence callbacks for source after watch_channel.
2117+
source.checkpoint_manager_persistence();
2118+
// Complete any monitor persistence callbacks made available for source after watch_channel.
20752119
source.complete_all_pending_monitor_updates();
20762120

20772121
let events = source.get_and_clear_pending_events();
@@ -2143,6 +2187,11 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
21432187
ChannelMonitorUpdateStatus::Completed
21442188
},
21452189
];
2190+
let deferred = [
2191+
config_byte & 0b0010_0000 != 0,
2192+
config_byte & 0b0100_0000 != 0,
2193+
config_byte & 0b1000_0000 != 0,
2194+
];
21462195

21472196
let wallet_a = TestWalletSource::new(SecretKey::from_slice(&[1; 32]).unwrap());
21482197
let wallet_b = TestWalletSource::new(SecretKey::from_slice(&[2; 32]).unwrap());
@@ -2180,6 +2229,7 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
21802229
Arc::clone(&fee_est_a),
21812230
Arc::clone(&broadcast_a),
21822231
persistence_styles[0],
2232+
deferred[0],
21832233
&out,
21842234
router,
21852235
chan_type,
@@ -2190,6 +2240,7 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
21902240
Arc::clone(&fee_est_b),
21912241
Arc::clone(&broadcast_b),
21922242
persistence_styles[1],
2243+
deferred[1],
21932244
&out,
21942245
router,
21952246
chan_type,
@@ -2200,6 +2251,7 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
22002251
Arc::clone(&fee_est_c),
22012252
Arc::clone(&broadcast_c),
22022253
persistence_styles[2],
2254+
deferred[2],
22032255
&out,
22042256
router,
22052257
chan_type,
@@ -2217,14 +2269,14 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
22172269
// channel gets its own txid and funding outpoint.
22182270
// A-B: channel 2 A and B have 0-reserve (trusted open + trusted accept),
22192271
// channel 3 A has 0-reserve (trusted accept).
2220-
make_channel(&nodes[0], &nodes[1], 1, false, false, &mut chain_state);
2221-
make_channel(&nodes[0], &nodes[1], 2, true, true, &mut chain_state);
2222-
make_channel(&nodes[0], &nodes[1], 3, false, true, &mut chain_state);
2272+
make_channel(&mut nodes, 0, 1, 1, false, false, &mut chain_state);
2273+
make_channel(&mut nodes, 0, 1, 2, true, true, &mut chain_state);
2274+
make_channel(&mut nodes, 0, 1, 3, false, true, &mut chain_state);
22232275
// B-C: channel 4 B has 0-reserve (via trusted accept),
22242276
// channel 5 C has 0-reserve (via trusted open).
2225-
make_channel(&nodes[1], &nodes[2], 4, false, true, &mut chain_state);
2226-
make_channel(&nodes[1], &nodes[2], 5, true, false, &mut chain_state);
2227-
make_channel(&nodes[1], &nodes[2], 6, false, false, &mut chain_state);
2277+
make_channel(&mut nodes, 1, 2, 4, false, true, &mut chain_state);
2278+
make_channel(&mut nodes, 1, 2, 5, true, false, &mut chain_state);
2279+
make_channel(&mut nodes, 1, 2, 6, false, false, &mut chain_state);
22282280

22292281
// Wipe the transactions-broadcasted set to make sure we don't broadcast
22302282
// any transactions during normal operation after setup.
@@ -2251,7 +2303,7 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
22512303
};
22522304

22532305
for node in &mut nodes {
2254-
node.serialized_manager = node.encode();
2306+
node.force_checkpoint_manager_persistence();
22552307
}
22562308

22572309
Self {
@@ -2671,7 +2723,7 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
26712723
// claim/fail handling per event batch.
26722724
let mut claim_set = new_hash_map();
26732725
let mut events = nodes[node_idx].get_and_clear_pending_events();
2674-
let had_events = !events.is_empty();
2726+
let mut had_events = !events.is_empty();
26752727
for event in events.drain(..) {
26762728
match event {
26772729
events::Event::PaymentClaimable { payment_hash, .. } => {
@@ -2727,6 +2779,7 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
27272779
}
27282780
while nodes[node_idx].needs_pending_htlc_processing() {
27292781
nodes[node_idx].process_pending_htlc_forwards();
2782+
had_events = true;
27302783
}
27312784
had_events
27322785
}
@@ -2749,9 +2802,10 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
27492802
"It may take may iterations to settle the state, but it should not take forever"
27502803
);
27512804
}
2805+
let mut made_progress = self.checkpoint_manager_persistences();
27522806
// Next, make sure no monitor completion callbacks are pending.
2753-
self.ab_link.complete_all_monitor_updates(&self.nodes);
2754-
self.bc_link.complete_all_monitor_updates(&self.nodes);
2807+
made_progress |= self.ab_link.complete_all_monitor_updates(&self.nodes);
2808+
made_progress |= self.bc_link.complete_all_monitor_updates(&self.nodes);
27552809
// Then, make sure any current forwards make their way to their destination.
27562810
if self.process_msg_events(0, false, ProcessMessages::AllMessages) {
27572811
last_pass_no_updates = false;
@@ -2778,6 +2832,10 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
27782832
last_pass_no_updates = false;
27792833
continue;
27802834
}
2835+
if made_progress {
2836+
last_pass_no_updates = false;
2837+
continue;
2838+
}
27812839
if last_pass_no_updates {
27822840
// In some cases, we may generate a message to send in
27832841
// `process_msg_events`, but block sending until
@@ -2876,19 +2934,22 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
28762934
self.nodes[2].record_last_htlc_clear_fee();
28772935
}
28782936

2879-
fn refresh_serialized_managers(&mut self) {
2937+
fn checkpoint_manager_persistences(&mut self) -> bool {
2938+
let mut made_progress = false;
28802939
for node in &mut self.nodes {
2881-
node.refresh_serialized_manager();
2940+
made_progress |= node.checkpoint_manager_persistence();
28822941
}
2942+
made_progress
28832943
}
28842944
}
28852945

28862946
#[inline]
28872947
pub fn do_test<Out: Output + MaybeSend + MaybeSync>(data: &[u8], out: Out) {
28882948
let router = FuzzRouter {};
2889-
// Read initial monitor styles and channel type from fuzz input byte 0:
2949+
// Read initial monitor styles, channel type, and deferred write mode from fuzz input byte 0:
28902950
// bits 0-2: monitor styles (1 bit per node)
28912951
// bits 3-4: channel type (0=Legacy, 1=KeyedAnchors, 2=ZeroFeeCommitments)
2952+
// bits 5-7: deferred monitor write mode (1 bit per node)
28922953
let config_byte = if !data.is_empty() { data[0] } else { 0 };
28932954
let mut harness = Harness::new(config_byte, out, &router);
28942955
let mut read_pos = 1; // First byte was consumed for initial config.
@@ -3300,7 +3361,7 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(data: &[u8], out: Out) {
33003361
_ => break 'fuzz_loop,
33013362
}
33023363

3303-
harness.refresh_serialized_managers();
3364+
harness.checkpoint_manager_persistences();
33043365
}
33053366
harness.finish();
33063367
}

0 commit comments

Comments
 (0)