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

lightningnetwork / lnd / 23047540074

13 Mar 2026 10:51AM UTC coverage: 51.126% (-11.2%) from 62.349%
23047540074

Pull #10643

github

web-flow
Merge f4a32cc73 into 78b104ec7
Pull Request #10643: docs: move coop close confirmation scaling note to 0.21.0

113591 of 222178 relevant lines covered (51.13%)

19830.47 hits per line

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

55.54
/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 {
87✔
39
        pubBytes, err := hex.DecodeString(pubStr)
87✔
40
        if err != nil {
87✔
41
                panic(err)
×
42
        }
×
43

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

49
        return *pub
87✔
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) {
103✔
80
        if len(rawSig) == schnorr.SignatureSize {
111✔
81
                return schnorr.ParseSignature(rawSig)
8✔
82
        }
8✔
83

84
        return ecdsa.ParseDERSignature(rawSig)
95✔
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) {
29,910✔
90
        scriptHash := sha256.Sum256(witnessScript)
29,910✔
91
        return txscript.ScriptTemplate(
29,910✔
92
                `OP_0 {{ hex .ScriptHash }}`,
29,910✔
93
                txscript.WithScriptTemplateParams(TemplateParams{
29,910✔
94
                        "ScriptHash": scriptHash[:],
29,910✔
95
                }),
29,910✔
96
        )
29,910✔
97
}
29,910✔
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) {
34✔
103
        pkhash := btcutil.Hash160(pubkey)
34✔
104
        return txscript.ScriptTemplate(
34✔
105
                `OP_0 {{ hex .PKHash }}`,
34✔
106
                txscript.WithScriptTemplateParams(TemplateParams{
34✔
107
                        "PKHash": pkhash,
34✔
108
                }),
34✔
109
        )
34✔
110
}
34✔
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) {
3✔
127
        pkHash := btcutil.Hash160(pubkey)
3✔
128
        return txscript.ScriptTemplate(
3✔
129
                `OP_DUP OP_HASH160 {{ hex .pkh }} OP_EQUALVERIFY OP_CHECKSIG`,
3✔
130
                txscript.WithScriptTemplateParams(TemplateParams{
3✔
131
                        "pkh": pkHash,
3✔
132
                }),
3✔
133
        )
3✔
134
}
3✔
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) {
490✔
139
        witnessScript := make([]byte, 40)
490✔
140
        return txscript.ScriptTemplate(
490✔
141
                `OP_0 {{ hex .WitnessScript }}`,
490✔
142
                txscript.WithScriptTemplateParams(TemplateParams{
490✔
143
                        "WitnessScript": witnessScript,
490✔
144
                }),
490✔
145
        )
490✔
146
}
490✔
147

×
148
// GenMultiSigScript generates the non-p2sh'd multisig script for 2 of 2
×
149
// pubkeys.
×
150
func GenMultiSigScript(aPub, bPub []byte) ([]byte, error) {
2,015✔
151
        if len(aPub) != 33 || len(bPub) != 33 {
2,015✔
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 {
2,927✔
161
                aPub, bPub = bPub, aPub
912✔
162
        }
912✔
163

×
164
        return txscript.ScriptTemplate(
2,015✔
165
                `OP_2 {{ hex .pubA }} {{ hex .pubB }} OP_2 OP_CHECKMULTISIG`,
2,015✔
166
                txscript.WithScriptTemplateParams(TemplateParams{
2,015✔
167
                        "pubA": aPub,
2,015✔
168
                        "pubB": bPub,
2,015✔
169
                }),
2,015✔
170
        )
2,015✔
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) {
288✔
176
        // As a sanity check, ensure that the passed amount is above zero.
288✔
177
        if amt <= 0 {
288✔
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)
288✔
184
        if err != nil {
288✔
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)
288✔
191
        if err != nil {
288✔
192
                return nil, nil, err
×
193
        }
×
194

195
        return witnessScript, wire.NewTxOut(amt, pkScript), nil
288✔
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) {
93✔
203

93✔
204
        muSig2Opt := musig2.WithBIP86KeyTweak()
93✔
205
        tapscriptRoot.WhenSome(func(scriptRoot chainhash.Hash) {
125✔
206
                muSig2Opt = musig2.WithTaprootKeyTweak(scriptRoot[:])
32✔
207
        })
32✔
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(
93✔
215
                []*btcec.PublicKey{aPub, bPub}, true, muSig2Opt,
93✔
216
        )
93✔
217
        if err != nil {
93✔
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)
93✔
224
        if err != nil {
93✔
225
                return nil, nil, fmt.Errorf("unable to make taproot "+
×
226
                        "pkscript: %w", err)
×
227
        }
×
228

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

93✔
231
        // For the "witness program" we just return the raw pkScript since the
93✔
232
        // output we create can _only_ be spent with a MuSig2 signature.
93✔
233
        return pkScript, txOut, nil
93✔
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 {
146✔
240

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

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

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

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

146✔
262
        return witness
146✔
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) {
89✔
271
        found := false
89✔
272
        index := uint32(0)
89✔
273
        for i, txOut := range tx.TxOut {
212✔
274
                if bytes.Equal(txOut.PkScript, script) {
210✔
275
                        found = true
87✔
276
                        index = uint32(i)
87✔
277
                        break
87✔
278
                }
×
279
        }
×
280

×
281
        return found, index
89✔
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 {
8,872✔
289
        h := ripemd160.New()
8,872✔
290
        h.Write(d)
8,872✔
291
        return h.Sum(nil)
8,872✔
292
}
8,872✔
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) {
3,992✔
335

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

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

×
371
        // Close out the top level if statement.
×
372
        scriptTemplate += ` OP_ENDIF`
3,992✔
373

3,992✔
374
        // Use the ScriptTemplate function with the properly formatted template
3,992✔
375
        return txscript.ScriptTemplate(
3,992✔
376
                scriptTemplate,
3,992✔
377
                txscript.WithScriptTemplateParams(TemplateParams{
3,992✔
378
                        "RevKeyHash":        btcutil.Hash160(revocationKey.SerializeCompressed()), //nolint:ll
3,992✔
379
                        "ReceiverKey":       receiverHtlcKey.SerializeCompressed(),                //nolint:ll
3,992✔
380
                        "SenderKey":         senderHtlcKey.SerializeCompressed(),                  //nolint:ll
3,992✔
381
                        "PaymentHashRipemd": Ripemd160H(paymentHash),
3,992✔
382
                }),
3,992✔
383
        )
3,992✔
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,
×
394
        revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
5✔
395

5✔
396
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
5✔
397
        if err != nil {
5✔
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.
×
406
        witnessStack := wire.TxWitness(make([][]byte, 3))
5✔
407
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
5✔
408
        witnessStack[1] = revokeKey.SerializeCompressed()
5✔
409
        witnessStack[2] = signDesc.WitnessScript
5✔
410

5✔
411
        return witnessStack, nil
5✔
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,
×
422
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
4✔
423

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

429
        return SenderHtlcSpendRevokeWithKey(signer, signDesc, revokeKey, sweepTx)
4✔
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 {
4✔
441
                return len(txIn.Witness) == 1, nil
×
442
        }
×
443

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

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

2✔
452
                return true, nil
2✔
453
        }
2✔
454

×
455
        return false, nil
2✔
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) {
11✔
465

11✔
466
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
11✔
467
        if err != nil {
11✔
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))
11✔
475
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
11✔
476
        witnessStack[1] = paymentPreimage
11✔
477
        witnessStack[2] = signDesc.WitnessScript
11✔
478

11✔
479
        return witnessStack, nil
11✔
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) {
53✔
490

53✔
491
        sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
53✔
492
        if err != nil {
53✔
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))
53✔
501
        witnessStack[0] = nil
53✔
502
        witnessStack[1] = append(receiverSig.Serialize(), byte(receiverSigHash))
53✔
503
        witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType))
