@@ -664,6 +664,10 @@ pub enum Balance {
664
664
claimable_height : u32 ,
665
665
/// The payment hash whose preimage our counterparty needs to claim this HTLC.
666
666
payment_hash : PaymentHash ,
667
+ /// Whether this HTLC represents a payment which was sent outbound from us. Otherwise it
668
+ /// represents an HTLC which was forwarded (and should, thus, have a corresponding inbound
669
+ /// edge on another channel).
670
+ outbound_payment : bool ,
667
671
} ,
668
672
/// HTLCs which we received from our counterparty which are claimable with a preimage which we
669
673
/// do not currently have. This will only be claimable if we receive the preimage from the node
@@ -693,9 +697,15 @@ pub enum Balance {
693
697
}
694
698
695
699
impl Balance {
696
- /// The amount claimable, in satoshis. This excludes balances that we are unsure if we are able
697
- /// to claim, this is because we are waiting for a preimage or for a timeout to expire. For more
698
- /// information on these balances see [`Balance::MaybeTimeoutClaimableHTLC`] and
700
+ /// The amount claimable, in satoshis.
701
+ ///
702
+ /// For outbound payments, this excludes the balance from the possible HTLC timeout.
703
+ ///
704
+ /// For forwarded payments, this includes the balance from the possible HTLC timeout as
705
+ /// (to be conservative) that balance does not include routing fees we'd earn if we'd claim
706
+ /// the balance from a preimage in a successful forward.
707
+ ///
708
+ /// For more information on these balances see [`Balance::MaybeTimeoutClaimableHTLC`] and
699
709
/// [`Balance::MaybePreimageClaimableHTLC`].
700
710
///
701
711
/// On-chain fees required to claim the balance are not included in this amount.
@@ -706,9 +716,9 @@ impl Balance {
706
716
Balance :: ContentiousClaimable { amount_satoshis, .. } |
707
717
Balance :: CounterpartyRevokedOutputClaimable { amount_satoshis, .. }
708
718
=> * amount_satoshis,
709
- Balance :: MaybeTimeoutClaimableHTLC { .. } |
710
- Balance :: MaybePreimageClaimableHTLC { .. }
711
- => 0 ,
719
+ Balance :: MaybeTimeoutClaimableHTLC { amount_satoshis , outbound_payment , .. }
720
+ => if * outbound_payment { 0 } else { * amount_satoshis } ,
721
+ Balance :: MaybePreimageClaimableHTLC { .. } => 0 ,
712
722
}
713
723
}
714
724
}
@@ -1960,9 +1970,10 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
1960
1970
impl < Signer : EcdsaChannelSigner > ChannelMonitorImpl < Signer > {
1961
1971
/// Helper for get_claimable_balances which does the work for an individual HTLC, generating up
1962
1972
/// to one `Balance` for the HTLC.
1963
- fn get_htlc_balance ( & self , htlc : & HTLCOutputInCommitment , holder_commitment : bool ,
1964
- counterparty_revoked_commitment : bool , confirmed_txid : Option < Txid > )
1965
- -> Option < Balance > {
1973
+ fn get_htlc_balance ( & self , htlc : & HTLCOutputInCommitment , source : Option < & HTLCSource > ,
1974
+ holder_commitment : bool , counterparty_revoked_commitment : bool ,
1975
+ confirmed_txid : Option < Txid >
1976
+ ) -> Option < Balance > {
1966
1977
let htlc_commitment_tx_output_idx =
1967
1978
if let Some ( v) = htlc. transaction_output_index { v } else { return None ; } ;
1968
1979
@@ -2099,10 +2110,19 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
2099
2110
confirmation_height : conf_thresh,
2100
2111
} ) ;
2101
2112
} else {
2113
+ let outbound_payment = match source {
2114
+ None => {
2115
+ debug_assert ! ( false , "Outbound HTLCs should have a source" ) ;
2116
+ true
2117
+ } ,
2118
+ Some ( & HTLCSource :: PreviousHopData ( _) ) => false ,
2119
+ Some ( & HTLCSource :: OutboundRoute { .. } ) => true ,
2120
+ } ;
2102
2121
return Some ( Balance :: MaybeTimeoutClaimableHTLC {
2103
2122
amount_satoshis : htlc. amount_msat / 1000 ,
2104
2123
claimable_height : htlc. cltv_expiry ,
2105
2124
payment_hash : htlc. payment_hash ,
2125
+ outbound_payment,
2106
2126
} ) ;
2107
2127
}
2108
2128
} else if let Some ( payment_preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
@@ -2175,10 +2195,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2175
2195
2176
2196
macro_rules! walk_htlcs {
2177
2197
( $holder_commitment: expr, $counterparty_revoked_commitment: expr, $htlc_iter: expr) => {
2178
- for htlc in $htlc_iter {
2198
+ for ( htlc, source ) in $htlc_iter {
2179
2199
if htlc. transaction_output_index. is_some( ) {
2180
2200
2181
- if let Some ( bal) = us. get_htlc_balance( htlc, $holder_commitment, $counterparty_revoked_commitment, confirmed_txid) {
2201
+ if let Some ( bal) = us. get_htlc_balance(
2202
+ htlc, source, $holder_commitment, $counterparty_revoked_commitment, confirmed_txid
2203
+ ) {
2182
2204
res. push( bal) ;
2183
2205
}
2184
2206
}
@@ -2209,9 +2231,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2209
2231
}
2210
2232
}
2211
2233
if Some ( txid) == us. current_counterparty_commitment_txid || Some ( txid) == us. prev_counterparty_commitment_txid {
2212
- walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, _ ) | a ) ) ;
2234
+ walk_htlcs ! ( false , false , counterparty_tx_htlcs. iter( ) . map( |( a, b ) | ( a , b . as_ref ( ) . map ( |b| & * * b ) ) ) ) ;
2213
2235
} else {
2214
- walk_htlcs ! ( false , true , counterparty_tx_htlcs. iter( ) . map( |( a, _ ) | a ) ) ;
2236
+ walk_htlcs ! ( false , true , counterparty_tx_htlcs. iter( ) . map( |( a, b ) | ( a , b . as_ref ( ) . map ( |b| & * * b ) ) ) ) ;
2215
2237
// The counterparty broadcasted a revoked state!
2216
2238
// Look for any StaticOutputs first, generating claimable balances for those.
2217
2239
// If any match the confirmed counterparty revoked to_self output, skip
@@ -2251,7 +2273,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2251
2273
}
2252
2274
found_commitment_tx = true ;
2253
2275
} else if txid == us. current_holder_commitment_tx . txid {
2254
- walk_htlcs ! ( true , false , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, _ ) | a ) ) ;
2276
+ walk_htlcs ! ( true , false , us. current_holder_commitment_tx. htlc_outputs. iter( ) . map( |( a, _, c ) | ( a , c . as_ref ( ) ) ) ) ;
2255
2277
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
2256
2278
res. push ( Balance :: ClaimableAwaitingConfirmations {
2257
2279
amount_satoshis : us. current_holder_commitment_tx . to_self_value_sat ,
@@ -2261,7 +2283,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2261
2283
found_commitment_tx = true ;
2262
2284
} else if let Some ( prev_commitment) = & us. prev_holder_signed_commitment_tx {
2263
2285
if txid == prev_commitment. txid {
2264
- walk_htlcs ! ( true , false , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, _ ) | a ) ) ;
2286
+ walk_htlcs ! ( true , false , prev_commitment. htlc_outputs. iter( ) . map( |( a, _, c ) | ( a , c . as_ref ( ) ) ) ) ;
2265
2287
if let Some ( conf_thresh) = pending_commitment_tx_conf_thresh {
2266
2288
res. push ( Balance :: ClaimableAwaitingConfirmations {
2267
2289
amount_satoshis : prev_commitment. to_self_value_sat ,
@@ -2284,13 +2306,22 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
2284
2306
}
2285
2307
} else {
2286
2308
let mut claimable_inbound_htlc_value_sat = 0 ;
2287
- for ( htlc, _, _ ) in us. current_holder_commitment_tx . htlc_outputs . iter ( ) {
2309
+ for ( htlc, _, source ) in us. current_holder_commitment_tx . htlc_outputs . iter ( ) {
2288
2310
if htlc. transaction_output_index . is_none ( ) { continue ; }
2289
2311
if htlc. offered {
2312
+ let outbound_payment = match source {
2313
+ None => {
2314
+ debug_assert ! ( false , "Outbound HTLCs should have a source" ) ;
2315
+ true
2316
+ } ,
2317
+ Some ( HTLCSource :: PreviousHopData ( _) ) => false ,
2318
+ Some ( HTLCSource :: OutboundRoute { .. } ) => true ,
2319
+ } ;
2290
2320
res. push ( Balance :: MaybeTimeoutClaimableHTLC {
2291
2321
amount_satoshis : htlc. amount_msat / 1000 ,
2292
2322
claimable_height : htlc. cltv_expiry ,
2293
2323
payment_hash : htlc. payment_hash ,
2324
+ outbound_payment,
2294
2325
} ) ;
2295
2326
} else if us. payment_preimages . get ( & htlc. payment_hash ) . is_some ( ) {
2296
2327
claimable_inbound_htlc_value_sat += htlc. amount_msat / 1000 ;
0 commit comments