...

Source file src/github.com/decred/dcrd/dcrec/secp256k1/v4/bench_test.go

Documentation: github.com/decred/dcrd/dcrec/secp256k1/v4

     1  // Copyright (c) 2015-2024 The Decred developers
     2  // Copyright 2013-2016 The btcsuite 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  
    26  	b.ReportAllocs()
    27  	b.ResetTimer()
    28  	var result JacobianPoint
    29  	for i := 0; i < b.N; i++ {
    30  		AddNonConst(&p1, &p2, &result)
    31  	}
    32  }
    33  
    34  // BenchmarkAddNonConstNotZOne benchmarks the secp256k1 curve AddNonConst
    35  // function with Z values other than one so the optimizations associated with
    36  // Z=1 aren't used.
    37  func BenchmarkAddNonConstNotZOne(b *testing.B) {
    38  	x1 := new(FieldVal).SetHex("d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718")
    39  	y1 := new(FieldVal).SetHex("5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190")
    40  	z1 := new(FieldVal).SetHex("2")
    41  	x2 := new(FieldVal).SetHex("91abba6a34b7481d922a4bd6a04899d5a686f6cf6da4e66a0cb427fb25c04bd4")
    42  	y2 := new(FieldVal).SetHex("03fede65e30b4e7576a2abefc963ddbf9fdccbf791b77c29beadefe49951f7d1")
    43  	z2 := new(FieldVal).SetHex("3")
    44  	p1 := MakeJacobianPoint(x1, y1, z1)
    45  	p2 := MakeJacobianPoint(x2, y2, z2)
    46  
    47  	b.ReportAllocs()
    48  	b.ResetTimer()
    49  	var result JacobianPoint
    50  	for i := 0; i < b.N; i++ {
    51  		AddNonConst(&p1, &p2, &result)
    52  	}
    53  }
    54  
    55  // BenchmarkScalarBaseMultNonConst benchmarks multiplying a scalar by the base
    56  // point of the curve using whichever variant is active.
    57  func BenchmarkScalarBaseMultNonConst(b *testing.B) {
    58  	k := hexToModNScalar("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
    59  
    60  	b.ReportAllocs()
    61  	b.ResetTimer()
    62  	var result JacobianPoint
    63  	for i := 0; i < b.N; i++ {
    64  		ScalarBaseMultNonConst(k, &result)
    65  	}
    66  }
    67  
    68  // BenchmarkScalarBaseMultNonConstFast benchmarks multiplying a scalar by the
    69  // base point of the curve using the fast variant.
    70  func BenchmarkScalarBaseMultNonConstFast(b *testing.B) {
    71  	k := hexToModNScalar("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
    72  
    73  	b.ReportAllocs()
    74  	b.ResetTimer()
    75  	var result JacobianPoint
    76  	for i := 0; i < b.N; i++ {
    77  		scalarBaseMultNonConstFast(k, &result)
    78  	}
    79  }
    80  
    81  // BenchmarkScalarBaseMultNonConstSlow benchmarks multiplying a scalar by the
    82  // base point of the curve using the resource-constrained slow variant.
    83  func BenchmarkScalarBaseMultNonConstSlow(b *testing.B) {
    84  	k := hexToModNScalar("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
    85  
    86  	b.ReportAllocs()
    87  	b.ResetTimer()
    88  	var result JacobianPoint
    89  	for i := 0; i < b.N; i++ {
    90  		scalarBaseMultNonConstSlow(k, &result)
    91  	}
    92  }
    93  
    94  // BenchmarkSplitK benchmarks decomposing scalars into a balanced length-two
    95  // representation.
    96  func BenchmarkSplitK(b *testing.B) {
    97  	// Values computed from the group half order and lambda such that they
    98  	// exercise the decomposition edge cases and maximize the bit lengths of the
    99  	// produced scalars.
   100  	h := "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0"
   101  	negOne := new(ModNScalar).NegateVal(oneModN)
   102  	halfOrder := hexToModNScalar(h)
   103  	halfOrderMOne := new(ModNScalar).Add2(halfOrder, negOne)
   104  	halfOrderPOne := new(ModNScalar).Add2(halfOrder, oneModN)
   105  	lambdaMOne := new(ModNScalar).Add2(endoLambda, negOne)
   106  	lambdaPOne := new(ModNScalar).Add2(endoLambda, oneModN)
   107  	negLambda := new(ModNScalar).NegateVal(endoLambda)
   108  	halfOrderMOneMLambda := new(ModNScalar).Add2(halfOrderMOne, negLambda)
   109  	halfOrderMLambda := new(ModNScalar).Add2(halfOrder, negLambda)
   110  	halfOrderPOneMLambda := new(ModNScalar).Add2(halfOrderPOne, negLambda)
   111  	lambdaPHalfOrder := new(ModNScalar).Add2(endoLambda, halfOrder)
   112  	lambdaPOnePHalfOrder := new(ModNScalar).Add2(lambdaPOne, halfOrder)
   113  	scalars := []*ModNScalar{
   114  		new(ModNScalar),      // zero
   115  		oneModN,              // one
   116  		negOne,               // group order - 1 (aka -1 mod N)
   117  		halfOrderMOneMLambda, // group half order - 1 - lambda
   118  		halfOrderMLambda,     // group half order - lambda
   119  		halfOrderPOneMLambda, // group half order + 1 - lambda
   120  		halfOrderMOne,        // group half order - 1
   121  		halfOrder,            // group half order
   122  		halfOrderPOne,        // group half order + 1
   123  		lambdaMOne,           // lambda - 1
   124  		endoLambda,           // lambda
   125  		lambdaPOne,           // lambda + 1
   126  		lambdaPHalfOrder,     // lambda + group half order
   127  		lambdaPOnePHalfOrder, // lambda + 1 + group half order
   128  	}
   129  
   130  	b.ReportAllocs()
   131  	b.ResetTimer()
   132  	for i := 0; i < b.N; i += len(scalars) {
   133  		for j := 0; j < len(scalars); j++ {
   134  			_, _ = splitK(scalars[j])
   135  		}
   136  	}
   137  }
   138  
   139  // BenchmarkScalarMultNonConst benchmarks multiplying a scalar by an arbitrary
   140  // point on the curve.
   141  func BenchmarkScalarMultNonConst(b *testing.B) {
   142  	k := hexToModNScalar("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
   143  	point := jacobianPointFromHex(
   144  		"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
   145  		"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
   146  		"1",
   147  	)
   148  
   149  	b.ReportAllocs()
   150  	b.ResetTimer()
   151  	var result JacobianPoint
   152  	for i := 0; i < b.N; i++ {
   153  		ScalarMultNonConst(k, &point, &result)
   154  	}
   155  }
   156  
   157  // BenchmarkNAF benchmarks conversion of a positive integer into its
   158  // non-adjacent form representation.
   159  func BenchmarkNAF(b *testing.B) {
   160  	k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
   161  	kBytes := k.Bytes()
   162  
   163  	b.ReportAllocs()
   164  	b.ResetTimer()
   165  	for i := 0; i < b.N; i++ {
   166  		naf(kBytes)
   167  	}
   168  }
   169  
   170  // BenchmarkPubKeyDecompress benchmarks how long it takes to decompress the  y
   171  // coordinate from a given public key x coordinate.
   172  func BenchmarkPubKeyDecompress(b *testing.B) {
   173  	// Randomly generated keypair.
   174  	// Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d
   175  	pubKeyX := new(FieldVal).SetHex("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab")
   176  
   177  	b.ReportAllocs()
   178  	b.ResetTimer()
   179  	var y FieldVal
   180  	for i := 0; i < b.N; i++ {
   181  		_ = DecompressY(pubKeyX, false, &y)
   182  	}
   183  }
   184  
   185  // BenchmarkParsePubKeyCompressed benchmarks how long it takes to parse a
   186  // compressed public key with an even y coordinate.
   187  func BenchmarkParsePubKeyCompressed(b *testing.B) {
   188  	format := "02"
   189  	x := "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d"
   190  	pubKeyBytes := hexToBytes(format + x)
   191  
   192  	b.ReportAllocs()
   193  	b.ResetTimer()
   194  	for i := 0; i < b.N; i++ {
   195  		ParsePubKey(pubKeyBytes)
   196  	}
   197  }
   198  
   199  // BenchmarkParsePubKeyUncompressed benchmarks how long it takes to parse an
   200  // uncompressed public key.
   201  func BenchmarkParsePubKeyUncompressed(b *testing.B) {
   202  	format := "04"
   203  	x := "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"
   204  	y := "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"
   205  	pubKeyBytes := hexToBytes(format + x + y)
   206  
   207  	b.ReportAllocs()
   208  	b.ResetTimer()
   209  	for i := 0; i < b.N; i++ {
   210  		ParsePubKey(pubKeyBytes)
   211  	}
   212  }
   213  

View as plain text