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

lightningnetwork / lnd / 23572043051

26 Mar 2026 12:56AM UTC coverage: 52.204% (-9.9%) from 62.117%
23572043051

Pull #9985

github

web-flow
Merge d8d2a45f2 into 46fbc10fc
Pull Request #9985: multi: implement awareness of the final/production taproot channel variant

376 of 589 new or added lines in 25 files covered. (63.84%)

31494 existing lines in 479 files now uncovered.

101631 of 194681 relevant lines covered (52.2%)

2.16 hits per line

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

74.52
/input/script_utils.go
1
package input
2

3
import (
4
        "bytes"
5
        "crypto/sha256"
6
        "encoding/hex"
7
        "fmt"
8

9
        "github.com/btcsuite/btcd/btcec/v2"
10
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
11
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
12
        "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
13
        "github.com/btcsuite/btcd/btcutil"
14
        "github.com/btcsuite/btcd/chaincfg/chainhash"
15
        "github.com/btcsuite/btcd/txscript"
16
        "github.com/btcsuite/btcd/wire"
17
        "github.com/lightningnetwork/lnd/fn/v2"
18
        "github.com/lightningnetwork/lnd/lntypes"
19
        "github.com/lightningnetwork/lnd/lnutils"
20
        "golang.org/x/crypto/ripemd160"
21
)
22

23
// TemplateParams is a type alias for the map[string]interface{} type used
24
// with txscript.ScriptTemplate to make code more readable.
25
type TemplateParams map[string]interface{}
26

27
var (
28
        // TODO(roasbeef): remove these and use the one's defined in txscript
29
        // within testnet-L.
30

31
        // SequenceLockTimeSeconds is the 22nd bit which indicates the lock
32
        // time is in seconds.
33
        SequenceLockTimeSeconds = uint32(1 << 22)
34
)
35

36
// MustParsePubKey parses a hex encoded public key string into a public key and
37
// panic if parsing fails.
38
func MustParsePubKey(pubStr string) btcec.PublicKey {
4✔
39
        pubBytes, err := hex.DecodeString(pubStr)
4✔
40
        if err != nil {
4✔
41
                panic(err)
×
42
        }
43

44
        pub, err := btcec.ParsePubKey(pubBytes)
4✔
45
        if err != nil {
4✔
46
                panic(err)
×
47
        }
48

49
        return *pub
4✔
50
}
51

52
// TaprootNUMSHex is the hex encoded version of the taproot NUMs key.
53
const TaprootNUMSHex = "02dca094751109d0bd055d03565874e8276dd53e926b44e3bd1bb" +
54
        "6bf4bc130a279"
55

56
var (
57
        // TaprootNUMSKey is a NUMS key (nothing up my sleeves number) that has
58
        // no known private key. This was generated using the following script:
59
        // https://github.com/lightninglabs/lightning-node-connect/tree/
60
        // master/mailbox/numsgen, with the seed phrase "Lightning Simple
61
        // Taproot".
62
        TaprootNUMSKey = MustParsePubKey(TaprootNUMSHex)
63
)
64

65
// Signature is an interface for objects that can populate signatures during
66
// witness construction.
67
type Signature interface {
68
        // Serialize returns a DER-encoded ECDSA signature.
69
        Serialize() []byte
70

71
        // Verify return true if the ECDSA signature is valid for the passed
72
        // message digest under the provided public key.
73
        Verify([]byte, *btcec.PublicKey) bool
74
}
75

76
// ParseSignature parses a raw signature into an input.Signature instance. This
77
// routine supports parsing normal ECDSA DER encoded signatures, as well as
78
// schnorr signatures.
79
func ParseSignature(rawSig []byte) (Signature, error) {
4✔
80
        if len(rawSig) == schnorr.SignatureSize {
8✔
81
                return schnorr.ParseSignature(rawSig)
4✔
82
        }
4✔
83

84
        return ecdsa.ParseDERSignature(rawSig)
4✔
85
}
86

87
// WitnessScriptHash generates a pay-to-witness-script-hash public key script
88
// paying to a version 0 witness program paying to the passed redeem script.
89
func WitnessScriptHash(witnessScript []byte) ([]byte, error) {
4✔
90
        scriptHash := sha256.Sum256(witnessScript)
4✔
91
        return txscript.ScriptTemplate(
4✔
92
                `OP_0 {{ hex .ScriptHash }}`,
4✔
93
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
94
                        "ScriptHash": scriptHash[:],
4✔
95
                }),
4✔
96
        )
4✔
97
}
4✔
98

99
// WitnessPubKeyHash generates a pay-to-witness-pubkey-hash public key script
100
// paying to a version 0 witness program containing the passed serialized
101
// public key.
102
func WitnessPubKeyHash(pubkey []byte) ([]byte, error) {
4✔
103
        pkhash := btcutil.Hash160(pubkey)
4✔
104
        return txscript.ScriptTemplate(
4✔
105
                `OP_0 {{ hex .PKHash }}`,
4✔
106
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
107
                        "PKHash": pkhash,
4✔
108
                }),
4✔
109
        )
4✔
110
}
4✔
111

112
// GenerateP2SH generates a pay-to-script-hash public key script paying to the
113
// passed redeem script.
114
func GenerateP2SH(script []byte) ([]byte, error) {
4✔
115
        scriptHash := btcutil.Hash160(script)
4✔
116
        return txscript.ScriptTemplate(
4✔
117
                `OP_HASH160 {{ hex .ScriptHash }} OP_EQUAL`,
4✔
118
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
119
                        "ScriptHash": scriptHash,
4✔
120
                }),
4✔
121
        )
4✔
122
}
4✔
123

124
// GenerateP2PKH generates a pay-to-public-key-hash public key script paying to
125
// the passed serialized public key.
126
func GenerateP2PKH(pubkey []byte) ([]byte, error) {
4✔
127
        pkHash := btcutil.Hash160(pubkey)
4✔
128
        return txscript.ScriptTemplate(
4✔
129
                `OP_DUP OP_HASH160 {{ hex .pkh }} OP_EQUALVERIFY OP_CHECKSIG`,
4✔
130
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
131
                        "pkh": pkHash,
4✔
132
                }),
4✔
133
        )
4✔
134
}
4✔
135

136
// GenerateUnknownWitness generates the maximum-sized witness public key script
137
// consisting of a version push and a 40-byte data push.
138
func GenerateUnknownWitness() ([]byte, error) {
4✔
139
        witnessScript := make([]byte, 40)
4✔
140
        return txscript.ScriptTemplate(
4✔
141
                `OP_0 {{ hex .WitnessScript }}`,
4✔
142
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
143
                        "WitnessScript": witnessScript,
4✔
144
                }),
4✔
145
        )
4✔
146
}
4✔
147

148
// GenMultiSigScript generates the non-p2sh'd multisig script for 2 of 2
149
// pubkeys.
150
func GenMultiSigScript(aPub, bPub []byte) ([]byte, error) {
4✔
151
        if len(aPub) != 33 || len(bPub) != 33 {
4✔
152
                return nil, fmt.Errorf("pubkey size error: compressed " +
×
153
                        "pubkeys only")
×
154
        }
×
155

156
        // Swap to sort pubkeys if needed. Keys are sorted in lexicographical
157
        // order. The signatures within the scriptSig must also adhere to the
158
        // order, ensuring that the signatures for each public key appears in
159
        // the proper order on the stack.
160
        if bytes.Compare(aPub, bPub) == 1 {
8✔
161
                aPub, bPub = bPub, aPub
4✔
162
        }
4✔
163

164
        return txscript.ScriptTemplate(
4✔
165
                `OP_2 {{ hex .pubA }} {{ hex .pubB }} OP_2 OP_CHECKMULTISIG`,
4✔
166
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
167
                        "pubA": aPub,
4✔
168
                        "pubB": bPub,
4✔
169
                }),
4✔
170
        )
4✔
171
}
172

173
// GenFundingPkScript creates a redeem script, and its matching p2wsh
174
// output for the funding transaction.
175
func GenFundingPkScript(aPub, bPub []byte, amt int64) ([]byte, *wire.TxOut, error) {
4✔
176
        // As a sanity check, ensure that the passed amount is above zero.
4✔
177
        if amt <= 0 {
4✔
178
                return nil, nil, fmt.Errorf("can't create FundTx script with " +
×
179
                        "zero, or negative coins")
×
180
        }
×
181

182
        // First, create the 2-of-2 multi-sig script itself.
183
        witnessScript, err := GenMultiSigScript(aPub, bPub)
4✔
184
        if err != nil {
4✔
185
                return nil, nil, err
×
186
        }
×
187

188
        // With the 2-of-2 script in had, generate a p2wsh script which pays
189
        // to the funding script.
190
        pkScript, err := WitnessScriptHash(witnessScript)
4✔
191
        if err != nil {
4✔
192
                return nil, nil, err
×
193
        }
×
194

195
        return witnessScript, wire.NewTxOut(amt, pkScript), nil
4✔
196
}
197

198
// GenTaprootFundingScript constructs the taproot-native funding output that
199
// uses MuSig2 to create a single aggregated key to anchor the channel.
200
func GenTaprootFundingScript(aPub, bPub *btcec.PublicKey,
201
        amt int64, tapscriptRoot fn.Option[chainhash.Hash]) ([]byte,
202
        *wire.TxOut, error) {
4✔
203

4✔
204
        muSig2Opt := musig2.WithBIP86KeyTweak()
4✔
205
        tapscriptRoot.WhenSome(func(scriptRoot chainhash.Hash) {
4✔
UNCOV
206
                muSig2Opt = musig2.WithTaprootKeyTweak(scriptRoot[:])
×
UNCOV
207
        })
×
208

209
        // Similar to the existing p2wsh funding script, we'll always make sure
210
        // we sort the keys before any major operations. In order to ensure
211
        // that there's no other way this output can be spent, we'll use a BIP
212
        // 86 tweak here during aggregation, unless the user has explicitly
213
        // specified a tapscript root.
214
        combinedKey, _, _, err := musig2.AggregateKeys(
4✔
215
                []*btcec.PublicKey{aPub, bPub}, true, muSig2Opt,
4✔
216
        )
4✔
217
        if err != nil {
4✔
218
                return nil, nil, fmt.Errorf("unable to combine keys: %w", err)
×
219
        }
×
220

221
        // Now that we have the combined key, we can create a taproot pkScript
222
        // from this, and then make the txOut given the amount.
223
        pkScript, err := PayToTaprootScript(combinedKey.FinalKey)
4✔
224
        if err != nil {
4✔
225
                return nil, nil, fmt.Errorf("unable to make taproot "+
×
226
                        "pkscript: %w", err)
×
227
        }
×
228

229
        txOut := wire.NewTxOut(amt, pkScript)
4✔
230

4✔
231
        // For the "witness program" we just return the raw pkScript since the
4✔
232
        // output we create can _only_ be spent with a MuSig2 signature.
4✔
233
        return pkScript, txOut, nil
4✔
234
}
235

236
// SpendMultiSig generates the witness stack required to redeem the 2-of-2 p2wsh
237
// multi-sig output.
238
func SpendMultiSig(witnessScript, pubA []byte, sigA Signature,
239
        pubB []byte, sigB Signature) [][]byte {
4✔
240

4✔
241
        witness := make([][]byte, 4)
4✔
242

4✔
243
        // When spending a p2wsh multi-sig script, rather than an OP_0, we add
4✔
244
        // a nil stack element to eat the extra pop.
4✔
245
        witness[0] = nil
4✔
246

4✔
247
        // When initially generating the witnessScript, we sorted the serialized
4✔
248
        // public keys in descending order. So we do a quick comparison in order
4✔
249
        // ensure the signatures appear on the Script Virtual Machine stack in
4✔
250
        // the correct order.
4✔
251
        if bytes.Compare(pubA, pubB) == 1 {
8✔
252
                witness[1] = append(sigB.Serialize(), byte(txscript.SigHashAll))
4✔
253
                witness[2] = append(sigA.Serialize(), byte(txscript.SigHashAll))
4✔
254
        } else {
8✔
255
                witness[1] = append(sigA.Serialize(), byte(txscript.SigHashAll))
4✔
256
                witness[2] = append(sigB.Serialize(), byte(txscript.SigHashAll))
4✔
257
        }
4✔
258

259
        // Finally, add the preimage as the last witness element.
260
        witness[3] = witnessScript
4✔
261

4✔
262
        return witness
4✔
263
}
264

265
// FindScriptOutputIndex finds the index of the public key script output
266
// matching 'script'. Additionally, a boolean is returned indicating if a
267
// matching output was found at all.
268
//
269
// NOTE: The search stops after the first matching script is found.
270
func FindScriptOutputIndex(tx *wire.MsgTx, script []byte) (bool, uint32) {
4✔
271
        found := false
4✔
272
        index := uint32(0)
4✔
273
        for i, txOut := range tx.TxOut {
8✔
274
                if bytes.Equal(txOut.PkScript, script) {
8✔
275
                        found = true
4✔
276
                        index = uint32(i)
4✔
277
                        break
4✔
278
                }
279
        }
280

281
        return found, index
4✔
282
}
283

284
// Ripemd160H calculates the ripemd160 of the passed byte slice. This is used to
285
// calculate the intermediate hash for payment pre-images. Payment hashes are
286
// the result of ripemd160(sha256(paymentPreimage)). As a result, the value
287
// passed in should be the sha256 of the payment hash.
288
func Ripemd160H(d []byte) []byte {
4✔
289
        h := ripemd160.New()
4✔
290
        h.Write(d)
4✔
291
        return h.Sum(nil)
4✔
292
}
4✔
293

294
// SenderHTLCScript constructs the public key script for an outgoing HTLC
295
// output payment for the sender's version of the commitment transaction. The
296
// possible script paths from this output include:
297
//
298
//   - The sender timing out the HTLC using the second level HTLC timeout
299
//     transaction.
300
//   - The receiver of the HTLC claiming the output on-chain with the payment
301
//     preimage.
302
//   - The receiver of the HTLC sweeping all the funds in the case that a
303
//     revoked commitment transaction bearing this HTLC was broadcast.
304
//
305
// If confirmedSpend=true, a 1 OP_CSV check will be added to the non-revocation
306
// cases, to allow sweeping only after confirmation.
307
//
308
// Possible Input Scripts:
309
//
310
//        SENDR: <0> <sendr sig>  <recvr sig> <0> (spend using HTLC timeout transaction)
311
//        RECVR: <recvr sig>  <preimage>
312
//        REVOK: <revoke sig> <revoke key>
313
//         * receiver revoke
314
//
315
// Offered HTLC Output Script:
316
//
317
//         OP_DUP OP_HASH160 <revocation key hash160> OP_EQUAL
318
//         OP_IF
319
//                OP_CHECKSIG
320
//         OP_ELSE
321
//                <recv htlc key>
322
//                OP_SWAP OP_SIZE 32 OP_EQUAL
323
//                OP_NOTIF
324
//                    OP_DROP 2 OP_SWAP <sender htlc key> 2 OP_CHECKMULTISIG
325
//                OP_ELSE
326
//                    OP_HASH160 <ripemd160(payment hash)> OP_EQUALVERIFY
327
//                    OP_CHECKSIG
328
//                OP_ENDIF
329
//                [1 OP_CHECKSEQUENCEVERIFY OP_DROP] <- if allowing confirmed
330
//                spend only.
331
//         OP_ENDIF
332
func SenderHTLCScript(senderHtlcKey, receiverHtlcKey,
333
        revocationKey *btcec.PublicKey, paymentHash []byte,
334
        confirmedSpend bool) ([]byte, error) {
4✔
335

4✔
336
        // Build the base script template. The script structure is:
4✔
337
        //   - Revocation path: hash the top-of-stack item and check if it
4✔
338
        //     matches the revocation key hash. If so, checksig.
4✔
339
        //   - Else branch: push the receiver's key, swap to expose the
4✔
340
        //     witness item, and check its size.
4✔
341
        //     - If not 32 bytes (timeout path): drop, then 2-of-2 multisig
4✔
342
        //       with sender+receiver HTLC keys.
4✔
343
        //     - If 32 bytes (preimage path): hash160-verify, then checksig
4✔
344
        //       with the receiver's key.
4✔
345
        //   - Optional 1-block CSV for confirmed spend.
4✔
346
        scriptTemplate := `
4✔
347
                OP_DUP OP_HASH160 {{ hex .RevKeyHash }} OP_EQUAL
4✔
348
                OP_IF
4✔
349
                        OP_CHECKSIG
4✔
350
                OP_ELSE
4✔
351
                        {{ hex .ReceiverKey }}
4✔
352
                        OP_SWAP
4✔
353
                        OP_SIZE 32 OP_EQUAL
4✔
354
                        OP_NOTIF
4✔
355
                                OP_DROP 2 OP_SWAP
4✔
356
                                {{ hex .SenderKey }} 2 OP_CHECKMULTISIG
4✔
357
                        OP_ELSE
4✔
358
                                OP_HASH160 {{ hex .PaymentHashRipemd }}
4✔
359
                                OP_EQUALVERIFY
4✔
360
                                OP_CHECKSIG
4✔
361
                        OP_ENDIF
4✔
362
        `
4✔
363

4✔
364
        // Add 1 block CSV delay if a confirmation is required for the
4✔
365
        // non-revocation clauses.
4✔
366
        if confirmedSpend {
8✔
367
                scriptTemplate += `
4✔
368
                        OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP`
4✔
369
        }
4✔
370

371
        // Close out the top level if statement.
372
        scriptTemplate += ` OP_ENDIF`
4✔
373

4✔
374
        // Use the ScriptTemplate function with the properly formatted template
4✔
375
        return txscript.ScriptTemplate(
4✔
376
                scriptTemplate,
4✔
377
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
378
                        "RevKeyHash":        btcutil.Hash160(revocationKey.SerializeCompressed()), //nolint:ll
4✔
379
                        "ReceiverKey":       receiverHtlcKey.SerializeCompressed(),                //nolint:ll
4✔
380
                        "SenderKey":         senderHtlcKey.SerializeCompressed(),                  //nolint:ll
4✔
381
                        "PaymentHashRipemd": Ripemd160H(paymentHash),
4✔
382
                }),
4✔
383
        )
4✔
384
}
385

386
// SenderHtlcSpendRevokeWithKey constructs a valid witness allowing the receiver of an
387
// HTLC to claim the output with knowledge of the revocation private key in the
388
// scenario that the sender of the HTLC broadcasts a previously revoked
389
// commitment transaction. A valid spend requires knowledge of the private key
390
// that corresponds to their revocation base point and also the private key from
391
// the per commitment point, and a valid signature under the combined public
392
// key.
393
func SenderHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor,
UNCOV
394
        revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
×
UNCOV
395

×
UNCOV
396
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
×
UNCOV
397
        if err != nil {
×
398
                return nil, err
×
399
        }
×
400

401
        // The stack required to sweep a revoke HTLC output consists simply of
402
        // the exact witness stack as one of a regular p2wkh spend. The only
403
        // difference is that the keys used were derived in an adversarial
404
        // manner in order to encode the revocation contract into a sig+key
405
        // pair.
UNCOV
406
        witnessStack := wire.TxWitness(make([][]byte, 3))
