Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1268,16 +1268,29 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {

let pending_payments = RefCell::new([Vec::new(), Vec::new(), Vec::new()]);
let resolved_payments = RefCell::new([Vec::new(), Vec::new(), Vec::new()]);
let mut fc_ab = false; // Force-closed one A-B channel
let mut fc_bc = false; // Force-closed one B-C channel

macro_rules! test_return {
() => {{
assert_eq!(nodes[0].list_channels().len(), 3);
assert_eq!(nodes[1].list_channels().len(), 6);
assert_eq!(nodes[2].list_channels().len(), 3);

// At no point should we have broadcasted any transactions after the initial channel
// opens.
assert!(broadcast.txn_broadcasted.borrow().is_empty());
// Node A has 3 A-B channels, minus 1 if we force-closed.
let expected_a = if fc_ab { 2 } else { 3 };
assert_eq!(nodes[0].list_channels().len(), expected_a);
// Node B has 3 A-B + 3 B-C channels. Counterparty may not have processed
// the force-close yet, so we bound the count.
let node_b_chans = nodes[1].list_channels().len();
let min_b = 6 - (if fc_ab { 1 } else { 0 }) - (if fc_bc { 1 } else { 0 });
let max_b = 6 - (if fc_bc { 1 } else { 0 });
assert!(node_b_chans >= min_b && node_b_chans <= max_b);
// Node C has 3 B-C channels. Counterparty may not have processed force-close.
let node_c_chans = nodes[2].list_channels().len();
let min_c = if fc_bc { 2 } else { 3 };
assert!(node_c_chans >= min_c && node_c_chans <= 3);

// Only check for no broadcasts if no force-closes happened.
if !fc_ab && !fc_bc {
assert!(broadcast.txn_broadcasted.borrow().is_empty());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some changes that will be going up soon that rework this, you may want to wait until then. Each node will have its own broadcaster, and there's also a concept of a "chain" now so we can mine transactions.

}

return;
}};
Expand Down Expand Up @@ -1350,6 +1363,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
},
MessageSendEvent::SendChannelReady { .. } => continue,
MessageSendEvent::SendAnnouncementSignatures { .. } => continue,
MessageSendEvent::HandleError { .. } => continue,
MessageSendEvent::BroadcastChannelUpdate { .. } => continue,
MessageSendEvent::SendChannelUpdate { ref node_id, ref msg } => {
assert_eq!(msg.contents.channel_flags & 2, 0); // The disable bit must never be set!
if Some(*node_id) == expect_drop_id { panic!("peer_disconnected should drop msgs bound for the disconnected peer"); }
Expand Down Expand Up @@ -1571,6 +1586,12 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
// force-close which we should detect as an error).
assert_eq!(msg.contents.channel_flags & 2, 0);
},
MessageSendEvent::HandleError { .. } => {
// Can be generated by force-close
},
MessageSendEvent::BroadcastChannelUpdate { .. } => {
// Can be generated by force-close (with disable bit set)
},
_ => if out.may_fail.load(atomic::Ordering::Acquire) {
return;
} else {
Expand Down Expand Up @@ -1614,6 +1635,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
MessageSendEvent::SendChannelUpdate { ref msg, .. } => {
assert_eq!(msg.contents.channel_flags & 2, 0); // The disable bit must never be set!
},
MessageSendEvent::HandleError { .. } => {},
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
_ => {
if out.may_fail.load(atomic::Ordering::Acquire) {
return;
Expand Down Expand Up @@ -1641,6 +1664,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
MessageSendEvent::SendChannelUpdate { ref msg, .. } => {
assert_eq!(msg.contents.channel_flags & 2, 0); // The disable bit must never be set!
},
MessageSendEvent::HandleError { .. } => {},
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
_ => {
if out.may_fail.load(atomic::Ordering::Acquire) {
return;
Expand Down Expand Up @@ -1735,6 +1760,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
},
events::Event::SplicePending { .. } => {},
events::Event::SpliceFailed { .. } => {},
events::Event::ChannelClosed { .. } => {},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably open a new channel to replace the force closed one?


_ => {
if out.may_fail.load(atomic::Ordering::Acquire) {
Expand Down Expand Up @@ -2326,6 +2352,25 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
}
},

// Force close A-B channel 0
0xc0 => {
let _ = nodes[0].force_close_broadcasting_latest_txn(
&chan_a_id,
&nodes[1].get_our_node_id(),
"]]]]".to_string(),
);
fc_ab = true;
},
// Force close B-C channel 0
0xc1 => {
let _ = nodes[1].force_close_broadcasting_latest_txn(
&chan_b_id,
&nodes[2].get_our_node_id(),
"]]]]".to_string(),
);
fc_bc = true;
},

0xb0 | 0xb1 | 0xb2 => {
// Restart node A, picking among the in-flight `ChannelMonitor`s to use based on
// the value of `v` we're matching.
Expand Down Expand Up @@ -2555,13 +2600,20 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
}

// Finally, make sure that at least one end of each channel can make a substantial payment
for &scid in &chan_ab_scids {
// (skip channel 0 if it was force-closed)
for (i, &scid) in chan_ab_scids.iter().enumerate() {
if fc_ab && i == 0 {
continue;
}
assert!(
send(0, 1, scid, 10_000_000, &mut p_ctr)
|| send(1, 0, scid, 10_000_000, &mut p_ctr)
);
}
for &scid in &chan_bc_scids {
for (i, &scid) in chan_bc_scids.iter().enumerate() {
if fc_bc && i == 0 {
continue;
}
assert!(
send(1, 2, scid, 10_000_000, &mut p_ctr)
|| send(2, 1, scid, 10_000_000, &mut p_ctr)
Expand Down
Loading