@@ -126,14 +126,13 @@ fn htlc_timeout_transaction_weight(context: &AnchorChannelReserveContext) -> u64
126
126
}
127
127
}
128
128
129
- fn anchor_output_spend_transaction_weight ( context : & AnchorChannelReserveContext ) -> u64 {
129
+ fn anchor_output_spend_transaction_weight (
130
+ context : & AnchorChannelReserveContext , input_weight : Weight ,
131
+ ) -> u64 {
130
132
TRANSACTION_BASE_WEIGHT
131
133
+ ANCHOR_INPUT_WEIGHT
132
- + if context. taproot_wallet {
133
- P2TR_INPUT_WEIGHT + P2TR_OUTPUT_WEIGHT
134
- } else {
135
- P2WPKH_INPUT_WEIGHT + P2WPKH_OUTPUT_WEIGHT
136
- }
134
+ + input_weight. to_wu ( )
135
+ + if context. taproot_wallet { P2TR_OUTPUT_WEIGHT } else { P2WPKH_OUTPUT_WEIGHT }
137
136
}
138
137
139
138
/// Parameters defining the context around the anchor channel reserve requirement calculation.
@@ -178,12 +177,8 @@ impl Default for AnchorChannelReserveContext {
178
177
}
179
178
}
180
179
181
- /// Returns the amount that needs to be maintained as a reserve per anchor channel.
182
- ///
183
- /// This reserve currently needs to be allocated as a disjoint set of UTXOs per channel,
184
- /// as claims are not yet aggregated across channels.
185
- pub fn get_reserve_per_channel (
186
- context : & AnchorChannelReserveContext ,
180
+ fn get_reserve_per_channel_with_input (
181
+ context : & AnchorChannelReserveContext , initial_input_weight : Weight ,
187
182
) -> Result < Amount , AnchorChannelReserveError > {
188
183
let num_htlcs = min ( context. expected_accepted_htlcs , MAX_HTLCS ) as u64 ;
189
184
let weight = Weight :: from_wu (
@@ -193,7 +188,7 @@ pub fn get_reserve_per_channel(
193
188
// bound for the reserve, resulting in `expected_accepted_htlcs` inbound HTLCs and
194
189
// `expected_accepted_htlcs` outbound HTLCs per channel in aggregate.
195
190
2 * num_htlcs * COMMITMENT_TRANSACTION_PER_HTLC_WEIGHT +
196
- anchor_output_spend_transaction_weight ( context) +
191
+ anchor_output_spend_transaction_weight ( context, initial_input_weight ) +
197
192
// As an upper bound, it is assumed that each HTLC is resolved in a separate transaction.
198
193
// However, they might be aggregated when possible depending on timelocks and expiries.
199
194
htlc_success_transaction_weight ( context) * num_htlcs +
@@ -202,22 +197,35 @@ pub fn get_reserve_per_channel(
202
197
context. upper_bound_fee_rate . fee_wu ( weight) . ok_or ( AnchorChannelReserveError :: FeeOverflow )
203
198
}
204
199
200
+ /// Returns the amount that needs to be maintained as a reserve per anchor channel.
201
+ ///
202
+ /// This reserve currently needs to be allocated as a disjoint set of UTXOs per channel,
203
+ /// as claims are not yet aggregated across channels.
204
+ ///
205
+ /// Note that the returned amount assumes that the reserve will be provided by a single UTXO of the
206
+ /// type indicated by [AnchorChannelReserveContext::taproot_wallet]. Larger sets of UTXOs with more
207
+ /// complex witnesses will require a correspondingly larger reserve due to the weight required to
208
+ /// spend them.
209
+ pub fn get_reserve_per_channel (
210
+ context : & AnchorChannelReserveContext ,
211
+ ) -> Result < Amount , AnchorChannelReserveError > {
212
+ get_reserve_per_channel_with_input (
213
+ context,
214
+ if context. taproot_wallet {
215
+ Weight :: from_wu ( P2TR_INPUT_WEIGHT )
216
+ } else {
217
+ Weight :: from_wu ( P2WPKH_INPUT_WEIGHT )
218
+ } ,
219
+ )
220
+ }
221
+
205
222
/// Calculates the number of anchor channels that can be supported by the reserve provided
206
223
/// by `utxos`.
207
224
pub fn get_supportable_anchor_channels (
208
225
context : & AnchorChannelReserveContext , utxos : & [ Utxo ] ,
209
226
) -> Result < u64 , AnchorChannelReserveError > {
210
- // Get the reserve needed per channel, replacing the fee for an initial spend with the actual value
211
- // below.
212
- let default_satisfaction_fee = context
213
- . upper_bound_fee_rate
214
- . fee_wu ( Weight :: from_wu ( if context. taproot_wallet {
215
- P2TR_INPUT_WEIGHT
216
- } else {
217
- P2WPKH_INPUT_WEIGHT
218
- } ) )
219
- . ok_or ( AnchorChannelReserveError :: FeeOverflow ) ?;
220
- let reserve_per_channel = get_reserve_per_channel ( context) ? - default_satisfaction_fee;
227
+ // Get the reserve needed per channel, accounting for the actual satisfaction weight below.
228
+ let reserve_per_channel = get_reserve_per_channel_with_input ( context, Weight :: ZERO ) ?;
221
229
222
230
let mut total_fractional_amount = Amount :: from_sat ( 0 ) ;
223
231
let mut num_whole_utxos = 0 ;
@@ -368,20 +376,20 @@ mod test {
368
376
// https://mempool.space/tx/188b0f9f26999a48611dba4e2a88507251eba31f3695d005023de3514cba34bd
369
377
// DER-encoded ECDSA signatures vary in size and can be 71-73 bytes.
370
378
assert_eq ! (
371
- anchor_output_spend_transaction_weight( & AnchorChannelReserveContext {
372
- taproot_wallet: false ,
373
- .. Default :: default ( )
374
- } ) ,
379
+ anchor_output_spend_transaction_weight(
380
+ & AnchorChannelReserveContext { taproot_wallet: false , .. Default :: default ( ) } ,
381
+ Weight :: from_wu ( P2WPKH_INPUT_WEIGHT ) ,
382
+ ) ,
375
383
717
376
384
) ;
377
385
378
386
// Example:
379
387
// https://mempool.space/tx/9c493177e395ec77d9e725e1cfd465c5f06d4a5816dd0274c3a8c2442d854a85
380
388
assert_eq ! (
381
- anchor_output_spend_transaction_weight( & AnchorChannelReserveContext {
382
- taproot_wallet: true ,
383
- .. Default :: default ( )
384
- } ) ,
389
+ anchor_output_spend_transaction_weight(
390
+ & AnchorChannelReserveContext { taproot_wallet: true , .. Default :: default ( ) } ,
391
+ Weight :: from_wu ( P2TR_INPUT_WEIGHT ) ,
392
+ ) ,
385
393
723
386
394
) ;
387
395
}
0 commit comments