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

lightningnetwork / lnd / 19980314240

06 Dec 2025 12:56AM UTC coverage: 68.199%. First build
19980314240

Pull #9985

github

web-flow
Merge bb1b9fc2a into 6d31dc242
Pull Request #9985: multi: implement awareness of the final/production taproot channel variant

374 of 520 new or added lines in 23 files covered. (71.92%)

135066 of 198048 relevant lines covered (68.2%)

22052.57 hits per line

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

88.79
/input/input.go
1
package input
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/btcutil"
7
        "github.com/btcsuite/btcd/txscript"
8
        "github.com/btcsuite/btcd/wire"
9
        "github.com/lightningnetwork/lnd/fn/v2"
10
        "github.com/lightningnetwork/lnd/lntypes"
11
        "github.com/lightningnetwork/lnd/tlv"
12
)
13

14
// EmptyOutPoint is a zeroed outpoint.
15
var EmptyOutPoint wire.OutPoint
16

17
// Input represents an abstract UTXO which is to be spent using a sweeping
18
// transaction. The method provided give the caller all information needed to
19
// construct a valid input within a sweeping transaction to sweep this
20
// lingering UTXO.
21
type Input interface {
22
        // OutPoint returns the reference to the output being spent, used to
23
        // construct the corresponding transaction input.
24
        OutPoint() wire.OutPoint
25

26
        // RequiredTxOut returns a non-nil TxOut if input commits to a certain
27
        // transaction output. This is used in the SINGLE|ANYONECANPAY case to
28
        // make sure any presigned input is still valid by including the
29
        // output.
30
        RequiredTxOut() *wire.TxOut
31

32
        // RequiredLockTime returns whether this input commits to a tx locktime
33
        // that must be used in the transaction including it.
34
        RequiredLockTime() (uint32, bool)
35

36
        // WitnessType returns an enum specifying the type of witness that must
37
        // be generated in order to spend this output.
38
        WitnessType() WitnessType
39

40
        // SignDesc returns a reference to a spendable output's sign
41
        // descriptor, which is used during signing to compute a valid witness
42
        // that spends this output.
43
        SignDesc() *SignDescriptor
44

45
        // CraftInputScript returns a valid set of input scripts allowing this
46
        // output to be spent. The returns input scripts should target the
47
        // input at location txIndex within the passed transaction. The input
48
        // scripts generated by this method support spending p2wkh, p2wsh, and
49
        // also nested p2sh outputs.
50
        CraftInputScript(signer Signer, txn *wire.MsgTx,
51
                hashCache *txscript.TxSigHashes,
52
                prevOutputFetcher txscript.PrevOutputFetcher,
53
                txinIdx int) (*Script, error)
54

55
        // BlocksToMaturity returns the relative timelock, as a number of
56
        // blocks, that must be built on top of the confirmation height before
57
        // the output can be spent. For non-CSV locked inputs this is always
58
        // zero.
59
        BlocksToMaturity() uint32
60

61
        // HeightHint returns the minimum height at which a confirmed spending
62
        // tx can occur.
63
        HeightHint() uint32
64

65
        // UnconfParent returns information about a possibly unconfirmed parent
66
        // tx.
67
        UnconfParent() *TxInfo
68

69
        // ResolutionBlob returns a special opaque blob to be used to
70
        // sweep/resolve this input.
71
        ResolutionBlob() fn.Option[tlv.Blob]
72

73
        // Preimage returns the preimage for the input if it is an HTLC input.
74
        Preimage() fn.Option[lntypes.Preimage]
75
}
76

77
// TxInfo describes properties of a parent tx that are relevant for CPFP.
78
type TxInfo struct {
79
        // Fee is the fee of the tx.
80
        Fee btcutil.Amount
81

82
        // Weight is the weight of the tx.
83
        Weight lntypes.WeightUnit
84
}
85

86
// String returns a human readable version of the tx info.
87
func (t *TxInfo) String() string {
3✔
88
        return fmt.Sprintf("fee=%v, weight=%v", t.Fee, t.Weight)
3✔
89
}
3✔
90

91
// SignDetails is a struct containing information needed to resign certain
92
// inputs. It is used to re-sign 2nd level HTLC transactions that uses the
93
// SINGLE|ANYONECANPAY sighash type, as we have a signature provided by our
94
// peer, but we can aggregate multiple of these 2nd level transactions into a
95
// new transaction, that needs to be signed by us.
96
type SignDetails struct {
97
        // SignDesc is the sign descriptor needed for us to sign the input.
98
        SignDesc SignDescriptor
99

100
        // PeerSig is the peer's signature for this input.
101
        PeerSig Signature
102

103
        // SigHashType is the sighash signed by the peer.
104
        SigHashType txscript.SigHashType
105
}
106

107
type inputKit struct {
108
        outpoint        wire.OutPoint
109
        witnessType     WitnessType
110
        signDesc        SignDescriptor
111
        heightHint      uint32
112
        blockToMaturity uint32
113
        cltvExpiry      uint32
114

115
        // unconfParent contains information about a potential unconfirmed
116
        // parent transaction.
117
        unconfParent *TxInfo
118

119
        // resolutionBlob is an optional blob that can be used to resolve an
120
        // input.
121
        resolutionBlob fn.Option[tlv.Blob]
122
}
123

124
// OutPoint returns the breached output's identifier that is to be included as
125
// a transaction input.
126
func (i *inputKit) OutPoint() wire.OutPoint {
2,933✔
127
        return i.outpoint
2,933✔
128
}
2,933✔
129

130
// RequiredTxOut returns a nil for the base input type.
131
func (i *inputKit) RequiredTxOut() *wire.TxOut {
146✔
132
        return nil
146✔
133
}
146✔
134

135
// RequiredLockTime returns whether this input commits to a tx locktime that
136
// must be used in the transaction including it. This will be false for the
137
// base input type since we can re-sign for any lock time.
138
func (i *inputKit) RequiredLockTime() (uint32, bool) {
29✔
139
        return i.cltvExpiry, i.cltvExpiry > 0
29✔
140
}
29✔
141

142
// WitnessType returns the type of witness that must be generated to spend the
143
// breached output.
144
func (i *inputKit) WitnessType() WitnessType {
1,533✔
145
        return i.witnessType
1,533✔
146
}
1,533✔
147

148
// SignDesc returns the breached output's SignDescriptor, which is used during
149
// signing to compute the witness.
150
func (i *inputKit) SignDesc() *SignDescriptor {
2,893✔
151
        return &i.signDesc
2,893✔
152
}
2,893✔
153

154
// HeightHint returns the minimum height at which a confirmed spending
155
// tx can occur.
156
func (i *inputKit) HeightHint() uint32 {
8✔
157
        return i.heightHint
8✔
158
}
8✔
159

160
// BlocksToMaturity returns the relative timelock, as a number of blocks, that
161
// must be built on top of the confirmation height before the output can be
162
// spent. For non-CSV locked inputs this is always zero.
163
func (i *inputKit) BlocksToMaturity() uint32 {
1,420✔
164
        return i.blockToMaturity
1,420✔
165
}
1,420✔
166

167
// Cpfp returns information about a possibly unconfirmed parent tx.
168
func (i *inputKit) UnconfParent() *TxInfo {
69✔
169
        return i.unconfParent
69✔
170
}
69✔
171

172
// ResolutionBlob returns a special opaque blob to be used to sweep/resolve
173
// this input.
174
func (i *inputKit) ResolutionBlob() fn.Option[tlv.Blob] {
13✔
175
        return i.resolutionBlob
13✔
176
}
13✔
177

178
// inputOpts contains options for constructing a new input.
179
type inputOpts struct {
180
        // resolutionBlob is an optional blob that can be used to resolve an
181
        // input.
182
        resolutionBlob fn.Option[tlv.Blob]
183
}
184

185
// defaultInputOpts returns a new inputOpts with default values.
186
func defaultInputOpts() *inputOpts {
1,135✔
187
        return &inputOpts{}
1,135✔
188
}
1,135✔
189

190
// InputOpt is a functional option that can be used to modify the default input
191
// options.
192
type InputOpt func(*inputOpts) //nolint:revive
193

194
// WithResolutionBlob is an option that can be used to set a resolution blob on
195
// for an input.
196
func WithResolutionBlob(b fn.Option[tlv.Blob]) InputOpt {
14✔
197
        return func(o *inputOpts) {
28✔
198
                o.resolutionBlob = b
14✔
199
        }
14✔
200
}
201

202
// BaseInput contains all the information needed to sweep a basic
203
// output (CSV/CLTV/no time lock).
204
type BaseInput struct {
205
        inputKit
206
}
207

208
// MakeBaseInput assembles a new BaseInput that can be used to construct a
209
// sweep transaction.
210
func MakeBaseInput(outpoint *wire.OutPoint, witnessType WitnessType,
211
        signDescriptor *SignDescriptor, heightHint uint32,
212
        unconfParent *TxInfo, opts ...InputOpt) BaseInput {
1,135✔
213

1,135✔
214
        opt := defaultInputOpts()
1,135✔
215
        for _, optF := range opts {
1,149✔
216
                optF(opt)
14✔
217
        }
14✔
218

219
        return BaseInput{
1,135✔
220
                inputKit{
1,135✔
221
                        outpoint:       *outpoint,
1,135✔
222
                        witnessType:    witnessType,
1,135✔
223
                        signDesc:       *signDescriptor,
1,135✔
224
                        heightHint:     heightHint,
1,135✔
225
                        unconfParent:   unconfParent,
1,135✔
226
                        resolutionBlob: opt.resolutionBlob,
1,135✔
227
                },
1,135✔
228
        }
1,135✔
229
}
230

231
// NewBaseInput allocates and assembles a new *BaseInput that can be used to
232
// construct a sweep transaction.
233
func NewBaseInput(outpoint *wire.OutPoint, witnessType WitnessType,
234
        signDescriptor *SignDescriptor, heightHint uint32,
235
        opts ...InputOpt) *BaseInput {
570✔
236

570✔
237
        input := MakeBaseInput(
570✔
238
                outpoint, witnessType, signDescriptor, heightHint, nil, opts...,
570✔
239
        )
570✔
240

570✔
241
        return &input
570✔
242
}
570✔
243

244
// NewCsvInput assembles a new csv-locked input that can be used to
245
// construct a sweep transaction.
246
func NewCsvInput(outpoint *wire.OutPoint, witnessType WitnessType,
247
        signDescriptor *SignDescriptor, heightHint uint32,
248
        blockToMaturity uint32, opts ...InputOpt) *BaseInput {
512✔
249

512✔
250
        input := MakeBaseInput(
512✔
251
                outpoint, witnessType, signDescriptor, heightHint, nil, opts...,
512✔
252
        )
512✔
253

512✔
254
        input.blockToMaturity = blockToMaturity
512✔
255

512✔
256
        return &input
512✔
257
}
512✔
258

259
// NewCsvInputWithCltv assembles a new csv and cltv locked input that can be
260
// used to construct a sweep transaction.
261
func NewCsvInputWithCltv(outpoint *wire.OutPoint, witnessType WitnessType,
262
        signDescriptor *SignDescriptor, heightHint uint32,
263
        csvDelay uint32, cltvExpiry uint32, opts ...InputOpt) *BaseInput {
7✔
264

7✔
265
        input := MakeBaseInput(
7✔
266
                outpoint, witnessType, signDescriptor, heightHint, nil, opts...,
7✔
267
        )
7✔
268

7✔
269
        input.blockToMaturity = csvDelay
7✔
270
        input.cltvExpiry = cltvExpiry
7✔
271

7✔
272
        return &input
7✔
273
}
7✔
274

275
// CraftInputScript returns a valid set of input scripts allowing this output
276
// to be spent. The returned input scripts should target the input at location
277
// txIndex within the passed transaction. The input scripts generated by this
278
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
279
func (bi *BaseInput) CraftInputScript(signer Signer, txn *wire.MsgTx,
280
        hashCache *txscript.TxSigHashes,
281
        prevOutputFetcher txscript.PrevOutputFetcher, txinIdx int) (*Script,
282
        error) {
1,420✔
283

1,420✔
284
        signDesc := bi.SignDesc()
1,420✔
285
        signDesc.PrevOutputFetcher = prevOutputFetcher
1,420✔
286
        witnessFunc := bi.witnessType.WitnessGenerator(signer, signDesc)
1,420✔
287

1,420✔
288
        return witnessFunc(txn, hashCache, txinIdx)
1,420✔
289
}
1,420✔
290

291
// Preimage returns the preimage for the input if it is an HTLC input.
292
func (bi *BaseInput) Preimage() fn.Option[lntypes.Preimage] {
×
293
        return fn.None[lntypes.Preimage]()
×
294
}
×
295

296
// HtlcSucceedInput constitutes a sweep input that needs a pre-image. The input
297
// is expected to reside on the commitment tx of the remote party and should
298
// not be a second level tx output.
299
type HtlcSucceedInput struct {
300
        inputKit
301

302
        preimage []byte
303
}
304

305
// MakeHtlcSucceedInput assembles a new redeem input that can be used to
306
// construct a sweep transaction.
307
func MakeHtlcSucceedInput(outpoint *wire.OutPoint,
308
        signDescriptor *SignDescriptor, preimage []byte, heightHint,
309
        blocksToMaturity uint32, opts ...InputOpt) HtlcSucceedInput {
7✔
310

7✔
311
        input := MakeBaseInput(
7✔
312
                outpoint, HtlcAcceptedRemoteSuccess, signDescriptor,
7✔
313
                heightHint, nil, opts...,
7✔
314
        )
7✔
315
        input.blockToMaturity = blocksToMaturity
7✔
316

7✔
317
        return HtlcSucceedInput{
7✔
318
                inputKit: input.inputKit,
7✔
319
                preimage: preimage,
7✔
320
        }
7✔
321
}
7✔
322

323
// MakeTaprootHtlcSucceedInput creates a new HtlcSucceedInput that can be used
324
// to spend an HTLC output for a taproot channel on the remote party's
325
// commitment transaction.
326
func MakeTaprootHtlcSucceedInput(op *wire.OutPoint, signDesc *SignDescriptor,
327
        preimage []byte, heightHint, blocksToMaturity uint32,
328
        opts ...InputOpt) HtlcSucceedInput {
3✔
329

3✔
330
        input := MakeBaseInput(
3✔
331
                op, TaprootHtlcAcceptedRemoteSuccess, signDesc,
3✔
332
                heightHint, nil, opts...,
3✔
333
        )
3✔
334
        input.blockToMaturity = blocksToMaturity
3✔
335

3✔
336
        return HtlcSucceedInput{
3✔
337
                inputKit: input.inputKit,
3✔
338
                preimage: preimage,
3✔
339
        }
3✔
340
}
3✔
341

342
// MakeTaprootHtlcSucceedInputFinal creates a new HtlcSucceedInput that can be used
343
// to spend an HTLC output for a production taproot channel on the remote party's
344
// commitment transaction.
345
func MakeTaprootHtlcSucceedInputFinal(op *wire.OutPoint, signDesc *SignDescriptor,
346
        preimage []byte, heightHint, blocksToMaturity uint32,
NEW
347
        opts ...InputOpt) HtlcSucceedInput {
×
NEW
348

×
NEW
349
        input := MakeBaseInput(
×
NEW
350
                op, TaprootHtlcAcceptedRemoteSuccessFinal, signDesc,
×
NEW
351
                heightHint, nil, opts...,
×
NEW
352
        )
×
NEW
353
        input.blockToMaturity = blocksToMaturity
×
NEW
354

×
NEW
355
        return HtlcSucceedInput{
×
NEW
356
                inputKit: input.inputKit,
×
NEW
357
                preimage: preimage,
×
NEW
358
        }
×
NEW
359
}
×
360

361
// CraftInputScript returns a valid set of input scripts allowing this output
362
// to be spent. The returns input scripts should target the input at location
363
// txIndex within the passed transaction. The input scripts generated by this
364
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
365
func (h *HtlcSucceedInput) CraftInputScript(signer Signer, txn *wire.MsgTx,
366
        hashCache *txscript.TxSigHashes,
367
        prevOutputFetcher txscript.PrevOutputFetcher, txinIdx int) (*Script,
368
        error) {
3✔
369

3✔
370
        desc := h.signDesc
3✔
371
        desc.SigHashes = hashCache
3✔
372
        desc.InputIndex = txinIdx
3✔
373
        desc.PrevOutputFetcher = prevOutputFetcher
3✔
374

3✔
375
        isTaproot := txscript.IsPayToTaproot(desc.Output.PkScript)
3✔
376

3✔
377
        var (
3✔
378
                witness wire.TxWitness
3✔
379
                err     error
3✔
380
        )
3✔
381
        if isTaproot {
6✔
382
                if desc.ControlBlock == nil {
3✔
383
                        return nil, fmt.Errorf("ctrl block must be set")
×
384
                }
×
385

386
                desc.SignMethod = TaprootScriptSpendSignMethod
3✔
387
                witness, err = SenderHTLCScriptTaprootRedeem(
3✔
388
                        signer, &desc, txn, h.preimage, nil, nil,
3✔
389
                )
3✔
390
        } else {
3✔
391
                witness, err = SenderHtlcSpendRedeem(
3✔
392
                        signer, &desc, txn, h.preimage,
3✔
393
                )
3✔
394
        }
3✔
395
        if err != nil {
3✔
396
                return nil, err
×
397
        }
×
398

399
        return &Script{
3✔
400
                Witness: witness,
3✔
401
        }, nil
3✔
402
}
403

404
// Preimage returns the preimage for the input if it is an HTLC input.
405
func (h *HtlcSucceedInput) Preimage() fn.Option[lntypes.Preimage] {
×
406
        if len(h.preimage) == 0 {
×
407
                return fn.None[lntypes.Preimage]()
×
408
        }
×
409

410
        return fn.Some(lntypes.Preimage(h.preimage))
×
411
}
412

413
// HtlcSecondLevelAnchorInput is an input type used to spend HTLC outputs
414
// using a re-signed second level transaction, either via the timeout or success
415
// paths.
416
type HtlcSecondLevelAnchorInput struct {
417
        inputKit
418

419
        // SignedTx is the original second level transaction signed by the
420
        // channel peer.
421
        SignedTx *wire.MsgTx
422

423
        // createWitness creates a witness allowing the passed transaction to
424
        // spend the input.
425
        createWitness func(signer Signer, txn *wire.MsgTx,
426
                hashCache *txscript.TxSigHashes,
427
                prevOutputFetcher txscript.PrevOutputFetcher,
428
                txinIdx int) (wire.TxWitness, error)
429

430
        preimage []byte
431
}
432

433
// RequiredTxOut returns the tx out needed to be present on the sweep tx for
434
// the spend of the input to be valid.
435
func (i *HtlcSecondLevelAnchorInput) RequiredTxOut() *wire.TxOut {
3✔
436
        return i.SignedTx.TxOut[0]
3✔
437
}
3✔
438

439
// RequiredLockTime returns the locktime needed for the sweep tx for the spend
440
// of the input to be valid. For a second level HTLC timeout this will be the
441
// CLTV expiry, for HTLC success it will be zero.
442
func (i *HtlcSecondLevelAnchorInput) RequiredLockTime() (uint32, bool) {
3✔
443
        return i.SignedTx.LockTime, true
3✔
444
}
3✔
445

446
// CraftInputScript returns a valid set of input scripts allowing this output
447
// to be spent. The returns input scripts should target the input at location
448
// txIndex within the passed transaction. The input scripts generated by this
449
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
450
func (i *HtlcSecondLevelAnchorInput) CraftInputScript(signer Signer,
451
        txn *wire.MsgTx, hashCache *txscript.TxSigHashes,
452
        prevOutputFetcher txscript.PrevOutputFetcher, txinIdx int) (*Script,
453
        error) {
3✔
454

3✔
455
        witness, err := i.createWitness(
3✔
456
                signer, txn, hashCache, prevOutputFetcher, txinIdx,
3✔
457
        )
3✔
458
        if err != nil {
3✔
459
                return nil, err
×
460
        }
×
461

462
        return &Script{
3✔
463
                Witness: witness,
3✔
464
        }, nil
3✔
465
}
466

467
// Preimage returns the preimage for the input if it is an HTLC input.
468
func (i *HtlcSecondLevelAnchorInput) Preimage() fn.Option[lntypes.Preimage] {
×
469
        if len(i.preimage) == 0 {
×
470
                return fn.None[lntypes.Preimage]()
×
471
        }
×
472

473
        return fn.Some(lntypes.Preimage(i.preimage))
×
474
}
475

476
// MakeHtlcSecondLevelTimeoutAnchorInput creates an input allowing the sweeper
477
// to spend the HTLC output on our commit using the second level timeout
478
// transaction.
479
func MakeHtlcSecondLevelTimeoutAnchorInput(signedTx *wire.MsgTx,
480
        signDetails *SignDetails, heightHint uint32,
481
        opts ...InputOpt) HtlcSecondLevelAnchorInput {
5✔
482

5✔
483
        // Spend an HTLC output on our local commitment tx using the
5✔
484
        // 2nd timeout transaction.
5✔
485
        createWitness := func(signer Signer, txn *wire.MsgTx,
5✔
486
                hashCache *txscript.TxSigHashes,
5✔
487
                prevOutputFetcher txscript.PrevOutputFetcher,
5✔
488
                txinIdx int) (wire.TxWitness, error) {
8✔
489

3✔
490
                desc := signDetails.SignDesc
3✔
491
                desc.SigHashes = txscript.NewTxSigHashes(txn, prevOutputFetcher)
3✔
492
                desc.InputIndex = txinIdx
3✔
493
                desc.PrevOutputFetcher = prevOutputFetcher
3✔
494

3✔
495
                return SenderHtlcSpendTimeout(
3✔
496
                        signDetails.PeerSig, signDetails.SigHashType, signer,
3✔
497
                        &desc, txn,
3✔
498
                )
3✔
499
        }
3✔
500

501
        input := MakeBaseInput(
5✔
502
                &signedTx.TxIn[0].PreviousOutPoint,
5✔
503
                HtlcOfferedTimeoutSecondLevelInputConfirmed,
5✔
504
                &signDetails.SignDesc, heightHint, nil, opts...,
5✔
505
        )
5✔
506
        input.blockToMaturity = 1
5✔
507

5✔
508
        return HtlcSecondLevelAnchorInput{
5✔
509
                inputKit:      input.inputKit,
5✔
510
                SignedTx:      signedTx,
5✔
511
                createWitness: createWitness,
5✔
512
        }
5✔
513
}
514

515
// MakeHtlcSecondLevelTimeoutTaprootInput creates an input that allows the
516
// sweeper to spend an HTLC output to the second level on our commitment
517
// transaction. The sweeper is also able to generate witnesses on demand to
518
// sweep the second level HTLC aggregated with other transactions.
519
func MakeHtlcSecondLevelTimeoutTaprootInput(signedTx *wire.MsgTx,
520
        signDetails *SignDetails,
521
        heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput {
3✔
522

3✔
523
        createWitness := func(signer Signer, txn *wire.MsgTx,
3✔
524
                hashCache *txscript.TxSigHashes,
3✔
525
                prevOutputFetcher txscript.PrevOutputFetcher,
3✔
526
                txinIdx int) (wire.TxWitness, error) {
6✔
527

3✔
528
                desc := signDetails.SignDesc
3✔
529
                if desc.ControlBlock == nil {
3✔
530
                        return nil, fmt.Errorf("ctrl block must be set")
×
531
                }
×
532

533
                desc.SigHashes = txscript.NewTxSigHashes(txn, prevOutputFetcher)
3✔
534
                desc.InputIndex = txinIdx
3✔
535
                desc.PrevOutputFetcher = prevOutputFetcher
3✔
536

3✔
537
                desc.SignMethod = TaprootScriptSpendSignMethod
3✔
538

3✔
539
                return SenderHTLCScriptTaprootTimeout(
3✔
540
                        signDetails.PeerSig, signDetails.SigHashType, signer,
3✔
541
                        &desc, txn, nil, nil,
3✔
542
                )
3✔
543
        }
544

545
        input := MakeBaseInput(
3✔
546
                &signedTx.TxIn[0].PreviousOutPoint,
3✔
547
                TaprootHtlcLocalOfferedTimeout,
3✔
548
                &signDetails.SignDesc, heightHint, nil, opts...,
3✔
549
        )
3✔
550
        input.blockToMaturity = 1
3✔
551

3✔
552
        return HtlcSecondLevelAnchorInput{
3✔
553
                inputKit:      input.inputKit,
3✔
554
                SignedTx:      signedTx,
3✔
555
                createWitness: createWitness,
3✔
556
        }
3✔
557
}
558

559
// MakeHtlcSecondLevelSuccessAnchorInput creates an input allowing the sweeper
560
// to spend the HTLC output on our commit using the second level success
561
// transaction.
562
func MakeHtlcSecondLevelSuccessAnchorInput(signedTx *wire.MsgTx,
563
        signDetails *SignDetails, preimage lntypes.Preimage,
564
        heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput {
4✔
565

4✔
566
        // Spend an HTLC output on our local commitment tx using the 2nd
4✔
567
        // success transaction.
4✔
568
        createWitness := func(signer Signer, txn *wire.MsgTx,
4✔
569
                hashCache *txscript.TxSigHashes,
4✔
570
                prevOutputFetcher txscript.PrevOutputFetcher,
4✔
571
                txinIdx int) (wire.TxWitness, error) {
7✔
572

3✔
573
                desc := signDetails.SignDesc
3✔
574
                desc.SigHashes = hashCache
3✔
575
                desc.InputIndex = txinIdx
3✔
576
                desc.PrevOutputFetcher = prevOutputFetcher
3✔
577

3✔
578
                return ReceiverHtlcSpendRedeem(
3✔
579
                        signDetails.PeerSig, signDetails.SigHashType,
3✔
580
                        preimage[:], signer, &desc, txn,
3✔
581
                )
3✔
582
        }
3✔
583
        input := MakeBaseInput(
4✔
584
                &signedTx.TxIn[0].PreviousOutPoint,
4✔
585
                HtlcAcceptedSuccessSecondLevelInputConfirmed,
4✔
586
                &signDetails.SignDesc, heightHint, nil, opts...,
4✔
587
        )
4✔
588
        input.blockToMaturity = 1
4✔
589

4✔
590
        return HtlcSecondLevelAnchorInput{
4✔
591
                SignedTx:      signedTx,
4✔
592
                inputKit:      input.inputKit,
4✔
593
                createWitness: createWitness,
4✔
594
                preimage:      preimage[:],
4✔
595
        }
4✔
596
}
597

598
// MakeHtlcSecondLevelSuccessTaprootInput creates an input that allows the
599
// sweeper to spend an HTLC output to the second level on our taproot
600
// commitment transaction.
601
func MakeHtlcSecondLevelSuccessTaprootInput(signedTx *wire.MsgTx,
602
        signDetails *SignDetails, preimage lntypes.Preimage,
603
        heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput {
3✔
604

3✔
605
        createWitness := func(signer Signer, txn *wire.MsgTx,
3✔
606
                hashCache *txscript.TxSigHashes,
3✔
607
                prevOutputFetcher txscript.PrevOutputFetcher,
3✔
608
                txinIdx int) (wire.TxWitness, error) {
6✔
609

3✔
610
                desc := signDetails.SignDesc
3✔
611
                if desc.ControlBlock == nil {
3✔
612
                        return nil, fmt.Errorf("ctrl block must be set")
×
613
                }
×
614

615
                desc.SigHashes = txscript.NewTxSigHashes(txn, prevOutputFetcher)
3✔
616
                desc.InputIndex = txinIdx
3✔
617
                desc.PrevOutputFetcher = prevOutputFetcher
3✔
618

3✔
619
                desc.SignMethod = TaprootScriptSpendSignMethod
3✔
620

3✔
621
                return ReceiverHTLCScriptTaprootRedeem(
3✔
622
                        signDetails.PeerSig, signDetails.SigHashType,
3✔
623
                        preimage[:], signer, &desc, txn, nil, nil,
3✔
624
                )
3✔
625
        }
626

627
        input := MakeBaseInput(
3✔
628
                &signedTx.TxIn[0].PreviousOutPoint,
3✔
629
                TaprootHtlcAcceptedLocalSuccess,
3✔
630
                &signDetails.SignDesc, heightHint, nil, opts...,
3✔
631
        )
3✔
632
        input.blockToMaturity = 1
3✔
633

3✔
634
        return HtlcSecondLevelAnchorInput{
3✔
635
                inputKit:      input.inputKit,
3✔
636
                SignedTx:      signedTx,
3✔
637
                createWitness: createWitness,
3✔
638
                preimage:      preimage[:],
3✔
639
        }
3✔
640
}
641

642
// Compile-time constraints to ensure each input struct implement the Input
643
// interface.
644
var _ Input = (*BaseInput)(nil)
645
var _ Input = (*HtlcSucceedInput)(nil)
646
var _ Input = (*HtlcSecondLevelAnchorInput)(nil)
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