Skip to content

Commit ca97a2a

Browse files
committed
Send initial closing_signed message asynchronously and handle errs
When we added the support for external signing, many of the signing functions were allowed to return an error, closing the channel in such a case. `sign_closing_transaction` is one such function which can now return an error, except instead of handling it properly we'd simply never send a `closing_signed` message, hanging the channel until users intervene and force-close it. Piping the channel-closing error back through the various callsites (several of which already have pending results by the time they call `maybe_propose_first_closing_signed`) may be rather complicated, so instead we simply attempt to propose the initial `closing_signed` in `get_and_clear_pending_msg_events` like we do for holding-cell freeing. This simplifies a few function interfaces and has no impact on behavior, aside from a few message-ordering edge-cases, as seen in the two small test changes required.
1 parent 6f4d395 commit ca97a2a

File tree

4 files changed

+106
-73
lines changed

4 files changed

+106
-73
lines changed

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ fn test_monitor_and_persister_update_fail() {
141141
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
142142
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
143143
if let Some(ref mut channel) = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2) {
144-
if let Ok((_, _, _, update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].fee_estimator, &node_cfgs[0].logger) {
144+
if let Ok((_, _, update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
145145
// Check that even though the persister is returning a TemporaryFailure,
146146
// because the update is bogus, ultimately the error that's returned
147147
// should be a PermanentFailure.

lightning/src/ln/channel.rs

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,9 +2169,8 @@ impl<Signer: Sign> Channel<Signer> {
21692169
Ok(())
21702170
}
21712171

2172-
pub fn commitment_signed<F: Deref, L: Deref>(&mut self, msg: &msgs::CommitmentSigned, fee_estimator: &F, logger: &L) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>, Option<msgs::ClosingSigned>, ChannelMonitorUpdate), (Option<ChannelMonitorUpdate>, ChannelError)>
2173-
where F::Target: FeeEstimator,
2174-
L::Target: Logger
2172+
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>, ChannelMonitorUpdate), (Option<ChannelMonitorUpdate>, ChannelError)>
2173+
where L::Target: Logger
21752174
{
21762175
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
21772176
return Err((None, ChannelError::Close("Got commitment signed message when channel was not in an operational state".to_owned())));
@@ -2346,12 +2345,10 @@ impl<Signer: Sign> Channel<Signer> {
23462345
}
23472346
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
23482347
log_bytes!(self.channel_id));
2349-
// TODO: Call maybe_propose_first_closing_signed on restoration (or call it here and
2350-
// re-send the message on restoration)
23512348
return Err((Some(monitor_update), ChannelError::Ignore("Previous monitor update failure prevented generation of RAA".to_owned())));
23522349
}
23532350

2354-
let (commitment_signed, closing_signed) = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
2351+
let commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
23552352
// If we're AwaitingRemoteRevoke we can't send a new commitment here, but that's ok -
23562353
// we'll send one right away when we get the revoke_and_ack when we
23572354
// free_holding_cell_htlcs().
@@ -2360,10 +2357,8 @@ impl<Signer: Sign> Channel<Signer> {
23602357
// strictly increasing by one, so decrement it here.
23612358
self.latest_monitor_update_id = monitor_update.update_id;
23622359
monitor_update.updates.append(&mut additional_update.updates);
2363-
(Some(msg), None)
2364-
} else if !need_commitment {
2365-
(None, self.maybe_propose_first_closing_signed(fee_estimator))
2366-
} else { (None, None) };
2360+
Some(msg)
2361+
} else { None };
23672362

23682363
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
23692364
log_bytes!(self.channel_id()), if commitment_signed.is_some() { " our own commitment_signed and" } else { "" });
@@ -2372,7 +2367,7 @@ impl<Signer: Sign> Channel<Signer> {
23722367
channel_id: self.channel_id,
23732368
per_commitment_secret,
23742369
next_per_commitment_point,
2375-
}, commitment_signed, closing_signed, monitor_update))
2370+
}, commitment_signed, monitor_update))
23762371
}
23772372