53✔
504
        witnessStack[3] = nil
53✔
505
        witnessStack[4] = signDesc.WitnessScript
53✔
506

53✔
507
        return witnessStack, nil
53✔
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) {
155✔
519

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

×
533
        return txscript.NewBaseTapLeaf(timeoutLeafScript), nil
155✔
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) {
155✔
547

155✔
548
        opt := defaultTaprootScriptOpt()
155✔
549
        for _, o := range opts {
157✔
550
                o(opt)
2✔
551
        }
2✔
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
155✔
556
        switch {
155✔
557
        case opt.prodScript:
2✔
558
                scriptTemplate = `
2✔
559
                OP_SIZE 32 OP_EQUALVERIFY
2✔
560
                OP_HASH160 {{ hex .PaymentHashRipemd }} OP_EQUALVERIFY
2✔
561
                {{ hex .ReceiverKey }} OP_CHECKSIGVERIFY
2✔
562
                OP_1 OP_CHECKSEQUENCEVERIFY`
2✔
563
        default:
153✔
564
                scriptTemplate = `
153✔
565
                OP_SIZE 32 OP_EQUALVERIFY
153✔
566
                OP_HASH160 {{ hex .PaymentHashRipemd }} OP_EQUALVERIFY
153✔
567
                {{ hex .ReceiverKey }} OP_CHECKSIG
153✔
568
                OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP`
153✔
569
        }
×
570

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

584
        return txscript.NewBaseTapLeaf(successLeafScript), nil
155✔
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 {
263✔
634
        switch h.htlcType {
263✔
635
        // For incoming HLTCs on our local commitment, we care about verifying
636
        // the success path.
637
        case htlcLocalIncoming:
58✔
638
                return h.SuccessTapLeaf.Script
58✔
639

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

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

650
        // For outgoing HTLCs on the remote party's commitment, we want to sign
651
        // the success path for them.
652
        case htlcRemoteOutgoing:
63✔
653
                return h.SuccessTapLeaf.Script
63✔
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) {
8✔
663
        switch path {
8✔
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) {
×
677

×
678
        switch path {
×
679
        case ScriptPathSuccess:
×
680
                return lnutils.Ptr(MakeTaprootCtrlBlock(
×
681
                        h.SuccessTapLeaf.Script, h.InternalKey,
×
682
                        h.TapscriptTree,
×
683
                )), nil
×
684
        case ScriptPathTimeout:
×
685
                return lnutils.Ptr(MakeTaprootCtrlBlock(
×
686
                        h.TimeoutTapLeaf.Script, h.InternalKey,
×
687
                        h.TapscriptTree,
×
688
                )), nil
×
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) {
154✔
709

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

725
        tapLeaves := []txscript.TapLeaf{successTapLeaf, timeoutTapLeaf}
154✔
726
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
156✔
727
                tapLeaves = append(tapLeaves, l)
2✔
728
        })
2✔
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...)
154✔
733

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

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

154✔
742
        return &HtlcScriptTree{
154✔
743
                ScriptTree: ScriptTree{
154✔
744
                        TaprootKey:    htlcKey,
154✔
745
                        TapscriptTree: tapscriptTree,
154✔
746
                        TapscriptRoot: tapScriptRoot[:],
154✔
747
                        InternalKey:   revokeKey,
154✔
748
                },
154✔
749
                SuccessTapLeaf: successTapLeaf,
154✔
750
                TimeoutTapLeaf: timeoutTapLeaf,
154✔
751
                AuxLeaf:        auxLeaf,
154✔
752
                htlcType:       hType,
154✔
753
        }, nil
154✔
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) (*HtlcScriptTree,
787
        error) {
150✔
788

150✔
789
        var hType htlcType
150✔
790
        if whoseCommit.IsLocal() {
222✔
791
                hType = htlcLocalOutgoing
72✔
792
        } else {
150✔
793
                hType = htlcRemoteIncoming
78✔
794
        }
78✔
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(
150✔
800
                senderHtlcKey, receiverHtlcKey, revokeKey, payHash, hType,
150✔
801
                auxLeaf,
150✔
802
        )
150✔
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 {
1,667✔
808
        sigBytes := sig.Serialize()
1,667✔
809
        if sigHash == txscript.SigHashDefault {
3,119✔
810
                return sigBytes
1,452✔
811
        }
1,452✔
812

813
        return append(sigBytes, byte(sigHash))
215✔
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) {
17✔
823

17✔
824
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
17✔
825
        if err != nil {
17✔
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
17✔
832
        if signDesc.ControlBlock == nil {
34✔
833
                successControlBlock := MakeTaprootCtrlBlock(
17✔
834
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
17✔
835
                )
17✔
836

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

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

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

17✔
855
        return witnessStack, nil
17✔
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) {
26✔
867

26✔
868
        sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
26✔
869
        if err != nil {
26✔
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
26✔
876
        if signDesc.ControlBlock == nil {
52✔
877
                timeoutControlBlock := MakeTaprootCtrlBlock(
26✔
878
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
26✔
879
                )
26✔
880
                ctrlBytes, err := timeoutControlBlock.ToBytes()
26✔
881
                if err != nil {
26✔
882
                        return nil, err
×
883
                }
×
884

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

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

26✔
898
        return witnessStack, nil
26✔
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) {
17✔
906

17✔
907
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
17✔
908
        if err != nil {
17✔
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)
17✔
915
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
17✔
916

17✔
917
        return witnessStack, nil
17✔
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,431✔
960

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

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

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

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

58✔
1027
        // First, we'll generate a signature for the HTLC success transaction.
58✔
1028
        // The signDesc should be signing with the public key used as the
58✔
1029
        // receiver's public key and also the correct single tweak.
58✔
1030
        sweepSig, err := signer.SignOutputRaw(htlcSuccessTx, signDesc)
58✔
1031
        if err != nil {
58✔
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))
58✔
1040
        witnessStack[0] = nil
58✔
1041
        witnessStack[1] = append(senderSig.Serialize(), byte(senderSigHash))
58✔
1042
        witnessStack[2] = append(sweepSig.Serialize(), byte(signDesc.HashType))
58✔
1043
        witnessStack[3] = paymentPreimage
58✔
1044
        witnessStack[4] = signDesc.WitnessScript
58✔
1045

58✔
1046
        return witnessStack, nil
58✔
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,
×
1054
        revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
24✔
1055

24✔
1056
        // First, we'll generate a signature for the sweep transaction.  The
24✔
1057
        // signDesc should be signing with the public key used as the fully
24✔
1058
        // derived revocation public key and also the correct double tweak
24✔
1059
        // value.
24✔
1060
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
24✔
1061
        if err != nil {
24✔
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.
×
1068
        witnessStack := wire.TxWitness(make([][]byte, 3))
24✔
1069
        witnessStack[0] = append(sweepSig.Serialize(), byte(signDesc.HashType))
24✔
1070
        witnessStack[1] = revokeKey.SerializeCompressed()
24✔
1071
        witnessStack[2] = signDesc.WitnessScript
24✔
1072

24✔
1073
        return witnessStack, nil
24✔
1074
}
×
1075

×
1076
func deriveRevokePubKey(signDesc *SignDescriptor) (*btcec.PublicKey, error) {
31✔
1077
        if signDesc.KeyDesc.PubKey == nil {
31✔
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.
×
1084
        revokeKey := DeriveRevocationPubkey(
31✔
1085
                signDesc.KeyDesc.PubKey,
31✔
1086
                signDesc.DoubleTweak.PubKey(),
31✔
1087
        )
31✔
1088

31✔
1089
        return revokeKey, nil
31✔
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,
×
1100
        sweepTx *wire.MsgTx) (wire.TxWitness, error) {
23✔
1101

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

×
1107
        return ReceiverHtlcSpendRevokeWithKey(signer, signDesc, revokeKey, sweepTx)
23✔
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) {
8✔
1121

8✔
1122
        // If the caller set a proper timeout value, then we'll apply it
8✔
1123
        // directly to the transaction.
8✔
1124
        if cltvExpiry != -1 {
16✔
1125
                // The HTLC output has an absolute time period before we are
8✔
1126
                // permitted to recover the pending funds. Therefore we need to
8✔
1127
                // set the locktime on this sweeping transaction in order to
8✔
1128
                // pass Script verification.
8✔
1129
                sweepTx.LockTime = uint32(cltvExpiry)
8✔
1130
        }
8✔
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)
8✔
1138
        if err != nil {
8✔
1139
                return nil, err
×
1140
        }
×
1141

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

8✔
1147
        return witnessStack, nil
8✔
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) {
134✔
1159

134✔
1160
        opt := defaultTaprootScriptOpt()
134✔
1161
        for _, o := range opts {
136✔
1162
                o(opt)
2✔
1163
        }
2✔
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
134✔
1169
        switch {
134✔
1170
        case opt.prodScript:
2✔
1171
                scriptTemplate = `
2✔
1172
                {{ hex .SenderKey }} OP_CHECKSIGVERIFY
2✔
1173
                OP_1 OP_CHECKSEQUENCEVERIFY OP_VERIFY
2✔
1174
                {{ .CltvExpiry }} OP_CHECKLOCKTIMEVERIFY`
2✔
1175
        default:
132✔
1176
                scriptTemplate = `
132✔
1177
                {{ hex .SenderKey }} OP_CHECKSIG
132✔
1178
                OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP
132✔
1179
                {{ .CltvExpiry }} OP_CHECKLOCKTIMEVERIFY OP_DROP`
132✔
1180
        }
×
1181

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

1193
        return txscript.NewBaseTapLeaf(timeoutLeafScript), nil
134✔
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) {
134✔
1208

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

1227
        return txscript.NewBaseTapLeaf(successLeafScript), nil
134✔
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) {
133✔
1236

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

×
1252
        tapLeaves := []txscript.TapLeaf{timeoutTapLeaf, successTapLeaf}
133✔
1253
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
135✔
1254
                tapLeaves = append(tapLeaves, l)
2✔
1255
        })
2✔
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...)
133✔
1260

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

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

133✔
1269
        return &HtlcScriptTree{
133✔
1270
                ScriptTree: ScriptTree{
133✔
1271
                        TaprootKey:    htlcKey,
133✔
1272
                        TapscriptTree: tapscriptTree,
133✔
1273
                        TapscriptRoot: tapScriptRoot[:],
133✔
1274
                        InternalKey:   revokeKey,
133✔
1275
                },
133✔
1276
                SuccessTapLeaf: successTapLeaf,
133✔
1277
                TimeoutTapLeaf: timeoutTapLeaf,
133✔
1278
                AuxLeaf:        auxLeaf,
133✔
1279
                htlcType:       hType,
133✔
1280
        }, nil
133✔
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) (*HtlcScriptTree, error) {
129✔
1315

129✔
1316
        var hType htlcType
129✔
1317
        if whoseCommit.IsLocal() {
191✔
1318
                hType = htlcLocalIncoming
62✔
1319
        } else {
129✔
1320
                hType = htlcRemoteOutgoing
67✔
1321
        }
67✔
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(
129✔
1327
                senderHtlcKey, receiverHtlcKey, revocationKey, payHash,
129✔
1328
                cltvExpiry, hType, auxLeaf,
129✔
1329
        )
129✔
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) {
34✔
1340

34✔
1341
        // First, we'll generate a signature for the HTLC success transaction.
34✔
1342
        // The signDesc should be signing with the public key used as the
34✔
1343
        // receiver's public key and also the correct single tweak.
34✔
1344
        sweepSig, err := signer.SignOutputRaw(htlcSuccessTx, signDesc)
34✔
1345
        if err != nil {
34✔
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
34✔
1352
        if signDesc.ControlBlock == nil {
68✔
1353
                redeemControlBlock := MakeTaprootCtrlBlock(
34✔
1354
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
34✔
1355
                )
34✔
1356
                ctrlBytes, err := redeemControlBlock.ToBytes()
34✔
1357
                if err != nil {
34✔
1358
                        return nil, err
×
1359
                }
×
1360

1361
                ctrlBlock = ctrlBytes
34✔
1362
        } else {
×
1363
                ctrlBlock = signDesc.ControlBlock
×
1364
        }
×
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))
34✔
1370
        witnessStack[0] = maybeAppendSighash(senderSig, senderSigHash)
34✔
1371
        witnessStack[1] = maybeAppendSighash(sweepSig, signDesc.HashType)
34✔
1372
        witnessStack[2] = paymentPreimage
34✔
1373
        witnessStack[3] = signDesc.WitnessScript
34✔
1374
        witnessStack[4] = ctrlBlock
34✔
1375

34✔
1376
        return witnessStack, nil
34✔
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) {
25✔
1385

25✔
1386
        // If the caller set a proper timeout value, then we'll apply it
25✔
1387
        // directly to the transaction.
25✔
1388
        //
25✔
1389
        // TODO(roasbeef): helper func
25✔
1390
        if cltvExpiry != -1 {
50✔
1391
                // The HTLC output has an absolute time period before we are
25✔
1392
                // permitted to recover the pending funds. Therefore we need to
25✔
1393
                // set the locktime on this sweeping transaction in order to
25✔
1394
                // pass Script verification.
25✔
1395
                sweepTx.LockTime = uint32(cltvExpiry)
25✔
1396
        }
25✔
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)
25✔
1404
        if err != nil {
25✔
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
25✔
1411
        if signDesc.ControlBlock == nil {
50✔
1412
                timeoutControlBlock := MakeTaprootCtrlBlock(
25✔
1413
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
25✔
1414
                )
25✔
1415
                ctrlBlock, err = timeoutControlBlock.ToBytes()
25✔
1416
                if err != nil {
25✔
1417
                        return nil, err
×
1418
                }
×
1419
        } else {
×
1420
                ctrlBlock = signDesc.ControlBlock
×
1421
        }
×
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)
25✔
1426
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
25✔
1427
        witnessStack[1] = signDesc.WitnessScript
25✔
1428
        witnessStack[2] = ctrlBlock
25✔
1429

25✔
1430
        return witnessStack, nil
25✔
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) {
9✔
1438

9✔
1439
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
9✔
1440
        if err != nil {
9✔
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)
9✔
1447
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
9✔
1448

9✔
1449
        return witnessStack, nil
9✔
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) {
8,072✔
1483

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

220✔
1515
        opt := defaultTaprootScriptOpt()
220✔
1516
        for _, o := range opts {
222✔
1517
                o(opt)
2✔
1518
        }
2✔
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
220✔
1525
        switch {
220✔
1526
        case opt.prodScript:
2✔
1527
                scriptTemplate = `
2✔
1528
                {{ hex .DelayKey }} OP_CHECKSIGVERIFY
2✔
1529
                {{ .CsvDelay }} OP_CHECKSEQUENCEVERIFY`
2✔
1530
        default:
218✔
1531
                scriptTemplate = `
218✔
1532
                {{ hex .DelayKey }} OP_CHECKSIG
218✔
1533
                {{ .CsvDelay }} OP_CHECKSEQUENCEVERIFY OP_DROP`
218✔
1534
        }
1535

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

1547
        return txscript.NewBaseTapLeaf(secondLevelLeafScript), nil
220✔
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,
×
1554
        opts ...TaprootScriptOpt) (*txscript.IndexedTapScriptTree, error) {
219✔
1555

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

×
1565
        tapLeaves := []txscript.TapLeaf{secondLevelTapLeaf}
219✔
1566
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
221✔
1567
                tapLeaves = append(tapLeaves, l)
2✔
1568
        })
