-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathtaproot.go
More file actions
98 lines (77 loc) · 2.38 KB
/
Copy pathtaproot.go
File metadata and controls
98 lines (77 loc) · 2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package psbtutil
import (
"bytes"
"fmt"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/psbt/v2"
"github.com/btcsuite/btcd/txscript/v2"
"github.com/lightninglabs/wavelength/lib/arkscript"
)
// AddTapLeafScript ensures the PSBT input includes the leaf script and
// control block for the collaborative VTXO leaf. If the leaf is already
// present the function is a no-op.
func AddTapLeafScript(in *psbt.PInput, spendInfo *arkscript.SpendInfo) error {
if in == nil {
return fmt.Errorf("psbt input must be provided")
}
if spendInfo == nil {
return fmt.Errorf("spend info must be provided")
}
needle := &psbt.TaprootTapLeafScript{
ControlBlock: spendInfo.ControlBlock,
Script: spendInfo.WitnessScript,
LeafVersion: txscript.BaseLeafVersion,
}
for i := range in.TaprootLeafScript {
existing := in.TaprootLeafScript[i]
if existing == nil {
continue
}
if bytes.Equal(existing.ControlBlock, needle.ControlBlock) &&
bytes.Equal(existing.Script, needle.Script) &&
existing.LeafVersion == needle.LeafVersion {
return nil
}
}
in.TaprootLeafScript = append(in.TaprootLeafScript, needle)
return nil
}
// AddTaprootScriptSpendSig adds or replaces a taproot script-path spend
// signature in the PSBT input, keyed by (x-only pubkey, leaf hash).
func AddTaprootScriptSpendSig(in *psbt.PInput, pubKey *btcec.PublicKey,
leafScript []byte, sig []byte, sigHash txscript.SigHashType) error {
switch {
case in == nil:
return fmt.Errorf("psbt input must be provided")
case pubKey == nil:
return fmt.Errorf("pubkey must be provided")
case len(leafScript) == 0:
return fmt.Errorf("leaf script must be provided")
case len(sig) == 0:
return fmt.Errorf("signature must be provided")
}
leafHash := txscript.NewBaseTapLeaf(leafScript).TapHash()
leafHashBytes := make([]byte, 0, len(leafHash))
leafHashBytes = append(leafHashBytes, leafHash[:]...)
needle := &psbt.TaprootScriptSpendSig{
XOnlyPubKey: schnorr.SerializePubKey(pubKey),
LeafHash: leafHashBytes,
Signature: sig,
SigHash: sigHash,
}
for i := range in.TaprootScriptSpendSig {
existing := in.TaprootScriptSpendSig[i]
if existing == nil {
continue
}
if existing.EqualKey(needle) {
in.TaprootScriptSpendSig[i] = needle
return nil
}
}
in.TaprootScriptSpendSig = append(
in.TaprootScriptSpendSig, needle,
)
return nil
}