Skip to content

Commit b8db8cd

Browse files
TheBlueMattwaterson
authored andcommitted
Handle retrying sign_counterparty_commitment failures
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). This commit adds initial retrying of failures, specifically regenerating commitment updates, attempting to re-sign the `CommitmentSigned` message, and sending it to our peers if we succed.
1 parent f051dff commit b8db8cd

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

lightning/src/ln/channel.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,13 @@ pub(super) struct MonitorRestoreUpdates {
515515
pub announcement_sigs: Option<msgs::AnnouncementSignatures>,
516516
}
517517

518+
/// The return value of `signer_maybe_unblocked`
519+
pub(super) struct SignerResumeUpdates {
520+
pub commitment_update: Option<msgs::CommitmentUpdate>,
521+
pub funding_signed: Option<msgs::FundingSigned>,
522+
pub funding_created: Option<msgs::FundingCreated>,
523+
}
524+
518525
/// The return value of `channel_reestablish`
519526
pub(super) struct ReestablishResponses {
520527
pub channel_ready: Option<msgs::ChannelReady>,
@@ -3816,6 +3823,21 @@ impl<SP: Deref> Channel<SP> where
38163823
Ok(())
38173824
}
38183825

3826+
/// Indicates that the signer may have some signatures for us, so we should retry if we're
3827+
/// blocked.
3828+
pub fn signer_maybe_unblocked<L: Deref>(&mut self, logger: &L) -> SignerResumeUpdates where L::Target: Logger {
3829+
let commitment_update = if self.context.signer_pending_commitment_update {
3830+
None
3831+
} else { None };
3832+
let funding_signed = None;
3833+
let funding_created = None;
3834+
SignerResumeUpdates {
3835+
commitment_update,
3836+
funding_signed,
3837+
funding_created,
3838+
}
3839+
}
3840+
38193841
fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK {
38203842
let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
38213843
let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.cur_holder_commitment_transaction_number + 2);

lightning/src/ln/channelmanager.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6605,6 +6605,58 @@ where
66056605
has_update
66066606
}
66076607

6608+
/// When a call to a [`ChannelSigner`] method returns an error, this indicates that the signer
6609+
/// is (temporarily) unavailable, and the operation should be retried later.
6610+
///
6611+
/// This method allows for that retry - either checking for any signer-pending messages to be
6612+
/// attempted in every channel, or in the specifically provided channel.
6613+
#[cfg(test)] // This is only implemented for one signer method, and should be private until we
6614+
// actually finish implementing it fully.
6615+
pub fn signer_unblocked(&self, channel_opt: Option<(PublicKey, ChannelId)>) {
6616+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
6617+
6618+
let unblock_chan = |chan: &mut Channel<SP>, pending_msg_events: &mut Vec<MessageSendEvent>| {
6619+
let msgs = chan.signer_maybe_unblocked(&self.logger);
6620+
if let Some(updates) = msgs.commitment_update {
6621+
pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
6622+
node_id: chan.context.get_counterparty_node_id(),
6623+
updates,
6624+
});
6625+
}
6626+
if let Some(msg) = msgs.funding_signed {
6627+
pending_msg_events.push(events::MessageSendEvent::SendFundingSigned {
6628+
node_id: chan.context.get_counterparty_node_id(),
6629+
msg,
6630+
});
6631+
}
6632+
if let Some(msg) = msgs.funding_created {
6633+
pending_msg_events.push(events::MessageSendEvent::SendFundingCreated {
6634+
node_id: chan.context.get_counterparty_node_id(),
6635+
msg,
6636+
});
6637+
}
6638+
};
6639+
6640+
let per_peer_state = self.per_peer_state.read().unwrap();
6641+
if let Some((counterparty_node_id, channel_id)) = channel_opt {
6642+
if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) {
6643+
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
6644+
let peer_state = &mut *peer_state_lock;
6645+
if let Some(chan) = peer_state.channel_by_id.get_mut(&channel_id) {
6646+
unblock_chan(chan, &mut peer_state.pending_msg_events);
6647+
}
6648+
}
6649+
} else {
6650+
for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
6651+
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
6652+
let peer_state = &mut *peer_state_lock;
6653+
for (_, chan) in peer_state.channel_by_id.iter_mut() {
6654+
unblock_chan(chan, &mut peer_state.pending_msg_events);
6655+
}
6656+
}
6657+
}
6658+
}
6659+
66086660
/// Check whether any channels have finished removing all pending updates after a shutdown
66096661
/// exchange and can now send a closing_signed.
66106662
/// Returns whether any closing_signed messages were generated.

0 commit comments

Comments
 (0)