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

lightningnetwork / lnd / 15736109134

18 Jun 2025 02:46PM UTC coverage: 58.197% (-10.1%) from 68.248%
15736109134

Pull #9752

github

web-flow
Merge d2634a68c into 31c74f20f
Pull Request #9752: routerrpc: reject payment to invoice that don't have payment secret or blinded paths

6 of 13 new or added lines in 2 files covered. (46.15%)

28331 existing lines in 455 files now uncovered.

97860 of 168153 relevant lines covered (58.2%)

1.81 hits per line

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

75.92
/internal/musig2v040/nonces.go
1
// Copyright 2013-2022 The btcsuite developers
2

3
package musig2v040
4

5
import (
6
        "bytes"
7
        "crypto/rand"
8
        "encoding/binary"
9
        "io"
10

11
        "github.com/btcsuite/btcd/btcec/v2"
12
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
13
        "github.com/btcsuite/btcd/chaincfg/chainhash"
14
)
15

16
const (
17
        // PubNonceSize is the size of the public nonces. Each public nonce is
18
        // serialized the full compressed encoding, which uses 32 bytes for each
19
        // nonce.
20
        PubNonceSize = 66
21

22
        // SecNonceSize is the size of the secret nonces for musig2. The secret
23
        // nonces are the corresponding private keys to the public nonce points.
24
        SecNonceSize = 64
25
)
26

27
var (
28
        // NonceAuxTag is the tag used to optionally mix in the secret key with
29
        // the set of aux randomness.
30
        NonceAuxTag = []byte("MuSig/aux")
31

32
        // NonceGenTag is used to generate the value (from a set of required an
33
        // optional field) that will be used as the part of the secret nonce.
34
        NonceGenTag = []byte("MuSig/nonce")
35

36
        byteOrder = binary.BigEndian
37
)
38

39
// zeroSecNonce is a secret nonce that's all zeroes. This is used to check that
40
// we're not attempting to re-use a nonce, and also protect callers from it.
41
var zeroSecNonce [SecNonceSize]byte
42

43
// Nonces holds the public and secret nonces required for musig2.
44
//
45
// TODO(roasbeef): methods on this to help w/ parsing, etc?
46
type Nonces struct {
47
        // PubNonce holds the two 33-byte compressed encoded points that serve
48
        // as the public set of nonces.
49
        PubNonce [PubNonceSize]byte
50

51
        // SecNonce holds the two 32-byte scalar values that are the private
52
        // keys to the two public nonces.
53
        SecNonce [SecNonceSize]byte
54
}
55

56
// secNonceToPubNonce takes our two secrete nonces, and produces their two
57
// corresponding EC points, serialized in compressed format.
58
func secNonceToPubNonce(secNonce [SecNonceSize]byte) [PubNonceSize]byte {
3✔
59
        var k1Mod, k2Mod btcec.ModNScalar
3✔
60
        k1Mod.SetByteSlice(secNonce[:btcec.PrivKeyBytesLen])
3✔
61
        k2Mod.SetByteSlice(secNonce[btcec.PrivKeyBytesLen:])
3✔
62

3✔
63
        var r1, r2 btcec.JacobianPoint
3✔
64
        btcec.ScalarBaseMultNonConst(&k1Mod, &r1)
3✔
65
        btcec.ScalarBaseMultNonConst(&k2Mod, &r2)
3✔
66

3✔
67
        // Next, we'll convert the key in jacobian format to a normal public
3✔
68
        // key expressed in affine coordinates.
3✔
69
        r1.ToAffine()
3✔
70
        r2.ToAffine()
3✔
71
        r1Pub := btcec.NewPublicKey(&r1.X, &r1.Y)
3✔
72
        r2Pub := btcec.NewPublicKey(&r2.X, &r2.Y)
3✔
73

3✔
74
        var pubNonce [PubNonceSize]byte
3✔
75

3✔
76
        // The public nonces are serialized as: R1 || R2, where both keys are
3✔
77
        // serialized in compressed format.
3✔
78
        copy(pubNonce[:], r1Pub.SerializeCompressed())
3✔
79
        copy(
3✔
80
                pubNonce[btcec.PubKeyBytesLenCompressed:],
3✔
81
                r2Pub.SerializeCompressed(),
3✔
82
        )
3✔
83

3✔
84
        return pubNonce
3✔
85
}
3✔
86

87
// NonceGenOption is a function option that allows callers to modify how nonce
88
// generation happens.
89
type NonceGenOption func(*nonceGenOpts)
90

