Bitcoin Core 28.99.0
P2P Digital Currency
bench.c
Go to the documentation of this file.
1/***********************************************************************
2 * Copyright (c) 2014 Pieter Wuille *
3 * Distributed under the MIT software license, see the accompanying *
4 * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
5 ***********************************************************************/
6
7#include <stdio.h>
8#include <string.h>
9
10#include "../include/secp256k1.h"
11#include "util.h"
12#include "bench.h"
13
14static void help(int default_iters) {
15 printf("Benchmarks the following algorithms:\n");
16 printf(" - ECDSA signing/verification\n");
17
18#ifdef ENABLE_MODULE_ECDH
19 printf(" - ECDH key exchange (optional module)\n");
20#endif
21
22#ifdef ENABLE_MODULE_RECOVERY
23 printf(" - Public key recovery (optional module)\n");
24#endif
25
26#ifdef ENABLE_MODULE_SCHNORRSIG
27 printf(" - Schnorr signatures (optional module)\n");
28#endif
29
30 printf("\n");
31 printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters);
32 printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n");
33 printf("\n");
34 printf("Usage: ./bench [args]\n");
35 printf("By default, all benchmarks will be run.\n");
36 printf("args:\n");
37 printf(" help : display this help and exit\n");
38 printf(" ecdsa : all ECDSA algorithms--sign, verify, recovery (if enabled)\n");
39 printf(" ecdsa_sign : ECDSA siging algorithm\n");
40 printf(" ecdsa_verify : ECDSA verification algorithm\n");
41 printf(" ec : all EC public key algorithms (keygen)\n");
42 printf(" ec_keygen : EC public key generation\n");
43
44#ifdef ENABLE_MODULE_RECOVERY
45 printf(" ecdsa_recover : ECDSA public key recovery algorithm\n");
46#endif
47
48#ifdef ENABLE_MODULE_ECDH
49 printf(" ecdh : ECDH key exchange algorithm\n");
50#endif
51
52#ifdef ENABLE_MODULE_SCHNORRSIG
53 printf(" schnorrsig : all Schnorr signature algorithms (sign, verify)\n");
54 printf(" schnorrsig_sign : Schnorr sigining algorithm\n");
55 printf(" schnorrsig_verify : Schnorr verification algorithm\n");
56#endif
57
58#ifdef ENABLE_MODULE_ELLSWIFT
59 printf(" ellswift : all ElligatorSwift benchmarks (encode, decode, keygen, ecdh)\n");
60 printf(" ellswift_encode : ElligatorSwift encoding\n");
61 printf(" ellswift_decode : ElligatorSwift decoding\n");
62 printf(" ellswift_keygen : ElligatorSwift key generation\n");
63 printf(" ellswift_ecdh : ECDH on ElligatorSwift keys\n");
64#endif
65
66 printf("\n");
67}
68
69typedef struct {
71 unsigned char msg[32];
72 unsigned char key[32];
73 unsigned char sig[72];
74 size_t siglen;
75 unsigned char pubkey[33];
76 size_t pubkeylen;
78
79static void bench_verify(void* arg, int iters) {
80 int i;
81 bench_data* data = (bench_data*)arg;
82
83 for (i = 0; i < iters; i++) {
84 secp256k1_pubkey pubkey;
86 data->sig[data->siglen - 1] ^= (i & 0xFF);
87 data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
88 data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
89 CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
90 CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
91 CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0));
92 data->sig[data->siglen - 1] ^= (i & 0xFF);
93 data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
94 data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
95 }
96}
97
98static void bench_sign_setup(void* arg) {
99 int i;
100 bench_data *data = (bench_data*)arg;
101
102 for (i = 0; i < 32; i++) {
103 data->msg[i] = i + 1;
104 }
105 for (i = 0; i < 32; i++) {
106 data->key[i] = i + 65;
107 }
108}
109
110static void bench_sign_run(void* arg, int iters) {
111 int i;
112 bench_data *data = (bench_data*)arg;
113
114 unsigned char sig[74];
115 for (i = 0; i < iters; i++) {
116 size_t siglen = 74;
117 int j;
119 CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL));
120 CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature));
121 for (j = 0; j < 32; j++) {
122 data->msg[j] = sig[j];
123 data->key[j] = sig[j + 32];
124 }
125 }
126}
127
128static void bench_keygen_setup(void* arg) {
129 int i;
130 bench_data *data = (bench_data*)arg;
131
132 for (i = 0; i < 32; i++) {
133 data->key[i] = i + 65;
134 }
135}
136
137static void bench_keygen_run(void *arg, int iters) {
138 int i;
139 bench_data *data = (bench_data*)arg;
140
141 for (i = 0; i < iters; i++) {
142 unsigned char pub33[33];
143 size_t len = 33;
144 secp256k1_pubkey pubkey;
145 CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->key));
147 memcpy(data->key, pub33 + 1, 32);
148 }
149}
150
151
152#ifdef ENABLE_MODULE_ECDH
154#endif
155
156#ifdef ENABLE_MODULE_RECOVERY
158#endif
159
160#ifdef ENABLE_MODULE_SCHNORRSIG
162#endif
163
164#ifdef ENABLE_MODULE_ELLSWIFT
166#endif
167
168int main(int argc, char** argv) {
169 int i;
170 secp256k1_pubkey pubkey;
173
174 int d = argc == 1;
175 int default_iters = 20000;
176 int iters = get_iters(default_iters);
177
178 /* Check for invalid user arguments */
179 char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
180 "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec",
181 "keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode",
182 "ellswift_decode", "ellswift_keygen", "ellswift_ecdh"};
183 size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
184 int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);
185
186 if (argc > 1) {
187 if (have_flag(argc, argv, "-h")
188 || have_flag(argc, argv, "--help")
189 || have_flag(argc, argv, "help")) {
190 help(default_iters);
191 return 0;
192 } else if (invalid_args) {
193 fprintf(stderr, "./bench: unrecognized argument.\n\n");
194 help(default_iters);
195 return 1;
196 }
197 }
198
199/* Check if the user tries to benchmark optional module without building it */
200#ifndef ENABLE_MODULE_ECDH
201 if (have_flag(argc, argv, "ecdh")) {
202 fprintf(stderr, "./bench: ECDH module not enabled.\n");
203 fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
204 return 1;
205 }
206#endif
207
208#ifndef ENABLE_MODULE_RECOVERY
209 if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
210 fprintf(stderr, "./bench: Public key recovery module not enabled.\n");
211 fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n");
212 return 1;
213 }
214#endif
215
216#ifndef ENABLE_MODULE_SCHNORRSIG
217 if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
218 fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
219 fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
220 return 1;
221 }
222#endif
223
224#ifndef ENABLE_MODULE_ELLSWIFT
225 if (have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ellswift_encode") || have_flag(argc, argv, "ellswift_decode") ||
226 have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") ||
227 have_flag(argc, argv, "ellswift_ecdh")) {
228 fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n");
229 fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n");
230 return 1;
231 }
232#endif
233
234 /* ECDSA benchmark */
236
237 for (i = 0; i < 32; i++) {
238 data.msg[i] = 1 + i;
239 }
240 for (i = 0; i < 32; i++) {
241 data.key[i] = 33 + i;
242 }
243 data.siglen = 72;
244 CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL));
246 CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
247 data.pubkeylen = 33;
248 CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
249
251 if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "ecdsa_verify")) run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters);
252
253 if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "ecdsa_sign")) run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters);
254 if (d || have_flag(argc, argv, "ec") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ec_keygen")) run_benchmark("ec_keygen", bench_keygen_run, bench_keygen_setup, NULL, &data, 10, iters);
255
257
258#ifdef ENABLE_MODULE_ECDH
259 /* ECDH benchmarks */
260 run_ecdh_bench(iters, argc, argv);
261#endif
262
263#ifdef ENABLE_MODULE_RECOVERY
264 /* ECDSA recovery benchmarks */
265 run_recovery_bench(iters, argc, argv);
266#endif
267
268#ifdef ENABLE_MODULE_SCHNORRSIG
269 /* Schnorr signature benchmarks */
270 run_schnorrsig_bench(iters, argc, argv);
271#endif
272
273#ifdef ENABLE_MODULE_ELLSWIFT
274 /* ElligatorSwift benchmarks */
275 run_ellswift_bench(iters, argc, argv);
276#endif
277
278 return 0;
279}
static void run_benchmark(char *name, void(*benchmark)(void *), void(*setup)(void *), void(*teardown)(void *), void *data, int count, int iter)
Definition: bench.c:26
int main(void)
Definition: bench.c:156
static void run_ecdh_bench(int iters, int argc, char **argv)
Definition: bench_impl.h:45
void run_ellswift_bench(int iters, int argc, char **argv)
Definition: bench_impl.h:91
#define CHECK(cond)
Unconditional failure on condition failure.
Definition: util.h:35
void printf(FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1089
static void run_recovery_bench(int iters, int argc, char **argv)
Definition: bench_impl.h:51
static void run_schnorrsig_bench(int iters, int argc, char **argv)
Definition: bench_impl.h:48
static void help(int default_iters)
Definition: bench.c:14
static void bench_keygen_run(void *arg, int iters)
Definition: bench.c:137
static void bench_sign_setup(void *arg)
Definition: bench.c:98
static void bench_sign_run(void *arg, int iters)
Definition: bench.c:110
static void bench_keygen_setup(void *arg)
Definition: bench.c:128
static void bench_verify(void *arg, int iters)
Definition: bench.c:79
static int get_iters(int default_iters)
Definition: bench.h:170
static void print_output_table_header_row(void)
Definition: bench.h:179
static int have_invalid_args(int argc, char **argv, char **valid_args, size_t n)
Definition: bench.h:148
static int have_flag(int argc, char **argv, char *flag)
Definition: bench.h:132
SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx) SECP256K1_ARG_NONNULL(1)
Destroy a secp256k1 context object (created in dynamically allocated memory).
Definition: secp256k1.c:187
SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Serialize a pubkey object into a serialized byte sequence.
Definition: secp256k1.c:268
SECP256K1_API secp256k1_context * secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT
Create a secp256k1 context object (in dynamically allocated memory).
Definition: secp256k1.c:141
SECP256K1_API int secp256k1_ecdsa_sign(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Create an ECDSA signature.
Definition: secp256k1.c:566
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a variable-length public key into the pubkey object.
Definition: secp256k1.c:250
#define SECP256K1_CONTEXT_NONE
Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size,...
Definition: secp256k1.h:202
SECP256K1_API int secp256k1_ecdsa_signature_parse_der(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, const unsigned char *input, size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a DER ECDSA signature.
Definition: secp256k1.c:369
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Compute the public key for a secret key.
Definition: secp256k1.c:604
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:212
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msghash32, const secp256k1_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Verify an ECDSA signature.
Definition: secp256k1.c:450
SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature *sig) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Serialize an ECDSA signature in DER format.
Definition: secp256k1.c:406
secp256k1_context * ctx
Definition: bench.c:70
size_t siglen
Definition: bench.c:74
size_t pubkeylen
Definition: bench.c:76
Opaque data structure that holds a parsed ECDSA signature.
Definition: secp256k1.h:74
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:61