Skip to content

Somewhat clean up closure pipelines #3881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 18 additions & 26 deletions lightning-persister/src/fs_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,23 +592,19 @@ mod tests {
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

let node_a_id = nodes[0].node.get_our_node_id();

let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
let error_message = "Channel force-closed";

let message = "Channel force-closed".to_owned();
nodes[1]
.node
.force_close_broadcasting_latest_txn(
&chan.2,
&nodes[0].node.get_our_node_id(),
error_message.to_string(),
)
.force_close_broadcasting_latest_txn(&chan.2, &node_a_id, message.clone())
.unwrap();
check_closed_event!(
nodes[1],
1,
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) },
[nodes[0].node.get_our_node_id()],
100000
);
let reason =
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true), message };
check_closed_event!(nodes[1], 1, reason, [node_a_id], 100000);
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();

// Set the store's directory to read-only, which should result in
Expand Down Expand Up @@ -640,23 +636,19 @@ mod tests {
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

let node_a_id = nodes[0].node.get_our_node_id();

let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
let error_message = "Channel force-closed";

let message = "Channel force-closed".to_owned();
nodes[1]
.node
.force_close_broadcasting_latest_txn(
&chan.2,
&nodes[0].node.get_our_node_id(),
error_message.to_string(),
)
.force_close_broadcasting_latest_txn(&chan.2, &node_a_id, message.clone())
.unwrap();
check_closed_event!(
nodes[1],
1,
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) },
[nodes[0].node.get_our_node_id()],
100000
);
let reason =
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true), message };
check_closed_event!(nodes[1], 1, reason, [node_a_id], 100000);
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap();
let update_id = update_map.get(&added_monitors[0].1.channel_id()).unwrap();
Expand Down
20 changes: 7 additions & 13 deletions lightning-persister/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ pub(crate) fn do_test_store<K: KVStore + Sync>(store_0: &K, store_1: &K) {
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

let node_b_id = nodes[1].node.get_our_node_id();

// Check that the persisted channel data is empty before any channels are
// open.
let mut persisted_chan_data_0 =
Expand Down Expand Up @@ -178,22 +180,14 @@ pub(crate) fn do_test_store<K: KVStore + Sync>(store_0: &K, store_1: &K) {

// Force close because cooperative close doesn't result in any persisted
// updates.
let error_message = "Channel force-closed";
let message = "Channel force-closed".to_owned();
let chan_id = nodes[0].node.list_channels()[0].channel_id;
nodes[0]
.node
.force_close_broadcasting_latest_txn(
&nodes[0].node.list_channels()[0].channel_id,
&nodes[1].node.get_our_node_id(),
error_message.to_string(),
)
.force_close_broadcasting_latest_txn(&chan_id, &node_b_id, message.clone())
.unwrap();
check_closed_event!(
nodes[0],
1,
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) },
[nodes[1].node.get_our_node_id()],
100000
);
let reason = ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true), message };
check_closed_event!(nodes[0], 1, reason, [node_b_id], 100000);
check_closed_broadcast!(nodes[0], true);
check_added_monitors!(nodes[0], 1);