91
// nonceGenOpts is the set of options that control how nonce generation
92
// happens.
93
type nonceGenOpts struct {
94
        // randReader is what we'll use to generate a set of random bytes. If
95
        // unspecified, then the normal crypto/rand rand.Read method will be
96
        // used in place.
97
        randReader io.Reader
98

99
        // secretKey is an optional argument that's used to further augment the
100
        // generated nonce by xor'ing it with this secret key.
101
        secretKey []byte
102

103
        // combinedKey is an optional argument that if specified, will be
104
        // combined along with the nonce generation.
105
        combinedKey []byte
106

107
        // msg is an optional argument that will be mixed into the nonce
108
        // derivation algorithm.
109
        msg []byte
110

111
        // auxInput is an optional argument that will be mixed into the nonce
112
        // derivation algorithm.
113
        auxInput []byte
114
}
115

116
// cryptoRandAdapter is an adapter struct that allows us to pass in the package
117
// level Read function from crypto/rand into a context that accepts an
118
// io.Reader.
119
type cryptoRandAdapter struct {
120
}
121

122
// Read implements the io.Reader interface for the crypto/rand package.  By
123
// default, we always use the crypto/rand reader, but the caller is able to
124
// specify their own generation, which can be useful for deterministic tests.
125
func (c *cryptoRandAdapter) Read(p []byte) (n int, err error) {
3✔
126
        return rand.Read(p)
3✔
127
}
3✔
128

129
// defaultNonceGenOpts returns the default set of nonce generation options.
130
func defaultNonceGenOpts() *nonceGenOpts {
3✔
131
        return &nonceGenOpts{
3✔
132
                randReader: &cryptoRandAdapter{},
3✔
133
        }
3✔
134
}
3✔
135

136
// WithCustomRand allows a caller to use a custom random number generator in
137
// place for crypto/rand. This should only really be used to generate
138
// determinstic tests.
139
func WithCustomRand(r io.Reader) NonceGenOption {
×
140
        return func(o *nonceGenOpts) {
×
141
                o.randReader = r
×
142
        }
×
143
}
144

145
// WithNonceSecretKeyAux allows a caller to optionally specify a secret key
146
// that should be used to augment the randomness used to generate the nonces.
147
func WithNonceSecretKeyAux(secKey *btcec.PrivateKey) NonceGenOption {
3✔
148
        return func(o *nonceGenOpts) {
6✔
149
                o.secretKey = secKey.Serialize()
3✔
150
        }
3✔
151
}
152

153
// WithNonceCombinedKeyAux allows a caller to optionally specify the combined
154
// key used in this signing session to further augment the randomness used to
155
// generate nonces.
156
func WithNonceCombinedKeyAux(combinedKey *btcec.PublicKey) NonceGenOption {
3✔
157
        return func(o *nonceGenOpts) {
6✔
158
                o.combinedKey = schnorr.SerializePubKey(combinedKey)
3✔
159
        }
3✔
160
}
161

162
// WithNonceMessageAux allows a caller to optionally specify a message to be
163
// mixed into the randomness generated to create the nonce.
164
func WithNonceMessageAux(msg [32]byte) NonceGenOption {
×
165
        return func(o *nonceGenOpts) {
×
166
                o.msg = msg[:]
×
167
        }
×
168
}
169

170
// WithNonceAuxInput is a set of auxiliary randomness, similar to BIP 340 that
171
// can be used to further augment the nonce generation process.
172
func WithNonceAuxInput(aux []byte) NonceGenOption {
×
173
        return func(o *nonceGenOpts) {
×
174
                o.auxInput = aux
×
175
        }
×
176
}
177

178
// withCustomOptions allows a caller to pass a complete set of custom
179
// nonceGenOpts, without needing to create custom and checked structs such as
180
// *btcec.PrivateKey. This is mainly used to match the testcases provided by
181
// the MuSig2 BIP.
UNCOV
182
func withCustomOptions(customOpts nonceGenOpts) NonceGenOption {
×
UNCOV
183
        return func(o *nonceGenOpts) {
×
UNCOV
184
                o.randReader = customOpts.randReader
×
UNCOV
185
                o.secretKey = customOpts.secretKey
×
UNCOV
186
                o.combinedKey = customOpts.combinedKey
×
UNCOV
187
                o.msg = customOpts.msg
×
UNCOV
188
                o.auxInput = customOpts.auxInput
×
UNCOV
189
        }
×
190
}
191

192
// lengthWriter is a function closure that allows a caller to control how the
193
// length prefix of a byte slice is written.
194
type lengthWriter func(w io.Writer, b []byte) error
195

