Skip to content

Commit c406a74

Browse files
author
Antoine Riard
committed
-f Add documentation in onchain_utils
1 parent 7161338 commit c406a74

File tree

1 file changed

+90
-44
lines changed

1 file changed

+90
-44
lines changed

lightning/src/chain/onchain_utils.rs

Lines changed: 90 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
//! Utilities for computing witnesses weight and feerate computation for onchain operation
1+
// This file is Copyright its original authors, visible in version control
2+
// history.
3+
//
4+
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5+
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7+
// You may not use this file except in accordance with one or both of these
8+
// licenses.
9+
10+
//! Various utilities to assemble claimable outpoints in package of one or more transactions. Those
11+
//! packages are attached metadatas, guiding their aggregation or fee-bumping re-schedule. This file
12+
//! also includes witness weight computation and fee computation methods.
213
314
use bitcoin::blockdata::transaction::{TxOut,TxIn, Transaction, SigHashType};
415
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
@@ -24,6 +35,8 @@ use std::ops::Deref;
2435

2536
const MAX_ALLOC_SIZE: usize = 64*1024;
2637

38+
39+
/// witnessScript markers used to compute the expected witness weight.
2740
#[derive(PartialEq, Clone, Copy)]
2841
pub(crate) enum InputDescriptors {
2942
RevokedOfferedHTLC,
@@ -80,6 +93,8 @@ impl Readable for InputDescriptors {
8093
}
8194
}
8295

96+
/// Sum up witnesses weight of a set of given inputs. Inputs might belong to differing descriptors.
97+
/// Weights should be compliant with BOLT 3 Appendix A.
8398
pub(crate) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
8499
let mut tx_weight = 2; // count segwit flags
85100
for inp in inputs {
@@ -110,9 +125,16 @@ pub(crate) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
110125
tx_weight
111126
}
112127

113-
/// A struct to describe a revoked output, the templated witnessScript variables to claim it
114-
/// (hash, timelock, pubkeys) and per_commitment_key to generate a solving witness. It is used by
115-
/// OnchainTxHandler to generate a valid transaction claiming this output.
128+
/// A struct to describe a revoked output and corresponding informations to generate a solving
129+
/// witness.
130+
///
131+
/// If the revoked output is a HTLC output on a committment transaction, HTLCOuputInCommitment (hash
132+
/// timelock, direction), pubkeys are used to generate the suiting witnessScript.
133+
///
134+
/// Otherwise, CSV is used to generate a witnessScript redeeming a balance output on a commitment
135+
/// transaction or second-stage HTLC transaction.
136+
///
137+
/// Amount and revocation secret are used in both cases.
116138
#[derive(Clone, PartialEq)]
117139
pub(crate) struct RevokedOutput {
118140
per_commitment_point: PublicKey,
@@ -177,9 +199,12 @@ impl Readable for RevokedOutput {
177199
}
178200
}
179201

180-
/// A struct to describe a counterparty htlc output, the templated witnessScript variables to claim it (hash,
181-
/// timelock, pubkeys) and preimage to generate a solving witness. It is used by OnchainTxHandler
182-
/// to generate a valid transaction claiming this output.
202+
/// A struct to describe a HTLC output on a counterparty commitment transaction.
203+
///
204+
/// HTLCOutputInCommitment (hash, timelock, directon) and pubkeys are used to generate the suiting
205+
/// witnessScript.
206+
///
207+
/// If the HTLC is offered to holder, the preimae is used as part of the witness.
183208
#[derive(Clone, PartialEq)]
184209
pub(crate) struct CounterpartyHTLCOutput {
185210
per_commitment_point: PublicKey,
@@ -229,9 +254,10 @@ impl Readable for CounterpartyHTLCOutput {
229254
}
230255
}
231256

232-
/// A struct to describe a holder htlc output, amount and preimage to generate a signature and
233-
/// solving witness. It is used by OnchainTxHandler to finalize a HTLC transaction claiming this
234-
/// output.
257+
/// A struct to describe a HTLC output on holder commitment transaction.
258+
///
259+
/// Either offered or received, the amount is always used as part of the bip143 sighash.
260+
/// Preimage is only included as part of the witness in former case.
235261
#[derive(Clone, PartialEq)]
236262
pub(crate) struct HolderHTLCOutput {
237263
preimage: Option<PaymentPreimage>,
@@ -266,8 +292,9 @@ impl Readable for HolderHTLCOutput {
266292
}
267293
}
268294

