Skip to content

Commit dda97a7

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 142cd45 commit dda97a7

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
@@ -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
//
@@ -5831,6 +5835,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
58315835
monitor_pending_finalized_fulfills: Vec::new(),
58325836

58335837
signer_pending_commitment_update: false,
5838+
signer_pending_funding: false,
58345839

58355840
#[cfg(debug_assertions)]
58365841
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
@@ -5912,15 +5917,14 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59125917
})
59135918
}
59145919

5915-
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
5916-
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
5920+
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ()> where L::Target: Logger {
59175921
let counterparty_keys = self.context.build_remote_transaction_keys();
59185922
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
59195923
match &self.context.holder_signer {
59205924
// TODO (taproot|arik): move match into calling method for Taproot
59215925
ChannelSignerType::Ecdsa(ecdsa) => {
5922-
Ok(ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5923-
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0)
5926+
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5927+
.map(|(sig, _)| sig)
59245928
}
59255929
}
59265930
}
@@ -5933,7 +5937,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59335937
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
59345938
/// If an Err is returned, it is a ChannelError::Close.
59355939
pub fn get_funding_created<L: Deref>(mut self, funding_transaction: Transaction, funding_txo: OutPoint, is_batch_funding: bool, logger: &L)
5936-
-> Result<(Channel<SP>, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger {
5940+
-> Result<(Channel<SP>, Option<msgs::FundingCreated>), (Self, ChannelError)> where L::Target: Logger {
59375941
if !self.context.is_outbound() {
59385942
panic!("Tried to create outbound funding_created message on an inbound channel!");
59395943
}
@@ -5949,15 +5953,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59495953
self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
59505954
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
59515955

5952-
let signature = match self.get_funding_created_signature(logger) {
5953-
Ok(res) => res,
5954-
Err(e) => {
5955-
log_error!(logger, "Got bad signatures: {:?}!", e);
5956-
self.context.channel_transaction_parameters.funding_outpoint = None;
5957-
return Err((self, e));
5958-
}
5959-
};
5960-
59615956
let temporary_channel_id = self.context.channel_id;
59625957

59635958
// Now that we're past error-generating stuff, update our local state:
@@ -5976,20 +5971,27 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
59765971
self.context.funding_transaction = Some(funding_transaction);
59775972
self.context.is_batch_funding = Some(()).filter(|_| is_batch_funding);
59785973

5974+
let funding_created = if let Ok(signature) = self.get_funding_created_signature(logger) {
5975+
Some(msgs::FundingCreated {
5976+
temporary_channel_id,
5977+
funding_txid: funding_txo.txid,
5978+
funding_output_index: funding_txo.index,
5979+
signature,
5980+
#[cfg(taproot)]
5981+
partial_signature_with_nonce: None,
5982+
#[cfg(taproot)]
5983+
next_local_nonce: None,
5984+
})
5985+
} else {
5986+
self.context.signer_pending_funding = true;
5987+
None
5988+
};
5989+
59795990
let channel = Channel {
59805991
context: self.context,
59815992
};
59825993

5983-
Ok((channel, msgs::FundingCreated {
5984-
temporary_channel_id,
5985-
funding_txid: funding_txo.txid,
5986-
funding_output_index: funding_txo.index,
5987-
signature,
5988-
#[cfg(taproot)]
5989-
partial_signature_with_nonce: None,
5990-
#[cfg(taproot)]
5991-
next_local_nonce: None,
5992-
}))
5994+
Ok((channel, funding_created))
59935995
}
59945996

59955997
fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
@@ -6482,6 +6484,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
64826484
monitor_pending_finalized_fulfills: Vec::new(),
64836485

64846486
signer_pending_commitment_update: false,
6487+
signer_pending_funding: false,
64856488

64866489
#[cfg(debug_assertions)]
64876490
holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
@@ -7575,6 +7578,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
75757578
monitor_pending_finalized_fulfills: monitor_pending_finalized_fulfills.unwrap(),
75767579

75777580
signer_pending_commitment_update: false,
7581+
signer_pending_funding: false,
75787582

75797583
pending_update_fee,
75807584
holding_cell_update_fee,
@@ -7847,7 +7851,7 @@ mod tests {
78477851
}]};
78487852
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
78497853
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
7850-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7854+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
78517855

78527856
// Node B --> Node A: funding signed
78537857
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -7974,7 +7978,7 @@ mod tests {
79747978
}]};
79757979
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
79767980
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
7977-
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7981+
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();
79787982

79797983
// Node B --> Node A: funding signed
79807984
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -8162,7 +8166,7 @@ mod tests {
81628166
}]};
81638167
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
81648168
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
8165-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
8169+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
81668170

81678171
// Node B --> Node A: funding signed
81688172
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -9222,7 +9226,7 @@ mod tests {
92229226
&&logger,
92239227
).map_err(|_| ()).unwrap();
92249228
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(
9225-
&funding_created_msg,
9229+
&funding_created_msg.unwrap(),
92269230
best_block,
92279231
&&keys_provider,
92289232
&&logger,

lightning/src/ln/channelmanager.rs

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

37393739
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
37403740
let peer_state = &mut *peer_state_lock;
3741-
let (chan, msg) = match peer_state.channel_by_id.remove(temporary_channel_id) {
3741+
let (chan, msg_opt) = match peer_state.channel_by_id.remove(temporary_channel_id) {
37423742
Some(ChannelPhase::UnfundedOutboundV1(chan)) => {
37433743
let funding_txo = find_funding_output(&chan, &funding_transaction)?;
37443744

@@ -3777,10 +3777,12 @@ where
37773777
}),
37783778
};
37793779

3780-
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3781-
node_id: chan.context.get_counterparty_node_id(),
3782-
msg,
3783-
});
3780+
if let Some(msg) = msg_opt {
3781+
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3782+
node_id: chan.context.get_counterparty_node_id(),
3783+
msg,
3784+
});
3785+
}
37843786
match peer_state.channel_by_id.entry(chan.context.channel_id()) {
37853787
hash_map::Entry::Occupied(_) => {
37863788
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
@@ -9044,7 +9044,7 @@ fn test_duplicate_chan_id() {
90449044
}
90459045
};
90469046
check_added_monitors!(nodes[0], 0);
9047-
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
9047+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created.unwrap());
90489048
// At this point we'll look up if the channel_id is present and immediately fail the channel
90499049
// without trying to persist the `ChannelMonitor`.
90509050
check_added_monitors!(nodes[1], 0);

0 commit comments

Comments
 (0)