Skip to content

Commit 9c2ee48

Browse files
committed
Refactor ShutdownResult type and construction
1 parent ba2980e commit 9c2ee48

File tree

2 files changed

+74
-56
lines changed

2 files changed

+74
-56
lines changed

lightning/src/ln/channel.rs

+51-27
Original file line numberDiff line numberDiff line change
@@ -540,18 +540,16 @@ pub(super) struct ReestablishResponses {
540540
pub shutdown_msg: Option<msgs::Shutdown>,
541541
}
542542

543-
/// The return type of `force_shutdown`
544-
///
545-
/// Contains a tuple with the following:
546-
/// - An optional (counterparty_node_id, funding_txo, [`ChannelMonitorUpdate`]) tuple
547-
/// - A list of HTLCs to fail back in the form of the (source, payment hash, and this channel's
548-
/// counterparty_node_id and channel_id).
549-
/// - An optional transaction id identifying a corresponding batch funding transaction.
550-
pub(crate) type ShutdownResult = (
551-
Option<(PublicKey, OutPoint, ChannelMonitorUpdate)>,
552-
Vec<(HTLCSource, PaymentHash, PublicKey, ChannelId)>,
553-
Option<Txid>
554-
);
543+
/// The result of a shutdown that should be handled.
544+
pub(crate) struct ShutdownResult {
545+
/// A channel monitor update to apply.
546+
pub(crate) monitor_update: Option<(PublicKey, OutPoint, ChannelMonitorUpdate)>,
547+
/// A list of dropped outbound HTLCs that can safely be failed backwards immediately.
548+
pub(crate) dropped_outbound_htlcs: Vec<(HTLCSource, PaymentHash, PublicKey, ChannelId)>,
549+
/// An unbroadcasted batch funding transaction id. The closure of this channel should be
550+
/// propagated to the remainder of the batch.
551+
pub(crate) unbroadcasted_batch_funding_txid: Option<Txid>,
552+
}
555553

556554
/// If the majority of the channels funds are to the fundee and the initiator holds only just
557555
/// enough funds to cover their reserve value, channels are at risk of getting "stuck". Because the
@@ -2052,7 +2050,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
20522050

20532051
self.channel_state = ChannelState::ShutdownComplete as u32;
20542052
self.update_time_counter += 1;
2055-
(monitor_update, dropped_outbound_htlcs, unbroadcasted_batch_funding_txid)
2053+
ShutdownResult {
2054+
monitor_update,
2055+
dropped_outbound_htlcs,
2056+
unbroadcasted_batch_funding_txid,
2057+
}
20562058
}
20572059
}
20582060

@@ -4207,18 +4209,18 @@ impl<SP: Deref> Channel<SP> where
42074209

42084210
pub fn maybe_propose_closing_signed<F: Deref, L: Deref>(
42094211
&mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L)
4210-
-> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError>
4212+
-> Result<(Option<msgs::ClosingSigned>, Option<Transaction>, Option<ShutdownResult>), ChannelError>
42114213
where F::Target: FeeEstimator, L::Target: Logger
42124214
{
42134215
if self.context.last_sent_closing_fee.is_some() || !self.closing_negotiation_ready() {
4214-
return Ok((None, None));
4216+
return Ok((None, None, None));
42154217
}
42164218

42174219
if !self.context.is_outbound() {
42184220
if let Some(msg) = &self.context.pending_counterparty_closing_signed.take() {
42194221
return self.closing_signed(fee_estimator, &msg);
42204222
}
4221-
return Ok((None, None));
4223+
return Ok((None, None, None));
42224224
}
42234225

42244226
let (our_min_fee, our_max_fee) = self.calculate_closing_fee_limits(fee_estimator);
@@ -4243,7 +4245,7 @@ impl<SP: Deref> Channel<SP> where
42434245
min_fee_satoshis: our_min_fee,
42444246
max_fee_satoshis: our_max_fee,
42454247
}),
4246-
}), None))
4248+
}), None, None))
42474249
}
42484250
}
42494251
}
@@ -4392,7 +4394,7 @@ impl<SP: Deref> Channel<SP> where
43924394

