• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 10285980579

07 Aug 2024 02:11PM UTC coverage: 57.666% (-0.8%) from 58.478%
10285980579

push

github

web-flow
Merge pull request #8886 from bitromortac/buildroute-inbound-fees

routing: inbound fees support for BuildRoute

311 of 321 new or added lines in 1 file covered. (96.88%)

18350 existing lines in 229 files now uncovered.

94516 of 163902 relevant lines covered (57.67%)

37110.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.63
/lnwallet/commitment.go
1
package lnwallet
2

3
import (
4
        "bytes"
5
        "fmt"
6

7
        "github.com/btcsuite/btcd/blockchain"
8
        "github.com/btcsuite/btcd/btcec/v2"
9
        "github.com/btcsuite/btcd/btcutil"
10
        "github.com/btcsuite/btcd/chaincfg/chainhash"
11
        "github.com/btcsuite/btcd/txscript"
12
        "github.com/btcsuite/btcd/wire"
13
        "github.com/lightningnetwork/lnd/channeldb"
14
        "github.com/lightningnetwork/lnd/input"
15
        "github.com/lightningnetwork/lnd/lntypes"
16
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
17
        "github.com/lightningnetwork/lnd/lnwire"
18
)
19

20
// anchorSize is the constant anchor output size.
21
const anchorSize = btcutil.Amount(330)
22

23
// DefaultAnchorsCommitMaxFeeRateSatPerVByte is the default max fee rate in
24
// sat/vbyte the initiator will use for anchor channels. This should be enough
25
// to ensure propagation before anchoring down the commitment transaction.
26
const DefaultAnchorsCommitMaxFeeRateSatPerVByte = 10
27

28
// CommitmentKeyRing holds all derived keys needed to construct commitment and
29
// HTLC transactions. The keys are derived differently depending whether the
30
// commitment transaction is ours or the remote peer's. Private keys associated
31
// with each key may belong to the commitment owner or the "other party" which
32
// is referred to in the field comments, regardless of which is local and which
33
// is remote.
34
type CommitmentKeyRing struct {
35
        // CommitPoint is the "per commitment point" used to derive the tweak
36
        // for each base point.
37
        CommitPoint *btcec.PublicKey
38

39
        // LocalCommitKeyTweak is the tweak used to derive the local public key
40
        // from the local payment base point or the local private key from the
41
        // base point secret. This may be included in a SignDescriptor to
42
        // generate signatures for the local payment key.
43
        //
44
        // NOTE: This will always refer to "our" local key, regardless of
45
        // whether this is our commit or not.
46
        LocalCommitKeyTweak []byte
47

48
        // TODO(roasbeef): need delay tweak as well?
49

50
        // LocalHtlcKeyTweak is the tweak used to derive the local HTLC key
51
        // from the local HTLC base point. This value is needed in order to
52
        // derive the final key used within the HTLC scripts in the commitment
53
        // transaction.
54
        //
55
        // NOTE: This will always refer to "our" local HTLC key, regardless of
56
        // whether this is our commit or not.
57
        LocalHtlcKeyTweak []byte
58

59
        // LocalHtlcKey is the key that will be used in any clause paying to
60
        // our node of any HTLC scripts within the commitment transaction for
61
        // this key ring set.
62
        //
63
        // NOTE: This will always refer to "our" local HTLC key, regardless of
64
        // whether this is our commit or not.
65
        LocalHtlcKey *btcec.PublicKey
66

67
        // RemoteHtlcKey is the key that will be used in clauses within the
68
        // HTLC script that send money to the remote party.
69
        //
70
        // NOTE: This will always refer to "their" remote HTLC key, regardless
71
        // of whether this is our commit or not.
72
        RemoteHtlcKey *btcec.PublicKey
73

74
        // ToLocalKey is the commitment transaction owner's key which is
75
        // included in HTLC success and timeout transaction scripts. This is
76
        // the public key used for the to_local output of the commitment
77
        // transaction.
78
        //
79
        // NOTE: Who's key this is depends on the current perspective. If this
80
        // is our commitment this will be our key.
81
        ToLocalKey *btcec.PublicKey
82

83
        // ToRemoteKey is the non-owner's payment key in the commitment tx.
84
        // This is the key used to generate the to_remote output within the
85
        // commitment transaction.
86
        //
87
        // NOTE: Who's key this is depends on the current perspective. If this
88
        // is our commitment this will be their key.
89
        ToRemoteKey *btcec.PublicKey
90

91
        // RevocationKey is the key that can be used by the other party to
92
        // redeem outputs from a revoked commitment transaction if it were to
93
        // be published.
94
        //
95
        // NOTE: Who can sign for this key depends on the current perspective.
96
        // If this is our commitment, it means the remote node can sign for
97
        // this key in case of a breach.
98
        RevocationKey *btcec.PublicKey
99
}
100

101
// DeriveCommitmentKeys generates a new commitment key set using the base points
102
// and commitment point. The keys are derived differently depending on the type
103
// of channel, and whether the commitment transaction is ours or the remote
104
// peer's.
105
func DeriveCommitmentKeys(commitPoint *btcec.PublicKey,
106
        whoseCommit lntypes.ChannelParty, chanType channeldb.ChannelType,
107
        localChanCfg, remoteChanCfg *channeldb.ChannelConfig) *CommitmentKeyRing {
12,957✔
108

12,957✔
109
        tweaklessCommit := chanType.IsTweakless()
12,957✔
110

12,957✔
111
        // Depending on if this is our commit or not, we'll choose the correct
12,957✔
112
        // base point.
12,957✔
113
        localBasePoint := localChanCfg.PaymentBasePoint
12,957✔
114
        if whoseCommit.IsLocal() {
17,949✔
115
                localBasePoint = localChanCfg.DelayBasePoint
4,992✔
116
        }
4,992✔
117

118
        // First, we'll derive all the keys that don't depend on the context of
119
        // whose commitment transaction this is.
120
        keyRing := &CommitmentKeyRing{
12,957✔
121
                CommitPoint: commitPoint,
12,957✔
122

12,957✔
123
                LocalCommitKeyTweak: input.SingleTweakBytes(
12,957✔
124
                        commitPoint, localBasePoint.PubKey,
12,957✔
125
                ),
12,957✔
126
                LocalHtlcKeyTweak: input.SingleTweakBytes(
12,957✔
127
                        commitPoint, localChanCfg.HtlcBasePoint.PubKey,
12,957✔
128
                ),
12,957✔
129
                LocalHtlcKey: input.TweakPubKey(
12,957✔
130
                        localChanCfg.HtlcBasePoint.PubKey, commitPoint,
12,957✔
131
                ),
12,957✔
132
                RemoteHtlcKey: input.TweakPubKey(
12,957✔
133
                        remoteChanCfg.HtlcBasePoint.PubKey, commitPoint,
12,957✔
134
                ),
12,957✔
135
        }
12,957✔
136

12,957✔
137
        // We'll now compute the to_local, to_remote, and revocation key based
12,957✔
138
        // on the current commitment point. All keys are tweaked each state in
12,957✔
139
        // order to ensure the keys from each state are unlinkable. To create
12,957✔
140
        // the revocation key, we take the opposite party's revocation base
12,957✔
141
        // point and combine that with the current commitment point.
12,957✔
142
        var (
12,957✔
143
                toLocalBasePoint    *btcec.PublicKey
12,957✔
144
                toRemoteBasePoint   *btcec.PublicKey
12,957✔
145
                revocationBasePoint *btcec.PublicKey
12,957✔
146
        )
12,957✔
147
        if whoseCommit.IsLocal() {
17,949✔
148
                toLocalBasePoint = localChanCfg.DelayBasePoint.PubKey
4,992✔
149
                toRemoteBasePoint = remoteChanCfg.PaymentBasePoint.PubKey
4,992✔
150
                revocationBasePoint = remoteChanCfg.RevocationBasePoint.PubKey
4,992✔
151
        } else {
12,957✔
152
                toLocalBasePoint = remoteChanCfg.DelayBasePoint.PubKey
7,965✔
153
                toRemoteBasePoint = localChanCfg.PaymentBasePoint.PubKey
7,965✔
154
                revocationBasePoint = localChanCfg.RevocationBasePoint.PubKey
7,965✔
155
        }
7,965✔
156

157
        // With the base points assigned, we can now derive the actual keys
158
        // using the base point, and the current commitment tweak.
159
        keyRing.ToLocalKey = input.TweakPubKey(toLocalBasePoint, commitPoint)
12,957✔
160
        keyRing.RevocationKey = input.DeriveRevocationPubkey(
12,957✔
161
                revocationBasePoint, commitPoint,
12,957✔
162
        )
12,957✔
163

12,957✔
164
        // If this commitment should omit the tweak for the remote point, then
12,957✔
165
        // we'll use that directly, and ignore the commitPoint tweak.
12,957✔
166
        if tweaklessCommit {
24,073✔
167
                keyRing.ToRemoteKey = toRemoteBasePoint
11,116✔
168

11,116✔
169
                // If this is not our commitment, the above ToRemoteKey will be
11,116✔
170
                // ours, and we blank out the local commitment tweak to
11,116✔
171
                // indicate that the key should not be tweaked when signing.
11,116✔
172
                if whoseCommit.IsRemote() {
18,008✔
173
                        keyRing.LocalCommitKeyTweak = nil
6,892✔
174
                }
6,892✔
175
        } else {
1,841✔
176
                keyRing.ToRemoteKey = input.TweakPubKey(
1,841✔
177
                        toRemoteBasePoint, commitPoint,
1,841✔
178
                )
1,841✔
179
        }
1,841✔
180

181
        return keyRing
12,957✔
182
}
183