2✔
1569

×
1570
        // Now that we have the sole second level script, we can create the
×
1571
        // tapscript tree that commits to both the leaves.
×
1572
        return txscript.AssembleTaprootScriptTree(tapLeaves...), nil
219✔
1573
}
×
1574

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

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

×
1603
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
×
1604

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

×
1612
        return redemptionKey, nil
×
1613
}
×
1614

×
1615
// SecondLevelScriptTree is a tapscript tree used to spend the second level
×
1616
// HTLC output after the CSV delay has passed.
×
1617
type SecondLevelScriptTree struct {
×
1618
        ScriptTree
1619

×
1620
        // SuccessTapLeaf is the tapleaf for the redemption path.
1621
        SuccessTapLeaf txscript.TapLeaf
1622

1623
        // AuxLeaf is an optional leaf that can be used to extend the script
1624
        // tree.
1625
        AuxLeaf AuxTapLeaf
×
1626
}
×
1627

×
1628
// TaprootSecondLevelScriptTree constructs the tapscript tree used to spend the
×
1629
// second level HTLC output.
×
1630
func TaprootSecondLevelScriptTree(revokeKey, delayKey *btcec.PublicKey,
×
1631
        csvDelay uint32, auxLeaf AuxTapLeaf) (*SecondLevelScriptTree, error) {
213✔
1632

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

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

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

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

×
1669
// WitnessScriptForPath returns the witness script for the given spending path.
×
1670
// An error is returned if the path is unknown.
×
1671
func (s *SecondLevelScriptTree) WitnessScriptForPath(
1672
        path ScriptPath) ([]byte, error) {
8✔
1673

8✔
1674
        switch path {
8✔
1675
        case ScriptPathDelay:
×
1676
                fallthrough
×
1677
        case ScriptPathSuccess:
8✔
1678
                return s.SuccessTapLeaf.Script, nil
8✔
1679

×
1680
        default:
×
1681
                return nil, fmt.Errorf("unknown script path: %v", path)
×
1682
        }
1683
}
1684

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

8✔
1690
        switch path {
8✔
1691
        case ScriptPathDelay:
×
1692
                fallthrough
×
1693
        case ScriptPathSuccess:
8✔
1694
                return lnutils.Ptr(MakeTaprootCtrlBlock(
8✔
1695
                        s.SuccessTapLeaf.Script, s.InternalKey,
8✔
1696
                        s.TapscriptTree,
8✔
1697
                )), nil
8✔
1698

1699
        default:
×
1700
                return nil, fmt.Errorf("unknown script path: %v", path)
×
1701
        }
×
1702
}
×
1703

