Skip to content

Commit 05f2848

Browse files
authored
Merge pull request lightningdevkit#4122 from wpaulino/test-splice-while-disconnected
Allow outgoing splice request while disconnected
2 parents ec6d9a7 + 5452f15 commit 05f2848

File tree

5 files changed

+599
-106
lines changed

5 files changed

+599
-106
lines changed

lightning/src/ln/async_signer_tests.rs

Lines changed: 12 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,14 @@ 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, _, _, _) =
622+
let (_, revoke_and_ack, commitment_signed, _, _, _, _) =
623623
handle_chan_reestablish_msgs!(dst, src);
624624
assert!(revoke_and_ack.is_none());
625625
assert!(commitment_signed.is_none());
@@ -746,7 +746,8 @@ fn do_test_async_commitment_signature_peer_disconnect(
746746
}
747747

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

761762
if test_case == UnblockSignerAcrossDisconnectCase::AtEnd {
762-
let (_, _, commitment_signed, _, _, _) = handle_chan_reestablish_msgs!(dst, src);
763+
let (_, _, commitment_signed, _, _, _, _) = handle_chan_reestablish_msgs!(dst, src);
763764
assert!(commitment_signed.is_some());
764765
} else {
765766
// Make sure we don't double send the CS.
766-
let (_, _, commitment_signed, _, _, _) = handle_chan_reestablish_msgs!(dst, src);
767+
let (_, _, commitment_signed, _, _, _, _) = handle_chan_reestablish_msgs!(dst, src);
767768
assert!(commitment_signed.is_none());
768769
}
769770
}
@@ -880,6 +881,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
880881
assert!(as_resp.2.is_none());
881882
assert!(as_resp.4.is_none());
882883
assert!(as_resp.5.is_none());
884+
assert!(as_resp.6.is_none());
883885

884886
if monitor_update_failure {
885887
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
@@ -901,6 +903,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
901903
assert!(as_resp.2.is_none());
902904
assert!(as_resp.4.is_none());
903905
assert!(as_resp.5.is_none());
906+
assert!(as_resp.6.is_none());
904907

905908
nodes[0].enable_channel_signer_op(&node_b_id, &chan_id, SignerOp::SignCounterpartyCommitment);
906909
nodes[0].node.signer_unblocked(Some((node_b_id, chan_id)));
@@ -923,6 +926,9 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
923926
assert!(as_resp.5.is_none());
924927
assert!(bs_resp.5.is_none());
925928

929+
assert!(as_resp.6.is_none());
930+
assert!(bs_resp.6.is_none());
931+
926932
// Now that everything is restored, get the CS + RAA and handle them.
927933
nodes[1]
928934
.node

lightning/src/ln/channel.rs

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6846,6 +6846,9 @@ pub struct FundingTxSigned {
68466846

68476847
/// Information about the completed funding negotiation.
68486848
pub splice_negotiated: Option<SpliceFundingNegotiated>,
6849+
6850+
/// A `splice_locked` to send to the counterparty when the splice requires 0 confirmations.
6851+
pub splice_locked: Option<msgs::SpliceLocked>,
68496852
}
68506853

68516854
/// Information about a splice funding negotiation that has been completed.
@@ -8877,9 +8880,13 @@ where
88778880
}
88788881
}
88798882

8880-
fn on_tx_signatures_exchange(
8881-
&mut self, funding_tx: Transaction,
8882-
) -> Option<SpliceFundingNegotiated> {
8883+
fn on_tx_signatures_exchange<'a, L: Deref>(
8884+
&mut self, funding_tx: Transaction, best_block_height: u32,
8885+
logger: &WithChannelContext<'a, L>,
8886+
) -> (Option<SpliceFundingNegotiated>, Option<msgs::SpliceLocked>)
8887+
where
8888+
L::Target: Logger,
8889+
{
88838890
debug_assert!(!self.context.channel_state.is_monitor_update_in_progress());
88848891
debug_assert!(!self.context.channel_state.is_awaiting_remote_revoke());
88858892

@@ -8901,22 +8908,42 @@ where
89018908
channel_type,
89028909
};
89038910

