Skip to content

Commit 91760b2

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 18a8e6b commit 91760b2

File tree

3 files changed

+39
-33
lines changed

3 files changed

+39
-33
lines changed

lightning/src/ln/channel.rs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,10 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
736736
/// This flag is set in such a case. Note that we don't need to persist this as we'll end up
737737
/// setting it again as a side-effect of [`Channel::channel_reestablish`].
738738
signer_pending_commitment_update: bool,
739+
/// Similar to [`Self::signer_pending_commitment_update`] but we're waiting to send either a
740+
/// [`msgs::FundingCreated`] or [`msgs::FundingSigned`] depending on if this channel is
741+
/// outbound or inbound.
742+
signer_pending_funding: bool,
739743

740744
// pending_update_fee is filled when sending and receiving update_fee.
741745
//
@@ -5746,6 +5750,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
57465750
monitor_pending_finalized_fulfills: Vec::new(),
57475751

57485752
signer_pending_commitment_update: false,
5753+
signer_pending_funding: false,
57495754

57505755
#[cfg(debug_assertions)]
57515756
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
@@ -5826,15 +5831,14 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
58265831
})
58275832
}
58285833

5829-
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
5830-
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
5834+
fn get_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ()> where L::Target: Logger {
58315835
let counterparty_keys = self.context.build_remote_transaction_keys();
58325836
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
58335837
match &self.context.holder_signer {
58345838
// TODO (taproot|arik): move match into calling method for Taproot
58355839
ChannelSignerType::Ecdsa(ecdsa) => {
5836-
Ok(ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5837-
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0)
5840+
ecdsa.sign_counterparty_commitment(&counterparty_initial_commitment_tx, Vec::new(), &self.context.secp_ctx)
5841+
.map(|(sig, _)| sig)
58385842
}
58395843
}
58405844
}
@@ -5847,7 +5851,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
58475851
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
58485852
/// If an Err is returned, it is a ChannelError::Close.
58495853
pub fn get_funding_created<L: Deref>(mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L)
5850-
-> Result<(Channel<SP>, msgs::FundingCreated), (Self, ChannelError)> where L::Target: Logger {
5854+
-> Result<(Channel<SP>, Option<msgs::FundingCreated>), (Self, ChannelError)> where L::Target: Logger {
58515855
if !self.context.is_outbound() {
58525856
panic!("Tried to create outbound funding_created message on an inbound channel!");
58535857
}
@@ -5863,15 +5867,6 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
58635867
self.context.channel_transaction_parameters.funding_outpoint = Some(funding_txo);
58645868
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
58655869

5866-
let signature = match self.get_funding_created_signature(logger) {
5867-
Ok(res) => res,
5868-
Err(e) => {
5869-
log_error!(logger, "Got bad signatures: {:?}!", e);
5870-
self.context.channel_transaction_parameters.funding_outpoint = None;
5871-
return Err((self, e));
5872-
}
5873-
};
5874-
58755870
let temporary_channel_id = self.context.channel_id;
58765871

58775872
// Now that we're past error-generating stuff, update our local state:
@@ -5889,20 +5884,27 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
58895884

58905885
self.context.funding_transaction = Some(funding_transaction);
58915886

5887+
let funding_created = if let Ok(signature) = self.get_funding_created_signature(logger) {
5888+
Some(msgs::FundingCreated {
5889+
temporary_channel_id,
5890+
funding_txid: funding_txo.txid,
5891+
funding_output_index: funding_txo.index,
5892+
signature,
5893+
#[cfg(taproot)]
5894+
partial_signature_with_nonce: None,
5895+
#[cfg(taproot)]
5896+
next_local_nonce: None,
5897+
})
5898+
} else {
5899+
self.context.signer_pending_funding = true;
5900+
None
5901+
};
5902+
58925903
let channel = Channel {
58935904
context: self.context,
58945905
};
58955906

5896-
Ok((channel, msgs::FundingCreated {
5897-
temporary_channel_id,
5898-
funding_txid: funding_txo.txid,
5899-
funding_output_index: funding_txo.index,
5900-
signature,
5901-
#[cfg(taproot)]
5902-
partial_signature_with_nonce: None,
5903-
#[cfg(taproot)]
5904-
next_local_nonce: None,
5905-
}))
5907+
Ok((channel, funding_created))
59065908
}
59075909

59085910
fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures) -> ChannelTypeFeatures {
@@ -6395,6 +6397,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
63956397
monitor_pending_finalized_fulfills: Vec::new(),
63966398

63976399
signer_pending_commitment_update: false,
6400+
signer_pending_funding: false,
63986401

63996402
#[cfg(debug_assertions)]
64006403
holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
@@ -7483,6 +7486,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
74837486
monitor_pending_finalized_fulfills: monitor_pending_finalized_fulfills.unwrap(),
74847487

74857488
signer_pending_commitment_update: false,
7489+
signer_pending_funding: false,
74867490

74877491
pending_update_fee,
74887492
holding_cell_update_fee,
@@ -7754,7 +7758,7 @@ mod tests {
77547758
}]};
77557759
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
77567760
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
7757-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7761+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
77587762

77597763
// Node B --> Node A: funding signed
77607764
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -7881,7 +7885,7 @@ mod tests {
78817885
}]};
78827886
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
78837887
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
7884-
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
7888+
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();
78857889

78867890
// Node B --> Node A: funding signed
78877891
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();
@@ -8069,7 +8073,7 @@ mod tests {
80698073
}]};
80708074
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
80718075
let (mut node_a_chan, funding_created_msg) = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, &&logger).map_err(|_| ()).unwrap();
8072-
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
8076+
let (_, funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg.unwrap(), best_block, &&keys_provider, &&logger).map_err(|_| ()).unwrap();
80738077

80748078
// Node B --> Node A: funding signed
80758079
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&keys_provider, &&logger).unwrap();

lightning/src/ln/channelmanager.rs

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

34893489
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
34903490
let peer_state = &mut *peer_state_lock;
3491-
let (chan, msg) = match peer_state.channel_by_id.remove(temporary_channel_id) {
3491+
let (chan, msg_opt) = match peer_state.channel_by_id.remove(temporary_channel_id) {
34923492
Some(ChannelPhase::UnfundedOutboundV1(chan)) => {
34933493
let funding_txo = find_funding_output(&chan, &funding_transaction)?;
34943494

@@ -3527,10 +3527,12 @@ where
35273527
}),
35283528
};
35293529

3530-
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3531-
node_id: chan.context.get_counterparty_node_id(),
3532-
msg,
3533-
});
3530+
if let Some(msg) = msg_opt {
3531+
peer_state.pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
3532+
node_id: chan.context.get_counterparty_node_id(),
3533+
msg,
3534+
});
3535+
}
35343536
match peer_state.channel_by_id.entry(chan.context.channel_id()) {
35353537
hash_map::Entry::Occupied(_) => {
35363538
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
@@ -8970,7 +8970,7 @@ fn test_duplicate_chan_id() {
89708970
}
89718971
};
89728972
check_added_monitors!(nodes[0], 0);
8973-
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
8973+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created.unwrap());
89748974
// At this point we'll look up if the channel_id is present and immediately fail the channel
89758975
// without trying to persist the `ChannelMonitor`.
89768976
check_added_monitors!(nodes[1], 0);

0 commit comments

Comments
 (0)