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