×
1704
// Tree returns the underlying ScriptTree of the SecondLevelScriptTree.
×
1705
func (s *SecondLevelScriptTree) Tree() ScriptTree {
×
1706
        return s.ScriptTree
×
1707
}
×
1708

×
1709
// A compile time check to ensure SecondLevelScriptTree implements the
×
1710
// TapscriptDescriptor interface.
1711
var _ TapscriptDescriptor = (*SecondLevelScriptTree)(nil)
1712

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

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

1730
        // The witness stack in this case is pretty simple: we only need to
1731
        // specify the signature generated.
1732
        witnessStack := make(wire.TxWitness, 1)
17✔
1733
        witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
17✔
1734

17✔
1735
        return witnessStack, nil
17✔
1736
}
×
1737

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

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

1755
        var ctrlBlock []byte
25✔
1756
        if signDesc.ControlBlock == nil {
46✔
1757
                // Now that we have the sweep signature, we'll construct the
21✔
1758
                // control block needed to spend the script path.
21✔
1759
                redeemControlBlock := MakeTaprootCtrlBlock(
21✔
1760
                        signDesc.WitnessScript, revokeKey, tapscriptTree,
21✔
1761
                )
21✔
1762

21✔
1763
                ctrlBlock, err = redeemControlBlock.ToBytes()
21✔
1764
                if err != nil {
21✔
1765
                        return nil, err
×
1766
                }
×
1767
        } else {
4✔
1768
                ctrlBlock = signDesc.ControlBlock
4✔
1769
        }
