@@ -1451,6 +1451,143 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
1451
1451
stats
1452
1452
}
1453
1453
1454
+ /// Get the available balances, see [`AvailableBalances`]'s fields for more info.
1455
+ /// Doesn't bother handling the
1456
+ /// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC
1457
+ /// corner case properly.
1458
+ pub fn get_available_balances ( & self ) -> AvailableBalances {
1459
+ let context = & self ;
1460
+ // Note that we have to handle overflow due to the above case.
1461
+ let inbound_stats = context. get_inbound_pending_htlc_stats ( None ) ;
1462
+ let outbound_stats = context. get_outbound_pending_htlc_stats ( None ) ;
1463
+
1464
+ let mut balance_msat = context. value_to_self_msat ;
1465
+ for ref htlc in context. pending_inbound_htlcs . iter ( ) {
1466
+ if let InboundHTLCState :: LocalRemoved ( InboundHTLCRemovalReason :: Fulfill ( _) ) = htlc. state {
1467
+ balance_msat += htlc. amount_msat ;
1468
+ }
1469
+ }
1470
+ balance_msat -= outbound_stats. pending_htlcs_value_msat ;
1471
+
1472
+ let outbound_capacity_msat = context. value_to_self_msat
1473
+ . saturating_sub ( outbound_stats. pending_htlcs_value_msat )
1474
+ . saturating_sub (
1475
+ context. counterparty_selected_channel_reserve_satoshis . unwrap_or ( 0 ) * 1000 ) ;
1476
+
1477
+ let mut available_capacity_msat = outbound_capacity_msat;
1478
+
1479
+ if context. is_outbound ( ) {
1480
+ // We should mind channel commit tx fee when computing how much of the available capacity
1481
+ // can be used in the next htlc. Mirrors the logic in send_htlc.
1482
+ //
1483
+ // The fee depends on whether the amount we will be sending is above dust or not,
1484
+ // and the answer will in turn change the amount itself — making it a circular
1485
+ // dependency.
1486
+ // This complicates the computation around dust-values, up to the one-htlc-value.
1487
+ let mut real_dust_limit_timeout_sat = context. holder_dust_limit_satoshis ;
1488
+ if !context. opt_anchors ( ) {
1489
+ real_dust_limit_timeout_sat += context. feerate_per_kw as u64 * htlc_timeout_tx_weight ( false ) / 1000 ;
1490
+ }
1491
+
1492
+ let htlc_above_dust = HTLCCandidate :: new ( real_dust_limit_timeout_sat * 1000 , HTLCInitiator :: LocalOffered ) ;
1493
+ let max_reserved_commit_tx_fee_msat = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * context. next_local_commit_tx_fee_msat ( htlc_above_dust, Some ( ( ) ) ) ;
1494
+ let htlc_dust = HTLCCandidate :: new ( real_dust_limit_timeout_sat * 1000 - 1 , HTLCInitiator :: LocalOffered ) ;
1495
+ let min_reserved_commit_tx_fee_msat = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * context. next_local_commit_tx_fee_msat ( htlc_dust, Some ( ( ) ) ) ;
1496
+
1497
+ // We will first subtract the fee as if we were above-dust. Then, if the resulting
1498
+ // value ends up being below dust, we have this fee available again. In that case,
1499
+ // match the value to right-below-dust.
1500
+ let mut capacity_minus_commitment_fee_msat: i64 = ( available_capacity_msat as i64 ) - ( max_reserved_commit_tx_fee_msat as i64 ) ;
1501
+ if capacity_minus_commitment_fee_msat < ( real_dust_limit_timeout_sat as i64 ) * 1000 {
1502
+ let one_htlc_difference_msat = max_reserved_commit_tx_fee_msat - min_reserved_commit_tx_fee_msat;
1503
+ debug_assert ! ( one_htlc_difference_msat != 0 ) ;
1504
+ capacity_minus_commitment_fee_msat += one_htlc_difference_msat as i64 ;
1505
+ capacity_minus_commitment_fee_msat = cmp:: min ( real_dust_limit_timeout_sat as i64 * 1000 - 1 , capacity_minus_commitment_fee_msat) ;
1506
+ available_capacity_msat = cmp:: max ( 0 , cmp:: min ( capacity_minus_commitment_fee_msat, available_capacity_msat as i64 ) ) as u64 ;
1507
+ } else {
1508
+ available_capacity_msat = capacity_minus_commitment_fee_msat as u64 ;
1509
+ }
1510
+ } else {
1511
+ // If the channel is inbound (i.e. counterparty pays the fee), we need to make sure
1512
+ // sending a new HTLC won't reduce their balance below our reserve threshold.
1513
+ let mut real_dust_limit_success_sat = context. counterparty_dust_limit_satoshis ;
1514
+ if !context. opt_anchors ( ) {
1515
+ real_dust_limit_success_sat += context. feerate_per_kw as u64 * htlc_success_tx_weight ( false ) / 1000 ;
1516
+ }
1517
+
1518
+ let htlc_above_dust = HTLCCandidate :: new ( real_dust_limit_success_sat * 1000 , HTLCInitiator :: LocalOffered ) ;
1519
+ let max_reserved_commit_tx_fee_msat = context. next_remote_commit_tx_fee_msat ( htlc_above_dust, None ) ;
1520
+
1521
+ let holder_selected_chan_reserve_msat = context. holder_selected_channel_reserve_satoshis * 1000 ;
1522
+ let remote_balance_msat = ( context. channel_value_satoshis * 1000 - context. value_to_self_msat )
1523
+ . saturating_sub ( inbound_stats. pending_htlcs_value_msat ) ;
1524
+
1525
+ if remote_balance_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat {
1526
+ // If another HTLC's fee would reduce the remote's balance below the reserve limit
1527
+ // we've selected for them, we can only send dust HTLCs.
1528
+ available_capacity_msat = cmp:: min ( available_capacity_msat, real_dust_limit_success_sat * 1000 - 1 ) ;
1529
+ }
1530
+ }
1531
+
1532
+ let mut next_outbound_htlc_minimum_msat = context. counterparty_htlc_minimum_msat ;
1533
+
1534
+ // If we get close to our maximum dust exposure, we end up in a situation where we can send
1535
+ // between zero and the remaining dust exposure limit remaining OR above the dust limit.
1536
+ // Because we cannot express this as a simple min/max, we prefer to tell the user they can
1537
+ // send above the dust limit (as the router can always overpay to meet the dust limit).
1538
+ let mut remaining_msat_below_dust_exposure_limit = None ;
1539
+ let mut dust_exposure_dust_limit_msat = 0 ;
1540
+
1541
+ let ( htlc_success_dust_limit, htlc_timeout_dust_limit) = if context. opt_anchors ( ) {
1542
+ ( context. counterparty_dust_limit_satoshis , context. holder_dust_limit_satoshis )
1543
+ } else {
1544
+ let dust_buffer_feerate = context. get_dust_buffer_feerate ( None ) as u64 ;
1545
+ ( context. counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight ( false ) / 1000 ,
1546
+ context. holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight ( false ) / 1000 )
1547
+ } ;
1548
+ let on_counterparty_dust_htlc_exposure_msat = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
1549
+ if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > context. get_max_dust_htlc_exposure_msat ( ) as i64 {
1550
+ remaining_msat_below_dust_exposure_limit =
1551
+ Some ( context. get_max_dust_htlc_exposure_msat ( ) . saturating_sub ( on_counterparty_dust_htlc_exposure_msat) ) ;
1552
+ dust_exposure_dust_limit_msat = cmp:: max ( dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000 ) ;
1553
+ }
1554
+
1555
+ let on_holder_dust_htlc_exposure_msat = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
1556
+ if on_holder_dust_htlc_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > context. get_max_dust_htlc_exposure_msat ( ) as i64 {
1557
+ remaining_msat_below_dust_exposure_limit = Some ( cmp:: min (
1558
+ remaining_msat_below_dust_exposure_limit. unwrap_or ( u64:: max_value ( ) ) ,
1559
+ context. get_max_dust_htlc_exposure_msat ( ) . saturating_sub ( on_holder_dust_htlc_exposure_msat) ) ) ;
1560
+ dust_exposure_dust_limit_msat = cmp:: max ( dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000 ) ;
1561
+ }
1562
+
1563
+ if let Some ( remaining_limit_msat) = remaining_msat_below_dust_exposure_limit {
1564
+ if available_capacity_msat < dust_exposure_dust_limit_msat {
1565
+ available_capacity_msat = cmp:: min ( available_capacity_msat, remaining_limit_msat) ;
1566
+ } else {
1567
+ next_outbound_htlc_minimum_msat = cmp:: max ( next_outbound_htlc_minimum_msat, dust_exposure_dust_limit_msat) ;
1568
+ }
1569
+ }
1570
+
1571
+ available_capacity_msat = cmp:: min ( available_capacity_msat,
1572
+ context. counterparty_max_htlc_value_in_flight_msat - outbound_stats. pending_htlcs_value_msat ) ;
1573
+
1574
+ if outbound_stats. pending_htlcs + 1 > context. counterparty_max_accepted_htlcs as u32 {
1575
+ available_capacity_msat = 0 ;
1576
+ }
1577
+
1578
+ AvailableBalances {
1579
+ inbound_capacity_msat : cmp:: max ( context. channel_value_satoshis as i64 * 1000
1580
+ - context. value_to_self_msat as i64
1581
+ - context. get_inbound_pending_htlc_stats ( None ) . pending_htlcs_value_msat as i64
1582
+ - context. holder_selected_channel_reserve_satoshis as i64 * 1000 ,
1583
+ 0 ) as u64 ,
1584
+ outbound_capacity_msat,
1585
+ next_outbound_htlc_limit_msat : available_capacity_msat,
1586
+ next_outbound_htlc_minimum_msat,
1587
+ balance_msat,
1588
+ }
1589
+ }
1590
+
1454
1591
pub fn get_holder_counterparty_selected_channel_reserve_satoshis ( & self ) -> ( u64 , Option < u64 > ) {
1455
1592
let context = & self ;
1456
1593
( context. holder_selected_channel_reserve_satoshis , context. counterparty_selected_channel_reserve_satoshis )
@@ -3222,143 +3359,6 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
3222
3359
}
3223
3360
}
3224
3361
3225
- /// Get the available balances, see [`AvailableBalances`]'s fields for more info.
3226
- /// Doesn't bother handling the
3227
- /// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC
3228
- /// corner case properly.
3229
- pub fn get_available_balances ( & self ) -> AvailableBalances {
3230
- let context = & self . context ;
3231
- // Note that we have to handle overflow due to the above case.
3232
- let inbound_stats = context. get_inbound_pending_htlc_stats ( None ) ;
3233
- let outbound_stats = context. get_outbound_pending_htlc_stats ( None ) ;
3234
-
3235
- let mut balance_msat = context. value_to_self_msat ;
3236
- for ref htlc in context. pending_inbound_htlcs . iter ( ) {
3237
- if let InboundHTLCState :: LocalRemoved ( InboundHTLCRemovalReason :: Fulfill ( _) ) = htlc. state {
3238
- balance_msat += htlc. amount_msat ;
3239
- }
3240
- }
3241
- balance_msat -= outbound_stats. pending_htlcs_value_msat ;
3242
-
3243
- let outbound_capacity_msat = context. value_to_self_msat
3244
- . saturating_sub ( outbound_stats. pending_htlcs_value_msat )
3245
- . saturating_sub (
3246
- context. counterparty_selected_channel_reserve_satoshis . unwrap_or ( 0 ) * 1000 ) ;
3247
-
3248
- let mut available_capacity_msat = outbound_capacity_msat;
3249
-
3250
- if context. is_outbound ( ) {
3251
- // We should mind channel commit tx fee when computing how much of the available capacity
3252
- // can be used in the next htlc. Mirrors the logic in send_htlc.
3253
- //
3254
- // The fee depends on whether the amount we will be sending is above dust or not,
3255
- // and the answer will in turn change the amount itself — making it a circular
3256
- // dependency.
3257
- // This complicates the computation around dust-values, up to the one-htlc-value.
3258
- let mut real_dust_limit_timeout_sat = context. holder_dust_limit_satoshis ;
3259
- if !context. opt_anchors ( ) {
3260
- real_dust_limit_timeout_sat += context. feerate_per_kw as u64 * htlc_timeout_tx_weight ( false ) / 1000 ;
3261
- }
3262
-
3263
- let htlc_above_dust = HTLCCandidate :: new ( real_dust_limit_timeout_sat * 1000 , HTLCInitiator :: LocalOffered ) ;
3264
- let max_reserved_commit_tx_fee_msat = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * context. next_local_commit_tx_fee_msat ( htlc_above_dust, Some ( ( ) ) ) ;
3265
- let htlc_dust = HTLCCandidate :: new ( real_dust_limit_timeout_sat * 1000 - 1 , HTLCInitiator :: LocalOffered ) ;
3266
- let min_reserved_commit_tx_fee_msat = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * context. next_local_commit_tx_fee_msat ( htlc_dust, Some ( ( ) ) ) ;
3267
-
3268
- // We will first subtract the fee as if we were above-dust. Then, if the resulting
3269
- // value ends up being below dust, we have this fee available again. In that case,
3270
- // match the value to right-below-dust.
3271
- let mut capacity_minus_commitment_fee_msat: i64 = ( available_capacity_msat as i64 ) - ( max_reserved_commit_tx_fee_msat as i64 ) ;
3272
- if capacity_minus_commitment_fee_msat < ( real_dust_limit_timeout_sat as i64 ) * 1000 {
3273
- let one_htlc_difference_msat = max_reserved_commit_tx_fee_msat - min_reserved_commit_tx_fee_msat;
3274
- debug_assert ! ( one_htlc_difference_msat != 0 ) ;
3275
- capacity_minus_commitment_fee_msat += one_htlc_difference_msat as i64 ;
3276
- capacity_minus_commitment_fee_msat = cmp:: min ( real_dust_limit_timeout_sat as i64 * 1000 - 1 , capacity_minus_commitment_fee_msat) ;
3277
- available_capacity_msat = cmp:: max ( 0 , cmp:: min ( capacity_minus_commitment_fee_msat, available_capacity_msat as i64 ) ) as u64 ;
3278
- } else {
3279
- available_capacity_msat = capacity_minus_commitment_fee_msat as u64 ;
3280
- }
3281
- } else {
3282
- // If the channel is inbound (i.e. counterparty pays the fee), we need to make sure
3283
- // sending a new HTLC won't reduce their balance below our reserve threshold.
3284
- let mut real_dust_limit_success_sat = context. counterparty_dust_limit_satoshis ;
3285
- if !context. opt_anchors ( ) {
3286
- real_dust_limit_success_sat += context. feerate_per_kw as u64 * htlc_success_tx_weight ( false ) / 1000 ;
3287
- }
3288
-
3289
- let htlc_above_dust = HTLCCandidate :: new ( real_dust_limit_success_sat * 1000 , HTLCInitiator :: LocalOffered ) ;
3290
- let max_reserved_commit_tx_fee_msat = context. next_remote_commit_tx_fee_msat ( htlc_above_dust, None ) ;
3291
-
3292
- let holder_selected_chan_reserve_msat = context. holder_selected_channel_reserve_satoshis * 1000 ;
3293
- let remote_balance_msat = ( context. channel_value_satoshis * 1000 - context. value_to_self_msat )
3294
- . saturating_sub ( inbound_stats. pending_htlcs_value_msat ) ;
3295
-
3296
- if remote_balance_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat {
3297
- // If another HTLC's fee would reduce the remote's balance below the reserve limit
3298
- // we've selected for them, we can only send dust HTLCs.
3299
- available_capacity_msat = cmp:: min ( available_capacity_msat, real_dust_limit_success_sat * 1000 - 1 ) ;
3300
- }
3301
- }
3302
-
3303
- let mut next_outbound_htlc_minimum_msat = context. counterparty_htlc_minimum_msat ;
3304
-
3305
- // If we get close to our maximum dust exposure, we end up in a situation where we can send
3306
- // between zero and the remaining dust exposure limit remaining OR above the dust limit.
3307
- // Because we cannot express this as a simple min/max, we prefer to tell the user they can
3308
- // send above the dust limit (as the router can always overpay to meet the dust limit).
3309
- let mut remaining_msat_below_dust_exposure_limit = None ;
3310
- let mut dust_exposure_dust_limit_msat = 0 ;
3311
-
3312
- let ( htlc_success_dust_limit, htlc_timeout_dust_limit) = if context. opt_anchors ( ) {
3313
- ( context. counterparty_dust_limit_satoshis , context. holder_dust_limit_satoshis )
3314
- } else {
3315
- let dust_buffer_feerate = context. get_dust_buffer_feerate ( None ) as u64 ;
3316
- ( context. counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight ( false ) / 1000 ,
3317
- context. holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight ( false ) / 1000 )
3318
- } ;
3319
- let on_counterparty_dust_htlc_exposure_msat = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
3320
- if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > context. get_max_dust_htlc_exposure_msat ( ) as i64 {
3321
- remaining_msat_below_dust_exposure_limit =
3322
- Some ( context. get_max_dust_htlc_exposure_msat ( ) . saturating_sub ( on_counterparty_dust_htlc_exposure_msat) ) ;
3323
- dust_exposure_dust_limit_msat = cmp:: max ( dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000 ) ;
3324
- }
3325
-
3326
- let on_holder_dust_htlc_exposure_msat = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
3327
- if on_holder_dust_htlc_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > context. get_max_dust_htlc_exposure_msat ( ) as i64 {
3328
- remaining_msat_below_dust_exposure_limit = Some ( cmp:: min (
3329
- remaining_msat_below_dust_exposure_limit. unwrap_or ( u64:: max_value ( ) ) ,
3330
- context. get_max_dust_htlc_exposure_msat ( ) . saturating_sub ( on_holder_dust_htlc_exposure_msat) ) ) ;
3331
- dust_exposure_dust_limit_msat = cmp:: max ( dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000 ) ;
3332
- }
3333
-
3334
- if let Some ( remaining_limit_msat) = remaining_msat_below_dust_exposure_limit {
3335
- if available_capacity_msat < dust_exposure_dust_limit_msat {
3336
- available_capacity_msat = cmp:: min ( available_capacity_msat, remaining_limit_msat) ;
3337
- } else {
3338
- next_outbound_htlc_minimum_msat = cmp:: max ( next_outbound_htlc_minimum_msat, dust_exposure_dust_limit_msat) ;
3339
- }
3340
- }
3341
-
3342
- available_capacity_msat = cmp:: min ( available_capacity_msat,
3343
- context. counterparty_max_htlc_value_in_flight_msat - outbound_stats. pending_htlcs_value_msat ) ;
3344
-
3345
- if outbound_stats. pending_htlcs + 1 > context. counterparty_max_accepted_htlcs as u32 {
3346
- available_capacity_msat = 0 ;
3347
- }
3348
-
3349
- AvailableBalances {
3350
- inbound_capacity_msat : cmp:: max ( context. channel_value_satoshis as i64 * 1000
3351
- - context. value_to_self_msat as i64
3352
- - context. get_inbound_pending_htlc_stats ( None ) . pending_htlcs_value_msat as i64
3353
- - context. holder_selected_channel_reserve_satoshis as i64 * 1000 ,
3354
- 0 ) as u64 ,
3355
- outbound_capacity_msat,
3356
- next_outbound_htlc_limit_msat : available_capacity_msat,
3357
- next_outbound_htlc_minimum_msat,
3358
- balance_msat,
3359
- }
3360
- }
3361
-
3362
3362
pub fn update_add_htlc < F , L : Deref > ( & mut self , msg : & msgs:: UpdateAddHTLC , mut pending_forward_status : PendingHTLCStatus , create_pending_htlc_status : F , logger : & L ) -> Result < ( ) , ChannelError >
3363
3363
where F : for < ' a > Fn ( & ' a Self , PendingHTLCStatus , u16 ) -> PendingHTLCStatus , L :: Target : Logger {
3364
3364
// We can't accept HTLCs sent after we've sent a shutdown.
@@ -6048,7 +6048,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
6048
6048
return Err ( ChannelError :: Ignore ( "Cannot send 0-msat HTLC" . to_owned ( ) ) ) ;
6049
6049
}
6050
6050
6051
- let available_balances = self . get_available_balances ( ) ;
6051
+ let available_balances = self . context . get_available_balances ( ) ;
6052
6052
if amount_msat < available_balances. next_outbound_htlc_minimum_msat {
6053
6053
return Err ( ChannelError :: Ignore ( format ! ( "Cannot send less than our next-HTLC minimum - {} msat" ,
6054
6054
available_balances. next_outbound_htlc_minimum_msat) ) ) ;
0 commit comments