Skip to content
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
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2156,9 +2156,11 @@ impl Node {
// dropping it. This lets `channel_reestablish` drive the recovery flow, which is
// especially important against LND peers that don't always handle force-closure
// error messages correctly.
}

Ok(())
Ok(())
} else {
Err(Error::ChannelClosingFailed)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We should always at least log what/why it failed when we return an error.

}
}

/// Update the config for a previously opened channel.
Expand Down
43 changes: 42 additions & 1 deletion tests/integration_tests_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use ldk_node::payment::{
ConfirmationStatus, ForwardedPaymentId, PayerProofOptions, PaymentDetails, PaymentDirection,
PaymentKind, PaymentStatus, TransactionType, UnifiedPaymentResult,
};
use ldk_node::{BuildError, Builder, Event, Node, NodeError, ReserveType};
use ldk_node::{BuildError, Builder, Event, Node, NodeError, ReserveType, UserChannelId};
use lightning::ln::channelmanager::PaymentId;
use lightning::routing::gossip::{NodeAlias, NodeId};
use lightning::routing::router::RouteParametersConfig;
Expand Down Expand Up @@ -546,6 +546,47 @@ async fn peer_removed_when_counterparty_force_closes_last_channel() {
);
}

/// Regression test for issue #1084: `Node::close_channel` and
/// `Node::force_close_channel` returned `Ok(())` when the supplied
/// `UserChannelId` did not match any channel for the counterparty, silently
/// succeeding without initiating a close.
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn close_unknown_user_channel_id_errors() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think the change is worth a dedicated test case, please drop it.

let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
let chain_source = random_chain_source(&bitcoind, &electrsd);
let (node_a, node_b) = setup_two_nodes(&chain_source, false, false);

let address_a = node_a.onchain_payment().new_address().unwrap();
premine_and_distribute_funds(
&bitcoind.client,
&electrsd.client,
vec![address_a],
Amount::from_sat(5_000_000),
)
.await;
node_a.sync_wallets().unwrap();

open_channel(&node_a, &node_b, 4_000_000, false, &electrsd).await;
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
node_a.sync_wallets().unwrap();
node_b.sync_wallets().unwrap();

let user_channel_id_a = expect_channel_ready_event!(node_a, node_b.node_id());
let _user_channel_id_b = expect_channel_ready_event!(node_b, node_a.node_id());
let unknown_user_channel_id = UserChannelId(user_channel_id_a.0 ^ 1);

assert_eq!(
node_a.close_channel(&unknown_user_channel_id, node_b.node_id()),
Err(NodeError::ChannelClosingFailed)
);

// force_close_channel shares close_channel_internal and should also error.
assert_eq!(
node_a.force_close_channel(&unknown_user_channel_id, node_b.node_id(), None),
Err(NodeError::ChannelClosingFailed)
);
}

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn channel_full_cycle_0conf() {
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
Expand Down
Loading