bench_test.go raw
1 // Copyright 2013-2022 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package musig2
6
7 import (
8 "fmt"
9 "testing"
10
11 "next.orly.dev/pkg/nostr/crypto/ec"
12 "next.orly.dev/pkg/nostr/crypto/ec/schnorr"
13 "next.orly.dev/pkg/nostr/encoders/hex"
14 )
15
16 var (
17 testPrivBytes = hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d")
18 testMsg = hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7")
19 )
20
21 func hexToBytes(s string) []byte {
22 b, err := hex.Dec(s)
23 if err != nil {
24 panic("invalid hex in source file: " + s)
25 }
26 return b
27 }
28
29 func hexToModNScalar(s string) *btcec.ModNScalar {
30 b, err := hex.Dec(s)
31 if err != nil {
32 panic("invalid hex in source file: " + s)
33 }
34 var scalar btcec.ModNScalar
35 if overflow := scalar.SetByteSlice(b); overflow {
36 panic("hex in source file overflows mod N scalar: " + s)
37 }
38 return &scalar
39 }
40
41 func genSigner(t *testing.B) signer {
42 privKey, err := btcec.NewSecretKey()
43 if err != nil {
44 t.Fatalf("unable to gen priv key: %v", err)
45 }
46 pubKey := privKey.PubKey()
47 nonces, err := GenNonces(WithPublicKey(pubKey))
48 if err != nil {
49 t.Fatalf("unable to gen nonces: %v", err)
50 }
51 return signer{
52 privKey: privKey,
53 pubKey: pubKey,
54 nonces: nonces,
55 }
56 }
57
58 var (
59 testSig *PartialSignature
60 testErr error
61 )
62
63 // BenchmarkPartialSign benchmarks how long it takes to generate a partial
64 // signature factoring in if the keys are sorted and also if we're in fast sign
65 // mode.
66 func BenchmarkPartialSign(b *testing.B) {
67 for _, numSigners := range []int{10, 100} {
68 for _, fastSign := range []bool{true, false} {
69 for _, sortKeys := range []bool{true, false} {
70 name := fmt.Sprintf(
71 "num_signers=%v/fast_sign=%v/sort=%v",
72 numSigners, fastSign, sortKeys,
73 )
74 signers := make(signerSet, numSigners)
75 for i := 0; i < numSigners; i++ {
76 signers[i] = genSigner(b)
77 }
78 combinedNonce, err := AggregateNonces(signers.pubNonces())
79 if err != nil {
80 b.Fatalf("unable to generate combined nonce: %v", err)
81 }
82 var sig *PartialSignature
83 var msg [32]byte
84 copy(msg[:], testMsg[:])
85 keys := signers.keys()
86 b.Run(
87 name, func(b *testing.B) {
88 var signOpts []SignOption
89 if fastSign {
90 signOpts = append(signOpts, WithFastSign())
91 }
92 if sortKeys {
93 signOpts = append(signOpts, WithSortedKeys())
94 }
95 b.ResetTimer()
96 b.ReportAllocs()
97 for i := 0; i < b.N; i++ {
98 sig, err = Sign(
99 signers[0].nonces.SecNonce, signers[0].privKey,
100 combinedNonce, keys, msg, signOpts...,
101 )
102 if err != nil {
103 b.Fatalf("unable to generate sig: %v", err)
104 }
105 }
106 testSig = sig
107 testErr = err
108 },
109 )
110 }
111 }
112 }
113 }
114
115 // TODO: this fails
116 // // TODO(roasbeef): add impact of sorting ^
117 //
118 // var sigOk bo
119 //
120 // // BenchmarkPartialVerify benchmarks how long it takes to verify a partial
121 // // signature.
122 // func BenchmarkPartialVerify(b *testing.B) {
123 // for _, numSigners := range []int{10, 100} {
124 // for _, sortKeys := range []bool{true, false} {
125 // name := fmt.Sprintf("sort_keys=%v/num_signers=%v",
126 // sortKeys, numSigners)
127 // signers := make(signerSet, numSigners)
128 // for i := 0; i < numSigners; i++ {
129 // signers[i] = genSigner(b)
130 // }
131 // combinedNonce, err := AggregateNonces(
132 // signers.pubNonces(),
133 // )
134 // if err != nil {
135 // b.Fatalf("unable to generate combined "+
136 // "nonce: %v", err)
137 // }
138 // var sig *PartialSignature
139 // var msg [32]byte
140 // copy(msg[:], testMsg[:])
141 // b.ReportAllocs()
142 // b.ResetTimer()
143 // sig, err = Sign(
144 // signers[0].nonces.SecNonce, signers[0].privKey,
145 // combinedNonce, signers.keys(), msg,
146 // )
147 // if err != nil {
148 // b.Fatalf("unable to generate sig: %v", err)
149 // }
150 // keys := signers.keys()
151 // pubKey := signers[0].pubKey
152 // b.Run(name, func(b *testing.B) {
153 // var signOpts []SignOption
154 // if sortKeys {
155 // signOpts = append(
156 // signOpts, WithSortedKeys(),
157 // )
158 // }
159 // b.ResetTimer()
160 // b.ReportAllocs()
161 // var ok bo
162 // for i := 0; i < b.no; i++ {
163 // ok = sig.Verify(
164 // signers[0].nonces.PubNonce, combinedNonce,
165 // keys, pubKey, msg, signOpts...,
166 // )
167 // if !ok {
168 // b.Fatalf("generated invalid sig!")
169 // }
170 // }
171 // sigOk = ok
172 // })
173 //
174 // }
175 // }
176 // }
177
178 var finalSchnorrSig *schnorr.Signature
179
180 // BenchmarkCombineSigs benchmarks how long it takes to combine a set amount of
181 // signatures.
182 func BenchmarkCombineSigs(b *testing.B) {
183 for _, numSigners := range []int{10, 100} {
184 signers := make(signerSet, numSigners)
185 for i := 0; i < numSigners; i++ {
186 signers[i] = genSigner(b)
187 }
188 combinedNonce, err := AggregateNonces(signers.pubNonces())
189 if err != nil {
190 b.Fatalf("unable to generate combined nonce: %v", err)
191 }
192 var msg [32]byte
193 copy(msg[:], testMsg[:])
194 var finalNonce *btcec.PublicKey
195 for i := range signers {
196 signer := signers[i]
197 partialSig, err := Sign(
198 signer.nonces.SecNonce, signer.privKey,
199 combinedNonce, signers.keys(), msg,
200 )
201 if err != nil {
202 b.Fatalf(
203 "unable to generate partial sig: %v",
204 err,
205 )
206 }
207 signers[i].partialSig = partialSig
208 if finalNonce == nil {
209 finalNonce = partialSig.R
210 }
211 }
212 sigs := signers.partialSigs()
213 name := fmt.Sprintf("num_signers=%v", numSigners)
214 b.Run(
215 name, func(b *testing.B) {
216 b.ResetTimer()
217 b.ReportAllocs()
218 finalSig := CombineSigs(finalNonce, sigs)
219 finalSchnorrSig = finalSig
220 },
221 )
222 }
223 }
224
225 var testNonce [PubNonceSize]byte
226
227 // BenchmarkAggregateNonces benchmarks how long it takes to combine nonces.
228 func BenchmarkAggregateNonces(b *testing.B) {
229 for _, numSigners := range []int{10, 100} {
230 signers := make(signerSet, numSigners)
231 for i := 0; i < numSigners; i++ {
232 signers[i] = genSigner(b)
233 }
234 nonces := signers.pubNonces()
235 name := fmt.Sprintf("num_signers=%v", numSigners)
236 b.Run(
237 name, func(b *testing.B) {
238 b.ResetTimer()
239 b.ReportAllocs()
240 pubNonce, err := AggregateNonces(nonces)
241 if err != nil {
242 b.Fatalf("unable to generate nonces: %v", err)
243 }
244 testNonce = pubNonce
245 },
246 )
247 }
248 }
249
250 var testKey *btcec.PublicKey
251
252 // BenchmarkAggregateKeys benchmarks how long it takes to aggregate public
253 // keys.
254 func BenchmarkAggregateKeys(b *testing.B) {
255 for _, numSigners := range []int{10, 100} {
256 for _, sortKeys := range []bool{true, false} {
257 signers := make(signerSet, numSigners)
258 for i := 0; i < numSigners; i++ {
259 signers[i] = genSigner(b)
260 }
261 signerKeys := signers.keys()
262 name := fmt.Sprintf(
263 "num_signers=%v/sort_keys=%v",
264 numSigners, sortKeys,
265 )
266 uniqueKeyIndex := secondUniqueKeyIndex(signerKeys, false)
267 b.Run(
268 name, func(b *testing.B) {
269 b.ResetTimer()
270 b.ReportAllocs()
271 aggKey, _, _, _ := AggregateKeys(
272 signerKeys, sortKeys,
273 WithUniqueKeyIndex(uniqueKeyIndex),
274 )
275 testKey = aggKey.FinalKey
276 },
277 )
278 }
279 }
280 }
281