Skip to content

Commit 6f56dbc

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 cc3486c commit 6f56dbc

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
@@ -1775,11 +1775,9 @@ where
17751775
}
17761776
}
17771777

1778-
pub fn force_shutdown(
1779-
&mut self, should_broadcast: bool, closure_reason: ClosureReason,
1780-
) -> ShutdownResult {
1778+
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
17811779
let (funding, context) = self.funding_and_context_mut();
1782-
context.force_shutdown(funding, should_broadcast, closure_reason)
1780+
context.force_shutdown(funding, closure_reason)
17831781
}
17841782

17851783
#[rustfmt::skip]
@@ -5340,20 +5338,19 @@ where
53405338
self.unbroadcasted_funding_txid(funding).filter(|_| self.is_batch_funding())
53415339
}
53425340

5343-
/// Gets the latest commitment transaction and any dependent transactions for relay (forcing
5344-
/// shutdown of this channel - no more calls into this Channel may be made afterwards except
5345-
/// those explicitly stated to be allowed after shutdown completes, eg some simple getters).
5346-
/// Also returns the list of payment_hashes for channels which we can safely fail backwards
5347-
/// immediately (others we will have to allow to time out).
5348-
pub fn force_shutdown(
5349-
&mut self, funding: &FundingScope, should_broadcast: bool, closure_reason: ClosureReason,
5341+
/// Shuts down this Channel (no more calls into this Channel may be made afterwards except
5342+
/// those explicitly stated to be alowed after shutdown, e.g. some simple getters).
5343+
fn force_shutdown(
5344+
&mut self, funding: &FundingScope, mut closure_reason: ClosureReason,
53505345
) -> ShutdownResult {
53515346
// Note that we MUST only generate a monitor update that indicates force-closure - we're
53525347
// called during initialization prior to the chain_monitor in the encompassing ChannelManager
53535348
// being fully configured in some cases. Thus, its likely any monitor events we generate will
53545349
// be delayed in being processed! See the docs for `ChannelManagerReadArgs` for more.
53555350
assert!(!matches!(self.channel_state, ChannelState::ShutdownComplete));
53565351

5352+
let broadcast = self.is_funding_broadcast();
5353+
53575354
// We go ahead and "free" any holding cell HTLCs or HTLCs we haven't yet committed to and
53585355
// return them to fail the payment.
53595356
let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len());
@@ -5384,7 +5381,7 @@ where
53845381
let update = ChannelMonitorUpdate {
53855382
update_id: self.latest_monitor_update_id,
53865383
updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed {
5387-
should_broadcast,
5384+
should_broadcast: broadcast,
53885385
}],
53895386
channel_id: Some(self.channel_id()),
53905387
};
@@ -5398,6 +5395,12 @@ where
53985395
let unbroadcasted_batch_funding_txid = self.unbroadcasted_batch_funding_txid(funding);
53995396
let unbroadcasted_funding_tx = self.unbroadcasted_funding(funding);
54005397

5398+
if let ClosureReason::HolderForceClosed { ref mut broadcasted_latest_txn, .. } =
5399+
&mut closure_reason
5400+
{
5401+
*broadcasted_latest_txn = Some(broadcast);
5402+
}
5403+
54015404
self.channel_state = ChannelState::ShutdownComplete;
54025405
self.update_time_counter += 1;
54035406
ShutdownResult {
@@ -6047,10 +6050,8 @@ where
60476050
&self.context
60486051
}
60496052

6050-
pub fn force_shutdown(
6051-
&mut self, closure_reason: ClosureReason, should_broadcast: bool,
6052-
) -> ShutdownResult {
6053-
self.context.force_shutdown(&self.funding, should_broadcast, closure_reason)
6053+
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
6054+
self.context.force_shutdown(&self.funding, closure_reason)
60546055
}
60556056

