Skip to content

Commit 6563f7a

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 63d4365 commit 6563f7a

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

@@ -764,18 +769,18 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
764769
}
765770
},
766771

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

780785
0x1c => {
781786
if !chan_a_disconnected {
@@ -875,6 +880,62 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
875880
0x5c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); },
876881
0x5d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); },
877882

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

0 commit comments

Comments
 (0)