Skip to content

Commit baac0a3

Browse files
TheBlueMattwaterson
authored andcommitted
Handle sign_counterparty_commitment failing during outb 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 outbound channel funding, setting a new flag in `ChannelContext` which indicates we should retry sending the `funding_created` later. We don't yet add any ability to do that retry.
1 parent 7e2ad07 commit baac0a3

File tree

3 files changed

+40
-34
lines changed

3 files changed

+40
-34
lines changed

lightning/src/ln/channel.rs

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,10 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
757757
/// This flag is set in such a case. Note that we don't need to persist this as we'll end up
758758
/// setting it again as a side-effect of [`Channel::channel_reestablish`].
759759
signer_pending_commitment_update: bool,
760+
/// Similar to [`Self::signer_pending_commitment_update`] but we're waiting to send either a
761+
/// [`msgs::FundingCreated`] or [`msgs::FundingSigned`] depending on if this channel is
762+
/// outbound or inbound.
763+
signer_pending_funding: bool,
760764

761765
// pending_update_fee is filled when sending and receiving update_fee.
762766
//
@@ -5847,6 +5851,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
58475851
monitor_pending_finalized_fulfills: Vec::new(),
58485852

58495853
signer_pending_commitment_update: false,
5854+
signer_pending_funding: false,
58505855

58515856
#[cfg(debug_assertions)]
58525857
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
@@ -5928,15 +5933,14 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59285933
})
59295934
}
59305935

5931-
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
5932-
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
5936+
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ()> where L::Target: Logger {
59335937
let counterparty_keys = self.context.build_remote_transaction_keys();
59345938
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
59355939
match &self.context.holder_signer {
59365940
// TODO (taproot|arik): move match into calling method for Taproot
59375941
ChannelSignerType::Ecdsa(ecdsa) => {
5938-
Ok(ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5939-
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0)
5942+
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5943+
.map(|(sig, _)| sig)
59405944
}
59415945
}
59425946
}
@@ -5949,7 +5953,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59495953
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
59505954
/// If an Err is returned, it is a ChannelError::Close.
59515955
pub fn get_funding_created<L: Deref>(mut self, funding_transaction: Transaction, funding_txo: OutPoint, is_batch_funding: bool, logger: &L)
5952-
-> Result<(Channel<SP>, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger {
5956+
-> Result<(Channel<SP>, Option<msgs::FundingCreated>), (Self, ChannelError)> where L::Target: Logger {
59535957
if !self.context.is_outbound() {
59545958
panic!("Tried to create outbound funding_created message on an inbound channel!");
59555959
}
@@ -5965,15 +5969,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59655969
self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
59665970
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
59675971

5968-
let signature = match self.get_funding_created_signature(logger) {
5969-
Ok(res) => res,
5970-
Err(e) => {
5971-
log_error!(logger, "Got bad signatures: {:?}!", e);
5972-
self.context.channel_transaction_parameters.funding_outpoint = None;
5973-
return Err((self, e));
5974-
}
5975-
};
5976-
59775972
let temporary_channel_id = self.context.channel_id;
59785973

59795974
// Now that we're past error-generating stuff, update our local state:
@@ -5992,20 +5987,27 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59925987
self.context.funding_transaction = Some(funding_transaction);
59935988
self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding);
59945989

5990+
let funding_created = if let Ok(signature) = self.get_funding_created_signature(logger) {
5991+
Some(msgs::FundingCreated {
5992+
temporary_channel_id,
5993+
funding_txid: funding_txo.txid,
5994+
funding_output_index: funding_txo.index,
5995+
signature,
5996+
#[cfg(taproot)]
5997+
partial_signature_with_nonce: None,
5998+
#[cfg(taproot)]
5999+
next_local_nonce: None,
6000+
})
6001+
} else {
6002+
self.context.signer_pending_funding = true;
6003+
None
6004+
};
6005+
59956006
let channel = Channel {
59966007
context: self.context,
59976008
};
59986009

5999-
Ok((channel, 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-
}))
6010+
Ok((channel, funding_created))
60096011
}
60106012

60116013
fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
@@ -6503,6 +6505,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
65036505
monitor_pending_finalized_fulfills: Vec::new(),
65046506

65056507
signer_pending_commitment_update: false,
6508+
signer_pending_funding: false,
65066509

65076510
#[cfg(debug_assertions)]
65086511
holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
@@ -7596,6 +7599,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
75967599
monitor_pending_finalized_fulfills: monitor_pending_finalized_fulfills.unwrap(),
75977600

75987601
signer_pending_commitment_update: false,
7602+
signer_pending_funding: false,
75997603

76007604
pending_update_fee,
76017605
holding_cell_update_fee,
@@ -7868,7 +7872,7 @@ mod tests {
78687872
}]};
78697873
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
78707874
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
7871-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7875+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
78727876

78737877
// Node B --> Node A: funding signed
78747878
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -7995,7 +7999,7 @@ mod tests {
79957999
}]};
79968000
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
79978001
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
7998-
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
8002+
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();
79998003

80008004
// Node B --> Node A: funding signed
80018005
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -8183,7 +8187,7 @@ mod tests {
81838187
}]};
81848188
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
81858189
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
8186-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
8190+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
81878191

81888192
// Node B --> Node A: funding signed
81898193
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -9255,7 +9259,7 @@ mod tests {
92559259
&&logger,
92569260
).map_err(|_| ()).unwrap();
92579261
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(
9258-
&funding_created_msg,
9262+
&funding_created_msg.unwrap(),
92599263
best_block,
92609264
&&keys_provider,
92619265
&&logger,

lightning/src/ln/channelmanager.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3803,7 +3803,7 @@ where
38033803

38043804
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
38053805
let peer_state = &mut *peer_state_lock;
3806-
let (chan, msg) = match peer_state.channel_by_id.remove(temporary_channel_id) {
3806+
let (chan, msg_opt) = match peer_state.channel_by_id.remove(temporary_channel_id) {
38073807
Some(ChannelPhase::UnfundedOutboundV1(chan)) => {
38083808
let funding_txo = find_funding_output(&chan, &funding_transaction)?;
38093809

@@ -3842,10 +3842,12 @@ where
38423842
}),
38433843
};
38443844

3845-
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3846-
node_id: chan.context.get_counterparty_node_id(),
3847-
msg,
3848-
});
3845+
if let Some(msg) = msg_opt {
3846+
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3847+
node_id: chan.context.get_counterparty_node_id(),
3848+
msg,
3849+
});
3850+
}
38493851
match peer_state.channel_by_id.entry(chan.context.channel_id()) {
38503852
hash_map::Entry::Occupied(_) => {
38513853
panic!("Generated duplicate funding txid?");

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9045,7 +9045,7 @@ fn test_duplicate_chan_id() {
90459045
}
90469046
};
90479047
check_added_monitors!(nodes[0], 0);
9048-
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
9048+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created.unwrap());
90499049
// At this point we'll look up if the channel_id is present and immediately fail the channel
90509050
// without trying to persist the `ChannelMonitor`.
90519051
check_added_monitors!(nodes[1], 0);

0 commit comments

Comments
 (0)