×
UNCOV
407
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
×
UNCOV
408
        witnessStack[1] = revokeKey.SerializeCompressed()
×
UNCOV
409
        witnessStack[2] = signDesc.WitnessScript
×
UNCOV
410

×
UNCOV
411
        return witnessStack, nil
×
412
}
413

414
// SenderHtlcSpendRevoke constructs a valid witness allowing the receiver of an
415
// HTLC to claim the output with knowledge of the revocation private key in the
416
// scenario that the sender of the HTLC broadcasts a previously revoked
417
// commitment transaction.  This method first derives the appropriate revocation
418
// key, and requires that the provided SignDescriptor has a local revocation
419
// basepoint and commitment secret in the PubKey and DoubleTweak fields,
420
// respectively.
421
func SenderHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
UNCOV
422
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
×
UNCOV
423

×
UNCOV
424
        revokeKey, err := deriveRevokePubKey(signDesc)
×
UNCOV
425
        if err != nil {
×
426
                return nil, err
×
427
        }
×
428

UNCOV
429
        return SenderHtlcSpendRevokeWithKey(signer, signDesc, revokeKey, sweepTx)
×
430
}
431

432
// IsHtlcSpendRevoke is used to determine if the passed spend is spending a
433
// HTLC output using the revocation key.
434
func IsHtlcSpendRevoke(txIn *wire.TxIn, signDesc *SignDescriptor) (
435
        bool, error) {
4✔
436

4✔
437
        // For taproot channels, the revocation path only has a single witness,
4✔
438
        // as that's the key spend path.
4✔
439
        isTaproot := txscript.IsPayToTaproot(signDesc.Output.PkScript)
4✔
440
        if isTaproot {
8✔
441
                return len(txIn.Witness) == 1, nil
4✔
442
        }
4✔
443

UNCOV
444
        revokeKey, err := deriveRevokePubKey(signDesc)
×
UNCOV
445
        if err != nil {
×
446
                return false, err
×
447
        }
×
448

UNCOV
449
        if len(txIn.Witness) == 3 &&
×
UNCOV
450
                bytes.Equal(txIn.Witness[1], revokeKey.SerializeCompressed()) {
×
UNCOV
451

×
UNCOV
452
                return true, nil
×
UNCOV
453
        }
×
454

UNCOV
455
        return false, nil
×
456
}
457

458
// SenderHtlcSpendRedeem constructs a valid witness allowing the receiver of an
459
// HTLC to redeem the pending output in the scenario that the sender broadcasts
460
// their version of the commitment transaction. A valid spend requires
461
// knowledge of the payment preimage, and a valid signature under the receivers
462
// public key.
463
func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor,
464
        sweepTx *wire.MsgTx, paymentPreimage []byte) (wire.TxWitness, error) {
4✔
465

4✔
466
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
467
        if err != nil {
4✔
468
                return nil, err
×
469
        }
×
470

471
        // The stack required to spend this output is simply the signature
472
        // generated above under the receiver's public key, and the payment
473
        // pre-image.
474
        witnessStack := wire.TxWitness(make([][]byte, 3))
4✔
475
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
476
        witnessStack[1] = paymentPreimage
4✔
477
        witnessStack[2] = signDesc.WitnessScript
4✔
478

4✔
479
        return witnessStack, nil
4✔
480
}
481

482
// SenderHtlcSpendTimeout constructs a valid witness allowing the sender of an
483
// HTLC to activate the time locked covenant clause of a soon to be expired
484
// HTLC.  This script simply spends the multi-sig output using the
485
// pre-generated HTLC timeout transaction.
486
func SenderHtlcSpendTimeout(receiverSig Signature,
487
        receiverSigHash txscript.SigHashType, signer Signer,
488
        signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) (
489
        wire.TxWitness, error) {
4✔
490

4✔
491
        sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
4✔
492
        if err != nil {
4✔
493
                return nil, err
×
494
        }
×
495

496
        // We place a zero as the first item of the evaluated witness stack in
497
        // order to force Script execution to the HTLC timeout clause. The
498
        // second zero is required to consume the extra pop due to a bug in the
499
        // original OP_CHECKMULTISIG.
500
        witnessStack := wire.TxWitness(make([][]byte, 5))
4✔
501
        witnessStack[0] = nil
4✔
502
        witnessStack[1] = append(receiverSig.Serialize(), byte(receiverSigHash))
4✔
503
        witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
504
        witnessStack[3] = nil
4✔
505
        witnessStack[4] = signDesc.WitnessScript
4✔
506

4✔
507
        return witnessStack, nil
4✔
508
}
509

510
// SenderHTLCTapLeafTimeout returns the full tapscript leaf for the timeout
511
// path of the sender HTLC. This is a small script that allows the sender to
512
// timeout the HTLC after a period of time:
513
//
514
//        <local_key> OP_CHECKSIGVERIFY
515
//        <remote_key> OP_CHECKSIG
516
func SenderHTLCTapLeafTimeout(senderHtlcKey,
517
        receiverHtlcKey *btcec.PublicKey,
518
        _ ...TaprootScriptOpt) (txscript.TapLeaf, error) {
4✔
519

4✔
520
        timeoutLeafScript, err := txscript.ScriptTemplate(
4✔
521
                `
4✔
522
                {{ hex .SenderKey }} OP_CHECKSIGVERIFY
4✔
523
                {{ hex .ReceiverKey }} OP_CHECKSIG`,
4✔
524
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
525
                        "SenderKey":   schnorr.SerializePubKey(senderHtlcKey),
4✔
526
                        "ReceiverKey": schnorr.SerializePubKey(receiverHtlcKey),
4✔
527
                }),
4✔
528
        )
4✔
529
        if err != nil {
4✔
530
                return txscript.TapLeaf{}, err
×
531
        }
×
532

533
        return txscript.NewBaseTapLeaf(timeoutLeafScript), nil
4✔
534
}
535

536
// SenderHTLCTapLeafSuccess returns the full tapscript leaf for the success
537
// path of the sender HTLC. This is a small script that allows the receiver to
538
// redeem the HTLC with a pre-image:
539
//
540
//        OP_SIZE 32 OP_EQUALVERIFY OP_HASH160
541
//        <RIPEMD160(payment_hash)> OP_EQUALVERIFY
542
//        <remote_htlcpubkey> OP_CHECKSIG
543
//        1 OP_CHECKSEQUENCEVERIFY OP_DROP
544
func SenderHTLCTapLeafSuccess(receiverHtlcKey *btcec.PublicKey,
545
        paymentHash []byte,
546
        opts ...TaprootScriptOpt) (txscript.TapLeaf, error) {
4✔
547

4✔
548
        opt := defaultTaprootScriptOpt()
4✔
549
        for _, o := range opts {
8✔
550
                o(opt)
4✔
551
        }
4✔
552

553
        // Check pre-image size (32 bytes), verify hash, then verify the
554
        // remote party's signature with a 1-block CSV delay.
555
        var scriptTemplate string
4✔
556
        switch {
4✔
557
        case opt.prodScript:
4✔
558
                scriptTemplate = `
4✔
559
                OP_SIZE 32 OP_EQUALVERIFY
4✔
560
                OP_HASH160 {{ hex .PaymentHashRipemd }} OP_EQUALVERIFY
4✔
561
                {{ hex .ReceiverKey }} OP_CHECKSIGVERIFY
4✔
562
                OP_1 OP_CHECKSEQUENCEVERIFY`
4✔
563
        default:
4✔
564
                scriptTemplate = `
4✔
565
                OP_SIZE 32 OP_EQUALVERIFY
4✔
566
                OP_HASH160 {{ hex .PaymentHashRipemd }} OP_EQUALVERIFY
4✔
567
                {{ hex .ReceiverKey }} OP_CHECKSIG
4✔
568
                OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP`
4✔
569
        }
570

571
        successLeafScript, err := txscript.ScriptTemplate(
4✔
572
                scriptTemplate,
4✔
573
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
574
                        "PaymentHashRipemd": Ripemd160H(paymentHash),
4✔
575
                        "ReceiverKey": schnorr.SerializePubKey(
4✔
576
                                receiverHtlcKey,
4✔
577
                        ),
4✔
578
                }),
4✔
579
        )
4✔
580
        if err != nil {
4✔
581
                return txscript.TapLeaf{}, err
×
582
        }
×
583

584
        return txscript.NewBaseTapLeaf(successLeafScript), nil
4✔
585
}
586

587
// htlcType is an enum value that denotes what type of HTLC script this is.
588
type htlcType uint8
589

590
const (
591
        // htlcLocalIncoming represents an incoming HTLC on the local
592
        // commitment transaction.
593
        htlcLocalIncoming htlcType = iota
594

595
        // htlcLocalOutgoing represents an outgoing HTLC on the local
596
        // commitment transaction.
597
        htlcLocalOutgoing
598

599
        // htlcRemoteIncoming represents an incoming HTLC on the remote
600
        // commitment transaction.
601
        htlcRemoteIncoming
602

603
        // htlcRemoteOutgoing represents an outgoing HTLC on the remote
604
        // commitment transaction.
605
        htlcRemoteOutgoing
606
)
607

608
// HtlcScriptTree holds the taproot output key, as well as the two script path
609
// leaves that every taproot HTLC script depends on.
610
type HtlcScriptTree struct {
611
        ScriptTree
612

613
        // SuccessTapLeaf is the tapleaf for the redemption path.
614
        SuccessTapLeaf txscript.TapLeaf
615

616
        // TimeoutTapLeaf is the tapleaf for the timeout path.
617
        TimeoutTapLeaf txscript.TapLeaf
618

619
        // AuxLeaf is an auxiliary leaf that can be used to extend the base
620
        // HTLC script tree with new spend paths, or just as extra commitment
621
        // space. When present, this leaf will always be in the right-most area
622
        // of the tapscript tree.
623
        AuxLeaf AuxTapLeaf
624

625
        // htlcType is the type of HTLC script this is.
626
        htlcType htlcType
627
}
628

629
// WitnessScriptToSign returns the witness script that we'll use when signing
630
// for the remote party, and also verifying signatures on our transactions. As
631
// an example, when we create an outgoing HTLC for the remote party, we want to
632
// sign the success path for them, so we'll return the success path leaf.
633
func (h *HtlcScriptTree) WitnessScriptToSign() []byte {
4✔
634
        switch h.htlcType {
4✔
635
        // For incoming HLTCs on our local commitment, we care about verifying
636
        // the success path.
637
        case htlcLocalIncoming:
4✔
638
                return h.SuccessTapLeaf.Script
4✔
639

640
        // For incoming HTLCs on the remote party's commitment, we want to sign
641
        // the timeout path for them.
642
        case htlcRemoteIncoming:
4✔
643
                return h.TimeoutTapLeaf.Script
4✔
644

645
        // For outgoing HTLCs on our local commitment, we want to verify the
646
        // timeout path.
647
        case htlcLocalOutgoing:
4✔
648
                return h.TimeoutTapLeaf.Script
4✔
649

650
        // For outgoing HTLCs on the remote party's commitment, we want to sign
651
        // the success path for them.
652
        case htlcRemoteOutgoing:
4✔
653
                return h.SuccessTapLeaf.Script
4✔
654

655
        default:
×
656
                panic(fmt.Sprintf("unknown htlc type: %v", h.htlcType))
×
657
        }
658
}
659

660
// WitnessScriptForPath returns the witness script for the given spending path.
661
// An error is returned if the path is unknown.
662
func (h *HtlcScriptTree) WitnessScriptForPath(path ScriptPath) ([]byte, error) {
4✔
663
        switch path {
4✔
664
        case ScriptPathSuccess:
4✔
665
                return h.SuccessTapLeaf.Script, nil
4✔
666
        case ScriptPathTimeout:
4✔
667
                return h.TimeoutTapLeaf.Script, nil
4✔
668
        default:
×
669
                return nil, fmt.Errorf("unknown script path: %v", path)
×
670
        }
671
}
672

673
// CtrlBlockForPath returns the control block for the given spending path. For
674
// script types that don't have a control block, nil is returned.
675
func (h *HtlcScriptTree) CtrlBlockForPath(
676
        path ScriptPath) (*txscript.ControlBlock, error) {
4✔
677

4✔
678
        switch path {
4✔
679
        case ScriptPathSuccess:
4✔
680
                return lnutils.Ptr(MakeTaprootCtrlBlock(
4✔
681
                        h.SuccessTapLeaf.Script, h.InternalKey,
4✔
682
                        h.TapscriptTree,
4✔
683
                )), nil
4✔
684
        case ScriptPathTimeout:
4✔
685
                return lnutils.Ptr(MakeTaprootCtrlBlock(
4✔
686
                        h.TimeoutTapLeaf.Script, h.InternalKey,
4✔
687
                        h.TapscriptTree,
4✔
688
                )), nil
4✔
689
        default:
×
690
                return nil, fmt.Errorf("unknown script path: %v", path)
×
691
        }
692
}
693

694
// Tree returns the underlying ScriptTree of the HtlcScriptTree.
695
func (h *HtlcScriptTree) Tree() ScriptTree {
×
696
        return h.ScriptTree
×
697
}
×
698

699
// A compile time check to ensure HtlcScriptTree implements the
700
// TapscriptMultiplexer interface.
701
var _ TapscriptDescriptor = (*HtlcScriptTree)(nil)
702

703
// senderHtlcTapScriptTree builds the tapscript tree which is used to anchor
704
// the HTLC key for HTLCs on the sender's commitment.
705
func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
706
        revokeKey *btcec.PublicKey, payHash []byte, hType htlcType,
707
        auxLeaf AuxTapLeaf,
708
        opts ...TaprootScriptOpt) (*HtlcScriptTree, error) {
4✔
709

4✔
710
        // First, we'll obtain the tap leaves for both the success and timeout
4✔
711
        // path.
4✔
712
        successTapLeaf, err := SenderHTLCTapLeafSuccess(
4✔
713
                receiverHtlcKey, payHash, opts...,
4✔
714
        )
4✔
715
        if err != nil {
4✔
716
                return nil, err
×
717
        }
×
718
        timeoutTapLeaf, err := SenderHTLCTapLeafTimeout(
4✔
719
                senderHtlcKey, receiverHtlcKey, opts...,
4✔
720
        )
4✔
721
        if err != nil {
4✔
722
                return nil, err
×
723
        }
×
724

725
        tapLeaves := []txscript.TapLeaf{successTapLeaf, timeoutTapLeaf}
4✔
726
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
4✔
UNCOV
727
                tapLeaves = append(tapLeaves, l)
×
UNCOV
728
        })
×
729

730
        // With the two leaves obtained, we'll now make the tapscript tree,
731
        // then obtain the root from that
732
        tapscriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
4✔
733

4✔
734
        tapScriptRoot := tapscriptTree.RootNode.TapHash()
4✔
735

4✔
736
        // With the tapscript root obtained, we'll tweak the revocation key
4✔
737
        // with this value to obtain the key that HTLCs will be sent to.
4✔
738
        htlcKey := txscript.ComputeTaprootOutputKey(
4✔
739
                revokeKey, tapScriptRoot[:],
4✔
740
        )
4✔
741

4✔
742
        return &HtlcScriptTree{
4✔
743
                ScriptTree: ScriptTree{
4✔
744
                        TaprootKey:    htlcKey,
4✔
745
                        TapscriptTree: tapscriptTree,
4✔
746
                        TapscriptRoot: tapScriptRoot[:],
4✔
747
                        InternalKey:   revokeKey,
4✔
748
                },
4✔
749
                SuccessTapLeaf: successTapLeaf,
4✔
750
                TimeoutTapLeaf: timeoutTapLeaf,
4✔
751
                AuxLeaf:        auxLeaf,
4✔
752
                htlcType:       hType,
4✔
753
        }, nil
4✔
754
}
755

756
// SenderHTLCScriptTaproot constructs the taproot witness program (schnorr key)
757
// for an outgoing HTLC on the sender's version of the commitment transaction.
758
// This method returns the top level tweaked public key that commits to both
759
// the script paths. This is also known as an offered HTLC.
760
//
761
// The returned key commits to a tapscript tree with two possible paths:
762
//
763
//   - Timeout path:
764
//     <local_key> OP_CHECKSIGVERIFY
765
//     <remote_key> OP_CHECKSIG
766
//
767
//   - Success path:
768
//     OP_SIZE 32 OP_EQUALVERIFY
769
//     OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
770
//     <remote_htlcpubkey> OP_CHECKSIG
771
//     1 OP_CHECKSEQUENCEVERIFY OP_DROP
772
//
773
// The timeout path can be spent with a witness of (sender timeout):
774
//
775
//        <receiver sig> <local sig> <timeout_script> <control_block>
776
//
777
// The success path can be spent with a valid control block, and a witness of
778
// (receiver redeem):
779
//
780
//        <receiver sig> <preimage> <success_script> <control_block>
781
//
782
// The top level keyspend key is the revocation key, which allows a defender to
783
// unilaterally spend the created output.
784
func SenderHTLCScriptTaproot(senderHtlcKey, receiverHtlcKey,
785
        revokeKey *btcec.PublicKey, payHash []byte,
786
        whoseCommit lntypes.ChannelParty, auxLeaf AuxTapLeaf,
787
        opts ...TaprootScriptOpt) (*HtlcScriptTree, error) {
4✔
788

4✔
789
        var hType htlcType
4✔
790
        if whoseCommit.IsLocal() {
8✔
791
                hType = htlcLocalOutgoing
4✔
792
        } else {
8✔
793
                hType = htlcRemoteIncoming
4✔
794
        }
4✔
795

796
        // Given all the necessary parameters, we'll return the HTLC script
797
        // tree that includes the top level output script, as well as the two
798
        // tap leaf paths.
799
        return senderHtlcTapScriptTree(
4✔
800
                senderHtlcKey, receiverHtlcKey, revokeKey, payHash, hType,
4✔
801
                auxLeaf, opts...,
4✔
802
        )
4✔
803
}
804

805
// maybeAppendSighashType appends a sighash type to the end of a signature if
806
// the sighash type isn't sighash default.
807
func maybeAppendSighash(sig Signature, sigHash txscript.SigHashType) []byte {
4✔
808
        sigBytes := sig.Serialize()
4✔
809
        if sigHash == txscript.SigHashDefault {
8✔
810
                return sigBytes
4✔
811
        }
4✔
812

813
        return append(sigBytes, byte(sigHash))
4✔
814
}
815

816
// SenderHTLCScriptTaprootRedeem creates a valid witness needed to redeem a
817
// sender taproot HTLC with the pre-image. The returned witness is valid and
818
// includes the control block required to spend the output. This is the offered
819
// HTLC claimed by the remote party.
820
func SenderHTLCScriptTaprootRedeem(signer Signer, signDesc *SignDescriptor,
821
        sweepTx *wire.MsgTx, preimage []byte, revokeKey *btcec.PublicKey,
822
        tapscriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
823

4✔
824
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
825
        if err != nil {
4✔
826
                return nil, err
×
827
        }
×
828

829
        // In addition to the signature and the witness/leaf script, we also
830
        // need to make a control block proof using the tapscript tree.
831
        var ctrlBlock []byte
4✔
832
        if signDesc.ControlBlock == nil {
4✔
UNCOV
833
                successControlBlock := MakeTaprootCtrlBlock(
×
UNCOV
834
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
×
UNCOV
835
                )
×
UNCOV
836

×
UNCOV
837
                ctrlBytes, err := successControlBlock.ToBytes()
×
UNCOV
838
                if err != nil {
×
839
                        return nil, err
×
840
                }
×
841

UNCOV
842
                ctrlBlock = ctrlBytes
×
843
        } else {
4✔
844
                ctrlBlock = signDesc.ControlBlock
4✔
845
        }
4✔
846

847
        // The final witness stack is:
848
        //  <receiver sig> <preimage> <success_script> <control_block>
849
        witnessStack := make(wire.TxWitness, 4)
4✔
850
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
851
        witnessStack[1] = preimage
4✔
852
        witnessStack[2] = signDesc.WitnessScript
4✔
853
        witnessStack[3] = ctrlBlock
4✔
854

4✔
855
        return witnessStack, nil
4✔
856
}
857

