@@ -1684,63 +1684,108 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1684
1684
( COMMITMENT_TX_BASE_WEIGHT + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC ) * self . feerate_per_kw as u64 / 1000 * 1000
1685
1685
}
1686
1686
1687
- // Get the commitment tx fee for the local (i.e our) next commitment transaction
1688
- // based on the number of pending HTLCs that are on track to be in our next
1689
- // commitment tx. `addl_htcs` is an optional parameter allowing the caller
1690
- // to add a number of additional HTLCs to the calculation. Note that dust
1691
- // HTLCs are excluded.
1692
- fn next_local_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1687
+ // Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
1688
+ // number of pending HTLCs that are on track to be in our next commitment tx, plus an additional
1689
+ // HTLC if `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs
1690
+ // are excluded.
1691
+ fn next_local_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , locally_offered : bool , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
1693
1692
assert ! ( self . is_outbound( ) ) ;
1694
1693
1695
- let mut their_acked_htlcs = self . pending_inbound_htlcs . len ( ) ;
1694
+ let real_dust_limit_success_sat = ( self . feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1695
+ let real_dust_limit_timeout_sat = ( self . feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1696
+
1697
+ let mut addl_htlcs = 0 ;
1698
+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1699
+ if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1700
+ addl_htlcs += 1 ;
1701
+ } else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1702
+ addl_htlcs += 1 ;
1703
+ }
1704
+
1705
+ let mut included_htlcs = 0 ;
1706
+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1707
+ if htlc. amount_msat / 1000 < real_dust_limit_success_sat {
1708
+ continue
1709
+ }
1710
+ // We include LocalRemoved HTLCs here because we may still need to broadcast a commitment
1711
+ // transaction including this HTLC if it times out before they RAA.
1712
+ included_htlcs += 1 ;
1713
+ }
1714
+
1696
1715
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1697
- if htlc. amount_msat / 1000 <= self . holder_dust_limit_satoshis {
1716
+ if htlc. amount_msat / 1000 < real_dust_limit_timeout_sat {
1698
1717
continue
1699
1718
}
1700
1719
match htlc. state {
1701
- OutboundHTLCState :: Committed => their_acked_htlcs += 1 ,
1702
- OutboundHTLCState :: RemoteRemoved { ..} => their_acked_htlcs += 1 ,
1703
- OutboundHTLCState :: LocalAnnounced { ..} => their_acked_htlcs += 1 ,
1720
+ OutboundHTLCState :: LocalAnnounced { ..} => included_htlcs += 1 ,
1721
+ OutboundHTLCState :: Committed => included_htlcs += 1 ,
1722
+ OutboundHTLCState :: RemoteRemoved { ..} => included_htlcs += 1 ,
1723
+ // We don't include AwaitingRemoteRevokeToRemove HTLCs because our next commitment
1724
+ // transaction won't be generated until they send us their next RAA, which will mean
1725
+ // dropping any HTLCs in this state.
1704
1726
_ => { } ,
1705
1727
}
1706
1728
}
1707
1729
1708
1730
for htlc in self . holding_cell_htlc_updates . iter ( ) {
1709
1731
match htlc {
1710
- & HTLCUpdateAwaitingACK :: AddHTLC { .. } => their_acked_htlcs += 1 ,
1711
- _ => { } ,
1732
+ & HTLCUpdateAwaitingACK :: AddHTLC { amount_msat, .. } => {
1733
+ if amount_msat / 1000 < real_dust_limit_timeout_sat {
1734
+ continue
1735
+ }
1736
+ included_htlcs += 1
1737
+ } ,
1738
+ _ => { } , // Don't include claims/fails that are awaiting ack, because once we get the
1739
+ // ack we're guaranteed to never include them in commitment txs anymore.
1712
1740
}
1713
1741
}
1714
1742
1715
- self . commit_tx_fee_msat ( their_acked_htlcs + addl_htlcs)
1743
+ self . commit_tx_fee_msat ( included_htlcs + addl_htlcs)
1716
1744
}
1717
1745
1718
- // Get the commitment tx fee for the remote's next commitment transaction
1719
- // based on the number of pending HTLCs that are on track to be in their
1720
- // next commitment tx. `addl_htcs` is an optional parameter allowing the caller
1721
- // to add a number of additional HTLCs to the calculation. Note that dust HTLCs
1722
- // are excluded.
1723
- fn next_remote_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1746
+ // Get the commitment tx fee for the remote's next commitment transaction based on the number of
1747
+ // pending HTLCs that are on track to be in their next commitment tx, plus an additional HTLC if
1748
+ // `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs are
1749
+ // excluded.
1750
+ fn next_remote_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , locally_offered : bool , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
1724
1751
assert ! ( !self . is_outbound( ) ) ;
1725
1752
1726
- // When calculating the set of HTLCs which will be included in their next
1727
- // commitment_signed, all inbound HTLCs are included (as all states imply it will be
1728
- // included) and only committed outbound HTLCs, see below.
1729
- let mut their_acked_htlcs = self . pending_inbound_htlcs . len ( ) ;
1753
+ let real_dust_limit_success_sat = ( self . feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1754
+ let real_dust_limit_timeout_sat = ( self . feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1755
+
1756
+ let mut addl_htlcs = 0 ;
1757
+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1758
+ if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1759
+ addl_htlcs += 1 ;
1760
+ } else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1761
+ addl_htlcs += 1 ;
1762
+ }
1763
+
1764
+ // When calculating the set of HTLCs which will be included in their next commitment_signed, all
1765
+ // non-dust inbound HTLCs are included (as all states imply it will be included) and only
1766
+ // committed outbound HTLCs, see below.
1767
+ let mut included_htlcs = 0 ;
1768
+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1769
+ if htlc. amount_msat / 1000 <= real_dust_limit_timeout_sat {
1770
+ continue
1771
+ }
1772
+ included_htlcs += 1 ;
1773
+ }
1774
+
1730
1775
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1731
- if htlc. amount_msat / 1000 <= self . counterparty_dust_limit_satoshis {
1776
+ if htlc. amount_msat / 1000 <= real_dust_limit_success_sat {
1732
1777
continue
1733
1778
}
1734
- // We only include outbound HTLCs if it will not be included in their next
1735
- // commitment_signed, i.e. if they've responded to us with an RAA after announcement.
1779
+ // We only include outbound HTLCs if it will not be included in their next commitment_signed,
1780
+ // i.e. if they've responded to us with an RAA after announcement.
1736
1781
match htlc. state {
1737
- OutboundHTLCState :: Committed => their_acked_htlcs += 1 ,
1738
- OutboundHTLCState :: RemoteRemoved { ..} => their_acked_htlcs += 1 ,
1782
+ OutboundHTLCState :: Committed => included_htlcs += 1 ,
1783
+ OutboundHTLCState :: RemoteRemoved { ..} => included_htlcs += 1 ,
1739
1784
_ => { } ,
1740
1785
}
1741
1786
}
1742
1787
1743
- self . commit_tx_fee_msat ( their_acked_htlcs + addl_htlcs)
1788
+ self . commit_tx_fee_msat ( included_htlcs + addl_htlcs)
1744
1789
}
1745
1790
1746
1791
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 >
@@ -1808,8 +1853,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1808
1853
// Check that the remote can afford to pay for this HTLC on-chain at the current
1809
1854
// feerate_per_kw, while maintaining their channel reserve (as required by the spec).
1810
1855
let remote_commit_tx_fee_msat = if self . is_outbound ( ) { 0 } else {
1811
- // +1 for this HTLC.
1812
- self . next_remote_commit_tx_fee_msat ( 1 )
1856
+ self . next_remote_commit_tx_fee_msat ( msg. amount_msat , false , None ) // Don't include the extra fee spike buffer HTLC in calculations
1813
1857
} ;
1814
1858
if pending_remote_value_msat - msg. amount_msat < remote_commit_tx_fee_msat {
1815
1859
return Err ( ChannelError :: Close ( "Remote HTLC add would not leave enough to pay for fees" . to_owned ( ) ) ) ;
@@ -1822,14 +1866,15 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1822
1866
}
1823
1867
1824
1868
if !self . is_outbound ( ) {
1825
- // `+1` for this HTLC, `2 *` and `+1` fee spike buffer we keep for the remote. This deviates from the
1826
- // spec because in the spec, the fee spike buffer requirement doesn't exist on the receiver's side,
1827
- // only on the sender's.
1828
- // Note that when we eventually remove support for fee updates and switch to anchor output fees,
1829
- // we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep the extra +1
1830
- // as we should still be able to afford adding this HTLC plus one more future HTLC, regardless of
1831
- // being sensitive to fee spikes.
1832
- let remote_fee_cost_incl_stuck_buffer_msat = 2 * self . next_remote_commit_tx_fee_msat ( 1 + 1 ) ;
1869
+ // `2 *` and `Some(())` is for the fee spike buffer we keep for the remote. This deviates from
1870
+ // the spec because in the spec, the fee spike buffer requirement doesn't exist on the
1871
+ // receiver's side, only on the sender's.
1872
+ // Note that when we eventually remove support for fee updates and switch to anchor output
1873
+ // fees, we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep
1874
+ // the extra htlc when calculating the next remote commitment transaction fee as we should
1875
+ // still be able to afford adding this HTLC plus one more future HTLC, regardless of being
1876
+ // sensitive to fee spikes.
1877
+ let remote_fee_cost_incl_stuck_buffer_msat = 2 * self . next_remote_commit_tx_fee_msat ( msg. amount_msat , false , Some ( ( ) ) ) ;
1833
1878
if pending_remote_value_msat - msg. amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
1834
1879
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
1835
1880
// the HTLC, i.e. its status is already set to failing.
@@ -1838,9 +1883,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1838
1883
}
1839
1884
} else {
1840
1885
// Check that they won't violate our local required channel reserve by adding this HTLC.
1841
-
1842
- // +1 for this HTLC.
1843
- let local_commit_tx_fee_msat = self . next_local_commit_tx_fee_msat ( 1 ) ;
1886
+ let local_commit_tx_fee_msat = self . next_local_commit_tx_fee_msat ( msg. amount_msat , false , None ) ;
1844
1887
if self . value_to_self_msat < self . counterparty_selected_channel_reserve_satoshis * 1000 + local_commit_tx_fee_msat {
1845
1888
return Err ( ChannelError :: Close ( "Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value" . to_owned ( ) ) ) ;
1846
1889
}
@@ -3720,11 +3763,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3720
3763
3721
3764
if !self . is_outbound ( ) {
3722
3765
// Check that we won't violate the remote channel reserve by adding this HTLC.
3723
-
3724
3766
let counterparty_balance_msat = self . channel_value_satoshis * 1000 - self . value_to_self_msat ;
3725
3767
let holder_selected_chan_reserve_msat = Channel :: < ChanSigner > :: get_holder_selected_channel_reserve_satoshis ( self . channel_value_satoshis ) ;
3726
- // 1 additional HTLC corresponding to this HTLC.
3727
- let counterparty_commit_tx_fee_msat = self . next_remote_commit_tx_fee_msat ( 1 ) ;
3768
+ let counterparty_commit_tx_fee_msat = self . next_remote_commit_tx_fee_msat ( amount_msat, true , None ) ;
3728
3769
if counterparty_balance_msat < holder_selected_chan_reserve_msat + counterparty_commit_tx_fee_msat {
3729
3770
return Err ( ChannelError :: Ignore ( "Cannot send value that would put counterparty balance under holder-announced channel reserve value" . to_owned ( ) ) ) ;
3730
3771
}
@@ -3735,10 +3776,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3735
3776
return Err ( ChannelError :: Ignore ( format ! ( "Cannot send value that would overdraw remaining funds. Amount: {}, pending value to self {}" , amount_msat, pending_value_to_self_msat) ) ) ;
3736
3777
}
3737
3778
3738
- // The `+1` is for the HTLC currently being added to the commitment tx and
3739
- // the `2 *` and `+1` are for the fee spike buffer.
3779
+ // `2 *` and extra HTLC are for the fee spike buffer.
3740
3780
let commit_tx_fee_msat = if self . is_outbound ( ) {
3741
- 2 * self . next_local_commit_tx_fee_msat ( 1 + 1 )
3781
+ 2 * self . next_local_commit_tx_fee_msat ( amount_msat , true , Some ( ( ) ) )
3742
3782
} else { 0 } ;
3743
3783
if pending_value_to_self_msat - amount_msat < commit_tx_fee_msat {
3744
3784
return Err ( ChannelError :: Ignore ( format ! ( "Cannot send value that would not leave enough to pay for fees. Pending value to self: {}. local_commit_tx_fee {}" , pending_value_to_self_msat, commit_tx_fee_msat) ) ) ;
@@ -4575,6 +4615,73 @@ mod tests {
4575
4615
assert_eq ! ( open_channel_msg. feerate_per_kw, original_fee) ;
4576
4616
}
4577
4617
4618
+ #[ test]
4619
+ fn test_commit_tx_fees_with_dust ( ) {
4620
+ // Test that when calculating the local and remote commitment transaction fees, the correct
4621
+ // dust limits are used.
4622
+ let feeest = TestFeeEstimator { fee_est : 15000 } ;
4623
+ let secp_ctx = Secp256k1 :: new ( ) ;
4624
+ let seed = [ 42 ; 32 ] ;
4625
+ let network = Network :: Testnet ;
4626
+ let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
4627
+
4628
+ // Go through the flow of opening a channel between two nodes, making sure
4629
+ // they have different dust limits.
4630
+
4631
+ // Create Node A's channel pointing to Node B's pubkey
4632
+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
4633
+ let config = UserConfig :: default ( ) ;
4634
+ let mut node_a_chan = Channel :: < EnforcingChannelKeys > :: new_outbound ( & & feeest, & & keys_provider, node_b_node_id, 10000000 , 100000 , 42 , & config) . unwrap ( ) ;
4635
+
4636
+ // Create Node B's channel by receiving Node A's open_channel message
4637
+ // Make sure A's dust limit is as we expect.
4638
+ let open_channel_msg = node_a_chan. get_open_channel ( genesis_block ( network) . header . block_hash ( ) ) ;
4639
+ assert_eq ! ( open_channel_msg. dust_limit_satoshis, 1560 ) ;
4640
+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 7 ; 32 ] ) . unwrap ( ) ) ;
4641
+ let node_b_chan = Channel :: < EnforcingChannelKeys > :: new_from_req ( & & feeest, & & keys_provider, node_b_node_id, InitFeatures :: known ( ) , & open_channel_msg, 7 , & config) . unwrap ( ) ;
4642
+
4643
+ // Node B --> Node A: accept channel, explicitly setting B's dust limit.
4644
+ let mut accept_channel_msg = node_b_chan. get_accept_channel ( ) ;
4645
+ accept_channel_msg. dust_limit_satoshis = 546 ;
4646
+ node_a_chan. accept_channel ( & accept_channel_msg, & config, InitFeatures :: known ( ) ) . unwrap ( ) ;
4647
+
4648
+ // Put some inbound and outbound HTLCs in A's channel.
4649
+ let htlc_amount_msat = 11_092_000 ; // put an amount below A's effective dust amount but above B's.
4650
+ node_a_chan. pending_inbound_htlcs . push ( InboundHTLCOutput {
4651
+ htlc_id : 0 ,
4652
+ amount_msat : htlc_amount_msat,
4653
+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 42 ; 32 ] ) . into_inner ( ) ) ,
4654
+ cltv_expiry : 300000000 ,
4655
+ state : InboundHTLCState :: Committed ,
4656
+ } ) ;
4657
+
4658
+ node_a_chan. pending_outbound_htlcs . push ( OutboundHTLCOutput {
4659
+ htlc_id : 1 ,
4660
+ amount_msat : htlc_amount_msat, // put an amount below A's dust amount but above B's.
4661
+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 43 ; 32 ] ) . into_inner ( ) ) ,
4662
+ cltv_expiry : 200000000 ,
4663
+ state : OutboundHTLCState :: Committed ,
4664
+ source : HTLCSource :: OutboundRoute {
4665
+ path : Vec :: new ( ) ,
4666
+ session_priv : SecretKey :: from_slice ( & hex:: decode ( "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ) . unwrap ( ) [ ..] ) . unwrap ( ) ,
4667
+ first_hop_htlc_msat : 548 ,
4668
+ }
4669
+ } ) ;
4670
+
4671
+ // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
4672
+ // the dust limit check.
4673
+ let local_commit_tx_fee = node_a_chan. next_local_commit_tx_fee_msat ( htlc_amount_msat, true , None ) ;
4674
+ let local_commit_fee_0_htlcs = node_a_chan. commit_tx_fee_msat ( 0 ) ;
4675
+ assert_eq ! ( local_commit_tx_fee, local_commit_fee_0_htlcs) ;
4676
+
4677
+ // Finally, make sure that when Node A calculates the remote's commitment transaction fees, all
4678
+ // of the HTLCs are seen to be above the dust limit.
4679
+ node_a_chan. channel_transaction_parameters . is_outbound_from_holder = false ;
4680
+ let remote_commit_fee_3_htlcs = node_a_chan. commit_tx_fee_msat ( 3 ) ;
4681
+ let remote_commit_tx_fee = node_a_chan. next_remote_commit_tx_fee_msat ( htlc_amount_msat, true , None ) ;
4682
+ assert_eq ! ( remote_commit_tx_fee, remote_commit_fee_3_htlcs) ;
4683
+ }
4684
+
4578
4685
#[ test]
4579
4686
fn channel_reestablish_no_updates ( ) {
4580
4687
let feeest = TestFeeEstimator { fee_est : 15000 } ;
0 commit comments