Skip to content

Commit 1f2e903

Browse files
joostjagerclaude
andcommitted
fuzz: support initial async monitor persistence in chanmon_consistency
Read the first byte of fuzz input to determine initial monitor styles for each node (bit 0 = node A, bit 1 = node B, bit 2 = node C). When set, the node starts with InProgress persistence mode from the beginning. This allows fuzzing the async persistence path during initial channel creation, not just after reload. The make_channel macro now completes pending monitor updates after watch_channel calls to allow the channel handshake to proceed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 9859bb9 commit 1f2e903

File tree

1 file changed

+53
-16
lines changed

1 file changed

+53
-16
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,10 @@ impl chain::Watch<TestChannelSigner> for TestChainMonitor {
299299
persisted_monitor: ser.0,
300300
pending_monitors: Vec::new(),
301301
},
302-
Ok(chain::ChannelMonitorUpdateStatus::InProgress) => {
303-
panic!("The test currently doesn't test initial-persistence via the async pipeline")
302+
Ok(chain::ChannelMonitorUpdateStatus::InProgress) => LatestMonitorState {
303+
persisted_monitor_id: monitor_id,
304+
persisted_monitor: Vec::new(),
305+
pending_monitors: vec![(monitor_id, ser.0)],
304306
},
305307
Ok(chain::ChannelMonitorUpdateStatus::UnrecoverableError) => panic!(),
306308
Err(()) => panic!(),
@@ -706,6 +708,26 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
706708
let broadcast = Arc::new(TestBroadcaster {});
707709
let router = FuzzRouter {};
708710

711+
// Read initial monitor styles from fuzz input (1 byte: 2 bits per node)
712+
let initial_mon_styles = if !data.is_empty() { data[0] } else { 0 };
713+
let mon_style = [
714+
RefCell::new(if initial_mon_styles & 0b01 != 0 {
715+
ChannelMonitorUpdateStatus::InProgress
716+
} else {
717+
ChannelMonitorUpdateStatus::Completed
718+
}),
719+
RefCell::new(if initial_mon_styles & 0b10 != 0 {
720+
ChannelMonitorUpdateStatus::InProgress
721+
} else {
722+
ChannelMonitorUpdateStatus::Completed
723+
}),
724+
RefCell::new(if initial_mon_styles & 0b100 != 0 {
725+
ChannelMonitorUpdateStatus::InProgress
726+
} else {
727+
ChannelMonitorUpdateStatus::Completed
728+
}),
729+
];
730+
709731
macro_rules! make_node {
710732
($node_id: expr, $fee_estimator: expr) => {{
711733
let logger: Arc<dyn Logger> =
@@ -725,7 +747,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
725747
logger.clone(),
726748
$fee_estimator.clone(),
727749
Arc::new(TestPersister {
728-
update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed),
750+
update_ret: Mutex::new(mon_style[$node_id as usize].borrow().clone()),
729751
}),
730752
Arc::clone(&keys_manager),
731753
));
@@ -762,9 +784,6 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
762784
}};
763785
}
764786

765-
let default_mon_style = RefCell::new(ChannelMonitorUpdateStatus::Completed);
766-
let mon_style = [default_mon_style.clone(), default_mon_style.clone(), default_mon_style];
767-
768787
let reload_node = |ser: &Vec<u8>,
769788
node_id: u8,
770789
old_monitors: &TestChainMonitor,
@@ -860,8 +879,21 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
860879
};
861880

862881
let mut channel_txn = Vec::new();
882+
macro_rules! complete_all_pending_monitor_updates {
883+
($monitor: expr) => {{
884+
for (channel_id, state) in $monitor.latest_monitors.lock().unwrap().iter_mut() {
885+
for (id, data) in state.pending_monitors.drain(..) {
886+
$monitor.chain_monitor.channel_monitor_updated(*channel_id, id).unwrap();
887+
if id >= state.persisted_monitor_id {
888+
state.persisted_monitor_id = id;
889+
state.persisted_monitor = data;
890+
}
891+
}
892+
}
893+
}};
894+
}
863895
macro_rules! make_channel {
864-
($source: expr, $dest: expr, $dest_keys_manager: expr, $chan_id: expr) => {{
896+
($source: expr, $dest: expr, $source_monitor: expr, $dest_monitor: expr, $dest_keys_manager: expr, $chan_id: expr) => {{
865897
let init_dest = Init {
866898
features: $dest.init_features(),
867899
networks: None,
@@ -965,12 +997,14 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
965997
}
966998
};
967999
$dest.handle_funding_created($source.get_our_node_id(), &funding_created);
1000+
// Complete any pending monitor updates for dest after watch_channel
1001+
complete_all_pending_monitor_updates!($dest_monitor);
9681002

969-
let funding_signed = {
1003+
let (funding_signed, channel_id) = {
9701004
let events = $dest.get_and_clear_pending_msg_events();
9711005
assert_eq!(events.len(), 1);
9721006
if let MessageSendEvent::SendFundingSigned { ref msg, .. } = events[0] {
973-
msg.clone()
1007+
(msg.clone(), msg.channel_id.clone())
9741008
} else {
9751009
panic!("Wrong event type");
9761010
}
@@ -984,19 +1018,22 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
9841018
}
9851019

9861020
$source.handle_funding_signed($dest.get_our_node_id(), &funding_signed);
1021+
// Complete any pending monitor updates for source after watch_channel
1022+
complete_all_pending_monitor_updates!($source_monitor);
1023+
9871024
let events = $source.get_and_clear_pending_events();
9881025
assert_eq!(events.len(), 1);
989-
let channel_id = if let events::Event::ChannelPending {
1026+
if let events::Event::ChannelPending {
9901027
ref counterparty_node_id,
991-
ref channel_id,
1028+
channel_id: ref event_channel_id,
9921029
..
9931030
} = events[0]
9941031
{
9951032
assert_eq!(counterparty_node_id, &$dest.get_our_node_id());
996-
channel_id.clone()
1033+
assert_eq!(*event_channel_id, channel_id);
9971034
} else {
9981035
panic!("Wrong event type");
999-
};
1036+
}
10001037

10011038
channel_id
10021039
}};
@@ -1087,8 +1124,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
10871124

10881125
let mut nodes = [node_a, node_b, node_c];
10891126

1090-
let chan_1_id = make_channel!(nodes[0], nodes[1], keys_manager_b, 0);
1091-
let chan_2_id = make_channel!(nodes[1], nodes[2], keys_manager_c, 1);
1127+
let chan_1_id = make_channel!(nodes[0], nodes[1], monitor_a, monitor_b, keys_manager_b, 0);
1128+
let chan_2_id = make_channel!(nodes[1], nodes[2], monitor_b, monitor_c, keys_manager_c, 1);
10921129

10931130
for node in nodes.iter() {
10941131
confirm_txn!(node);
@@ -1124,7 +1161,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
11241161
}};
11251162
}
11261163

1127-
let mut read_pos = 0;
1164+
let mut read_pos = 1; // First byte was consumed for initial mon_style
11281165
macro_rules! get_slice {
11291166
($len: expr) => {{
11301167
let slice_len = $len as usize;

0 commit comments

Comments
 (0)