8904-
Some(splice_negotiated)
8911+
let splice_locked = pending_splice.check_get_splice_locked(
8912+
&self.context,
8913+
pending_splice.negotiated_candidates.len() - 1,
8914+
best_block_height,
8915+
);
8916+
if let Some(splice_txid) =
8917+
splice_locked.as_ref().map(|splice_locked| splice_locked.splice_txid)
8918+
{
8919+
log_info!(
8920+
logger,
8921+
"Sending 0conf splice_locked txid {} to our peer for channel {}",
8922+
splice_txid,
8923+
&self.context.channel_id
8924+
);
8925+
}
8926+
8927+
(Some(splice_negotiated), splice_locked)
89058928
} else {
89068929
debug_assert!(false);
8907-
None
8930+
(None, None)
89088931
}
89098932
} else {
89108933
self.funding.funding_transaction = Some(funding_tx);
89118934
self.context.channel_state =
89128935
ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
8913-
None
8936+
(None, None)
89148937
}
89158938
}
89168939

8917-
pub fn funding_transaction_signed(
8918-
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>,
8919-
) -> Result<FundingTxSigned, APIError> {
8940+
pub fn funding_transaction_signed<L: Deref>(
8941+
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>, best_block_height: u32,
8942+
logger: &L,
8943+
) -> Result<FundingTxSigned, APIError>
8944+
where
8945+
L::Target: Logger,
8946+
{
89208947
let signing_session =
89218948
if let Some(signing_session) = self.context.interactive_tx_signing_session.as_mut() {
89228949
if let Some(pending_splice) = self.pending_splice.as_ref() {
@@ -8937,6 +8964,7 @@ where
89378964
tx_signatures: None,
89388965
funding_tx: None,
89398966
splice_negotiated: None,
8967+
splice_locked: None,
89408968
});
89418969
}
89428970

@@ -8949,6 +8977,7 @@ where
89498977
tx_signatures: None,
89508978
funding_tx: None,
89518979
splice_negotiated: None,
8980+
splice_locked: None,
89528981
});
89538982
}
89548983
let err =
@@ -8991,19 +9020,30 @@ where
89919020
.provide_holder_witnesses(tx_signatures, &self.context.secp_ctx)
89929021
.map_err(|err| APIError::APIMisuseError { err })?;
89939022

8994-
let splice_negotiated = if let Some(funding_tx) = funding_tx.clone() {
9023+
let logger = WithChannelContext::from(logger, &self.context, None);
9024+
if tx_signatures.is_some() {
9025+
log_info!(
9026+
logger,
9027+
"Sending tx_signatures for interactive funding transaction {funding_txid_signed}"
9028+
);
9029+
}
9030+
9031+
let (splice_negotiated, splice_locked) = if let Some(funding_tx) = funding_tx.clone() {
89959032
debug_assert!(tx_signatures.is_some());
8996-
self.on_tx_signatures_exchange(funding_tx)
9033+
self.on_tx_signatures_exchange(funding_tx, best_block_height, &logger)
89979034
} else {
8998-
None
9035+
(None, None)
89999036
};
90009037

9001-
Ok(FundingTxSigned { tx_signatures, funding_tx, splice_negotiated })
9038+
Ok(FundingTxSigned { tx_signatures, funding_tx, splice_negotiated, splice_locked })
90029039
}
90039040

