Replaced legacy `*.orly` module imports with `next.orly.dev/pkg` paths across the codebase for consistency. Removed legacy `go.mod` files from sub-packages, consolidating dependency management. Added Dockerfiles and configurations for benchmarking environments.
281 lines
6.9 KiB
Go
281 lines
6.9 KiB
Go
// Copyright 2013-2022 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package musig2
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"next.orly.dev/pkg/crypto/ec"
|
|
"next.orly.dev/pkg/crypto/ec/schnorr"
|
|
"next.orly.dev/pkg/encoders/hex"
|
|
)
|
|
|
|
var (
|
|
testPrivBytes = hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d")
|
|
testMsg = hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7")
|
|
)
|
|
|
|
func hexToBytes(s string) []byte {
|
|
b, err := hex.Dec(s)
|
|
if err != nil {
|
|
panic("invalid hex in source file: " + s)
|
|
}
|
|
return b
|
|
}
|
|
|
|
func hexToModNScalar(s string) *btcec.ModNScalar {
|
|
b, err := hex.Dec(s)
|
|
if err != nil {
|
|
panic("invalid hex in source file: " + s)
|
|
}
|
|
var scalar btcec.ModNScalar
|
|
if overflow := scalar.SetByteSlice(b); overflow {
|
|
panic("hex in source file overflows mod N scalar: " + s)
|
|
}
|
|
return &scalar
|
|
}
|
|
|
|
func genSigner(t *testing.B) signer {
|
|
privKey, err := btcec.NewSecretKey()
|
|
if err != nil {
|
|
t.Fatalf("unable to gen priv key: %v", err)
|
|
}
|
|
pubKey := privKey.PubKey()
|
|
nonces, err := GenNonces(WithPublicKey(pubKey))
|
|
if err != nil {
|
|
t.Fatalf("unable to gen nonces: %v", err)
|
|
}
|
|
return signer{
|
|
privKey: privKey,
|
|
pubKey: pubKey,
|
|
nonces: nonces,
|
|
}
|
|
}
|
|
|
|
var (
|
|
testSig *PartialSignature
|
|
testErr error
|
|
)
|
|
|
|
// BenchmarkPartialSign benchmarks how long it takes to generate a partial
|
|
// signature factoring in if the keys are sorted and also if we're in fast sign
|
|
// mode.
|
|
func BenchmarkPartialSign(b *testing.B) {
|
|
for _, numSigners := range []int{10, 100} {
|
|
for _, fastSign := range []bool{true, false} {
|
|
for _, sortKeys := range []bool{true, false} {
|
|
name := fmt.Sprintf(
|
|
"num_signers=%v/fast_sign=%v/sort=%v",
|
|
numSigners, fastSign, sortKeys,
|
|
)
|
|
signers := make(signerSet, numSigners)
|
|
for i := 0; i < numSigners; i++ {
|
|
signers[i] = genSigner(b)
|
|
}
|
|
combinedNonce, err := AggregateNonces(signers.pubNonces())
|
|
if err != nil {
|
|
b.Fatalf("unable to generate combined nonce: %v", err)
|
|
}
|
|
var sig *PartialSignature
|
|
var msg [32]byte
|
|
copy(msg[:], testMsg[:])
|
|
keys := signers.keys()
|
|
b.Run(
|
|
name, func(b *testing.B) {
|
|
var signOpts []SignOption
|
|
if fastSign {
|
|
signOpts = append(signOpts, WithFastSign())
|
|
}
|
|
if sortKeys {
|
|
signOpts = append(signOpts, WithSortedKeys())
|
|
}
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
sig, err = Sign(
|
|
signers[0].nonces.SecNonce, signers[0].privKey,
|
|
combinedNonce, keys, msg, signOpts...,
|
|
)
|
|
if err != nil {
|
|
b.Fatalf("unable to generate sig: %v", err)
|
|
}
|
|
}
|
|
testSig = sig
|
|
testErr = err
|
|
},
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: this fails
|
|
// // TODO(roasbeef): add impact of sorting ^
|
|
//
|
|
// var sigOk bo
|
|
//
|
|
// // BenchmarkPartialVerify benchmarks how long it takes to verify a partial
|
|
// // signature.
|
|
// func BenchmarkPartialVerify(b *testing.B) {
|
|
// for _, numSigners := range []int{10, 100} {
|
|
// for _, sortKeys := range []bool{true, false} {
|
|
// name := fmt.Sprintf("sort_keys=%v/num_signers=%v",
|
|
// sortKeys, numSigners)
|
|
// signers := make(signerSet, numSigners)
|
|
// for i := 0; i < numSigners; i++ {
|
|
// signers[i] = genSigner(b)
|
|
// }
|
|
// combinedNonce, err := AggregateNonces(
|
|
// signers.pubNonces(),
|
|
// )
|
|
// if err != nil {
|
|
// b.Fatalf("unable to generate combined "+
|
|
// "nonce: %v", err)
|
|
// }
|
|
// var sig *PartialSignature
|
|
// var msg [32]byte
|
|
// copy(msg[:], testMsg[:])
|
|
// b.ReportAllocs()
|
|
// b.ResetTimer()
|
|
// sig, err = Sign(
|
|
// signers[0].nonces.SecNonce, signers[0].privKey,
|
|
// combinedNonce, signers.keys(), msg,
|
|
// )
|
|
// if err != nil {
|
|
// b.Fatalf("unable to generate sig: %v", err)
|
|
// }
|
|
// keys := signers.keys()
|
|
// pubKey := signers[0].pubKey
|
|
// b.Run(name, func(b *testing.B) {
|
|
// var signOpts []SignOption
|
|
// if sortKeys {
|
|
// signOpts = append(
|
|
// signOpts, WithSortedKeys(),
|
|
// )
|
|
// }
|
|
// b.ResetTimer()
|
|
// b.ReportAllocs()
|
|
// var ok bo
|
|
// for i := 0; i < b.no; i++ {
|
|
// ok = sig.Verify(
|
|
// signers[0].nonces.PubNonce, combinedNonce,
|
|
// keys, pubKey, msg, signOpts...,
|
|
// )
|
|
// if !ok {
|
|
// b.Fatalf("generated invalid sig!")
|
|
// }
|
|
// }
|
|
// sigOk = ok
|
|
// })
|
|
//
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
var finalSchnorrSig *schnorr.Signature
|
|
|
|
// BenchmarkCombineSigs benchmarks how long it takes to combine a set amount of
|
|
// signatures.
|
|
func BenchmarkCombineSigs(b *testing.B) {
|
|
for _, numSigners := range []int{10, 100} {
|
|
signers := make(signerSet, numSigners)
|
|
for i := 0; i < numSigners; i++ {
|
|
signers[i] = genSigner(b)
|
|
}
|
|
combinedNonce, err := AggregateNonces(signers.pubNonces())
|
|
if err != nil {
|
|
b.Fatalf("unable to generate combined nonce: %v", err)
|
|
}
|
|
var msg [32]byte
|
|
copy(msg[:], testMsg[:])
|
|
var finalNonce *btcec.PublicKey
|
|
for i := range signers {
|
|
signer := signers[i]
|
|
partialSig, err := Sign(
|
|
signer.nonces.SecNonce, signer.privKey,
|
|
combinedNonce, signers.keys(), msg,
|
|
)
|
|
if err != nil {
|
|
b.Fatalf(
|
|
"unable to generate partial sig: %v",
|
|
err,
|
|
)
|
|
}
|
|
signers[i].partialSig = partialSig
|
|
if finalNonce == nil {
|
|
finalNonce = partialSig.R
|
|
}
|
|
}
|
|
sigs := signers.partialSigs()
|
|
name := fmt.Sprintf("num_signers=%v", numSigners)
|
|
b.Run(
|
|
name, func(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
finalSig := CombineSigs(finalNonce, sigs)
|
|
finalSchnorrSig = finalSig
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
var testNonce [PubNonceSize]byte
|
|
|
|
// BenchmarkAggregateNonces benchmarks how long it takes to combine nonces.
|
|
func BenchmarkAggregateNonces(b *testing.B) {
|
|
for _, numSigners := range []int{10, 100} {
|
|
signers := make(signerSet, numSigners)
|
|
for i := 0; i < numSigners; i++ {
|
|
signers[i] = genSigner(b)
|
|
}
|
|
nonces := signers.pubNonces()
|
|
name := fmt.Sprintf("num_signers=%v", numSigners)
|
|
b.Run(
|
|
name, func(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
pubNonce, err := AggregateNonces(nonces)
|
|
if err != nil {
|
|
b.Fatalf("unable to generate nonces: %v", err)
|
|
}
|
|
testNonce = pubNonce
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
var testKey *btcec.PublicKey
|
|
|
|
// BenchmarkAggregateKeys benchmarks how long it takes to aggregate public
|
|
// keys.
|
|
func BenchmarkAggregateKeys(b *testing.B) {
|
|
for _, numSigners := range []int{10, 100} {
|
|
for _, sortKeys := range []bool{true, false} {
|
|
signers := make(signerSet, numSigners)
|
|
for i := 0; i < numSigners; i++ {
|
|
signers[i] = genSigner(b)
|
|
}
|
|
signerKeys := signers.keys()
|
|
name := fmt.Sprintf(
|
|
"num_signers=%v/sort_keys=%v",
|
|
numSigners, sortKeys,
|
|
)
|
|
uniqueKeyIndex := secondUniqueKeyIndex(signerKeys, false)
|
|
b.Run(
|
|
name, func(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
aggKey, _, _, _ := AggregateKeys(
|
|
signerKeys, sortKeys,
|
|
WithUniqueKeyIndex(uniqueKeyIndex),
|
|
)
|
|
testKey = aggKey.FinalKey
|
|
},
|
|
)
|
|
}
|
|
}
|
|
}
|