Skip to content

Commit 3a6bd3d

Browse files
TheBlueMattwaterson
authored andcommitted
Handle retrying sign_counterparty_commitment outb funding failures
If sign_counterparty_commitment fails (i.e. because the signer is temporarily disconnected), this really indicates that we should retry the message sending which required the signature later, rather than force-closing the channel (which probably won't even work if the signer is missing). This commit adds retrying of outbound funding_created signing failures, regenerating the `FundingCreated` message, attempting to re-sign, and sending it to our peers if we succeed.
1 parent e9b5f25 commit 3a6bd3d

File tree

1 file changed

+31
-27
lines changed

1 file changed

+31
-27
lines changed

lightning/src/ln/channel.rs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,31 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
20852085
self.update_time_counter += 1;
20862086
(monitor_update, dropped_outbound_htlcs, unbroadcasted_batch_funding_txid)
20872087
}
2088+
2089+
/// Only allowed after [`Self::channel_transaction_parameters`] is set.
2090+
fn get_funding_created_msg<L: Deref>(&mut self, logger: &L) -> Option<msgs::FundingCreated> where L::Target: Logger {
2091+
let counterparty_keys = self.build_remote_transaction_keys();
2092+
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
2093+
let signature = match &self.holder_signer {
2094+
// TODO (taproot|arik): move match into calling method for Taproot
2095+
ChannelSignerType::Ecdsa(ecdsa) => {
2096+
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.secp_ctx)
2097+
.map(|(sig, _)| sig).ok()?
2098+
}
2099+
};
2100+
2101+
self.signer_pending_funding = false;
2102+
Some(msgs::FundingCreated {
2103+
temporary_channel_id: self.temporary_channel_id.unwrap(),
2104+
funding_txid: self.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().txid,
2105+
funding_output_index: self.channel_transaction_parameters.funding_outpoint.as_ref().unwrap().index,
2106+
signature,
2107+
#[cfg(taproot)]
2108+
partial_signature_with_nonce: None,
2109+
#[cfg(taproot)]
2110+
next_local_nonce: None,
2111+
})
2112+
}
20882113
}
20892114

20902115
// Internal utility functions for channels
@@ -3911,7 +3936,9 @@ impl<SP: Deref> Channel<SP> where
39113936
self.get_last_commitment_update_for_send(logger).ok()
39123937
} else { None };
39133938
let funding_signed = None;
3914-
let funding_created = None;
3939+
let funding_created = if self.context.signer_pending_funding && self.context.is_outbound() {
3940+
self.context.get_funding_created_msg(logger)
3941+
} else { None };
39153942
SignerResumeUpdates {
39163943
commitment_update,
39173944
funding_signed,
@@ -5941,18 +5968,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59415968
})
59425969
}
59435970

5944-
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ()> where L::Target: Logger {
5945-
let counterparty_keys = self.context.build_remote_transaction_keys();
5946-
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
5947-
match &self.context.holder_signer {
5948-
// TODO (taproot|arik): move match into calling method for Taproot
5949-
ChannelSignerType::Ecdsa(ecdsa) => {
5950-
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5951-
.map(|(sig, _)| sig)
5952-
}
5953-
}
5954-
}
5955-
59565971
/// Updates channel state with knowledge of the funding transaction's txid/index, and generates
59575972
/// a funding_created message for the remote peer.
59585973
/// Panics if called at some time other than immediately after initial handshake, if called twice,
@@ -5995,21 +6010,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59956010
self.context.funding_transaction = Some(funding_transaction);
59966011
self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding);
59976012

5998-
let funding_created = if let Ok(signature) = self.get_funding_created_signature(logger) {
5999-
Some(msgs::FundingCreated {
6000-
temporary_channel_id,
6001-
funding_txid: funding_txo.txid,
6002-
funding_output_index: funding_txo.index,
6003-
signature,
6004-
#[cfg(taproot)]
6005-
partial_signature_with_nonce: None,
6006-
#[cfg(taproot)]
6007-
next_local_nonce: None,
6008-
})
6009-
} else {
6013+
let funding_created = self.context.get_funding_created_msg(logger);
6014+
if funding_created.is_none() {
60106015
self.context.signer_pending_funding = true;
6011-
None
6012-
};
6016+
}
60136017

60146018
let channel = Channel {
60156019
context: self.context,

0 commit comments

Comments
 (0)