23782373
/// Public version of the below, checking relevant preconditions first.
@@ -2504,9 +2499,8 @@ impl<Signer: Sign> Channel<Signer> {
25042499
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
25052500
/// generating an appropriate error *after* the channel state has been updated based on the
25062501
/// revoke_and_ack message.
2507-
pub fn revoke_and_ack<F: Deref, L: Deref>(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &F, logger: &L) -> Result<(Option<msgs::CommitmentUpdate>, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, Option<msgs::ClosingSigned>, ChannelMonitorUpdate, Vec<(HTLCSource, PaymentHash)>), ChannelError>
2508-
where F::Target: FeeEstimator,
2509-
L::Target: Logger,
2502+
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Option<msgs::CommitmentUpdate>, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, ChannelMonitorUpdate, Vec<(HTLCSource, PaymentHash)>), ChannelError>
2503+
where L::Target: Logger,
25102504
{
25112505
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
25122506
return Err(ChannelError::Close("Got revoke/ACK message when channel was not in an operational state".to_owned()));
@@ -2686,7 +2680,7 @@ impl<Signer: Sign> Channel<Signer> {
26862680
self.monitor_pending_forwards.append(&mut to_forward_infos);
26872681
self.monitor_pending_failures.append(&mut revoked_htlcs);
26882682
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
2689-
return Ok((None, Vec::new(), Vec::new(), None, monitor_update, Vec::new()))
2683+
return Ok((None, Vec::new(), Vec::new(), monitor_update, Vec::new()))
26902684
}
26912685

26922686
match self.free_holding_cell_htlcs(logger)? {
@@ -2705,7 +2699,7 @@ impl<Signer: Sign> Channel<Signer> {
27052699
self.latest_monitor_update_id = monitor_update.update_id;
27062700
monitor_update.updates.append(&mut additional_update.updates);
27072701

2708-
Ok((Some(commitment_update), to_forward_infos, revoked_htlcs, None, monitor_update, htlcs_to_fail))
2702+
Ok((Some(commitment_update), to_forward_infos, revoked_htlcs, monitor_update, htlcs_to_fail))
27092703
},
27102704
(None, htlcs_to_fail) => {
27112705
if require_commitment {
@@ -2725,14 +2719,13 @@ impl<Signer: Sign> Channel<Signer> {
27252719
update_fail_malformed_htlcs,
27262720
update_fee: None,
27272721
commitment_signed
2728-
}), to_forward_infos, revoked_htlcs, None, monitor_update, htlcs_to_fail))
2722+
}), to_forward_infos, revoked_htlcs, monitor_update, htlcs_to_fail))
27292723
} else {
27302724
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
2731-
Ok((None, to_forward_infos, revoked_htlcs, self.maybe_propose_first_closing_signed(fee_estimator), monitor_update, htlcs_to_fail))
2725+
Ok((None, to_forward_infos, revoked_htlcs, monitor_update, htlcs_to_fail))
27322726
}
27332727
}
27342728
}
2735-
27362729
}
27372730

27382731
/// Adds a pending update to this channel. See the doc for send_htlc for
@@ -3119,13 +3112,17 @@ impl<Signer: Sign> Channel<Signer> {
31193112
}
31203113
}
31213114

3122-
fn maybe_propose_first_closing_signed<F: Deref>(&mut self, fee_estimator: &F) -> Option<msgs::ClosingSigned>
3123-
where F::Target: FeeEstimator
3115+
pub fn maybe_propose_first_closing_signed<F: Deref, L: Deref>(&mut self, fee_estimator: &F, logger: &L)
3116+
-> Result<Option<msgs::ClosingSigned>, ChannelError>
3117+
where F::Target: FeeEstimator, L::Target: Logger
31243118
{
31253119
if !self.is_outbound() || !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() ||
3126-
self.channel_state & (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::AwaitingRemoteRevoke as u32) != BOTH_SIDES_SHUTDOWN_MASK ||
3120+
self.channel_state &
3121+
(BOTH_SIDES_SHUTDOWN_MASK | ChannelState::AwaitingRemoteRevoke as u32 |
3122+
ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateFailed as u32)
3123+
!= BOTH_SIDES_SHUTDOWN_MASK ||
31273124
self.last_sent_closing_fee.is_some() || self.pending_update_fee.is_some() {
3128-
return None;
3125+
return Ok(None);
31293126
}
31303127

31313128
let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
@@ -3134,26 +3131,24 @@ impl<Signer: Sign> Channel<Signer> {
31343131
}
31353132
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
31363133
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
3134+
log_trace!(logger, "Proposing initial closing signed for our counterparty with a feerate of {} sat/kWeight (= {} sats)",
3135+
proposed_feerate, proposed_total_fee_satoshis);
31373136

31383137
let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false);
31393138
let sig = self.holder_signer
31403139
.sign_closing_transaction(&closing_tx, &self.secp_ctx)
3141-
.ok();
3142-
assert!(closing_tx.get_weight() as u64 <= tx_weight);
3143-
if sig.is_none() { return None; }
3140+
.map_err(|()| ChannelError::Close("Failed to get signature for closing transaction.".to_owned()))?;
31443141

