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

lightningnetwork / lnd / 13408822928

19 Feb 2025 08:59AM UTC coverage: 41.123% (-17.7%) from 58.794%
13408822928

Pull #9521

github

web-flow
Merge d2f397b3c into 0e8786348
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

92496 of 224923 relevant lines covered (41.12%)

18825.83 hits per line

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

57.23
/input/test_utils.go
1
package input
2

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

8
        "github.com/btcsuite/btcd/btcec/v2"
9
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
10
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
11
        "github.com/btcsuite/btcd/btcutil"
12
        "github.com/btcsuite/btcd/chaincfg"
13
        "github.com/btcsuite/btcd/chaincfg/chainhash"
14
        "github.com/btcsuite/btcd/txscript"
15
        "github.com/btcsuite/btcd/wire"
16
        "github.com/lightningnetwork/lnd/keychain"
17
)
18

19
var (
20

21
        // For simplicity a single priv key controls all of our test outputs.
22
        testWalletPrivKey = []byte{
23
                0x2b, 0xd8, 0x06, 0xc9, 0x7f, 0x0e, 0x00, 0xaf,
24
                0x1a, 0x1f, 0xc3, 0x32, 0x8f, 0xa7, 0x63, 0xa9,
25
                0x26, 0x97, 0x23, 0xc8, 0xdb, 0x8f, 0xac, 0x4f,
26
                0x93, 0xaf, 0x71, 0xdb, 0x18, 0x6d, 0x6e, 0x90,
27
        }
28

29
        // We're alice :)
30
        bobsPrivKey = []byte{
31
                0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
32
                0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
33
                0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
34
                0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
35
        }
36

37
        // Use a hard-coded HD seed.
38
        testHdSeed = chainhash.Hash{
39
                0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
40
                0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
41
                0x4f, 0x2f, 0x6f, 0x25, 0x88, 0xa3, 0xef, 0xb9,
42
                0x6a, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
43
        }
44
)
45

46
// MockSigner is a simple implementation of the Signer interface. Each one has
47
// a set of private keys in a slice and can sign messages using the appropriate
48
// one.
49
type MockSigner struct {
50
        Privkeys  []*btcec.PrivateKey
51
        NetParams *chaincfg.Params
52

53
        *MusigSessionManager
54
}
55

56
// NewMockSigner returns a new instance of the MockSigner given a set of
57
// backing private keys.
58
func NewMockSigner(privKeys []*btcec.PrivateKey,
59
        netParams *chaincfg.Params) *MockSigner {
×
60

×
61
        signer := &MockSigner{
×
62
                Privkeys:  privKeys,
×
63
                NetParams: netParams,
×
64
        }
×
65

×
66
        keyFetcher := func(*keychain.KeyDescriptor) (*btcec.PrivateKey, error) {
×
67
                return signer.Privkeys[0], nil
×
68
        }
×
69
        signer.MusigSessionManager = NewMusigSessionManager(keyFetcher)
×
70

×
71
        return signer
×
72
}
73