43934395
pub fn closing_signed<F: Deref>(
43944396
&mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, msg: &msgs::ClosingSigned)
4395-
-> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError>
4397+
-> Result<(Option<msgs::ClosingSigned>, Option<Transaction>, Option<ShutdownResult>), ChannelError>
43964398
where F::Target: FeeEstimator
43974399
{
43984400
if self.context.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
@@ -4414,7 +4416,7 @@ impl<SP: Deref> Channel<SP> where
44144416

44154417
if self.context.channel_state & ChannelState::MonitorUpdateInProgress as u32 != 0 {
44164418
self.context.pending_counterparty_closing_signed = Some(msg.clone());
4417-
return Ok((None, None));
4419+
return Ok((None, None, None));
44184420
}
44194421

44204422
let funding_redeemscript = self.context.get_funding_redeemscript();
@@ -4444,10 +4446,15 @@ impl<SP: Deref> Channel<SP> where
44444446
assert!(self.context.shutdown_scriptpubkey.is_some());
44454447
if let Some((last_fee, sig)) = self.context.last_sent_closing_fee {
44464448
if last_fee == msg.fee_satoshis {
4449+
let shutdown_result = ShutdownResult {
4450+
monitor_update: None,
4451+
dropped_outbound_htlcs: Vec::new(),
4452+
unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(),
4453+
};
44474454
let tx = self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig);
44484455
self.context.channel_state = ChannelState::ShutdownComplete as u32;
44494456
self.context.update_time_counter += 1;
4450-
return Ok((None, Some(tx)));
4457+
return Ok((None, Some(tx), Some(shutdown_result)));
44514458
}
44524459
}
44534460

@@ -4466,13 +4473,22 @@ impl<SP: Deref> Channel<SP> where
44664473
let sig = ecdsa
44674474
.sign_closing_transaction(&closing_tx, &self.context.secp_ctx)
44684475
.map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?;
4469-
4470-
let signed_tx = if $new_fee == msg.fee_satoshis {
4476+
let signed_tx;
4477+
let shutdown_result;
4478+
if $new_fee == msg.fee_satoshis {
4479+
shutdown_result = Some(ShutdownResult {
4480+
monitor_update: None,
4481+
dropped_outbound_htlcs: Vec::new(),
4482+
unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(),
4483+
});
44714484
self.context.channel_state = ChannelState::ShutdownComplete as u32;
44724485
self.context.update_time_counter += 1;
44734486
let tx = self.build_signed_closing_transaction(&closing_tx, &msg.signature, &sig);
4474-
Some(tx)
4475-
} else { None };
4487+
signed_tx = Some(tx);
4488+
} else {
4489+
shutdown_result = None;
4490+
signed_tx = None;
4491+
};
44764492

44774493
self.context.last_sent_closing_fee = Some((used_fee, sig.clone()));
44784494
Ok((Some(msgs::ClosingSigned {
@@ -4483,7 +4499,7 @@ impl<SP: Deref> Channel<SP> where
44834499
min_fee_satoshis: our_min_fee,
44844500
max_fee_satoshis: our_max_fee,
44854501
}),
4486-
}), signed_tx))
4502+
}), signed_tx, shutdown_result))
44874503
}
44884504
}
44894505
}
@@ -5557,7 +5573,7 @@ impl<SP: Deref> Channel<SP> where
55575573
/// [`ChannelMonitorUpdate`] will be returned).
55585574
pub fn get_shutdown(&mut self, signer_provider: &SP, their_features: &InitFeatures,
55595575
target_feerate_sats_per_kw: Option<u32>, override_shutdown_script: Option<ShutdownScript>)
5560-
-> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>), APIError>
5576+
-> Result<(msgs::Shutdown, Option<ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>, Option<ShutdownResult>), APIError>
55615577
{
55625578
for htlc in self.context.pending_outbound_htlcs.iter() {
55635579
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
@@ -5611,11 +5627,19 @@ impl<SP: Deref> Channel<SP> where
56115627
};
56125628

56135629
// From here on out, we may not fail!
5630+
let shutdown_result;
5631+
let unbroadcasted_batch_funding_txid = self.context.unbroadcasted_batch_funding_txid();
56145632
self.context.target_closing_feerate_sats_per_kw = target_feerate_sats_per_kw;
56155633
if self.context.channel_state & !STATE_FLAGS < ChannelState::FundingSent as u32 {
56165634
self.context.channel_state = ChannelState::ShutdownComplete as u32;
5635+
shutdown_result = Some(ShutdownResult {
5636+
monitor_update: None,
5637+
dropped_outbound_htlcs: Vec::new(),
5638+
unbroadcasted_batch_funding_txid,
5639+
});
56175640
} else {
56185641
self.context.channel_state |= ChannelState::LocalShutdownSent as u32;
5642+
shutdown_result = None;
56195643
}
56205644
self.context.update_time_counter += 1;
56215645

@@ -5652,7 +5676,7 @@ impl<SP: Deref> Channel<SP> where
56525676
debug_assert!(!self.is_shutdown() || monitor_update.is_none(),
56535677
"we can't both complete shutdown and return a monitor update");
56545678

5655-
Ok((shutdown, monitor_update, dropped_outbound_htlcs))
5679+
Ok((shutdown, monitor_update, dropped_outbound_htlcs, shutdown_result))
56565680
}
56575681

