Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Capture announcement signatures resend in reconnection tests
We'll use this in the next commit to test the resend logic for
`announcement_signatures` when reestablishing a channel that had a
pending splice become locked.
  • Loading branch information
wpaulino committed Oct 8, 2025
commit ac6be6834916c707f3070eb1adeb75f5ef18d90c
17 changes: 11 additions & 6 deletions lightning/src/ln/async_signer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ fn do_test_async_raa_peer_disconnect(
}

// Expect the RAA
let (_, revoke_and_ack, commitment_signed, resend_order) =
let (_, revoke_and_ack, commitment_signed, resend_order, _) =
handle_chan_reestablish_msgs!(dst, src);
if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
assert!(revoke_and_ack.is_none());
Expand All @@ -612,14 +612,14 @@ fn do_test_async_raa_peer_disconnect(
dst.node.signer_unblocked(Some((src_node_id, chan_id)));

if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
let (_, revoke_and_ack, commitment_signed, resend_order) =
let (_, revoke_and_ack, commitment_signed, resend_order, _) =
handle_chan_reestablish_msgs!(dst, src);
assert!(revoke_and_ack.is_some());
assert!(commitment_signed.is_some());
assert!(resend_order == RAACommitmentOrder::RevokeAndACKFirst);
} else {
// Make sure we don't double send the RAA.
let (_, revoke_and_ack, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
let (_, revoke_and_ack, commitment_signed, _, _) = handle_chan_reestablish_msgs!(dst, src);
assert!(revoke_and_ack.is_none());
assert!(commitment_signed.is_none());
}
Expand Down Expand Up @@ -745,7 +745,7 @@ fn do_test_async_commitment_signature_peer_disconnect(
}

// Expect the RAA
let (_, revoke_and_ack, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
let (_, revoke_and_ack, commitment_signed, _, _) = handle_chan_reestablish_msgs!(dst, src);
assert!(revoke_and_ack.is_some());
if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
assert!(commitment_signed.is_none());
Expand All @@ -758,11 +758,11 @@ fn do_test_async_commitment_signature_peer_disconnect(
dst.node.signer_unblocked(Some((src_node_id, chan_id)));

if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
let (_, _, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
let (_, _, commitment_signed, _, _) = handle_chan_reestablish_msgs!(dst, src);
assert!(commitment_signed.is_some());
} else {
// Make sure we don't double send the CS.
let (_, _, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
let (_, _, commitment_signed, _, _) = handle_chan_reestablish_msgs!(dst, src);
assert!(commitment_signed.is_none());
}
}
Expand Down Expand Up @@ -877,6 +877,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
assert!(as_resp.0.is_none());
assert!(as_resp.1.is_none());
assert!(as_resp.2.is_none());
assert!(as_resp.4.is_none());

if monitor_update_failure {
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
Expand All @@ -896,6 +897,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
assert!(as_resp.0.is_none());
assert!(as_resp.1.is_none());
assert!(as_resp.2.is_none());
assert!(as_resp.4.is_none());

nodes[0].enable_channel_signer_op(&node_b_id, &chan_id, SignerOp::SignCounterpartyCommitment);
nodes[0].node.signer_unblocked(Some((node_b_id, chan_id)));
Expand All @@ -912,6 +914,9 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {

assert!(as_resp.3 == RAACommitmentOrder::CommitmentFirst);

assert!(as_resp.4.is_none());
assert!(bs_resp.4.is_none());

// Now that everything is restored, get the CS + RAA and handle them.
nodes[1]
.node
Expand Down
1 change: 1 addition & 0 deletions lightning/src/ln/chanmon_update_fail_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
nodes[1].node.peer_disconnected(node_a_id);
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_channel_ready = (true, true);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);
}

Expand Down
49 changes: 44 additions & 5 deletions lightning/src/ln/functional_test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4796,11 +4796,14 @@ macro_rules! handle_chan_reestablish_msgs {
None
};

if let Some(&MessageSendEvent::SendAnnouncementSignatures { ref node_id, msg: _ }) =
let mut announcement_sigs = None; // May be now or later
if let Some(&MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg }) =
msg_events.get(idx)
{
idx += 1;
assert_eq!(*node_id, $dst_node.node.get_our_node_id());
assert!(announcement_sigs.is_none());
announcement_sigs = Some(msg.clone());
}

let mut had_channel_update = false; // ChannelUpdate may be now or later, but not both
Expand Down Expand Up @@ -4859,23 +4862,33 @@ macro_rules! handle_chan_reestablish_msgs {
}
}

if let Some(&MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg }) =
msg_events.get(idx)
{
idx += 1;
assert_eq!(*node_id, $dst_node.node.get_our_node_id());
assert!(announcement_sigs.is_none());
announcement_sigs = Some(msg.clone());
}

