@@ -34,7 +34,7 @@ use lightning_net_tokio::SocketDescriptor;
3434
3535use crate :: chain:: bitcoind:: UtxoSourceClient ;
3636use crate :: chain:: ChainSource ;
37- use crate :: config:: ChannelConfig ;
37+ use crate :: config:: { AnchorChannelsConfig , ChannelConfig } ;
3838use crate :: data_store:: DataStore ;
3939use crate :: fee_estimator:: OnchainFeeEstimator ;
4040use crate :: ffi:: maybe_wrap;
@@ -412,6 +412,47 @@ pub struct ChannelCounterparty {
412412 pub outbound_htlc_maximum_msat : Option < u64 > ,
413413}
414414
415+ /// Describes the reserve behavior of a channel based on its type and trust configuration.
416+ ///
417+ /// This captures the combination of the channel's on-chain construction (anchor outputs vs legacy
418+ /// static_remote_key) and whether the counterparty is in our trusted peers list. It tells the
419+ /// user what reserve obligations exist for this channel without exposing internal protocol details.
420+ ///
421+ /// See [`AnchorChannelsConfig`] for how reserve behavior is configured.
422+ ///
423+ /// [`AnchorChannelsConfig`]: crate::config::AnchorChannelsConfig
424+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
425+ #[ cfg_attr( feature = "uniffi" , derive( uniffi:: Enum ) ) ]
426+ pub enum ReserveType {
427+ /// An anchor outputs channel where we maintain a per-channel on-chain reserve for fee
428+ /// bumping force-close transactions.
429+ ///
430+ /// Anchor channels allow either party to fee-bump commitment transactions via CPFP
431+ /// at broadcast time. Because the pre-signed commitment fee may be insufficient under
432+ /// current fee conditions, the broadcaster must supply additional funds (hence adaptive)
433+ /// through an anchor output spend. The reserve ensures sufficient on-chain funds are
434+ /// available to cover this.
435+ ///
436+ /// This is the default for anchor channels when the counterparty is not in
437+ /// [`trusted_peers_no_reserve`].
438+ ///
439+ /// [`trusted_peers_no_reserve`]: crate::config::AnchorChannelsConfig::trusted_peers_no_reserve
440+ Adaptive ,
441+ /// An anchor outputs channel where we do not maintain any reserve, because the counterparty
442+ /// is in our [`trusted_peers_no_reserve`] list.
443+ ///
444+ /// In this mode, we trust the counterparty to broadcast a valid commitment transaction on
445+ /// our behalf and do not set aside funds for fee bumping.
446+ ///
447+ /// [`trusted_peers_no_reserve`]: crate::config::AnchorChannelsConfig::trusted_peers_no_reserve
448+ TrustedPeersNoReserve ,
449+ /// A legacy (pre-anchor) channel using only `option_static_remotekey`.
450+ ///
451+ /// These channels do not use anchor outputs and therefore do not require an on-chain reserve
452+ /// for fee bumping. Commitment transaction fees are pre-committed at channel open time.
453+ Legacy ,
454+ }
455+
415456/// Details of a channel as returned by [`Node::list_channels`].
416457///
417458/// When a channel is spliced, most fields continue to refer to the original pre-splice channel
@@ -576,10 +617,32 @@ pub struct ChannelDetails {
576617 ///
577618 /// Will be `None` for objects serialized with LDK Node v0.1 and earlier.
578619 pub channel_shutdown_state : Option < ChannelShutdownState > ,
620+ /// The type of on-chain reserve maintained for this channel.
621+ ///
622+ /// See [`ReserveType`] for details on how reserves differ between anchor and legacy channels.
623+ pub reserve_type : ReserveType ,
579624}
580625
581- impl From < LdkChannelDetails > for ChannelDetails {
582- fn from ( value : LdkChannelDetails ) -> Self {
626+ impl ChannelDetails {
627+ pub ( crate ) fn from_ldk (
628+ value : LdkChannelDetails , anchor_channels_config : Option < & AnchorChannelsConfig > ,
629+ ) -> Self {
630+ let reserve_type =
631+ if value. channel_type . as_ref ( ) . is_some_and ( |ct| ct. supports_anchors_zero_fee_htlc_tx ( ) )
632+ {
633+ if let Some ( config) = anchor_channels_config {
634+ if config. trusted_peers_no_reserve . contains ( & value. counterparty . node_id ) {
635+ ReserveType :: TrustedPeersNoReserve
636+ } else {
637+ ReserveType :: Adaptive
638+ }
639+ } else {
640+ ReserveType :: Adaptive
641+ }
642+ } else {
643+ ReserveType :: Legacy
644+ } ;
645+
583646 ChannelDetails {
584647 channel_id : value. channel_id ,
585648 counterparty : ChannelCounterparty {
@@ -621,6 +684,7 @@ impl From<LdkChannelDetails> for ChannelDetails {
621684 // unwrap safety: `config` is only `None` for LDK objects serialized prior to 0.0.109.
622685 config : value. config . map ( |c| c. into ( ) ) . unwrap ( ) ,
623686 channel_shutdown_state : value. channel_shutdown_state ,
687+ reserve_type,
624688 }
625689 }
626690}
0 commit comments