@@ -42,7 +42,7 @@ use lightning_net_tokio::SocketDescriptor;
4242
4343use crate :: chain:: bitcoind:: UtxoSourceClient ;
4444use crate :: chain:: ChainSource ;
45- use crate :: config:: ChannelConfig ;
45+ use crate :: config:: { AnchorChannelsConfig , ChannelConfig } ;
4646use crate :: data_store:: DataStore ;
4747use crate :: fee_estimator:: OnchainFeeEstimator ;
4848use crate :: ffi:: maybe_wrap;
@@ -452,6 +452,47 @@ pub struct ChannelCounterparty {
452452 pub outbound_htlc_maximum_msat : Option < u64 > ,
453453}
454454
455+ /// Describes the reserve behavior of a channel based on its type and trust configuration.
456+ ///
457+ /// This captures the combination of the channel's on-chain construction (anchor outputs vs legacy
458+ /// static_remote_key) and whether the counterparty is in our trusted peers list. It tells the
459+ /// user what reserve obligations exist for this channel without exposing internal protocol details.
460+ ///
461+ /// See [`AnchorChannelsConfig`] for how reserve behavior is configured.
462+ ///
463+ /// [`AnchorChannelsConfig`]: crate::config::AnchorChannelsConfig
464+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
465+ #[ cfg_attr( feature = "uniffi" , derive( uniffi:: Enum ) ) ]
466+ pub enum ReserveType {
467+ /// An anchor outputs channel where we maintain a per-channel on-chain reserve for fee
468+ /// bumping force-close transactions.
469+ ///
470+ /// Anchor channels allow either party to fee-bump commitment transactions via CPFP
471+ /// at broadcast time. Because the pre-signed commitment fee may be insufficient under
472+ /// current fee conditions, the broadcaster must supply additional funds (hence adaptive)
473+ /// through an anchor output spend. The reserve ensures sufficient on-chain funds are
474+ /// available to cover this.
475+ ///
476+ /// This is the default for anchor channels when the counterparty is not in
477+ /// [`trusted_peers_no_reserve`].
478+ ///
479+ /// [`trusted_peers_no_reserve`]: crate::config::AnchorChannelsConfig::trusted_peers_no_reserve
480+ Adaptive ,
481+ /// An anchor outputs channel where we do not maintain any reserve, because the counterparty
482+ /// is in our [`trusted_peers_no_reserve`] list.
483+ ///
484+ /// In this mode, we trust the counterparty to broadcast a valid commitment transaction on
485+ /// our behalf and do not set aside funds for fee bumping.
486+ ///
487+ /// [`trusted_peers_no_reserve`]: crate::config::AnchorChannelsConfig::trusted_peers_no_reserve
488+ TrustedPeersNoReserve ,
489+ /// A legacy (pre-anchor) channel using only `option_static_remotekey`.
490+ ///
491+ /// These channels do not use anchor outputs and therefore do not require an on-chain reserve
492+ /// for fee bumping. Commitment transaction fees are pre-committed at channel open time.
493+ Legacy ,
494+ }
495+
455496/// Details of a channel as returned by [`Node::list_channels`].
456497///
457498/// When a channel is spliced, most fields continue to refer to the original pre-splice channel
@@ -616,10 +657,32 @@ pub struct ChannelDetails {
616657 ///
617658 /// Will be `None` for objects serialized with LDK Node v0.1 and earlier.
618659 pub channel_shutdown_state : Option < ChannelShutdownState > ,
660+ /// The type of on-chain reserve maintained for this channel.
661+ ///
662+ /// See [`ReserveType`] for details on how reserves differ between anchor and legacy channels.
663+ pub reserve_type : ReserveType ,
619664}
620665
621- impl From < LdkChannelDetails > for ChannelDetails {
622- fn from ( value : LdkChannelDetails ) -> Self {
666+ impl ChannelDetails {
667+ pub ( crate ) fn from_ldk (
668+ value : LdkChannelDetails , anchor_channels_config : Option < & AnchorChannelsConfig > ,
669+ ) -> Self {
670+ let reserve_type =
671+ if value. channel_type . as_ref ( ) . is_some_and ( |ct| ct. supports_anchors_zero_fee_htlc_tx ( ) )
672+ {
673+ if let Some ( config) = anchor_channels_config {
674+ if config. trusted_peers_no_reserve . contains ( & value. counterparty . node_id ) {
675+ ReserveType :: TrustedPeersNoReserve
676+ } else {
677+ ReserveType :: Adaptive
678+ }
679+ } else {
680+ ReserveType :: Adaptive
681+ }
682+ } else {
683+ ReserveType :: Legacy
684+ } ;
685+
623686 ChannelDetails {
624687 channel_id : value. channel_id ,
625688 counterparty : ChannelCounterparty {
@@ -664,6 +727,7 @@ impl From<LdkChannelDetails> for ChannelDetails {
664727 . map ( |c| c. into ( ) )
665728 . expect ( "value is set for objects serialized with LDK v0.0.109+" ) ,
666729 channel_shutdown_state : value. channel_shutdown_state ,
730+ reserve_type,
667731 }
668732 }
669733}
0 commit comments