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