184
// WitnessScriptDesc holds the output script and the witness script for p2wsh
185
// outputs.
186
type WitnessScriptDesc struct {
187
        // OutputScript is the output's PkScript.
188
        OutputScript []byte
189

190
        // WitnessScript is the full script required to properly redeem the
191
        // output. This field should be set to the full script if a p2wsh
192
        // output is being signed. For p2wkh it should be set equal to the
193
        // PkScript.
194
        WitnessScript []byte
195
}
196

197
// PkScript is the public key script that commits to the final
198
// contract.
199
func (w *WitnessScriptDesc) PkScript() []byte {
1,458,180✔
200
        return w.OutputScript
1,458,180✔
201
}
1,458,180✔
202

203
// WitnessScript returns the witness script that we'll use when signing for the
204
// remote party, and also verifying signatures on our transactions. As an
205
// example, when we create an outgoing HTLC for the remote party, we want to
206
// sign their success path.
207
func (w *WitnessScriptDesc) WitnessScriptToSign() []byte {
478,753✔
208
        return w.WitnessScript
478,753✔
209
}
478,753✔
210

211
// WitnessScriptForPath returns the witness script for the given spending path.
212
// An error is returned if the path is unknown. This is useful as when
213
// constructing a contrl block for a given path, one also needs witness script
214
// being signed.
215
func (w *WitnessScriptDesc) WitnessScriptForPath(_ input.ScriptPath,
216
) ([]byte, error) {
296✔
217

296✔
218
        return w.WitnessScript, nil
296✔
219
}
296✔
220

221
// CommitScriptToSelf constructs the public key script for the output on the
222
// commitment transaction paying to the "owner" of said commitment transaction.
223
// The `initiator` argument should correspond to the owner of the commitment
224
// transaction which we are generating the to_local script for. If the other
225
// party learns of the preimage to the revocation hash, then they can claim all
226
// the settled funds in the channel, plus the unsettled funds.
227
func CommitScriptToSelf(chanType channeldb.ChannelType, initiator bool,
228
        selfKey, revokeKey *btcec.PublicKey, csvDelay, leaseExpiry uint32,
229
) (
230
        input.ScriptDescriptor, error) {
9,835✔
231

9,835✔
232
        switch {
9,835✔
233
        // For taproot scripts, we'll need to make a slightly modified script
234
        // where a NUMS key is used to force a script path reveal of either the
235
        // revocation or the CSV timeout.
236
        //
237
        // Our "redeem" script here is just the taproot witness program.
238
        case chanType.IsTaproot():
105✔
239
                return input.NewLocalCommitScriptTree(
105✔
240
                        csvDelay, selfKey, revokeKey,
105✔
241
                )
105✔
242

243
        // If we are the initiator of a leased channel, then we have an
244
        // additional CLTV requirement in addition to the usual CSV
245
        // requirement.
UNCOV
246
        case initiator && chanType.HasLeaseExpiration():
×
UNCOV
247
                toLocalRedeemScript, err := input.LeaseCommitScriptToSelf(
×
UNCOV
248
                        selfKey, revokeKey, csvDelay, leaseExpiry,
×
UNCOV
249
                )
×
UNCOV
250
                if err != nil {
×
251
                        return nil, err
×
252
                }
×
253

UNCOV
254
                toLocalScriptHash, err := input.WitnessScriptHash(
×
UNCOV
255
                        toLocalRedeemScript,
×
UNCOV
256
                )
×
UNCOV
257
                if err != nil {
×
258
                        return nil, err
×
259
                }
×
260

UNCOV
261
                return &WitnessScriptDesc{
×
UNCOV
262
                        OutputScript:  toLocalScriptHash,
×
UNCOV
263
                        WitnessScript: toLocalRedeemScript,
×
UNCOV
264
                }, nil
×
265

266
        default:
9,730✔
267
                toLocalRedeemScript, err := input.CommitScriptToSelf(
9,730✔
268
                        csvDelay, selfKey, revokeKey,
9,730✔
269
                )
9,730✔
270
                if err != nil {
9,730✔
271
                        return nil, err
×
272
                }
×
273

274
                toLocalScriptHash, err := input.WitnessScriptHash(
9,730✔
275
                        toLocalRedeemScript,
9,730✔
276
                )
9,730✔
277
                if err != nil {
9,730✔
278
                        return nil, err
×
279
                }
×
280

281
                return &WitnessScriptDesc{
9,730✔
282
                        OutputScript:  toLocalScriptHash,
9,730✔
283
                        WitnessScript: toLocalRedeemScript,
9,730✔
284
                }, nil
9,730✔
285
        }
286
}
287