if let Some(&MessageSendEvent::SendChannelUpdate { ref node_id, .. }) = msg_events.get(idx)
{
assert_eq!(*node_id, $dst_node.node.get_our_node_id());
idx += 1;
assert!(!had_channel_update);
}

assert_eq!(msg_events.len(), idx);
assert_eq!(msg_events.len(), idx, "{msg_events:?}");

(channel_ready, revoke_and_ack, commitment_update, order)
(channel_ready, revoke_and_ack, commitment_update, order, announcement_sigs)
}};
}

pub struct ReconnectArgs<'a, 'b, 'c, 'd> {
pub node_a: &'a Node<'b, 'c, 'd>,
pub node_b: &'a Node<'b, 'c, 'd>,
pub send_channel_ready: (bool, bool),
pub send_announcement_sigs: (bool, bool),
pub pending_responding_commitment_signed: (bool, bool),
/// Indicates that the pending responding commitment signed will be a dup for the recipient,
/// and no monitor update is expected
Expand All @@ -4894,6 +4907,7 @@ impl<'a, 'b, 'c, 'd> ReconnectArgs<'a, 'b, 'c, 'd> {
node_a,
node_b,
send_channel_ready: (false, false),
send_announcement_sigs: (false, false),
pending_responding_commitment_signed: (false, false),
pending_responding_commitment_signed_dup_monitor: (false, false),
pending_htlc_adds: (0, 0),
Expand All @@ -4913,6 +4927,7 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
node_a,
node_b,
send_channel_ready,
send_announcement_sigs,
pending_htlc_adds,
pending_htlc_claims,
pending_htlc_fails,
Expand Down Expand Up @@ -4994,7 +5009,7 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
&& pending_cell_htlc_fails.1 == 0)
);

for chan_msgs in resp_1.drain(..) {
for mut chan_msgs in resp_1.drain(..) {
if send_channel_ready.0 {
node_a.node.handle_channel_ready(node_b_id, &chan_msgs.0.unwrap());
let announcement_event = node_a.node.get_and_clear_pending_msg_events();
Expand All @@ -5009,6 +5024,18 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
} else {
assert!(chan_msgs.0.is_none());
}
if send_announcement_sigs.0 {
let announcement_sigs = chan_msgs.4.take().unwrap();
node_a.node.handle_announcement_signatures(node_b_id, &announcement_sigs);
let msg_events = node_a.node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 1, "{msg_events:?}");
if let MessageSendEvent::BroadcastChannelAnnouncement { .. } = msg_events[0] {
} else {
panic!("Unexpected event! {:?}", msg_events[0]);
}
} else {
assert!(chan_msgs.4.is_none());
}
if pending_raa.0 {
assert!(chan_msgs.3 == RAACommitmentOrder::RevokeAndACKFirst);
node_a.node.handle_revoke_and_ack(node_b_id, &chan_msgs.1.unwrap());
Expand Down Expand Up @@ -5073,7 +5100,7 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
}
}

for chan_msgs in resp_2.drain(..) {
for mut chan_msgs in resp_2.drain(..) {
if send_channel_ready.1 {
node_b.node.handle_channel_ready(node_a_id, &chan_msgs.0.unwrap());
let announcement_event = node_b.node.get_and_clear_pending_msg_events();
Expand All @@ -5088,6 +5115,18 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) {
} else {
assert!(chan_msgs.0.is_none());
}
if send_announcement_sigs.1 {
let announcement_sigs = chan_msgs.4.take().unwrap();
node_b.node.handle_announcement_signatures(node_a_id, &announcement_sigs);
let mut msg_events = node_b.node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 1, "{msg_events:?}");
if let MessageSendEvent::BroadcastChannelAnnouncement { .. } = msg_events.remove(0) {
} else {
panic!();
}
} else {
assert!(chan_msgs.4.is_none());
}
if pending_raa.1 {
assert!(chan_msgs.3 == RAACommitmentOrder::RevokeAndACKFirst);
node_b.node.handle_revoke_and_ack(node_a_id, &chan_msgs.1.unwrap());
Expand Down
35 changes: 33 additions & 2 deletions lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,7 @@ pub fn test_simple_peer_disconnect() {
nodes[1].node.peer_disconnected(node_a_id);
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_channel_ready = (true, true);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);

let payment_preimage_1 = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000).0;
Expand Down Expand Up @@ -2716,22 +2717,29 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
// received on either side, both sides will need to resend them.
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_channel_ready = (true, true);
if simulate_broken_lnd || messages_delivered > 0 {
reconnect_args.send_announcement_sigs.0 = true;
}
reconnect_args.send_announcement_sigs.1 = true;
reconnect_args.pending_htlc_adds.1 = 1;
reconnect_nodes(reconnect_args);
} else if messages_delivered == 3 {
// nodes[0] still wants its RAA + commitment_signed
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_args.pending_responding_commitment_signed.0 = true;
reconnect_args.pending_raa.0 = true;
reconnect_nodes(reconnect_args);
} else if messages_delivered == 4 {
// nodes[0] still wants its commitment_signed
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_announcement_sigs.0 = true;
reconnect_args.pending_responding_commitment_signed.0 = true;
reconnect_nodes(reconnect_args);
} else if messages_delivered == 5 {
// nodes[1] still wants its final RAA
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_announcement_sigs.0 = true;
reconnect_args.pending_raa.1 = true;
reconnect_nodes(reconnect_args);
} else if messages_delivered == 6 {
Expand All @@ -2752,7 +2760,16 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken

nodes[0].node.peer_disconnected(node_b_id);
nodes[1].node.peer_disconnected(node_a_id);
reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1]));
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
if !simulate_broken_lnd
&& (messages_delivered == 0 || (messages_delivered > 2 && messages_delivered < 6))
{
reconnect_args.send_announcement_sigs.0 = true;
}
if messages_delivered < 4 {
reconnect_args.send_announcement_sigs.1 = true;
}
reconnect_nodes(reconnect_args);

