Skip to content

Commit 3ae86c0

Browse files
committed
Decide on close-broadcasting commitment txn based on channel state
In a previous commit, we removed the ability for users to pick whether we will broadcast a commitment transaction on channel closure. However, that doesn't mean that there is no value in never broadcasting commitment transactions on channel closure. Rather, we use it to avoid broadcasting transactions which we know cannot confirm if the channel's funding transaction was not broadcasted. Here we make this relationship more formal by splitting the force-closure handling logic in `Channel` into the existing `ChannelContext::force_shutdown` as well as a new `ChannelContext::abandon_unfunded_chan`. `ChannelContext::force_shutdown` is the only public method, but it delegates to `abandon_unfunded_chan` based on the channel's state. This has the nice side effect of avoiding commitment transaction broadcasting when a batch open fails to get past the funding stage.
1 parent d6408f0 commit 3ae86c0

File tree

4 files changed

+59
-81
lines changed

4 files changed

+59
-81
lines changed

lightning/src/events/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,9 @@ pub enum ClosureReason {
327327
/// Whether or not the latest transaction was broadcasted when the channel was force
328328
/// closed.
329329
///
330-
/// TODO: Update docs on when this will happen!
330+
/// This will be set to `Some(true)` for any channels closed after their funding
331+
/// transaction was (or might have been) broadcasted, and `Some(false)` for any channels
332+
/// closed prior to their funding transaction being broadcasted.
331333
///
332334
/// This will be `None` for objects generated or written by LDK 0.0.123 and
333335
/// earlier.

lightning/src/ln/channel.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,11 +1778,9 @@ where
17781778
}
17791779
}
17801780

1781-
pub fn force_shutdown(
1782-
&mut self, should_broadcast: bool, closure_reason: ClosureReason,
1783-
) -> ShutdownResult {
1781+
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
17841782
let (funding, context) = self.funding_and_context_mut();
1785-
context.force_shutdown(funding, should_broadcast, closure_reason)
1783+
context.force_shutdown(funding, closure_reason)
17861784
}
17871785

17881786
#[rustfmt::skip]
@@ -5294,20 +5292,19 @@ where
52945292
self.unbroadcasted_funding_txid(funding).filter(|_| self.is_batch_funding())
52955293
}
52965294

5297-
/// Gets the latest commitment transaction and any dependent transactions for relay (forcing
5298-
/// shutdown of this channel - no more calls into this Channel may be made afterwards except
5299-
/// those explicitly stated to be allowed after shutdown completes, eg some simple getters).
5300-
/// Also returns the list of payment_hashes for channels which we can safely fail backwards
5301-
/// immediately (others we will have to allow to time out).
5302-
pub fn force_shutdown(
5303-
&mut self, funding: &FundingScope, should_broadcast: bool, closure_reason: ClosureReason,
5295+
/// Shuts down this Channel (no more calls into this Channel may be made afterwards except
5296+
/// those explicitly stated to be alowed after shutdown, e.g. some simple getters).
5297+
fn force_shutdown(
5298+
&mut self, funding: &FundingScope, mut closure_reason: ClosureReason,
53045299
) -> ShutdownResult {
53055300
// Note that we MUST only generate a monitor update that indicates force-closure - we're
53065301
// called during initialization prior to the chain_monitor in the encompassing ChannelManager
53075302
// being fully configured in some cases. Thus, its likely any monitor events we generate will
53085303
// be delayed in being processed! See the docs for `ChannelManagerReadArgs` for more.
53095304
assert!(!matches!(self.channel_state, ChannelState::ShutdownComplete));
53105305

5306+
let broadcast = self.is_funding_broadcast();
5307+
53115308
// We go ahead and "free" any holding cell HTLCs or HTLCs we haven't yet committed to and
53125309
// return them to fail the payment.
53135310
let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len());
@@ -5338,7 +5335,7 @@ where
53385335
let update = ChannelMonitorUpdate {
53395336
update_id: self.latest_monitor_update_id,
53405337
updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed {
5341-
should_broadcast,
5338+
should_broadcast: broadcast,
53425339
}],
53435340
channel_id: Some(self.channel_id()),
53445341
};
@@ -5352,6 +5349,12 @@ where
53525349
let unbroadcasted_batch_funding_txid = self.unbroadcasted_batch_funding_txid(funding);
53535350
let unbroadcasted_funding_tx = self.unbroadcasted_funding(funding);
53545351

5352+
if let ClosureReason::HolderForceClosed { ref mut broadcasted_latest_txn, .. } =
5353+
&mut closure_reason
5354+
{
5355+
*broadcasted_latest_txn = Some(broadcast);
5356+
}
5357+
53555358
self.channel_state = ChannelState::ShutdownComplete;
53565359
self.update_time_counter += 1;
53575360
ShutdownResult {
@@ -5993,10 +5996,8 @@ where
59935996
&self.context
59945997
}
59955998