288
// CommitScriptToRemote derives the appropriate to_remote script based on the
289
// channel's commitment type. The `initiator` argument should correspond to the
290
// owner of the commitment transaction which we are generating the to_remote
291
// script for. The second return value is the CSV delay of the output script,
292
// what must be satisfied in order to spend the output.
293
func CommitScriptToRemote(chanType channeldb.ChannelType, initiator bool,
294
        remoteKey *btcec.PublicKey,
295
        leaseExpiry uint32) (input.ScriptDescriptor, uint32, error) {
9,781✔
296

9,781✔
297
        switch {
9,781✔
298
        // If we are not the initiator of a leased channel, then the remote
299
        // party has an additional CLTV requirement in addition to the 1 block
300
        // CSV requirement.
UNCOV
301
        case chanType.HasLeaseExpiration() && !initiator:
×
UNCOV
302
                script, err := input.LeaseCommitScriptToRemoteConfirmed(
×
UNCOV
303
                        remoteKey, leaseExpiry,
×
UNCOV
304
                )
×
UNCOV
305
                if err != nil {
×
306
                        return nil, 0, err
×
307
                }
×
308

UNCOV
309
                p2wsh, err := input.WitnessScriptHash(script)
×
UNCOV
310
                if err != nil {
×
311
                        return nil, 0, err
×
312
                }
×
313

UNCOV
314
                return &WitnessScriptDesc{
×
UNCOV
315
                        OutputScript:  p2wsh,
×
UNCOV
316
                        WitnessScript: script,
×
UNCOV
317
                }, 1, nil
×
318

319
        // For taproot channels, we'll use a slightly different format, where
320
        // we use a NUMS key to force the remote party to take a script path,
321
        // with the sole tap leaf enforcing the 1 CSV delay.
322
        case chanType.IsTaproot():
103✔
323
                toRemoteScriptTree, err := input.NewRemoteCommitScriptTree(
103✔
324
                        remoteKey,
103✔
325
                )
103✔
326
                if err != nil {
103✔
327
                        return nil, 0, err
×
328
                }
×
329

330
                return toRemoteScriptTree, 1, nil
103✔
331

332
        // If this channel type has anchors, we derive the delayed to_remote
333
        // script.
334
        case chanType.HasAnchors():
241✔
335
                script, err := input.CommitScriptToRemoteConfirmed(remoteKey)
241✔
336
                if err != nil {
241✔
337
                        return nil, 0, err
×
338
                }
×
339

340
                p2wsh, err := input.WitnessScriptHash(script)
241✔
341
                if err != nil {
241✔
342
                        return nil, 0, err
×
343
                }
×
344

345
                return &WitnessScriptDesc{
241✔
346
                        OutputScript:  p2wsh,
241✔
347
                        WitnessScript: script,
241✔
348
                }, 1, nil
241✔
349

350
        default:
9,437✔
351
                // Otherwise the to_remote will be a simple p2wkh.
9,437✔
352
                p2wkh, err := input.CommitScriptUnencumbered(remoteKey)
9,437✔
353
                if err != nil {
9,437✔
354
                        return nil, 0, err
×
355
                }
×
356

357
                // Since this is a regular P2WKH, the WitnessScipt and PkScript
358
                // should both be set to the script hash.
359
                return &WitnessScriptDesc{
9,437✔
360
                        OutputScript:  p2wkh,
9,437✔
361
                        WitnessScript: p2wkh,
9,437✔
362
                }, 0, nil
9,437✔
363
        }
364
}
365

366
// HtlcSigHashType returns the sighash type to use for HTLC success and timeout
367
// transactions given the channel type.
368
func HtlcSigHashType(chanType channeldb.ChannelType) txscript.SigHashType {
6,141✔
369
        if chanType.HasAnchors() {
6,363✔
370
                return txscript.SigHashSingle | txscript.SigHashAnyOneCanPay
222✔
371
        }
222✔
372

373
        return txscript.SigHashAll
5,919✔
374
}
375

376
// HtlcSignDetails converts the passed parameters to a SignDetails valid for
377
// this channel type. For non-anchor channels this will return nil.
378
func HtlcSignDetails(chanType channeldb.ChannelType, signDesc input.SignDescriptor,
379
        sigHash txscript.SigHashType, peerSig input.Signature) *input.SignDetails {
92✔
380

92✔
381
        // Non-anchor channels don't need sign details, as the HTLC second
92✔
382
        // level cannot be altered.
92✔
383
        if !chanType.HasAnchors() {
133✔
384
                return nil
41✔
385
        }
41✔
386

387
        return &input.SignDetails{
51✔
388
                SignDesc:    signDesc,
51✔
389
                SigHashType: sigHash,
51✔
390
                PeerSig:     peerSig,
51✔
391
        }
51✔
392
}
393

394
// HtlcSecondLevelInputSequence dictates the sequence number we must use on the
395
// input to a second level HTLC transaction.
396
func HtlcSecondLevelInputSequence(chanType channeldb.ChannelType) uint32 {
478,506✔
397
        if chanType.HasAnchors() {
478,741✔
398
                return 1
235✔
399
        }
235✔
400

401
        return 0
478,271✔
402
}
403

404
// sweepSigHash returns the sign descriptor to use when signing a sweep
405
// transaction. For taproot channels, we'll use this to always sweep with
406
// sighash default.
407
func sweepSigHash(chanType channeldb.ChannelType) txscript.SigHashType {
310✔
408
        if chanType.IsTaproot() {
324✔
409
                return txscript.SigHashDefault
14✔
410
        }
14✔
411

412
        return txscript.SigHashAll
296✔
413
}
414

415
// SecondLevelHtlcScript derives the appropriate second level HTLC script based
416
// on the channel's commitment type. It is the uniform script that's used as the
417
// output for the second-level HTLC transactions. The second level transaction
418
// act as a sort of covenant, ensuring that a 2-of-2 multi-sig output can only
419
// be spent in a particular way, and to a particular output. The `initiator`
420
// argument should correspond to the owner of the commitment transaction which
421
// we are generating the to_local script for.
422
func SecondLevelHtlcScript(chanType channeldb.ChannelType, initiator bool,
423
        revocationKey, delayKey *btcec.PublicKey,
424
        csvDelay, leaseExpiry uint32) (input.ScriptDescriptor, error) {
478,601✔
425

478,601✔
426
        switch {
478,601✔
427
        // For taproot channels, the pkScript is a segwit v1 p2tr output.
428
        case chanType.IsTaproot():
48✔
429
                return input.TaprootSecondLevelScriptTree(
48✔
430
                        revocationKey, delayKey, csvDelay,
48✔
431
                )
48✔
432

433
        // If we are the initiator of a leased channel, then we have an
434
        // additional CLTV requirement in addition to the usual CSV
435
        // requirement.
UNCOV
436
        case initiator && chanType.HasLeaseExpiration():
×
UNCOV
437
                witnessScript, err := input.LeaseSecondLevelHtlcScript(
×
UNCOV
438
                        revocationKey, delayKey, csvDelay, leaseExpiry,
×
UNCOV
439
                )
×
UNCOV
440
                if err != nil {
×
441
                        return nil, err
×
442
                }
×
443

UNCOV
444
                pkScript, err := input.WitnessScriptHash(witnessScript)
×
UNCOV
445
                if err != nil {
×
446
                        return nil, err
×
447
                }
×
448

UNCOV
449
                return &WitnessScriptDesc{
×
UNCOV
450
                        OutputScript:  pkScript,
×
UNCOV
451
                        WitnessScript: witnessScript,
×
UNCOV
452
                }, nil
×
453

454
        default:
478,553✔
455
                witnessScript, err := input.SecondLevelHtlcScript(
478,553✔
456
                        revocationKey, delayKey, csvDelay,
478,553✔
457
                )
478,553✔
458
                if err != nil {
478,553✔
459
                        return nil, err
×
460
                }
×
461

462
                pkScript, err := input.WitnessScriptHash(witnessScript)
478,553✔
463
                if err != nil {
478,553✔
464
                        return nil, err
×
465
                }
×
466

467
                return &WitnessScriptDesc{
478,553✔
468
                        OutputScript:  pkScript,
478,553✔
469
                        WitnessScript: witnessScript,
478,553✔
470
                }, nil
478,553✔
471
        }
472
}
473

474
// CommitWeight returns the base commitment weight before adding HTLCs.
475
func CommitWeight(chanType channeldb.ChannelType) lntypes.WeightUnit {
30,360✔
476
        switch {
30,360✔
477
        case chanType.IsTaproot():
167✔
478
                return input.TaprootCommitWeight
167✔
479

480
        // If this commitment has anchors, it will be slightly heavier.
481
        case chanType.HasAnchors():
1,752✔
482
                return input.AnchorCommitWeight
1,752✔
483

484
        default:
28,441✔
485
                return input.CommitWeight
28,441✔
486
        }
487
}
488

