@@ -777,6 +777,24 @@ pub enum BalanceSource {
777777 Htlc ,
778778}
779779
780+ /// The claimable balance of a holder commitment transaction that has yet to be broadcast.
781+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
782+ #[ cfg_attr( test, derive( PartialOrd , Ord ) ) ]
783+ pub struct HolderCommitmentTransactionBalance {
784+ /// The amount available to claim, in satoshis, excluding the on-chain fees which will be
785+ /// required to do so.
786+ pub amount_satoshis : u64 ,
787+ /// The transaction fee we pay for the closing commitment transaction. This amount is not
788+ /// included in the [`HolderCommitmentTransactionBalance::amount_satoshis`] value.
789+ /// This amount includes the sum of dust HTLCs on the commitment transaction, any elided anchors,
790+ /// as well as the sum of msat amounts rounded down from non-dust HTLCs.
791+ ///
792+ /// Note that if this channel is inbound (and thus our counterparty pays the commitment
793+ /// transaction fee) this value will be zero. For [`ChannelMonitor`]s created prior to LDK
794+ /// 0.0.124, the channel is always treated as outbound (and thus this value is never zero).
795+ pub transaction_fee_satoshis : u64 ,
796+ }
797+
780798/// Details about the balance(s) available for spending once the channel appears on chain.
781799///
782800/// See [`ChannelMonitor::get_claimable_balances`] for more details on when these will or will not
@@ -785,21 +803,26 @@ pub enum BalanceSource {
785803#[ cfg_attr( test, derive( PartialOrd , Ord ) ) ]
786804pub enum Balance {
787805 /// The channel is not yet closed (or the commitment or closing transaction has not yet
788- /// appeared in a block). The given balance is claimable (less on-chain fees) if the channel is
789- /// force-closed now.
806+ /// appeared in a block).
790807 ClaimableOnChannelClose {
791- /// The amount available to claim, in satoshis, excluding the on-chain fees which will be
792- /// required to do so.
793- amount_satoshis : u64 ,
794- /// The transaction fee we pay for the closing commitment transaction. This amount is not
795- /// included in the [`Balance::ClaimableOnChannelClose::amount_satoshis`] value.
796- /// This amount includes the sum of dust HTLCs on the commitment transaction, any elided anchors,
797- /// as well as the sum of msat amounts rounded down from non-dust HTLCs.
808+ /// A list of balance candidates based on the latest set of valid holder commitment
809+ /// transactions that can hit the chain. Typically, a channel only has one valid holder
810+ /// commitment transaction that spends the current funding output. As soon as a channel is
811+ /// spliced, an alternative holder commitment transaction exists spending the new funding
812+ /// output. More alternative holder commitment transactions can exist as the splice remains
813+ /// pending and RBF attempts are made.
798814 ///
799- /// Note that if this channel is inbound (and thus our counterparty pays the commitment
800- /// transaction fee) this value will be zero. For [`ChannelMonitor`]s created prior to LDK
801- /// 0.0.124, the channel is always treated as outbound (and thus this value is never zero).
802- transaction_fee_satoshis : u64 ,
815+ /// The candidates are sorted by the order in which the holder commitment transactions were
816+ /// negotiated. When only one candidate exists, the channel does not have a splice pending.
817+ /// When multiple candidates exist, the last one reflects the balance of the
818+ /// latest splice/RBF attempt, while the first reflects the balance prior to the splice
819+ /// occurring.
820+ balance_candidates : Vec < HolderCommitmentTransactionBalance > ,
821+ /// The index within [`Balance::ClaimableOnChannelClose::balance_candidates`] for the
822+ /// balance according to the current onchain state of the channel. This can be helpful when
823+ /// wanting to determine the claimable amount when the holder commitment transaction for the
824+ /// current funding transaction is broadcast and/or confirms.
825+ confirmed_balance_candidate_index : usize ,
803826 /// The amount of millisatoshis which has been burned to fees from HTLCs which are outbound
804827 /// from us and are related to a payment which was sent by us. This is the sum of the
805828 /// millisatoshis part of all HTLCs which are otherwise represented by
@@ -821,7 +844,7 @@ pub enum Balance {
821844 /// to us and for which we know the preimage. This is the sum of the millisatoshis part of
822845 /// all HTLCs which would be represented by [`Balance::ContentiousClaimable`] on channel
823846 /// close, but whose current value is included in
824- /// [`Balance::ClaimableOnChannelClose ::amount_satoshis`], as well as any dust HTLCs which
847+ /// [`HolderCommitmentTransactionBalance ::amount_satoshis`], as well as any dust HTLCs which
825848 /// would otherwise be represented the same.
826849 ///
827850 /// This amount (rounded up to a whole satoshi value) will not be included in the counterparty's
@@ -915,6 +938,13 @@ pub enum Balance {
915938impl Balance {
916939 /// The amount claimable, in satoshis.
917940 ///
941+ /// When the channel has yet to close, this returns the balance we expect to claim from the
942+ /// channel. This may change throughout the lifetime of the channel due to payments, but also
943+ /// due to splicing. If there's a pending splice, this will return the balance we expect to have
944+ /// assuming the latest negotiated splice confirms. However, if one of the negotiated splice
945+ /// transactions has already confirmed but is not yet locked, this reports the corresponding
946+ /// balance for said splice transaction instead.
947+ ///
918948 /// For outbound payments, this excludes the balance from the possible HTLC timeout.
919949 ///
920950 /// For forwarded payments, this includes the balance from the possible HTLC timeout as
@@ -928,7 +958,15 @@ impl Balance {
928958 #[ rustfmt:: skip]
929959 pub fn claimable_amount_satoshis ( & self ) -> u64 {
930960 match self {
931- Balance :: ClaimableOnChannelClose { amount_satoshis, .. } |
961+ Balance :: ClaimableOnChannelClose {
962+ balance_candidates, confirmed_balance_candidate_index, ..
963+ } => {
964+ if * confirmed_balance_candidate_index != 0 {
965+ balance_candidates[ * confirmed_balance_candidate_index] . amount_satoshis
966+ } else {
967+ balance_candidates. last ( ) . map ( |balance| balance. amount_satoshis ) . unwrap_or ( 0 )
968+ }
969+ } ,
932970 Balance :: ClaimableAwaitingConfirmations { amount_satoshis, .. } |
933971 Balance :: ContentiousClaimable { amount_satoshis, .. } |
934972 Balance :: CounterpartyRevokedOutputClaimable { amount_satoshis, .. }
@@ -2671,7 +2709,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
26712709 debug_assert ! ( htlc_input_idx_opt. is_some( ) ) ;
26722710 BitcoinOutPoint :: new ( * txid, htlc_input_idx_opt. unwrap_or ( 0 ) )
26732711 } else {
2674- debug_assert ! ( !self . channel_type_features( ) . supports_anchors_zero_fee_htlc_tx( ) ) ;
2712+ let funding = get_confirmed_funding_scope ! ( self ) ;
2713+ debug_assert ! ( !funding. channel_type_features( ) . supports_anchors_zero_fee_htlc_tx( ) ) ;
26752714 BitcoinOutPoint :: new ( * txid, 0 )
26762715 }
26772716 } else {
@@ -2833,8 +2872,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
28332872 }
28342873
28352874 if let Some ( txid) = confirmed_txid {
2875+ let funding_spent = get_confirmed_funding_scope ! ( us) ;
28362876 let mut found_commitment_tx = false ;
2837- if let Some ( counterparty_tx_htlcs) = us . funding . counterparty_claimable_outpoints . get ( & txid) {
2877+ if let Some ( counterparty_tx_htlcs) = funding_spent . counterparty_claimable_outpoints . get ( & txid) {
28382878 // First look for the to_remote output back to us.
28392879 if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
28402880 if let Some ( value) = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
@@ -2855,7 +2895,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
28552895 // confirmation with the same height or have never met our dust amount.
28562896 }
28572897 }
2858- if Some ( txid) == us . funding . current_counterparty_commitment_txid || Some ( txid) == us . funding . prev_counterparty_commitment_txid {
2898+ if Some ( txid) == funding_spent . current_counterparty_commitment_txid || Some ( txid) == funding_spent . prev_counterparty_commitment_txid {
28592899 walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, b) | ( a, b. as_ref( ) . map( |b| & * * b) ) ) ) ;
28602900 } else {
28612901 walk_htlcs ! ( false , true , counterparty_tx_htlcs. iter( ) . map( |( a, b) | ( a, b. as_ref( ) . map( |b| & * * b) ) ) ) ;
@@ -2898,17 +2938,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
28982938 }
28992939 }
29002940 found_commitment_tx = true ;
2901- } else if txid == us . funding . current_holder_commitment_tx . trust ( ) . txid ( ) {
2941+ } else if txid == funding_spent . current_holder_commitment_tx . trust ( ) . txid ( ) {
29022942 walk_htlcs ! ( true , false , holder_commitment_htlcs!( us, CURRENT_WITH_SOURCES ) ) ;
29032943 if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
29042944 res. push ( Balance :: ClaimableAwaitingConfirmations {
2905- amount_satoshis : us . funding . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
2945+ amount_satoshis : funding_spent . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
29062946 confirmation_height : conf_thresh,
29072947 source : BalanceSource :: HolderForceClosed ,
29082948 } ) ;
29092949 }
29102950 found_commitment_tx = true ;
2911- } else if let Some ( prev_holder_commitment_tx) = & us . funding . prev_holder_commitment_tx {
2951+ } else if let Some ( prev_holder_commitment_tx) = & funding_spent . prev_holder_commitment_tx {
29122952 if txid == prev_holder_commitment_tx. trust ( ) . txid ( ) {
29132953 walk_htlcs ! ( true , false , holder_commitment_htlcs!( us, PREV_WITH_SOURCES ) . unwrap( ) ) ;
29142954 if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
@@ -2927,7 +2967,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
29272967 // neither us nor our counterparty misbehaved. At worst we've under-estimated
29282968 // the amount we can claim as we'll punish a misbehaving counterparty.
29292969 res. push ( Balance :: ClaimableAwaitingConfirmations {
2930- amount_satoshis : us . funding . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
2970+ amount_satoshis : funding_spent . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
29312971 confirmation_height : conf_thresh,
29322972 source : BalanceSource :: CoopClose ,
29332973 } ) ;
@@ -2939,6 +2979,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
29392979 let mut outbound_forwarded_htlc_rounded_msat = 0 ;
29402980 let mut inbound_claiming_htlc_rounded_msat = 0 ;
29412981 let mut inbound_htlc_rounded_msat = 0 ;
2982+ // We share the same set of HTLCs across all scopes, so we don't need to check the other
2983+ // scopes as it'd be redundant.
29422984 for ( htlc, source) in holder_commitment_htlcs ! ( us, CURRENT_WITH_SOURCES ) {
29432985 let rounded_value_msat = if htlc. transaction_output_index . is_none ( ) {
29442986 htlc. amount_msat
@@ -2980,16 +3022,40 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
29803022 }
29813023 }
29823024 }
2983- let to_self_value_sat = us. funding . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ;
3025+ let balance_candidates = core:: iter:: once ( & us. funding )
3026+ . chain ( us. pending_funding . iter ( ) )
3027+ . map ( |funding| {
3028+ let to_self_value_sat = funding. current_holder_commitment_tx . to_broadcaster_value_sat ( ) ;
3029+ // In addition to `commit_tx_fee_sat`, this can also include dust HTLCs, any
3030+ // elided anchors, and the total msat amount rounded down from non-dust HTLCs.
3031+ let transaction_fee_satoshis = if us. holder_pays_commitment_tx_fee . unwrap_or ( true ) {
3032+ let transaction = & funding. current_holder_commitment_tx . trust ( ) . built_transaction ( ) . transaction ;
3033+ let output_value_sat: u64 = transaction. output . iter ( ) . map ( |txout| txout. value . to_sat ( ) ) . sum ( ) ;
3034+ funding. channel_parameters . channel_value_satoshis - output_value_sat
3035+ } else {
3036+ 0
3037+ } ;
3038+ HolderCommitmentTransactionBalance {
3039+ amount_satoshis : to_self_value_sat + claimable_inbound_htlc_value_sat,
3040+ transaction_fee_satoshis,
3041+ }
3042+ } )
3043+ . collect ( ) ;
3044+ let confirmed_balance_candidate_index = core:: iter:: once ( & us. funding )
3045+ . chain ( us. pending_funding . iter ( ) )
3046+ . enumerate ( )
3047+ . find ( |( _, funding) | {
3048+ us. alternative_funding_confirmed
3049+ . map ( |( funding_txid_confirmed, _) | funding. funding_txid ( ) == funding_txid_confirmed)
3050+ // If `alternative_funding_confirmed` is not set, we can assume the current
3051+ // funding is confirmed.
3052+ . unwrap_or ( true )
3053+ } )
3054+ . map ( |( idx, _) | idx)
3055+ . expect ( "We must have one FundingScope that is confirmed" ) ;
29843056 res. push ( Balance :: ClaimableOnChannelClose {
2985- amount_satoshis : to_self_value_sat + claimable_inbound_htlc_value_sat,
2986- // In addition to `commit_tx_fee_sat`, this can also include dust HTLCs, any elided anchors,
2987- // and the total msat amount rounded down from non-dust HTLCs
2988- transaction_fee_satoshis : if us. holder_pays_commitment_tx_fee . unwrap_or ( true ) {
2989- let transaction = & us. funding . current_holder_commitment_tx . trust ( ) . built_transaction ( ) . transaction ;
2990- let output_value_sat: u64 = transaction. output . iter ( ) . map ( |txout| txout. value . to_sat ( ) ) . sum ( ) ;
2991- us. funding . channel_parameters . channel_value_satoshis - output_value_sat
2992- } else { 0 } ,
3057+ balance_candidates,
3058+ confirmed_balance_candidate_index,
29933059 outbound_payment_htlc_rounded_msat,
29943060 outbound_forwarded_htlc_rounded_msat,
29953061 inbound_claiming_htlc_rounded_msat,
0 commit comments