56585682
pub fn inflight_htlc_sources(&self) -> impl Iterator<Item=(&HTLCSource, &PaymentHash)> {

lightning/src/ln/channelmanager.rs

+23-29
Original file line numberDiff line numberDiff line change
@@ -2548,7 +2548,7 @@ where
25482548
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
25492549

25502550
let mut failed_htlcs: Vec<(HTLCSource, PaymentHash)>;
2551-
let mut shutdown_result = None;
2551+
let shutdown_result;
25522552
loop {
25532553
let per_peer_state = self.per_peer_state.read().unwrap();
25542554

@@ -2563,10 +2563,10 @@ where
25632563
if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
25642564
let funding_txo_opt = chan.context.get_funding_txo();
25652565
let their_features = &peer_state.latest_features;
2566-
let unbroadcasted_batch_funding_txid = chan.context.unbroadcasted_batch_funding_txid();
2567-
let (shutdown_msg, mut monitor_update_opt, htlcs) =
2566+
let (shutdown_msg, mut monitor_update_opt, htlcs, local_shutdown_result) =
25682567
chan.get_shutdown(&self.signer_provider, their_features, target_feerate_sats_per_1000_weight, override_shutdown_script)?;
25692568
failed_htlcs = htlcs;
2569+
shutdown_result = local_shutdown_result;
25702570

25712571
// We can send the `shutdown` message before updating the `ChannelMonitor`
25722572
// here as we don't need the monitor update to complete until we send a
@@ -2594,7 +2594,6 @@ where
25942594
});
25952595
}
25962596
self.issue_channel_close_events(&chan.context, ClosureReason::HolderForceClosed);
2597-
shutdown_result = Some((None, Vec::new(), unbroadcasted_batch_funding_txid));
25982597
}
25992598
}
26002599
break;
@@ -2684,30 +2683,29 @@ where
26842683
self.close_channel_internal(channel_id, counterparty_node_id, target_feerate_sats_per_1000_weight, shutdown_script)
26852684
}
26862685

