Skip to content
Open
Show file tree
Hide file tree
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
18 changes: 12 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, _, _, _) =
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 @@ -746,7 +746,8 @@ 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 @@ -759,11 +760,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 @@ -880,6 +881,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
assert!(as_resp.2.is_none());
assert!(as_resp.4.is_none());
assert!(as_resp.5.is_none());
assert!(as_resp.6.is_none());

if monitor_update_failure {
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
Expand All @@ -901,6 +903,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
assert!(as_resp.2.is_none());
assert!(as_resp.4.is_none());
assert!(as_resp.5.is_none());
assert!(as_resp.6.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 @@ -923,6 +926,9 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
assert!(as_resp.5.is_none());
assert!(bs_resp.5.is_none());

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

// Now that everything is restored, get the CS + RAA and handle them.
nodes[1]
.node
Expand Down
108 changes: 86 additions & 22 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8636,16 +8636,38 @@ where
}
}

fn on_tx_signatures_exchange(&mut self, funding_tx: Transaction) {
fn on_tx_signatures_exchange<'a, L: Deref>(
&mut self, funding_tx: Transaction, best_block_height: u32,
logger: &WithChannelContext<'a, L>,
) -> Option<msgs::SpliceLocked>
where
L::Target: Logger,
{
debug_assert!(!self.context.channel_state.is_monitor_update_in_progress());
debug_assert!(!self.context.channel_state.is_awaiting_remote_revoke());

let mut splice_locked = None;
if let Some(pending_splice) = self.pending_splice.as_mut() {
if let Some(FundingNegotiation::AwaitingSignatures { mut funding }) =
pending_splice.funding_negotiation.take()
{
funding.funding_transaction = Some(funding_tx);
pending_splice.negotiated_candidates.push(funding);
splice_locked = pending_splice.check_get_splice_locked(
&self.context,
pending_splice.negotiated_candidates.len() - 1,
best_block_height,
);
if let Some(splice_txid) =
splice_locked.as_ref().map(|splice_locked| splice_locked.splice_txid)
{
log_info!(
logger,
"Sending 0conf splice_locked txid {} to our peer for channel {}",
splice_txid,
&self.context.channel_id
);
}
} else {
debug_assert!(false);
}
Expand All @@ -8655,11 +8677,20 @@ where
self.context.channel_state =
ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
}

splice_locked
}