4✔
1770

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

25✔
1780
        return witnessStack, nil
25✔
1781
}
1782

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

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

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

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

11✔
1847
        // Finally, OP_CSV requires that the version of the transaction
11✔
1848
        // spending a pkscript with OP_CSV within it *must* be >= 2.
11✔
1849
        sweepTx.Version = 2
11✔
1850

11✔
1851
        // As we mutated the transaction, we'll re-calculate the sighashes for
11✔
1852
        // this instance.
11✔
1853
        signDesc.SigHashes = NewTxSigHashesV0Only(sweepTx)
11✔
1854

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

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

11✔
1872
        return witnessStack, nil
11✔
1873
}
1874

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

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

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

14✔
1897
        return witnessStack, nil
14✔
1898
}
×
1899

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

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

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

×
1928
        return witnessStack, nil
×
1929
}
1930

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

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

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

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

1999
        // SettleLeaf is the leaf used to settle the output after the delay.
2000
        SettleLeaf txscript.TapLeaf
2001

2002
        // RevocationLeaf is the leaf used to spend the output with the
×
2003
        // revocation key signature.
×
2004
        RevocationLeaf txscript.TapLeaf
×
2005

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

2013
// A compile time check to ensure CommitScriptTree implements the
2014
// TapscriptDescriptor interface.
2015
var _ TapscriptDescriptor = (*CommitScriptTree)(nil)
2016

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

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

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

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

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

×
2068
// Tree returns the underlying ScriptTree of the CommitScriptTree.
×
2069
func (c *CommitScriptTree) Tree() ScriptTree {
×
2070
        return c.ScriptTree
×
2071
}
×
2072

×
2073
// taprootScriptOpts is a set of options that modify the behavior of the way we
×
2074
// create taproot scripts.
×
2075
type taprootScriptOpts struct {
×
2076
        prodScript bool
×
2077
}
×
2078

×
2079
// TaprootScriptOpt is a functional option that allows us to modify the behavior
×
2080
// of the taproot script creation.
×
2081
type TaprootScriptOpt func(*taprootScriptOpts)
×
2082

×
2083
// defaultTaprootScriptOpt is the default set of options that we use when
×
2084
// creating taproot scripts.
×
2085
func defaultTaprootScriptOpt() *taprootScriptOpts {
3,391✔
2086
        return &taprootScriptOpts{
3,391✔
2087
                prodScript: false,
3,391✔
2088
        }
3,391✔
2089
}
3,391✔
2090

×
2091
// WithProdScripts is a functional option that allows us to create scripts to
×
2092
// match the final version of the taproot channels.
×
2093
func WithProdScripts() func(*taprootScriptOpts) {
10✔
2094
        return func(o *taprootScriptOpts) {
20✔
2095
                o.prodScript = true
10✔
2096
        }
10✔
2097
}
2098

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

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

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

2123
        // With both scripts computed, we'll now create a tapscript tree with
2124
        // the two leaves, and then obtain a root from that.
×
2125
        delayTapLeaf := txscript.NewBaseTapLeaf(delayScript)
