@@ -126,14 +126,13 @@ fn htlc_timeout_transaction_weight(context: &AnchorChannelReserveContext) -> u64
126126 }
127127}
128128
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 {
130132 TRANSACTION_BASE_WEIGHT
131133 + 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 }
137136}
138137
139138/// Parameters defining the context around the anchor channel reserve requirement calculation.
@@ -178,12 +177,8 @@ impl Default for AnchorChannelReserveContext {
178177 }
179178}
180179
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 ,
187182) -> Result < Amount , AnchorChannelReserveError > {
188183 let num_htlcs = min ( context. expected_accepted_htlcs , MAX_HTLCS ) as u64 ;
189184 let weight = Weight :: from_wu (
@@ -193,7 +188,7 @@ pub fn get_reserve_per_channel(
193188 // bound for the reserve, resulting in `expected_accepted_htlcs` inbound HTLCs and
194189 // `expected_accepted_htlcs` outbound HTLCs per channel in aggregate.
195190 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 ) +
197192 // As an upper bound, it is assumed that each HTLC is resolved in a separate transaction.
198193 // However, they might be aggregated when possible depending on timelocks and expiries.
199194 htlc_success_transaction_weight ( context) * num_htlcs +
@@ -202,22 +197,35 @@ pub fn get_reserve_per_channel(
202197 context. upper_bound_fee_rate . fee_wu ( weight) . ok_or ( AnchorChannelReserveError :: FeeOverflow )
203198}
204199
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+
205222/// Calculates the number of anchor channels that can be supported by the reserve provided
206223/// by `utxos`.
207224pub fn get_supportable_anchor_channels (
208225 context : & AnchorChannelReserveContext , utxos : & [ Utxo ] ,
209226) -> 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 ) ?;
221229
222230 let mut total_fractional_amount = Amount :: from_sat ( 0 ) ;
223231 let mut num_whole_utxos = 0 ;
@@ -368,20 +376,20 @@ mod test {
368376 // https://mempool.space/tx/188b0f9f26999a48611dba4e2a88507251eba31f3695d005023de3514cba34bd
369377 // DER-encoded ECDSA signatures vary in size and can be 71-73 bytes.
370378 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+ ) ,
375383 717
376384 ) ;
377385
378386 // Example:
379387 // https://mempool.space/tx/9c493177e395ec77d9e725e1cfd465c5f06d4a5816dd0274c3a8c2442d854a85
380388 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+ ) ,
385393 723
386394 ) ;
387395 }
0 commit comments