Skip to content

Commit 95671e2

Browse files
committed
[fuzz] Check that channels don't get stuck in chanmon_consistency
This adds a new command string in the chanmon_consistency fuzzer which tests that, once all pending HTLCs are settled, at least one side of a channel can still send funds. While this should have caught the recent(ish) spec bug where channels could get stuck, I did not attempt to reproduce said bug with this patch.
1 parent 888b059 commit 95671e2

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,60 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
871871
0x5c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); },
872872
0x5d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); },
873873

874+
0xff => {
875+
// Test that no channel is in a stuck state where neither party can send funds even
876+
// after we resolve all pending events.
877+
// First make sure there are no pending monitor updates, resetting the error state
878+
// and calling channel_monitor_updated for each monitor.
879+
*monitor_a.update_ret.lock().unwrap() = Ok(());
880+
*monitor_b.update_ret.lock().unwrap() = Ok(());
881+
*monitor_c.update_ret.lock().unwrap() = Ok(());
882+
883+
if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) {
884+
nodes[0].channel_monitor_updated(&chan_1_funding, *id);
885+
}
886+
if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_1_funding) {
887+
nodes[1].channel_monitor_updated(&chan_1_funding, *id);
888+
}
889+
if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_2_funding) {
890+
nodes[1].channel_monitor_updated(&chan_2_funding, *id);
891+
}
892+
if let Some((id, _)) = monitor_c.latest_monitors.lock().unwrap().get(&chan_2_funding) {
893+
nodes[2].channel_monitor_updated(&chan_2_funding, *id);
894+
}
895+
896+
// Next, make sure peers are all connected to each other
897+
if chan_a_disconnected {
898+
nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
899+
nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() });
900+
chan_a_disconnected = false;
901+
}
902+
if chan_b_disconnected {
903+
nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() });
904+
nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
905+
chan_b_disconnected = false;
906+
}
907+
908+
for _ in 0..13 {
909+
// Then, make sure any current forwards make their way to their destination
910+
process_msg_events!(0, false);
911+
process_msg_events!(1, false);
912+
process_msg_events!(2, false);
913+
// ...making sure any pending PendingHTLCsForwardable events are handled and
914+
// payments claimed.
915+
process_events!(0, false);
916+
process_events!(1, false);
917+
process_events!(2, false);
918+
}
919+
920+
// Finally, make sure that at least one end of each channel can make a substantial payment.
921+
assert!(
922+
send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id) ||
923+
send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id));
924+
assert!(
925+
send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id) ||
926+
send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id));
927+
},
874928
_ => test_return!(),
875929
}
876930

0 commit comments

Comments
 (0)