1,790✔
2126
        revokeTapLeaf := txscript.NewBaseTapLeaf(revokeScript)
1,790✔
2127

1,790✔
2128
        tapLeaves := []txscript.TapLeaf{delayTapLeaf, revokeTapLeaf}
1,790✔
2129
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
1,792✔
2130
                tapLeaves = append(tapLeaves, l)
2✔
2131
        })
2✔
2132

×
2133
        tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
1,790✔
2134
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
1,790✔
2135

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

1,790✔
2142
        return &CommitScriptTree{
1,790✔
2143
                ScriptTree: ScriptTree{
1,790✔
2144
                        TaprootKey:    toLocalOutputKey,
1,790✔
2145
                        TapscriptTree: tapScriptTree,
1,790✔
2146
                        TapscriptRoot: tapScriptRoot[:],
1,790✔
2147
                        InternalKey:   &TaprootNUMSKey,
1,790✔
2148
                },
1,790✔
2149
                SettleLeaf:     delayTapLeaf,
1,790✔
2150
                RevocationLeaf: revokeTapLeaf,
1,790✔
2151
                AuxLeaf:        auxLeaf,
1,790✔
2152
        }, nil
1,790✔
2153
}
×
2154

×
2155
// TaprootLocalCommitDelayScript builds the tap leaf with the CSV delay script
×
2156
// for the to-local output.
×
2157
func TaprootLocalCommitDelayScript(csvTimeout uint32,
×
2158
        selfKey *btcec.PublicKey, opts ...TaprootScriptOpt) ([]byte, error) {
1,791✔
2159

1,791✔
2160
        opt := defaultTaprootScriptOpt()
1,791✔
2161
        for _, o := range opts {
1,793✔
2162
                o(opt)
2✔
2163
        }
2✔
2164

×
2165
        var scriptTemplate string
1,791✔
2166
        switch {
1,791✔
2167
        case opt.prodScript:
2✔
2168
                scriptTemplate = `
2✔
2169
                {{ hex .SelfKey }} OP_CHECKSIGVERIFY
2✔
2170
                {{ .CsvTimeout }} OP_CHECKSEQUENCEVERIFY`
2✔
2171
        default:
1,789✔
2172
                scriptTemplate = `
1,789✔
2173
                {{ hex .SelfKey }} OP_CHECKSIG
1,789✔
2174
                {{ .CsvTimeout }} OP_CHECKSEQUENCEVERIFY OP_DROP`
1,789✔
2175
        }
2176

2177
        return txscript.ScriptTemplate(
1,791✔
2178
                scriptTemplate,
1,791✔
2179
                txscript.WithScriptTemplateParams(TemplateParams{
1,791✔
2180
                        "SelfKey":    schnorr.SerializePubKey(selfKey),
1,791✔
2181
                        "CsvTimeout": int64(csvTimeout),
1,791✔
2182
                }),
1,791✔
2183
        )
1,791✔
2184
}
×
2185

×
2186
// TaprootLocalCommitRevokeScript builds the tap leaf with the revocation path
×
2187
// for the to-local output.
×
2188
func TaprootLocalCommitRevokeScript(selfKey, revokeKey *btcec.PublicKey,
2189
        _ ...TaprootScriptOpt) ([]byte, error) {
1,793✔
2190

1,793✔
2191
        return txscript.ScriptTemplate(
1,793✔
2192
                `
1,793✔
2193
                {{ hex .SelfKey }} OP_DROP 
1,793✔
2194
                {{ hex .RevokeKey }} OP_CHECKSIG`,
1,793✔
2195
                txscript.WithScriptTemplateParams(TemplateParams{
1,793✔
2196
                        "SelfKey":   schnorr.SerializePubKey(selfKey),
1,793✔
2197
                        "RevokeKey": schnorr.SerializePubKey(revokeKey),
1,793✔
2198
                }),
1,793✔
2199
        )
1,793✔
2200
}
1,793✔
2201

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

×
2238
        commitScriptTree, err := NewLocalCommitScriptTree(
×
2239
                csvTimeout, selfKey, revokeKey, NoneTapLeaf(),
×
2240
        )
×
2241
        if err != nil {
×
2242
                return nil, err
×
2243
        }
×
2244

2245
        return commitScriptTree.TaprootKey, nil
×
2246
}
×
2247

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

200✔
2254
        tapLeafHash := txscript.NewBaseTapLeaf(leafScript).TapHash()
200✔
2255
        scriptIdx := scriptTree.LeafProofIndex[tapLeafHash]
200✔
2256
        settleMerkleProof := scriptTree.LeafMerkleProofs[scriptIdx]
200✔
2257

200✔
2258
        return settleMerkleProof.ToControlBlock(internalKey)
200✔
2259
}
200✔
2260

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

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

2284
                ctrlBlockBytes = ctrlBytes
21✔
2285
        } else {
×
2286
                ctrlBlockBytes = signDesc.ControlBlock
×
2287
        }
×
2288

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

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

21✔
2304
        return witnessStack, nil
21✔
2305
}
2306

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

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

×
2325
                ctrlBlockBytes = revokeBytes
17✔
2326
        } else {
685✔
2327
                ctrlBlockBytes = signDesc.ControlBlock
685✔
2328
        }
685✔
2329

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

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

702✔
2345
        return witnessStack, nil
702✔
2346
}
×
2347

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

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

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

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

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

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

6✔
2431
        return witnessStack, nil
6✔
2432
}
×
2433

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

31✔
2444
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
31✔
2445
        if err != nil {
31✔
2446
                return nil, err
×
2447
        }
×
2448

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

31✔
2456
        return witnessStack, nil
31✔
2457
}
×
2458

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

31✔
2470
        if signDesc.KeyDesc.PubKey == nil {
31✔
2471
                return nil, fmt.Errorf("cannot generate witness with nil " +
×
2472
                        "KeyDesc pubkey")
×
2473
        }
×
2474

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

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

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

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

2503
        return witness, nil
31✔
2504
}
2505

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

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

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

1,091✔
2549
        opt := defaultTaprootScriptOpt()
1,091✔
2550
        for _, o := range opts {
1,093✔
2551
                o(opt)
2✔
2552
        }