489
// HtlcTimeoutFee returns the fee in satoshis required for an HTLC timeout
490
// transaction based on the current fee rate.
491
func HtlcTimeoutFee(chanType channeldb.ChannelType,
492
        feePerKw chainfee.SatPerKWeight) btcutil.Amount {
3,622,857✔
493

3,622,857✔
494
        switch {
3,622,857✔
495
        // For zero-fee HTLC channels, this will always be zero, regardless of
496
        // feerate.
497
        case chanType.ZeroHtlcTxFee() || chanType.IsTaproot():
497✔
498
                return 0
497✔
499

500
        case chanType.HasAnchors():
478✔
501
                return feePerKw.FeeForWeight(input.HtlcTimeoutWeightConfirmed)
478✔
502

503
        default:
3,621,882✔
504
                return feePerKw.FeeForWeight(input.HtlcTimeoutWeight)
3,621,882✔
505
        }
506
}
507

508
// HtlcSuccessFee returns the fee in satoshis required for an HTLC success
509
// transaction based on the current fee rate.
510
func HtlcSuccessFee(chanType channeldb.ChannelType,
511
        feePerKw chainfee.SatPerKWeight) btcutil.Amount {
3,765,673✔
512

3,765,673✔
513
        switch {
3,765,673✔
514
        // For zero-fee HTLC channels, this will always be zero, regardless of
515
        // feerate.
516
        case chanType.ZeroHtlcTxFee() || chanType.IsTaproot():
879✔
517
                return 0
879✔
518

519
        case chanType.HasAnchors():
1,071✔
520
                return feePerKw.FeeForWeight(input.HtlcSuccessWeightConfirmed)
1,071✔
521

522
        default:
3,763,723✔
523
                return feePerKw.FeeForWeight(input.HtlcSuccessWeight)
3,763,723✔
524
        }
525
}
526

527
// CommitScriptAnchors return the scripts to use for the local and remote
528
// anchor.
529
func CommitScriptAnchors(chanType channeldb.ChannelType,
530
        localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
531
        keyRing *CommitmentKeyRing) (
532
        input.ScriptDescriptor, input.ScriptDescriptor, error) {
297✔
533

297✔
534
        var (
297✔
535
                anchorScript func(key *btcec.PublicKey) (
297✔
536
                        input.ScriptDescriptor, error)
297✔
537

297✔
538
                keySelector func(*channeldb.ChannelConfig,
297✔
539
                        bool) *btcec.PublicKey
297✔
540
        )
297✔
541

297✔
542
        switch {
297✔
543
        // For taproot channels, the anchor is slightly different: the top
544
        // level key is now the (relative) local delay and remote public key,
545
        // since these are fully revealed once the commitment hits the chain.
546
        case chanType.IsTaproot():
74✔
547
                anchorScript = func(key *btcec.PublicKey,
74✔
548
                ) (input.ScriptDescriptor, error) {
222✔
549

148✔
550
                        return input.NewAnchorScriptTree(
148✔
551
                                key,
148✔
552
                        )
148✔
553
                }
148✔
554

555
                keySelector = func(cfg *channeldb.ChannelConfig,
74✔
556
                        local bool) *btcec.PublicKey {
222✔
557

148✔
558
                        if local {
222✔
559
                                return keyRing.ToLocalKey
74✔
560
                        }
74✔
561

562
                        return keyRing.ToRemoteKey
74✔
563
                }
564

565
        // For normal channels we'll use the multi-sig keys since those are
566
        // revealed when the channel closes
567
        default:
223✔
568
                // For normal channels, we'll create a p2wsh script based on
223✔
569
                // the target key.
223✔
570
                anchorScript = func(key *btcec.PublicKey,
223✔
571
                ) (input.ScriptDescriptor, error) {
669✔
572

446✔
573
                        script, err := input.CommitScriptAnchor(key)
446✔
574
                        if err != nil {
446✔
575
                                return nil, err
×
576
                        }
×
577

578
                        scriptHash, err := input.WitnessScriptHash(script)
446✔
579
                        if err != nil {
446✔
580
                                return nil, err
×
581
                        }
×
582

583
                        return &WitnessScriptDesc{
446✔
584
                                OutputScript:  scriptHash,
446✔
585
                                WitnessScript: script,
446✔
586
                        }, nil
446✔
587
                }
588

589
                // For the existing channels, we'll always select the multi-sig
590
                // key from the party's channel config.
591
                keySelector = func(cfg *channeldb.ChannelConfig,
223✔
592
                        _ bool) *btcec.PublicKey {
669✔
593

446✔
594
                        return cfg.MultiSigKey.PubKey
446✔
595
                }
446✔
596
        }
597

598
        // Get the script used for the anchor output spendable by the local
599
        // node.
600
        localAnchor, err := anchorScript(keySelector(localChanCfg, true))
297✔
601
        if err != nil {
297✔
602
                return nil, nil, err
×
603
        }
×
604

605
        // And the anchor spendable by the remote node.
606
        remoteAnchor, err := anchorScript(keySelector(remoteChanCfg, false))
297✔
607
        if err != nil {
297✔
608
                return nil, nil, err
×
609
        }
×
610

611
        return localAnchor, remoteAnchor, nil
297✔
612
}
613

614
// CommitmentBuilder is a type that wraps the type of channel we are dealing
615
// with, and abstracts the various ways of constructing commitment
616
// transactions.
617
type CommitmentBuilder struct {
618
        // chanState is the underlying channels's state struct, used to
619
        // determine the type of channel we are dealing with, and relevant
620
        // parameters.
621
        chanState *channeldb.OpenChannel
622

623
        // obfuscator is a 48-bit state hint that's used to obfuscate the
624
        // current state number on the commitment transactions.
625
        obfuscator [StateHintSize]byte
626
}
627

628
// NewCommitmentBuilder creates a new CommitmentBuilder from chanState.
629
func NewCommitmentBuilder(chanState *channeldb.OpenChannel) *CommitmentBuilder {
760✔
630
        // The anchor channel type MUST be tweakless.
760✔
631
        if chanState.ChanType.HasAnchors() && !chanState.ChanType.IsTweakless() {
760✔
632
                panic("invalid channel type combination")
×
633
        }
634

635
        return &CommitmentBuilder{
760✔
636
                chanState:  chanState,
760✔
637
                obfuscator: createStateHintObfuscator(chanState),
760✔
638
        }
760✔
639
}
640

641
// createStateHintObfuscator derives and assigns the state hint obfuscator for
642
// the channel, which is used to encode the commitment height in the sequence
643
// number of commitment transaction inputs.
644
func createStateHintObfuscator(state *channeldb.OpenChannel) [StateHintSize]byte {
923✔
645
        if state.IsInitiator {
1,445✔
646
                return DeriveStateHintObfuscator(
522✔
647
                        state.LocalChanCfg.PaymentBasePoint.PubKey,
522✔
648
                        state.RemoteChanCfg.PaymentBasePoint.PubKey,
522✔
649
                )
522✔
650
        }
522✔
651

652
        return DeriveStateHintObfuscator(
401✔
653
                state.RemoteChanCfg.PaymentBasePoint.PubKey,
401✔
654
                state.LocalChanCfg.PaymentBasePoint.PubKey,
401✔
655
        )
401✔
656
}
657

