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.
2
13
3
14
use bitcoin:: blockdata:: transaction:: { TxOut , TxIn , Transaction , SigHashType } ;
4
15
use bitcoin:: blockdata:: transaction:: OutPoint as BitcoinOutPoint ;
@@ -24,6 +35,8 @@ use std::ops::Deref;
24
35
25
36
const MAX_ALLOC_SIZE : usize = 64 * 1024 ;
26
37
38
+
39
+ /// witnessScript markers used to compute the expected witness weight.
27
40
#[ derive( PartialEq , Clone , Copy ) ]
28
41
pub ( crate ) enum InputDescriptors {
29
42
RevokedOfferedHTLC ,
@@ -80,6 +93,8 @@ impl Readable for InputDescriptors {
80
93
}
81
94
}
82
95
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.
83
98
pub ( crate ) fn get_witnesses_weight ( inputs : & [ InputDescriptors ] ) -> usize {
84
99
let mut tx_weight = 2 ; // count segwit flags
85
100
for inp in inputs {
@@ -110,9 +125,16 @@ pub(crate) fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
110
125
tx_weight
111
126
}
112
127
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.
116
138
#[ derive( Clone , PartialEq ) ]
117
139
pub ( crate ) struct RevokedOutput {
118
140
per_commitment_point : PublicKey ,
@@ -177,9 +199,12 @@ impl Readable for RevokedOutput {
177
199
}
178
200
}
179
201
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.
183
208
#[ derive( Clone , PartialEq ) ]
184
209
pub ( crate ) struct CounterpartyHTLCOutput {
185
210
per_commitment_point : PublicKey ,
@@ -229,9 +254,10 @@ impl Readable for CounterpartyHTLCOutput {
229
254
}
230
255
}
231
256
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.
235
261
#[ derive( Clone , PartialEq ) ]
236
262
pub ( crate ) struct HolderHTLCOutput {
237
263
preimage : Option < PaymentPreimage > ,
@@ -266,8 +292,9 @@ impl Readable for HolderHTLCOutput {
266
292
}
267
293
}
268
294
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.
271
298
#[ derive( Clone , PartialEq ) ]
272
299
pub ( crate ) struct HolderFundingOutput {
273
300
funding_redeemscript : Script ,
@@ -296,6 +323,10 @@ impl Readable for HolderFundingOutput {
296
323
}
297
324
}
298
325
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.
299
330
#[ derive( Clone , PartialEq ) ]
300
331
pub ( crate ) enum PackageSolvingData {
301
332
RevokedOutput ( RevokedOutput ) ,
@@ -431,6 +462,9 @@ impl Readable for PackageSolvingData {
431
462
}
432
463
}
433
464
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.
434
468
#[ derive( Clone , PartialEq ) ]
435
469
pub ( crate ) enum PackageMalleability {
436
470
Malleable ,
@@ -467,48 +501,47 @@ impl Readable for PackageMalleability {
467
501
}
468
502
}
469
503
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.
472
506
///
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.
478
510
///
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.
492
513
#[ derive( Clone , PartialEq ) ]
493
514
pub ( crate ) struct PackageTemplate {
515
+ // List of onchain outputs and solving data to generate satisfying witnesses.
494
516
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.
495
522
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`.
498
526
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.
504
535
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.
507
539
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 .
510
542
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.
512
545
height_original : u32 ,
513
546
}
514
547
@@ -735,6 +768,10 @@ impl Readable for PackageTemplate {
735
768
}
736
769
}
737
770
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
738
775
fn subtract_high_prio_fee < F : Deref , L : Deref > ( input_amounts : u64 , predicted_weight : usize , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
739
776
where F :: Target : FeeEstimator ,
740
777
L :: Target : Logger ,
@@ -766,6 +803,12 @@ fn subtract_high_prio_fee<F: Deref, L: Deref>(input_amounts: u64, predicted_weig
766
803
}
767
804
}
768
805
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.
769
812
fn feerate_bump < F : Deref , L : Deref > ( predicted_weight : usize , input_amounts : u64 , previous_feerate : u64 , fee_estimator : & F , logger : & L ) -> Option < ( u64 , u64 ) >
770
813
where F :: Target : FeeEstimator ,
771
814
L :: Target : Logger ,
@@ -801,6 +844,9 @@ fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64,
801
844
Some ( ( new_fee, new_fee * 1000 / ( predicted_weight as u64 ) ) )
802
845
}
803
846
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.
804
850
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 ) >
805
851
where F :: Target : FeeEstimator ,
806
852
L :: Target : Logger ,
0 commit comments