74
// SignOutputRaw generates a signature for the passed transaction according to
75
// the data within the passed SignDescriptor.
76
func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx,
77
        signDesc *SignDescriptor) (Signature, error) {
188✔
78

188✔
79
        pubkey := signDesc.KeyDesc.PubKey
188✔
80
        switch {
188✔
81
        case signDesc.SingleTweak != nil:
37✔
82
                pubkey = TweakPubKeyWithTweak(pubkey, signDesc.SingleTweak)
37✔
83
        case signDesc.DoubleTweak != nil:
7✔
84
                pubkey = DeriveRevocationPubkey(pubkey, signDesc.DoubleTweak.PubKey())
7✔
85
        }
86

87
        hash160 := btcutil.Hash160(pubkey.SerializeCompressed())
188✔
88
        privKey := m.findKey(hash160, signDesc.SingleTweak, signDesc.DoubleTweak)
188✔
89
        if privKey == nil {
188✔
90
                return nil, fmt.Errorf("mock signer does not have key")
×
91
        }
×
92

93
        // In case of a taproot output any signature is always a Schnorr
94
        // signature, based on the new tapscript sighash algorithm.
95
        if txscript.IsPayToTaproot(signDesc.Output.PkScript) {
320✔
96
                sigHashes := txscript.NewTxSigHashes(
132✔
97
                        tx, signDesc.PrevOutputFetcher,
132✔
98
                )
132✔
99

132✔
100
                // Are we spending a script path or the key path? The API is
132✔
101
                // slightly different, so we need to account for that to get
132✔
102
                // the raw signature.
132✔
103
                var (
132✔
104
                        rawSig []byte
132✔
105
                        err    error
132✔
106
                )
132✔
107
                switch signDesc.SignMethod {
132✔
108
                case TaprootKeySpendBIP0086SignMethod,
109
                        TaprootKeySpendSignMethod:
24✔
110

24✔
111
                        // This function tweaks the private key using the tap
24✔
112
                        // root key supplied as the tweak.
24✔
113
                        rawSig, err = txscript.RawTxInTaprootSignature(
24✔
114
                                tx, sigHashes, signDesc.InputIndex,
24✔
115
                                signDesc.Output.Value, signDesc.Output.PkScript,
24✔
116
                                signDesc.TapTweak, signDesc.HashType,
24✔
117
                                privKey,
24✔
118
                        )
24✔
119
                        if err != nil {
24✔
120
                                return nil, err
×
121
                        }
×
122

123
                case TaprootScriptSpendSignMethod:
108✔
124
                        leaf := txscript.TapLeaf{
108✔
125
                                LeafVersion: txscript.BaseLeafVersion,
108✔
126
                                Script:      signDesc.WitnessScript,
108✔
127
                        }
108✔
128
                        rawSig, err = txscript.RawTxInTapscriptSignature(
108✔
129
                                tx, sigHashes, signDesc.InputIndex,
108✔
130
                                signDesc.Output.Value, signDesc.Output.PkScript,
108✔
131
                                leaf, signDesc.HashType, privKey,
108✔
132
                        )
108✔
133
                        if err != nil {
108✔
134
                                return nil, err
×
135
                        }
×
136
                }
137

138
                // The signature returned above might have a sighash flag
139
                // attached if a non-default type was used. We'll slice this
140
                // off if it exists to ensure we can properly parse the raw
141
                // signature.
142
                sig, err := schnorr.ParseSignature(
132✔
143
                        rawSig[:schnorr.SignatureSize],
132✔
144
                )
132✔
145
                if err != nil {
132✔
146
                        return nil, err
×
147
                }
×
148

149
                return sig, nil
132✔
150
        }
151

152
        sig, err := txscript.RawTxInWitnessSignature(
56✔
153
                tx, signDesc.SigHashes, signDesc.InputIndex,
56✔
154
                signDesc.Output.Value, signDesc.WitnessScript,
56✔
155
                signDesc.HashType, privKey,
56✔
156
        )
56✔
157
        if err != nil {
56✔
158
                return nil, err
×
159
        }
×
160

161
        return ecdsa.ParseDERSignature(sig[:len(sig)-1])
56✔
162
}
163

164
// ComputeInputScript generates a complete InputIndex for the passed transaction
165
// with the signature as defined within the passed SignDescriptor. This method
166
// should be capable of generating the proper input script for both regular
167
// p2wkh output and p2wkh outputs nested within a regular p2sh output.
168
func (m *MockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor) (*Script, error) {
×
169
        scriptType, addresses, _, err := txscript.ExtractPkScriptAddrs(
×
170
                signDesc.Output.PkScript, m.NetParams)
×
171
        if err != nil {
×
172
                return nil, err
×
173
        }
×
174

175
        switch scriptType {
×
176
        case txscript.PubKeyHashTy:
×
177
                privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak,
×
178
                        signDesc.DoubleTweak)
×
179
                if privKey == nil {
×
180
                        return nil, fmt.Errorf("mock signer does not have key for "+
×
181
                                "address %v", addresses[0])
×
182
                }
×
183

184
                sigScript, err := txscript.SignatureScript(
×
185
                        tx, signDesc.InputIndex, signDesc.Output.PkScript,
×
186
                        txscript.SigHashAll, privKey, true,
×
187
                )
×
188
                if err != nil {
×
189
                        return nil, err
×
190
                }
×
191

192
                return &Script{SigScript: sigScript}, nil
×
193

194
        case txscript.WitnessV0PubKeyHashTy:
×
195
                privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak,
×
196
                        signDesc.DoubleTweak)