pub fn funding_transaction_signed(
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>,
) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), APIError> {
pub fn funding_transaction_signed<L: Deref>(
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>, best_block_height: u32,
logger: &L,
) -> Result<
(Option<msgs::TxSignatures>, Option<msgs::SpliceLocked>, Option<Transaction>),
APIError,
>
where
L::Target: Logger,
{
let signing_session =
if let Some(signing_session) = self.context.interactive_tx_signing_session.as_mut() {
if let Some(pending_splice) = self.pending_splice.as_ref() {
Expand All @@ -8674,17 +8705,17 @@ where
}

if signing_session.holder_tx_signatures().is_some() {
// Our `tx_signatures` either should've been the first time we processed them,
// or we're waiting for our counterparty to send theirs first.
return Ok((None, None));
// Our `tx_signatures` either should've been sent the first time we processed
// them, or we're waiting for our counterparty to send theirs first.
return Ok((None, None, None));
}

signing_session
} else {
if Some(funding_txid_signed) == self.funding.get_funding_txid() {
// We may be handling a duplicate call and the funding was already locked so we
// no longer have the signing session present.
return Ok((None, None));
return Ok((None, None, None));
}
let err =
format!("Channel {} not expecting funding signatures", self.context.channel_id);
Expand Down Expand Up @@ -8726,17 +8757,31 @@ where
.provide_holder_witnesses(tx_signatures, &self.context.secp_ctx)
.map_err(|err| APIError::APIMisuseError { err })?;

if let Some(funding_tx) = funding_tx_opt.clone() {
debug_assert!(tx_signatures_opt.is_some());
self.on_tx_signatures_exchange(funding_tx);
let logger = WithChannelContext::from(logger, &self.context, None);
if tx_signatures_opt.is_some() {
log_info!(
logger,
"Sending tx_signatures for interactive funding transaction {funding_txid_signed}"
);
}

Ok((tx_signatures_opt, funding_tx_opt))
let splice_locked_opt = funding_tx_opt.clone().and_then(|funding_tx| {
debug_assert!(tx_signatures_opt.is_some());
self.on_tx_signatures_exchange(funding_tx, best_block_height, &logger)
});

Ok((tx_signatures_opt, splice_locked_opt, funding_tx_opt))
}

pub fn tx_signatures(
&mut self, msg: &msgs::TxSignatures,
) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), ChannelError> {
pub fn tx_signatures<L: Deref>(
&mut self, msg: &msgs::TxSignatures, best_block_height: u32, logger: &L,
) -> Result<
(Option<msgs::TxSignatures>, Option<msgs::SpliceLocked>, Option<Transaction>),
ChannelError,
>
where
L::Target: Logger,
{
let signing_session = if let Some(signing_session) =
self.context.interactive_tx_signing_session.as_mut()
{
Expand Down Expand Up @@ -8782,11 +8827,18 @@ where
let (holder_tx_signatures_opt, funding_tx_opt) =
signing_session.received_tx_signatures(msg).map_err(|msg| ChannelError::Warn(msg))?;

if let Some(funding_tx) = funding_tx_opt.clone() {
self.on_tx_signatures_exchange(funding_tx);
}
let logger = WithChannelContext::from(logger, &self.context, None);
log_info!(
logger,
"Received tx_signatures for interactive funding transaction {}",
msg.tx_hash
);

let splice_locked_opt = funding_tx_opt.clone().and_then(|funding_tx| {
self.on_tx_signatures_exchange(funding_tx, best_block_height, &logger)
});

Ok((holder_tx_signatures_opt, funding_tx_opt))
Ok((holder_tx_signatures_opt, splice_locked_opt, funding_tx_opt))
}

/// Queues up an outbound update fee by placing it in the holding cell. You should call
Expand Down Expand Up @@ -10879,6 +10931,12 @@ where
let announcement_sigs =
self.get_announcement_sigs(node_signer, chain_hash, user_config, block_height, logger);

if let Some(quiescent_action) = self.quiescent_action.as_ref() {
if matches!(quiescent_action, QuiescentAction::Splice(_)) {
self.context.channel_state.set_awaiting_quiescence();
}
}

Some(SpliceFundingPromotion {
funding_txo,
monitor_update,
Expand Down Expand Up @@ -11113,7 +11171,11 @@ where
confirmed_funding_index,
height,
) {
log_info!(logger, "Sending a splice_locked to our peer for channel {}", &self.context.channel_id);
log_info!(
logger, "Sending splice_locked txid {} to our peer for channel {}",
splice_locked.splice_txid,
&self.context.channel_id
);

let (funding_txo, monitor_update, announcement_sigs, discarded_funding) = chain_node_signer
.and_then(|(chain_hash, node_signer, user_config)| {
Expand Down Expand Up @@ -11546,10 +11608,10 @@ where
});
}

if !self.context.is_live() {
if !self.context.is_usable() {
return Err(APIError::APIMisuseError {
err: format!(
"Channel {} cannot be spliced, as channel is not live",
"Channel {} cannot be spliced as it is either pending open/close",
self.context.channel_id()
),
});
Expand Down Expand Up @@ -12695,13 +12757,15 @@ where
|| self.context.channel_state.is_awaiting_quiescence()
|| self.context.channel_state.is_local_stfu_sent()
{
log_info!(logger, "Channel is either pending or already quiescent");
return Ok(None);
}

self.context.channel_state.set_awaiting_quiescence();
if self.context.is_live() {
Ok(Some(self.send_stfu(logger)?))
} else {
log_info!(logger, "Waiting for peer reconnection to send stfu");
Ok(None)
}
}
Expand Down
Loading