858
// SenderHTLCScriptTaprootTimeout creates a valid witness needed to timeout an
859
// HTLC on the sender's commitment transaction. The returned witness is valid
860
// and includes the control block required to spend the output. This is a
861
// timeout of the offered HTLC by the sender.
862
func SenderHTLCScriptTaprootTimeout(receiverSig Signature,
863
        receiverSigHash txscript.SigHashType, signer Signer,
864
        signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx,
865
        revokeKey *btcec.PublicKey,
866
        tapscriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
867

4✔
868
        sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
4✔
869
        if err != nil {
4✔
870
                return nil, err
×
871
        }
×
872

873
        // With the sweep signature obtained, we'll obtain the control block
874
        // proof needed to perform a valid spend for the timeout path.
875
        var ctrlBlockBytes []byte
4✔
876
        if signDesc.ControlBlock == nil {
8✔
877
                timeoutControlBlock := MakeTaprootCtrlBlock(
4✔
878
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
4✔
879
                )
4✔
880
                ctrlBytes, err := timeoutControlBlock.ToBytes()
4✔
881
                if err != nil {
4✔
882
                        return nil, err
×
883
                }
×
884

885
                ctrlBlockBytes = ctrlBytes
4✔
886
        } else {
4✔
887
                ctrlBlockBytes = signDesc.ControlBlock
4✔
888
        }
4✔
889

890
        // The final witness stack is:
891
        //  <receiver sig> <local sig> <timeout_script> <control_block>
892
        witnessStack := make(wire.TxWitness, 4)
4✔
893
        witnessStack[0] = maybeAppendSighash(receiverSig, receiverSigHash)
4✔
894
        witnessStack[1] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
895
        witnessStack[2] = signDesc.WitnessScript
4✔
896
        witnessStack[3] = ctrlBlockBytes
4✔
897

4✔
898
        return witnessStack, nil
4✔
899
}
900

901
// SenderHTLCScriptTaprootRevoke creates a valid witness needed to spend the
902
// revocation path of the HTLC. This uses a plain keyspend using the specified
903
// revocation key.
904
func SenderHTLCScriptTaprootRevoke(signer Signer, signDesc *SignDescriptor,
905
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
906

4✔
907
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
908
        if err != nil {
4✔
909
                return nil, err
×
910
        }
×
911

912
        // The witness stack in this case is pretty simple: we only need to
913
        // specify the signature generated.
914
        witnessStack := make(wire.TxWitness, 1)
4✔
915
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
916

4✔
917
        return witnessStack, nil
4✔
918
}
919

920
// ReceiverHTLCScript constructs the public key script for an incoming HTLC
921
// output payment for the receiver's version of the commitment transaction. The
922
// possible execution paths from this script include:
923
//   - The receiver of the HTLC uses its second level HTLC transaction to
924
//     advance the state of the HTLC into the delay+claim state.
925
//   - The sender of the HTLC sweeps all the funds of the HTLC as a breached
926
//     commitment was broadcast.
927
//   - The sender of the HTLC sweeps the HTLC on-chain after the timeout period
928
//     of the HTLC has passed.
929
//
930
// If confirmedSpend=true, a 1 OP_CSV check will be added to the non-revocation
931
// cases, to allow sweeping only after confirmation.
932
//
933
// Possible Input Scripts:
934
//
935
//        RECVR: <0> <sender sig> <recvr sig> <preimage> (spend using HTLC success transaction)
936
//        REVOK: <sig> <key>
937
//        SENDR: <sig> 0
938
//
939
// Received HTLC Output Script:
940
//
941
//         OP_DUP OP_HASH160 <revocation key hash160> OP_EQUAL
942
//         OP_IF
943
//                 OP_CHECKSIG
944
//         OP_ELSE
945
//                <sendr htlc key>
946
//                OP_SWAP OP_SIZE 32 OP_EQUAL
947
//                OP_IF
948
//                    OP_HASH160 <ripemd160(payment hash)> OP_EQUALVERIFY
949
//                    2 OP_SWAP <recvr htlc key> 2 OP_CHECKMULTISIG
950
//                OP_ELSE
951
//                    OP_DROP <cltv expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
952
//                    OP_CHECKSIG
953
//                OP_ENDIF
954
//                [1 OP_CHECKSEQUENCEVERIFY OP_DROP] <- if allowing confirmed
955
//                spend only.
956
//         OP_ENDIF
957
func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
958
        receiverHtlcKey, revocationKey *btcec.PublicKey,
959
        paymentHash []byte, confirmedSpend bool) ([]byte, error) {
4✔
960

4✔
961
        // The script structure mirrors SenderHTLCScript but from the
4✔
962
        // receiver's perspective:
4✔
963
        //   - Revocation path: DUP+HASH160 check, then checksig.
4✔
964
        //   - Else: push sender key, swap, check size.
4✔
965
        //     - If 32 bytes (preimage path): hash160-verify the preimage,
4✔
966
        //       then 2-of-2 multisig with sender+receiver keys.
4✔
967
        //     - If not 32 bytes (timeout path): drop, CLTV check, checksig.
4✔
968
        //   - Optional 1-block CSV for confirmed spend.
4✔
969
        scriptTemplate := `
4✔
970
                OP_DUP OP_HASH160 {{ hex .RevKeyHash }} OP_EQUAL
4✔
971
                OP_IF
4✔
972
                        OP_CHECKSIG
4✔
973
                OP_ELSE
4✔
974
                        {{ hex .SenderKey }}
4✔
975
                        OP_SWAP
4✔
976
                        OP_SIZE 32 OP_EQUAL
4✔
977
                        OP_IF
4✔
978
                                OP_HASH160 {{ hex .PaymentHashRipemd }}
4✔
979
                                OP_EQUALVERIFY
4✔
980
                                OP_2 OP_SWAP {{ hex .ReceiverKey }}
4✔
981
                                OP_2 OP_CHECKMULTISIG
4✔
982
                        OP_ELSE
4✔
983
                                OP_DROP
4✔
984
                                {{ .CltvExpiry }} OP_CHECKLOCKTIMEVERIFY
4✔
985
                                OP_DROP OP_CHECKSIG
4✔
986
                        OP_ENDIF
4✔
987
        `
4✔
988

4✔
989
        // Add 1 block CSV delay for non-revocation clauses if confirmation is
4✔
990
        // required.
4✔
991
        if confirmedSpend {
8✔
992
                scriptTemplate += `
4✔
993
                        OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP`
4✔
994
        }
4✔
995

996
        // Close out the outer if statement.
997
        scriptTemplate += ` OP_ENDIF`
4✔
998

4✔
999
        // Use the ScriptTemplate function with the properly formatted template
4✔
1000
        return txscript.ScriptTemplate(
4✔
1001
                scriptTemplate,
4✔
1002
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
1003
                        "RevKeyHash": btcutil.Hash160(
4✔
1004
                                revocationKey.SerializeCompressed(),
4✔
1005
                        ),
4✔
1006
                        "SenderKey":         senderHtlcKey.SerializeCompressed(),   //nolint:ll
4✔
1007
                        "ReceiverKey":       receiverHtlcKey.SerializeCompressed(), //nolint:ll
4✔
1008
                        "PaymentHashRipemd": Ripemd160H(paymentHash),
4✔
1009
                        "CltvExpiry":        int64(cltvExpiry),
4✔
1010
                }),
4✔
1011
        )
4✔
1012
}
1013

1014
// ReceiverHtlcSpendRedeem constructs a valid witness allowing the receiver of
1015
// an HTLC to redeem the conditional payment in the event that their commitment
1016
// transaction is broadcast. This clause transitions the state of the HLTC
1017
// output into the delay+claim state by activating the off-chain covenant bound
1018
// by the 2-of-2 multi-sig output. The HTLC success timeout transaction being
1019
// signed has a relative timelock delay enforced by its sequence number. This
1020
// delay give the sender of the HTLC enough time to revoke the output if this
1021
// is a breach commitment transaction.
1022
func ReceiverHtlcSpendRedeem(senderSig Signature,
1023
        senderSigHash txscript.SigHashType, paymentPreimage []byte,
1024
        signer Signer, signDesc *SignDescriptor, htlcSuccessTx *wire.MsgTx) (
1025
        wire.TxWitness, error) {
4✔
1026

4✔
1027
        // First, we'll generate a signature for the HTLC success transaction.
4✔
1028
        // The signDesc should be signing with the public key used as the
4✔
1029
        // receiver's public key and also the correct single tweak.
4✔
1030
        sweepSig, err := signer.SignOutputRaw(htlcSuccessTx, signDesc)
4✔
1031
        if err != nil {
4✔
1032
                return nil, err
×
1033
        }
×
1034

1035
        // The final witness stack is used the provide the script with the
1036
        // payment pre-image, and also execute the multi-sig clause after the
1037
        // pre-images matches. We add a nil item at the bottom of the stack in
1038
        // order to consume the extra pop within OP_CHECKMULTISIG.
1039
        witnessStack := wire.TxWitness(make([][]byte, 5))
4✔
1040
        witnessStack[0] = nil
4✔
1041
        witnessStack[1] = append(senderSig.Serialize(), byte(senderSigHash))
4✔
1042
        witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
1043
        witnessStack[3] = paymentPreimage
4✔
1044
        witnessStack[4] = signDesc.WitnessScript
4✔
1045

4✔
1046
        return witnessStack, nil
4✔
1047
}
1048

1049
// ReceiverHtlcSpendRevokeWithKey constructs a valid witness allowing the sender of an
1050
// HTLC within a previously revoked commitment transaction to re-claim the
1051
// pending funds in the case that the receiver broadcasts this revoked
1052
// commitment transaction.
1053
func ReceiverHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor,
UNCOV
1054
        revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
×
UNCOV
1055

×
UNCOV
1056
        // First, we'll generate a signature for the sweep transaction.  The
×
UNCOV
1057
        // signDesc should be signing with the public key used as the fully
×
UNCOV
1058
        // derived revocation public key and also the correct double tweak
×
UNCOV
1059
        // value.
×
UNCOV
1060
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
×
UNCOV
1061
        if err != nil {
×
1062
                return nil, err
×
1063
        }
×
1064

1065
        // We place a zero, then one as the first items in the evaluated
1066
        // witness stack in order to force script execution to the HTLC
1067
        // revocation clause.
UNCOV
1068
        witnessStack := wire.TxWitness(make([][]byte, 3))
×
UNCOV
1069
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
×
UNCOV
1070
        witnessStack[1] = revokeKey.SerializeCompressed()
×
UNCOV
1071
        witnessStack[2] = signDesc.WitnessScript
×
UNCOV
1072

×
UNCOV
1073
        return witnessStack, nil
×
1074
}
1075

UNCOV
1076
func deriveRevokePubKey(signDesc *SignDescriptor) (*btcec.PublicKey, error) {
×
UNCOV
1077
        if signDesc.KeyDesc.PubKey == nil {
×
1078
                return nil, fmt.Errorf("cannot generate witness with nil " +
×
1079
                        "KeyDesc pubkey")
×
1080
        }
×
1081

1082
        // Derive the revocation key using the local revocation base point and
1083
        // commitment point.
UNCOV
1084
        revokeKey := DeriveRevocationPubkey(
×
UNCOV
1085
                signDesc.KeyDesc.PubKey,
×
UNCOV
1086
                signDesc.DoubleTweak.PubKey(),
×
UNCOV
1087
        )
×
UNCOV
1088

×
UNCOV
1089
        return revokeKey, nil
×
1090
}
1091

1092
// ReceiverHtlcSpendRevoke constructs a valid witness allowing the sender of an
1093
// HTLC within a previously revoked commitment transaction to re-claim the
1094
// pending funds in the case that the receiver broadcasts this revoked
1095
// commitment transaction. This method first derives the appropriate revocation
1096
// key, and requires that the provided SignDescriptor has a local revocation
1097
// basepoint and commitment secret in the PubKey and DoubleTweak fields,
1098
// respectively.
1099
func ReceiverHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
UNCOV
1100
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
×
UNCOV
1101

×
UNCOV
1102
        revokeKey, err := deriveRevokePubKey(signDesc)
×
UNCOV
1103
        if err != nil {
×
1104
                return nil, err
×
1105
        }
×
1106

UNCOV
1107
        return ReceiverHtlcSpendRevokeWithKey(signer, signDesc, revokeKey, sweepTx)
×
1108
}
1109

1110
// ReceiverHtlcSpendTimeout constructs a valid witness allowing the sender of
1111
// an HTLC to recover the pending funds after an absolute timeout in the
1112
// scenario that the receiver of the HTLC broadcasts their version of the
1113
// commitment transaction. If the caller has already set the lock time on the
1114
// spending transaction, than a value of -1 can be passed for the cltvExpiry
1115
// value.
1116
//
1117
// NOTE: The target input of the passed transaction MUST NOT have a final
1118
// sequence number. Otherwise, the OP_CHECKLOCKTIMEVERIFY check will fail.
1119
func ReceiverHtlcSpendTimeout(signer Signer, signDesc *SignDescriptor,
1120
        sweepTx *wire.MsgTx, cltvExpiry int32) (wire.TxWitness, error) {
4✔
1121

4✔
1122
        // If the caller set a proper timeout value, then we'll apply it
4✔
1123
        // directly to the transaction.
4✔
1124
        if cltvExpiry != -1 {
4✔
UNCOV
1125
                // The HTLC output has an absolute time period before we are
×
UNCOV
1126
                // permitted to recover the pending funds. Therefore we need to
×
UNCOV
1127
                // set the locktime on this sweeping transaction in order to
×
UNCOV
1128
                // pass Script verification.
×
UNCOV
1129
                sweepTx.LockTime = uint32(cltvExpiry)
×
UNCOV
1130
        }
×
1131

1132
        // With the lock time on the transaction set, we'll not generate a
1133
        // signature for the sweep transaction. The passed sign descriptor
1134
        // should be created using the raw public key of the sender (w/o the
1135
        // single tweak applied), and the single tweak set to the proper value
1136
        // taking into account the current state's point.
1137
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
1138
        if err != nil {
4✔
1139
                return nil, err
×
1140
        }
×
1141

1142
        witnessStack := wire.TxWitness(make([][]byte, 3))
4✔
1143
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
1144
        witnessStack[1] = nil
4✔
1145
        witnessStack[2] = signDesc.WitnessScript
4✔
1146

4✔
1147
        return witnessStack, nil
4✔
1148
}
1149

1150
// ReceiverHtlcTapLeafTimeout returns the full tapscript leaf for the timeout
1151
// path of the sender HTLC. This is a small script that allows the sender
1152
// timeout the HTLC after expiry:
1153
//
1154
//        <sender_htlcpubkey> OP_CHECKSIG
1155
//        1 OP_CHECKSEQUENCEVERIFY OP_DROP
1156
//        <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
1157
func ReceiverHtlcTapLeafTimeout(senderHtlcKey *btcec.PublicKey,
1158
        cltvExpiry uint32, opts ...TaprootScriptOpt) (txscript.TapLeaf, error) {
4✔
1159

4✔
1160
        opt := defaultTaprootScriptOpt()
4✔
1161
        for _, o := range opts {
8✔
1162
                o(opt)
4✔
1163
        }
4✔
1164

1165
        // Verify sender signature, enforce 1-block CSV, then verify CLTV
1166
        // expiry. The prod script variant uses CHECKSIGVERIFY/VERIFY instead
1167
        // of CHECKSIG+DROP patterns.
1168
        var scriptTemplate string
4✔
1169
        switch {
4✔
1170
        case opt.prodScript:
4✔
1171
                scriptTemplate = `
4✔
1172
                {{ hex .SenderKey }} OP_CHECKSIGVERIFY
4✔
1173
                OP_1 OP_CHECKSEQUENCEVERIFY OP_VERIFY
4✔
1174
                {{ .CltvExpiry }} OP_CHECKLOCKTIMEVERIFY`
4✔
1175
        default:
4✔
1176
                scriptTemplate = `
4✔
1177
                {{ hex .SenderKey }} OP_CHECKSIG
4✔
1178
                OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP
4✔
1179
                {{ .CltvExpiry }} OP_CHECKLOCKTIMEVERIFY OP_DROP`
4✔
1180
        }
1181

1182
        timeoutLeafScript, err := txscript.ScriptTemplate(
4✔
1183
                scriptTemplate,
4✔
1184
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
1185
                        "SenderKey":  schnorr.SerializePubKey(senderHtlcKey),
4✔
1186
                        "CltvExpiry": int64(cltvExpiry),
4✔
1187
                }),
4✔
1188
        )
4✔
1189
        if err != nil {
4✔
1190
                return txscript.TapLeaf{}, err
×
1191
        }
×
1192

1193
        return txscript.NewBaseTapLeaf(timeoutLeafScript), nil
4✔
1194
}
1195

1196
// ReceiverHtlcTapLeafSuccess returns the full tapscript leaf for the success
1197
// path for an HTLC on the receiver's commitment transaction. This script
1198
// allows the receiver to redeem an HTLC with knowledge of the preimage:
1199
//
1200
//        OP_SIZE 32 OP_EQUALVERIFY OP_HASH160
1201
//        <RIPEMD160(payment_hash)> OP_EQUALVERIFY
1202
//        <receiver_htlcpubkey> OP_CHECKSIGVERIFY
1203
//        <sender_htlcpubkey> OP_CHECKSIG
1204
func ReceiverHtlcTapLeafSuccess(receiverHtlcKey *btcec.PublicKey,
1205
        senderHtlcKey *btcec.PublicKey,
1206
        paymentHash []byte,
1207
        _ ...TaprootScriptOpt) (txscript.TapLeaf, error) {
4✔
1208

4✔
1209
        successLeafScript, err := txscript.ScriptTemplate(
4✔
1210
                `
4✔
1211
                OP_SIZE 32 OP_EQUALVERIFY
4✔
1212
                OP_HASH160 {{ hex .PaymentHashRipemd }} OP_EQUALVERIFY
4✔
1213
                {{ hex .ReceiverKey }} OP_CHECKSIGVERIFY
4✔
1214
                {{ hex .SenderKey }} OP_CHECKSIG`,
4✔
1215
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
1216
                        "PaymentHashRipemd": Ripemd160H(paymentHash),
4✔
1217
                        "ReceiverKey": schnorr.SerializePubKey(
4✔
1218
                                receiverHtlcKey,
4✔
1219
                        ),
4✔
1220
                        "SenderKey": schnorr.SerializePubKey(senderHtlcKey),
4✔
1221
                }),
