Skip to content

Commit f061a14

Browse files
committed
Expose ChannelDetails::channel_shutdown_state
Add a `ChannelShutdownState` enum mirroring LDK's own type, and expose it as an `Option<ChannelShutdownState>` field on `ChannelDetails`.
1 parent b0e159a commit f061a14

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

src/ffi/types.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub use bitcoin::{Address, BlockHash, FeeRate, Network, OutPoint, ScriptBuf, Txi
2525
pub use lightning::chain::channelmonitor::BalanceSource;
2626
use lightning::events::PaidBolt12Invoice as LdkPaidBolt12Invoice;
2727
pub use lightning::events::{ClosureReason, PaymentFailureReason};
28+
use lightning::ln::channel_state::ChannelShutdownState;
2829
use lightning::ln::channelmanager::PaymentId;
2930
use lightning::ln::msgs::DecodeError;
3031
pub use lightning::ln::types::ChannelId;
@@ -1408,6 +1409,26 @@ uniffi::custom_type!(LSPSDateTime, String, {
14081409
},
14091410
});
14101411

1412+
/// The shutdown state of a channel as returned in [`ChannelDetails::channel_shutdown_state`].
1413+
///
1414+
/// [`ChannelDetails::channel_shutdown_state`]: crate::ChannelDetails::channel_shutdown_state
1415+
#[uniffi::remote(Enum)]
1416+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1417+
pub enum ChannelShutdownState {
1418+
/// Channel has not sent or received a shutdown message.
1419+
NotShuttingDown,
1420+
/// Local node has sent a shutdown message for this channel.
1421+
ShutdownInitiated,
1422+
/// Shutdown message exchanges have concluded and the channels are in the midst of
1423+
/// resolving all existing open HTLCs before closing can continue.
1424+
ResolvingHTLCs,
1425+
/// All HTLCs have been resolved, nodes are currently negotiating channel close onchain fee rates.
1426+
NegotiatingClosingFee,
1427+
/// We've successfully negotiated a closing_signed dance. At this point `ChannelManager` is about
1428+
/// to drop the channel.
1429+
ShutdownComplete,
1430+
}
1431+
14111432
/// The reason the channel was closed. See individual variants for more details.
14121433
#[uniffi::remote(Enum)]
14131434
#[derive(Clone, Debug, PartialEq, Eq)]

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ pub use lightning;
145145
use lightning::chain::BestBlock;
146146
use lightning::impl_writeable_tlv_based;
147147
use lightning::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
148-
use lightning::ln::channel_state::{ChannelDetails as LdkChannelDetails, ChannelShutdownState};
148+
use lightning::ln::channel_state::ChannelDetails as LdkChannelDetails;
149+
pub use lightning::ln::channel_state::ChannelShutdownState;
149150
use lightning::ln::channelmanager::PaymentId;
150151
use lightning::ln::msgs::SocketAddress;
151152
use lightning::routing::gossip::NodeAlias;

src/types.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use bitcoin::{OutPoint, ScriptBuf};
1515
use bitcoin_payment_instructions::onion_message_resolver::LDKOnionMessageDNSSECHrnResolver;
1616
use lightning::chain::chainmonitor;
1717
use lightning::impl_writeable_tlv_based;
18-
use lightning::ln::channel_state::ChannelDetails as LdkChannelDetails;
18+
use lightning::ln::channel_state::{ChannelDetails as LdkChannelDetails, ChannelShutdownState};
1919
use lightning::ln::msgs::{RoutingMessageHandler, SocketAddress};
2020
use lightning::ln::peer_handler::IgnoringMessageHandler;
2121
use lightning::ln::types::ChannelId;
@@ -529,6 +529,10 @@ pub struct ChannelDetails {
529529
pub inbound_htlc_maximum_msat: Option<u64>,
530530
/// Set of configurable parameters that affect channel operation.
531531
pub config: ChannelConfig,
532+
/// The current shutdown state of the channel, if any.
533+
///
534+
/// Will be `None` for objects serialized with LDK Node v0.1 and earlier.
535+
pub channel_shutdown_state: Option<ChannelShutdownState>,
532536
}
533537

534538
impl From<LdkChannelDetails> for ChannelDetails {
@@ -584,6 +588,7 @@ impl From<LdkChannelDetails> for ChannelDetails {
584588
inbound_htlc_maximum_msat: value.inbound_htlc_maximum_msat,
585589
// unwrap safety: `config` is only `None` for LDK objects serialized prior to 0.0.109.
586590
config: value.config.map(|c| c.into()).unwrap(),
591+
channel_shutdown_state: value.channel_shutdown_state,
587592
}
588593
}
589594
}

tests/common/mod.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ use ldk_node::entropy::{generate_entropy_mnemonic, NodeEntropy};
3131
use ldk_node::io::sqlite_store::SqliteStore;
3232
use ldk_node::payment::{PaymentDirection, PaymentKind, PaymentStatus};
3333
use ldk_node::{
34-
Builder, CustomTlvRecord, Event, LightningBalance, Node, NodeError, PendingSweepBalance,
35-
UserChannelId,
34+
Builder, ChannelShutdownState, CustomTlvRecord, Event, LightningBalance, Node, NodeError,
35+
PendingSweepBalance, UserChannelId,
3636
};
3737
use lightning::io;
3838
use lightning::ln::msgs::SocketAddress;
@@ -918,6 +918,12 @@ pub(crate) async fn do_channel_full_cycle<E: ElectrumApi>(
918918
let user_channel_id_a = expect_channel_ready_event!(node_a, node_b.node_id());
919919
let user_channel_id_b = expect_channel_ready_event!(node_b, node_a.node_id());
920920

921+
// After channel_ready, no shutdown should be in progress.
922+
assert!(node_a.list_channels().iter().all(|c| matches!(
923+
c.channel_shutdown_state,
924+
None | Some(ChannelShutdownState::NotShuttingDown)
925+
)));
926+
921927
println!("\nB receive");
922928
let invoice_amount_1_msat = 2500_000;
923929
let invoice_description: Bolt11InvoiceDescription =
@@ -1269,6 +1275,20 @@ pub(crate) async fn do_channel_full_cycle<E: ElectrumApi>(
12691275
node_a.force_close_channel(&user_channel_id_a, node_b.node_id(), None).unwrap();
12701276
} else {
12711277
node_a.close_channel(&user_channel_id_a, node_b.node_id()).unwrap();
1278+
// The cooperative shutdown may complete before we get to check, but if the channel
1279+
// is still visible it must already be in a shutdown state.
1280+
if let Some(channel) =
1281+
node_a.list_channels().into_iter().find(|c| c.user_channel_id == user_channel_id_a)
1282+
{
1283+
assert!(
1284+
!matches!(
1285+
channel.channel_shutdown_state,
1286+
None | Some(ChannelShutdownState::NotShuttingDown)
1287+
),
1288+
"Expected shutdown in progress on node_a, got {:?}",
1289+
channel.channel_shutdown_state,
1290+
);
1291+
}
12721292
}
12731293

12741294
expect_event!(node_a, ChannelClosed);

0 commit comments

Comments
 (0)