196
// uint8Writer is an implementation of lengthWriter that writes the length of
197
// the byte slice using 1 byte.
198
func uint8Writer(w io.Writer, b []byte) error {
3✔
199
        return binary.Write(w, byteOrder, uint8(len(b)))
3✔
200
}
3✔
201

202
// uint32Writer is an implementation of lengthWriter that writes the length of
203
// the byte slice using 4 bytes.
204
func uint32Writer(w io.Writer, b []byte) error {
3✔
205
        return binary.Write(w, byteOrder, uint32(len(b)))
3✔
206
}
3✔
207

208
// writeBytesPrefix is used to write out: len(b) || b, to the passed io.Writer.
209
// The lengthWriter function closure is used to allow the caller to specify the
210
// precise byte packing of the length.
211
func writeBytesPrefix(w io.Writer, b []byte, lenWriter lengthWriter) error {
3✔
212
        // Write out the length of the byte first, followed by the set of bytes
3✔
213
        // itself.
3✔
214
        if err := lenWriter(w, b); err != nil {
3✔
215
                return err
×
216
        }
×
217

218
        if _, err := w.Write(b); err != nil {
3✔
219
                return err
×
220
        }
×
221

222
        return nil
3✔
223
}
224

225
// genNonceAuxBytes writes out the full byte string used to derive a secret
226
// nonce based on some initial randomness as well as the series of optional
227
// fields. The byte string used for derivation is:
228
//   - tagged_hash("MuSig/nonce", rand || len(aggpk) || aggpk || len(m)
229
//     || m || len(in) || in || i).
230
//
231
// where i is the ith secret nonce being generated.
232
func genNonceAuxBytes(rand []byte, i int,
233
        opts *nonceGenOpts) (*chainhash.Hash, error) {
3✔
234

3✔
235
        var w bytes.Buffer
3✔
236

3✔
237
        // First, write out the randomness generated in the prior step.
3✔
238
        if _, err := w.Write(rand); err != nil {
3✔
239
                return nil, err
×
240
        }
×
241

242
        // Next, we'll write out: len(aggpk) || aggpk.
243
        err := writeBytesPrefix(&w, opts.combinedKey, uint8Writer)
3✔
244
        if err != nil {
3✔
245
                return nil, err
×
246
        }
×
247

248
        // Next, we'll write out the length prefixed message.
249
        err = writeBytesPrefix(&w, opts.msg, uint8Writer)
3✔
250
        if err != nil {
3✔
251
                return nil, err
×
252
        }
×
253

254
        // Finally we'll write out the auxiliary input.
255
        err = writeBytesPrefix(&w, opts.auxInput, uint32Writer)
3✔
256
        if err != nil {
3✔
257
                return nil, err
×
258
        }
×
259

260
        // Next we'll write out the interaction/index number which will
261
        // uniquely generate two nonces given the rest of the possibly static
262
        // parameters.
263
        if err := binary.Write(&w, byteOrder, uint8(i)); err != nil {
3✔
264
                return nil, err
×
265
        }
×
266

267
        // With the message buffer complete, we'll now derive the tagged hash
268
        // using our set of params.
269
        return chainhash.TaggedHash(NonceGenTag, w.Bytes()), nil
3✔
270
}
271

272
// GenNonces generates the secret nonces, as well as the public nonces which
273
// correspond to an EC point generated using the secret nonce as a private key.
274
func GenNonces(options ...NonceGenOption) (*Nonces, error) {
3✔
275
        opts := defaultNonceGenOpts()
3✔
276
        for _, opt := range options {
6✔
277
                opt(opts)
3✔
278
        }
3✔
279

280
        // First, we'll start out by generating 32 random bytes drawn from our
281
        // CSPRNG.
282
        var randBytes [32]byte
3✔
283
        if _, err := opts.randReader.Read(randBytes[:]); err != nil {
3✔
284
                return nil, err
×
285
        }
×
286

287
        // If the options contain a secret key, we XOR it with with the tagged
288
        // random bytes.
289
        if len(opts.secretKey) == 32 {
6✔
290
                taggedHash := chainhash.TaggedHash(NonceAuxTag, randBytes[:])
3✔
291

3✔
292
                for i := 0; i < chainhash.HashSize; i++ {
6✔
293
                        randBytes[i] = opts.secretKey[i] ^ taggedHash[i]
3✔
294
                }
3✔
295
        }
296

297
        // Using our randomness and the set of optional params, generate our
298
        // two secret nonces: k1 and k2.
299
        k1, err := genNonceAuxBytes(randBytes[:], 0, opts)
3✔
300
        if err != nil {
3✔
301
                return nil, err
×
302
        }
×
303
        k2, err := genNonceAuxBytes(randBytes[:], 1, opts)
3✔
304
        if err != nil {
3✔
305
                return nil, err
×
306
        }
×
307

308
        var k1Mod, k2Mod btcec.ModNScalar
3✔
309
        k1Mod.SetBytes((*[32]byte)(k1))
3✔
310
        k2Mod.SetBytes((*[32]byte)(k2))
3✔
311

3✔
312
        // The secret nonces are serialized as the concatenation of the two 32
3✔
313
        // byte secret nonce values.
3✔
314
        var nonces Nonces
3✔
315
        k1Mod.PutBytesUnchecked(nonces.SecNonce[:])
3✔
316
        k2Mod.PutBytesUnchecked(nonces.SecNonce[btcec.PrivKeyBytesLen:])
3✔
317

3✔
318
        // Next, we'll generate R_1 = k_1*G and R_2 = k_2*G. Along the way we
3✔
319
        // need to map our nonce values into mod n scalars so we can work with
3✔
320
        // the btcec API.
3✔
321
        nonces.PubNonce = secNonceToPubNonce(nonces.SecNonce)
3✔
322

3✔
323
        return &nonces, nil
3✔
324
}
325