269-
/// A struct to describe a holder funding output with the static witnessScript to claim it. It is
270-
/// used by OnchainTxHandler to finalize a holder commitment transaction claiming this output.
295+
/// A struct to describe the channel output on the funding transaction.
296+
///
297+
/// witnessScript is used as part of the witness redeeming the funding utxo.
271298
#[derive(Clone, PartialEq)]
272299
pub(crate) struct HolderFundingOutput {
273300
funding_redeemscript: Script,
@@ -296,6 +323,10 @@ impl Readable for HolderFundingOutput {
296323
}
297324
}
298325

326+
/// A wrapper encapsulating all in-protocol differing outputs categories.
327+
///
328+
/// The generic API offers access to outputs attributes (amount, weight, category) or allow
329+
/// transformation such as finalizing an input claiming the output.
299330
#[derive(Clone, PartialEq)]
300331
pub(crate) enum PackageSolvingData {
301332
RevokedOutput(RevokedOutput),
@@ -431,6 +462,9 @@ impl Readable for PackageSolvingData {
431462
}
432463
}
433464

465+
/// A malleable package might be aggregated with other packages to save on fees.
466+
/// A untractable package has been counter-signed and aggregation will break cached counterparty
467+
/// signatures.
434468
#[derive(Clone, PartialEq)]
435469
pub(crate) enum PackageMalleability {
436470
Malleable,
@@ -467,48 +501,47 @@ impl Readable for PackageMalleability {
467501
}
468502
}
469503

470-
/// An enum to describe a claim content which is generated by ChannelMonitor and
471-
/// used by OnchainTxHandler to regenerate feerate-bump transactions to settle claims.
504+
/// A structure to describe a package content which is generated by ChannelMonitor and
505+
/// used by OnchainTxHandler to generate and broadcast transactions settling onchain claims.
472506
///
473-
/// Template may be either malleable (a justice tx, a counterparty HTLC tx) or lockdown (a holder htlc
474-
/// tx, a holder commitment tx, a pre-signed justice tx). Bumping can be a Replace-by-Fee, that way
475-
/// the claim-settlement tx in itself has its feerate increased or Child-Pay-For-Parent, a child
476-
/// of the claim tx has its feerate increased. For the latter case, access to the whole package
477-
/// sizea and pre-committed fee is required to compute an efficient bump.
507+
/// A package is defined as one or more transactions claiming onchain outputs in reaction
508+
/// to confirmation of a channel transaction. Those packages might be aggregated to save on
509+
/// fees, if satisfaction of outputs's witnessScript let's us do so.
478510
///
479-
/// Metadata are related to multiple fields playing a role in package lifetime.
480-
/// Once issued, it may be aggregated with other package if it's judged safe
481-
/// and feerate opportunistic.
482-
/// Current LN fees model, pre-committed fees with update_fee adjustement, means
483-
/// that counter-signed transactions must be CPFP to be dynamically confirmed as a
484-
/// bumping strategy. If transactions aren't lockdown (i.e justice transactions) we
485-
/// may RBF them.
486-
/// Feerate previous will serve as a feerate floor between different bumping attempts.
487-
/// Height timer clocks these different bumping attempts.
488-
/// Absolute timelock defines the block barrier at which claiming isn't exclusive
489-
/// to us anymore and thus we MUST have get it solved before.
490-
/// Height original serves as a packet timestamps to prune out claim in case of reorg.
491-
/// Content embeds transactions elements to generate transaction. See PackageTemplate.
511+
/// As packages are time-sensitive, we fee-bump and rebroadcast them at scheduled intervals.
512+
/// Failing to confirm a package translate as a loss of funds for the user.
492513
#[derive(Clone, PartialEq)]
493514
pub(crate) struct PackageTemplate {
515+
// List of onchain outputs and solving data to generate satisfying witnesses.
494516
inputs: Vec<(BitcoinOutPoint, PackageSolvingData)>,
517+
// Packages are deemed as malleable if we have local knwoledge of at least one set of
518+
// private keys yelling a satisfying witnesses. Malleability implies that we can aggregate
519+
// packages among them to save on fees or rely on RBF to bump their feerates.
520+
// Untractable packages have been counter-signed and thus imply that we can't aggregate
521+
// them without breaking signatures. Fee-bumping strategy will also rely on CPFP.
495522
malleability: PackageMalleability,
496-
// Block height before which claiming is exclusive to one party,
497-
// after reaching it, claiming may be contentious.
523+
// Block height after which the soonest-output belonging to this package is mature for a
524+
// competing claim by the counterparty. As our chain tip becomes nearer from the timelock,
525+
// the fee-bumping frequency will increase. See `OnchainTxHandler::get_height_timer`.
498526
absolute_timelock: u32,
499-
// Timeout tx must have nLocktime set which means aggregating multiple
500-
// ones must take the higher nLocktime among them to satisfy all of them.
501-
// Sadly it has few pitfalls, a) it takes longuer to get fund back b) CLTV_DELTA
502-
// of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
503-
// To simplify we mark them as non-aggregable.
527+
// Timelocked outputs belonging to the same transaction might have differing
528+
// satisfying heights. Picking up the highest height among the output set would be a valid
529+
// aggregation strategy but it comes with at least 2 trade-offs :
530+
// * soonest-output fund are going to take longer to come back
531+
// * CLTV delta backing up a corresponding HTLC on an upstream channel could be swallowed
532+
// by the requirement of the highest-output part of the set
533+
// For now, we mark such timelocked outputs as non-aggregable, though we might introduce
534+
// smarter aggregation strategy in the future.
504535
aggregation: bool,
505-
// Based feerate of previous broadcast. If resources available (either
506-
// output value or utxo bumping).
536+
// Cache of package feerate committed at previous (re)broadcast. If bumping resources
537+
// (either claimed output value or external utxo), it will keep increasing until holder
538+
// or counterparty successful claim.
507539
feerate_previous: u64,
508-
// At every block tick, used to check if pending claiming tx is taking too
509-
// much time for confirmation and we need to bump it.
540+
// Cache of next height at which fee-bumping and rebroadcast will be attempted. In
541+
// the future, we might abstract it to an observed mempool fluctuation.
510542
height_timer: Option<u32>,
511-
// Tracked in case of reorg to wipe out now-superflous request.
543+
// Confirmation height of the claimed outputs set transaction. In case of reorg reaching
544+
// it, we wipe out and forget the package.
512545
height_original: u32,
513546
}
514547

