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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 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