5996-
pub fn force_shutdown(
5997-
&mut self, closure_reason: ClosureReason, should_broadcast: bool,
5998-
) -> ShutdownResult {
5999-
self.context.force_shutdown(&self.funding, should_broadcast, closure_reason)
5999+
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
6000+
self.context.force_shutdown(&self.funding, closure_reason)
60006001
}
60016002

60026003
#[rustfmt::skip]
@@ -8097,7 +8098,7 @@ where
80978098
(closing_signed, signed_tx, shutdown_result)
80988099
}
80998100
Err(err) => {
8100-
let shutdown = self.context.force_shutdown(&self.funding, true, ClosureReason::ProcessingError {err: err.to_string()});
8101+
let shutdown = self.context.force_shutdown(&self.funding, ClosureReason::ProcessingError {err: err.to_string()});
81018102
(None, None, Some(shutdown))
81028103
}
81038104
}
@@ -11200,6 +11201,10 @@ impl<SP: Deref> OutboundV1Channel<SP>
1120011201
where
1120111202
SP::Target: SignerProvider,
1120211203
{
11204+
pub fn abandon_unfunded_chan(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
11205+
self.context.force_shutdown(&self.funding, closure_reason)
11206+
}
11207+
1120311208
#[allow(dead_code)] // TODO(dual_funding): Remove once opending V2 channels is enabled.
1120411209
#[rustfmt::skip]
1120511210
pub fn new<ES: Deref, F: Deref, L: Deref>(

lightning/src/ln/channelmanager.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3245,7 +3245,7 @@ macro_rules! convert_channel_err {
32453245
($self: ident, $peer_state: expr, $err: expr, $funded_channel: expr, $channel_id: expr, FUNDED_CHANNEL) => { {
32463246
let mut do_close = |reason| {
32473247
(
3248-
$funded_channel.force_shutdown(reason, true),
3248+
$funded_channel.force_shutdown(reason),
32493249
$self.get_channel_update_for_broadcast(&$funded_channel).ok(),
32503250
)
32513251
};
@@ -3255,7 +3255,7 @@ macro_rules! convert_channel_err {
32553255
convert_channel_err!($self, $peer_state, $err, $funded_channel, do_close, locked_close, $channel_id, _internal)
32563256
} };
32573257
($self: ident, $peer_state: expr, $err: expr, $channel: expr, $channel_id: expr, UNFUNDED_CHANNEL) => { {
3258-
let mut do_close = |reason| { ($channel.force_shutdown(true, reason), None) };
3258+
let mut do_close = |reason| { ($channel.force_shutdown(reason), None) };
32593259
let locked_close = |_, chan: &mut Channel<_>| { locked_close_channel!($self, chan.context(), UNFUNDED); };
32603260
convert_channel_err!($self, $peer_state, $err, $channel, do_close, locked_close, $channel_id, _internal)
32613261
} };
@@ -4435,6 +4435,8 @@ where
44354435
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
44364436
log_debug!(self.logger,
44374437
"Force-closing channel, The error message sent to the peer : {}", error_message);
4438+
// No matter what value for `broadcast_latest_txn` we set here, `Channel` will override it
4439+
// and set the appropriate value.
44384440
let reason = ClosureReason::HolderForceClosed {
44394441
broadcasted_latest_txn: Some(true),
44404442
message: error_message,
@@ -5570,12 +5572,12 @@ where
55705572
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
55715573
let peer_state = &mut *peer_state_lock;
55725574

5573-
macro_rules! close_chan { ($err: expr, $api_err: expr, $chan: expr) => { {
5575+
macro_rules! abandon_chan { ($err: expr, $api_err: expr, $chan: expr) => { {
55745576
let counterparty;
55755577
let err = if let ChannelError::Close((msg, reason)) = $err {
55765578
let channel_id = $chan.context.channel_id();
55775579
counterparty = $chan.context.get_counterparty_node_id();
5578-
let shutdown_res = $chan.context.force_shutdown(&$chan.funding, false, reason);
5580+
let shutdown_res = $chan.abandon_unfunded_chan(reason);
55795581
MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None)
55805582
} else { unreachable!(); };
55815583

@@ -5595,7 +5597,7 @@ where
55955597
Err(err) => {
55965598
let chan_err = ChannelError::close(err.to_owned());
55975599
let api_err = APIError::APIMisuseError { err: err.to_owned() };
5598-
return close_chan!(chan_err, api_err, chan);
5600+
return abandon_chan!(chan_err, api_err, chan);
55995601
},
56005602
}
56015603

@@ -5605,7 +5607,7 @@ where
56055607
Ok(funding_msg) => (chan, funding_msg),
56065608
Err((mut chan, chan_err)) => {
56075609
let api_err = APIError::ChannelUnavailable { err: "Signer refused to sign the initial commitment transaction".to_owned() };
5608-
return close_chan!(chan_err, api_err, chan);
5610+
return abandon_chan!(chan_err, api_err, chan);
56095611
}
56105612
}
56115613
},
@@ -5634,7 +5636,7 @@ where
56345636
let chan_err = ChannelError::close(err.to_owned());
56355637
let api_err = APIError::APIMisuseError { err: err.to_owned() };
56365638
chan.unset_funding_info();
5637-
return close_chan!(chan_err, api_err, chan);
5639+
return abandon_chan!(chan_err, api_err, chan);
56385640
},
56395641
hash_map::Entry::Vacant(e) => {
56405642
if let Some(msg) = msg_opt {
@@ -14735,7 +14737,7 @@ where
1473514737
log_error!(logger, " The ChannelMonitor for channel {} is at counterparty commitment transaction number {} but the ChannelManager is at counterparty commitment transaction number {}.",
1473614738
&channel.context.channel_id(), monitor.get_cur_counterparty_commitment_number(), channel.get_cur_counterparty_commitment_transaction_number());
1473714739
}
14738-
let mut shutdown_result = channel.context.force_shutdown(&channel.funding, true, ClosureReason::OutdatedChannelManager);
14740+
let mut shutdown_result = channel.force_shutdown(ClosureReason::OutdatedChannelManager);
1473914741
if shutdown_result.unbroadcasted_batch_funding_txid.is_some() {
1474014742
return Err(DecodeError::InvalidValue);
1474114743
}
@@ -14808,7 +14810,6 @@ where
1480814810
// If we were persisted and shut down while the initial ChannelMonitor persistence
1480914811
// was in-progress, we never broadcasted the funding transaction and can still
1481014812
// safely discard the channel.
14811-
let _ = channel.context.force_shutdown(&channel.funding, false, ClosureReason::DisconnectedPeer);
1481214813
channel_closures.push_back((events::Event::ChannelClosed {
1481314814
channel_id: channel.context.channel_id(),
1481414815
user_channel_id: channel.context.get_user_id(),

lightning/src/ln/functional_tests.rs

Lines changed: 24 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11418,14 +11418,10 @@ pub fn test_close_in_funding_batch() {
1141811418
_ => panic!("Unexpected message."),
1141911419
}
1142011420

11421-
// We broadcast the commitment transaction as part of the force-close.
11422-
{
11423-
let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast();
11424-
assert_eq!(broadcasted_txs.len(), 1);
11425-
assert!(broadcasted_txs[0].compute_txid() != tx.compute_txid());
11426-
assert_eq!(broadcasted_txs[0].input.len(), 1);
11427-
assert_eq!(broadcasted_txs[0].input[0].previous_output.txid, tx.compute_txid());
11428-
}
11421+
// Because the funding was never broadcasted, we should never bother to broadcast the
11422+
// commitment transactions either.
11423+
let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast();
11424+
assert_eq!(broadcasted_txs.len(), 0);
1142911425

1143011426
// All channels in the batch should close immediately.
1143111427
check_closed_events(
@@ -11524,15 +11520,10 @@ pub fn test_batch_funding_close_after_funding_signed() {
1152411520
_ => panic!("Unexpected message."),
1152511521
}
1152611522

11527-
// TODO: We shouldn't broadcast any commitment transaction here as we have not yet broadcasted
11528-
// the funding transaction.
11529-
{
11530-
let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast();
11531-
assert_eq!(broadcasted_txs.len(), 2);
11532-
assert!(broadcasted_txs[0].compute_txid() != tx.compute_txid());
11533-
assert_eq!(broadcasted_txs[0].input.len(), 1);
11534-
assert_eq!(broadcasted_txs[0].input[0].previous_output.txid, tx.compute_txid());
11535-
}
11523+
// Because the funding was never broadcasted, we should never bother to broadcast the
11524+
// commitment transactions either.
11525+
let broadcasted_txs = nodes[0].tx_broadcaster.txn_broadcast();
11526+
assert_eq!(broadcasted_txs.len(), 0);
1153611527

1153711528
// All channels in the batch should close immediately.
1153811529
check_closed_events(
@@ -11559,7 +11550,8 @@ pub fn test_batch_funding_close_after_funding_signed() {
1155911550
assert!(nodes[0].node.list_channels().is_empty());
1156011551
}
1156111552

11562-
fn do_test_funding_and_commitment_tx_confirm_same_block(confirm_remote_commitment: bool) {
11553+
#[xtest(feature = "_externalize_tests")]
11554+
pub fn test_funding_and_commitment_tx_confirm_same_block() {
1156311555
// Tests that a node will forget the channel (when it only requires 1 confirmation) if the
1156411556
// funding and commitment transaction confirm in the same block.
1156511557
let chanmon_cfgs = create_chanmon_cfgs(2);
@@ -11573,6 +11565,9 @@ fn do_test_funding_and_commitment_tx_confirm_same_block(confirm_remote_commitmen
1157311565
);
1157411566
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1157511567

11568+
let node_a_id = nodes[0].node.get_our_node_id();
11569+
let node_b_id = nodes[1].node.get_our_node_id();
11570+
1157611571
let funding_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 0);
1157711572
let chan_id = ChannelId::v1_from_funding_outpoint(chain::transaction::OutPoint {
1157811573
txid: funding_tx.compute_txid(),
@@ -11582,55 +11577,30 @@ fn do_test_funding_and_commitment_tx_confirm_same_block(confirm_remote_commitmen
1158211577
assert_eq!(nodes[0].node.list_channels().len(), 1);
1158311578
assert_eq!(nodes[1].node.list_channels().len(), 1);
1158411579

11585-
let (closing_node, other_node) =
11586-
if confirm_remote_commitment { (&nodes[1], &nodes[0]) } else { (&nodes[0], &nodes[1]) };
11587-
let closing_node_id = closing_node.node.get_our_node_id();
11588-
let other_node_id = other_node.node.get_our_node_id();
11589-
11590-
let message = "Channel force-closed".to_owned();
11591-
closing_node
11592-
.node
11593-
.force_close_broadcasting_latest_txn(&chan_id, &other_node_id, message.clone())
11594-
.unwrap();
11595-
let mut msg_events = closing_node.node.get_and_clear_pending_msg_events();
11596-
assert_eq!(msg_events.len(), 1);
11597-
match msg_events.pop().unwrap() {
11598-
MessageSendEvent::HandleError {
11599-
action: msgs::ErrorAction::SendErrorMessage { .. },
11600-
..
11601-
} => {},
11602-
_ => panic!("Unexpected event"),
11603-
}
11604-
check_added_monitors(closing_node, 1);
11605-
let reason = ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true), message };
11606-
check_closed_event(closing_node, 1, reason, false, &[other_node_id], 1_000_000);
11607-
1160811580
let commitment_tx = {
11609-
let mut txn = closing_node.tx_broadcaster.txn_broadcast();
11581+
let mon = get_monitor!(nodes[0], chan_id);
11582+
let mut txn = mon.unsafe_get_latest_holder_commitment_txn(&nodes[0].logger);
1161011583
assert_eq!(txn.len(), 1);
11611-
let commitment_tx = txn.pop().unwrap();
11612-
check_spends!(commitment_tx, funding_tx);
11613-
commitment_tx
11584+
txn.pop().unwrap()
1161411585
};
1161511586

1161611587
mine_transactions(&nodes[0], &[&funding_tx, &commitment_tx]);
1161711588
mine_transactions(&nodes[1], &[&funding_tx, &commitment_tx]);
1161811589

11619-
check_closed_broadcast(other_node, 1, true);
11620-
check_added_monitors(other_node, 1);
11590+
check_closed_broadcast(&nodes[0], 1, true);
11591+
check_added_monitors(&nodes[0], 1);
11592+
let reason = ClosureReason::CommitmentTxConfirmed;
11593+
check_closed_event(&nodes[0], 1, reason, false, &[node_b_id], 1_000_000);
11594+
11595+
check_closed_broadcast(&nodes[1], 1, true);
11596+
check_added_monitors(&nodes[1], 1);
1162111597
let reason = ClosureReason::CommitmentTxConfirmed;
11622-
check_closed_event(other_node, 1, reason, false, &[closing_node_id], 1_000_000);
11598+
check_closed_event(&nodes[1], 1, reason, false, &[node_a_id], 1_000_000);
1162311599

1162411600
assert!(nodes[0].node.list_channels().is_empty());
1162511601
assert!(nodes[1].node.list_channels().is_empty());
1162611602
}
1162711603

11628-
#[xtest(feature = "_externalize_tests")]
11629-
pub fn test_funding_and_commitment_tx_confirm_same_block() {
11630-
do_test_funding_and_commitment_tx_confirm_same_block(false);
11631-
do_test_funding_and_commitment_tx_confirm_same_block(true);
11632-
}
11633-
1163411604
#[xtest(feature = "_externalize_tests")]
1163511605
pub fn test_accept_inbound_channel_errors_queued() {
1163611606
// For manually accepted inbound channels, tests that a close error is correctly handled

0 commit comments

Comments
 (0)