Skip to content

Commit 3ce8204

Browse files
authored
Merge pull request #4079 from wpaulino/test-splice-reestablish
Test channel reestablish during splice lifecycle
2 parents fec434b + 5594f9b commit 3ce8204

10 files changed

+543
-131
lines changed

lightning/src/ln/async_signer_tests.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ fn do_test_async_raa_peer_disconnect(
596596
}
597597

598598
// Expect the RAA
599-
let (_, revoke_and_ack, commitment_signed, resend_order) =
599+
let (_, revoke_and_ack, commitment_signed, resend_order, _, _) =
600600
handle_chan_reestablish_msgs!(dst, src);
601601
if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
602602
assert!(revoke_and_ack.is_none());
@@ -612,14 +612,15 @@ fn do_test_async_raa_peer_disconnect(
612612
dst.node.signer_unblocked(Some((src_node_id, chan_id)));
613613

614614
if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
615-
let (_, revoke_and_ack, commitment_signed, resend_order) =
615+
let (_, revoke_and_ack, commitment_signed, resend_order, _, _) =
616616
handle_chan_reestablish_msgs!(dst, src);
617617
assert!(revoke_and_ack.is_some());
618618
assert!(commitment_signed.is_some());
619619
assert!(resend_order == RAACommitmentOrder::RevokeAndACKFirst);
620620
} else {
621621
// Make sure we don't double send the RAA.
622-
let (_, revoke_and_ack, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
622+
let (_, revoke_and_ack, commitment_signed, _, _, _) =
623+
handle_chan_reestablish_msgs!(dst, src);
623624
assert!(revoke_and_ack.is_none());
624625
assert!(commitment_signed.is_none());
625626
}
@@ -745,7 +746,7 @@ fn do_test_async_commitment_signature_peer_disconnect(
745746
}
746747

747748
// Expect the RAA
748-
let (_, revoke_and_ack, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
749+
let (_, revoke_and_ack, commitment_signed, _, _, _) = handle_chan_reestablish_msgs!(dst, src);
749750
assert!(revoke_and_ack.is_some());
750751
if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
751752
assert!(commitment_signed.is_none());
@@ -758,11 +759,11 @@ fn do_test_async_commitment_signature_peer_disconnect(
758759
dst.node.signer_unblocked(Some((src_node_id, chan_id)));
759760

760761
if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
761-
let (_, _, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
762+
let (_, _, commitment_signed, _, _, _) = handle_chan_reestablish_msgs!(dst, src);
762763
assert!(commitment_signed.is_some());
763764
} else {
764765
// Make sure we don't double send the CS.
765-
let (_, _, commitment_signed, _) = handle_chan_reestablish_msgs!(dst, src);
766+
let (_, _, commitment_signed, _, _, _) = handle_chan_reestablish_msgs!(dst, src);
766767
assert!(commitment_signed.is_none());
767768
}
768769
}
@@ -877,6 +878,8 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
877878
assert!(as_resp.0.is_none());
878879
assert!(as_resp.1.is_none());
879880
assert!(as_resp.2.is_none());
881+
assert!(as_resp.4.is_none());
882+
assert!(as_resp.5.is_none());
880883

881884
if monitor_update_failure {
882885
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
@@ -896,6 +899,8 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
896899
assert!(as_resp.0.is_none());
897900
assert!(as_resp.1.is_none());
898901
assert!(as_resp.2.is_none());
902+
assert!(as_resp.4.is_none());
903+
assert!(as_resp.5.is_none());
899904

900905
nodes[0].enable_channel_signer_op(&node_b_id, &chan_id, SignerOp::SignCounterpartyCommitment);
901906
nodes[0].node.signer_unblocked(Some((node_b_id, chan_id)));
@@ -912,6 +917,12 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
912917

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

920+
assert!(as_resp.4.is_none());
921+
assert!(bs_resp.4.is_none());
922+
923+
assert!(as_resp.5.is_none());
924+
assert!(bs_resp.5.is_none());
925+
915926
// Now that everything is restored, get the CS + RAA and handle them.
916927
nodes[1]
917928
.node

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
206206
nodes[1].node.peer_disconnected(node_a_id);
207207
let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]);
208208
reconnect_args.send_channel_ready = (true, true);
209+
reconnect_args.send_announcement_sigs = (true, true);
209210
reconnect_nodes(reconnect_args);
210211
}
211212