326
// AggregateNonces aggregates the set of a pair of public nonces for each party
327
// into a single aggregated nonces to be used for multi-signing.
328
func AggregateNonces(pubNonces [][PubNonceSize]byte) ([PubNonceSize]byte, error) {
3✔
329
        // combineNonces is a helper function that aggregates (adds) up a
3✔
330
        // series of nonces encoded in compressed format. It uses a slicing
3✔
331
        // function to extra 33 bytes at a time from the packed 2x public
3✔
332
        // nonces.
3✔
333
        type nonceSlicer func([PubNonceSize]byte) []byte
3✔
334
        combineNonces := func(slicer nonceSlicer) (btcec.JacobianPoint, error) {
6✔
335
                // Convert the set of nonces into jacobian coordinates we can
3✔
336
                // use to accumulate them all into each other.
3✔
337
                pubNonceJs := make([]*btcec.JacobianPoint, len(pubNonces))
3✔
338
                for i, pubNonceBytes := range pubNonces {
6✔
339
                        // Using the slicer, extract just the bytes we need to
3✔
340
                        // decode.
3✔
341
                        var nonceJ btcec.JacobianPoint
3✔
342

3✔
343
                        nonceJ, err := btcec.ParseJacobian(slicer(pubNonceBytes))
3✔
344
                        if err != nil {
3✔
UNCOV
345
                                return btcec.JacobianPoint{}, err
×
UNCOV
346
                        }
×
347

348
                        pubNonceJs[i] = &nonceJ
3✔
349
                }
350

351
                // Now that we have the set of complete nonces, we'll aggregate
352
                // them: R = R_i + R_i+1 + ... + R_i+n.
353
                var aggregateNonce btcec.JacobianPoint
3✔
354
                for _, pubNonceJ := range pubNonceJs {
6✔
355
                        btcec.AddNonConst(
3✔
356
                                &aggregateNonce, pubNonceJ, &aggregateNonce,
3✔
357
                        )
3✔
358
                }
3✔
359

360
                aggregateNonce.ToAffine()
3✔
361
                return aggregateNonce, nil
3✔
362
        }
363

364
        // The final nonce public nonce is actually two nonces, one that
365
        // aggregate the first nonce of all the parties, and the other that
366
        // aggregates the second nonce of all the parties.
367
        var finalNonce [PubNonceSize]byte
3✔
368
        combinedNonce1, err := combineNonces(func(n [PubNonceSize]byte) []byte {
6✔
369
                return n[:btcec.PubKeyBytesLenCompressed]
3✔
370
        })
3✔
371
        if err != nil {
3✔
UNCOV
372
                return finalNonce, err
×
UNCOV
373
        }
×
374

375
        combinedNonce2, err := combineNonces(func(n [PubNonceSize]byte) []byte {
6✔
376
                return n[btcec.PubKeyBytesLenCompressed:]
3✔
377
        })
3✔
378
        if err != nil {
3✔
UNCOV
379
                return finalNonce, err
×
UNCOV
380
        }
×
381

382
        copy(finalNonce[:], btcec.JacobianToByteSlice(combinedNonce1))
3✔
383
        copy(
3✔
384
                finalNonce[btcec.PubKeyBytesLenCompressed:],
3✔
385
                btcec.JacobianToByteSlice(combinedNonce2),
3✔
386
        )
3✔
387

3✔
388
        return finalNonce, nil
3✔
389
}
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