2✔
2553

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

2568
        remoteScript, err := txscript.ScriptTemplate(
1,091✔
2569
                scriptTemplate,
1,091✔
2570
                txscript.WithScriptTemplateParams(TemplateParams{
1,091✔
2571
                        "RemoteKey": schnorr.SerializePubKey(remoteKey),
1,091✔
2572
                }),
1,091✔
2573
        )
1,091✔
2574
        if err != nil {
1,091✔
2575
                return nil, err
×
2576
        }
×
2577

2578
        tapLeaf := txscript.NewBaseTapLeaf(remoteScript)
1,091✔
2579

1,091✔
2580
        tapLeaves := []txscript.TapLeaf{tapLeaf}
1,091✔
2581
        auxLeaf.WhenSome(func(l txscript.TapLeaf) {
1,093✔
2582
                tapLeaves = append(tapLeaves, l)
2✔
2583
        })
2✔
2584

×
2585
        // With this script constructed, we'll map that into a tapLeaf, then
×
2586
        // make a new tapscript root from that.
×
2587
        tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
1,091✔
2588
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
1,091✔
2589

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

1,091✔
2596
        return &CommitScriptTree{
1,091✔
2597
                ScriptTree: ScriptTree{
1,091✔
2598
                        TaprootKey:    toRemoteOutputKey,
1,091✔
2599
                        TapscriptTree: tapScriptTree,
1,091✔
2600
                        TapscriptRoot: tapScriptRoot[:],
1,091✔
2601
                        InternalKey:   &TaprootNUMSKey,
1,091✔
2602
                },
1,091✔
2603
                SettleLeaf: tapLeaf,
1,091✔
2604
                AuxLeaf:    auxLeaf,
1,091✔
2605
        }, nil
1,091✔
2606
}
×
2607

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

×
2623
        commitScriptTree, err := NewRemoteCommitScriptTree(remoteKey, auxLeaf)
×
2624
        if err != nil {
×
2625
                return nil, err
×
2626
        }
×
2627

×
2628
        return commitScriptTree.TaprootKey, nil
×
2629
}
×
2630

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

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

×
2649
                ctrlBlockBytes = ctrlBytes
25✔
2650
        } else {
684✔
2651
                ctrlBlockBytes = signDesc.ControlBlock
684✔
2652
        }
684✔
2653

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

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

709✔
2669
        return witnessStack, nil
709✔
2670
}
2671

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

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

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

12✔
2709
        if signDesc.KeyDesc.PubKey == nil {
12✔
2710
                return nil, fmt.Errorf("cannot generate witness with nil " +
×
2711
                        "KeyDesc pubkey")
×
2712
        }
×
2713

2714
        // Similar to non delayed output, only a signature is needed.
×
2715
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
12✔
2716
        if err != nil {
12✔
2717
                return nil, err
×
2718
        }
×
2719

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

12✔
2726
        return witnessStack, nil
12✔
2727
}
×
2728

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

×
2760
// AnchorScriptTree holds all the contents needed to sweep a taproot anchor
×
2761
// output on chain.
×
2762
type AnchorScriptTree struct {
×
2763
        ScriptTree
×
2764

×
2765
        // SweepLeaf is the leaf used to settle the output after the delay.
2766
        SweepLeaf txscript.TapLeaf
2767
}
2768

2769
// NewAnchorScriptTree makes a new script tree for an anchor output with the
2770
// passed anchor key.
2771
func NewAnchorScriptTree(
×
2772
        anchorKey *btcec.PublicKey) (*AnchorScriptTree, error) {
746✔
2773

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

×
2783
        // With the script, we can make our sole leaf, then derive the root
2784
        // from that.
2785
        tapLeaf := txscript.NewBaseTapLeaf(anchorScript)
746✔
2786
        tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf)
746✔
2787
        tapScriptRoot := tapScriptTree.RootNode.TapHash()
746✔
2788

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

746✔
2795
        return &AnchorScriptTree{
746✔
2796
                ScriptTree: ScriptTree{
746✔
2797
                        TaprootKey:    anchorOutputKey,
746✔
2798
                        TapscriptTree: tapScriptTree,
746✔
2799
                        TapscriptRoot: tapScriptRoot[:],
746✔
2800
                        InternalKey:   anchorKey,
746✔
2801
                },
746✔
2802
                SweepLeaf: tapLeaf,
746✔
2803
        }, nil
746✔
2804
}
2805

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

×
2814
// WitnessScriptForPath returns the witness script for the given spending path.
×
2815
// An error is returned if the path is unknown.
×
2816
func (a *AnchorScriptTree) WitnessScriptForPath(
×
2817
        path ScriptPath) ([]byte, error) {
8✔
2818

8✔
2819
        switch path {
8✔
2820
        case ScriptPathDelay:
×
2821
                fallthrough
×
2822
        case ScriptPathSuccess:
8✔
2823
                return a.SweepLeaf.Script, nil
8✔
2824

×
2825
        default:
×
2826
                return nil, fmt.Errorf("unknown script path: %v", path)
×
2827
        }
2828
}
2829

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

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

×
2844
        default:
×
2845
                return nil, fmt.Errorf("unknown script path: %v", path)
×
2846
        }
×
2847
}
×
2848

×
2849
// Tree returns the underlying ScriptTree of the AnchorScriptTree.
×
2850
func (a *AnchorScriptTree) Tree() ScriptTree {
×
2851
        return a.ScriptTree
×
2852
}
×
2853

2854
// A compile time check to ensure AnchorScriptTree implements the
2855
// TapscriptDescriptor interface.
×
2856
var _ TapscriptDescriptor = (*AnchorScriptTree)(nil)
×
2857

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

×
2872
        return anchorScriptTree.TaprootKey, nil
×
2873
}
×
2874

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

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

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

5✔
2892
        return witnessStack, nil
5✔
2893
}
×
2894

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

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

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

×
2922
        return witnessStack, nil
2✔
2923
}
2924

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

2✔
2931
        if signDesc.KeyDesc.PubKey == nil {
2✔
2932
                return nil, fmt.Errorf("cannot generate witness with nil " +
×
2933
                        "KeyDesc pubkey")
×
2934
        }
