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

lightningnetwork / lnd / 12284350326

11 Dec 2024 08:27PM UTC coverage: 57.485% (+7.9%) from 49.54%
12284350326

Pull #9348

github

ziggie1984
github: update goveralls tool
Pull Request #9348: github: update goveralls tool

101901 of 177264 relevant lines covered (57.49%)

24841.21 hits per line

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

53.17
/input/signdescriptor.go
1
package input
2

3
import (
4
        "encoding/binary"
5
        "errors"
6
        "fmt"
7
        "io"
8

9
        "github.com/btcsuite/btcd/btcec/v2"
10
        "github.com/btcsuite/btcd/txscript"
11
        "github.com/btcsuite/btcd/wire"
12
        "github.com/lightningnetwork/lnd/keychain"
13
)
14

15
var (
16
        // ErrTweakOverdose signals a SignDescriptor is invalid because both of its
17
        // SingleTweak and DoubleTweak are non-nil.
18
        ErrTweakOverdose = errors.New("sign descriptor should only have one tweak")
19
)
20

21
// SignDescriptor houses the necessary information required to successfully
22
// sign a given segwit output. This struct is used by the Signer interface in
23
// order to gain access to critical data needed to generate a valid signature.
24
type SignDescriptor struct {
25
        // KeyDesc is a descriptor that precisely describes *which* key to use
26
        // for signing. This may provide the raw public key directly, or
27
        // require the Signer to re-derive the key according to the populated
28
        // derivation path.
29
        KeyDesc keychain.KeyDescriptor
30

31
        // SingleTweak is a scalar value that will be added to the private key
32
        // corresponding to the above public key to obtain the private key to
33
        // be used to sign this input. This value is typically derived via the
34
        // following computation:
35
        //
36
        //  * derivedKey = privkey + sha256(perCommitmentPoint || pubKey) mod N
37
        //
38
        // NOTE: If this value is nil, then the input can be signed using only
39
        // the above public key. Either a SingleTweak should be set or a
40
        // DoubleTweak, not both.
41
        SingleTweak []byte
42

43
        // DoubleTweak is a private key that will be used in combination with
44
        // its corresponding private key to derive the private key that is to
45
        // be used to sign the target input. Within the Lightning protocol,
46
        // this value is typically the commitment secret from a previously
47
        // revoked commitment transaction. This value is in combination with
48
        // two hash values, and the original private key to derive the private
49
        // key to be used when signing.
50
        //
51
        //  * k = (privKey*sha256(pubKey || tweakPub) +
52
        //        tweakPriv*sha256(tweakPub || pubKey)) mod N
53
        //
54
        // NOTE: If this value is nil, then the input can be signed using only
55
        // the above public key. Either a SingleTweak should be set or a
56
        // DoubleTweak, not both.
57
        DoubleTweak *btcec.PrivateKey
58

59
        // TapTweak is a 32-byte value that will be used to derive a taproot
60
        // output public key (or the corresponding private key) from an
61
        // internal key and this tweak. The transformation applied is:
62
        //  * outputKey = internalKey +
63
        //        tagged_hash("tapTweak", internalKey || tapTweak)
64
        //
65
        // When attempting to sign an output derived via BIP 86, then this
66
        // field should be an empty byte array.
67
        //
68
        // When attempting to sign for the key spend path of an output key that
69
        // commits to an actual script tree, the script root should be used.
70
        TapTweak []byte
71

72
        // WitnessScript is the full script required to properly redeem the
73
        // output. This field should be set to the full script if a p2wsh
74
        // output is being signed. For p2wkh it should be set to the hashed
75
        // script (PkScript).
76
        WitnessScript []byte
77

78
        // SignMethod specifies how the input should be signed. Depending on the
79
        // selected method, either the TapTweak, WitnessScript or both need to
80
        // be specified.
81
        SignMethod SignMethod
82

83
        // Output is the target output which should be signed. The PkScript and
84
        // Value fields within the output should be properly populated,
85
        // otherwise an invalid signature may be generated.
86
        Output *wire.TxOut
87

88
        // HashType is the target sighash type that should be used when
89
        // generating the final sighash, and signature.
90
        HashType txscript.SigHashType
91

92
        // SigHashes is the pre-computed sighash midstate to be used when
93
        // generating the final sighash for signing.
94
        SigHashes *txscript.TxSigHashes
95

96
        // PrevOutputFetcher is an interface that can return the output
97
        // information on all UTXOs that are being spent in this transaction.
98
        // This MUST be set when spending Taproot outputs.
99
        PrevOutputFetcher txscript.PrevOutputFetcher
100

101
        // ControlBlock is a fully serialized control block that contains the
102
        // merkle proof necessary to spend a taproot output. This may
103
        // optionally be set if the SignMethod is
104
        // input.TaprootScriptSpendSignMethod. In which case, this should be an
105
        // inclusion proof for the WitnessScript.
106
        ControlBlock []byte
107

108
        // InputIndex is the target input within the transaction that should be
109
        // signed.
110
        InputIndex int
111
}
112