4✔
1222
        )
4✔
1223
        if err != nil {
4✔
1224
                return txscript.TapLeaf{}, err
×
1225
        }
×
1226

1227
        return txscript.NewBaseTapLeaf(successLeafScript), nil
4✔
1228
}
1229

1230
// receiverHtlcTapScriptTree builds the tapscript tree which is used to anchor
1231
// the HTLC key for HTLCs on the receiver's commitment.
1232
func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
1233
        revokeKey *btcec.PublicKey, payHash []byte, cltvExpiry uint32,
1234
        hType htlcType, auxLeaf AuxTapLeaf,
1235
        opts ...TaprootScriptOpt) (*HtlcScriptTree, error) {
4✔
1236

4✔
1237
        // First, we'll obtain the tap leaves for both the success and timeout
4✔
1238
        // path.
4✔
1239
        successTapLeaf, err := ReceiverHtlcTapLeafSuccess(
4✔
1240
                receiverHtlcKey, senderHtlcKey, payHash, opts...,
4✔
1241
        )
4✔
1242
        if err != nil {
4✔
1243
                return nil, err
×
1244
        }
×
1245
        timeoutTapLeaf, err := ReceiverHtlcTapLeafTimeout(
4✔
1246
                senderHtlcKey, cltvExpiry, opts...,
4✔
1247
        )
4✔
1248
        if err != nil {
4✔
1249
                return nil, err
×
1250
        }
×
1251

1252
        tapLeaves := []txscript.TapLeaf{timeoutTapLeaf, successTapLeaf}
4✔
1253
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
4✔
UNCOV
1254
                tapLeaves = append(tapLeaves, l)
×
UNCOV
1255
        })
×
1256

1257
        // With the two leaves obtained, we'll now make the tapscript tree,
1258
        // then obtain the root from that
1259
        tapscriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
4✔
1260

4✔
1261
        tapScriptRoot := tapscriptTree.RootNode.TapHash()
4✔
1262

4✔
1263
        // With the tapscript root obtained, we'll tweak the revocation key
4✔
1264
        // with this value to obtain the key that HTLCs will be sent to.
4✔
1265
        htlcKey := txscript.ComputeTaprootOutputKey(
4✔
1266
                revokeKey, tapScriptRoot[:],
4✔
1267
        )
4✔
1268

4✔
1269
        return &HtlcScriptTree{
4✔
1270
                ScriptTree: ScriptTree{
4✔
1271
                        TaprootKey:    htlcKey,
4✔
1272
                        TapscriptTree: tapscriptTree,
4✔
1273
                        TapscriptRoot: tapScriptRoot[:],
4✔
1274
                        InternalKey:   revokeKey,
4✔
1275
                },
4✔
1276
                SuccessTapLeaf: successTapLeaf,
4✔
1277
                TimeoutTapLeaf: timeoutTapLeaf,
4✔
1278
                AuxLeaf:        auxLeaf,
4✔
1279
                htlcType:       hType,
4✔
1280
        }, nil
4✔
1281
}
1282

1283
// ReceiverHTLCScriptTaproot constructs the taproot witness program (schnor
1284
// key) for an incoming HTLC on the receiver's version of the commitment
1285
// transaction. This method returns the top level tweaked public key that
1286
// commits to both the script paths. From the PoV of the receiver, this is an
1287
// accepted HTLC.
1288
//
1289
// The returned key commits to a tapscript tree with two possible paths:
1290
//
1291
//   - The timeout path:
1292
//     <remote_htlcpubkey> OP_CHECKSIG
1293
//     1 OP_CHECKSEQUENCEVERIFY OP_DROP
1294
//     <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
1295
//
1296
//   - Success path:
1297
//     OP_SIZE 32 OP_EQUALVERIFY
1298
//     OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
1299
//     <local_htlcpubkey> OP_CHECKSIGVERIFY
1300
//     <remote_htlcpubkey> OP_CHECKSIG
1301
//
1302
// The timeout path can be spent with a witness of:
1303
//   - <sender sig> <timeout_script> <control_block>
1304
//
1305
// The success path can be spent with a witness of:
1306
//   - <sender sig> <receiver sig> <preimage> <success_script> <control_block>
1307
//
1308
// The top level keyspend key is the revocation key, which allows a defender to
1309
// unilaterally spend the created output. Both the final output key as well as
1310
// the tap leaf are returned.
1311
func ReceiverHTLCScriptTaproot(cltvExpiry uint32,
1312
        senderHtlcKey, receiverHtlcKey, revocationKey *btcec.PublicKey,
1313
        payHash []byte, whoseCommit lntypes.ChannelParty,
1314
        auxLeaf AuxTapLeaf, opts ...TaprootScriptOpt) (*HtlcScriptTree, error) {
4✔
1315

4✔
1316
        var hType htlcType
4✔
1317
        if whoseCommit.IsLocal() {
8✔
1318
                hType = htlcLocalIncoming
4✔
1319
        } else {
8✔
1320
                hType = htlcRemoteOutgoing
4✔
1321
        }
4✔
1322

1323
        // Given all the necessary parameters, we'll return the HTLC script
1324
        // tree that includes the top level output script, as well as the two
1325
        // tap leaf paths.
1326
        return receiverHtlcTapScriptTree(
4✔
1327
                senderHtlcKey, receiverHtlcKey, revocationKey, payHash,
4✔
1328
                cltvExpiry, hType, auxLeaf, opts...,
4✔
1329
        )
4✔
1330
}
1331

1332
// ReceiverHTLCScriptTaprootRedeem creates a valid witness needed to redeem a
1333
// receiver taproot HTLC with the pre-image. The returned witness is valid and
1334
// includes the control block required to spend the output.
1335
func ReceiverHTLCScriptTaprootRedeem(senderSig Signature,
1336
        senderSigHash txscript.SigHashType, paymentPreimage []byte,
1337
        signer Signer, signDesc *SignDescriptor,
1338
        htlcSuccessTx *wire.MsgTx, revokeKey *btcec.PublicKey,
1339
        tapscriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
1340

4✔
1341
        // First, we'll generate a signature for the HTLC success transaction.
4✔
1342
        // The signDesc should be signing with the public key used as the
4✔
1343
        // receiver's public key and also the correct single tweak.
4✔
1344
        sweepSig, err := signer.SignOutputRaw(htlcSuccessTx, signDesc)
4✔
1345
        if err != nil {
4✔
1346
                return nil, err
×
1347
        }
×
1348

1349
        // In addition to the signature and the witness/leaf script, we also
1350
        // need to make a control block proof using the tapscript tree.
1351
        var ctrlBlock []byte
4✔
1352
        if signDesc.ControlBlock == nil {
8✔
1353
                redeemControlBlock := MakeTaprootCtrlBlock(
4✔
1354
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
4✔
1355
                )
4✔
1356
                ctrlBytes, err := redeemControlBlock.ToBytes()
4✔
1357
                if err != nil {
4✔
1358
                        return nil, err
×
1359
                }
×
1360

1361
                ctrlBlock = ctrlBytes
4✔
1362
        } else {
4✔
1363
                ctrlBlock = signDesc.ControlBlock
4✔
1364
        }
4✔
1365

1366
        // The final witness stack is:
1367
        //  * <sender sig> <receiver sig> <preimage> <success_script>
1368
        //    <control_block>
1369
        witnessStack := wire.TxWitness(make([][]byte, 5))
4✔
1370
        witnessStack[0] = maybeAppendSighash(senderSig, senderSigHash)
4✔
1371
        witnessStack[1] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
1372
        witnessStack[2] = paymentPreimage
4✔
1373
        witnessStack[3] = signDesc.WitnessScript
4✔
1374
        witnessStack[4] = ctrlBlock
4✔
1375

4✔
1376
        return witnessStack, nil
4✔
1377
}
1378

1379
// ReceiverHTLCScriptTaprootTimeout creates a valid witness needed to timeout
1380
// an HTLC on the receiver's commitment transaction after the timeout has
1381
// elapsed.
1382
func ReceiverHTLCScriptTaprootTimeout(signer Signer, signDesc *SignDescriptor,
1383
        sweepTx *wire.MsgTx, cltvExpiry int32, revokeKey *btcec.PublicKey,
1384
        tapscriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
1385

4✔
1386
        // If the caller set a proper timeout value, then we'll apply it
4✔
1387
        // directly to the transaction.
4✔
1388
        //
4✔
1389
        // TODO(roasbeef): helper func
4✔
1390
        if cltvExpiry != -1 {
4✔
UNCOV
1391
                // The HTLC output has an absolute time period before we are
×
UNCOV
1392
                // permitted to recover the pending funds. Therefore we need to
×
UNCOV
1393
                // set the locktime on this sweeping transaction in order to
×
UNCOV
1394
                // pass Script verification.
×
UNCOV
1395
                sweepTx.LockTime = uint32(cltvExpiry)
×
UNCOV
1396
        }
×
1397

1398
        // With the lock time on the transaction set, we'll now generate a
1399
        // signature for the sweep transaction. The passed sign descriptor
1400
        // should be created using the raw public key of the sender (w/o the
1401
        // single tweak applied), and the single tweak set to the proper value
1402
        // taking into account the current state's point.
1403
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
1404
        if err != nil {
4✔
1405
                return nil, err
×
1406
        }
×
1407

1408
        // In addition to the signature and the witness/leaf script, we also
1409
        // need to make a control block proof using the tapscript tree.
1410
        var ctrlBlock []byte
4✔
1411
        if signDesc.ControlBlock == nil {
4✔
UNCOV
1412
                timeoutControlBlock := MakeTaprootCtrlBlock(
×
UNCOV
1413
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
×
UNCOV
1414
                )
×
UNCOV
1415
                ctrlBlock, err = timeoutControlBlock.ToBytes()
×
UNCOV
1416
                if err != nil {
×
1417
                        return nil, err
×
1418
                }
×
1419
        } else {
4✔
1420
                ctrlBlock = signDesc.ControlBlock
4✔
1421
        }
4✔
1422

1423
        // The final witness is pretty simple, we just need to present a valid
1424
        // signature for the script, and then provide the control block.
1425
        witnessStack := make(wire.TxWitness, 3)
4✔
1426
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
1427
        witnessStack[1] = signDesc.WitnessScript
4✔
1428
        witnessStack[2] = ctrlBlock
4✔
1429

4✔
1430
        return witnessStack, nil
4✔
1431
}
1432

1433
// ReceiverHTLCScriptTaprootRevoke creates a valid witness needed to spend the
1434
// revocation path of the HTLC from the PoV of the sender (offerer) of the
1435
// HTLC. This uses a plain keyspend using the specified revocation key.
1436
func ReceiverHTLCScriptTaprootRevoke(signer Signer, signDesc *SignDescriptor,
1437
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
1438

4✔
1439
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
1440
        if err != nil {
4✔
1441
                return nil, err
×
1442
        }
×
1443

1444
        // The witness stack in this case is pretty simple: we only need to
1445
        // specify the signature generated.
1446
        witnessStack := make(wire.TxWitness, 1)
4✔
1447
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
1448

4✔
1449
        return witnessStack, nil
4✔
1450
}
1451

1452
// SecondLevelHtlcScript is the uniform script that's used as the output for
1453
// the second-level HTLC transactions. The second level transaction act as a
1454
// sort of covenant, ensuring that a 2-of-2 multi-sig output can only be
1455
// spent in a particular way, and to a particular output.
1456
//
1457
// Possible Input Scripts:
1458
//
1459
//   - To revoke an HTLC output that has been transitioned to the claim+delay
1460
//     state:
1461
//     <revoke sig> 1
1462
//
1463
//   - To claim and HTLC output, either with a pre-image or due to a timeout:
1464
//     <delay sig> 0
1465
//
1466
// Output Script:
1467
//
1468
//         OP_IF
1469
//                <revoke key>
1470
//         OP_ELSE
1471
//                <delay in blocks>
1472
//                OP_CHECKSEQUENCEVERIFY
1473
//                OP_DROP
1474
//                <delay key>
1475
//         OP_ENDIF
1476
//         OP_CHECKSIG
1477
//
1478
// TODO(roasbeef): possible renames for second-level
1479
//   - transition?
1480
//   - covenant output
1481
func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
1482
        csvDelay uint32) ([]byte, error) {
4✔
1483

4✔
1484
        // In either case, we'll ensure that only either the party possessing
4✔
1485
        // the revocation private key, or the delay private key is able to
4✔
1486
        // spend this output.
4✔
1487
        return txscript.ScriptTemplate(
4✔
1488
                `
4✔
1489
                OP_IF
4✔
1490
                        {{ hex .RevokeKey }}
4✔
1491
                OP_ELSE
4✔
1492
                        {{ .CsvDelay }} OP_CHECKSEQUENCEVERIFY OP_DROP
4✔
1493
                        {{ hex .DelayKey }}
4✔
1494
                OP_ENDIF OP_CHECKSIG`,
4✔
1495
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
1496
                        "RevokeKey": revocationKey.SerializeCompressed(),
4✔
1497
                        "CsvDelay":  int64(csvDelay),
4✔
1498
                        "DelayKey":  delayKey.SerializeCompressed(),
4✔
1499
                }),
4✔
1500
        )
4✔
1501
}
4✔
1502

1503
// TODO(roasbeef): move all taproot stuff to new file?
1504

1505
// TaprootSecondLevelTapLeaf constructs the tap leaf used as the sole script
1506
// path for a second level HTLC spend.
1507
//
1508
// The final script used is:
1509
//
1510
//        <local_delay_key> OP_CHECKSIG
1511
//        <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
1512
func TaprootSecondLevelTapLeaf(delayKey *btcec.PublicKey,
1513
        csvDelay uint32, opts ...TaprootScriptOpt) (txscript.TapLeaf, error) {
4✔
1514

4✔
1515
        opt := defaultTaprootScriptOpt()
4✔
1516
        for _, o := range opts {
8✔
1517
                o(opt)
4✔
1518
        }
4✔
1519

1520
        // Ensure the proper party can sign for this output.
1521
        // Assuming the above passes, then we'll now ensure that the CSV delay
1522
        // has been upheld, dropping the int we pushed on. If the sig above is
1523
        // valid, then a 1 will be left on the stack.
1524
        var scriptTemplate string
4✔
1525
        switch {
4✔
1526
        case opt.prodScript:
4✔
1527
                scriptTemplate = `
4✔
1528
                {{ hex .DelayKey }} OP_CHECKSIGVERIFY
4✔
1529
                {{ .CsvDelay }} OP_CHECKSEQUENCEVERIFY`
4✔
1530
        default:
4✔
1531
                scriptTemplate = `
4✔
1532
                {{ hex .DelayKey }} OP_CHECKSIG
4✔
1533
                {{ .CsvDelay }} OP_CHECKSEQUENCEVERIFY OP_DROP`
4✔
1534
        }
1535

1536
        secondLevelLeafScript, err := txscript.ScriptTemplate(
4✔
1537
                scriptTemplate,
4✔
1538
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
1539
                        "DelayKey": schnorr.SerializePubKey(delayKey),
4✔
1540
                        "CsvDelay": int64(csvDelay),
4✔
1541
                }),
4✔
1542
        )
4✔
1543
        if err != nil {
4✔
1544
                return txscript.TapLeaf{}, err
×
1545
        }
×
1546

1547
        return txscript.NewBaseTapLeaf(secondLevelLeafScript), nil
4✔
1548
}
1549

1550
// SecondLevelHtlcTapscriptTree construct the indexed tapscript tree needed to
1551
// generate the tap tweak to create the final output and also control block.
1552
func SecondLevelHtlcTapscriptTree(delayKey *btcec.PublicKey, csvDelay uint32,
1553
        auxLeaf AuxTapLeaf, opts ...TaprootScriptOpt) (*txscript.IndexedTapScriptTree, error) {
4✔
1554

4✔
1555
        // First grab the second level leaf script we need to create the top
4✔
1556
        // level output.
4✔
1557
        secondLevelTapLeaf, err := TaprootSecondLevelTapLeaf(delayKey, csvDelay, opts...)
4✔
1558
        if err != nil {
4✔
UNCOV
1559
                return nil, err
×
UNCOV
1560
        }
×
1561

1562
        tapLeaves := []txscript.TapLeaf{secondLevelTapLeaf}
4✔
1563
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
4✔
UNCOV
1564
                tapLeaves = append(tapLeaves, l)
×
UNCOV
1565
        })
×
1566

1567
        // Now that we have the sole second level script, we can create the
1568
        // tapscript tree that commits to both the leaves.
1569
        return txscript.AssembleTaprootScriptTree(tapLeaves...), nil
4✔
1570
}
1571

1572
// TaprootSecondLevelHtlcScript is the uniform script that's used as the output
1573
// for the second-level HTLC transaction. The second level transaction acts as
1574
// an off-chain 2-of-2 covenant that can only be spent a particular way and to
1575
// a particular output.
1576
//
1577
// Possible Input Scripts:
1578
//   - revocation sig
1579
//   - <local_delay_sig>
1580
//
1581
// The script main script lets the broadcaster spend after a delay the script
1582
// path:
1583
//
1584
//        <local_delay_key> OP_CHECKSIG
1585
//        <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
1586
//
1587
// The keyspend path require knowledge of the top level revocation private key.
1588
func TaprootSecondLevelHtlcScript(revokeKey, delayKey *btcec.PublicKey,
UNCOV
1589
        csvDelay uint32, auxLeaf AuxTapLeaf, opts ...TaprootScriptOpt) (*btcec.PublicKey, error) {
×
UNCOV
1590

×
UNCOV
1591
        // First, we'll make the tapscript tree that commits to the redemption
×
NEW
1592
        // path.
×
NEW
1593
        tapScriptTree, err := SecondLevelHtlcTapscriptTree(
×
1594
                delayKey, csvDelay, auxLeaf, opts...,
×
1595
        )
×
1596
        if err != nil {
×
1597
                return nil, err
×
NEW
1598
        }
×
1599

1600
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
×
1601

×
1602
        // With the tapscript root obtained, we'll tweak the revocation key
×
UNCOV
1603
        // with this value to obtain the key that the second level spend will
×
1604
        // create.
×
1605
        redemptionKey := txscript.ComputeTaprootOutputKey(
×
1606
                revokeKey, tapScriptRoot[:],
×
1607
        )
×
1608

×
1609
        return redemptionKey, nil
×
1610
}
1611

1612
// SecondLevelScriptTree is a tapscript tree used to spend the second level
1613
// HTLC output after the CSV delay has passed.
1614
type SecondLevelScriptTree struct {
1615
        ScriptTree
1616

1617
        // SuccessTapLeaf is the tapleaf for the redemption path.
1618
        SuccessTapLeaf txscript.TapLeaf
1619

1620
        // AuxLeaf is an optional leaf that can be used to extend the script
1621
        // tree.
1622
        AuxLeaf AuxTapLeaf
1623
}
1624

