1
1
//! Defines the `TxBuilder` trait, and the `SpecTxBuilder` type
2
2
#![ allow( dead_code) ]
3
3
4
- use core:: ops:: Deref ;
5
4
use core:: cmp;
5
+ use core:: ops:: Deref ;
6
6
7
7
use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 } ;
8
8
@@ -29,7 +29,10 @@ pub(crate) struct HTLCAmountDirection {
29
29
}
30
30
31
31
impl 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 {
33
36
let htlc_tx_fee_sat = if channel_type. supports_anchors_zero_fee_htlc_tx ( ) {
34
37
0
35
38
} else {
@@ -55,20 +58,35 @@ pub(crate) struct BuilderStats {
55
58
pub counterparty_balance_msat : Option < u64 > ,
56
59
}
57
60
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 {
59
65
htlcs
60
66
. 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
+ } )
62
71
. sum ( )
63
72
}
64
73
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 > ) {
66
79
let mut on_counterparty_tx_accepted_nondust_htlcs = 0 ;
67
80
let mut on_counterparty_tx_offered_nondust_htlcs = 0 ;
68
81
let mut on_counterparty_tx_dust_exposure_msat: u64 = on_remote_htlcs
69
82
. iter ( )
70
83
. 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
+ ) {
72
90
Some ( htlc. amount_msat )
73
91
} else {
74
92
if !htlc. outbound {
@@ -83,13 +101,34 @@ fn on_counterparty_tx_dust_exposure_msat(dust_buffer_feerate: u32, excess_feerat
83
101
84
102
let extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat =
85
103
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 ;
93
132
on_counterparty_tx_dust_exposure_msat += ( commit_tx_fee_sat + htlc_tx_fees_sat) * 1000 ;
94
133
extra_htlc_dust_exposure
95
134
} ) ;
@@ -141,7 +180,13 @@ fn get_dust_buffer_feerate(feerate_per_kw: u32) -> u32 {
141
180
}
142
181
143
182
pub ( 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 ;
145
190
fn commit_tx_fee_sat (
146
191
& self , feerate_per_kw : u32 , nondust_htlc_count : usize , channel_type : & ChannelTypeFeatures ,
147
192
) -> u64 ;
@@ -162,8 +207,15 @@ pub(crate) trait TxBuilder {
162
207
pub ( crate ) struct SpecTxBuilder { }
163
208
164
209
impl 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 ) ) ;
167
219
// Dust exposure is only decoupled from feerate for zero fee commitment channels.
168
220
let is_zero_fee_comm = channel_type. supports_anchor_zero_fee_commitments ( ) ;
169
221
debug_assert_eq ! ( is_zero_fee_comm, dust_exposure_limiting_feerate. is_none( ) ) ;
@@ -175,17 +227,27 @@ impl TxBuilder for SpecTxBuilder {
175
227
176
228
// Calculate balances after htlcs
177
229
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) ;
182
238
183
239
// Increment the feerate by a buffer to calculate dust exposure
184
240
let dust_buffer_feerate = get_dust_buffer_feerate ( feerate_per_kw) ;
185
241
186
242
// 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) ;
189
251
let on_holder_tx_dust_exposure_msat = on_holder_tx_dust_exposure_msat (
190
252
dust_buffer_feerate,
191
253
holder_dust_limit_satoshis,
@@ -194,9 +256,21 @@ impl TxBuilder for SpecTxBuilder {
194
256
) ;
195
257
196
258
// 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 (
200
274
dust_buffer_feerate,
201
275
excess_feerate_opt,
202
276
counterparty_dust_limit_satoshis,
@@ -205,7 +279,12 @@ impl TxBuilder for SpecTxBuilder {
205
279
) ;
206
280
207
281
// 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
+ ) ;
209
288
210
289
BuilderStats {
211
290
holder_commit_tx_fee_sat,
0 commit comments