113
// SignMethod defines the different ways a signer can sign, given a specific
114
// input.
115
type SignMethod uint8
116

117
const (
118
        // WitnessV0SignMethod denotes that a SegWit v0 (p2wkh, np2wkh, p2wsh)
119
        // input script should be signed.
120
        WitnessV0SignMethod SignMethod = 0
121

122
        // TaprootKeySpendBIP0086SignMethod denotes that a SegWit v1 (p2tr)
123
        // input should be signed by using the BIP0086 method (commit to
124
        // internal key only).
125
        TaprootKeySpendBIP0086SignMethod SignMethod = 1
126

127
        // TaprootKeySpendSignMethod denotes that a SegWit v1 (p2tr)
128
        // input should be signed by using a given taproot hash to commit to in
129
        // addition to the internal key.
130
        TaprootKeySpendSignMethod SignMethod = 2
131

132
        // TaprootScriptSpendSignMethod denotes that a SegWit v1 (p2tr) input
133
        // should be spent using the script path and that a specific leaf script
134
        // should be signed for.
135
        TaprootScriptSpendSignMethod SignMethod = 3
136
)
137

138
// String returns a human-readable representation of the signing method.
139
func (s SignMethod) String() string {
3,917✔
140
        switch s {
3,917✔
141
        case WitnessV0SignMethod:
3,848✔
142
                return "witness_v0"
3,848✔
143
        case TaprootKeySpendBIP0086SignMethod:
×
144
                return "taproot_key_spend_bip86"
×
145
        case TaprootKeySpendSignMethod:
×
146
                return "taproot_key_spend"
×
147
        case TaprootScriptSpendSignMethod:
69✔
148
                return "taproot_script_spend"
69✔
149
        default:
×
150
                return fmt.Sprintf("unknown<%d>", s)
×
151
        }
152
}
153

154
// PkScriptCompatible returns true if the given public key script is compatible
155
// with the sign method.
156
func (s SignMethod) PkScriptCompatible(pkScript []byte) bool {
×
157
        switch s {
×
158
        // SegWit v0 can be p2wkh, np2wkh, p2wsh.
159
        case WitnessV0SignMethod:
×
160
                return txscript.IsPayToWitnessPubKeyHash(pkScript) ||
×
161
                        txscript.IsPayToWitnessScriptHash(pkScript) ||
×
162
                        txscript.IsPayToScriptHash(pkScript)
×
163

164
        case TaprootKeySpendBIP0086SignMethod, TaprootKeySpendSignMethod,
165
                TaprootScriptSpendSignMethod:
×
166

×
167
                return txscript.IsPayToTaproot(pkScript)
×
168

169
        default:
×
170
                return false
×
171
        }
172
}
173

174
// WriteSignDescriptor serializes a SignDescriptor struct into the passed
175
// io.Writer stream.
176
//
177
// NOTE: We assume the SigHashes and InputIndex fields haven't been assigned
178
// yet, since that is usually done just before broadcast by the witness
179
// generator.
180
func WriteSignDescriptor(w io.Writer, sd *SignDescriptor) error {
170✔
181
        err := binary.Write(w, binary.BigEndian, sd.KeyDesc.Family)
170✔
182
        if err != nil {
170✔
183
                return err
×
184
        }
×
185
        err = binary.Write(w, binary.BigEndian, sd.KeyDesc.Index)
170✔
186
        if err != nil {
170✔
187
                return err
×
188
        }
×
189

190
        err = binary.Write(w, binary.BigEndian, sd.KeyDesc.PubKey != nil)
170✔
191
        if err != nil {
170✔
192
                return err
×
193
        }
×
194

195
        if sd.KeyDesc.PubKey != nil {
279✔
196
                serializedPubKey := sd.KeyDesc.PubKey.SerializeCompressed()
109✔
197
                if err := wire.WriteVarBytes(w, 0, serializedPubKey); err != nil {
109✔
198
                        return err
×
199
                }
×
200
        }
201

202
        if err := wire.WriteVarBytes(w, 0, sd.SingleTweak); err != nil {
170✔
203
                return err
×
204
        }
×
205

206
        var doubleTweakBytes []byte
170✔
207
        if sd.DoubleTweak != nil {
178✔
208
                doubleTweakBytes = sd.DoubleTweak.Serialize()
8✔
209
        }
8✔
210
        if err := wire.WriteVarBytes(w, 0, doubleTweakBytes); err != nil {
170✔
211
                return err
×
212
        }
×
213

214
        if err := wire.WriteVarBytes(w, 0, sd.WitnessScript); err != nil {
170✔
215
                return err
×
216
        }
×
217

218
        if err := writeTxOut(w, sd.Output); err != nil {
170✔
219
                return err
×
220
        }
×
221

222
        var scratch [4]byte
170✔
223
        binary.BigEndian.PutUint32(scratch[:], uint32(sd.HashType))
170✔
224
        if _, err := w.Write(scratch[:]); err != nil {
170✔
225
                return err
×
226
        }
×
227

228
        return nil
170✔
229
}
230