658
// unsignedCommitmentTx is the final commitment created from evaluating an HTLC
659
// view at a given height, along with some meta data.
660
type unsignedCommitmentTx struct {
661
        // txn is the final, unsigned commitment transaction for this view.
662
        txn *wire.MsgTx
663

664
        // fee is the total fee of the commitment transaction.
665
        fee btcutil.Amount
666

667
        // ourBalance is our balance on this commitment *after* subtracting
668
        // commitment fees and anchor outputs. This can be different than the
669
        // balances before creating the commitment transaction as one party must
670
        // pay the commitment fee.
671
        ourBalance lnwire.MilliSatoshi
672

673
        // theirBalance is their balance of this commitment *after* subtracting
674
        // commitment fees and anchor outputs. This can be different than the
675
        // balances before creating the commitment transaction as one party must
676
        // pay the commitment fee.
677
        theirBalance lnwire.MilliSatoshi
678

679
        // cltvs is a sorted list of CLTV deltas for each HTLC on the commitment
680
        // transaction. Any non-htlc outputs will have a CLTV delay of zero.
681
        cltvs []uint32
682
}
683

684
// createUnsignedCommitmentTx generates the unsigned commitment transaction for
685
// a commitment view and returns it as part of the unsignedCommitmentTx. The
686
// passed in balances should be balances *before* subtracting any commitment
687
// fees, but after anchor outputs.
688
func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
689
        theirBalance lnwire.MilliSatoshi, whoseCommit lntypes.ChannelParty,
690
        feePerKw chainfee.SatPerKWeight, height uint64,
691
        filteredHTLCView *htlcView,
692
        keyRing *CommitmentKeyRing) (*unsignedCommitmentTx, error) {
6,043✔
693

6,043✔
694
        dustLimit := cb.chanState.LocalChanCfg.DustLimit
6,043✔
695
        if whoseCommit.IsRemote() {
9,072✔
696
                dustLimit = cb.chanState.RemoteChanCfg.DustLimit
3,029✔
697
        }
3,029✔
698

699
        numHTLCs := int64(0)
6,043✔
700
        for _, htlc := range filteredHTLCView.ourUpdates {
312,621✔
701
                if HtlcIsDust(
306,578✔
702
                        cb.chanState.ChanType, false, whoseCommit, feePerKw,
306,578✔
703
                        htlc.Amount.ToSatoshis(), dustLimit,
306,578✔
704
                ) {
373,948✔
705

67,370✔
706
                        continue
67,370✔
707
                }
708

709
                numHTLCs++
239,208✔
710
        }
711
        for _, htlc := range filteredHTLCView.theirUpdates {
312,613✔
712
                if HtlcIsDust(
306,570✔
713
                        cb.chanState.ChanType, true, whoseCommit, feePerKw,
306,570✔
714
                        htlc.Amount.ToSatoshis(), dustLimit,
306,570✔
715
                ) {
373,940✔
716

67,370✔
717
                        continue
67,370✔
718
                }
719

720
                numHTLCs++
239,200✔
721
        }
722

723
        // Next, we'll calculate the fee for the commitment transaction based
724
        // on its total weight. Once we have the total weight, we'll multiply
725
        // by the current fee-per-kw, then divide by 1000 to get the proper
726
        // fee.
727
        totalCommitWeight := CommitWeight(cb.chanState.ChanType) +
6,043✔
728
                lntypes.WeightUnit(input.HTLCWeight*numHTLCs)
6,043✔
729

6,043✔
730
        // With the weight known, we can now calculate the commitment fee,
6,043✔
731
        // ensuring that we account for any dust outputs trimmed above.
6,043✔
732
        commitFee := feePerKw.FeeForWeight(totalCommitWeight)
6,043✔
733
        commitFeeMSat := lnwire.NewMSatFromSatoshis(commitFee)
6,043✔
734

6,043✔
735
        // Currently, within the protocol, the initiator always pays the fees.
6,043✔
736
        // So we'll subtract the fee amount from the balance of the current
6,043✔
737
        // initiator. If the initiator is unable to pay the fee fully, then
6,043✔
738
        // their entire output is consumed.
6,043✔
739
        switch {
6,043✔
740
        case cb.chanState.IsInitiator && commitFee > ourBalance.ToSatoshis():
×
741
                ourBalance = 0
×
742

743
        case cb.chanState.IsInitiator:
3,025✔
744
                ourBalance -= commitFeeMSat
3,025✔
745

746
        case !cb.chanState.IsInitiator && commitFee > theirBalance.ToSatoshis():
×
747
                theirBalance = 0
×
748

749
        case !cb.chanState.IsInitiator:
3,018✔
750
                theirBalance -= commitFeeMSat
3,018✔
751
        }
752

753
        var (
6,043✔
754
                commitTx *wire.MsgTx
6,043✔
755
                err      error
6,043✔
756
        )
6,043✔
757

6,043✔
758
        // Depending on whether the transaction is ours or not, we call
6,043✔
759
        // CreateCommitTx with parameters matching the perspective, to generate
6,043✔
760
        // a new commitment transaction with all the latest unsettled/un-timed
6,043✔
761
        // out HTLCs.
6,043✔
762
        var leaseExpiry uint32
6,043✔
763
        if cb.chanState.ChanType.HasLeaseExpiration() {
6,043✔
UNCOV
764
                leaseExpiry = cb.chanState.ThawHeight
×
UNCOV
765
        }
×
766
        if whoseCommit.IsLocal() {
9,057✔
767
                commitTx, err = CreateCommitTx(
3,014✔
768
                        cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing,
3,014✔
769
                        &cb.chanState.LocalChanCfg, &cb.chanState.RemoteChanCfg,
3,014✔
770
                        ourBalance.ToSatoshis(), theirBalance.ToSatoshis(),
3,014✔
771
                        numHTLCs, cb.chanState.IsInitiator, leaseExpiry,
3,014✔
772
                )
3,014✔
773
        } else {
6,043✔
774
                commitTx, err = CreateCommitTx(
3,029✔
775
                        cb.chanState.ChanType, fundingTxIn(cb.chanState), keyRing,
3,029✔
776
                        &cb.chanState.RemoteChanCfg, &cb.chanState.LocalChanCfg,
3,029✔
777
                        theirBalance.ToSatoshis(), ourBalance.ToSatoshis(),
3,029✔
778
                        numHTLCs, !cb.chanState.IsInitiator, leaseExpiry,
3,029✔
779
                )
3,029✔
780
        }
3,029✔
781
        if err != nil {
6,043✔
782
                return nil, err
×
783
        }
×
784

785
        // We'll now add all the HTLC outputs to the commitment transaction.
786
        // Each output includes an off-chain 2-of-2 covenant clause, so we'll
787
        // need the objective local/remote keys for this particular commitment
788
        // as well. For any non-dust HTLCs that are manifested on the commitment
789
        // transaction, we'll also record its CLTV which is required to sort the
790
        // commitment transaction below. The slice is initially sized to the
791
        // number of existing outputs, since any outputs already added are
792
        // commitment outputs and should correspond to zero values for the
793
        // purposes of sorting.
794
        cltvs := make([]uint32, len(commitTx.TxOut))
6,043✔
795
        for _, htlc := range filteredHTLCView.ourUpdates {
312,621✔
796
                if HtlcIsDust(
306,578✔
797
                        cb.chanState.ChanType, false, whoseCommit, feePerKw,
306,578✔
798
                        htlc.Amount.ToSatoshis(), dustLimit,
306,578✔
799
                ) {
373,948✔
800

67,370✔
801
                        continue
67,370✔
802
                }
803

804
                err := addHTLC(
239,208✔
805
                        commitTx, whoseCommit, false, htlc, keyRing,
239,208✔
806
                        cb.chanState.ChanType,
239,208✔
807
                )
239,208✔
808
                if err != nil {
239,208✔
809
                        return nil, err
×
810
                }
×
811
                cltvs = append(cltvs, htlc.Timeout) // nolint:makezero
239,208✔
812
        }
813
        for _, htlc := range filteredHTLCView.theirUpdates {
312,613✔
814
                if HtlcIsDust(
306,570✔
815
                        cb.chanState.ChanType, true, whoseCommit, feePerKw,
306,570✔
816
                        htlc.Amount.ToSatoshis(), dustLimit,
306,570✔
817
                ) {
373,940✔
818

67,370✔
819
                        continue
67,370✔
820
                }
821

822
                err := addHTLC(
239,200✔
823
                        commitTx, whoseCommit, true, htlc, keyRing,
239,200✔
824
                        cb.chanState.ChanType,
239,200✔
825
                )
239,200✔
826
                if err != nil {
239,200✔
827
                        return nil, err
×
828
                }
×
829
                cltvs = append(cltvs, htlc.Timeout) // nolint:makezero
239,200✔
830
        }
831

832
        // Set the state hint of the commitment transaction to facilitate
833
        // quickly recovering the necessary penalty state in the case of an
834
        // uncooperative broadcast.
835
        err = SetStateNumHint(commitTx, height, cb.obfuscator)
6,043✔
836
        if err != nil {
6,043✔
837
                return nil, err
×
838
        }
×
839

840
        // Sort the transactions according to the agreed upon canonical
841
        // ordering. This lets us skip sending the entire transaction over,
842
        // instead we'll just send signatures.
843
        InPlaceCommitSort(commitTx, cltvs)
6,043✔
844

6,043✔
845
        // Next, we'll ensure that we don't accidentally create a commitment
6,043✔
846
        // transaction which would be invalid by consensus.
6,043✔
847
        uTx := btcutil.NewTx(commitTx)
6,043✔
848
        if err := blockchain.CheckTransactionSanity(uTx); err != nil {
6,043✔
849
                return nil, err
×
850
        }
×
851

852
        // Finally, we'll assert that were not attempting to draw more out of
853
        // the channel that was originally placed within it.
854
        var totalOut btcutil.Amount
6,043✔
855
        for _, txOut := range commitTx.TxOut {
496,831✔
856
                totalOut += btcutil.Amount(txOut.Value)
490,788✔
857
        }
490,788✔
858
        if totalOut+commitFee > cb.chanState.Capacity {
6,043✔
859
                return nil, fmt.Errorf("height=%v, for ChannelPoint(%v) "+
×
860
                        "attempts to consume %v while channel capacity is %v",
×
861
                        height, cb.chanState.FundingOutpoint,
×
862
                        totalOut+commitFee, cb.chanState.Capacity)
×
863
        }
×
864

865
        return &unsignedCommitmentTx{
6,043✔
866
                txn:          commitTx,
6,043✔
867
                fee:          commitFee,
6,043✔
868
                ourBalance:   ourBalance,
6,043✔
869
                theirBalance: theirBalance,
6,043✔
870
                cltvs:        cltvs,
6,043✔
871
        }, nil
6,043✔
872
}
873

874
// CreateCommitTx creates a commitment transaction, spending from specified
875
// funding output. The commitment transaction contains two outputs: one local
876
// output paying to the "owner" of the commitment transaction which can be
877
// spent after a relative block delay or revocation event, and a remote output
878
// paying the counterparty within the channel, which can be spent immediately
879
// or after a delay depending on the commitment type. The `initiator` argument
880
// should correspond to the owner of the commitment transaction we are creating.
881
func CreateCommitTx(chanType channeldb.ChannelType,
882
        fundingOutput wire.TxIn, keyRing *CommitmentKeyRing,
883
        localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
884
        amountToLocal, amountToRemote btcutil.Amount,
885
        numHTLCs int64, initiator bool, leaseExpiry uint32) (*wire.MsgTx, error) {
6,809✔
886

6,809✔
887
        // First, we create the script for the delayed "pay-to-self" output.
6,809✔
888
        // This output has 2 main redemption clauses: either we can redeem the
6,809✔
889
        // output after a relative block delay, or the remote node can claim
6,809✔
890
        // the funds with the revocation key if we broadcast a revoked
6,809✔
891
        // commitment transaction.
6,809✔
892
        toLocalScript, err := CommitScriptToSelf(
6,809✔
893
                chanType, initiator, keyRing.ToLocalKey, keyRing.RevocationKey,
6,809✔
894
                uint32(localChanCfg.CsvDelay), leaseExpiry,
6,809✔
895
        )
6,809✔
896
        if err != nil {
6,809✔
897
                return nil, err
×
898
        }
×
899

900
        // Next, we create the script paying to the remote.
901
        toRemoteScript, _, err := CommitScriptToRemote(
6,809✔
902
                chanType, initiator, keyRing.ToRemoteKey, leaseExpiry,
6,809✔
903
        )
6,809✔
904
        if err != nil {
6,809✔
905
                return nil, err
×
906
        }
×
907

908
        // Now that both output scripts have been created, we can finally create
909
        // the transaction itself. We use a transaction version of 2 since CSV
910
        // will fail unless the tx version is >= 2.
911
        commitTx := wire.NewMsgTx(2)
6,809✔
912
        commitTx.AddTxIn(&fundingOutput)
6,809✔
913

6,809✔
914
        // Avoid creating dust outputs within the commitment transaction.
6,809✔
915
        localOutput := amountToLocal >= localChanCfg.DustLimit
6,809✔
916
        if localOutput {
13,546✔
917
                commitTx.AddTxOut(&wire.TxOut{
6,737✔
918
                        PkScript: toLocalScript.PkScript(),
6,737✔
919
                        Value:    int64(amountToLocal),
6,737✔
920
                })
6,737✔
921
        }
6,737✔
922

923
        remoteOutput := amountToRemote >= localChanCfg.DustLimit
6,809✔
924
        if remoteOutput {
13,548✔
925
                commitTx.AddTxOut(&wire.TxOut{
6,739✔
926
                        PkScript: toRemoteScript.PkScript(),
6,739✔
927
                        Value:    int64(amountToRemote),
6,739✔
928
                })
6,739✔
929
        }
6,739✔
930

931
        // If this channel type has anchors, we'll also add those.
932
        if chanType.HasAnchors() {
7,075✔
933
                localAnchor, remoteAnchor, err := CommitScriptAnchors(
266✔
934
                        chanType, localChanCfg, remoteChanCfg, keyRing,
266✔
935
                )
266✔
936
                if err != nil {
266✔
937
                        return nil, err
×
938
                }
×
939

940
                // Add local anchor output only if we have a commitment output
941
                // or there are HTLCs.
942
                if localOutput || numHTLCs > 0 {
516✔
943
                        commitTx.AddTxOut(&wire.TxOut{
250✔
944
                                PkScript: localAnchor.PkScript(),
250✔
945
                                Value:    int64(anchorSize),
250✔
946
                        })
250✔
947
                }
250✔
948

949
                // Add anchor output to remote only if they have a commitment
950
                // output or there are HTLCs.
951
                if remoteOutput || numHTLCs > 0 {
516✔
952
                        commitTx.AddTxOut(&wire.TxOut{
250✔
953
                                PkScript: remoteAnchor.PkScript(),
250✔
954
                                Value:    int64(anchorSize),
250✔
955
                        })
250✔
956
                }
250✔
957
        }
958

959
        return commitTx, nil
6,809✔
960
}
961

