@@ -2135,6 +2135,100 @@ fn test_revoked_counterparty_aggregated_claims() {
21352135 do_test_revoked_counterparty_aggregated_claims ( true ) ;
21362136}
21372137
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+
21382232fn do_test_restored_packages_retry ( check_old_monitor_retries_after_upgrade : bool ) {
21392233 // Tests that we'll retry packages that were previously timelocked after we've restored them.
21402234 let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
0 commit comments