231
// ReadSignDescriptor deserializes a SignDescriptor struct from the passed
232
// io.Reader stream.
233
func ReadSignDescriptor(r io.Reader, sd *SignDescriptor) error {
261✔
234
        err := binary.Read(r, binary.BigEndian, &sd.KeyDesc.Family)
261✔
235
        if err != nil {
261✔
236
                return err
×
237
        }
×
238
        err = binary.Read(r, binary.BigEndian, &sd.KeyDesc.Index)
261✔
239
        if err != nil {
261✔
240
                return err
×
241
        }
×
242

243
        var hasKey bool
261✔
244
        err = binary.Read(r, binary.BigEndian, &hasKey)
261✔
245
        if err != nil {
261✔
246
                return err
×
247
        }
×
248

249
        if hasKey {
431✔
250
                pubKeyBytes, err := wire.ReadVarBytes(r, 0, 34, "pubkey")
170✔
251
                if err != nil {
170✔
252
                        return err
×
253
                }
×
254
                sd.KeyDesc.PubKey, err = btcec.ParsePubKey(pubKeyBytes)
170✔
255
                if err != nil {
170✔
256
                        return err
×
257
                }
×
258
        }
259

260
        singleTweak, err := wire.ReadVarBytes(r, 0, 32, "singleTweak")
261✔
261
        if err != nil {
261✔
262
                return err
×
263
        }
×
264

265
        // Serializing a SignDescriptor with a nil-valued SingleTweak results
266
        // in deserializing a zero-length slice. Since a nil-valued SingleTweak
267
        // has special meaning and a zero-length slice for a SingleTweak is
268
        // invalid, we can use the zero-length slice as the flag for a
269
        // nil-valued SingleTweak.
270
        if len(singleTweak) == 0 {
392✔
271
                sd.SingleTweak = nil
131✔
272
        } else {
261✔
273
                sd.SingleTweak = singleTweak
130✔
274
        }
130✔
275

276
        doubleTweakBytes, err := wire.ReadVarBytes(r, 0, 32, "doubleTweak")
261✔
277
        if err != nil {
261✔
278
                return err
×
279
        }
×
280

281
        // Serializing a SignDescriptor with a nil-valued DoubleTweak results
282
        // in deserializing a zero-length slice. Since a nil-valued DoubleTweak
283
        // has special meaning and a zero-length slice for a DoubleTweak is
284
        // invalid, we can use the zero-length slice as the flag for a
285
        // nil-valued DoubleTweak.
286
        if len(doubleTweakBytes) == 0 {
522✔
287
                sd.DoubleTweak = nil
261✔
288
        } else {
261✔
289
                sd.DoubleTweak, _ = btcec.PrivKeyFromBytes(doubleTweakBytes)
×
290
        }
×
291

292
        // Only one tweak should ever be set, fail if both are present.
293
        if sd.SingleTweak != nil && sd.DoubleTweak != nil {
261✔
294
                return ErrTweakOverdose
×
295
        }
×
296

297
        witnessScript, err := wire.ReadVarBytes(r, 0, 500, "witnessScript")
261✔
298
        if err != nil {
261✔
299
                return err
×
300
        }
×
301
        sd.WitnessScript = witnessScript
261✔
302

261✔
303
        txOut := &wire.TxOut{}
261✔
304
        if err := readTxOut(r, txOut); err != nil {
261✔
305
                return err
×
306
        }
×
307
        sd.Output = txOut
261✔
308

261✔
309
        var hashType [4]byte
261✔
310
        if _, err := io.ReadFull(r, hashType[:]); err != nil {
261✔
311
                return err
×
312
        }
×
313
        sd.HashType = txscript.SigHashType(binary.BigEndian.Uint32(hashType[:]))
261✔
314

261✔
315
        return nil
261✔
316
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc