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

lightningnetwork / lnd / 12343072627

15 Dec 2024 11:09PM UTC coverage: 57.504% (-1.1%) from 58.636%
12343072627

Pull #9315

github

yyforyongyu
contractcourt: offer outgoing htlc one block earlier before its expiry

We need to offer the outgoing htlc one block earlier to make sure when
the expiry height hits, the sweeper will not miss sweeping it in the
same block. This also means the outgoing contest resolver now only does
one thing - watch for preimage spend till height expiry-1, which can
easily be moved into the timeout resolver instead in the future.
Pull Request #9315: Implement `blockbeat`

1445 of 2007 new or added lines in 26 files covered. (72.0%)

19246 existing lines in 249 files now uncovered.

102342 of 177975 relevant lines covered (57.5%)

24772.24 hits per line

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

44.81
/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.
UNCOV
87
func (t *TxInfo) String() string {
×
UNCOV
88
        return fmt.Sprintf("fee=%v, weight=%v", t.Fee, t.Weight)
×
UNCOV
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,912✔
127
        return i.outpoint
2,912✔
128
}
2,912✔
129

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

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

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

1,128✔
214
        opt := defaultInputOpts()
1,128✔
215
        for _, optF := range opts {
1,136✔
216
                optF(opt)
8✔
217
        }
8✔
218

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

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

566✔
241
        return &input
566✔
242
}
566✔
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,416✔
283

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

1,416✔
288
        return witnessFunc(txn, hashCache, txinIdx)
