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