Expand Down
5 changes: 3 additions & 2 deletions lightning/src/chain/chainmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1438,12 +1438,13 @@ mod tests {

// Test that monitors with pending_claims are persisted on every block.
// Now, close channel_2 i.e. b/w node-0 and node-2 to create pending_claim in node[0].
let message = "Channel force-closed".to_owned();
nodes[0]
.node
.force_close_broadcasting_latest_txn(&channel_2, &node_c_id, "closed".to_string())
.force_close_broadcasting_latest_txn(&channel_2, &node_c_id, message.clone())
.unwrap();
let closure_reason =
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) };
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true), message };
check_closed_event!(&nodes[0], 1, closure_reason, false, [node_c_id], 1000000);
check_closed_broadcast(&nodes[0], 1, true);
let close_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
Expand Down
6 changes: 5 additions & 1 deletion lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3445,7 +3445,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
F::Target: FeeEstimator,
L::Target: Logger,
{
let (claimable_outpoints, _) = self.generate_claimable_outpoints_and_watch_outputs(ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) });
let reason = ClosureReason::HolderForceClosed {
broadcasted_latest_txn: Some(true),
message: "ChannelMonitor-initiated commitment transaction broadcast".to_owned(),
};
let (claimable_outpoints, _) = self.generate_claimable_outpoints_and_watch_outputs(reason);
let conf_target = self.closure_conf_target();
self.onchain_tx_handler.update_claims_view_from_requests(
claimable_outpoints, self.best_block.height, self.best_block.height, broadcaster,
Expand Down
50 changes: 32 additions & 18 deletions lightning/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,16 +325,15 @@ pub enum ClosureReason {
/// Whether or not the latest transaction was broadcasted when the channel was force
/// closed.
///
/// Channels closed using [`ChannelManager::force_close_broadcasting_latest_txn`] will have
/// this field set to true, whereas channels closed using [`ChannelManager::force_close_without_broadcasting_txn`]
/// or force-closed prior to being funded will have this field set to false.
/// This will be set to `Some(true)` for any channels closed after their funding
/// transaction was (or might have been) broadcasted, and `Some(false)` for any channels
/// closed prior to their funding transaction being broadcasted.
///
/// This will be `None` for objects generated or written by LDK 0.0.123 and
/// earlier.
///
/// [`ChannelManager::force_close_broadcasting_latest_txn`]: crate::ln::channelmanager::ChannelManager::force_close_broadcasting_latest_txn.
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn.
broadcasted_latest_txn: Option<bool>,
/// XXX: What was passed to force_close!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this XXX still needs to be addressed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, sorry, I was somewhat rushing to get it up last night. Just needed to write docs here.

message: String,
},
/// The channel was closed after negotiating a cooperative close and we've now broadcasted
/// the cooperative close transaction. Note the shutdown may have been initiated by us.
Expand All @@ -356,7 +355,8 @@ pub enum ClosureReason {
/// commitment transaction came from our counterparty, but it may also have come from
/// a copy of our own `ChannelMonitor`.
CommitmentTxConfirmed,
/// The funding transaction failed to confirm in a timely manner on an inbound channel.
/// The funding transaction failed to confirm in a timely manner on an inbound channel or the
/// counterparty failed to fund the channel in a timely manner.
FundingTimedOut,
/// Closure generated from processing an event, likely a HTLC forward/relay/reception.
ProcessingError {
Expand All @@ -383,6 +383,12 @@ pub enum ClosureReason {
/// The counterparty requested a cooperative close of a channel that had not been funded yet.
/// The channel has been immediately closed.
CounterpartyCoopClosedUnfundedChannel,
/// We requested a cooperative close of a channel that had not been funded yet.
/// The channel has been immediately closed.
///
/// Note that events containing this variant will be lost on downgrade to a version of LDK
/// prior to 0.2.
LocallyCoopClosedUnfundedChannel,
/// Another channel in the same funding batch closed before the funding transaction
/// was ready to be broadcast.
FundingBatchClosure,
Expand Down Expand Up @@ -412,12 +418,13 @@ impl core::fmt::Display for ClosureReason {
ClosureReason::CounterpartyForceClosed { peer_msg } => {
f.write_fmt(format_args!("counterparty force-closed with message: {}", peer_msg))
},
ClosureReason::HolderForceClosed { broadcasted_latest_txn } => {
f.write_str("user force-closed the channel")?;
ClosureReason::HolderForceClosed { broadcasted_latest_txn, message } => {
f.write_str("user force-closed the channel with the message \"")?;
f.write_str(message)?;
if let Some(brodcasted) = broadcasted_latest_txn {
write!(
f,
" and {} the latest transaction",
"\" and {} the latest transaction",
if *brodcasted { "broadcasted" } else { "elected not to broadcast" }
)
} else {
Expand Down Expand Up @@ -454,6 +461,9 @@ impl core::fmt::Display for ClosureReason {
ClosureReason::CounterpartyCoopClosedUnfundedChannel => {
f.write_str("the peer requested the unfunded channel be closed")
},
ClosureReason::LocallyCoopClosedUnfundedChannel => {
f.write_str("we requested the unfunded channel be closed")
},
ClosureReason::FundingBatchClosure => {
f.write_str("another channel in the same funding batch closed")
},
Expand All @@ -472,7 +482,10 @@ impl core::fmt::Display for ClosureReason {
impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
(0, CounterpartyForceClosed) => { (1, peer_msg, required) },
(1, FundingTimedOut) => {},
(2, HolderForceClosed) => { (1, broadcasted_latest_txn, option) },
(2, HolderForceClosed) => {
(1, broadcasted_latest_txn, option),
(3, message, required), // XXX: upgrade to empty string or whatever and document
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: unaddressed XXX. Probably could use a default_value with "Channel force-closed" here?

},
(6, CommitmentTxConfirmed) => {},
(4, LegacyCooperativeClosure) => {},
(8, ProcessingError) => { (1, err, required) },
Expand All @@ -487,6 +500,7 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
(0, peer_feerate_sat_per_kw, required),
(2, required_feerate_sat_per_kw, required),
},
(25, LocallyCoopClosedUnfundedChannel) => {},
);

/// The type of HTLC handling performed in [`Event::HTLCHandlingFailed`].
Expand Down Expand Up @@ -1459,7 +1473,7 @@ pub enum Event {
///
/// To accept the request (and in the case of a dual-funded channel, not contribute funds),
/// call [`ChannelManager::accept_inbound_channel`].
/// To reject the request, call [`ChannelManager::force_close_without_broadcasting_txn`].
/// To reject the request, call [`ChannelManager::force_close_broadcasting_latest_txn`].
/// Note that a ['ChannelClosed`] event will _not_ be triggered if the channel is rejected.
///
/// The event is only triggered when a new open channel request is received and the
Expand All @@ -1470,27 +1484,27 @@ pub enum Event {
/// returning `Err(ReplayEvent ())`) and won't be persisted across restarts.
///
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
/// [`ChannelManager::force_close_broadcasting_latest_txn`]: crate::ln::channelmanager::ChannelManager::force_close_broadcasting_latest_txn
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
OpenChannelRequest {
/// The temporary channel ID of the channel requested to be opened.
///
/// When responding to the request, the `temporary_channel_id` should be passed
/// back to the ChannelManager through [`ChannelManager::accept_inbound_channel`] to accept,
/// or through [`ChannelManager::force_close_without_broadcasting_txn`] to reject.
/// or through [`ChannelManager::force_close_broadcasting_latest_txn`] to reject.
///
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
/// [`ChannelManager::force_close_broadcasting_latest_txn`]: crate::ln::channelmanager::ChannelManager::force_close_broadcasting_latest_txn
temporary_channel_id: ChannelId,
/// The node_id of the counterparty requesting to open the channel.
///
/// When responding to the request, the `counterparty_node_id` should be passed
/// back to the `ChannelManager` through [`ChannelManager::accept_inbound_channel`] to
/// accept the request, or through [`ChannelManager::force_close_without_broadcasting_txn`] to reject the
/// request.
/// accept the request, or through [`ChannelManager::force_close_broadcasting_latest_txn`]
/// to reject the request.
///
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
/// [`ChannelManager::force_close_broadcasting_latest_txn`]: crate::ln::channelmanager::ChannelManager::force_close_broadcasting_latest_txn
counterparty_node_id: PublicKey,
/// The channel value of the requested channel.
funding_satoshis: u64,
Expand Down
12 changes: 8 additions & 4 deletions lightning/src/ln/async_signer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -843,15 +843,19 @@ fn do_test_async_holder_signatures(anchors: bool, remote_commitment: bool) {
// Route an HTLC and set the signer as unavailable.
let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1);
route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
let error_message = "Channel force-closed";


if remote_commitment {
let message = "Channel force-closed".to_owned();
// Make the counterparty broadcast its latest commitment.
nodes[1].node.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), error_message.to_string()).unwrap();
nodes[1]
.node
.force_close_broadcasting_latest_txn(&chan_id, &nodes[0].node.get_our_node_id(), message.clone())
.unwrap();
check_added_monitors(&nodes[1], 1);
check_closed_broadcast(&nodes[1], 1, true);
check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, false, &[nodes[0].node.get_our_node_id()], 100_000);
let reason =
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true), message };
check_closed_event(&nodes[1], 1, reason, false, &[nodes[0].node.get_our_node_id()], 100_000);
} else {
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderCommitment);
nodes[0].disable_channel_signer_op(&nodes[1].node.get_our_node_id(), &chan_id, SignerOp::SignHolderHtlcTransaction);
Expand Down
Loading
Loading