×
197
                if privKey == nil {
×
198
                        return nil, fmt.Errorf("mock signer does not have key for "+
×
199
                                "address %v", addresses[0])
×
200
                }
×
201

202
                witnessScript, err := txscript.WitnessSignature(tx, signDesc.SigHashes,
×
203
                        signDesc.InputIndex, signDesc.Output.Value,
×
204
                        signDesc.Output.PkScript, txscript.SigHashAll, privKey, true)
×
205
                if err != nil {
×
206
                        return nil, err
×
207
                }
×
208

209
                return &Script{Witness: witnessScript}, nil
×
210

211
        default:
×
212
                return nil, fmt.Errorf("unexpected script type: %v", scriptType)
×
213
        }
214
}
215

216
// findKey searches through all stored private keys and returns one
217
// corresponding to the hashed pubkey if it can be found. The public key may
218
// either correspond directly to the private key or to the private key with a
219
// tweak applied.
220
func (m *MockSigner) findKey(needleHash160 []byte, singleTweak []byte,
221
        doubleTweak *btcec.PrivateKey) *btcec.PrivateKey {
188✔
222

188✔
223
        for _, privkey := range m.Privkeys {
376✔
224
                // First check whether public key is directly derived from
188✔
225
                // private key.
188✔
226
                hash160 := btcutil.Hash160(privkey.PubKey().SerializeCompressed())
188✔
227
                if bytes.Equal(hash160, needleHash160) {
332✔
228
                        return privkey
144✔
229
                }
144✔
230

231
                // Otherwise check if public key is derived from tweaked
232
                // private key.
233
                switch {
44✔
234
                case singleTweak != nil:
37✔
235
                        privkey = TweakPrivKey(privkey, singleTweak)
37✔
236
                case doubleTweak != nil:
7✔
237
                        privkey = DeriveRevocationPrivKey(privkey, doubleTweak)
7✔
238
                default:
×
239
                        continue
×
240
                }
241
                hash160 = btcutil.Hash160(privkey.PubKey().SerializeCompressed())
44✔
242
                if bytes.Equal(hash160, needleHash160) {
88✔
243
                        return privkey
44✔
244
                }
44✔
245
        }
246
        return nil
×
247
}
248

249
// pubkeyFromHex parses a Bitcoin public key from a hex encoded string.
250
func pubkeyFromHex(keyHex string) (*btcec.PublicKey, error) {
2✔
251
        bytes, err := hex.DecodeString(keyHex)
2✔
252
        if err != nil {
2✔
253
                return nil, err
×
254
        }
×
255
        return btcec.ParsePubKey(bytes)
2✔
256
}
257

258
// privkeyFromHex parses a Bitcoin private key from a hex encoded string.
259
func privkeyFromHex(keyHex string) (*btcec.PrivateKey, error) {
2✔
260
        bytes, err := hex.DecodeString(keyHex)
2✔
261
        if err != nil {
2✔
262
                return nil, err
×
263
        }
×
264
        key, _ := btcec.PrivKeyFromBytes(bytes)
2✔
265
        return key, nil
2✔
266

267
}
268

269
// pubkeyToHex serializes a Bitcoin public key to a hex encoded string.
270
func pubkeyToHex(key *btcec.PublicKey) string {
2✔
271
        return hex.EncodeToString(key.SerializeCompressed())
2✔
272
}
2✔
273

274
// privkeyFromHex serializes a Bitcoin private key to a hex encoded string.
275
func privkeyToHex(key *btcec.PrivateKey) string {
2✔
276
        return hex.EncodeToString(key.Serialize())
2✔
277
}
2✔
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