1625
// TaprootSecondLevelScriptTree constructs the tapscript tree used to spend the
1626
// second level HTLC output.
1627
func TaprootSecondLevelScriptTree(revokeKey, delayKey *btcec.PublicKey,
1628
        csvDelay uint32, auxLeaf AuxTapLeaf, opts ...TaprootScriptOpt) (*SecondLevelScriptTree, error) {
4✔
1629

4✔
1630
        // First, we'll make the tapscript tree that commits to the redemption
4✔
1631
        // path.
4✔
1632
        tapScriptTree, err := SecondLevelHtlcTapscriptTree(
4✔
1633
                delayKey, csvDelay, auxLeaf, opts...,
4✔
1634
        )
4✔
1635
        if err != nil {
4✔
UNCOV
1636
                return nil, err
×
UNCOV
1637
        }
×
1638

1639
        // With the tree constructed, we can make the pkscript which is the
1640
        // taproot output key itself.
1641
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
4✔
1642
        outputKey := txscript.ComputeTaprootOutputKey(
4✔
1643
                revokeKey, tapScriptRoot[:],
4✔
1644
        )
4✔
1645

4✔
1646
        return &SecondLevelScriptTree{
4✔
1647
                ScriptTree: ScriptTree{
4✔
1648
                        TaprootKey:    outputKey,
4✔
1649
                        TapscriptTree: tapScriptTree,
4✔
1650
                        TapscriptRoot: tapScriptRoot[:],
4✔
1651
                        InternalKey:   revokeKey,
4✔
1652
                },
4✔
1653
                SuccessTapLeaf: tapScriptTree.LeafMerkleProofs[0].TapLeaf,
4✔
1654
                AuxLeaf:        auxLeaf,
4✔
1655
        }, nil
4✔
1656
}
1657

1658
// WitnessScriptToSign returns the witness script that we'll use when signing
1659
// for the remote party, and also verifying signatures on our transactions. As
1660
// an example, when we create an outgoing HTLC for the remote party, we want to
1661
// sign their success path.
UNCOV
1662
func (s *SecondLevelScriptTree) WitnessScriptToSign() []byte {
×
UNCOV
1663
        return s.SuccessTapLeaf.Script
×
UNCOV
1664
}
×
1665

1666
// WitnessScriptForPath returns the witness script for the given spending path.
1667
// An error is returned if the path is unknown.
1668
func (s *SecondLevelScriptTree) WitnessScriptForPath(
1669
        path ScriptPath) ([]byte, error) {
4✔
1670

4✔
1671
        switch path {
4✔
UNCOV
1672
        case ScriptPathDelay:
×
UNCOV
1673
                fallthrough
×
1674
        case ScriptPathSuccess:
4✔
1675
                return s.SuccessTapLeaf.Script, nil
4✔
1676

1677
        default:
×
1678
                return nil, fmt.Errorf("unknown script path: %v", path)
×
1679
        }
1680
}
1681

1682
// CtrlBlockForPath returns the control block for the given spending path. For
1683
// script types that don't have a control block, nil is returned.
1684
func (s *SecondLevelScriptTree) CtrlBlockForPath(
1685
        path ScriptPath) (*txscript.ControlBlock, error) {
4✔
1686

4✔
1687
        switch path {
4✔
UNCOV
1688
        case ScriptPathDelay:
×
UNCOV
1689
                fallthrough
×
1690
        case ScriptPathSuccess:
4✔
1691
                return lnutils.Ptr(MakeTaprootCtrlBlock(
4✔
1692
                        s.SuccessTapLeaf.Script, s.InternalKey,
4✔
1693
                        s.TapscriptTree,
4✔
1694
                )), nil
4✔
1695

UNCOV
1696
        default:
×
UNCOV
1697
                return nil, fmt.Errorf("unknown script path: %v", path)
×
1698
        }
1699
}
1700

1701
// Tree returns the underlying ScriptTree of the SecondLevelScriptTree.
1702
func (s *SecondLevelScriptTree) Tree() ScriptTree {
×
UNCOV
1703
        return s.ScriptTree
×
UNCOV
1704
}
×
1705

1706
// A compile time check to ensure SecondLevelScriptTree implements the
1707
// TapscriptDescriptor interface.
1708
var _ TapscriptDescriptor = (*SecondLevelScriptTree)(nil)
1709

1710
// TaprootHtlcSpendRevoke spends a second-level HTLC output via the revocation
1711
// path. This uses the top level keyspend path to redeem the contested output.
1712
//
1713
// The passed SignDescriptor MUST have the proper witness script and also the
1714
// proper top-level tweak derived from the tapscript tree for the second level
1715
// output.
1716
func TaprootHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
UNCOV
1717
        revokeTx *wire.MsgTx) (wire.TxWitness, error) {
×
UNCOV
1718

×
UNCOV
1719
        // We don't need any spacial modifications to the transaction as this
×
UNCOV
1720
        // is just sweeping a revoked HTLC output. So we'll generate a regular
×
UNCOV
1721
        // schnorr signature.
×
UNCOV
1722
        sweepSig, err := signer.SignOutputRaw(revokeTx, signDesc)
×
UNCOV
1723
        if err != nil {
×
UNCOV
1724
                return nil, err
×
UNCOV
1725
        }
×
1726

1727
        // The witness stack in this case is pretty simple: we only need to
1728
        // specify the signature generated.
1729
        witnessStack := make(wire.TxWitness, 1)
×
1730
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
×
UNCOV
1731

×
UNCOV
1732
        return witnessStack, nil
×
1733
}
1734

1735
// TaprootHtlcSpendSuccess spends a second-level HTLC output via the redemption
1736
// path. This should be used to sweep funds after the pre-image is known.
1737
//
1738
// NOTE: The caller MUST set the txn version, sequence number, and sign
1739
// descriptor's sig hash cache before invocation.
1740
func TaprootHtlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
1741
        sweepTx *wire.MsgTx, revokeKey *btcec.PublicKey,
1742
        tapscriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
1743

4✔
1744
        // First, we'll generate the sweep signature based on the populated
4✔
1745
        // sign desc. This should give us a valid schnorr signature for the
4✔
1746
        // sole script path leaf.
4✔
1747
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
1748
        if err != nil {
4✔
UNCOV
1749
                return nil, err
×
UNCOV
1750
        }
×
1751

1752
        var ctrlBlock []byte
4✔
1753
        if signDesc.ControlBlock == nil {
4✔
1754
                // Now that we have the sweep signature, we'll construct the
×
1755
                // control block needed to spend the script path.
×
UNCOV
1756
                redeemControlBlock := MakeTaprootCtrlBlock(
×
UNCOV
1757
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
×
UNCOV
1758
                )
×
UNCOV
1759

×
UNCOV
1760
                ctrlBlock, err = redeemControlBlock.ToBytes()
×
UNCOV
1761
                if err != nil {
×
UNCOV
1762
                        return nil, err
×
UNCOV
1763
                }
×
1764
        } else {
4✔
1765
                ctrlBlock = signDesc.ControlBlock
4✔
1766
        }
4✔
1767

1768
        // Now that we have the redeem control block, we can construct the
1769
        // final witness needed to spend the script:
1770
        //
1771
        //  <success sig> <success script> <control_block>
1772
        witnessStack := make(wire.TxWitness, 3)
4✔
1773
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
1774
        witnessStack[1] = signDesc.WitnessScript
4✔
1775
        witnessStack[2] = ctrlBlock
4✔
1776

4✔
1777
        return witnessStack, nil
4✔
1778
}
1779

1780
// LeaseSecondLevelHtlcScript is the uniform script that's used as the output
1781
// for the second-level HTLC transactions. The second level transaction acts as
1782
// a sort of covenant, ensuring that a 2-of-2 multi-sig output can only be
1783
// spent in a particular way, and to a particular output.
1784
//
1785
// Possible Input Scripts:
1786
//
1787
//   - To revoke an HTLC output that has been transitioned to the claim+delay
1788
//     state:
1789
//     <revoke sig> 1
1790
//
1791
//   - To claim an HTLC output, either with a pre-image or due to a timeout:
1792
//     <delay sig> 0
1793
//
1794
// Output Script:
1795
//
1796
//         OP_IF
1797
//                <revoke key>
1798
//         OP_ELSE
1799
//                <lease maturity in blocks>
1800
//                OP_CHECKLOCKTIMEVERIFY
1801
//                OP_DROP
1802
//                <delay in blocks>
1803
//                OP_CHECKSEQUENCEVERIFY
1804
//                OP_DROP
1805
//                <delay key>
1806
//         OP_ENDIF
1807
//         OP_CHECKSIG.
1808
func LeaseSecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
1809
        csvDelay, cltvExpiry uint32) ([]byte, error) {
4✔
1810

4✔
1811
        // Build a script template with conditional paths for revocation and
4✔
1812
        // normal spending If this is the revocation clause, the spender will
4✔
1813
        // push a 1, forcing the first path Otherwise, this is either the sender
4✔
1814
        // or receiver of the HTLC attempting to claim
4✔
1815
        return txscript.ScriptTemplate(
4✔
1816
                `
4✔
1817
                OP_IF
4✔
1818
                        {{ hex .RevokeKey }}
4✔
1819
                OP_ELSE
4✔
1820
                        {{ .CltvExpiry }} OP_CHECKLOCKTIMEVERIFY OP_DROP
4✔
1821
                        {{ .CsvDelay }} OP_CHECKSEQUENCEVERIFY OP_DROP
4✔
1822
                        {{ hex .DelayKey }}
4✔
1823
                OP_ENDIF OP_CHECKSIG`,
4✔
1824
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
1825
                        "RevokeKey":  revocationKey.SerializeCompressed(),
4✔
1826
                        "CltvExpiry": int64(cltvExpiry),
4✔
1827
                        "CsvDelay":   int64(csvDelay),
4✔
1828
                        "DelayKey":   delayKey.SerializeCompressed(),
4✔
1829
                }),
4✔
1830
        )
4✔
1831
}
4✔
1832

1833
// HtlcSpendSuccess spends a second-level HTLC output. This function is to be
1834
// used by the sender of an HTLC to claim the output after a relative timeout
1835
// or the receiver of the HTLC to claim on-chain with the pre-image.
1836
func HtlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
UNCOV
1837
        sweepTx *wire.MsgTx, csvDelay uint32) (wire.TxWitness, error) {
×
UNCOV
1838

×
UNCOV
1839
        // We're required to wait a relative period of time before we can sweep
×
UNCOV
1840
        // the output in order to allow the other party to contest our claim of
×
UNCOV
1841
        // validity to this version of the commitment transaction.
×
UNCOV
1842
        sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, csvDelay)
×
UNCOV
1843

×
UNCOV
1844
        // Finally, OP_CSV requires that the version of the transaction
×
UNCOV
1845
        // spending a pkscript with OP_CSV within it *must* be >= 2.
×
UNCOV
1846
        sweepTx.Version = 2
×
UNCOV
1847

×
UNCOV
1848
        // As we mutated the transaction, we'll re-calculate the sighashes for
×
UNCOV
1849
        // this instance.
×
UNCOV
1850
        signDesc.SigHashes = NewTxSigHashesV0Only(sweepTx)
×
UNCOV
1851

×
UNCOV
1852
        // With the proper sequence and version set, we'll now sign the timeout
×
UNCOV
1853
        // transaction using the passed signed descriptor. In order to generate
×
UNCOV
1854
        // a valid signature, then signDesc should be using the base delay
×
UNCOV
1855
        // public key, and the proper single tweak bytes.
×
UNCOV
1856
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
×
UNCOV
1857
        if err != nil {
×
UNCOV
1858
                return nil, err
×
UNCOV
1859
        }
×
1860

1861
        // We set a zero as the first element the witness stack (ignoring the
1862
        // witness script), in order to force execution to the second portion
1863
        // of the if clause.
1864
        witnessStack := wire.TxWitness(make([][]byte, 3))
×
UNCOV
1865
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
×
UNCOV
1866
        witnessStack[1] = nil
×
UNCOV
1867
        witnessStack[2] = signDesc.WitnessScript
×
UNCOV
1868

×
UNCOV
1869
        return witnessStack, nil
×
1870
}
1871

1872
// HtlcSpendRevoke spends a second-level HTLC output. This function is to be
1873
// used by the sender or receiver of an HTLC to claim the HTLC after a revoked
1874
// commitment transaction was broadcast.
1875
func HtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
UNCOV
1876
        revokeTx *wire.MsgTx) (wire.TxWitness, error) {
×
UNCOV
1877

×
UNCOV
1878
        // We don't need any spacial modifications to the transaction as this
×
UNCOV
1879
        // is just sweeping a revoked HTLC output. So we'll generate a regular
×
UNCOV
1880
        // witness signature.
×
UNCOV
1881
        sweepSig, err := signer.SignOutputRaw(revokeTx, signDesc)
×
UNCOV
1882
        if err != nil {
×
UNCOV
1883
                return nil, err
×
UNCOV
1884
        }
×
1885

1886
        // We set a one as the first element the witness stack (ignoring the
1887
        // witness script), in order to force execution to the revocation
1888
        // clause in the second level HTLC script.
1889
        witnessStack := wire.TxWitness(make([][]byte, 3))
×
UNCOV
1890
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
×
UNCOV
1891
        witnessStack[1] = []byte{1}
×
UNCOV
1892
        witnessStack[2] = signDesc.WitnessScript
×
UNCOV
1893

×
UNCOV
1894
        return witnessStack, nil
×
1895
}
1896

1897
// HtlcSecondLevelSpend exposes the public witness generation function for
1898
// spending an HTLC success transaction, either due to an expiring time lock or
1899
// having had the payment preimage. This method is able to spend any
1900
// second-level HTLC transaction, assuming the caller sets the locktime or
1901
// seqno properly.
1902
//
1903
// NOTE: The caller MUST set the txn version, sequence number, and sign
1904
// descriptor's sig hash cache before invocation.
1905
func HtlcSecondLevelSpend(signer Signer, signDesc *SignDescriptor,
1906
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
1907

4✔
1908
        // With the proper sequence and version set, we'll now sign the timeout
4✔
1909
        // transaction using the passed signed descriptor. In order to generate
4✔
1910
        // a valid signature, then signDesc should be using the base delay
4✔
1911
        // public key, and the proper single tweak bytes.
4✔
1912
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
1913
        if err != nil {
4✔
UNCOV
1914
                return nil, err
×
UNCOV
1915
        }
×
1916

1917
        // We set a zero as the first element the witness stack (ignoring the
1918
        // witness script), in order to force execution to the second portion
1919
        // of the if clause.
1920
        witnessStack := wire.TxWitness(make([][]byte, 3))
4✔
1921
        witnessStack[0] = append(sweepSig.Serialize(), byte(txscript.SigHashAll))
4✔
1922
        witnessStack[1] = nil
4✔
1923
        witnessStack[2] = signDesc.WitnessScript
4✔
1924

4✔
1925
        return witnessStack, nil
4✔
1926
}
1927

1928
// LockTimeToSequence converts the passed relative locktime to a sequence
1929
// number in accordance to BIP-68.
1930
// See: https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
1931
//   - (Compatibility)
UNCOV
1932
func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 {
×
UNCOV
1933
        if !isSeconds {
×
UNCOV
1934
                // The locktime is to be expressed in confirmations.
×
UNCOV
1935
                return locktime
×
UNCOV
1936
        }
×
1937

1938
        // Set the 22nd bit which indicates the lock time is in seconds, then
1939
        // shift the locktime over by 9 since the time granularity is in
1940
        // 512-second intervals (2^9). This results in a max lock-time of
1941
        // 33,554,431 seconds, or 1.06 years.
UNCOV
1942
        return SequenceLockTimeSeconds | (locktime >> 9)
×
1943
}
1944

1945
// CommitScriptToSelf constructs the public key script for the output on the
1946
// commitment transaction paying to the "owner" of said commitment transaction.
1947
// If the other party obtains the revocation private key for this commitment,
1948
// then they can claim all the settled funds in the channel, plus the unsettled
1949
// funds.
1950
//
1951
// Possible Input Scripts:
1952
//
1953
//        REVOKE:     <sig> 1
1954
//        SENDRSWEEP: <sig> <emptyvector>
1955
//
1956
// Output Script:
1957
//
1958
//        OP_IF
1959
//            <revokeKey>
1960
//        OP_ELSE
1961
//            <numRelativeBlocks> OP_CHECKSEQUENCEVERIFY OP_DROP
1962
//            <selfKey>
1963
//        OP_ENDIF
1964
//        OP_CHECKSIG
1965
func CommitScriptToSelf(csvTimeout uint32, selfKey, revokeKey *btcec.PublicKey) ([]byte, error) {
4✔
1966
        // This script is spendable under two conditions: either the
4✔
1967
        // 'csvTimeout' has passed and we can redeem our funds, or they can
4✔
1968
        // produce a valid signature with the revocation public key. The
4✔
1969
        // revocation public key will *only* be known to the other party if we
4✔
1970
        // have divulged the revocation hash, allowing them to homomorphically
4✔
1971
        // derive the proper private key which corresponds to the revoke public
4✔
1972
        // key.
4✔
1973
        return txscript.ScriptTemplate(
4✔
1974
                `
4✔
1975
                OP_IF
4✔
1976
                        {{ hex .RevokeKey }}
4✔
1977
                OP_ELSE
4✔
1978
                        {{ .CsvTimeout }} OP_CHECKSEQUENCEVERIFY OP_DROP
4✔
1979
                        {{ hex .SelfKey }}
4✔
1980
                OP_ENDIF
4✔
1981
                OP_CHECKSIG`,
4✔
1982
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
1983
                        "RevokeKey":  revokeKey.SerializeCompressed(),
4✔
1984
                        "CsvTimeout": int64(csvTimeout),
4✔
1985
                        "SelfKey":    selfKey.SerializeCompressed(),
4✔
1986
                }),
4✔
1987
        )
4✔
1988
}
4✔
1989

1990
// CommitScriptTree holds the taproot output key (in this case the revocation
1991
// key, or a NUMs point for the remote output) along with the tapscript leaf
1992
// that can spend the output after a delay.
1993
type CommitScriptTree struct {
1994
        ScriptTree
1995

1996
        // SettleLeaf is the leaf used to settle the output after the delay.
1997
        SettleLeaf txscript.TapLeaf
1998

1999
        // RevocationLeaf is the leaf used to spend the output with the
2000
        // revocation key signature.
2001
        RevocationLeaf txscript.TapLeaf
2002

2003
        // AuxLeaf is an auxiliary leaf that can be used to extend the base
2004
        // commitment script tree with new spend paths, or just as extra
2005
        // commitment space. When present, this leaf will always be in the
2006
        // left-most or right-most area of the tapscript tree.
2007
        AuxLeaf AuxTapLeaf
2008
}
2009

2010
// A compile time check to ensure CommitScriptTree implements the
2011
// TapscriptDescriptor interface.
2012
var _ TapscriptDescriptor = (*CommitScriptTree)(nil)
2013

2014
// WitnessScriptToSign returns the witness script that we'll use when signing
2015
// for the remote party, and also verifying signatures on our transactions. As
2016
// an example, when we create an outgoing HTLC for the remote party, we want to
2017
// sign their success path.
UNCOV
2018
func (c *CommitScriptTree) WitnessScriptToSign() []byte {
×
UNCOV
2019
        // TODO(roasbeef): abstraction leak here? always dependent
×
UNCOV
2020
        return nil
×
UNCOV
2021
}
×
2022

