Skip to content

Commit d86f73b

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 1da2929 commit d86f73b

File tree

3 files changed

+46
-34
lines changed

3 files changed

+46
-34
lines changed

lightning/src/ln/channel.rs

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

760764
// pending_update_fee is filled when sending and receiving update_fee.
761765
//
@@ -4817,6 +4821,12 @@ impl<SP: Deref> Channel<SP> where
48174821
return None;
48184822
}
48194823

4824+
// If we're still pending the signature on a funding transaction, then we're not ready to send a
4825+
// channel_ready yet.
4826+
if self.context.signer_pending_funding {
4827+
return None;
4828+
}
4829+
48204830
// Note that we don't include ChannelState::WaitingForBatch as we don't want to send
48214831
// channel_ready until the entire batch is ready.
48224832
let non_shutdown_state = self.context.channel_state & (!MULTI_STATE_FLAGS);
@@ -5874,6 +5884,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
58745884
monitor_pending_finalized_fulfills: Vec::new(),
58755885

58765886
signer_pending_commitment_update: false,
5887+
signer_pending_funding: false,
58775888

58785889
#[cfg(debug_assertions)]
58795890
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
@@ -5955,15 +5966,14 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59555966
})
59565967
}
59575968

5958-
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
5959-
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
5969+
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ()> where L::Target: Logger {
59605970
let counterparty_keys = self.context.build_remote_transaction_keys();
59615971
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
59625972
match &self.context.holder_signer {
59635973
// TODO (taproot|arik): move match into calling method for Taproot
59645974
ChannelSignerType::Ecdsa(ecdsa) => {
5965-
Ok(ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5966-
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0)
5975+
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5976+
.map(|(sig, _)| sig)
59675977
}
59685978
}
59695979
}
@@ -5976,7 +5986,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59765986
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
59775987
/// If an Err is returned, it is a ChannelError::Close.
59785988
pub fn get_funding_created<L: Deref>(mut self, funding_transaction: Transaction, funding_txo: OutPoint, is_batch_funding: bool, logger: &L)
5979-
-> Result<(Channel<SP>, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger {
5989+
-> Result<(Channel<SP>, Option<msgs::FundingCreated>), (Self, ChannelError)> where L::Target: Logger {
59805990
if !self.context.is_outbound() {
59815991
panic!("Tried to create outbound funding_created message on an inbound channel!");
59825992
}
@@ -5992,15 +6002,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59926002
self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
59936003
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
59946004

5995-
let signature = match self.get_funding_created_signature(logger) {
5996-
Ok(res) => res,
5997-
Err(e) => {
5998-
log_error!(logger, "Got bad signatures: {:?}!", e);
5999-
self.context.channel_transaction_parameters.funding_outpoint = None;
6000-
return Err((self, e));
6001-
}
6002-
};
6003-
60046005
let temporary_channel_id = self.context.channel_id;
60056006

60066007
// Now that we're past error-generating stuff, update our local state:
@@ -6019,20 +6020,27 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
60196020
self.context.funding_transaction = Some(funding_transaction);
60206021
self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding);
60216022

6023+
let funding_created = if let Ok(signature) = self.get_funding_created_signature(logger) {
6024+
Some(msgs::FundingCreated {
6025+
temporary_channel_id,
6026+
funding_txid: funding_txo.txid,
6027+
funding_output_index: funding_txo.index,
6028+
signature,
6029+
#[cfg(taproot)]
6030+
partial_signature_with_nonce: None,
6031+
#[cfg(taproot)]
6032+
next_local_nonce: None,
6033+
})
6034+
} else {
6035+
self.context.signer_pending_funding = true;
6036+
None
6037+
};
6038+
60226039
let channel = Channel {
60236040
context: self.context,
60246041
};
60256042

6026-
Ok((channel, msgs::FundingCreated {
6027-
temporary_channel_id,
6028-
funding_txid: funding_txo.txid,
6029-
funding_output_index: funding_txo.index,
6030-
signature,
6031-
#[cfg(taproot)]
6032-
partial_signature_with_nonce: None,
6033-
#[cfg(taproot)]
6034-
next_local_nonce: None,
6035-
}))
6043+
Ok((channel, funding_created))
60366044
}
60376045

60386046
fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
@@ -6530,6 +6538,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
65306538
monitor_pending_finalized_fulfills: Vec::new(),
65316539

65326540
signer_pending_commitment_update: false,
6541+
signer_pending_funding: false,
65336542

65346543
#[cfg(debug_assertions)]
65356544
holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
@@ -7623,6 +7632,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
76237632
monitor_pending_finalized_fulfills: monitor_pending_finalized_fulfills.unwrap(),
76247633

76257634
signer_pending_commitment_update: false,
7635+
signer_pending_funding: false,
76267636

76277637
pending_update_fee,
76287638
holding_cell_update_fee,
@@ -7895,7 +7905,7 @@ mod tests {
78957905
}]};
78967906
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
78977907
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
7898-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7908+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
78997909

79007910
// Node B --> Node A: funding signed
79017911
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -8022,7 +8032,7 @@ mod tests {
80228032
}]};
80238033
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
80248034
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
8025-
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
8035+
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();
80268036

80278037
// Node B --> Node A: funding signed
80288038
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -8210,7 +8220,7 @@ mod tests {
82108220
}]};
82118221
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
82128222
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
8213-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
8223+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
82148224

82158225
// Node B --> Node A: funding signed
82168226
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -9282,7 +9292,7 @@ mod tests {
92829292
&&logger,
92839293
).map_err(|_| ()).unwrap();
92849294
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(
9285-
&funding_created_msg,
9295+
&funding_created_msg.unwrap(),
92869296
best_block,
92879297
&&keys_provider,
92889298
&&logger,

lightning/src/ln/channelmanager.rs

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

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

@@ -3841,10 +3841,12 @@ where
38413841
}),
38423842
};
38433843

3844-
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3845-
node_id: chan.context.get_counterparty_node_id(),
3846-
msg,
3847-
});
3844+
if let Some(msg) = msg_opt {
3845+
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3846+
node_id: chan.context.get_counterparty_node_id(),
3847+
msg,
3848+
});
3849+
}
38483850
match peer_state.channel_by_id.entry(chan.context.channel_id()) {
38493851
hash_map::Entry::Occupied(_) => {
38503852
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)