3145-
self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis, sig.clone().unwrap()));
3146-
Some(msgs::ClosingSigned {
3142+
self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis, sig.clone()));
3143+
Ok(Some(msgs::ClosingSigned {
31473144
channel_id: self.channel_id,
31483145
fee_satoshis: total_fee_satoshis,
3149-
signature: sig.unwrap(),
3146+
signature: sig,
31503147
fee_range: None,
3151-
})
3148+
}))
31523149
}
31533150

3154-
pub fn shutdown<F: Deref>(&mut self, fee_estimator: &F, their_features: &InitFeatures, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
3155-
where F::Target: FeeEstimator
3156-
{
3151+
pub fn shutdown(&mut self, their_features: &InitFeatures, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Vec<(HTLCSource, PaymentHash)>), ChannelError> {
31573152
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
31583153
return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish".to_owned()));
31593154
}
@@ -3217,7 +3212,7 @@ impl<Signer: Sign> Channel<Signer> {
32173212
self.channel_state |= ChannelState::LocalShutdownSent as u32;
32183213
self.update_time_counter += 1;
32193214

3220-
Ok((shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs))
3215+
Ok((shutdown, dropped_outbound_htlcs))
32213216
}
32223217

32233218
fn build_signed_closing_transaction(&self, tx: &mut Transaction, counterparty_sig: &Signature, sig: &Signature) {

lightning/src/ln/channelmanager.rs

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3058,19 +3058,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30583058
log_bytes!(msg.channel_id),
30593059
if chan_entry.get().we_want_shutdown() { " after we initiated shutdown" } else { "" });
30603060
}
3061-
let (shutdown, closing_signed, dropped_htlcs) = try_chan_entry!(self, chan_entry.get_mut().shutdown(&self.fee_estimator, &their_features, &msg), channel_state, chan_entry);
3061+
let (shutdown, dropped_htlcs) = try_chan_entry!(self, chan_entry.get_mut().shutdown(&their_features, &msg), channel_state, chan_entry);
30623062
if let Some(msg) = shutdown {
30633063
channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
30643064
node_id: counterparty_node_id.clone(),
30653065
msg,
30663066
});
30673067
}
3068-
if let Some(msg) = closing_signed {
3069-
channel_state.pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
3070-
node_id: counterparty_node_id.clone(),
3071-
msg,
3072-
});
3073-
}
30743068
if chan_entry.get().is_shutdown() {
30753069
if let Some(short_id) = chan_entry.get().get_short_channel_id() {
30763070
channel_state.short_to_id.remove(&short_id);
@@ -3266,8 +3260,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32663260
if chan.get().get_counterparty_node_id() != *counterparty_node_id {
32673261
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
32683262
}
3269-
let (revoke_and_ack, commitment_signed, closing_signed, monitor_update) =
3270-
match chan.get_mut().commitment_signed(&msg, &self.fee_estimator, &self.logger) {
3263+
let (revoke_and_ack, commitment_signed, monitor_update) =
3264+
match chan.get_mut().commitment_signed(&msg, &self.logger) {
32713265
Err((None, e)) => try_chan_entry!(self, Err(e), channel_state, chan),
32723266
Err((Some(update), e)) => {
32733267
assert!(chan.get().is_awaiting_monitor_update());
@@ -3279,7 +3273,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32793273
};
32803274
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
32813275
return_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, true, commitment_signed.is_some());
3282-
//TODO: Rebroadcast closing_signed if present on monitor update restoration
32833276
}
32843277
channel_state.pending_msg_events.push(events::MessageSendEvent::SendRevokeAndACK {
32853278
node_id: counterparty_node_id.clone(),
@@ -3298,12 +3291,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32983291
},
32993292
});
33003293
}
3301-
if let Some(msg) = closing_signed {
3302-
channel_state.pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
3303-
node_id: counterparty_node_id.clone(),
3304-
msg,
3305-
});
3306-
}
33073294
Ok(())
33083295
},
33093296
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
@@ -3358,12 +3345,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33583345
break Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
33593346
}
33603347
let was_frozen_for_monitor = chan.get().is_awaiting_monitor_update();
3361-
let (commitment_update, pending_forwards, pending_failures, closing_signed, monitor_update, htlcs_to_fail_in) =
3362-
break_chan_entry!(self, chan.get_mut().revoke_and_ack(&msg, &self.fee_estimator, &self.logger), channel_state, chan);
3348+
let (commitment_update, pending_forwards, pending_failures, monitor_update, htlcs_to_fail_in) =
3349+
break_chan_entry!(self, chan.get_mut().revoke_and_ack(&msg, &self.logger), channel_state, chan);
33633350
htlcs_to_fail = htlcs_to_fail_in;
33643351
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
33653352
if was_frozen_for_monitor {
3366-
assert!(commitment_update.is_none() && closing_signed.is_none() && pending_forwards.is_empty() && pending_failures.is_empty());
3353+
assert!(commitment_update.is_none() && pending_forwards.is_empty() && pending_failures.is_empty());
33673354
break Err(MsgHandleErrInternal::ignore_no_close("Previous monitor update failure prevented responses to RAA".to_owned()));
33683355
} else {
33693356
if let Err(e) = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, commitment_update.is_some(), pending_forwards, pending_failures) {
@@ -3377,12 +3364,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33773364
updates,
33783365
});
33793366
}
3380-
if let Some(msg) = closing_signed {
3381-
channel_state.pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
3382-
node_id: counterparty_node_id.clone(),
3383-
msg,
3384-
});
3385-
}
33863367
break Ok((pending_forwards, pending_failures, chan.get().get_short_channel_id().expect("RAA should only work on a short-id-available channel"), chan.get().get_funding_txo().unwrap()))
33873368
},
33883369
hash_map::Entry::Vacant(_) => break Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
@@ -3682,7 +3663,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
36823663
});
36833664
}
36843665