9004-
pub fn tx_signatures(
9005-
&mut self, msg: &msgs::TxSignatures,
9006-
) -> Result<FundingTxSigned, ChannelError> {
9041+
pub fn tx_signatures<L: Deref>(
9042+
&mut self, msg: &msgs::TxSignatures, best_block_height: u32, logger: &L,
9043+
) -> Result<FundingTxSigned, ChannelError>
9044+
where
9045+
L::Target: Logger,
9046+
{
90079047
let signing_session = if let Some(signing_session) =
90089048
self.context.interactive_tx_signing_session.as_mut()
90099049
{
@@ -9049,13 +9089,25 @@ where
90499089
let (holder_tx_signatures, funding_tx) =
90509090
signing_session.received_tx_signatures(msg).map_err(|msg| ChannelError::Warn(msg))?;
90519091

9052-
let splice_negotiated = if let Some(funding_tx) = funding_tx.clone() {
9053-
self.on_tx_signatures_exchange(funding_tx)
9092+
let logger = WithChannelContext::from(logger, &self.context, None);
9093+
log_info!(
9094+
logger,
9095+
"Received tx_signatures for interactive funding transaction {}",
9096+
msg.tx_hash
9097+
);
9098+
9099+
let (splice_negotiated, splice_locked) = if let Some(funding_tx) = funding_tx.clone() {
9100+
self.on_tx_signatures_exchange(funding_tx, best_block_height, &logger)
90549101
} else {
9055-
None
9102+
(None, None)
90569103
};
90579104

9058-
Ok(FundingTxSigned { tx_signatures: holder_tx_signatures, funding_tx, splice_negotiated })
9105+
Ok(FundingTxSigned {
9106+
tx_signatures: holder_tx_signatures,
9107+
funding_tx,
9108+
splice_negotiated,
9109+
splice_locked,
9110+
})
90599111
}
90609112

90619113
/// Queues up an outbound update fee by placing it in the holding cell. You should call
@@ -11128,6 +11180,12 @@ where
1112811180
let announcement_sigs =
1112911181
self.get_announcement_sigs(node_signer, chain_hash, user_config, block_height, logger);
1113011182

11183+
if let Some(quiescent_action) = self.quiescent_action.as_ref() {
11184+
if matches!(quiescent_action, QuiescentAction::Splice(_)) {
11185+
self.context.channel_state.set_awaiting_quiescence();
11186+
}
11187+
}
11188+
1113111189
Some(SpliceFundingPromotion {
1113211190
funding_txo,
1113311191
monitor_update,
@@ -11362,7 +11420,11 @@ where
1136211420
confirmed_funding_index,
1136311421
height,
1136411422
) {
11365-
log_info!(logger, "Sending a splice_locked to our peer for channel {}", &self.context.channel_id);
11423+
log_info!(
11424+
logger, "Sending splice_locked txid {} to our peer for channel {}",
11425+
splice_locked.splice_txid,
11426+
&self.context.channel_id
11427+
);
1136611428

1136711429
let (funding_txo, monitor_update, announcement_sigs, discarded_funding) = chain_node_signer
1136811430
.and_then(|(chain_hash, node_signer, user_config)| {
@@ -11795,10 +11857,10 @@ where
1179511857
});
1179611858
}
1179711859

11798-
if !self.context.is_live() {
11860+
if !self.context.is_usable() {
1179911861
return Err(APIError::APIMisuseError {
1180011862
err: format!(
11801-
"Channel {} cannot be spliced, as channel is not live",
11863+
"Channel {} cannot be spliced as it is either pending open/close",
1180211864
self.context.channel_id()
1180311865
),
1180411866
});
@@ -12961,13 +13023,15 @@ where
1296113023
|| self.context.channel_state.is_awaiting_quiescence()
1296213024
|| self.context.channel_state.is_local_stfu_sent()
1296313025
{
13026+
log_debug!(logger, "Channel is either pending quiescence or already quiescent");
1296413027
return Ok(None);
1296513028
}
1296613029

1296713030
self.context.channel_state.set_awaiting_quiescence();
1296813031
if self.context.is_live() {
1296913032
Ok(Some(self.send_stfu(logger)?))
1297013033
} else {
13034+
log_debug!(logger, "Waiting for peer reconnection to send stfu");
1297113035
Ok(None)
1297213036
}
1297313037
}

0 commit comments

Comments
 (0)