@@ -735,6 +768,10 @@ impl Readable for PackageTemplate {
735768
}
736769
}
737770

771+
/// Attempt to propose a fee based on consumed outpoints's values and predicted weight of the claiming
772+
/// transaction. We start with the highest priority feerate returned by the node's fee estimator
773+
/// then fall-back to lower priorities until we have enough value available to suck from.
774+
/// If the proposed fee is more than the claimable balance, we return None
738775
fn subtract_high_prio_fee<F: Deref, L: Deref>(input_amounts: u64, predicted_weight: usize, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
739776
where F::Target: FeeEstimator,
740777
L::Target: Logger,
@@ -766,6 +803,12 @@ fn subtract_high_prio_fee<F: Deref, L: Deref>(input_amounts: u64, predicted_weig
766803
}
767804
}
768805

806+
/// Attempt to propose a bumping fee based on consumed outpoint's value and predicted weight of the
807+
/// claiming transaction. If feerates proposed by the fee-estimator have been increasing since last
808+
/// fee-bumping attempt, use them. Otherwise, blindly bump the feerate by 25% of the previous
809+
/// feerate.
810+
/// We also verify that those bumping heuristics respect BIP125 rules 3) and 4) and if required
811+
/// adjust the new fee to meet the RBF policy requirement.
769812
fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
770813
where F::Target: FeeEstimator,
771814
L::Target: Logger,
@@ -801,6 +844,9 @@ fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64,
801844
Some((new_fee, new_fee * 1000 / (predicted_weight as u64)))
802845
}
803846

847+
/// Deduce a new proposed fee from the claiming transaction output value.
848+
/// If the new proposed fee is superior to the consumed outpoint's value, burn everything in miner's
849+
/// fee to deter counterparties attacker.
804850
pub(crate) fn compute_output_value<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
805851
where F::Target: FeeEstimator,
806852
L::Target: Logger,

0 commit comments

Comments
 (0)