bench_test.go raw

   1  // Copyright 2013-2016 The btcsuite developers
   2  // Copyright (c) 2015-2022 The Decred developers
   3  // Use of this source code is governed by an ISC
   4  // license that can be found in the LICENSE file.
   5  
   6  package secp256k1
   7  
   8  import (
   9  	"testing"
  10  )
  11  
  12  // BenchmarkAddNonConst benchmarks the secp256k1 curve AddNonConst function with
  13  // Z values of 1 so that the associated optimizations are used.
  14  func BenchmarkAddNonConst(b *testing.B) {
  15  	p1 := jacobianPointFromHex(
  16  		"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
  17  		"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
  18  		"1",
  19  	)
  20  	p2 := jacobianPointFromHex(
  21  		"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
  22  		"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
  23  		"1",
  24  	)
  25  	b.ReportAllocs()
  26  	b.ResetTimer()
  27  	var result JacobianPoint
  28  	for i := 0; i < b.N; i++ {
  29  		AddNonConst(&p1, &p2, &result)
  30  	}
  31  }
  32  
  33  // BenchmarkAddNonConstNotZOne benchmarks the secp256k1 curve AddNonConst
  34  // function with Z values other than one so the optimizations associated with
  35  // Z=1 aren't used.
  36  func BenchmarkAddNonConstNotZOne(b *testing.B) {
  37  	x1 := new(FieldVal).SetHex("d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718")
  38  	y1 := new(FieldVal).SetHex("5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190")
  39  	z1 := new(FieldVal).SetHex("2")
  40  	x2 := new(FieldVal).SetHex("91abba6a34b7481d922a4bd6a04899d5a686f6cf6da4e66a0cb427fb25c04bd4")
  41  	y2 := new(FieldVal).SetHex("03fede65e30b4e7576a2abefc963ddbf9fdccbf791b77c29beadefe49951f7d1")
  42  	z2 := new(FieldVal).SetHex("3")
  43  	p1 := MakeJacobianPoint(x1, y1, z1)
  44  	p2 := MakeJacobianPoint(x2, y2, z2)
  45  	b.ReportAllocs()
  46  	b.ResetTimer()
  47  	var result JacobianPoint
  48  	for i := 0; i < b.N; i++ {
  49  		AddNonConst(&p1, &p2, &result)
  50  	}
  51  }
  52  
  53  // BenchmarkScalarBaseMultNonConst benchmarks multiplying a scalar by the base
  54  // point of the curve.
  55  func BenchmarkScalarBaseMultNonConst(b *testing.B) {
  56  	k := hexToModNScalar("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
  57  	b.ReportAllocs()
  58  	b.ResetTimer()
  59  	var result JacobianPoint
  60  	for i := 0; i < b.N; i++ {
  61  		ScalarBaseMultNonConst(k, &result)
  62  	}
  63  }
  64  
  65  // BenchmarkSplitK benchmarks decomposing scalars into a balanced length-two
  66  // representation.
  67  func BenchmarkSplitK(b *testing.B) {
  68  	// Values computed from the group half order and lambda such that they
  69  	// exercise the decomposition edge cases and maximize the bit lengths of the
  70  	// produced scalars.
  71  	h := "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0"
  72  	negOne := new(ModNScalar).NegateVal(oneModN)
  73  	halfOrder := hexToModNScalar(h)
  74  	halfOrderMOne := new(ModNScalar).Add2(halfOrder, negOne)
  75  	halfOrderPOne := new(ModNScalar).Add2(halfOrder, oneModN)
  76  	lambdaMOne := new(ModNScalar).Add2(endoLambda, negOne)
  77  	lambdaPOne := new(ModNScalar).Add2(endoLambda, oneModN)
  78  	negLambda := new(ModNScalar).NegateVal(endoLambda)
  79  	halfOrderMOneMLambda := new(ModNScalar).Add2(halfOrderMOne, negLambda)
  80  	halfOrderMLambda := new(ModNScalar).Add2(halfOrder, negLambda)
  81  	halfOrderPOneMLambda := new(ModNScalar).Add2(halfOrderPOne, negLambda)
  82  	lambdaPHalfOrder := new(ModNScalar).Add2(endoLambda, halfOrder)
  83  	lambdaPOnePHalfOrder := new(ModNScalar).Add2(lambdaPOne, halfOrder)
  84  	scalars := []*ModNScalar{
  85  		new(ModNScalar),      // zero
  86  		oneModN,              // one
  87  		negOne,               // group order - 1 (aka -1 mod N)
  88  		halfOrderMOneMLambda, // group half order - 1 - lambda
  89  		halfOrderMLambda,     // group half order - lambda
  90  		halfOrderPOneMLambda, // group half order + 1 - lambda
  91  		halfOrderMOne,        // group half order - 1
  92  		halfOrder,            // group half order
  93  		halfOrderPOne,        // group half order + 1
  94  		lambdaMOne,           // lambda - 1
  95  		endoLambda,           // lambda
  96  		lambdaPOne,           // lambda + 1
  97  		lambdaPHalfOrder,     // lambda + group half order
  98  		lambdaPOnePHalfOrder, // lambda + 1 + group half order
  99  	}
 100  	b.ReportAllocs()
 101  	b.ResetTimer()
 102  	for i := 0; i < b.N; i += len(scalars) {
 103  		for j := 0; j < len(scalars); j++ {
 104  			_, _ = splitK(scalars[j])
 105  		}
 106  	}
 107  }
 108  
 109  // BenchmarkScalarMultNonConst benchmarks multiplying a scalar by an arbitrary
 110  // point on the curve.
 111  func BenchmarkScalarMultNonConst(b *testing.B) {
 112  	k := hexToModNScalar("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
 113  	point := jacobianPointFromHex(
 114  		"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
 115  		"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
 116  		"1",
 117  	)
 118  	b.ReportAllocs()
 119  	b.ResetTimer()
 120  	var result JacobianPoint
 121  	for i := 0; i < b.N; i++ {
 122  		ScalarMultNonConst(k, &point, &result)
 123  	}
 124  }
 125  
 126  // BenchmarkNAF benchmarks conversion of a positive integer into its
 127  // non-adjacent form representation.
 128  func BenchmarkNAF(b *testing.B) {
 129  	k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
 130  	kBytes := k.Bytes()
 131  	b.ReportAllocs()
 132  	b.ResetTimer()
 133  	for i := 0; i < b.N; i++ {
 134  		naf(kBytes)
 135  	}
 136  }
 137  
 138  // BenchmarkPubKeyDecompress benchmarks how long it takes to decompress the  y
 139  // coordinate from a given public key x coordinate.
 140  func BenchmarkPubKeyDecompress(b *testing.B) {
 141  	// Randomly generated keypair.
 142  	// Secret key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d
 143  	pubKeyX := new(FieldVal).SetHex("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab")
 144  	b.ReportAllocs()
 145  	b.ResetTimer()
 146  	var y FieldVal
 147  	for i := 0; i < b.N; i++ {
 148  		_ = DecompressY(pubKeyX, false, &y)
 149  	}
 150  }
 151  
 152  // BenchmarkParsePubKeyCompressed benchmarks how long it takes to parse a
 153  // compressed public key with an even y coordinate.
 154  func BenchmarkParsePubKeyCompressed(b *testing.B) {
 155  	format := "02"
 156  	x := "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d"
 157  	pubKeyBytes := hexToBytes(format + x)
 158  	b.ReportAllocs()
 159  	b.ResetTimer()
 160  	for i := 0; i < b.N; i++ {
 161  		ParsePubKey(pubKeyBytes)
 162  	}
 163  }
 164  
 165  // BenchmarkParsePubKeyUncompressed benchmarks how long it takes to parse an
 166  // uncompressed public key.
 167  func BenchmarkParsePubKeyUncompressed(b *testing.B) {
 168  	format := "04"
 169  	x := "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"
 170  	y := "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"
 171  	pubKeyBytes := hexToBytes(format + x + y)
 172  	b.ReportAllocs()
 173  	b.ResetTimer()
 174  	for i := 0; i < b.N; i++ {
 175  		ParsePubKey(pubKeyBytes)
 176  	}
 177  }
 178