2023
// WitnessScriptForPath returns the witness script for the given spending path.
2024
// An error is returned if the path is unknown.
2025
func (c *CommitScriptTree) WitnessScriptForPath(
2026
        path ScriptPath) ([]byte, error) {
4✔
2027

4✔
2028
        switch path {
4✔
2029
        // For the commitment output, the delay and success path are the same,
2030
        // so we'll fall through here to success.
2031
        case ScriptPathDelay:
4✔
2032
                fallthrough
4✔
2033
        case ScriptPathSuccess:
4✔
2034
                return c.SettleLeaf.Script, nil
4✔
2035
        case ScriptPathRevocation:
4✔
2036
                return c.RevocationLeaf.Script, nil
4✔
UNCOV
2037
        default:
×
UNCOV
2038
                return nil, fmt.Errorf("unknown script path: %v", path)
×
2039
        }
2040
}
2041

2042
// CtrlBlockForPath returns the control block for the given spending path. For
2043
// script types that don't have a control block, nil is returned.
2044
func (c *CommitScriptTree) CtrlBlockForPath(
2045
        path ScriptPath) (*txscript.ControlBlock, error) {
4✔
2046

4✔
2047
        switch path {
4✔
2048
        case ScriptPathDelay:
4✔
2049
                fallthrough
4✔
2050
        case ScriptPathSuccess:
4✔
2051
                return lnutils.Ptr(MakeTaprootCtrlBlock(
4✔
2052
                        c.SettleLeaf.Script, c.InternalKey,
4✔
2053
                        c.TapscriptTree,
4✔
2054
                )), nil
4✔
2055
        case ScriptPathRevocation:
4✔
2056
                return lnutils.Ptr(MakeTaprootCtrlBlock(
4✔
2057
                        c.RevocationLeaf.Script, c.InternalKey,
4✔
2058
                        c.TapscriptTree,
4✔
2059
                )), nil
4✔
UNCOV
2060
        default:
×
UNCOV
2061
                return nil, fmt.Errorf("unknown script path: %v", path)
×
2062
        }
2063
}
2064

2065
// Tree returns the underlying ScriptTree of the CommitScriptTree.
2066
func (c *CommitScriptTree) Tree() ScriptTree {
×
UNCOV
2067
        return c.ScriptTree
×
UNCOV
2068
}
×
2069

2070
// taprootScriptOpts is a set of options that modify the behavior of the way we
2071
// create taproot scripts.
2072
type taprootScriptOpts struct {
2073
        prodScript bool
2074
}
2075

2076
// TaprootScriptOpt is a functional option that allows us to modify the behavior
2077
// of the taproot script creation.
2078
type TaprootScriptOpt func(*taprootScriptOpts)
2079

2080
// defaultTaprootScriptOpt is the default set of options that we use when
2081
// creating taproot scripts.
2082
func defaultTaprootScriptOpt() *taprootScriptOpts {
4✔
2083
        return &taprootScriptOpts{
4✔
2084
                prodScript: false,
4✔
2085
        }
4✔
2086
}
4✔
2087

2088
// WithProdScripts is a functional option that allows us to create scripts to
2089
// match the final version of the taproot channels.
2090
func WithProdScripts() func(*taprootScriptOpts) {
4✔
2091
        return func(o *taprootScriptOpts) {
8✔
2092
                o.prodScript = true
4✔
2093
        }
4✔
2094
}
2095

2096
// NewLocalCommitScriptTree returns a new CommitScript tree that can be used to
2097
// create and spend the commitment output for the local party.
2098
func NewLocalCommitScriptTree(csvTimeout uint32, selfKey,
2099
        revokeKey *btcec.PublicKey, auxLeaf AuxTapLeaf,
2100
        opts ...TaprootScriptOpt) (*CommitScriptTree, error) {
4✔
2101

4✔
2102
        // First, we'll need to construct the tapLeaf that'll be our delay CSV
4✔
2103
        // clause.
4✔
2104
        delayScript, err := TaprootLocalCommitDelayScript(
4✔
2105
                csvTimeout, selfKey, opts...,
4✔
2106
        )
4✔
2107
        if err != nil {
4✔
UNCOV
2108
                return nil, err
×
UNCOV
2109
        }
×
2110

2111
        // Next, we'll need to construct the revocation path, which is just a
2112
        // simple checksig script.
2113
        revokeScript, err := TaprootLocalCommitRevokeScript(
4✔
2114
                selfKey, revokeKey, opts...,
4✔
2115
        )
4✔
2116
        if err != nil {
4✔
UNCOV
2117
                return nil, err
×
UNCOV
2118
        }
×
2119

2120
        // With both scripts computed, we'll now create a tapscript tree with
2121
        // the two leaves, and then obtain a root from that.
2122
        delayTapLeaf := txscript.NewBaseTapLeaf(delayScript)
4✔
2123
        revokeTapLeaf := txscript.NewBaseTapLeaf(revokeScript)
4✔
2124

4✔
2125
        tapLeaves := []txscript.TapLeaf{delayTapLeaf, revokeTapLeaf}
4✔
2126
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
4✔
UNCOV
2127
                tapLeaves = append(tapLeaves, l)
×
UNCOV
2128
        })
×
2129

2130
        tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
4✔
2131
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
4✔
2132

4✔
2133
        // Now that we have our root, we can arrive at the final output script
4✔
2134
        // by tweaking the internal key with this root.
4✔
2135
        toLocalOutputKey := txscript.ComputeTaprootOutputKey(
4✔
2136
                &TaprootNUMSKey, tapScriptRoot[:],
4✔
2137
        )
4✔
2138

4✔
2139
        return &CommitScriptTree{
4✔
2140
                ScriptTree: ScriptTree{
4✔
2141
                        TaprootKey:    toLocalOutputKey,
4✔
2142
                        TapscriptTree: tapScriptTree,
4✔
2143
                        TapscriptRoot: tapScriptRoot[:],
4✔
2144
                        InternalKey:   &TaprootNUMSKey,
4✔
2145
                },
4✔
2146
                SettleLeaf:     delayTapLeaf,
4✔
2147
                RevocationLeaf: revokeTapLeaf,
4✔
2148
                AuxLeaf:        auxLeaf,
4✔
2149
        }, nil
4✔
2150
}
2151

2152
// TaprootLocalCommitDelayScript builds the tap leaf with the CSV delay script
2153
// for the to-local output.
2154
func TaprootLocalCommitDelayScript(csvTimeout uint32,
2155
        selfKey *btcec.PublicKey, opts ...TaprootScriptOpt) ([]byte, error) {
4✔
2156

4✔
2157
        opt := defaultTaprootScriptOpt()
4✔
2158
        for _, o := range opts {
8✔
2159
                o(opt)
4✔
2160
        }
4✔
2161

2162
        var scriptTemplate string
4✔
2163
        switch {
4✔
2164
        case opt.prodScript:
4✔
2165
                scriptTemplate = `
4✔
2166
                {{ hex .SelfKey }} OP_CHECKSIGVERIFY
4✔
2167
                {{ .CsvTimeout }} OP_CHECKSEQUENCEVERIFY`
4✔
2168
        default:
4✔
2169
                scriptTemplate = `
4✔
2170
                {{ hex .SelfKey }} OP_CHECKSIG
4✔
2171
                {{ .CsvTimeout }} OP_CHECKSEQUENCEVERIFY OP_DROP`
4✔
2172
        }
2173

2174
        return txscript.ScriptTemplate(
4✔
2175
                scriptTemplate,
4✔
2176
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2177
                        "SelfKey":    schnorr.SerializePubKey(selfKey),
4✔
2178
                        "CsvTimeout": int64(csvTimeout),
4✔
2179
                }),
4✔
2180
        )
4✔
2181
}
2182

2183
// TaprootLocalCommitRevokeScript builds the tap leaf with the revocation path
2184
// for the to-local output.
2185
func TaprootLocalCommitRevokeScript(selfKey, revokeKey *btcec.PublicKey,
2186
        _ ...TaprootScriptOpt) ([]byte, error) {
4✔
2187

4✔
2188
        return txscript.ScriptTemplate(
4✔
2189
                `
4✔
2190
                {{ hex .SelfKey }} OP_DROP 
4✔
2191
                {{ hex .RevokeKey }} OP_CHECKSIG`,
4✔
2192
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2193
                        "SelfKey":   schnorr.SerializePubKey(selfKey),
4✔
2194
                        "RevokeKey": schnorr.SerializePubKey(revokeKey),
4✔
2195
                }),
4✔
2196
        )
4✔
2197
}
4✔
2198

2199
// TaprootCommitScriptToSelf creates the taproot witness program that commits
2200
// to the revocation (script path) and delay path (script path) in a single
2201
// taproot output key. Both the delay script and the revocation script are part
2202
// of the tapscript tree to ensure that the internal key (the local delay key)
2203
// is always revealed.  This ensures that a 3rd party can always sweep the set
2204
// of anchor outputs.
2205
//
2206
// For the delay path we have the following tapscript leaf script:
2207
//
2208
//        <local_delayedpubkey> OP_CHECKSIG
2209
//        <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
2210
//
2211
// This can then be spent with just:
2212
//
2213
//        <local_delayedsig> <to_delay_script> <delay_control_block>
2214
//
2215
// Where the to_delay_script is listed above, and the delay_control_block
2216
// computed as:
2217
//
2218
//        delay_control_block = (output_key_y_parity | 0xc0) || taproot_nums_key
2219
//
2220
// The revocation path is simply:
2221
//
2222
//        <local_delayedpubkey> OP_DROP
2223
//        <revocationkey> OP_CHECKSIG
2224
//
2225
// The revocation path can be spent with a control block similar to the above
2226
// (but contains the hash of the other script), and with the following witness:
2227
//
2228
//        <revocation_sig>
2229
//
2230
// We use a noop data push to ensure that the local public key is also revealed
2231
// on chain, which enables the anchor output to be swept.
2232
func TaprootCommitScriptToSelf(csvTimeout uint32,
UNCOV
2233
        selfKey, revokeKey *btcec.PublicKey) (*btcec.PublicKey, error) {
×
UNCOV
2234

×
UNCOV
2235
        commitScriptTree, err := NewLocalCommitScriptTree(
×
UNCOV
2236
                csvTimeout, selfKey, revokeKey, NoneTapLeaf(),
×
UNCOV
2237
        )
×
2238
        if err != nil {
×
2239
                return nil, err
×
2240
        }
×
2241

2242
        return commitScriptTree.TaprootKey, nil
×
2243
}
2244

2245
// MakeTaprootCtrlBlock takes a leaf script, the internal key (usually the
2246
// revoke key), and a script tree and creates a valid control block for a spend
2247
// of the leaf.
2248
func MakeTaprootCtrlBlock(leafScript []byte, internalKey *btcec.PublicKey,
2249
        scriptTree *txscript.IndexedTapScriptTree) txscript.ControlBlock {
4✔
2250

4✔
2251
        tapLeafHash := txscript.NewBaseTapLeaf(leafScript).TapHash()
4✔
2252
        scriptIdx := scriptTree.LeafProofIndex[tapLeafHash]
4✔
2253
        settleMerkleProof := scriptTree.LeafMerkleProofs[scriptIdx]
4✔
2254

4✔
2255
        return settleMerkleProof.ToControlBlock(internalKey)
4✔
2256
}
4✔
2257

2258
// TaprootCommitSpendSuccess constructs a valid witness allowing a node to
2259
// sweep the settled taproot output after the delay has passed for a force
2260
// close.
2261
func TaprootCommitSpendSuccess(signer Signer, signDesc *SignDescriptor,
2262
        sweepTx *wire.MsgTx,
2263
        scriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
2264

4✔
2265
        // First, we'll need to construct a valid control block to execute the
4✔
2266
        // leaf script for sweep settlement.
4✔
2267
        //
4✔
2268
        // TODO(roasbeef); make into closure instead? only need reovke key and
4✔
2269
        // scriptTree to make the ctrl block -- then default version that would
4✔
2270
        // take froms ign desc?
4✔
2271
        var ctrlBlockBytes []byte
4✔
2272
        if signDesc.ControlBlock == nil {
4✔
UNCOV
2273
                settleControlBlock := MakeTaprootCtrlBlock(
×
UNCOV
2274
                        signDesc.WitnessScript, &TaprootNUMSKey, scriptTree,
×
UNCOV
2275
                )
×
UNCOV
2276
                ctrlBytes, err := settleControlBlock.ToBytes()
×
UNCOV
2277
                if err != nil {
×
UNCOV
2278
                        return nil, err
×
UNCOV
2279
                }
×
2280

UNCOV
2281
                ctrlBlockBytes = ctrlBytes
×
2282
        } else {
4✔
2283
                ctrlBlockBytes = signDesc.ControlBlock
4✔
2284
        }
4✔
2285

2286
        // With the control block created, we'll now generate the signature we
2287
        // need to authorize the spend.
2288
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2289
        if err != nil {
4✔
UNCOV
2290
                return nil, err
×
UNCOV
2291
        }
×
2292

2293
        // The final witness stack will be:
2294
        //
2295
        //  <sweep sig> <sweep script> <control block>
2296
        witnessStack := make(wire.TxWitness, 3)
4✔
2297
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
2298
        witnessStack[1] = signDesc.WitnessScript
4✔
2299
        witnessStack[2] = ctrlBlockBytes
4✔
2300

4✔
2301
        return witnessStack, nil
4✔
2302
}
2303

2304
// TaprootCommitSpendRevoke constructs a valid witness allowing a node to sweep
2305
// the revoked taproot output of a malicious peer.
2306
func TaprootCommitSpendRevoke(signer Signer, signDesc *SignDescriptor,
2307
        revokeTx *wire.MsgTx,
2308
        scriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
2309

4✔
2310
        // First, we'll need to construct a valid control block to execute the
4✔
2311
        // leaf script for revocation path.
4✔
2312
        var ctrlBlockBytes []byte
4✔
2313
        if signDesc.ControlBlock == nil {
4✔
UNCOV
2314
                revokeCtrlBlock := MakeTaprootCtrlBlock(
×
UNCOV
2315
                        signDesc.WitnessScript, &TaprootNUMSKey, scriptTree,
×
UNCOV
2316
                )
×
UNCOV
2317
                revokeBytes, err := revokeCtrlBlock.ToBytes()
×
UNCOV
2318
                if err != nil {
×
UNCOV
2319
                        return nil, err
×
UNCOV
2320
                }
×
2321

UNCOV
2322
                ctrlBlockBytes = revokeBytes
×
2323
        } else {
4✔
2324
                ctrlBlockBytes = signDesc.ControlBlock
4✔
2325
        }
4✔
2326

2327
        // With the control block created, we'll now generate the signature we
2328
        // need to authorize the spend.
2329
        revokeSig, err := signer.SignOutputRaw(revokeTx, signDesc)
4✔
2330
        if err != nil {
4✔
UNCOV
2331
                return nil, err
×
UNCOV
2332
        }
×
2333

2334
        // The final witness stack will be:
2335
        //
2336
        //  <revoke sig sig> <revoke script> <control block>
2337
        witnessStack := make(wire.TxWitness, 3)
4✔
2338
        witnessStack[0] = maybeAppendSighash(revokeSig, signDesc.HashType)
4✔
2339
        witnessStack[1] = signDesc.WitnessScript
4✔
2340
        witnessStack[2] = ctrlBlockBytes
4✔
2341

4✔
2342
        return witnessStack, nil
4✔
2343
}
2344

2345
// LeaseCommitScriptToSelf constructs the public key script for the output on the
2346
// commitment transaction paying to the "owner" of said commitment transaction.
2347
// If the other party obtains the revocation private key for this commitment,
2348
// then they can claim all the settled funds in the channel, plus the unsettled
2349
// funds.
2350
//
2351
// Possible Input Scripts:
2352
//
2353
//        REVOKE:     <sig> 1
2354
//        SENDRSWEEP: <sig> <emptyvector>
2355
//
2356
// Output Script:
2357
//
2358
//        OP_IF
2359
//            <revokeKey>
2360
//        OP_ELSE
2361
//            <absoluteLeaseExpiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
2362
//            <numRelativeBlocks> OP_CHECKSEQUENCEVERIFY OP_DROP
2363
//            <selfKey>
2364
//        OP_ENDIF
2365
//        OP_CHECKSIG
2366
func LeaseCommitScriptToSelf(selfKey, revokeKey *btcec.PublicKey,
2367
        csvTimeout, leaseExpiry uint32) ([]byte, error) {
4✔
2368

4✔
2369
        // This script is spendable under two conditions: either the
4✔
2370
        // 'csvTimeout' has passed and we can redeem our funds, or they can
4✔
2371
        // produce a valid signature with the revocation public key. The
4✔
2372
        // revocation public key will *only* be known to the other party if we
4✔
2373
        // have divulged the revocation hash, allowing them to homomorphically
4✔
2374
        // derive the proper private key which corresponds to the revoke public
4✔
2375
        // key.
4✔
2376
        return txscript.ScriptTemplate(
4✔
2377
                `
4✔
2378
                OP_IF
4✔
2379
                        {{ hex .RevokeKey }}
4✔
2380
                OP_ELSE
4✔
2381
                        {{ .LeaseExpiry }} OP_CHECKLOCKTIMEVERIFY OP_DROP
4✔
2382
                        {{ .CsvTimeout }} OP_CHECKSEQUENCEVERIFY OP_DROP
4✔
2383
                        {{ hex .SelfKey }}
4✔
2384
                OP_ENDIF
4✔
2385
                OP_CHECKSIG`,
4✔
2386
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2387
                        "RevokeKey":   revokeKey.SerializeCompressed(),
4✔
2388
                        "LeaseExpiry": int64(leaseExpiry),
4✔
2389
                        "CsvTimeout":  int64(csvTimeout),
4✔
2390
                        "SelfKey":     selfKey.SerializeCompressed(),
4✔
2391
                }),
4✔
2392
        )
4✔
2393
}
4✔
2394

2395
// CommitSpendTimeout constructs a valid witness allowing the owner of a
2396
// particular commitment transaction to spend the output returning settled
2397
// funds back to themselves after a relative block timeout.  In order to
2398
// properly spend the transaction, the target input's sequence number should be
2399
// set accordingly based off of the target relative block timeout within the
2400
// redeem script.  Additionally, OP_CSV requires that the version of the
2401
// transaction spending a pkscript with OP_CSV within it *must* be >= 2.
2402
func CommitSpendTimeout(signer Signer, signDesc *SignDescriptor,
2403
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
2404

4✔
2405
        // Ensure the transaction version supports the validation of sequence
4✔
2406
        // locks and CSV semantics.
4✔
2407
        if sweepTx.Version < 2 {
4✔
UNCOV
2408
                return nil, fmt.Errorf("version of passed transaction MUST "+
×
UNCOV
2409
                        "be >= 2, not %v", sweepTx.Version)
×
UNCOV
2410
        }
×
2411

2412
        // With the sequence number in place, we're now able to properly sign
2413
        // off on the sweep transaction.
2414
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2415
        if err != nil {
4✔
UNCOV
2416
                return nil, err
×
UNCOV
2417
        }
×
2418

2419
        // Place an empty byte as the first item in the evaluated witness stack
2420
        // to force script execution to the timeout spend clause. We need to
2421
        // place an empty byte in order to ensure our script is still valid
2422
        // from the PoV of nodes that are enforcing minimal OP_IF/OP_NOTIF.
2423
        witnessStack := wire.TxWitness(make([][]byte, 3))
4✔
2424
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
2425
        witnessStack[1] = nil
4✔
2426
        witnessStack[2] = signDesc.WitnessScript
4✔
2427

4✔
2428
        return witnessStack, nil
4✔
2429
}
2430

