@@ -2145,6 +2145,100 @@ fn test_revoked_counterparty_aggregated_claims() {
2145
2145
do_test_revoked_counterparty_aggregated_claims ( true ) ;
2146
2146
}
2147
2147
2148
+ fn do_test_claimable_balance_correct_while_payment_pending ( outbound_payment : bool , anchors : bool ) {
2149
+ // Previously when a user fetched their balances via `get_claimable_balances` after forwarding a
2150
+ // payment, but before it cleared, and summed up their balance using `Balance::claimable_amount_satoshis`
2151
+ // neither the value of preimage claimable HTLC nor the timeout claimable HTLC would be included.
2152
+ // This was incorrect as exactly one of these outcomes is true. This has been fixed by including the
2153
+ // timeout claimable HTLC value in the balance as this excludes the routing fees and is the more
2154
+ // prudent approach.
2155
+ //
2156
+ // In the case of the holder sending a payment, the above value will not be included while the payment
2157
+ // is pending.
2158
+ //
2159
+ // This tests that we get the correct balance in either of the cases above.
2160
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
2161
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
2162
+ let mut user_config = test_default_channel_config ( ) ;
2163
+ if anchors {
2164
+ user_config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
2165
+ user_config. manually_accept_inbound_channels = true ;
2166
+ }
2167
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ Some ( user_config) , Some ( user_config) , Some ( user_config) ] ) ;
2168
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
2169
+
2170
+ let coinbase_tx = Transaction {
2171
+ version : Version :: TWO ,
2172
+ lock_time : LockTime :: ZERO ,
2173
+ input : vec ! [ TxIn { ..Default :: default ( ) } ] ,
2174
+ output : vec ! [
2175
+ TxOut {
2176
+ value: Amount :: ONE_BTC ,
2177
+ script_pubkey: nodes[ 0 ] . wallet_source. get_change_script( ) . unwrap( ) ,
2178
+ } ,
2179
+ TxOut {
2180
+ value: Amount :: ONE_BTC ,
2181
+ script_pubkey: nodes[ 1 ] . wallet_source. get_change_script( ) . unwrap( ) ,
2182
+ } ,
2183
+ ] ,
2184
+ } ;
2185
+ if anchors {
2186
+ nodes[ 0 ] . wallet_source . add_utxo ( bitcoin:: OutPoint { txid : coinbase_tx. txid ( ) , vout : 0 } , coinbase_tx. output [ 0 ] . value ) ;
2187
+ nodes[ 1 ] . wallet_source . add_utxo ( bitcoin:: OutPoint { txid : coinbase_tx. txid ( ) , vout : 1 } , coinbase_tx. output [ 1 ] . value ) ;
2188
+ }
2189
+
2190
+ // Create a channel from A -> B
2191
+ let ( _, _, chan_ab_id, funding_tx_ab) =
2192
+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 /* channel_value (sat) */ , 0 /* push_msat */ ) ;
2193
+ let funding_outpoint_ab = OutPoint { txid : funding_tx_ab. txid ( ) , index : 0 } ;
2194
+ assert_eq ! ( ChannelId :: v1_from_funding_outpoint( funding_outpoint_ab) , chan_ab_id) ;
2195
+ // Create a channel from B -> C
2196
+ let ( _, _, chan_bc_id, funding_tx_bc) =
2197
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 /* channel_value (sat) */ , 0 /* push_msat */ ) ;
2198
+ let funding_outpoint_bc = OutPoint { txid : funding_tx_bc. txid ( ) , index : 0 } ;
2199
+ assert_eq ! ( ChannelId :: v1_from_funding_outpoint( funding_outpoint_bc) , chan_bc_id) ;
2200
+
2201
+ let ( chan_feerate, channel_type_features) = if outbound_payment {
2202
+ let chan_ab_feerate = get_feerate ! ( nodes[ 0 ] , nodes[ 1 ] , chan_ab_id) ;
2203
+ let channel_type_features_ab = get_channel_type_features ! ( nodes[ 0 ] , nodes[ 1 ] , chan_ab_id) ;
2204
+ ( chan_ab_feerate, channel_type_features_ab)
2205
+ } else {
2206
+ let chan_bc_feerate = get_feerate ! ( nodes[ 1 ] , nodes[ 2 ] , chan_bc_id) ;
2207
+ let channel_type_features_bc = get_channel_type_features ! ( nodes[ 1 ] , nodes[ 2 ] , chan_bc_id) ;
2208
+ ( chan_bc_feerate, channel_type_features_bc)
2209
+ } ;
2210
+ let commitment_tx_fee = chan_feerate as u64 *
2211
+ ( chan_utils:: commitment_tx_base_weight ( & channel_type_features) + chan_utils:: COMMITMENT_TX_WEIGHT_PER_HTLC ) / 1000 ;
2212
+
2213
+ // This HTLC will be forwarded by B from A -> C
2214
+ let _ = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , 4_000_000 ) ;
2215
+ let anchor_outputs_value = if anchors { 2 * channel:: ANCHOR_OUTPUT_VALUE_SATOSHI } else { 0 } ;
2216
+
2217
+ if outbound_payment {
2218
+ assert_eq ! (
2219
+ 1_000_000 - commitment_tx_fee - anchor_outputs_value - 4_001 /* Note HTLC timeout amount of 4001 sats is excluded for outbound payment */ ,
2220
+ nodes[ 0 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint_ab) . unwrap( ) . get_claimable_balances( ) . iter( ) . map(
2221
+ |x| x. claimable_amount_satoshis( ) ) . sum( ) ) ;
2222
+ } else {
2223
+ assert_eq ! (
2224
+ 0u64 ,
2225
+ nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint_ab) . unwrap( ) . get_claimable_balances( ) . iter( ) . map(
2226
+ |x| x. claimable_amount_satoshis( ) ) . sum( ) ) ;
2227
+ assert_eq ! (
2228
+ 1_000_000 - commitment_tx_fee - anchor_outputs_value /* Note HTLC timeout amount of 4000 sats is included */ ,
2229
+ nodes[ 1 ] . chain_monitor. chain_monitor. get_monitor( funding_outpoint_bc) . unwrap( ) . get_claimable_balances( ) . iter( ) . map(
2230
+ |x| x. claimable_amount_satoshis( ) ) . sum( ) ) ;
2231
+ }
2232
+ }
2233
+
2234
+ #[ test]
2235
+ fn test_claimable_balance_correct_while_payment_pending ( ) {
2236
+ do_test_claimable_balance_correct_while_payment_pending ( false , false ) ;
2237
+ do_test_claimable_balance_correct_while_payment_pending ( false , true ) ;
2238
+ do_test_claimable_balance_correct_while_payment_pending ( true , false ) ;
2239
+ do_test_claimable_balance_correct_while_payment_pending ( true , true ) ;
2240
+ }
2241
+
2148
2242
fn do_test_restored_packages_retry ( check_old_monitor_retries_after_upgrade : bool ) {
2149
2243
// Tests that we'll retry packages that were previously timelocked after we've restored them.
2150
2244
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
0 commit comments