lightning/src/ln/channel.rs

Lines changed: 72 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,8 +1694,7 @@ where
16941694
pending_v2_channel.interactive_tx_constructor.take();
16951695
},
16961696
ChannelPhase::Funded(funded_channel) => {
1697-
if funded_channel.should_reset_pending_splice_funding_negotiation().unwrap_or(true)
1698-
{
1697+
if funded_channel.should_reset_pending_splice_state() {
16991698
funded_channel.reset_pending_splice_state();
17001699
} else {
17011700
debug_assert!(false, "We should never fail an interactive funding negotiation once we're exchanging tx_signatures");
@@ -1829,18 +1828,15 @@ where
18291828
pending_v2_channel.interactive_tx_constructor.take().is_some()
18301829
},
18311830
ChannelPhase::Funded(funded_channel) => {
1832-
if let Some(should_reset) =
1833-
funded_channel.should_reset_pending_splice_funding_negotiation()
1834-
{
1835-
if should_reset {
1836-
// We may have still tracked the pending funding negotiation state, so we
1837-
// should ack with our own `tx_abort`.
1838-
funded_channel.reset_pending_splice_state()
1839-
} else {
1840-
return Err(ChannelError::close(
1841-
"Received tx_abort while awaiting tx_signatures exchange".to_owned(),
1842-
));
1843-
}
1831+
if funded_channel.has_pending_splice_awaiting_signatures() {
1832+
return Err(ChannelError::close(
1833+
"Received tx_abort while awaiting tx_signatures exchange".to_owned(),
1834+
));
1835+
}
1836+
if funded_channel.should_reset_pending_splice_state() {
1837+
let has_funding_negotiation = funded_channel.reset_pending_splice_state();
1838+
debug_assert!(has_funding_negotiation);
1839+
true
18441840
} else {
18451841
// We were not tracking the pending funding negotiation state anymore, likely
18461842
// due to a disconnection or already having sent our own `tx_abort`.
@@ -2583,13 +2579,17 @@ impl FundingNegotiation {
25832579
}
25842580

25852581
impl PendingFunding {
2586-
fn can_abandon_funding_negotiation(&self) -> bool {
2582+
fn can_abandon_state(&self) -> bool {
25872583
self.funding_negotiation
25882584
.as_ref()
25892585
.map(|funding_negotiation| {
25902586
!matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures { .. })
25912587
})
2592-
.unwrap_or(true)
2588+
.unwrap_or_else(|| {
2589+
let has_negotiated_candidates = !self.negotiated_candidates.is_empty();
2590+
debug_assert!(has_negotiated_candidates);
2591+
!has_negotiated_candidates
2592+
})
25932593
}
25942594

25952595
fn check_get_splice_locked<SP: Deref>(
@@ -6773,40 +6773,35 @@ where
67736773
)
67746774
}
67756775

6776-
/// Returns `None` if there is no [`FundedChannel::pending_splice`], otherwise a boolean
6777-
/// indicating whether we should reset the splice's [`PendingFunding::funding_negotiation`].
6778-
fn should_reset_pending_splice_funding_negotiation(&self) -> Option<bool> {
6779-
self.pending_splice.as_ref().map(|pending_splice| {
6780-
if pending_splice.can_abandon_funding_negotiation() {
6781-
true
6782-
} else {
6783-
self.context
6784-
.interactive_tx_signing_session
6785-
.as_ref()
6786-
.map(|signing_session| !signing_session.has_received_commitment_signed())
6787-
.unwrap_or_else(|| {
6788-
debug_assert!(false);
6789-
false
6790-
})
6791-
}
6792-
})
6776+
fn has_pending_splice_awaiting_signatures(&self) -> bool {
6777+
self.pending_splice
6778+
.as_ref()
6779+
.and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
6780+
.map(|funding_negotiation| {
6781+
matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures { .. })
6782+
})
6783+
.unwrap_or(false)
67936784
}
67946785

6786+
/// Returns a boolean indicating whether we should reset the splice's
6787+
/// [`PendingFunding::funding_negotiation`].
67956788
fn should_reset_pending_splice_state(&self) -> bool {
6796-
self.should_reset_pending_splice_funding_negotiation().unwrap_or(true)
6797-
&& self.pending_funding().is_empty()
6789+
self.pending_splice
6790+
.as_ref()
6791+
.map(|pending_splice| pending_splice.can_abandon_state())
6792+
.unwrap_or(false)
67986793
}
67996794

68006795
fn reset_pending_splice_state(&mut self) -> bool {
6801-
debug_assert!(self.should_reset_pending_splice_funding_negotiation().unwrap_or(true));
6796+
debug_assert!(self.should_reset_pending_splice_state());
6797+
debug_assert!(self.context.interactive_tx_signing_session.is_none());
68026798
self.context.channel_state.clear_quiescent();
6803-
self.context.interactive_tx_signing_session.take();
68046799
let has_funding_negotiation = self
68056800
.pending_splice
68066801
.as_mut()
68076802
.and_then(|pending_splice| pending_splice.funding_negotiation.take())
68086803
.is_some();
6809-
if self.should_reset_pending_splice_state() {
6804+
if self.pending_funding().is_empty() {
68106805
self.pending_splice.take();
68116806
}
68126807
has_funding_negotiation
@@ -8678,8 +8673,19 @@ where
86788673
.unwrap_or(false));
86798674
}
86808675

8676+
if signing_session.holder_tx_signatures().is_some() {
8677+
// Our `tx_signatures` either should've been the first time we processed them,
8678+
// or we're waiting for our counterparty to send theirs first.
8679+
return Ok((None, None));
8680+
}
8681+
86818682
signing_session
86828683
} else {
8684+
if Some(funding_txid_signed) == self.funding.get_funding_txid() {
8685+
// We may be handling a duplicate call and the funding was already locked so we
8686+
// no longer have the signing session present.
8687+
return Ok((None, None));
8688+
}
86838689
let err =
86848690
format!("Channel {} not expecting funding signatures", self.context.channel_id);
86858691
return Err(APIError::APIMisuseError { err });
@@ -8937,13 +8943,16 @@ where
89378943
}
89388944
self.context.channel_state.clear_local_stfu_sent();
89398945
self.context.channel_state.clear_remote_stfu_sent();
8940-
if self.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
8941-
// If we were in quiescence but a splice was never negotiated, or the negotiation
8942-
// failed due to disconnecting, we shouldn't be quiescent anymore upon reconnecting.
8943-
// If there was a pending splice negotiation that has failed due to disconnecting,
8944-
// we also take the opportunity to clean up our state.
8946+
if self.should_reset_pending_splice_state() {
8947+
// If there was a pending splice negotiation that failed due to disconnecting, we
8948+
// also take the opportunity to clean up our state.
89458949
self.reset_pending_splice_state();
89468950
debug_assert!(!self.context.channel_state.is_quiescent());
8951+
} else if !self.has_pending_splice_awaiting_signatures() {
8952+
// We shouldn't be quiescent anymore upon reconnecting if:
8953+
// - We were in quiescence but a splice/RBF was never negotiated or
8954+
// - We were in quiescence but the splice negotiation failed due to disconnecting
8955+
self.context.channel_state.clear_quiescent();
89478956
}
89488957
}
89498958

@@ -9682,12 +9691,18 @@ where
96829691

96839692
// A node:
96849693
// - if `next_commitment_number` is 1 in both the `channel_reestablish` it
9685-
// sent and received:
9694+
// sent and received, and none of those `channel_reestablish` messages
9695+
// contain `my_current_funding_locked` or `next_funding` for a splice transaction:
96869696
// - MUST retransmit `channel_ready`.
96879697
// - otherwise:
96889698
// - MUST NOT retransmit `channel_ready`, but MAY send `channel_ready` with
96899699
// a different `short_channel_id` `alias` field.
9690-
let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.holder_commitment_point.next_transaction_number() == 1 {
9700+
let both_sides_on_initial_commitment_number = msg.next_local_commitment_number == 1
9701+
&& INITIAL_COMMITMENT_NUMBER - self.holder_commitment_point.next_transaction_number() == 1;
9702+
let channel_ready = if both_sides_on_initial_commitment_number
9703+
&& self.pending_splice.is_none()
9704+
&& self.funding.channel_transaction_parameters.splice_parent_funding_txid.is_none()
9705+
{
96919706
// We should never have to worry about MonitorUpdateInProgress resending ChannelReady
96929707
self.get_channel_ready(logger)
96939708
} else { None };
@@ -13976,10 +13991,13 @@ where
1397613991
}
1397713992
channel_state.clear_local_stfu_sent();
1397813993
channel_state.clear_remote_stfu_sent();
13979-
if self.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
13980-
// If we were in quiescence but a splice was never negotiated, or the
13981-
// negotiation failed due to disconnecting, we shouldn't be quiescent
13982-
// anymore upon reconnecting.
13994+
if self.should_reset_pending_splice_state()
13995+
|| !self.has_pending_splice_awaiting_signatures()
13996+
{
13997+
// We shouldn't be quiescent anymore upon reconnecting if:
13998+
// - We were in quiescence but a splice/RBF was never negotiated or
13999+
// - We were in quiescence but the splice negotiation failed due to
14000+
// disconnecting
1398314001
channel_state.clear_quiescent();
1398414002
}
1398514003
},
@@ -14344,19 +14362,10 @@ where
1434414362
let holder_commitment_point_next = self.holder_commitment_point.next_point();
1434514363
let holder_commitment_point_pending_next = self.holder_commitment_point.pending_next_point;
1434614364

14347-
let interactive_tx_signing_session =
14348-
if self.should_reset_pending_splice_funding_negotiation().unwrap_or(false) {
14349-
None
14350-
} else {
14351-
self.context.interactive_tx_signing_session.as_ref()
14352-
};
14353-
let pending_splice = if self.should_reset_pending_splice_state() {
14354-
None
14355-
} else {
14356-
// We don't have to worry about resetting the pending `FundingNegotiation` because we
14357-
// can only read `FundingNegotiation::AwaitingSignatures` variants anyway.
14358-
self.pending_splice.as_ref()
14359-
};
14365+
// We don't have to worry about resetting the pending `FundingNegotiation` because we
14366+
// can only read `FundingNegotiation::AwaitingSignatures` variants anyway.
14367+
let pending_splice =
14368+
self.pending_splice.as_ref().filter(|_| !self.should_reset_pending_splice_state());
1436014369

1436114370
write_tlv_fields!(writer, {
1436214371
(0, self.context.announcement_sigs, option),
@@ -14401,7 +14410,7 @@ where
1440114410
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
1440214411
(55, removed_htlc_attribution_data, optional_vec), // Added in 0.2
1440314412
(57, holding_cell_attribution_data, optional_vec), // Added in 0.2
14404-
(58, interactive_tx_signing_session, option), // Added in 0.2
14413+
(58, self.context.interactive_tx_signing_session, option), // Added in 0.2
1440514414
(59, self.funding.minimum_depth_override, option), // Added in 0.2
1440614415
(60, self.context.historical_scids, optional_vec), // Added in 0.2
1440714416
(61, fulfill_attribution_data, optional_vec), // Added in 0.2

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9391,6 +9391,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
93919391
if let Some(signing_session) = (!channel.is_awaiting_monitor_update())
93929392
.then(|| ())
93939393
.and_then(|_| channel.context.interactive_tx_signing_session.as_mut())
9394+
.filter(|signing_session| signing_session.has_received_commitment_signed())
93949395
.filter(|signing_session| signing_session.holder_tx_signatures().is_none())
93959396
{
93969397
if signing_session.has_local_contribution() {

0 commit comments

Comments
 (0)