field_bench_test.go raw

   1  // Copyright (c) 2020-2023 The Decred 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 secp256k1
   6  
   7  import (
   8  	"math/big"
   9  	"testing"
  10  )
  11  
  12  // BenchmarkFieldNormalize benchmarks how long it takes the internal field
  13  // to perform normalization (which includes modular reduction).
  14  func BenchmarkFieldNormalize(b *testing.B) {
  15  	// The function is constant time so any value is fine.
  16  	f := &FieldVal{
  17  		n: [10]uint32{
  18  			0x000148f6, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff,
  19  			0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x00000007,
  20  		},
  21  	}
  22  	b.ReportAllocs()
  23  	b.ResetTimer()
  24  	for i := 0; i < b.N; i++ {
  25  		f.Normalize()
  26  	}
  27  }
  28  
  29  // BenchmarkFieldSqrt benchmarks calculating the square root of an unsigned
  30  // 256-bit big-endian integer modulo the field prime  with the specialized type.
  31  func BenchmarkFieldSqrt(b *testing.B) {
  32  	// The function is constant time so any value is fine.
  33  	valHex := "16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca"
  34  	f := new(FieldVal).SetHex(valHex).Normalize()
  35  	b.ReportAllocs()
  36  	b.ResetTimer()
  37  	for i := 0; i < b.N; i++ {
  38  		var result FieldVal
  39  		_ = result.SquareRootVal(f)
  40  	}
  41  }
  42  
  43  // BenchmarkBigSqrt benchmarks calculating the square root of an unsigned
  44  // 256-bit big-endian integer modulo the field prime with stdlib big integers.
  45  func BenchmarkBigSqrt(b *testing.B) {
  46  	// The function is constant time so any value is fine.
  47  	valHex := "16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca"
  48  	val, ok := new(big.Int).SetString(valHex, 16)
  49  	if !ok {
  50  		b.Fatalf("failed to parse hex %s", valHex)
  51  	}
  52  	b.ReportAllocs()
  53  	b.ResetTimer()
  54  	for i := 0; i < b.N; i++ {
  55  		_ = new(big.Int).ModSqrt(val, curveParams.P)
  56  	}
  57  }
  58  
  59  // BenchmarkFieldIsGtOrEqPrimeMinusOrder benchmarks determining whether a value
  60  // is greater than or equal to the field prime minus the group order with the
  61  // specialized type.
  62  func BenchmarkFieldIsGtOrEqPrimeMinusOrder(b *testing.B) {
  63  	// The function is constant time so any value is fine.
  64  	valHex := "16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca"
  65  	f := new(FieldVal).SetHex(valHex).Normalize()
  66  	b.ReportAllocs()
  67  	b.ResetTimer()
  68  	for i := 0; i < b.N; i++ {
  69  		_ = f.IsGtOrEqPrimeMinusOrder()
  70  	}
  71  }
  72  
  73  // BenchmarkBigIsGtOrEqPrimeMinusOrder benchmarks determining whether a value
  74  // is greater than or equal to the field prime minus the group order with stdlib
  75  // big integers.
  76  func BenchmarkBigIsGtOrEqPrimeMinusOrder(b *testing.B) {
  77  	// Same value used in field val version.
  78  	valHex := "16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca"
  79  	val, ok := new(big.Int).SetString(valHex, 16)
  80  	if !ok {
  81  		b.Fatalf("failed to parse hex %s", valHex)
  82  	}
  83  	bigPMinusN := new(big.Int).Sub(curveParams.P, curveParams.N)
  84  	b.ReportAllocs()
  85  	b.ResetTimer()
  86  	for i := 0; i < b.N; i++ {
  87  		// In practice, the internal value to compare would have to be converted
  88  		// to a big integer from bytes, so it's a fair comparison to allocate a
  89  		// new big int here and set all bytes.
  90  		_ = new(big.Int).SetBytes(val.Bytes()).Cmp(bigPMinusN) >= 0
  91  	}
  92  }
  93