Skip to content

Commit 6626d08

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 4f60b71 commit 6626d08

File tree

1 file changed

+73
-12
lines changed

1 file changed

+73
-12
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
542542
bc_events.clear();
543543
new_events
544544
} else { Vec::new() };
545+
let mut had_events = false;
545546
for event in events.iter().chain(nodes[$node].get_and_clear_pending_msg_events().iter()) {
547+
had_events = true;
546548
match event {
547549
events::MessageSendEvent::UpdateHTLCs { ref node_id, updates: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
548550
for dest in nodes.iter() {
@@ -599,6 +601,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
599601
_ => panic!("Unhandled message event"),
600602
}
601603
}
604+
had_events
602605
} }
603606
}
604607

@@ -678,6 +681,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
678681
} else { Ordering::Equal }
679682
} else { Ordering::Equal }
680683
});
684+
let had_events = !events.is_empty();
681685
for event in events.drain(..) {
682686
match event {
683687
events::Event::PaymentReceived { payment_hash, payment_secret, amt } => {
@@ -697,6 +701,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
697701
_ => panic!("Unhandled event"),
698702
}
699703
}
704+
had_events
700705
} }
701706
}
702707

@@ -760,18 +765,18 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
760765
}
761766
},
762767

763-
0x10 => process_msg_events!(0, true),
764-
0x11 => process_msg_events!(0, false),
765-
0x12 => process_events!(0, true),
766-
0x13 => process_events!(0, false),
767-
0x14 => process_msg_events!(1, true),
768-
0x15 => process_msg_events!(1, false),
769-
0x16 => process_events!(1, true),
770-
0x17 => process_events!(1, false),
771-
0x18 => process_msg_events!(2, true),
772-
0x19 => process_msg_events!(2, false),
773-
0x1a => process_events!(2, true),
774-
0x1b => process_events!(2, false),
768+
0x10 => { process_msg_events!(0, true); },
769+
0x11 => { process_msg_events!(0, false); },
770+
0x12 => { process_events!(0, true); },
771+
0x13 => { process_events!(0, false); },
772+
0x14 => { process_msg_events!(1, true); },
773+
0x15 => { process_msg_events!(1, false); },
774+
0x16 => { process_events!(1, true); },
775+
0x17 => { process_events!(1, false); },
776+
0x18 => { process_msg_events!(2, true); },
777+
0x19 => { process_msg_events!(2, false); },
778+
0x1a => { process_events!(2, true); },
779+
0x1b => { process_events!(2, false); },
775780

776781
0x1c => {
777782
if !chan_a_disconnected {
@@ -871,6 +876,62 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
871876
0x5c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); },
872877
0x5d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); },
873878

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

0 commit comments

Comments
 (0)