2687-
fn finish_close_channel(&self, shutdown_res: ShutdownResult) {
2686+
fn finish_close_channel(&self, mut shutdown_res: ShutdownResult) {
26882687
debug_assert_ne!(self.per_peer_state.held_by_thread(), LockHeldState::HeldByThread);
26892688
#[cfg(debug_assertions)]
26902689
for (_, peer) in self.per_peer_state.read().unwrap().iter() {
26912690
debug_assert_ne!(peer.held_by_thread(), LockHeldState::HeldByThread);
26922691
}
26932692

2694-
let (monitor_update_option, mut failed_htlcs, unbroadcasted_batch_funding_txid) = shutdown_res;
2695-
log_debug!(self.logger, "Finishing closure of channel with {} HTLCs to fail", failed_htlcs.len());
2696-
for htlc_source in failed_htlcs.drain(..) {
2693+
log_debug!(self.logger, "Finishing closure of channel with {} HTLCs to fail", shutdown_res.dropped_outbound_htlcs.len());
2694+
for htlc_source in shutdown_res.dropped_outbound_htlcs.drain(..) {
26972695
let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source;
26982696
let reason = HTLCFailReason::from_failure_code(0x4000 | 8);
26992697
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
27002698
self.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver);
27012699
}
2702-
if let Some((_, funding_txo, monitor_update)) = monitor_update_option {
2700+
if let Some((_, funding_txo, monitor_update)) = shutdown_res.monitor_update {
27032701
// There isn't anything we can do if we get an update failure - we're already
27042702
// force-closing. The monitor update on the required in-memory copy should broadcast
27052703
// the latest local state, which is the best we can do anyway. Thus, it is safe to
27062704
// ignore the result here.
27072705
let _ = self.chain_monitor.update_channel(funding_txo, &monitor_update);
27082706
}
27092707
let mut shutdown_results = Vec::new();
2710-
if let Some(txid) = unbroadcasted_batch_funding_txid {
2708+
if let Some(txid) = shutdown_res.unbroadcasted_batch_funding_txid {
27112709
let mut funding_batch_states = self.funding_batch_states.lock().unwrap();
27122710
let affected_channels = funding_batch_states.remove(&txid).into_iter().flatten();
27132711
let per_peer_state = self.per_peer_state.read().unwrap();
@@ -6242,22 +6240,19 @@ where
62426240
}
62436241

62446242
fn internal_closing_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::ClosingSigned) -> Result<(), MsgHandleErrInternal> {
6245-
let mut shutdown_result = None;
6246-
let unbroadcasted_batch_funding_txid;
62476243
let per_peer_state = self.per_peer_state.read().unwrap();
62486244
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
62496245
.ok_or_else(|| {
62506246
debug_assert!(false);
62516247
MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
62526248
})?;
6253-
let (tx, chan_option) = {
6249+
let (tx, chan_option, shutdown_result) = {
62546250
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
62556251
let peer_state = &mut *peer_state_lock;
62566252
match peer_state.channel_by_id.entry(msg.channel_id.clone()) {
62576253
hash_map::Entry::Occupied(mut chan_phase_entry) => {
62586254
if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
6259-
unbroadcasted_batch_funding_txid = chan.context.unbroadcasted_batch_funding_txid();
6260-
let (closing_signed, tx) = try_chan_phase_entry!(self, chan.closing_signed(&self.fee_estimator, &msg), chan_phase_entry);
6255+
let (closing_signed, tx, shutdown_result) = try_chan_phase_entry!(self, chan.closing_signed(&self.fee_estimator, &msg), chan_phase_entry);
62616256
if let Some(msg) = closing_signed {
62626257
peer_state.pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
62636258
node_id: counterparty_node_id.clone(),
@@ -6270,8 +6265,8 @@ where
62706265
// also implies there are no pending HTLCs left on the channel, so we can
62716266
// fully delete it from tracking (the channel monitor is still around to
62726267
// watch for old state broadcasts)!
6273-
(tx, Some(remove_channel_phase!(self, chan_phase_entry)))
6274-
} else { (tx, None) }
6268+
(tx, Some(remove_channel_phase!(self, chan_phase_entry)), shutdown_result)
6269+
} else { (tx, None, shutdown_result) }
62756270
} else {
62766271
return try_chan_phase_entry!(self, Err(ChannelError::Close(
62776272
"Got a closing_signed message for an unfunded channel!".into())), chan_phase_entry);
@@ -6293,7 +6288,6 @@ where
62936288
});
62946289
}
62956290
self.issue_channel_close_events(&chan.context, ClosureReason::CooperativeClosure);
6296-
shutdown_result = Some((None, Vec::new(), unbroadcasted_batch_funding_txid));
62976291
}
62986292
mem::drop(per_peer_state);
62996293
if let Some(shutdown_result) = shutdown_result {
@@ -6972,8 +6966,7 @@ where
69726966
fn maybe_generate_initial_closing_signed(&self) -> bool {
69736967
let mut handle_errors: Vec<(PublicKey, Result<(), _>)> = Vec::new();
69746968
let mut has_update = false;
6975-
let mut shutdown_result = None;
6976-
let mut unbroadcasted_batch_funding_txid = None;
6969+
let mut shutdown_results = Vec::new();
69776970
{
69786971
let per_peer_state = self.per_peer_state.read().unwrap();
69796972

@@ -6984,15 +6977,17 @@ where
69846977
peer_state.channel_by_id.retain(|channel_id, phase| {
69856978
match phase {
69866979
ChannelPhase::Funded(chan) => {
6987-
unbroadcasted_batch_funding_txid = chan.context.unbroadcasted_batch_funding_txid();
69886980
match chan.maybe_propose_closing_signed(&self.fee_estimator, &self.logger) {
6989-
Ok((msg_opt, tx_opt)) => {
6981+
Ok((msg_opt, tx_opt, shutdown_result_opt)) => {
69906982
if let Some(msg) = msg_opt {
69916983
has_update = true;
69926984
pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
69936985
node_id: chan.context.get_counterparty_node_id(), msg,
69946986
});
69956987
}
6988+
if let Some(shutdown_result) = shutdown_result_opt {
6989+
shutdown_results.push(shutdown_result);
6990+
}
69966991
if let Some(tx) = tx_opt {
69976992
// We're done with this channel. We got a closing_signed and sent back
69986993
// a closing_signed with a closing transaction to broadcast.
@@ -7007,7 +7002,6 @@ where
70077002
log_info!(self.logger, "Broadcasting {}", log_tx!(tx));
70087003
self.tx_broadcaster.broadcast_transactions(&[&tx]);
70097004
update_maps_on_chan_removal!(self, &chan.context);
7010-
shutdown_result = Some((None, Vec::new(), unbroadcasted_batch_funding_txid));
70117005
false
70127006
} else { true }
70137007
},
@@ -7029,7 +7023,7 @@ where
70297023
let _ = handle_error!(self, err, counterparty_node_id);
70307024
}
70317025

7032-
if let Some(shutdown_result) = shutdown_result {
7026+
for shutdown_result in shutdown_results.drain(..) {
70337027
self.finish_close_channel(shutdown_result);
70347028
}
70357029

@@ -7048,7 +7042,7 @@ where
70487042
// Channel::force_shutdown tries to make us do) as we may still be in initialization,
70497043
// so we track the update internally and handle it when the user next calls
70507044
// timer_tick_occurred, guaranteeing we're running normally.
7051-
if let Some((counterparty_node_id, funding_txo, update)) = failure.0.take() {
7045+
if let Some((counterparty_node_id, funding_txo, update)) = failure.monitor_update.take() {
70527046
assert_eq!(update.updates.len(), 1);
70537047
if let ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } = update.updates[0] {
70547048
assert!(should_broadcast);
@@ -9266,16 +9260,16 @@ where
92669260
log_error!(args.logger, " The ChannelMonitor for channel {} is at counterparty commitment transaction number {} but the ChannelManager is at counterparty commitment transaction number {}.",
92679261
&channel.context.channel_id(), monitor.get_cur_counterparty_commitment_number(), channel.get_cur_counterparty_commitment_transaction_number());
92689262
}
9269-
let (monitor_update, mut new_failed_htlcs, batch_funding_txid) = channel.context.force_shutdown(true);
9270-
if batch_funding_txid.is_some() {
9263+
let mut shutdown_result = channel.context.force_shutdown(true);
9264+
if shutdown_result.unbroadcasted_batch_funding_txid.is_some() {
92719265
return Err(DecodeError::InvalidValue);
92729266
}
9273-
if let Some((counterparty_node_id, funding_txo, update)) = monitor_update {
9267+
if let Some((counterparty_node_id, funding_txo, update)) = shutdown_result.monitor_update {
92749268
close_background_events.push(BackgroundEvent::MonitorUpdateRegeneratedOnStartup {
92759269
counterparty_node_id, funding_txo, update
92769270
});
92779271
}
9278-
failed_htlcs.append(&mut new_failed_htlcs);
9272+
failed_htlcs.append(&mut shutdown_result.dropped_outbound_htlcs);
92799273
channel_closures.push_back((events::Event::ChannelClosed {
92809274
channel_id: channel.context.channel_id(),
92819275
user_channel_id: channel.context.get_user_id(),

0 commit comments

Comments
 (0)