2431
// CommitSpendRevoke constructs a valid witness allowing a node to sweep the
2432
// settled output of a malicious counterparty who broadcasts a revoked
2433
// commitment transaction.
2434
//
2435
// NOTE: The passed SignDescriptor should include the raw (untweaked)
2436
// revocation base public key of the receiver and also the proper double tweak
2437
// value based on the commitment secret of the revoked commitment.
2438
func CommitSpendRevoke(signer Signer, signDesc *SignDescriptor,
2439
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
2440

4✔
2441
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2442
        if err != nil {
4✔
UNCOV
2443
                return nil, err
×
UNCOV
2444
        }
×
2445

2446
        // Place a 1 as the first item in the evaluated witness stack to
2447
        // force script execution to the revocation clause.
2448
        witnessStack := wire.TxWitness(make([][]byte, 3))
4✔
2449
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
2450
        witnessStack[1] = []byte{1}
4✔
2451
        witnessStack[2] = signDesc.WitnessScript
4✔
2452

4✔
2453
        return witnessStack, nil
4✔
2454
}
2455

2456
// CommitSpendNoDelay constructs a valid witness allowing a node to spend their
2457
// settled no-delay output on the counterparty's commitment transaction. If the
2458
// tweakless field is true, then we'll omit the set where we tweak the pubkey
2459
// with a random set of bytes, and use it directly in the witness stack.
2460
//
2461
// NOTE: The passed SignDescriptor should include the raw (untweaked) public
2462
// key of the receiver and also the proper single tweak value based on the
2463
// current commitment point.
2464
func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor,
2465
        sweepTx *wire.MsgTx, tweakless bool) (wire.TxWitness, error) {
4✔
2466

4✔
2467
        if signDesc.KeyDesc.PubKey == nil {
4✔
UNCOV
2468
                return nil, fmt.Errorf("cannot generate witness with nil " +
×
UNCOV
2469
                        "KeyDesc pubkey")
×
UNCOV
2470
        }
×
2471

2472
        // This is just a regular p2wkh spend which looks something like:
2473
        //  * witness: <sig> <pubkey>
2474
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2475
        if err != nil {
4✔
UNCOV
2476
                return nil, err
×
UNCOV
2477
        }
×
2478

2479
        // Finally, we'll manually craft the witness. The witness here is the
2480
        // exact same as a regular p2wkh witness, depending on the value of the
2481
        // tweakless bool.
2482
        witness := make([][]byte, 2)
4✔
2483
        witness[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
2484

4✔
2485
        switch tweakless {
4✔
2486
        // If we're tweaking the key, then we use the tweaked public key as the
2487
        // last item in the witness stack which was originally used to created
2488
        // the pkScript we're spending.
2489
        case false:
4✔
2490
                witness[1] = TweakPubKeyWithTweak(
4✔
2491
                        signDesc.KeyDesc.PubKey, signDesc.SingleTweak,
4✔
2492
                ).SerializeCompressed()
4✔
2493

2494
        // Otherwise, we can just use the raw pubkey, since there's no random
2495
        // value to be combined.
2496
        case true:
4✔
2497
                witness[1] = signDesc.KeyDesc.PubKey.SerializeCompressed()
4✔
2498
        }
2499

2500
        return witness, nil
4✔
2501
}
2502

2503
// CommitScriptUnencumbered constructs the public key script on the commitment
2504
// transaction paying to the "other" party. The constructed output is a normal
2505
// p2wkh output spendable immediately, requiring no contestation period.
2506
func CommitScriptUnencumbered(key *btcec.PublicKey) ([]byte, error) {
4✔
2507
        // This script goes to the "other" party, and is spendable immediately.
4✔
2508
        return txscript.ScriptTemplate(
4✔
2509
                `OP_0 {{ hex .PKHash }}`,
4✔
2510
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2511
                        "PKHash": btcutil.Hash160(key.SerializeCompressed()),
4✔
2512
                }),
4✔
2513
        )
4✔
2514
}
4✔
2515

2516
// CommitScriptToRemoteConfirmed constructs the script for the output on the
2517
// commitment transaction paying to the remote party of said commitment
2518
// transaction. The money can only be spend after one confirmation.
2519
//
2520
// Possible Input Scripts:
2521
//
2522
//        SWEEP: <sig>
2523
//
2524
// Output Script:
2525
//
2526
//        <key> OP_CHECKSIGVERIFY
2527
//        1 OP_CHECKSEQUENCEVERIFY
2528
func CommitScriptToRemoteConfirmed(key *btcec.PublicKey) ([]byte, error) {
4✔
2529
        // Only the given key can spend the output after one confirmation.
4✔
2530
        return txscript.ScriptTemplate(
4✔
2531
                `
4✔
2532
                {{ hex .Key }} OP_CHECKSIGVERIFY 
4✔
2533
                OP_1 OP_CHECKSEQUENCEVERIFY`,
4✔
2534
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2535
                        "Key": key.SerializeCompressed(),
4✔
2536
                }),
4✔
2537
        )
4✔
2538
}
4✔
2539

2540
// NewRemoteCommitScriptTree constructs a new script tree for the remote party
2541
// to sweep their funds after a hard coded 1 block delay.
2542
func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
2543
        auxLeaf AuxTapLeaf,
2544
        opts ...TaprootScriptOpt) (*CommitScriptTree, error) {
4✔
2545

4✔
2546
        opt := defaultTaprootScriptOpt()
4✔
2547
        for _, o := range opts {
8✔
2548
                o(opt)
4✔
2549
        }
4✔
2550

2551
        // First, construct the remote party's tapscript they'll use to sweep
2552
        // their outputs.
2553
        var scriptTemplate string
4✔
2554
        switch {
4✔
2555
        case opt.prodScript:
4✔
2556
                scriptTemplate = `
4✔
2557
                {{ hex .RemoteKey }} OP_CHECKSIGVERIFY
4✔
2558
                OP_1 OP_CHECKSEQUENCEVERIFY`
4✔
2559
        default:
4✔
2560
                scriptTemplate = `
4✔
2561
                {{ hex .RemoteKey }} OP_CHECKSIG
4✔
2562
                OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP`
4✔
2563
        }
2564

2565
        remoteScript, err := txscript.ScriptTemplate(
4✔
2566
                scriptTemplate,
4✔
2567
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2568
                        "RemoteKey": schnorr.SerializePubKey(remoteKey),
4✔
2569
                }),
4✔
2570
        )
4✔
2571
        if err != nil {
4✔
UNCOV
2572
                return nil, err
×
UNCOV
2573
        }
×
2574

2575
        tapLeaf := txscript.NewBaseTapLeaf(remoteScript)
4✔
2576

4✔
2577
        tapLeaves := []txscript.TapLeaf{tapLeaf}
4✔
2578
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
4✔
UNCOV
2579
                tapLeaves = append(tapLeaves, l)
×
UNCOV
2580
        })
×
2581

2582
        // With this script constructed, we'll map that into a tapLeaf, then
2583
        // make a new tapscript root from that.
2584
        tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
4✔
2585
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
4✔
2586

4✔
2587
        // Now that we have our root, we can arrive at the final output script
4✔
2588
        // by tweaking the internal key with this root.
4✔
2589
        toRemoteOutputKey := txscript.ComputeTaprootOutputKey(
4✔
2590
                &TaprootNUMSKey, tapScriptRoot[:],
4✔
2591
        )
4✔
2592

4✔
2593
        return &CommitScriptTree{
4✔
2594
                ScriptTree: ScriptTree{
4✔
2595
                        TaprootKey:    toRemoteOutputKey,
4✔
2596
                        TapscriptTree: tapScriptTree,
4✔
2597
                        TapscriptRoot: tapScriptRoot[:],
4✔
2598
                        InternalKey:   &TaprootNUMSKey,
4✔
2599
                },
4✔
2600
                SettleLeaf: tapLeaf,
4✔
2601
                AuxLeaf:    auxLeaf,
4✔
2602
        }, nil
4✔
2603
}
2604

2605
// TaprootCommitScriptToRemote constructs a taproot witness program for the
2606
// output on the commitment transaction for the remote party. For the top level
2607
// key spend, we'll use a NUMs key to ensure that only the script path can be
2608
// taken. Using a set NUMs key here also means that recovery solutions can scan
2609
// the chain given knowledge of the public key for the remote party. We then
2610
// commit to a single tapscript leaf that holds the normal CSV 1 delay
2611
// script.
2612
//
2613
// Our single tapleaf will use the following script:
2614
//
2615
//        <remotepubkey> OP_CHECKSIG
2616
//        1 OP_CHECKSEQUENCEVERIFY OP_DROP
2617
func TaprootCommitScriptToRemote(remoteKey *btcec.PublicKey,
UNCOV
2618
        auxLeaf AuxTapLeaf) (*btcec.PublicKey, error) {
×
UNCOV
2619

×
UNCOV
2620
        commitScriptTree, err := NewRemoteCommitScriptTree(remoteKey, auxLeaf)
×
UNCOV
2621
        if err != nil {
×
UNCOV
2622
                return nil, err
×
2623
        }
×
2624

2625
        return commitScriptTree.TaprootKey, nil
×
2626
}
2627

2628
// TaprootCommitRemoteSpend allows the remote party to sweep their output into
2629
// their wallet after an enforced 1 block delay.
2630
func TaprootCommitRemoteSpend(signer Signer, signDesc *SignDescriptor,
2631
        sweepTx *wire.MsgTx,
2632
        scriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
4✔
2633

4✔
2634
        // First, we'll need to construct a valid control block to execute the
4✔
2635
        // leaf script for sweep settlement.
4✔
2636
        var ctrlBlockBytes []byte
4✔
2637
        if signDesc.ControlBlock == nil {
4✔
UNCOV
2638
                settleControlBlock := MakeTaprootCtrlBlock(
×
UNCOV
2639
                        signDesc.WitnessScript, &TaprootNUMSKey, scriptTree,
×
UNCOV
2640
                )
×
UNCOV
2641
                ctrlBytes, err := settleControlBlock.ToBytes()
×
UNCOV
2642
                if err != nil {
×
UNCOV
2643
                        return nil, err
×
UNCOV
2644
                }
×
2645

UNCOV
2646
                ctrlBlockBytes = ctrlBytes
×
2647
        } else {
4✔
2648
                ctrlBlockBytes = signDesc.ControlBlock
4✔
2649
        }
4✔
2650

2651
        // With the control block created, we'll now generate the signature we
2652
        // need to authorize the spend.
2653
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2654
        if err != nil {
4✔
UNCOV
2655
                return nil, err
×
UNCOV
2656
        }
×
2657

2658
        // The final witness stack will be:
2659
        //
2660
        //  <sweep sig> <sweep script> <control block>
2661
        witnessStack := make(wire.TxWitness, 3)
4✔
2662
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
2663
        witnessStack[1] = signDesc.WitnessScript
4✔
2664
        witnessStack[2] = ctrlBlockBytes
4✔
2665

4✔
2666
        return witnessStack, nil
4✔
2667
}
2668

2669
// LeaseCommitScriptToRemoteConfirmed constructs the script for the output on
2670
// the commitment transaction paying to the remote party of said commitment
2671
// transaction. The money can only be spend after one confirmation.
2672
//
2673
// Possible Input Scripts:
2674
//
2675
//        SWEEP: <sig>
2676
//
2677
// Output Script:
2678
//
2679
//                <key> OP_CHECKSIGVERIFY
2680
//             <lease maturity in blocks> OP_CHECKLOCKTIMEVERIFY OP_DROP
2681
//                1 OP_CHECKSEQUENCEVERIFY
2682
func LeaseCommitScriptToRemoteConfirmed(key *btcec.PublicKey,
2683
        leaseExpiry uint32) ([]byte, error) {
4✔
2684

4✔
2685
        // This script adds lease expiration constraint in addition to the
4✔
2686
        // standard remote confirmed script requirements.
4✔
2687
        return txscript.ScriptTemplate(
4✔
2688
                `
4✔
2689
                {{ hex .Key }} OP_CHECKSIGVERIFY
4✔
2690
                {{ .LeaseExpiry }} OP_CHECKLOCKTIMEVERIFY OP_DROP
4✔
2691
                OP_1 OP_CHECKSEQUENCEVERIFY`,
4✔
2692
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2693
                        "Key":         key.SerializeCompressed(),
4✔
2694
                        "LeaseExpiry": int64(leaseExpiry),
4✔
2695
                }),
4✔
2696
        )
4✔
2697
}
4✔
2698

2699
// CommitSpendToRemoteConfirmed constructs a valid witness allowing a node to
2700
// spend their settled output on the counterparty's commitment transaction when
2701
// it has one confirmetion. This is used for the anchor channel type. The
2702
// spending key will always be non-tweaked for this output type.
2703
func CommitSpendToRemoteConfirmed(signer Signer, signDesc *SignDescriptor,
2704
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
2705

4✔
2706
        if signDesc.KeyDesc.PubKey == nil {
4✔
UNCOV
2707
                return nil, fmt.Errorf("cannot generate witness with nil " +
×
UNCOV
2708
                        "KeyDesc pubkey")
×
UNCOV
2709
        }
×
2710

2711
        // Similar to non delayed output, only a signature is needed.
2712
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2713
        if err != nil {
4✔
2714
                return nil, err
×
UNCOV
2715
        }
×
2716

2717
        // Finally, we'll manually craft the witness. The witness here is the
2718
        // signature and the redeem script.
2719
        witnessStack := make([][]byte, 2)
4✔
2720
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
2721
        witnessStack[1] = signDesc.WitnessScript
4✔
2722

4✔
2723
        return witnessStack, nil
4✔
2724
}
2725

2726
// CommitScriptAnchor constructs the script for the anchor output spendable by
2727
// the given key immediately, or by anyone after 16 confirmations.
2728
//
2729
// Possible Input Scripts:
2730
//
2731
//        By owner:                                <sig>
2732
//        By anyone (after 16 conf):        <emptyvector>
2733
//
2734
// Output Script:
2735
//
2736
//        <funding_pubkey> OP_CHECKSIG OP_IFDUP
2737
//        OP_NOTIF
2738
//          OP_16 OP_CSV
2739
//        OP_ENDIF
2740
func CommitScriptAnchor(key *btcec.PublicKey) ([]byte, error) {
4✔
2741
        // Build the anchor script with two possible spending paths:
4✔
2742
        // 1. Spend immediately with key (the normal path)
4✔
2743
        // 2. Spend after 16 confirmations by anyone (the alternative path)
4✔
2744
        return txscript.ScriptTemplate(
4✔
2745
                `
4✔
2746
                {{ hex .Key }} OP_CHECKSIG
4✔
2747
                OP_IFDUP
4✔
2748
                OP_NOTIF
4✔
2749
                        OP_16 OP_CHECKSEQUENCEVERIFY
4✔
2750
                OP_ENDIF`,
4✔
2751
                txscript.WithScriptTemplateParams(TemplateParams{
4✔
2752
                        "Key": key.SerializeCompressed(),
4✔
2753
                }),
4✔
2754
        )
4✔
2755
}
4✔
2756

2757
// AnchorScriptTree holds all the contents needed to sweep a taproot anchor
2758
// output on chain.
2759
type AnchorScriptTree struct {
2760
        ScriptTree
2761

2762
        // SweepLeaf is the leaf used to settle the output after the delay.
2763
        SweepLeaf txscript.TapLeaf
2764
}
2765

2766
// NewAnchorScriptTree makes a new script tree for an anchor output with the
2767
// passed anchor key.
2768
func NewAnchorScriptTree(
2769
        anchorKey *btcec.PublicKey) (*AnchorScriptTree, error) {
4✔
2770

4✔
2771
        // The main script used is just a OP_16 CSV (anyone can sweep after 16
4✔
2772
        // blocks).
4✔
2773
        anchorScript, err := txscript.ScriptTemplate(
4✔
2774
                `OP_16 OP_CHECKSEQUENCEVERIFY`,
4✔
2775
        )
4✔
2776
        if err != nil {
4✔
UNCOV
2777
                return nil, err
×
UNCOV
2778
        }
×
2779

2780
        // With the script, we can make our sole leaf, then derive the root
2781
        // from that.
2782
        tapLeaf := txscript.NewBaseTapLeaf(anchorScript)
4✔
2783
        tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf)
4✔
2784
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
4✔
2785

4✔
2786
        // Now that we have our root, we can arrive at the final output script
4✔
2787
        // by tweaking the internal key with this root.
4✔
2788
        anchorOutputKey := txscript.ComputeTaprootOutputKey(
4✔
2789
                anchorKey, tapScriptRoot[:],
4✔
2790
        )
4✔
2791

4✔
2792
        return &AnchorScriptTree{
4✔
2793
                ScriptTree: ScriptTree{
4✔
2794
                        TaprootKey:    anchorOutputKey,
4✔
2795
                        TapscriptTree: tapScriptTree,
4✔
2796
                        TapscriptRoot: tapScriptRoot[:],
4✔
2797
                        InternalKey:   anchorKey,
4✔
2798
                },
4✔
2799
                SweepLeaf: tapLeaf,
4✔
2800
        }, nil
4✔
2801
}
2802

2803
// WitnessScriptToSign returns the witness script that we'll use when signing
2804
// for the remote party, and also verifying signatures on our transactions. As
2805
// an example, when we create an outgoing HTLC for the remote party, we want to
2806
// sign their success path.
UNCOV
2807
func (a *AnchorScriptTree) WitnessScriptToSign() []byte {
×
UNCOV
2808
        return a.SweepLeaf.Script
×
UNCOV
2809
}
×
2810

2811
// WitnessScriptForPath returns the witness script for the given spending path.
2812
// An error is returned if the path is unknown.
2813
func (a *AnchorScriptTree) WitnessScriptForPath(
2814
        path ScriptPath) ([]byte, error) {
4✔
2815

4✔
2816
        switch path {
4✔
UNCOV
2817
        case ScriptPathDelay:
×
UNCOV
2818
                fallthrough
×
2819
        case ScriptPathSuccess:
4✔
2820
                return a.SweepLeaf.Script, nil
4✔
2821

2822
        default:
×
2823
                return nil, fmt.Errorf("unknown script path: %v", path)
×
2824
        }
2825
}
2826

2827
// CtrlBlockForPath returns the control block for the given spending path. For
2828
// script types that don't have a control block, nil is returned.
2829
func (a *AnchorScriptTree) CtrlBlockForPath(
UNCOV
2830
        path ScriptPath) (*txscript.ControlBlock, error) {
×
UNCOV
2831

×
UNCOV
2832
        switch path {
×
UNCOV
2833
        case ScriptPathDelay:
×
UNCOV
2834
                fallthrough
×
2835
        case ScriptPathSuccess:
×
2836
                return lnutils.Ptr(MakeTaprootCtrlBlock(
×
2837
                        a.SweepLeaf.Script, a.InternalKey,
×
2838
                        a.TapscriptTree,
×
2839
                )), nil
×
2840

2841
        default:
×
2842
                return nil, fmt.Errorf("unknown script path: %v", path)
×
2843
        }
2844
}
2845

