@@ -777,6 +777,24 @@ pub enum BalanceSource {
777
777
Htlc ,
778
778
}
779
779
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
+
780
798
/// Details about the balance(s) available for spending once the channel appears on chain.
781
799
///
782
800
/// See [`ChannelMonitor::get_claimable_balances`] for more details on when these will or will not
@@ -785,21 +803,26 @@ pub enum BalanceSource {
785
803
#[ cfg_attr( test, derive( PartialOrd , Ord ) ) ]
786
804
pub enum Balance {
787
805
/// 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).
790
807
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.
798
814
///
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 ,
803
826
/// The amount of millisatoshis which has been burned to fees from HTLCs which are outbound
804
827
/// from us and are related to a payment which was sent by us. This is the sum of the
805
828
/// millisatoshis part of all HTLCs which are otherwise represented by
@@ -821,7 +844,7 @@ pub enum Balance {
821
844
/// to us and for which we know the preimage. This is the sum of the millisatoshis part of
822
845
/// all HTLCs which would be represented by [`Balance::ContentiousClaimable`] on channel
823
846
/// 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
825
848
/// would otherwise be represented the same.
826
849
///
827
850
/// This amount (rounded up to a whole satoshi value) will not be included in the counterparty's
@@ -915,6 +938,13 @@ pub enum Balance {
915
938
impl Balance {
916
939
/// The amount claimable, in satoshis.
917
940
///
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
+ ///
918
948
/// For outbound payments, this excludes the balance from the possible HTLC timeout.
919
949
///
920
950
/// For forwarded payments, this includes the balance from the possible HTLC timeout as
@@ -928,7 +958,15 @@ impl Balance {
928
958
#[ rustfmt:: skip]
929
959
pub fn claimable_amount_satoshis ( & self ) -> u64 {
930
960
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
+ } ,
932
970
Balance :: ClaimableAwaitingConfirmations { amount_satoshis, .. } |
933
971
Balance :: ContentiousClaimable { amount_satoshis, .. } |
934
972
Balance :: CounterpartyRevokedOutputClaimable { amount_satoshis, .. }
@@ -2671,7 +2709,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
2671
2709
debug_assert ! ( htlc_input_idx_opt. is_some( ) ) ;
2672
2710
BitcoinOutPoint :: new ( * txid, htlc_input_idx_opt. unwrap_or ( 0 ) )
2673
2711
} 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( ) ) ;
2675
2714
BitcoinOutPoint :: new ( * txid, 0 )
2676
2715
}
2677
2716
} else {
@@ -2833,8 +2872,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2833
2872
}
2834
2873
2835
2874
if let Some ( txid) = confirmed_txid {
2875
+ let funding_spent = get_confirmed_funding_scope ! ( us) ;
2836
2876
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) {
2838
2878
// First look for the to_remote output back to us.
2839
2879
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
2840
2880
if let Some ( value) = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
@@ -2855,7 +2895,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2855
2895
// confirmation with the same height or have never met our dust amount.
2856
2896
}
2857
2897
}
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 {
2859
2899
walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, b) | ( a, b. as_ref( ) . map( |b| & * * b) ) ) ) ;
2860
2900
} else {
2861
2901
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> {
2898
2938
}
2899
2939
}
2900
2940
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 ( ) {
2902
2942
walk_htlcs ! ( true , false , holder_commitment_htlcs!( us, CURRENT_WITH_SOURCES ) ) ;
2903
2943
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
2904
2944
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 ( ) ,
2906
2946
confirmation_height : conf_thresh,
2907
2947
source : BalanceSource :: HolderForceClosed ,
2908
2948
} ) ;
2909
2949
}
2910
2950
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 {
2912
2952
if txid == prev_holder_commitment_tx. trust ( ) . txid ( ) {
2913
2953
walk_htlcs ! ( true , false , holder_commitment_htlcs!( us, PREV_WITH_SOURCES ) . unwrap( ) ) ;
2914
2954
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
@@ -2927,7 +2967,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2927
2967
// neither us nor our counterparty misbehaved. At worst we've under-estimated
2928
2968
// the amount we can claim as we'll punish a misbehaving counterparty.
2929
2969
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 ( ) ,
2931
2971
confirmation_height : conf_thresh,
2932
2972
source : BalanceSource :: CoopClose ,
2933
2973
} ) ;
@@ -2939,6 +2979,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2939
2979
let mut outbound_forwarded_htlc_rounded_msat = 0 ;
2940
2980
let mut inbound_claiming_htlc_rounded_msat = 0 ;
2941
2981
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.
2942
2984
for ( htlc, source) in holder_commitment_htlcs ! ( us, CURRENT_WITH_SOURCES ) {
2943
2985
let rounded_value_msat = if htlc. transaction_output_index . is_none ( ) {
2944
2986
htlc. amount_msat
@@ -2980,16 +3022,40 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2980
3022
}
2981
3023
}
2982
3024
}
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" ) ;
2984
3056
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,
2993
3059
outbound_payment_htlc_rounded_msat,
2994
3060
outbound_forwarded_htlc_rounded_msat,
2995
3061
inbound_claiming_htlc_rounded_msat,
0 commit comments