nodes[1].node.process_pending_htlc_forwards();

Expand Down Expand Up @@ -2850,6 +2867,10 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
nodes[1].node.peer_disconnected(node_a_id);
if messages_delivered < 2 {
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
if !simulate_broken_lnd && messages_delivered == 0 {
reconnect_args.send_announcement_sigs.0 = true;
}
reconnect_args.send_announcement_sigs.1 = true;
reconnect_args.pending_htlc_claims.0 = 1;
reconnect_nodes(reconnect_args);
if messages_delivered < 1 {
Expand All @@ -2860,12 +2881,14 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
} else if messages_delivered == 2 {
// nodes[0] still wants its RAA + commitment_signed
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_announcement_sigs.1 = true;
reconnect_args.pending_responding_commitment_signed.1 = true;
reconnect_args.pending_raa.1 = true;
reconnect_nodes(reconnect_args);
} else if messages_delivered == 3 {
// nodes[0] still wants its commitment_signed
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_announcement_sigs.1 = true;
reconnect_args.pending_responding_commitment_signed.1 = true;
reconnect_nodes(reconnect_args);
} else if messages_delivered == 4 {
Expand All @@ -2885,7 +2908,15 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
nodes[0].node.peer_disconnected(node_b_id);
nodes[1].node.peer_disconnected(node_a_id);
}
reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1]));
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
if !simulate_broken_lnd {
if messages_delivered == 0 {
reconnect_args.send_announcement_sigs.0 = true;
} else if messages_delivered == 2 || messages_delivered == 3 {
reconnect_args.send_announcement_sigs.1 = true;
}
}
reconnect_nodes(reconnect_args);

if messages_delivered > 2 {
expect_payment_path_successful!(nodes[0]);
Expand Down
1 change: 1 addition & 0 deletions lightning/src/ln/payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4858,6 +4858,7 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) {
}
let mut reconnect_args = ReconnectArgs::new(&nodes[2], &nodes[3]);
reconnect_args.send_channel_ready = (true, true);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);

// Create a new channel between C and D as A will refuse to retry on the existing one because
Expand Down
1 change: 1 addition & 0 deletions lightning/src/ln/quiescence_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ fn do_test_quiescence_termination_on_disconnect(reload: bool) {

let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_channel_ready = (true, true);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);

send_payment(&nodes[0], &[&nodes[1]], 1_000_000);
Expand Down
1 change: 1 addition & 0 deletions lightning/src/ln/reorg_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ fn do_test_unconf_chan(reload_node: bool, reorg_after_reload: bool, use_funding_
// generate an error message we can handle below.
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_channel_ready = (true, true);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);
}
}
Expand Down
3 changes: 3 additions & 0 deletions lightning/src/ln/splicing_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ fn do_test_splice_state_reset_on_disconnect(reload: bool) {

let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_channel_ready = (true, true);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);

nodes[0]
Expand Down Expand Up @@ -457,6 +458,7 @@ fn do_test_splice_state_reset_on_disconnect(reload: bool) {

let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_channel_ready = (true, true);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);

// Attempt a splice negotiation that completes, (i.e. `tx_signatures` are exchanged). Reconnecting
Expand Down Expand Up @@ -488,6 +490,7 @@ fn do_test_splice_state_reset_on_disconnect(reload: bool) {
}

let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
reconnect_args.send_announcement_sigs = (true, true);
reconnect_nodes(reconnect_args);

mine_transaction(&nodes[0], &splice_tx);
Expand Down