1,416✔
289
}
1,416✔
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,
UNCOV
328
        opts ...InputOpt) HtlcSucceedInput {
×
UNCOV
329

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

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

342
// CraftInputScript returns a valid set of input scripts allowing this output
343
// to be spent. The returns input scripts should target the input at location
344
// txIndex within the passed transaction. The input scripts generated by this
345
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
346
func (h *HtlcSucceedInput) CraftInputScript(signer Signer, txn *wire.MsgTx,
347
        hashCache *txscript.TxSigHashes,
348
        prevOutputFetcher txscript.PrevOutputFetcher, txinIdx int) (*Script,
UNCOV
349
        error) {
×
UNCOV
350

×
UNCOV
351
        desc := h.signDesc
×
UNCOV
352
        desc.SigHashes = hashCache
×
UNCOV
353
        desc.InputIndex = txinIdx
×
UNCOV
354
        desc.PrevOutputFetcher = prevOutputFetcher
×
UNCOV
355

×
UNCOV
356
        isTaproot := txscript.IsPayToTaproot(desc.Output.PkScript)
×
UNCOV
357

×
UNCOV
358
        var (
×
UNCOV
359
                witness wire.TxWitness
×
UNCOV
360
                err     error
×
UNCOV
361
        )
×
UNCOV
362
        if isTaproot {
×
UNCOV
363
                if desc.ControlBlock == nil {
×
364
                        return nil, fmt.Errorf("ctrl block must be set")
×
365
                }
×
366

UNCOV
367
                desc.SignMethod = TaprootScriptSpendSignMethod
×
UNCOV
368
                witness, err = SenderHTLCScriptTaprootRedeem(
×
UNCOV
369
                        signer, &desc, txn, h.preimage, nil, nil,
×
UNCOV
370
                )
×
UNCOV
371
        } else {
×
UNCOV
372
                witness, err = SenderHtlcSpendRedeem(
×
UNCOV
373
                        signer, &desc, txn, h.preimage,
×
UNCOV
374
                )
×
UNCOV
375
        }
×
UNCOV
376
        if err != nil {
×
377
                return nil, err
×
378
        }
×
379

UNCOV
380
        return &Script{
×
UNCOV
381
                Witness: witness,
×
UNCOV
382
        }, nil
×
383
}
384

385
// Preimage returns the preimage for the input if it is an HTLC input.
386
func (h *HtlcSucceedInput) Preimage() fn.Option[lntypes.Preimage] {
×
387
        if len(h.preimage) == 0 {
×
388
                return fn.None[lntypes.Preimage]()
×
389
        }
×
390

391
        return fn.Some(lntypes.Preimage(h.preimage))
×
392
}
393

394
// HtlcSecondLevelAnchorInput is an input type used to spend HTLC outputs
395
// using a re-signed second level transaction, either via the timeout or success
396
// paths.
397
type HtlcSecondLevelAnchorInput struct {
398
        inputKit
399

400
        // SignedTx is the original second level transaction signed by the
401
        // channel peer.
402
        SignedTx *wire.MsgTx
403

404
        // createWitness creates a witness allowing the passed transaction to
405
        // spend the input.
406
        createWitness func(signer Signer, txn *wire.MsgTx,
407
                hashCache *txscript.TxSigHashes,
408
                prevOutputFetcher txscript.PrevOutputFetcher,
409
                txinIdx int) (wire.TxWitness, error)
410

411
        preimage []byte
412
}
413

414
// RequiredTxOut returns the tx out needed to be present on the sweep tx for
415
// the spend of the input to be valid.
UNCOV
416
func (i *HtlcSecondLevelAnchorInput) RequiredTxOut() *wire.TxOut {
×
UNCOV
417
        return i.SignedTx.TxOut[0]
×
UNCOV
418
}
×
419

420
// RequiredLockTime returns the locktime needed for the sweep tx for the spend
421
// of the input to be valid. For a second level HTLC timeout this will be the
422
// CLTV expiry, for HTLC success it will be zero.
UNCOV
423
func (i *HtlcSecondLevelAnchorInput) RequiredLockTime() (uint32, bool) {
×
UNCOV
424
        return i.SignedTx.LockTime, true
×
UNCOV
425
}
×
426

427
// CraftInputScript returns a valid set of input scripts allowing this output
428
// to be spent. The returns input scripts should target the input at location
429
// txIndex within the passed transaction. The input scripts generated by this
430
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
431
func (i *HtlcSecondLevelAnchorInput) CraftInputScript(signer Signer,
432
        txn *wire.MsgTx, hashCache *txscript.TxSigHashes,
433
        prevOutputFetcher txscript.PrevOutputFetcher, txinIdx int) (*Script,
UNCOV
434
        error) {
×
UNCOV
435

×
UNCOV
436
        witness, err := i.createWitness(
×
UNCOV
437
                signer, txn, hashCache, prevOutputFetcher, txinIdx,
×
UNCOV
438
        )
×
UNCOV
439
        if err != nil {
×
440
                return nil, err
×
441
        }
×
442

UNCOV
443
        return &Script{
×
UNCOV
444
                Witness: witness,
×
UNCOV
445
        }, nil
×
446
}
447

448
// Preimage returns the preimage for the input if it is an HTLC input.
449
func (i *HtlcSecondLevelAnchorInput) Preimage() fn.Option[lntypes.Preimage] {
×
450
        if len(i.preimage) == 0 {
×
451
                return fn.None[lntypes.Preimage]()
×
452
        }
×
453

454
        return fn.Some(lntypes.Preimage(i.preimage))
×
455
}
456

457
// MakeHtlcSecondLevelTimeoutAnchorInput creates an input allowing the sweeper
458
// to spend the HTLC output on our commit using the second level timeout
459
// transaction.
460
func MakeHtlcSecondLevelTimeoutAnchorInput(signedTx *wire.MsgTx,
461
        signDetails *SignDetails, heightHint uint32,
462
        opts ...InputOpt) HtlcSecondLevelAnchorInput {
2✔
463

2✔
464
        // Spend an HTLC output on our local commitment tx using the
2✔
465
        // 2nd timeout transaction.
2✔
466
        createWitness := func(signer Signer, txn *wire.MsgTx,
2✔
467
                hashCache *txscript.TxSigHashes,
2✔
468
                prevOutputFetcher txscript.PrevOutputFetcher,
2✔
469
                txinIdx int) (wire.TxWitness, error) {
2✔
UNCOV
470

×
UNCOV
471
                desc := signDetails.SignDesc
×
UNCOV
472
                desc.SigHashes = txscript.NewTxSigHashes(txn, prevOutputFetcher)
×
UNCOV
473
                desc.InputIndex = txinIdx
×
UNCOV
474
                desc.PrevOutputFetcher = prevOutputFetcher
×
UNCOV
475

×
UNCOV
476
                return SenderHtlcSpendTimeout(
×
UNCOV
477
                        signDetails.PeerSig, signDetails.SigHashType, signer,
×
UNCOV
478
                        &desc, txn,
×
UNCOV
479
                )
×
UNCOV
480
        }
×
481

482
        input := MakeBaseInput(
2✔
483
                &signedTx.TxIn[0].PreviousOutPoint,
2✔
484
                HtlcOfferedTimeoutSecondLevelInputConfirmed,
2✔
485
                &signDetails.SignDesc, heightHint, nil, opts...,
2✔
486
        )
2✔
487
        input.blockToMaturity = 1
2✔
488

2✔
489
        return HtlcSecondLevelAnchorInput{
2✔
490
                inputKit:      input.inputKit,
2✔
491
                SignedTx:      signedTx,
2✔
492
                createWitness: createWitness,
2✔
493
        }
2✔
494
}
495

496
// MakeHtlcSecondLevelTimeoutTaprootInput creates an input that allows the
497
// sweeper to spend an HTLC output to the second level on our commitment
498
// transaction. The sweeper is also able to generate witnesses on demand to
499
// sweep the second level HTLC aggregated with other transactions.
500
func MakeHtlcSecondLevelTimeoutTaprootInput(signedTx *wire.MsgTx,
501
        signDetails *SignDetails,
UNCOV
502
        heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput {
×
UNCOV
503

×
UNCOV
504
        createWitness := func(signer Signer, txn *wire.MsgTx,
×
UNCOV
505
                hashCache *txscript.TxSigHashes,
×
UNCOV
506
                prevOutputFetcher txscript.PrevOutputFetcher,
×
UNCOV
507
                txinIdx int) (wire.TxWitness, error) {
×
UNCOV
508

×
UNCOV
509
                desc := signDetails.SignDesc
×
UNCOV
510
                if desc.ControlBlock == nil {
×
511
                        return nil, fmt.Errorf("ctrl block must be set")
×
512
                }
×
513

UNCOV
514
                desc.SigHashes = txscript.NewTxSigHashes(txn, prevOutputFetcher)
×
UNCOV
515
                desc.InputIndex = txinIdx
×
UNCOV
516
                desc.PrevOutputFetcher = prevOutputFetcher
×
UNCOV
517

×
UNCOV
518
                desc.SignMethod = TaprootScriptSpendSignMethod
×
UNCOV
519

×
UNCOV
520
                return SenderHTLCScriptTaprootTimeout(
×
UNCOV
521
                        signDetails.PeerSig, signDetails.SigHashType, signer,
×
UNCOV
522
                        &desc, txn, nil, nil,
×
UNCOV
523
                )
×
524
        }
525

UNCOV
526
        input := MakeBaseInput(
×
UNCOV
527
                &signedTx.TxIn[0].PreviousOutPoint,
×
UNCOV
528
                TaprootHtlcLocalOfferedTimeout,
×
UNCOV
529
                &signDetails.SignDesc, heightHint, nil, opts...,
×
UNCOV
530
        )
×
UNCOV
531
        input.blockToMaturity = 1
×
UNCOV
532

×
UNCOV
533
        return HtlcSecondLevelAnchorInput{
×
UNCOV
534
                inputKit:      input.inputKit,
×
UNCOV
535
                SignedTx:      signedTx,
×
UNCOV
536
                createWitness: createWitness,
×
UNCOV
537
        }
×
538
}
539

540
// MakeHtlcSecondLevelSuccessAnchorInput creates an input allowing the sweeper
541
// to spend the HTLC output on our commit using the second level success
542
// transaction.
543
func MakeHtlcSecondLevelSuccessAnchorInput(signedTx *wire.MsgTx,
544
        signDetails *SignDetails, preimage lntypes.Preimage,
545
        heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput {
1✔
546

1✔
547
        // Spend an HTLC output on our local commitment tx using the 2nd
1✔
548
        // success transaction.
1✔
549
        createWitness := func(signer Signer, txn *wire.MsgTx,
1✔
550
                hashCache *txscript.TxSigHashes,
1✔
551
                prevOutputFetcher txscript.PrevOutputFetcher,
1✔
552
                txinIdx int) (wire.TxWitness, error) {
1✔
UNCOV
553

×
UNCOV
554
                desc := signDetails.SignDesc
×
UNCOV
555
                desc.SigHashes = hashCache
×
UNCOV
556
                desc.InputIndex = txinIdx
×
UNCOV
557
                desc.PrevOutputFetcher = prevOutputFetcher
×
UNCOV
558

×
UNCOV
559
                return ReceiverHtlcSpendRedeem(
×
UNCOV
560
                        signDetails.PeerSig, signDetails.SigHashType,
×
UNCOV
561
                        preimage[:], signer, &desc, txn,
×
UNCOV
562
                )
×
UNCOV
563
        }
×
564
        input := MakeBaseInput(
1✔
565
                &signedTx.TxIn[0].PreviousOutPoint,
1✔
566
                HtlcAcceptedSuccessSecondLevelInputConfirmed,
1✔
567
                &signDetails.SignDesc, heightHint, nil, opts...,
1✔
568
        )
1✔
569
        input.blockToMaturity = 1
1✔
570

1✔
571
        return HtlcSecondLevelAnchorInput{
1✔
572
                SignedTx:      signedTx,
1✔
573
                inputKit:      input.inputKit,
1✔
574
                createWitness: createWitness,
1✔
575
                preimage:      preimage[:],
1✔
576
        }
1✔
577
}
578

579
// MakeHtlcSecondLevelSuccessTaprootInput creates an input that allows the
580
// sweeper to spend an HTLC output to the second level on our taproot
581
// commitment transaction.
582
func MakeHtlcSecondLevelSuccessTaprootInput(signedTx *wire.MsgTx,
583
        signDetails *SignDetails, preimage lntypes.Preimage,
UNCOV
584
        heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput {
×
UNCOV
585

×
UNCOV
586
        createWitness := func(signer Signer, txn *wire.MsgTx,
×
UNCOV
587
                hashCache *txscript.TxSigHashes,
×
UNCOV
588
                prevOutputFetcher txscript.PrevOutputFetcher,
×
UNCOV
589
                txinIdx int) (wire.TxWitness, error) {
×
UNCOV
590

×
UNCOV
591
                desc := signDetails.SignDesc
×
UNCOV
592
                if desc.ControlBlock == nil {
×
593
                        return nil, fmt.Errorf("ctrl block must be set")
×
594
                }
×
595

UNCOV
596
                desc.SigHashes = txscript.NewTxSigHashes(txn, prevOutputFetcher)
×
UNCOV
597
                desc.InputIndex = txinIdx
×
UNCOV
598
                desc.PrevOutputFetcher = prevOutputFetcher
×
UNCOV
599

×
UNCOV
600
                desc.SignMethod = TaprootScriptSpendSignMethod
×
UNCOV
601

×
UNCOV
602
                return ReceiverHTLCScriptTaprootRedeem(
×
UNCOV
603
                        signDetails.PeerSig, signDetails.SigHashType,
×
UNCOV
604
                        preimage[:], signer, &desc, txn, nil, nil,
×
UNCOV
605
                )
×
606
        }
607

UNCOV
608
        input := MakeBaseInput(
×
UNCOV
609
                &signedTx.TxIn[0].PreviousOutPoint,
×
UNCOV
610
                TaprootHtlcAcceptedLocalSuccess,
×
UNCOV
611
                &signDetails.SignDesc, heightHint, nil, opts...,
×
UNCOV
612
        )
×
UNCOV
613
        input.blockToMaturity = 1
×
UNCOV
614

×
UNCOV
615
        return HtlcSecondLevelAnchorInput{
×
UNCOV
616
                inputKit:      input.inputKit,
×
UNCOV
617
                SignedTx:      signedTx,
×
UNCOV
618
                createWitness: createWitness,
×
UNCOV
619
                preimage:      preimage[:],
×
UNCOV
620
        }
×
621
}
622

623
// Compile-time constraints to ensure each input struct implement the Input
624
// interface.
625
var _ Input = (*BaseInput)(nil)
626
var _ Input = (*HtlcSucceedInput)(nil)
627
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