60566057
#[rustfmt::skip]
@@ -8124,7 +8125,7 @@ where
81248125
(closing_signed, signed_tx, shutdown_result)
81258126
}
81268127
Err(err) => {
8127-
let shutdown = self.context.force_shutdown(&self.funding, true, ClosureReason::ProcessingError {err: err.to_string()});
8128+
let shutdown = self.context.force_shutdown(&self.funding, ClosureReason::ProcessingError {err: err.to_string()});
81288129
(None, None, Some(shutdown))
81298130
}
81308131
}
@@ -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,
@@ -5550,12 +5552,12 @@ where
55505552
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
55515553
let peer_state = &mut *peer_state_lock;
55525554

5553-
macro_rules! close_chan { ($err: expr, $api_err: expr, $chan: expr) => { {
5555+
macro_rules! abandon_chan { ($err: expr, $api_err: expr, $chan: expr) => { {
55545556
let counterparty;
55555557
let err = if let ChannelError::Close((msg, reason)) = $err {
55565558
let channel_id = $chan.context.channel_id();
55575559
counterparty = $chan.context.get_counterparty_node_id();
5558-
let shutdown_res = $chan.context.force_shutdown(&$chan.funding, false, reason);
5560+
let shutdown_res = $chan.abandon_unfunded_chan(reason);
55595561
MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None)
55605562
} else { unreachable!(); };
55615563

@@ -5575,7 +5577,7 @@ where
55755577
Err(err) => {
55765578
let chan_err = ChannelError::close(err.to_owned());
55775579
let api_err = APIError::APIMisuseError { err: err.to_owned() };
5578-
return close_chan!(chan_err, api_err, chan);
5580+
return abandon_chan!(chan_err, api_err, chan);
55795581
},
55805582
}
55815583

@@ -5585,7 +5587,7 @@ where
55855587
Ok(funding_msg) => (chan, funding_msg),
55865588
Err((mut chan, chan_err)) => {
55875589
let api_err = APIError::ChannelUnavailable { err: "Signer refused to sign the initial commitment transaction".to_owned() };
5588-
return close_chan!(chan_err, api_err, chan);
5590+
return abandon_chan!(chan_err, api_err, chan);
55895591
}
55905592
}
55915593
},
@@ -5614,7 +5616,7 @@ where
56145616
let chan_err = ChannelError::close(err.to_owned());
56155617
let api_err = APIError::APIMisuseError { err: err.to_owned() };
56165618
chan.unset_funding_info();
5617-
return close_chan!(chan_err, api_err, chan);
5619+
return abandon_chan!(chan_err, api_err, chan);
56185620
},
56195621
hash_map::Entry::Vacant(e) => {
56205622
if let Some(msg) = msg_opt {
@@ -14632,7 +14634,7 @@ where
1463214634
log_error!(logger, " The ChannelMonitor for channel {} is at counterparty commitment transaction number {} but the ChannelManager is at counterparty commitment transaction number {}.",
1463314635
&channel.context.channel_id(), monitor.get_cur_counterparty_commitment_number(), channel.get_cur_counterparty_commitment_transaction_number());
1463414636
}
14635-
let mut shutdown_result = channel.context.force_shutdown(&channel.funding, true, ClosureReason::OutdatedChannelManager);
14637+
let mut shutdown_result = channel.force_shutdown(ClosureReason::OutdatedChannelManager);
1463614638
if shutdown_result.unbroadcasted_batch_funding_txid.is_some() {
1463714639
return Err(DecodeError::InvalidValue);
1463814640
}
@@ -14705,7 +14707,6 @@ where
1470514707
// If we were persisted and shut down while the initial ChannelMonitor persistence
1470614708
// was in-progress, we never broadcasted the funding transaction and can still
1470714709
// safely discard the channel.
14708-
let _ = channel.context.force_shutdown(&channel.funding, false, ClosureReason::DisconnectedPeer);
1470914710
channel_closures.push_back((events::Event::ChannelClosed {
1471014711
channel_id: channel.context.channel_id(),
1471114712
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)