3685-
let has_update = has_monitor_update || !failed_htlcs.is_empty();
3666+
let has_update = has_monitor_update || !failed_htlcs.is_empty() || !handle_errors.is_empty();
36863667
for (failures, channel_id) in failed_htlcs.drain(..) {
36873668
self.fail_holding_cell_htlcs(failures, channel_id);
36883669
}
@@ -3694,6 +3675,46 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
36943675
has_update
36953676
}
36963677

3678+
/// Check whether any channels have finished removing all pending updates after a shutdown
3679+
/// exchange and can now send a closing_signed.
3680+
/// Returns whether any closing_signed messages were generated.
3681+
fn maybe_generate_initial_closing_signed(&self) -> bool {
3682+
let mut handle_errors: Vec<(PublicKey, Result<(), _>)> = Vec::new();
3683+
let mut has_update = false;
3684+
{
3685+
let mut channel_state_lock = self.channel_state.lock().unwrap();
3686+
let channel_state = &mut *channel_state_lock;
3687+
let by_id = &mut channel_state.by_id;
3688+
let short_to_id = &mut channel_state.short_to_id;
3689+
let pending_msg_events = &mut channel_state.pending_msg_events;
3690+
3691+
by_id.retain(|channel_id, chan| {
3692+
match chan.maybe_propose_first_closing_signed(&self.fee_estimator, &self.logger) {
3693+
Ok(Some(msg)) => {
3694+
pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
3695+
node_id: chan.get_counterparty_node_id(), msg,
3696+
});
3697+
has_update = true;
3698+
true
3699+
},
3700+
Ok(None) => true,
3701+
Err(e) => {
3702+
has_update = true;
3703+
let (close_channel, res) = convert_chan_err!(self, e, short_to_id, chan, channel_id);
3704+
handle_errors.push((chan.get_counterparty_node_id(), Err(res)));
3705+
!close_channel
3706+
}
3707+
}
3708+
});
3709+
}
3710+
3711+
for (counterparty_node_id, err) in handle_errors.drain(..) {
3712+
let _ = handle_error!(self, err, counterparty_node_id);
3713+
}
3714+
3715+
has_update
3716+
}
3717+
36973718
/// Handle a list of channel failures during a block_connected or block_disconnected call,
36983719
/// pushing the channel monitor update (if any) to the background events queue and removing the
36993720
/// Channel object.
@@ -3847,6 +3868,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> MessageSend
38473868
if self.check_free_holding_cells() {
38483869
result = NotifyOption::DoPersist;
38493870
}
3871+
if self.maybe_generate_initial_closing_signed() {
3872+
result = NotifyOption::DoPersist;
3873+
}
38503874

38513875
let mut pending_events = Vec::new();
38523876
let mut channel_state = self.channel_state.lock().unwrap();

0 commit comments

Comments
 (0)