@@ -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
@@ -928,7 +951,18 @@ impl Balance {
928
951
#[ rustfmt:: skip]
929
952
pub fn claimable_amount_satoshis ( & self ) -> u64 {
930
953
match self {
931
- Balance :: ClaimableOnChannelClose { amount_satoshis, .. } |
954
+ Balance :: ClaimableOnChannelClose {
955
+ balance_candidates, confirmed_balance_candidate_index, ..
956
+ } => {
957
+ // If we have multiple candidates due to a splice, and one of the splice
958
+ // transactions has confirmed, report the corresponding balance. Otherwise, the
959
+ // splice is unconfirmed, so report the balance for the latest negotiated attempt.
960
+ if confirmed_balance_candidate_index != 0 {
961
+ balance_candidates[ * confirmed_balance_candidate_index] . amount_satoshis
962
+ } else {
963
+ balance_candidates. last ( ) . map ( |balance| balance. amount_satoshis ) . unwrap_or ( 0 )
964
+ }
965
+ } ,
932
966
Balance :: ClaimableAwaitingConfirmations { amount_satoshis, .. } |
933
967
Balance :: ContentiousClaimable { amount_satoshis, .. } |
934
968
Balance :: CounterpartyRevokedOutputClaimable { amount_satoshis, .. }
@@ -2671,7 +2705,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
2671
2705
debug_assert ! ( htlc_input_idx_opt. is_some( ) ) ;
2672
2706
BitcoinOutPoint :: new ( * txid, htlc_input_idx_opt. unwrap_or ( 0 ) )
2673
2707
} else {
2674
- debug_assert ! ( !self . channel_type_features( ) . supports_anchors_zero_fee_htlc_tx( ) ) ;
2708
+ let funding = get_confirmed_funding_scope ! ( self ) ;
2709
+ debug_assert ! ( !funding. channel_type_features( ) . supports_anchors_zero_fee_htlc_tx( ) ) ;
2675
2710
BitcoinOutPoint :: new ( * txid, 0 )
2676
2711
}
2677
2712
} else {
@@ -2833,8 +2868,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2833
2868
}
2834
2869
2835
2870
if let Some ( txid) = confirmed_txid {
2871
+ let funding_spent = get_confirmed_funding_scope ! ( us) ;
2836
2872
let mut found_commitment_tx = false ;
2837
- if let Some ( counterparty_tx_htlcs) = us . funding . counterparty_claimable_outpoints . get ( & txid) {
2873
+ if let Some ( counterparty_tx_htlcs) = funding_spent . counterparty_claimable_outpoints . get ( & txid) {
2838
2874
// First look for the to_remote output back to us.
2839
2875
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
2840
2876
if let Some ( value) = us. onchain_events_awaiting_threshold_conf . iter ( ) . find_map ( |event| {
@@ -2855,7 +2891,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2855
2891
// confirmation with the same height or have never met our dust amount.
2856
2892
}
2857
2893
}
2858
- if Some ( txid) == us . funding . current_counterparty_commitment_txid || Some ( txid) == us . funding . prev_counterparty_commitment_txid {
2894
+ if Some ( txid) == funding_spent . current_counterparty_commitment_txid || Some ( txid) == funding_spent . prev_counterparty_commitment_txid {
2859
2895
walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, b) | ( a, b. as_ref( ) . map( |b| & * * b) ) ) ) ;
2860
2896
} else {
2861
2897
walk_htlcs ! ( false , true , counterparty_tx_htlcs. iter( ) . map( |( a, b) | ( a, b. as_ref( ) . map( |b| & * * b) ) ) ) ;
@@ -2898,17 +2934,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2898
2934
}
2899
2935
}
2900
2936
found_commitment_tx = true ;
2901
- } else if txid == us . funding . current_holder_commitment_tx . trust ( ) . txid ( ) {
2937
+ } else if txid == funding_spent . current_holder_commitment_tx . trust ( ) . txid ( ) {
2902
2938
walk_htlcs ! ( true , false , holder_commitment_htlcs!( us, CURRENT_WITH_SOURCES ) ) ;
2903
2939
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
2904
2940
res. push ( Balance :: ClaimableAwaitingConfirmations {
2905
- amount_satoshis : us . funding . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
2941
+ amount_satoshis : funding_spent . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
2906
2942
confirmation_height : conf_thresh,
2907
2943
source : BalanceSource :: HolderForceClosed ,
2908
2944
} ) ;
2909
2945
}
2910
2946
found_commitment_tx = true ;
2911
- } else if let Some ( prev_holder_commitment_tx) = & us . funding . prev_holder_commitment_tx {
2947
+ } else if let Some ( prev_holder_commitment_tx) = & funding_spent . prev_holder_commitment_tx {
2912
2948
if txid == prev_holder_commitment_tx. trust ( ) . txid ( ) {
2913
2949
walk_htlcs ! ( true , false , holder_commitment_htlcs!( us, PREV_WITH_SOURCES ) . unwrap( ) ) ;
2914
2950
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
@@ -2927,7 +2963,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2927
2963
// neither us nor our counterparty misbehaved. At worst we've under-estimated
2928
2964
// the amount we can claim as we'll punish a misbehaving counterparty.
2929
2965
res. push ( Balance :: ClaimableAwaitingConfirmations {
2930
- amount_satoshis : us . funding . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
2966
+ amount_satoshis : funding_spent . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ,
2931
2967
confirmation_height : conf_thresh,
2932
2968
source : BalanceSource :: CoopClose ,
2933
2969
} ) ;
@@ -2939,6 +2975,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2939
2975
let mut outbound_forwarded_htlc_rounded_msat = 0 ;
2940
2976
let mut inbound_claiming_htlc_rounded_msat = 0 ;
2941
2977
let mut inbound_htlc_rounded_msat = 0 ;
2978
+ // We share the same set of HTLCs across all scopes, so we don't need to check the other
2979
+ // scopes as it'd be redundant.
2942
2980
for ( htlc, source) in holder_commitment_htlcs ! ( us, CURRENT_WITH_SOURCES ) {
2943
2981
let rounded_value_msat = if htlc. transaction_output_index . is_none ( ) {
2944
2982
htlc. amount_msat
@@ -2980,16 +3018,40 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2980
3018
}
2981
3019
}
2982
3020
}
2983
- let to_self_value_sat = us. funding . current_holder_commitment_tx . to_broadcaster_value_sat ( ) ;
3021
+ let balance_candidates = core:: iter:: once ( & us. funding )
3022
+ . chain ( us. pending_funding . iter ( ) )
3023
+ . map ( |funding| {
3024
+ let to_self_value_sat = funding. current_holder_commitment_tx . to_broadcaster_value_sat ( ) ;
3025
+ // In addition to `commit_tx_fee_sat`, this can also include dust HTLCs, any
3026
+ // elided anchors, and the total msat amount rounded down from non-dust HTLCs.
3027
+ let transaction_fee_satoshis = if us. holder_pays_commitment_tx_fee . unwrap_or ( true ) {
3028
+ let transaction = & funding. current_holder_commitment_tx . trust ( ) . built_transaction ( ) . transaction ;
3029
+ let output_value_sat: u64 = transaction. output . iter ( ) . map ( |txout| txout. value . to_sat ( ) ) . sum ( ) ;
3030
+ funding. channel_parameters . channel_value_satoshis - output_value_sat
3031
+ } else {
3032
+ 0
3033
+ } ;
3034
+ HolderCommitmentTransactionBalance {
3035
+ amount_satoshis : to_self_value_sat + claimable_inbound_htlc_value_sat,
3036
+ transaction_fee_satoshis,
3037
+ }
3038
+ } )
3039
+ . collect ( ) ;
3040
+ let confirmed_balance_candidate_index = core:: iter:: once ( & us. funding )
3041
+ . chain ( us. pending_funding . iter ( ) )
3042
+ . enumerate ( )
3043
+ . find ( |( _, funding) | {
3044
+ us. alternative_funding_confirmed
3045
+ . map ( |( funding_txid_confirmed, _) | funding. funding_txid ( ) == funding_txid_confirmed)
3046
+ // If `alternative_funding_confirmed` is not set, we can assume the current
3047
+ // funding is confirmed.
3048
+ . unwrap_or ( true )
3049
+ } )
3050
+ . map ( |( idx, _) | idx)
3051
+ . expect ( "FundingScope for confirmed alternative funding must exist" ) ;
2984
3052
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 } ,
3053
+ balance_candidates,
3054
+ confirmed_balance_candidate_index,
2993
3055
outbound_payment_htlc_rounded_msat,
2994
3056
outbound_forwarded_htlc_rounded_msat,
2995
3057
inbound_claiming_htlc_rounded_msat,
0 commit comments