11//! Defines the `TxBuilder` trait, and the `SpecTxBuilder` type
22#![ allow( dead_code) ]
33
4- use core:: ops:: Deref ;
54use core:: cmp;
5+ use core:: ops:: Deref ;
66
77use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 } ;
88
@@ -29,7 +29,10 @@ pub(crate) struct HTLCAmountDirection {
2929}
3030
3131impl HTLCAmountDirection {
32- fn is_dust ( & self , local : bool , feerate_per_kw : u32 , broadcaster_dust_limit_sat : u64 , channel_type : & ChannelTypeFeatures ) -> bool {
32+ fn is_dust (
33+ & self , local : bool , feerate_per_kw : u32 , broadcaster_dust_limit_sat : u64 ,
34+ channel_type : & ChannelTypeFeatures ,
35+ ) -> bool {
3336 let htlc_tx_fee_sat = if channel_type. supports_anchors_zero_fee_htlc_tx ( ) {
3437 0
3538 } else {
@@ -55,20 +58,35 @@ pub(crate) struct BuilderStats {
5558 pub counterparty_balance_msat : Option < u64 > ,
5659}
5760
58- fn on_holder_tx_dust_exposure_msat ( dust_buffer_feerate : u32 , holder_dust_limit_satoshis : u64 , channel_type : & ChannelTypeFeatures , htlcs : & [ HTLCAmountDirection ] ) -> u64 {
61+ fn on_holder_tx_dust_exposure_msat (
62+ dust_buffer_feerate : u32 , holder_dust_limit_satoshis : u64 , channel_type : & ChannelTypeFeatures ,
63+ htlcs : & [ HTLCAmountDirection ] ,
64+ ) -> u64 {
5965 htlcs
6066 . iter ( )
61- . filter_map ( |htlc| { htlc. is_dust ( true , dust_buffer_feerate, holder_dust_limit_satoshis, channel_type) . then_some ( htlc. amount_msat ) } )
67+ . filter_map ( |htlc| {
68+ htlc. is_dust ( true , dust_buffer_feerate, holder_dust_limit_satoshis, channel_type)
69+ . then_some ( htlc. amount_msat )
70+ } )
6271 . sum ( )
6372}
6473
65- fn on_counterparty_tx_dust_exposure_msat ( dust_buffer_feerate : u32 , excess_feerate_opt : Option < u32 > , counterparty_dust_limit_satoshis : u64 , channel_type : & ChannelTypeFeatures , on_remote_htlcs : & [ HTLCAmountDirection ] ) -> ( u64 , Option < u64 > ) {
74+ fn on_counterparty_tx_dust_exposure_msat (
75+ dust_buffer_feerate : u32 , excess_feerate_opt : Option < u32 > ,
76+ counterparty_dust_limit_satoshis : u64 , channel_type : & ChannelTypeFeatures ,
77+ on_remote_htlcs : & [ HTLCAmountDirection ] ,
78+ ) -> ( u64 , Option < u64 > ) {
6679 let mut on_counterparty_tx_accepted_nondust_htlcs = 0 ;
6780 let mut on_counterparty_tx_offered_nondust_htlcs = 0 ;
6881 let mut on_counterparty_tx_dust_exposure_msat: u64 = on_remote_htlcs
6982 . iter ( )
7083 . filter_map ( |htlc| {
71- if htlc. is_dust ( false , dust_buffer_feerate, counterparty_dust_limit_satoshis, channel_type) {
84+ if htlc. is_dust (
85+ false ,
86+ dust_buffer_feerate,
87+ counterparty_dust_limit_satoshis,
88+ channel_type,
89+ ) {
7290 Some ( htlc. amount_msat )
7391 } else {
7492 if !htlc. outbound {
@@ -83,13 +101,34 @@ fn on_counterparty_tx_dust_exposure_msat(dust_buffer_feerate: u32, excess_feerat
83101
84102 let extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat =
85103 excess_feerate_opt. map ( |excess_feerate| {
86- let extra_htlc_commit_tx_fee_sat = commit_tx_fee_sat ( excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + 1 + on_counterparty_tx_offered_nondust_htlcs, channel_type) ;
87- let extra_htlc_htlc_tx_fees_sat = htlc_tx_fees_sat ( excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + 1 , on_counterparty_tx_offered_nondust_htlcs, channel_type) ;
88-
89- let commit_tx_fee_sat = commit_tx_fee_sat ( excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + on_counterparty_tx_offered_nondust_htlcs, channel_type) ;
90- let htlc_tx_fees_sat = htlc_tx_fees_sat ( excess_feerate, on_counterparty_tx_accepted_nondust_htlcs, on_counterparty_tx_offered_nondust_htlcs, channel_type) ;
91-
92- let extra_htlc_dust_exposure = on_counterparty_tx_dust_exposure_msat + ( extra_htlc_commit_tx_fee_sat + extra_htlc_htlc_tx_fees_sat) * 1000 ;
104+ let extra_htlc_commit_tx_fee_sat = commit_tx_fee_sat (
105+ excess_feerate,
106+ on_counterparty_tx_accepted_nondust_htlcs
107+ + 1 + on_counterparty_tx_offered_nondust_htlcs,
108+ channel_type,
109+ ) ;
110+ let extra_htlc_htlc_tx_fees_sat = htlc_tx_fees_sat (
111+ excess_feerate,
112+ on_counterparty_tx_accepted_nondust_htlcs + 1 ,
113+ on_counterparty_tx_offered_nondust_htlcs,
114+ channel_type,
115+ ) ;
116+
117+ let commit_tx_fee_sat = commit_tx_fee_sat (
118+ excess_feerate,
119+ on_counterparty_tx_accepted_nondust_htlcs
120+ + on_counterparty_tx_offered_nondust_htlcs,
121+ channel_type,
122+ ) ;
123+ let htlc_tx_fees_sat = htlc_tx_fees_sat (
124+ excess_feerate,
125+ on_counterparty_tx_accepted_nondust_htlcs,
126+ on_counterparty_tx_offered_nondust_htlcs,
127+ channel_type,
128+ ) ;
129+
130+ let extra_htlc_dust_exposure = on_counterparty_tx_dust_exposure_msat
131+ + ( extra_htlc_commit_tx_fee_sat + extra_htlc_htlc_tx_fees_sat) * 1000 ;
93132 on_counterparty_tx_dust_exposure_msat += ( commit_tx_fee_sat + htlc_tx_fees_sat) * 1000 ;
94133 extra_htlc_dust_exposure
95134 } ) ;
@@ -141,7 +180,13 @@ fn get_dust_buffer_feerate(feerate_per_kw: u32) -> u32 {
141180}
142181
143182pub ( crate ) trait TxBuilder {
144- fn get_builder_stats ( & self , is_outbound_from_holder : bool , channel_value_satoshis : u64 , value_to_holder_msat : u64 , htlcs : & [ HTLCAmountDirection ] , nondust_htlcs : usize , feerate_per_kw : u32 , dust_exposure_limiting_feerate : Option < u32 > , channel_type : & ChannelTypeFeatures , holder_dust_limit_satoshis : u64 , counterparty_dust_limit_satoshis : u64 ) -> BuilderStats ;
183+ fn get_builder_stats (
184+ & self , is_outbound_from_holder : bool , channel_value_satoshis : u64 ,
185+ value_to_holder_msat : u64 , htlcs : & [ HTLCAmountDirection ] , nondust_htlcs : usize ,
186+ feerate_per_kw : u32 , dust_exposure_limiting_feerate : Option < u32 > ,
187+ channel_type : & ChannelTypeFeatures , holder_dust_limit_satoshis : u64 ,
188+ counterparty_dust_limit_satoshis : u64 ,
189+ ) -> BuilderStats ;
145190 fn commit_tx_fee_sat (
146191 & self , feerate_per_kw : u32 , nondust_htlc_count : usize , channel_type : & ChannelTypeFeatures ,
147192 ) -> u64 ;
@@ -162,8 +207,15 @@ pub(crate) trait TxBuilder {
162207pub ( crate ) struct SpecTxBuilder { }
163208
164209impl TxBuilder for SpecTxBuilder {
165- fn get_builder_stats ( & self , is_outbound_from_holder : bool , channel_value_satoshis : u64 , value_to_holder_msat : u64 , htlcs : & [ HTLCAmountDirection ] , nondust_htlcs : usize , feerate_per_kw : u32 , dust_exposure_limiting_feerate : Option < u32 > , channel_type : & ChannelTypeFeatures , holder_dust_limit_satoshis : u64 , counterparty_dust_limit_satoshis : u64 ) -> BuilderStats {
166- let excess_feerate_opt = feerate_per_kw. checked_sub ( dust_exposure_limiting_feerate. unwrap_or ( 0 ) ) ;
210+ fn get_builder_stats (
211+ & self , is_outbound_from_holder : bool , channel_value_satoshis : u64 ,
212+ value_to_holder_msat : u64 , htlcs : & [ HTLCAmountDirection ] , nondust_htlcs : usize ,
213+ feerate_per_kw : u32 , dust_exposure_limiting_feerate : Option < u32 > ,
214+ channel_type : & ChannelTypeFeatures , holder_dust_limit_satoshis : u64 ,
215+ counterparty_dust_limit_satoshis : u64 ,
216+ ) -> BuilderStats {
217+ let excess_feerate_opt =
218+ feerate_per_kw. checked_sub ( dust_exposure_limiting_feerate. unwrap_or ( 0 ) ) ;
167219 // Dust exposure is only decoupled from feerate for zero fee commitment channels.
168220 let is_zero_fee_comm = channel_type. supports_anchor_zero_fee_commitments ( ) ;
169221 debug_assert_eq ! ( is_zero_fee_comm, dust_exposure_limiting_feerate. is_none( ) ) ;
@@ -175,17 +227,27 @@ impl TxBuilder for SpecTxBuilder {
175227
176228 // Calculate balances after htlcs
177229 let value_to_counterparty_msat = channel_value_satoshis * 1000 - value_to_holder_msat;
178- let outbound_htlcs_value_msat: u64 = htlcs. iter ( ) . filter_map ( |htlc| htlc. outbound . then_some ( htlc. amount_msat ) ) . sum ( ) ;
179- let inbound_htlcs_value_msat: u64 = htlcs. iter ( ) . filter_map ( |htlc| ( !htlc. outbound ) . then_some ( htlc. amount_msat ) ) . sum ( ) ;
180- let value_to_holder_after_htlcs = value_to_holder_msat. checked_sub ( outbound_htlcs_value_msat) ;
181- let value_to_counterparty_after_htlcs = value_to_counterparty_msat. checked_sub ( inbound_htlcs_value_msat) ;
230+ let outbound_htlcs_value_msat: u64 =
231+ htlcs. iter ( ) . filter_map ( |htlc| htlc. outbound . then_some ( htlc. amount_msat ) ) . sum ( ) ;
232+ let inbound_htlcs_value_msat: u64 =
233+ htlcs. iter ( ) . filter_map ( |htlc| ( !htlc. outbound ) . then_some ( htlc. amount_msat ) ) . sum ( ) ;
234+ let value_to_holder_after_htlcs =
235+ value_to_holder_msat. checked_sub ( outbound_htlcs_value_msat) ;
236+ let value_to_counterparty_after_htlcs =
237+ value_to_counterparty_msat. checked_sub ( inbound_htlcs_value_msat) ;
182238
183239 // Increment the feerate by a buffer to calculate dust exposure
184240 let dust_buffer_feerate = get_dust_buffer_feerate ( feerate_per_kw) ;
185241
186242 // Calculate dust exposure on holder's commitment transaction
187- let on_holder_htlc_count = htlcs. iter ( ) . filter ( |htlc| !htlc. is_dust ( true , feerate_per_kw, holder_dust_limit_satoshis, channel_type) ) . count ( ) ;
188- let holder_commit_tx_fee_sat = commit_tx_fee_sat ( feerate_per_kw, on_holder_htlc_count + nondust_htlcs, channel_type) ;
243+ let on_holder_htlc_count = htlcs
244+ . iter ( )
245+ . filter ( |htlc| {
246+ !htlc. is_dust ( true , feerate_per_kw, holder_dust_limit_satoshis, channel_type)
247+ } )
248+ . count ( ) ;
249+ let holder_commit_tx_fee_sat =
250+ commit_tx_fee_sat ( feerate_per_kw, on_holder_htlc_count + nondust_htlcs, channel_type) ;
189251 let on_holder_tx_dust_exposure_msat = on_holder_tx_dust_exposure_msat (
190252 dust_buffer_feerate,
191253 holder_dust_limit_satoshis,
@@ -194,9 +256,21 @@ impl TxBuilder for SpecTxBuilder {
194256 ) ;
195257
196258 // Calculate dust exposure on counterparty's commitment transaction
197- let on_counterparty_htlc_count = htlcs. iter ( ) . filter ( |htlc| !htlc. is_dust ( false , feerate_per_kw, counterparty_dust_limit_satoshis, channel_type) ) . count ( ) ;
198- let counterparty_commit_tx_fee_sat = commit_tx_fee_sat ( feerate_per_kw, on_counterparty_htlc_count + nondust_htlcs, channel_type) ;
199- let ( on_counterparty_tx_dust_exposure_msat, extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat) = on_counterparty_tx_dust_exposure_msat (
259+ let on_counterparty_htlc_count = htlcs
260+ . iter ( )
261+ . filter ( |htlc| {
262+ !htlc. is_dust ( false , feerate_per_kw, counterparty_dust_limit_satoshis, channel_type)
263+ } )
264+ . count ( ) ;
265+ let counterparty_commit_tx_fee_sat = commit_tx_fee_sat (
266+ feerate_per_kw,
267+ on_counterparty_htlc_count + nondust_htlcs,
268+ channel_type,
269+ ) ;
270+ let (
271+ on_counterparty_tx_dust_exposure_msat,
272+ extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat,
273+ ) = on_counterparty_tx_dust_exposure_msat (
200274 dust_buffer_feerate,
201275 excess_feerate_opt,
202276 counterparty_dust_limit_satoshis,
@@ -205,7 +279,12 @@ impl TxBuilder for SpecTxBuilder {
205279 ) ;
206280
207281 // Subtract the anchors from the channel funder
208- let ( holder_balance_msat, counterparty_balance_msat) = subtract_addl_outputs ( is_outbound_from_holder, value_to_holder_after_htlcs, value_to_counterparty_after_htlcs, channel_type) ;
282+ let ( holder_balance_msat, counterparty_balance_msat) = subtract_addl_outputs (
283+ is_outbound_from_holder,
284+ value_to_holder_after_htlcs,
285+ value_to_counterparty_after_htlcs,
286+ channel_type,
287+ ) ;
209288
210289 BuilderStats {
211290 holder_commit_tx_fee_sat,
0 commit comments