962
// CoopCloseBalance returns the final balances that should be used to create
963
// the cooperative close tx, given the channel type and transaction fee.
964
func CoopCloseBalance(chanType channeldb.ChannelType, isInitiator bool,
965
        coopCloseFee btcutil.Amount, localCommit channeldb.ChannelCommitment) (
966
        btcutil.Amount, btcutil.Amount, error) {
39✔
967

39✔
968
        // Get both parties' balances from the latest commitment.
39✔
969
        ourBalance := localCommit.LocalBalance.ToSatoshis()
39✔
970
        theirBalance := localCommit.RemoteBalance.ToSatoshis()
39✔
971

39✔
972
        // We'll make sure we account for the complete balance by adding the
39✔
973
        // current dangling commitment fee to the balance of the initiator.
39✔
974
        initiatorDelta := localCommit.CommitFee
39✔
975

39✔
976
        // Since the initiator's balance also is stored after subtracting the
39✔
977
        // anchor values, add that back in case this was an anchor commitment.
39✔
978
        if chanType.HasAnchors() {
43✔
979
                initiatorDelta += 2 * anchorSize
4✔
980
        }
4✔
981

982
        // The initiator will pay the full coop close fee, subtract that value
983
        // from their balance.
984
        initiatorDelta -= coopCloseFee
39✔
985

39✔
986
        if isInitiator {
60✔
987
                ourBalance += initiatorDelta
21✔
988
        } else {
39✔
989
                theirBalance += initiatorDelta
18✔
990
        }
18✔
991

992
        // During fee negotiation it should always be verified that the
993
        // initiator can pay the proposed fee, but we do a sanity check just to
994
        // be sure here.
995
        if ourBalance < 0 || theirBalance < 0 {
40✔
996
                return 0, 0, fmt.Errorf("initiator cannot afford proposed " +
1✔
997
                        "coop close fee")
1✔
998
        }
1✔
999

1000
        return ourBalance, theirBalance, nil
38✔
1001
}
1002

1003
// genSegwitV0HtlcScript generates the HTLC scripts for a normal segwit v0
1004
// channel.
1005
func genSegwitV0HtlcScript(chanType channeldb.ChannelType,
1006
        isIncoming bool, whoseCommit lntypes.ChannelParty, timeout uint32,
1007
        rHash [32]byte, keyRing *CommitmentKeyRing,
1008
) (*WitnessScriptDesc, error) {
478,845✔
1009

478,845✔
1010
        var (
478,845✔
1011
                witnessScript []byte
478,845✔
1012
                err           error
478,845✔
1013
        )
478,845✔
1014

478,845✔
1015
        // Choose scripts based on channel type.
478,845✔
1016
        confirmedHtlcSpends := false
478,845✔
1017
        if chanType.HasAnchors() {
479,036✔
1018
                confirmedHtlcSpends = true
191✔
1019
        }
191✔
1020

1021
        // Generate the proper redeem scripts for the HTLC output modified by
1022
        // two-bits denoting if this is an incoming HTLC, and if the HTLC is
1023
        // being applied to their commitment transaction or ours.
1024
        switch {
478,845✔
1025
        // The HTLC is paying to us, and being applied to our commitment
1026
        // transaction. So we need to use the receiver's version of the HTLC
1027
        // script.
1028
        case isIncoming && whoseCommit.IsLocal():
120,015✔
1029
                witnessScript, err = input.ReceiverHTLCScript(
120,015✔
1030
                        timeout, keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
120,015✔
1031
                        keyRing.RevocationKey, rHash[:], confirmedHtlcSpends,
120,015✔
1032
                )
120,015✔
1033

1034
        // We're being paid via an HTLC by the remote party, and the HTLC is
1035
        // being added to their commitment transaction, so we use the sender's
1036
        // version of the HTLC script.
1037
        case isIncoming && whoseCommit.IsRemote():
119,363✔
1038
                witnessScript, err = input.SenderHTLCScript(
119,363✔
1039
                        keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
119,363✔
1040
                        keyRing.RevocationKey, rHash[:], confirmedHtlcSpends,
119,363✔
1041
                )
119,363✔
1042

1043
        // We're sending an HTLC which is being added to our commitment
1044
        // transaction. Therefore, we need to use the sender's version of the
1045
        // HTLC script.
1046
        case !isIncoming && whoseCommit.IsLocal():
119,382✔
1047
                witnessScript, err = input.SenderHTLCScript(
119,382✔
1048
                        keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
119,382✔
1049
                        keyRing.RevocationKey, rHash[:], confirmedHtlcSpends,
119,382✔
1050
                )
119,382✔
1051

1052
        // Finally, we're paying the remote party via an HTLC, which is being
1053
        // added to their commitment transaction. Therefore, we use the
1054
        // receiver's version of the HTLC script.
1055
        case !isIncoming && whoseCommit.IsRemote():
120,085✔
1056
                witnessScript, err = input.ReceiverHTLCScript(
120,085✔
1057
                        timeout, keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
120,085✔
1058
                        keyRing.RevocationKey, rHash[:], confirmedHtlcSpends,
120,085✔
1059
                )
120,085✔
1060
        }
1061
        if err != nil {
478,845✔
1062
                return nil, err
×
1063
        }
×
1064

1065
        // Now that we have the redeem scripts, create the P2WSH public key
1066
        // script for the output itself.
1067
        htlcP2WSH, err := input.WitnessScriptHash(witnessScript)
478,845✔
1068
        if err != nil {
478,845✔
1069
                return nil, err
×
1070
        }
×
1071

1072
        return &WitnessScriptDesc{
478,845✔
1073
                OutputScript:  htlcP2WSH,
478,845✔
1074
                WitnessScript: witnessScript,
478,845✔
1075
        }, nil
478,845✔
1076
}
1077

1078
// genTaprootHtlcScript generates the HTLC scripts for a taproot+musig2
1079
// channel.
1080
func genTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
1081
        timeout uint32, rHash [32]byte, keyRing *CommitmentKeyRing,
1082
) (*input.HtlcScriptTree, error) {
55✔
1083

55✔
1084
        var (
55✔
1085
                htlcScriptTree *input.HtlcScriptTree
55✔
1086
                err            error
55✔
1087
        )
55✔
1088

55✔
1089
        // Generate the proper redeem scripts for the HTLC output modified by
55✔
1090
        // two-bits denoting if this is an incoming HTLC, and if the HTLC is
55✔
1091
        // being applied to their commitment transaction or ours.
55✔
1092
        switch {
55✔
1093
        // The HTLC is paying to us, and being applied to our commitment
1094
        // transaction. So we need to use the receiver's version of HTLC the
1095
        // script.
1096
        case isIncoming && whoseCommit.IsLocal():
14✔
1097
                htlcScriptTree, err = input.ReceiverHTLCScriptTaproot(
14✔
1098
                        timeout, keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
14✔
1099
                        keyRing.RevocationKey, rHash[:], whoseCommit,
14✔
1100
                )
14✔
1101

1102
        // We're being paid via an HTLC by the remote party, and the HTLC is
1103
        // being added to their commitment transaction, so we use the sender's
1104
        // version of the HTLC script.
1105
        case isIncoming && whoseCommit.IsRemote():
9✔
1106
                htlcScriptTree, err = input.SenderHTLCScriptTaproot(
9✔
1107
                        keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
9✔
1108
                        keyRing.RevocationKey, rHash[:], whoseCommit,
9✔
1109
                )
9✔
1110

1111
        // We're sending an HTLC which is being added to our commitment
1112
        // transaction. Therefore, we need to use the sender's version of the
1113
        // HTLC script.
1114
        case !isIncoming && whoseCommit.IsLocal():
15✔
1115
                htlcScriptTree, err = input.SenderHTLCScriptTaproot(
15✔
1116
                        keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
15✔
1117
                        keyRing.RevocationKey, rHash[:], whoseCommit,
15✔
1118
                )
15✔
1119

1120
        // Finally, we're paying the remote party via an HTLC, which is being
1121
        // added to their commitment transaction. Therefore, we use the
1122
        // receiver's version of the HTLC script.
1123
        case !isIncoming && whoseCommit.IsRemote():
17✔
1124
                htlcScriptTree, err = input.ReceiverHTLCScriptTaproot(
17✔
1125
                        timeout, keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
17✔
1126
                        keyRing.RevocationKey, rHash[:], whoseCommit,
17✔
1127
                )
17✔
1128
        }
1129

1130
        return htlcScriptTree, err
55✔
1131
}
1132

