Skip to content

Commit 3dcb345

Browse files
TheBlueMattwaterson
authored andcommitted
Handle sign_counterparty_commitment failing during inb funding
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). Here we add initial handling of sign_counterparty_commitment failing during inbound channel funding, setting a flag in `ChannelContext` which indicates we should retry sending the `funding_signed` later. We don't yet add any ability to do that retry.
1 parent c6f0cb8 commit 3dcb345

File tree

2 files changed

+38
-22
lines changed

2 files changed

+38
-22
lines changed

lightning/src/ln/channel.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6545,7 +6545,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
65456545
self.generate_accept_channel_message()
65466546
}
65476547

6548-
fn funding_created_signature<L: Deref>(&mut self, sig: &Signature, logger: &L) -> Result<(CommitmentTransaction, CommitmentTransaction, Signature), ChannelError> where L::Target: Logger {
6548+
fn funding_created_signature<L: Deref>(&mut self, sig: &Signature, logger: &L) -> Result<(CommitmentTransaction, CommitmentTransaction, Option<Signature>), ChannelError> where L::Target: Logger {
65496549
let funding_script = self.context.get_funding_redeemscript();
65506550

65516551
let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
@@ -6574,7 +6574,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
65746574
// TODO (arik): move match into calling method for Taproot
65756575
ChannelSignerType::Ecdsa(ecdsa) => {
65766576
let counterparty_signature = ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
6577-
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0;
6577+
.map(|(sig, _)| sig).ok();
65786578

65796579
// We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish.
65806580
Ok((counterparty_initial_commitment_tx, initial_commitment_tx, counterparty_signature))
@@ -6584,7 +6584,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
65846584

65856585
pub fn funding_created<L: Deref>(
65866586
mut self, msg: &msgs::FundingCreated, best_block: BestBlock, signer_provider: &SP, logger: &L
6587-
) -> Result<(Channel<SP>, msgs::FundingSigned, ChannelMonitor<<SP::Target as SignerProvider>::Signer>), (Self, ChannelError)>
6587+
) -> Result<(Channel<SP>, Option<msgs::FundingSigned>, ChannelMonitor<<SP::Target as SignerProvider>::Signer>), (Self, ChannelError)>
65886588
where
65896589
L::Target: Logger
65906590
{
@@ -6609,7 +6609,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
66096609
// funding_created_signature may fail.
66106610
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
66116611

6612-
let (counterparty_initial_commitment_tx, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) {
6612+
let (counterparty_initial_commitment_tx, initial_commitment_tx, sig_opt) = match self.funding_created_signature(&msg.signature, logger) {
66136613
Ok(res) => res,
66146614
Err(ChannelError::Close(e)) => {
66156615
self.context.channel_transaction_parameters.funding_outpoint = None;
@@ -6673,12 +6673,19 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
66736673
let need_channel_ready = channel.check_get_channel_ready(0).is_some();
66746674
channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
66756675

6676-
Ok((channel, msgs::FundingSigned {
6677-
channel_id,
6678-
signature,
6679-
#[cfg(taproot)]
6680-
partial_signature_with_nonce: None,
6681-
}, channel_monitor))
6676+
let funding_signed = if let Some(signature) = sig_opt {
6677+
Some(msgs::FundingSigned {
6678+
channel_id,
6679+
signature,
6680+
#[cfg(taproot)]
6681+
partial_signature_with_nonce: None,
6682+
})
6683+
} else {
6684+
channel.context.signer_pending_funding = true;
6685+
None
6686+
};
6687+
6688+
Ok((channel, funding_signed, channel_monitor))
66826689
}
66836690
}
66846691

@@ -7761,7 +7768,7 @@ mod tests {
77617768
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
77627769

77637770
// Node B --> Node A: funding signed
7764-
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
7771+
let _ = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger).unwrap();
77657772

77667773
// Put some inbound and outbound HTLCs in A's channel.
77677774
let htlc_amount_msat = 11_092_000; // put an amount below A's effective dust limit but above B's.
@@ -7888,7 +7895,7 @@ mod tests {
78887895
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
78897896

78907897
// Node B --> Node A: funding signed
7891-
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
7898+
let _ = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger).unwrap();
78927899

78937900
// Now disconnect the two nodes and check that the commitment point in
78947901
// Node B's channel_reestablish message is sane.
@@ -8076,7 +8083,7 @@ mod tests {
80768083
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
80778084

80788085
// Node B --> Node A: funding signed
8079-
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
8086+
let _ = node_a_chan.funding_signed(&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger).unwrap();
80808087

80818088
// Make sure that receiving a channel update will update the Channel as expected.
80828089
let update = ChannelUpdate {

lightning/src/ln/channelmanager.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5842,7 +5842,7 @@ where
58425842

58435843
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
58445844
let peer_state = &mut *peer_state_lock;
5845-
let (chan, funding_msg, monitor) =
5845+
let (chan, funding_msg_opt, monitor) =
58465846
match peer_state.channel_by_id.remove(&msg.temporary_channel_id) {
58475847
Some(ChannelPhase::UnfundedInboundV1(inbound_chan)) => {
58485848
match inbound_chan.funding_created(msg, best_block, &self.signer_provider, &self.logger) {
@@ -5865,17 +5865,20 @@ where
58655865
None => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id))
58665866
};
58675867

5868-
match peer_state.channel_by_id.entry(funding_msg.channel_id) {
5868+
match peer_state.channel_by_id.entry(chan.context.channel_id()) {
58695869
hash_map::Entry::Occupied(_) => {
5870-
Err(MsgHandleErrInternal::send_err_msg_no_close("Already had channel with the new channel_id".to_owned(), funding_msg.channel_id))
5870+
Err(MsgHandleErrInternal::send_err_msg_no_close(
5871+
"Already had channel with the new channel_id".to_owned(),
5872+
chan.context.channel_id()
5873+
))
58715874
},
58725875
hash_map::Entry::Vacant(e) => {
58735876
let mut id_to_peer_lock = self.id_to_peer.lock().unwrap();
58745877
match id_to_peer_lock.entry(chan.context.channel_id()) {
58755878
hash_map::Entry::Occupied(_) => {
58765879
return Err(MsgHandleErrInternal::send_err_msg_no_close(
58775880
"The funding_created message had the same funding_txid as an existing channel - funding is not possible".to_owned(),
5878-
funding_msg.channel_id))
5881+
chan.context.channel_id()))
58795882
},
58805883
hash_map::Entry::Vacant(i_e) => {
58815884
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
@@ -5887,10 +5890,12 @@ where
58875890
// hasn't persisted to disk yet - we can't lose money on a transaction that we haven't
58885891
// accepted payment from yet. We do, however, need to wait to send our channel_ready
58895892
// until we have persisted our monitor.
5890-
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingSigned {
5891-
node_id: counterparty_node_id.clone(),
5892-
msg: funding_msg,
5893-
});
5893+
if let Some(msg) = funding_msg_opt {
5894+
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingSigned {
5895+
node_id: counterparty_node_id.clone(),
5896+
msg,
5897+
});
5898+
}
58945899

58955900
if let ChannelPhase::Funded(chan) = e.insert(ChannelPhase::Funded(chan)) {
58965901
handle_new_monitor_update!(self, persist_state, peer_state_lock, peer_state,
@@ -5901,9 +5906,13 @@ where
59015906
Ok(())
59025907
} else {
59035908
log_error!(self.logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
5909+
let channel_id = match funding_msg_opt {
5910+
Some(msg) => msg.channel_id,
5911+
None => chan.context.channel_id(),
5912+
};
59045913
return Err(MsgHandleErrInternal::send_err_msg_no_close(
59055914
"The funding_created message had the same funding_txid as an existing channel - funding is not possible".to_owned(),
5906-
funding_msg.channel_id));
5915+
channel_id));
59075916
}
59085917
}
59095918
}

0 commit comments

Comments
 (0)