lightning/util/anchor_channel_reserves.rs
1//! Defines anchor channel reserve requirements.
2//!
3//! The Lightning protocol advances the state of the channel based on commitment and HTLC
4//! transactions, which allow each participant to unilaterally close the channel with the correct
5//! state and resolve pending HTLCs on-chain. Originally, these transactions are signed by both
6//! counterparties over the entire transaction and therefore contain a fixed fee, which can be
7//! updated with the `update_fee` message by the funder. However, these fees can lead to
8//! disagreements and can diverge from the prevailing fee rate if a party is disconnected.
9//!
10//! To address these issues, fees are provided exogenously for anchor output channels.
11//! Anchor outputs are negotiated on channel opening to add outputs to each commitment transaction.
12//! These outputs can be spent in a child transaction with additional fees to incentivize the
13//! mining of the parent transaction, this technique is called Child Pays For Parent (CPFP).
14//! Similarly, HTLC transactions will be signed with `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` so
15//! additional inputs and outputs can be added to pay for fees.
16//!
17//! UTXO reserves will therefore be required to supply commitment transactions and HTLC
18//! transactions with fees to be confirmed in a timely manner. If HTLCs are not resolved
19//! appropriately, it can lead to loss of funds of the in-flight HLTCs as mentioned above. Only
20//! partially satisfying UTXO requirements incurs the risk of not being able to resolve a subset of
21//! HTLCs.
22use crate::chain::chaininterface::BroadcasterInterface;
23use crate::chain::chaininterface::FeeEstimator;
24use crate::chain::chainmonitor::ChainMonitor;
25use crate::chain::chainmonitor::Persist;
26use crate::chain::Filter;
27use crate::events::bump_transaction::Utxo;
28use crate::ln::chan_utils::max_htlcs;
29use crate::ln::channelmanager::AChannelManager;
30use crate::prelude::new_hash_set;
31use crate::sign::ecdsa::EcdsaChannelSigner;
32use crate::sign::EntropySource;
33use crate::types::features::ChannelTypeFeatures;
34use crate::util::logger::Logger;
35use bitcoin::constants::WITNESS_SCALE_FACTOR;
36use bitcoin::Amount;
37use bitcoin::FeeRate;
38use bitcoin::Weight;
39use core::cmp::min;
40use core::ops::Deref;
41
42// Transaction weights based on:
43// https://github.com/lightning/bolts/blob/master/03-transactions.md#appendix-a-expected-weights
44const COMMITMENT_TRANSACTION_BASE_WEIGHT: u64 = 900 + 224;
45const COMMITMENT_TRANSACTION_PER_HTLC_WEIGHT: u64 = 172;
46const PER_HTLC_TIMEOUT_WEIGHT: u64 = 666;
47const PER_HTLC_SUCCESS_WEIGHT: u64 = 706;
48
49// The transaction at least contains:
50// - 4 bytes for the version
51// - 4 bytes for the locktime
52// - 1 byte for the number of inputs
53// - 1 byte for the number of outputs
54// - 2 bytes for the witness header
55// - 1 byte for the flag
56// - 1 byte for the marker
57const TRANSACTION_BASE_WEIGHT: u64 = (4 + 4 + 1 + 1) * WITNESS_SCALE_FACTOR as u64 + 2;
58
59// A P2WPKH input consists of:
60// - 36 bytes for the previous outpoint:
61// - 32 bytes transaction hash
62// - 4 bytes index
63// - 4 bytes for the sequence
64// - 1 byte for the script sig length
65// - the witness:
66// - 1 byte for witness items count
67// - 1 byte for the signature length
68// - 72 bytes for the signature
69// - 1 byte for the public key length
70// - 33 bytes for the public key
71const P2WPKH_INPUT_WEIGHT: u64 = (36 + 4 + 1) * WITNESS_SCALE_FACTOR as u64 + (1 + 1 + 72 + 1 + 33);
72
73// A P2WPKH output consists of:
74// - 8 bytes for the output amount
75// - 1 byte for the script length
76// - 22 bytes for the script (OP_0 OP_PUSH20 20 byte public key hash)
77const P2WPKH_OUTPUT_WEIGHT: u64 = (8 + 1 + 22) * WITNESS_SCALE_FACTOR as u64;
78
79// A P2TR key path input consists of:
80// - 36 bytes for the previous outpoint:
81// - 32 bytes transaction hash
82// - 4 bytes index
83// - 4 bytes for the sequence
84// - 1 byte for the script sig length
85// - the witness:
86// - 1 byte for witness items count
87// - 1 byte for the signature length
88// - 64 bytes for the Schnorr signature
89const P2TR_KEYPATH_INPUT_WEIGHT: u64 = (36 + 4 + 1) * WITNESS_SCALE_FACTOR as u64 + (1 + 1 + 64);
90// A P2TR output consists of:
91// - 8 bytes for the output amount
92// - 1 byte for the script length
93// - 34 bytes for the script (OP_1 OP_PUSH32 32 byte Schnorr public key)
94const P2TR_OUTPUT_WEIGHT: u64 = (8 + 1 + 34) * WITNESS_SCALE_FACTOR as u64;
95
96// An P2WSH anchor input consists of:
97// - 36 bytes for the previous outpoint:
98// - 32 bytes transaction hash
99// - 4 bytes index
100// - 4 bytes for the sequence
101// - 1 byte for the script sig length
102// - the witness:
103// - 1 byte for witness item count
104// - 1 byte for signature length
105// - 72 bytes signature
106// - 1 byte for script length
107// - 40 byte script
108// <pubkey> OP_CHECKSIG OP_IFDUP OP_NOTIF OP_16 OP_CHECKSEQUENCEVERIFY OP_ENDIF
109// - 33 byte pubkey with 1 byte OP_PUSHBYTES_33.
110// - 6 1-byte opcodes
111const ANCHOR_INPUT_WEIGHT: u64 = (36 + 4 + 1) * WITNESS_SCALE_FACTOR as u64 + (1 + 1 + 72 + 1 + 40);
112
113fn htlc_success_transaction_weight(context: &AnchorChannelReserveContext) -> u64 {
114 PER_HTLC_SUCCESS_WEIGHT
115 + if context.taproot_wallet {
116 P2TR_KEYPATH_INPUT_WEIGHT + P2TR_OUTPUT_WEIGHT
117 } else {
118 P2WPKH_INPUT_WEIGHT + P2WPKH_OUTPUT_WEIGHT
119 }
120}
121
122fn htlc_timeout_transaction_weight(context: &AnchorChannelReserveContext) -> u64 {
123 PER_HTLC_TIMEOUT_WEIGHT
124 + if context.taproot_wallet {
125 P2TR_KEYPATH_INPUT_WEIGHT + P2TR_OUTPUT_WEIGHT
126 } else {
127 P2WPKH_INPUT_WEIGHT + P2WPKH_OUTPUT_WEIGHT
128 }
129}
130
131fn anchor_output_spend_transaction_weight(
132 context: &AnchorChannelReserveContext, input_weight: Weight,
133) -> u64 {
134 TRANSACTION_BASE_WEIGHT
135 + ANCHOR_INPUT_WEIGHT
136 + input_weight.to_wu()
137 + if context.taproot_wallet { P2TR_OUTPUT_WEIGHT } else { P2WPKH_OUTPUT_WEIGHT }
138}
139
140/// Parameters defining the context around the anchor channel reserve requirement calculation.
141#[derive(Clone, Debug, PartialEq, Eq)]
142pub struct AnchorChannelReserveContext {
143 /// An upper bound fee rate estimate used to calculate the anchor channel reserve that is
144 /// sufficient to provide fees for all required transactions.
145 pub upper_bound_fee_rate: FeeRate,
146 /// The expected number of accepted in-flight HTLCs per channel.
147 ///
148 /// Note that malicious counterparties can saturate the number of accepted in-flight HTLCs up to
149 /// the maximum prior to forcing a unilateral closure. This estimate can include that case as a
150 /// weighted average, assuming some percentage of channels are controlled by malicious peers and
151 /// have the maximum number of accepted in-flight HTLCs.
152 ///
153 /// See [ChannelHandshakeConfig::our_max_accepted_htlcs] to configure the maximum number of
154 /// accepted in-flight HTLCs.
155 ///
156 /// [ChannelHandshakeConfig::our_max_accepted_htlcs]: crate::util::config::ChannelHandshakeConfig::our_max_accepted_htlcs
157 pub expected_accepted_htlcs: u16,
158 /// Whether the wallet handling anchor channel reserves creates Taproot P2TR outputs for any new
159 /// outputs, or Segwit P2WPKH outputs otherwise.
160 pub taproot_wallet: bool,
161}
162
163/// A default for the [AnchorChannelReserveContext] parameters is provided as follows:
164/// - The upper bound fee rate is set to the 99th percentile of the median block fee rate since 2019:
165/// ~50 sats/vbyte.
166/// - The number of accepted in-flight HTLCs per channel is set to 10, providing additional margin
167/// above the number seen for a large routing node over a month (average <1, maximum 10
168/// accepted in-flight HTLCS aggregated across all channels).
169/// - The wallet is assumed to be a Segwit wallet.
170impl Default for AnchorChannelReserveContext {
171 fn default() -> Self {
172 AnchorChannelReserveContext {
173 upper_bound_fee_rate: FeeRate::from_sat_per_kwu(50 * 250),
174 expected_accepted_htlcs: 10,
175 taproot_wallet: false,
176 }
177 }
178}
179
180fn get_reserve_per_channel_with_input(
181 context: &AnchorChannelReserveContext, initial_input_weight: Weight,
182) -> Amount {
183 let max_max_htlcs = max_htlcs(&ChannelTypeFeatures::only_static_remote_key());
184 let expected_accepted_htlcs = min(context.expected_accepted_htlcs, max_max_htlcs) as u64;
185 let weight = Weight::from_wu(
186 COMMITMENT_TRANSACTION_BASE_WEIGHT +
187 // Reserves are calculated in terms of accepted HTLCs, as their timeout defines the urgency of
188 // on-chain resolution. Each accepted HTLC is assumed to be forwarded to calculate an upper
189 // bound for the reserve, resulting in `expected_accepted_htlcs` inbound HTLCs and
190 // `expected_accepted_htlcs` outbound HTLCs per channel in aggregate.
191 2 * expected_accepted_htlcs * COMMITMENT_TRANSACTION_PER_HTLC_WEIGHT +
192 anchor_output_spend_transaction_weight(context, initial_input_weight) +
193 // As an upper bound, it is assumed that each HTLC is resolved in a separate transaction.
194 // However, they might be aggregated when possible depending on timelocks and expiries.
195 htlc_success_transaction_weight(context) * expected_accepted_htlcs +
196 htlc_timeout_transaction_weight(context) * expected_accepted_htlcs,
197 );
198 context.upper_bound_fee_rate.fee_wu(weight).unwrap_or(Amount::MAX)
199}
200
201/// Returns the amount that needs to be maintained as a reserve per anchor channel.
202///
203/// This reserve currently needs to be allocated as a disjoint set of at least 1 UTXO per channel,
204/// as claims are not yet aggregated across channels.
205///
206/// To only require 1 UTXO per channel, it is assumed that, on average, transactions are able to
207/// get confirmed within 1 block with [ConfirmationTarget::UrgentOnChainSweep], or that only a
208/// portion of channels will go through unilateral closure at the same time, allowing UTXOs to be
209/// shared. Otherwise, multiple UTXOs would be needed per channel:
210/// - HTLC time-out transactions with different expiries cannot be aggregated. This could result in
211/// many individual transactions that need to be confirmed starting from different, but potentially
212/// sequential block heights.
213/// - If each transaction takes N blocks to confirm, at least N UTXOs per channel are needed to
214/// provide the necessary concurrency.
215///
216/// The returned amount includes the fee to spend a single UTXO of the type indicated by
217/// [AnchorChannelReserveContext::taproot_wallet]. Larger sets of UTXOs with more complex witnesses
218/// will need to include the corresponding fee required to spend them.
219///
220/// [ConfirmationTarget::UrgentOnChainSweep]: crate::chain::chaininterface::ConfirmationTarget::UrgentOnChainSweep
221pub fn get_reserve_per_channel(context: &AnchorChannelReserveContext) -> Amount {
222 get_reserve_per_channel_with_input(
223 context,
224 if context.taproot_wallet {
225 Weight::from_wu(P2TR_KEYPATH_INPUT_WEIGHT)
226 } else {
227 Weight::from_wu(P2WPKH_INPUT_WEIGHT)
228 },
229 )
230}
231
232/// Calculates the number of anchor channels that can be supported by the reserve provided
233/// by `utxos`.
234pub fn get_supportable_anchor_channels(
235 context: &AnchorChannelReserveContext, utxos: &[Utxo],
236) -> u64 {
237 // Get the reserve needed per channel, accounting for the actual satisfaction weight below.
238 let reserve_per_channel = get_reserve_per_channel_with_input(context, Weight::ZERO);
239
240 let mut total_fractional_amount = Amount::from_sat(0);
241 let mut num_whole_utxos = 0;
242 for utxo in utxos {
243 let satisfaction_fee = context
244 .upper_bound_fee_rate
245 .fee_wu(Weight::from_wu(utxo.satisfaction_weight))
246 .unwrap_or(Amount::MAX);
247 let amount = utxo.output.value.checked_sub(satisfaction_fee).unwrap_or(Amount::MIN);
248 if amount >= reserve_per_channel {
249 num_whole_utxos += 1;
250 } else {
251 total_fractional_amount =
252 total_fractional_amount.checked_add(amount).unwrap_or(Amount::MAX);
253 }
254 }
255 // We require disjoint sets of UTXOs for the reserve of each channel,
256 // as claims are currently only aggregated per channel.
257 //
258 // A worst-case coin selection is assumed for fractional UTXOs, selecting up to double the
259 // required amount.
260 num_whole_utxos + total_fractional_amount.to_sat() / reserve_per_channel.to_sat() / 2
261}
262
263/// Verifies whether the anchor channel reserve provided by `utxos` is sufficient to support
264/// an additional anchor channel.
265///
266/// This should be verified:
267/// - Before opening a new outbound anchor channel with [ChannelManager::create_channel].
268/// - Before accepting a new inbound anchor channel while handling [Event::OpenChannelRequest].
269///
270/// [ChannelManager::create_channel]: crate::ln::channelmanager::ChannelManager::create_channel
271/// [Event::OpenChannelRequest]: crate::events::Event::OpenChannelRequest
272pub fn can_support_additional_anchor_channel<
273 AChannelManagerRef: Deref,
274 ChannelSigner: EcdsaChannelSigner,
275 FilterRef: Deref,
276 BroadcasterRef: Deref,
277 EstimatorRef: Deref,
278 LoggerRef: Deref,
279 PersistRef: Deref,
280 EntropySourceRef: Deref,
281 ChainMonitorRef: Deref<
282 Target = ChainMonitor<
283 ChannelSigner,
284 FilterRef,
285 BroadcasterRef,
286 EstimatorRef,
287 LoggerRef,
288 PersistRef,
289 EntropySourceRef,
290 >,
291 >,
292>(
293 context: &AnchorChannelReserveContext, utxos: &[Utxo], a_channel_manager: AChannelManagerRef,
294 chain_monitor: ChainMonitorRef,
295) -> bool
296where
297 AChannelManagerRef::Target: AChannelManager,
298 FilterRef::Target: Filter,
299 BroadcasterRef::Target: BroadcasterInterface,
300 EstimatorRef::Target: FeeEstimator,
301 LoggerRef::Target: Logger,
302 PersistRef::Target: Persist<ChannelSigner>,
303 EntropySourceRef::Target: EntropySource,
304{
305 let mut anchor_channels = new_hash_set();
306 // Calculate the number of in-progress anchor channels by inspecting ChannelMonitors with balance.
307 // This includes channels that are in the process of being resolved on-chain.
308 for channel_id in chain_monitor.list_monitors() {
309 let channel_monitor = if let Ok(channel_monitor) = chain_monitor.get_monitor(channel_id) {
310 channel_monitor
311 } else {
312 continue;
313 };
314 if channel_monitor.channel_type_features().supports_anchors_zero_fee_htlc_tx()
315 && !channel_monitor.get_claimable_balances().is_empty()
316 {
317 anchor_channels.insert(channel_id);
318 }
319 }
320 // Also include channels that are in the middle of negotiation or anchor channels that don't have
321 // a ChannelMonitor yet.
322 for channel in a_channel_manager.get_cm().list_channels() {
323 if channel.channel_type.map_or(true, |ct| ct.supports_anchors_zero_fee_htlc_tx()) {
324 anchor_channels.insert(channel.channel_id);
325 }
326 }
327 get_supportable_anchor_channels(context, utxos) > anchor_channels.len() as u64
328}
329
330#[cfg(test)]
331mod test {
332 use super::*;
333 use bitcoin::{OutPoint, ScriptBuf, TxOut, Txid};
334 use std::str::FromStr;
335
336 #[test]
337 fn test_get_reserve_per_channel() {
338 // At a 1000 sats/kw, with 4 expected transactions at ~1kw (commitment transaction, anchor
339 // output spend transaction, 2 HTLC transactions), we expect the reserve to be around 4k sats.
340 assert_eq!(
341 get_reserve_per_channel(&AnchorChannelReserveContext {
342 upper_bound_fee_rate: FeeRate::from_sat_per_kwu(1000),
343 expected_accepted_htlcs: 1,
344 taproot_wallet: false,
345 }),
346 Amount::from_sat(4349)
347 );
348 }
349
350 fn make_p2wpkh_utxo(amount: Amount) -> Utxo {
351 Utxo {
352 outpoint: OutPoint {
353 txid: Txid::from_str(
354 "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
355 )
356 .unwrap(),
357 vout: 0,
358 },
359 output: TxOut { value: amount, script_pubkey: ScriptBuf::new() },
360 satisfaction_weight: 1 * 4 + (1 + 1 + 72 + 1 + 33),
361 }
362 }
363
364 #[test]
365 fn test_get_supportable_anchor_channels() {
366 let context = AnchorChannelReserveContext::default();
367 let reserve_per_channel = get_reserve_per_channel(&context);
368 // Only 3 disjoint sets with a value greater than the required reserve can be created.
369 let utxos = vec![
370 make_p2wpkh_utxo(reserve_per_channel * 3 / 2),
371 make_p2wpkh_utxo(reserve_per_channel),
372 make_p2wpkh_utxo(reserve_per_channel * 99 / 100),
373 make_p2wpkh_utxo(reserve_per_channel * 99 / 100),
374 make_p2wpkh_utxo(reserve_per_channel * 20 / 100),
375 ];
376 assert_eq!(get_supportable_anchor_channels(&context, utxos.as_slice()), 3);
377 }
378
379 #[test]
380 fn test_anchor_output_spend_transaction_weight() {
381 // Example with smaller signatures:
382 // https://mempool.space/tx/188b0f9f26999a48611dba4e2a88507251eba31f3695d005023de3514cba34bd
383 // DER-encoded ECDSA signatures vary in size and can be 71-73 bytes.
384 assert_eq!(
385 anchor_output_spend_transaction_weight(
386 &AnchorChannelReserveContext { taproot_wallet: false, ..Default::default() },
387 Weight::from_wu(P2WPKH_INPUT_WEIGHT),
388 ),
389 717
390 );
391
392 // Example:
393 // https://mempool.space/tx/9c493177e395ec77d9e725e1cfd465c5f06d4a5816dd0274c3a8c2442d854a85
394 assert_eq!(
395 anchor_output_spend_transaction_weight(
396 &AnchorChannelReserveContext { taproot_wallet: true, ..Default::default() },
397 Weight::from_wu(P2TR_KEYPATH_INPUT_WEIGHT),
398 ),
399 723
400 );
401 }
402
403 #[test]
404 fn test_htlc_success_transaction_weight() {
405 assert_eq!(
406 htlc_success_transaction_weight(&AnchorChannelReserveContext {
407 taproot_wallet: false,
408 ..Default::default()
409 }),
410 1102
411 );
412
413 assert_eq!(
414 htlc_success_transaction_weight(&AnchorChannelReserveContext {
415 taproot_wallet: true,
416 ..Default::default()
417 }),
418 1108
419 );
420 }
421
422 #[test]
423 fn test_htlc_timeout_transaction_weight() {
424 // Example with smaller signatures:
425 // https://mempool.space/tx/37185342f9f088bd12376599b245dbc02eb0bb6c4b99568b75a8cd775ddfd1f4
426 assert_eq!(
427 htlc_timeout_transaction_weight(&AnchorChannelReserveContext {
428 taproot_wallet: false,
429 ..Default::default()
430 }),
431 1062
432 );
433
434 assert_eq!(
435 htlc_timeout_transaction_weight(&AnchorChannelReserveContext {
436 taproot_wallet: true,
437 ..Default::default()
438 }),
439 1068
440 );
441 }
442}