1133
// genHtlcScript generates the proper P2WSH public key scripts for the HTLC
1134
// output modified by two-bits denoting if this is an incoming HTLC, and if the
1135
// HTLC is being applied to their commitment transaction or ours. A script
1136
// multiplexer for the various spending paths is returned. The script path that
1137
// we need to sign for the remote party (2nd level HTLCs) is also returned
1138
// along side the multiplexer.
1139
func genHtlcScript(chanType channeldb.ChannelType, isIncoming bool,
1140
        whoseCommit lntypes.ChannelParty, timeout uint32, rHash [32]byte,
1141
        keyRing *CommitmentKeyRing,
1142
) (input.ScriptDescriptor, error) {
478,900✔
1143

478,900✔
1144
        if !chanType.IsTaproot() {
957,745✔
1145
                return genSegwitV0HtlcScript(
478,845✔
1146
                        chanType, isIncoming, whoseCommit, timeout, rHash,
478,845✔
1147
                        keyRing,
478,845✔
1148
                )
478,845✔
1149
        }
478,845✔
1150

1151
        return genTaprootHtlcScript(
55✔
1152
                isIncoming, whoseCommit, timeout, rHash, keyRing,
55✔
1153
        )
55✔
1154
}
1155

1156
// addHTLC adds a new HTLC to the passed commitment transaction. One of four
1157
// full scripts will be generated for the HTLC output depending on if the HTLC
1158
// is incoming and if it's being applied to our commitment transaction or that
1159
// of the remote node's. Additionally, in order to be able to efficiently
1160
// locate the added HTLC on the commitment transaction from the
1161
// PaymentDescriptor that generated it, the generated script is stored within
1162
// the descriptor itself.
1163
func addHTLC(commitTx *wire.MsgTx, whoseCommit lntypes.ChannelParty,
1164
        isIncoming bool, paymentDesc *PaymentDescriptor,
1165
        keyRing *CommitmentKeyRing, chanType channeldb.ChannelType) error {
478,408✔
1166

478,408✔
1167
        timeout := paymentDesc.Timeout
478,408✔
1168
        rHash := paymentDesc.RHash
478,408✔
1169

478,408✔
1170
        scriptInfo, err := genHtlcScript(
478,408✔
1171
                chanType, isIncoming, whoseCommit, timeout, rHash, keyRing,
478,408✔
1172
        )
478,408✔
1173
        if err != nil {
478,408✔
1174
                return err
×
1175
        }
×
1176

1177
        pkScript := scriptInfo.PkScript()
478,408✔
1178

478,408✔
1179
        // Add the new HTLC outputs to the respective commitment transactions.
478,408✔
1180
        amountPending := int64(paymentDesc.Amount.ToSatoshis())
478,408✔
1181
        commitTx.AddTxOut(wire.NewTxOut(amountPending, pkScript))
478,408✔
1182

478,408✔
1183
        // Store the pkScript of this particular PaymentDescriptor so we can
478,408✔
1184
        // quickly locate it within the commitment transaction later.
478,408✔
1185
        if whoseCommit.IsLocal() {
717,608✔
1186
                paymentDesc.ourPkScript = pkScript
239,200✔
1187

239,200✔
1188
                paymentDesc.ourWitnessScript = scriptInfo.WitnessScriptToSign()
239,200✔
1189
        } else {
478,408✔
1190
                paymentDesc.theirPkScript = pkScript
239,208✔
1191

239,208✔
1192
                //nolint:lll
239,208✔
1193
                paymentDesc.theirWitnessScript = scriptInfo.WitnessScriptToSign()
239,208✔
1194
        }
239,208✔
1195

1196
        return nil
478,408✔
1197
}
1198

1199
// findOutputIndexesFromRemote finds the index of our and their outputs from
1200
// the remote commitment transaction. It derives the key ring to compute the
1201
// output scripts and compares them against the outputs inside the commitment
1202
// to find the match.
1203
func findOutputIndexesFromRemote(revocationPreimage *chainhash.Hash,
1204
        chanState *channeldb.OpenChannel) (uint32, uint32, error) {
2,943✔
1205

2,943✔
1206
        // Init the output indexes as empty.
2,943✔
1207
        ourIndex := uint32(channeldb.OutputIndexEmpty)
2,943✔
1208
        theirIndex := uint32(channeldb.OutputIndexEmpty)
2,943✔
1209

2,943✔
1210
        chanCommit := chanState.RemoteCommitment
2,943✔
1211
        _, commitmentPoint := btcec.PrivKeyFromBytes(revocationPreimage[:])
2,943✔
1212

2,943✔
1213
        // With the commitment point generated, we can now derive the king ring
2,943✔
1214
        // which will be used to generate the output scripts.
2,943✔
1215
        keyRing := DeriveCommitmentKeys(
2,943✔
1216
                commitmentPoint, lntypes.Remote, chanState.ChanType,
2,943✔
1217
                &chanState.LocalChanCfg, &chanState.RemoteChanCfg,
2,943✔
1218
        )
2,943✔
1219

2,943✔
1220
        // Since it's remote commitment chain, we'd used the mirrored values.
2,943✔
1221
        //
2,943✔
1222
        // We use the remote's channel config for the csv delay.
2,943✔
1223
        theirDelay := uint32(chanState.RemoteChanCfg.CsvDelay)
2,943✔
1224

2,943✔
1225
        // If we are the initiator of this channel, then it's be false from the
2,943✔
1226
        // remote's PoV.
2,943✔
1227
        isRemoteInitiator := !chanState.IsInitiator
2,943✔
1228

2,943✔
1229
        var leaseExpiry uint32
2,943✔
1230
        if chanState.ChanType.HasLeaseExpiration() {
2,943✔
UNCOV
1231
                leaseExpiry = chanState.ThawHeight
×
UNCOV
1232
        }
×
1233

1234
        // Map the scripts from our PoV. When facing a local commitment, the to
1235
        // local output belongs to us and the to remote output belongs to them.
1236
        // When facing a remote commitment, the to local output belongs to them
1237
        // and the to remote output belongs to us.
1238

1239
        // Compute the to local script. From our PoV, when facing a remote
1240
        // commitment, the to local output belongs to them.
1241
        theirScript, err := CommitScriptToSelf(
2,943✔
1242
                chanState.ChanType, isRemoteInitiator, keyRing.ToLocalKey,
2,943✔
1243
                keyRing.RevocationKey, theirDelay, leaseExpiry,
2,943✔
1244
        )
2,943✔
1245
        if err != nil {
2,943✔
1246
                return ourIndex, theirIndex, err
×
1247
        }
×
1248

1249
        // Compute the to remote script. From our PoV, when facing a remote
1250
        // commitment, the to remote output belongs to us.
1251
        ourScript, _, err := CommitScriptToRemote(
2,943✔
1252
                chanState.ChanType, isRemoteInitiator, keyRing.ToRemoteKey,
2,943✔
1253
                leaseExpiry,
2,943✔
1254
        )
2,943✔
1255
        if err != nil {
2,943✔
1256
                return ourIndex, theirIndex, err
×
1257
        }
×
1258

1259
        // Now compare the scripts to find our/their output index.
1260
        for i, txOut := range chanCommit.CommitTx.TxOut {
247,729✔
1261
                switch {
244,786✔
1262
                case bytes.Equal(txOut.PkScript, ourScript.PkScript()):
2,750✔
1263
                        ourIndex = uint32(i)
2,750✔
1264
                case bytes.Equal(txOut.PkScript, theirScript.PkScript()):
2,749✔
1265
                        theirIndex = uint32(i)
2,749✔
1266
                }
1267
        }
1268

1269
        return ourIndex, theirIndex, nil
2,943✔
1270
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc