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

lightningnetwork / lnd / 15843723163

24 Jun 2025 07:07AM UTC coverage: 56.04%. First build
15843723163

Pull #9985

github

web-flow
Merge 7f2e35788 into 1b95798fc
Pull Request #9985: multi: implement awareness of the final/production taproot channel variant

145 of 393 new or added lines in 18 files covered. (36.9%)

108424 of 193477 relevant lines covered (56.04%)

22573.28 hits per line

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

43.93
/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 {
×
88
        return fmt.Sprintf("fee=%v, weight=%v", t.Fee, t.Weight)
×
89
}
×
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,930✔
127
        return i.outpoint
2,930✔
128
}
2,930✔
129

130
// RequiredTxOut returns a nil for the base input type.
131
func (i *inputKit) RequiredTxOut() *wire.TxOut {
143✔
132
        return nil
143✔
133
}
143✔
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) {
26✔
139
        return i.cltvExpiry, i.cltvExpiry > 0
26✔
140
}
26✔
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,530✔
145
        return i.witnessType
1,530✔
146
}
1,530✔
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,890✔
151
        return &i.signDesc
2,890✔
152
}
2,890✔
153

154
// HeightHint returns the minimum height at which a confirmed spending
155
// tx can occur.
156
func (i *inputKit) HeightHint() uint32 {
5✔
157
        return i.heightHint
5✔
158
}
5✔
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,417✔
164
        return i.blockToMaturity
1,417✔
165
}
1,417✔
166

167
// Cpfp returns information about a possibly unconfirmed parent tx.
168
func (i *inputKit) UnconfParent() *TxInfo {
66✔
169
        return i.unconfParent
66✔
170
}
66✔
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] {
10✔
175
        return i.resolutionBlob
10✔
176
}
10✔
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,132✔
187
        return &inputOpts{}
1,132✔
188
}
1,132✔
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 {
11✔
197
        return func(o *inputOpts) {
22✔
198
                o.resolutionBlob = b
11✔
199
        }
11✔
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,132✔
213

1,132✔
214
        opt := defaultInputOpts()
1,132✔
215
        for _, optF := range opts {
1,143✔
216
                optF(opt)
11✔
217
        }
11✔
218

219
        return BaseInput{
1,132✔
220
                inputKit{
1,132✔
221
                        outpoint:       *outpoint,
1,132✔
222
                        witnessType:    witnessType,
1,132✔
223
                        signDesc:       *signDescriptor,
1,132✔
224
                        heightHint:     heightHint,
1,132✔
225
                        unconfParent:   unconfParent,
1,132✔
226
                        resolutionBlob: opt.resolutionBlob,
1,132✔
227
                },
1,132✔
228
        }
1,132✔
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 {
567✔
236

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

567✔
241
        return &input
567✔
242
}
567✔
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 {
509✔
249

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

509✔
254
        input.blockToMaturity = blockToMaturity
509✔
255

509✔
256
        return &input
509✔
257
}
509✔
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 {
4✔
264

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

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

4✔
272
        return &input
4✔
273
}
4✔
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,417✔
283

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

1,417✔
288
        return witnessFunc(txn, hashCache, txinIdx)
1,417✔
289
}
1,417✔
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 {
4✔
310

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

4✔
317
        return HtlcSucceedInput{
4✔
318
                inputKit: input.inputKit,
4✔
319
                preimage: preimage,
4✔
320
        }
4✔
321
}
4✔
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 {
×
329

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

×
336
        return HtlcSucceedInput{
×
337
                inputKit: input.inputKit,
×
338
                preimage: preimage,
×
339
        }
×
340
}
×
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) {
×
369

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

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

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

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

399
        return &Script{
×
400
                Witness: witness,
×
401
        }, nil
×
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 {
×
436
        return i.SignedTx.TxOut[0]
×
437
}
×
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) {
×
443
        return i.SignedTx.LockTime, true
×
444
}
×
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) {
×
454

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

462
        return &Script{
×
463
                Witness: witness,
×
464
        }, nil
×
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 {
2✔
482

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

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

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

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

2✔
508
        return HtlcSecondLevelAnchorInput{
2✔
509
                inputKit:      input.inputKit,
2✔
510
                SignedTx:      signedTx,
2✔
511
                createWitness: createWitness,
2✔
512
        }
2✔
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 {
×
522

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

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

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

×
537
                desc.SignMethod = TaprootScriptSpendSignMethod
×
538

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

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

×
552
        return HtlcSecondLevelAnchorInput{
×
553
                inputKit:      input.inputKit,
×
554
                SignedTx:      signedTx,
×
555
                createWitness: createWitness,
×
556
        }
×
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 {
1✔
565

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

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

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

1✔
590
        return HtlcSecondLevelAnchorInput{
1✔
591
                SignedTx:      signedTx,
1✔
592
                inputKit:      input.inputKit,
1✔
593
                createWitness: createWitness,
1✔
594
                preimage:      preimage[:],
1✔
595
        }
1✔
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 {
×
604

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

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

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

×
619
                desc.SignMethod = TaprootScriptSpendSignMethod
×
620

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

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

×
634
        return HtlcSecondLevelAnchorInput{
×
635
                inputKit:      input.inputKit,
×
636
                SignedTx:      signedTx,
×
637
                createWitness: createWitness,
×
638
                preimage:      preimage[:],
×
639
        }
×
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

© 2025 Coveralls, Inc