2846
// Tree returns the underlying ScriptTree of the AnchorScriptTree.
2847
func (a *AnchorScriptTree) Tree() ScriptTree {
×
UNCOV
2848
        return a.ScriptTree
×
UNCOV
2849
}
×
2850

2851
// A compile time check to ensure AnchorScriptTree implements the
2852
// TapscriptDescriptor interface.
2853
var _ TapscriptDescriptor = (*AnchorScriptTree)(nil)
2854

2855
// TaprootOutputKeyAnchor returns the segwit v1 (taproot) witness program that
2856
// encodes the anchor output spending conditions: the passed key can be used
2857
// for keyspend, with the OP_CSV 16 clause living within an internal tapscript
2858
// leaf.
2859
//
2860
// Spend paths:
2861
//   - Key spend: <key_signature>
2862
//   - Script spend: OP_16 CSV <control_block>
UNCOV
2863
func TaprootOutputKeyAnchor(key *btcec.PublicKey) (*btcec.PublicKey, error) {
×
UNCOV
2864
        anchorScriptTree, err := NewAnchorScriptTree(key)
×
UNCOV
2865
        if err != nil {
×
UNCOV
2866
                return nil, err
×
UNCOV
2867
        }
×
2868

2869
        return anchorScriptTree.TaprootKey, nil
×
2870
}
2871

2872
// TaprootAnchorSpend constructs a valid witness allowing a node to sweep their
2873
// anchor output.
2874
func TaprootAnchorSpend(signer Signer, signDesc *SignDescriptor,
2875
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
2876

4✔
2877
        // For this spend type, we only need a single signature which'll be a
4✔
2878
        // keyspend using the anchor private key.
4✔
2879
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2880
        if err != nil {
4✔
UNCOV
2881
                return nil, err
×
UNCOV
2882
        }
×
2883

2884
        // The witness stack in this case is pretty simple: we only need to
2885
        // specify the signature generated.
2886
        witnessStack := make(wire.TxWitness, 1)
4✔
2887
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
4✔
2888

4✔
2889
        return witnessStack, nil
4✔
2890
}
2891

2892
// TaprootAnchorSpendAny constructs a valid witness allowing anyone to sweep
2893
// the anchor output after 16 blocks.
UNCOV
2894
func TaprootAnchorSpendAny(anchorKey *btcec.PublicKey) (wire.TxWitness, error) {
×
UNCOV
2895
        anchorScriptTree, err := NewAnchorScriptTree(anchorKey)
×
UNCOV
2896
        if err != nil {
×
UNCOV
2897
                return nil, err
×
UNCOV
2898
        }
×
2899

2900
        // For this spend, the only thing we need to do is create a valid
2901
        // control block. Other than that, there're no restrictions to how the
2902
        // output can be spent.
2903
        scriptTree := anchorScriptTree.TapscriptTree
×
UNCOV
2904
        sweepLeaf := anchorScriptTree.SweepLeaf
×
UNCOV
2905
        sweepIdx := scriptTree.LeafProofIndex[sweepLeaf.TapHash()]
×
UNCOV
2906
        sweepMerkleProof := scriptTree.LeafMerkleProofs[sweepIdx]
×
UNCOV
2907
        sweepControlBlock := sweepMerkleProof.ToControlBlock(anchorKey)
×
UNCOV
2908

×
UNCOV
2909
        // The final witness stack will be:
×
UNCOV
2910
        //
×
UNCOV
2911
        //  <sweep script> <control block>
×
UNCOV
2912
        witnessStack := make(wire.TxWitness, 2)
×
UNCOV
2913
        witnessStack[0] = sweepLeaf.Script
×
UNCOV
2914
        witnessStack[1], err = sweepControlBlock.ToBytes()
×
UNCOV
2915
        if err != nil {
×
UNCOV
2916
                return nil, err
×
UNCOV
2917
        }
×
2918

UNCOV
2919
        return witnessStack, nil
×
2920
}
2921

2922
// CommitSpendAnchor constructs a valid witness allowing a node to spend their
2923
// anchor output on the commitment transaction using their funding key. This is
2924
// used for the anchor channel type.
2925
func CommitSpendAnchor(signer Signer, signDesc *SignDescriptor,
2926
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
2927

4✔
2928
        if signDesc.KeyDesc.PubKey == nil {
4✔
UNCOV
2929
                return nil, fmt.Errorf("cannot generate witness with nil " +
×
UNCOV
2930
                        "KeyDesc pubkey")
×
UNCOV
2931
        }
×
2932

2933
        // Create a signature.
2934
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
4✔
2935
        if err != nil {
4✔
2936
                return nil, err
×
UNCOV
2937
        }
×
2938

2939
        // The witness here is just a signature and the redeem script.
2940
        witnessStack := make([][]byte, 2)
4✔
2941
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
4✔
2942
        witnessStack[1] = signDesc.WitnessScript
4✔
2943

4✔
2944
        return witnessStack, nil
4✔
2945
}
2946

2947
// CommitSpendAnchorAnyone constructs a witness allowing anyone to spend the
2948
// anchor output after it has gotten 16 confirmations. Since no signing is
2949
// required, only knowledge of the redeem script is necessary to spend it.
UNCOV
2950
func CommitSpendAnchorAnyone(script []byte) (wire.TxWitness, error) {
×
UNCOV
2951
        // The witness here is just the redeem script.
×
UNCOV
2952
        witnessStack := make([][]byte, 2)
×
UNCOV
2953
        witnessStack[0] = nil
×
UNCOV
2954
        witnessStack[1] = script
×
UNCOV
2955

×
UNCOV
2956
        return witnessStack, nil
×
UNCOV
2957
}
×
2958

2959
// SingleTweakBytes computes set of bytes we call the single tweak. The purpose
2960
// of the single tweak is to randomize all regular delay and payment base
2961
// points. To do this, we generate a hash that binds the commitment point to
2962
// the pay/delay base point. The end result is that the basePoint is
2963
// tweaked as follows:
2964
//
2965
//   - key = basePoint + sha256(commitPoint || basePoint)*G
2966
func SingleTweakBytes(commitPoint, basePoint *btcec.PublicKey) []byte {
4✔
2967
        h := sha256.New()
4✔
2968
        h.Write(commitPoint.SerializeCompressed())
4✔
2969
        h.Write(basePoint.SerializeCompressed())
4✔
2970
        return h.Sum(nil)
4✔
2971
}
4✔
2972

2973
// TweakPubKey tweaks a public base point given a per commitment point. The per
2974
// commitment point is a unique point on our target curve for each commitment
2975
// transaction. When tweaking a local base point for use in a remote commitment
2976
// transaction, the remote party's current per commitment point is to be used.
2977
// The opposite applies for when tweaking remote keys. Precisely, the following
2978
// operation is used to "tweak" public keys:
2979
//
2980
//        tweakPub := basePoint + sha256(commitPoint || basePoint) * G
2981
//                 := G*k + sha256(commitPoint || basePoint)*G
2982
//                 := G*(k + sha256(commitPoint || basePoint))
2983
//
2984
// Therefore, if a party possess the value k, the private key of the base
2985
// point, then they are able to derive the proper private key for the
2986
// revokeKey by computing:
2987
//
2988
//        revokePriv := k + sha256(commitPoint || basePoint) mod N
2989
//
2990
// Where N is the order of the sub-group.
2991
//
2992
// The rationale for tweaking all public keys used within the commitment
2993
// contracts is to ensure that all keys are properly delinearized to avoid any
2994
// funny business when jointly collaborating to compute public and private
2995
// keys. Additionally, the use of the per commitment point ensures that each
2996
// commitment state houses a unique set of keys which is useful when creating
2997
// blinded channel outsourcing protocols.
2998
//
2999
// TODO(roasbeef): should be using double-scalar mult here
3000
func TweakPubKey(basePoint, commitPoint *btcec.PublicKey) *btcec.PublicKey {
4✔
3001
        tweakBytes := SingleTweakBytes(commitPoint, basePoint)
4✔
3002
        return TweakPubKeyWithTweak(basePoint, tweakBytes)
4✔
3003
}
4✔
3004

3005
// TweakPubKeyWithTweak is the exact same as the TweakPubKey function, however
3006
// it accepts the raw tweak bytes directly rather than the commitment point.
3007
func TweakPubKeyWithTweak(pubKey *btcec.PublicKey,
3008
        tweakBytes []byte) *btcec.PublicKey {
4✔
3009

4✔
3010
        var (
4✔
3011
                pubKeyJacobian btcec.JacobianPoint
4✔
3012
                tweakJacobian  btcec.JacobianPoint
4✔
3013
                resultJacobian btcec.JacobianPoint
4✔
3014
        )
4✔
3015
        tweakKey, _ := btcec.PrivKeyFromBytes(tweakBytes)
4✔
3016
        btcec.ScalarBaseMultNonConst(&tweakKey.Key, &tweakJacobian)
4✔
3017

4✔
3018
        pubKey.AsJacobian(&pubKeyJacobian)
4✔
3019
        btcec.AddNonConst(&pubKeyJacobian, &tweakJacobian, &resultJacobian)
4✔
3020

4✔
3021
        resultJacobian.ToAffine()
4✔
3022
        return btcec.NewPublicKey(&resultJacobian.X, &resultJacobian.Y)
4✔
3023
}
4✔
3024

3025
// TweakPrivKey tweaks the private key of a public base point given a per
3026
// commitment point. The per commitment secret is the revealed revocation
3027
// secret for the commitment state in question. This private key will only need
3028
// to be generated in the case that a channel counter party broadcasts a
3029
// revoked state. Precisely, the following operation is used to derive a
3030
// tweaked private key:
3031
//
3032
//   - tweakPriv := basePriv + sha256(commitment || basePub) mod N
3033
//
3034
// Where N is the order of the sub-group.
3035
func TweakPrivKey(basePriv *btcec.PrivateKey,
3036
        commitTweak []byte) *btcec.PrivateKey {
4✔
3037

4✔
3038
        // tweakInt := sha256(commitPoint || basePub)
4✔
3039
        tweakScalar := new(btcec.ModNScalar)
4✔
3040
        tweakScalar.SetByteSlice(commitTweak)
4✔
3041

4✔
3042
        tweakScalar.Add(&basePriv.Key)
4✔
3043

4✔
3044
        return &btcec.PrivateKey{Key: *tweakScalar}
4✔
3045
}
4✔
3046

3047
// DeriveRevocationPubkey derives the revocation public key given the
3048
// counterparty's commitment key, and revocation preimage derived via a
3049
// pseudo-random-function. In the event that we (for some reason) broadcast a
3050
// revoked commitment transaction, then if the other party knows the revocation
3051
// preimage, then they'll be able to derive the corresponding private key to
3052
// this private key by exploiting the homomorphism in the elliptic curve group:
3053
//   - https://en.wikipedia.org/wiki/Group_homomorphism#Homomorphisms_of_abelian_groups
3054
//
3055
// The derivation is performed as follows:
3056
//
3057
//        revokeKey := revokeBase * sha256(revocationBase || commitPoint) +
3058
//                     commitPoint * sha256(commitPoint || revocationBase)
3059
//
3060
//                  := G*(revokeBasePriv * sha256(revocationBase || commitPoint)) +
3061
//                     G*(commitSecret * sha256(commitPoint || revocationBase))
3062
//
3063
//                  := G*(revokeBasePriv * sha256(revocationBase || commitPoint) +
3064
//                        commitSecret * sha256(commitPoint || revocationBase))
3065
//
3066
// Therefore, once we divulge the revocation secret, the remote peer is able to
3067
// compute the proper private key for the revokeKey by computing:
3068
//
3069
//        revokePriv := (revokeBasePriv * sha256(revocationBase || commitPoint)) +
3070
//                      (commitSecret * sha256(commitPoint || revocationBase)) mod N
3071
//
3072
// Where N is the order of the sub-group.
3073
func DeriveRevocationPubkey(revokeBase,
3074
        commitPoint *btcec.PublicKey) *btcec.PublicKey {
4✔
3075

4✔
3076
        // R = revokeBase * sha256(revocationBase || commitPoint)
4✔
3077
        revokeTweakBytes := SingleTweakBytes(revokeBase, commitPoint)
4✔
3078
        revokeTweakScalar := new(btcec.ModNScalar)
4✔
3079
        revokeTweakScalar.SetByteSlice(revokeTweakBytes)
4✔
3080

4✔
3081
        var (
4✔
3082
                revokeBaseJacobian btcec.JacobianPoint
4✔
3083
                rJacobian          btcec.JacobianPoint
4✔
3084
        )
4✔
3085
        revokeBase.AsJacobian(&revokeBaseJacobian)
4✔
3086
        btcec.ScalarMultNonConst(
4✔
3087
                revokeTweakScalar, &revokeBaseJacobian, &rJacobian,
4✔
3088
        )
4✔
3089

4✔
3090
        // C = commitPoint * sha256(commitPoint || revocationBase)
4✔
3091
        commitTweakBytes := SingleTweakBytes(commitPoint, revokeBase)
4✔
3092
        commitTweakScalar := new(btcec.ModNScalar)
4✔
3093
        commitTweakScalar.SetByteSlice(commitTweakBytes)
4✔
3094

4✔
3095
        var (
4✔
3096
                commitPointJacobian btcec.JacobianPoint
4✔
3097
                cJacobian           btcec.JacobianPoint
4✔
3098
        )
4✔
3099
        commitPoint.AsJacobian(&commitPointJacobian)
4✔
3100
        btcec.ScalarMultNonConst(
4✔
3101
                commitTweakScalar, &commitPointJacobian, &cJacobian,
4✔
3102
        )
4✔
3103

4✔
3104
        // Now that we have the revocation point, we add this to their commitment
4✔
3105
        // public key in order to obtain the revocation public key.
4✔
3106
        //
4✔
3107
        // P = R + C
4✔
3108
        var resultJacobian btcec.JacobianPoint
4✔
3109
        btcec.AddNonConst(&rJacobian, &cJacobian, &resultJacobian)
4✔
3110

4✔
3111
        resultJacobian.ToAffine()
4✔
3112
        return btcec.NewPublicKey(&resultJacobian.X, &resultJacobian.Y)
4✔
3113
}
4✔
3114

3115
// DeriveRevocationPrivKey derives the revocation private key given a node's
3116
// commitment private key, and the preimage to a previously seen revocation
3117
// hash. Using this derived private key, a node is able to claim the output
3118
// within the commitment transaction of a node in the case that they broadcast
3119
// a previously revoked commitment transaction.
3120
//
3121
// The private key is derived as follows:
3122
//
3123
//        revokePriv := (revokeBasePriv * sha256(revocationBase || commitPoint)) +
3124
//                      (commitSecret * sha256(commitPoint || revocationBase)) mod N
3125
//
3126
// Where N is the order of the sub-group.
3127
func DeriveRevocationPrivKey(revokeBasePriv *btcec.PrivateKey,
3128
        commitSecret *btcec.PrivateKey) *btcec.PrivateKey {
4✔
3129

4✔
3130
        // r = sha256(revokeBasePub || commitPoint)
4✔
3131
        revokeTweakBytes := SingleTweakBytes(
4✔
3132
                revokeBasePriv.PubKey(), commitSecret.PubKey(),
4✔
3133
        )
4✔
3134
        revokeTweakScalar := new(btcec.ModNScalar)
4✔
3135
        revokeTweakScalar.SetByteSlice(revokeTweakBytes)
4✔
3136

4✔
3137
        // c = sha256(commitPoint || revokeBasePub)
4✔
3138
        commitTweakBytes := SingleTweakBytes(
4✔
3139
                commitSecret.PubKey(), revokeBasePriv.PubKey(),
4✔
3140
        )
4✔
3141
        commitTweakScalar := new(btcec.ModNScalar)
4✔
3142
        commitTweakScalar.SetByteSlice(commitTweakBytes)
4✔
3143

4✔
3144
        // Finally to derive the revocation secret key we'll perform the
4✔
3145
        // following operation:
4✔
3146
        //
4✔
3147
        //  k = (revocationPriv * r) + (commitSecret * c) mod N
4✔
3148
        //
4✔
3149
        // This works since:
4✔
3150
        //  P = (G*a)*b + (G*c)*d
4✔
3151
        //  P = G*(a*b) + G*(c*d)
4✔
3152
        //  P = G*(a*b + c*d)
4✔
3153
        revokeHalfPriv := revokeTweakScalar.Mul(&revokeBasePriv.Key)
4✔
3154
        commitHalfPriv := commitTweakScalar.Mul(&commitSecret.Key)
4✔
3155

4✔
3156
        revocationPriv := revokeHalfPriv.Add(commitHalfPriv)
4✔
3157

4✔
3158
        return &btcec.PrivateKey{Key: *revocationPriv}
4✔
3159
}
4✔
3160

3161
// ComputeCommitmentPoint generates a commitment point given a commitment
3162
// secret. The commitment point for each state is used to randomize each key in
3163
// the key-ring and also to used as a tweak to derive new public+private keys
3164
// for the state.
3165
func ComputeCommitmentPoint(commitSecret []byte) *btcec.PublicKey {
4✔
3166
        _, pubKey := btcec.PrivKeyFromBytes(commitSecret)
4✔
3167
        return pubKey
4✔
3168
}
4✔
3169

3170
// ScriptIsOpReturn returns true if the passed script is an OP_RETURN script.
3171
//
3172
// Lifted from the txscript package:
3173
// https://github.com/btcsuite/btcd/blob/cc26860b40265e1332cca8748c5dbaf3c81cc094/txscript/standard.go#L493-L526.
3174
//
3175
//nolint:ll
3176
func ScriptIsOpReturn(script []byte) bool {
4✔
3177
        // A null script is of the form:
4✔
3178
        //  OP_RETURN <optional data>
4✔
3179
        //
4✔
3180
        // Thus, it can either be a single OP_RETURN or an OP_RETURN followed by
4✔
3181
        // a data push up to MaxDataCarrierSize bytes.
4✔
3182

4✔
3183
        // The script can't possibly be a null data script if it doesn't start
4✔
3184
        // with OP_RETURN.  Fail fast to avoid more work below.
4✔
3185
        if len(script) < 1 || script[0] != txscript.OP_RETURN {
8✔
3186
                return false
4✔
3187
        }
4✔
3188

3189
        // Single OP_RETURN.
UNCOV
3190
        if len(script) == 1 {
×
UNCOV
3191
                return true
×
UNCOV
3192
        }
×
3193

3194
        // OP_RETURN followed by data push up to MaxDataCarrierSize bytes.
UNCOV
3195
        tokenizer := txscript.MakeScriptTokenizer(0, script[1:])
×
UNCOV
3196

×
UNCOV
3197
        return tokenizer.Next() && tokenizer.Done() &&
×
UNCOV
3198
                (txscript.IsSmallInt(tokenizer.Opcode()) ||
×
UNCOV
3199
                        tokenizer.Opcode() <= txscript.OP_PUSHDATA4) &&
×
UNCOV
3200
                len(tokenizer.Data()) <= txscript.MaxDataCarrierSize
×
3201
}
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