×
2935

2936
        // Create a signature.
×
2937
        sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
2✔
2938
        if err != nil {
2✔
2939
                return nil, err
×
2940
        }
×
2941

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

2✔
2947
        return witnessStack, nil
2✔
2948
}
×
2949

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

3✔
2959
        return witnessStack, nil
3✔
2960
}
3✔
2961

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

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

×
3008
// TweakPubKeyWithTweak is the exact same as the TweakPubKey function, however
×
3009
// it accepts the raw tweak bytes directly rather than the commitment point.
×
3010
func TweakPubKeyWithTweak(pubKey *btcec.PublicKey,
×
3011
        tweakBytes []byte) *btcec.PublicKey {
50,301✔
3012

50,301✔
3013
        var (
50,301✔
3014
                pubKeyJacobian btcec.JacobianPoint
50,301✔
3015
                tweakJacobian  btcec.JacobianPoint
50,301✔
3016
                resultJacobian btcec.JacobianPoint
50,301✔
3017
        )
50,301✔
3018
        tweakKey, _ := btcec.PrivKeyFromBytes(tweakBytes)
50,301✔
3019
        btcec.ScalarBaseMultNonConst(&tweakKey.Key, &tweakJacobian)
50,301✔
3020

50,301✔
3021
        pubKey.AsJacobian(&pubKeyJacobian)
50,301✔
3022
        btcec.AddNonConst(&pubKeyJacobian, &tweakJacobian, &resultJacobian)
50,301✔
3023

50,301✔
3024
        resultJacobian.ToAffine()
50,301✔
3025
        return btcec.NewPublicKey(&resultJacobian.X, &resultJacobian.Y)
50,301✔
3026
}
50,301✔
3027

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

7,889✔
3041
        // tweakInt := sha256(commitPoint || basePub)
7,889✔
3042
        tweakScalar := new(btcec.ModNScalar)
7,889✔
3043
        tweakScalar.SetByteSlice(commitTweak)
7,889✔
3044

7,889✔
3045
        tweakScalar.Add(&basePriv.Key)
7,889✔
3046

7,889✔
3047
        return &btcec.PrivateKey{Key: *tweakScalar}
7,889✔
3048
}
7,889✔
3049

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

14,834✔
3079
        // R = revokeBase * sha256(revocationBase || commitPoint)
14,834✔
3080
        revokeTweakBytes := SingleTweakBytes(revokeBase, commitPoint)
14,834✔
3081
        revokeTweakScalar := new(btcec.ModNScalar)
14,834✔
3082
        revokeTweakScalar.SetByteSlice(revokeTweakBytes)
14,834✔
3083

14,834✔
3084
        var (
14,834✔
3085
                revokeBaseJacobian btcec.JacobianPoint
14,834✔
3086
                rJacobian          btcec.JacobianPoint
14,834✔
3087
        )
14,834✔
3088
        revokeBase.AsJacobian(&revokeBaseJacobian)
14,834✔
3089
        btcec.ScalarMultNonConst(
14,834✔
3090
                revokeTweakScalar, &revokeBaseJacobian, &rJacobian,
14,834✔
3091
        )
14,834✔
3092

14,834✔
3093
        // C = commitPoint * sha256(commitPoint || revocationBase)
14,834✔
3094
        commitTweakBytes := SingleTweakBytes(commitPoint, revokeBase)
14,834✔
3095
        commitTweakScalar := new(btcec.ModNScalar)
14,834✔
3096
        commitTweakScalar.SetByteSlice(commitTweakBytes)
14,834✔
3097

14,834✔
3098
        var (
14,834✔
3099
                commitPointJacobian btcec.JacobianPoint
14,834✔
3100
                cJacobian           btcec.JacobianPoint
14,834✔
3101
        )
14,834✔
3102
        commitPoint.AsJacobian(&commitPointJacobian)
14,834✔
3103
        btcec.ScalarMultNonConst(
14,834✔
3104
                commitTweakScalar, &commitPointJacobian, &cJacobian,
14,834✔
3105
        )
14,834✔
3106

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

14,834✔
3114
        resultJacobian.ToAffine()
14,834✔
3115
        return btcec.NewPublicKey(&resultJacobian.X, &resultJacobian.Y)
14,834✔
3116
}
14,834✔
3117

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

55✔
3133
        // r = sha256(revokeBasePub || commitPoint)
55✔
3134
        revokeTweakBytes := SingleTweakBytes(
55✔
3135
                revokeBasePriv.PubKey(), commitSecret.PubKey(),
55✔
3136
        )
55✔
3137
        revokeTweakScalar := new(btcec.ModNScalar)
55✔
3138
        revokeTweakScalar.SetByteSlice(revokeTweakBytes)
55✔
3139

55✔
3140
        // c = sha256(commitPoint || revokeBasePub)
55✔
3141
        commitTweakBytes := SingleTweakBytes(
55✔
3142
                commitSecret.PubKey(), revokeBasePriv.PubKey(),
55✔
3143
        )
55✔
3144
        commitTweakScalar := new(btcec.ModNScalar)
55✔
3145
        commitTweakScalar.SetByteSlice(commitTweakBytes)
55✔
3146

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

55✔
3159
        revocationPriv := revokeHalfPriv.Add(commitHalfPriv)
55✔
3160

55✔
3161
        return &btcec.PrivateKey{Key: *revocationPriv}
55✔
3162
}
55✔
3163

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

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

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

3192
        // Single OP_RETURN.
3193
        if len(script) == 1 {
14✔
3194
                return true
4✔
3195
        }
4✔
3196

3197
        // OP_RETURN followed by data push up to MaxDataCarrierSize bytes.
3198
        tokenizer := txscript.MakeScriptTokenizer(0, script[1:])
6✔
3199

6✔
3200
        return tokenizer.Next() && tokenizer.Done() &&
6✔
3201
                (txscript.IsSmallInt(tokenizer.Opcode()) ||
6✔
3202
                        tokenizer.Opcode() <= txscript.OP_PUSHDATA4) &&
6✔
3203
                len(tokenizer.Data()) <= txscript.MaxDataCarrierSize
6✔
3204
}
×
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