Bitcoin ABC 0.33.5
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
14#ifdef ENABLE_MODULE_SCHNORR
16#endif
17
18static void help(int default_iters) {
19 printf("Benchmarks the following algorithms:\n");
20 printf(" - ECDSA signing/verification\n");
21
22#ifdef ENABLE_MODULE_ECDH
23 printf(" - ECDH key exchange (optional module)\n");
24#endif
25
26#ifdef ENABLE_MODULE_RECOVERY
27 printf(" - Public key recovery (optional module)\n");
28#endif
29
30#ifdef ENABLE_MODULE_SCHNORR
31 printf(" - eCash Schnorr signatures (optional module)\n");
32#endif
33
34#ifdef ENABLE_MODULE_SCHNORRSIG
35 printf(" - Taproot Schnorr signatures (optional module)\n");
36#endif
37
38
39 printf("\n");
40 printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters);
41 printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n");
42 printf("\n");
43 printf("Usage: ./bench [args]\n");
44 printf("By default, all benchmarks will be run.\n");
45 printf("args:\n");
46 printf(" help : display this help and exit\n");
47 printf(" ecdsa : all ECDSA algorithms--sign, verify, recovery (if enabled)\n");
48 printf(" ecdsa_sign : ECDSA siging algorithm\n");
49 printf(" ecdsa_verify : ECDSA verification algorithm\n");
50 printf(" ec : all EC public key algorithms (keygen)\n");
51 printf(" ec_keygen : EC public key generation\n");
52
53#ifdef ENABLE_MODULE_RECOVERY
54 printf(" ecdsa_recover : ECDSA public key recovery algorithm\n");
55#endif
56
57#ifdef ENABLE_MODULE_ECDH
58 printf(" ecdh : ECDH key exchange algorithm\n");
59#endif
60
61#ifdef ENABLE_MODULE_SCHNORR
62 printf(" schnorr : all eCash Schnorr signature algorithms (sign, verify)\n");
63 printf(" schnorr_sign : eCash Schnorr sigining algorithm\n");
64 printf(" schnorr_verify : eCash Schnorr verification algorithm\n");
65#endif
66
67#ifdef ENABLE_MODULE_SCHNORRSIG
68 printf(" schnorrsig : all taproot Schnorr signature algorithms (sign, verify)\n");
69 printf(" schnorrsig_sign : taproot Schnorr sigining algorithm\n");
70 printf(" schnorrsig_verify : taproot Schnorr verification algorithm\n");
71#endif
72
73#ifdef ENABLE_MODULE_ELLSWIFT
74 printf(" ellswift : all ElligatorSwift benchmarks (encode, decode, keygen, ecdh)\n");
75 printf(" ellswift_encode : ElligatorSwift encoding\n");
76 printf(" ellswift_decode : ElligatorSwift decoding\n");
77 printf(" ellswift_keygen : ElligatorSwift key generation\n");
78 printf(" ellswift_ecdh : ECDH on ElligatorSwift keys\n");
79#endif
80
81 printf("\n");
82}
83
84typedef struct {
86 unsigned char msg[32];
87 unsigned char key[32];
88 unsigned char sig[72];
89 size_t siglen;
90 unsigned char pubkey[33];
91 size_t pubkeylen;
93
94static void bench_verify(void* arg, int iters) {
95 int i;
96 bench_data* data = (bench_data*)arg;
97
98 for (i = 0; i < iters; i++) {
99 secp256k1_pubkey pubkey;
101 data->sig[data->siglen - 1] ^= (i & 0xFF);
102 data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
103 data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
104 CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
105 CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
106 CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0));
107 data->sig[data->siglen - 1] ^= (i & 0xFF);
108 data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
109 data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
110 }
111}
112
113#ifdef ENABLE_MODULE_SCHNORR
114static void bench_schnorr_verify(void* arg, int iters) {
115 int i;
116 bench_data* data = (bench_data*)arg;
117
118 for (i = 0; i < iters; i++) {
119 secp256k1_pubkey pubkey;
120 data->sig[data->siglen - 1] ^= (i & 0xFF);
121 data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
122 data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
123 CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
124 CHECK(secp256k1_schnorr_verify(data->ctx, data->sig, data->msg, &pubkey) == (i == 0));
125 data->sig[data->siglen - 1] ^= (i & 0xFF);
126 data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
127 data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
128 }
129}
130#endif
131
132static void bench_sign_setup(void* arg) {
133 int i;
134 bench_data *data = (bench_data*)arg;
135
136 for (i = 0; i < 32; i++) {
137 data->msg[i] = i + 1;
138 }
139 for (i = 0; i < 32; i++) {
140 data->key[i] = i + 65;
141 }
142}
143
144static void bench_sign_run(void* arg, int iters) {
145 int i;
146 bench_data *data = (bench_data*)arg;
147
148 unsigned char sig[74];
149 for (i = 0; i < iters; i++) {
150 size_t siglen = 74;
151 int j;
153 CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL));
154 CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature));
155 for (j = 0; j < 32; j++) {
156 data->msg[j] = sig[j];
157 data->key[j] = sig[j + 32];
158 }
159 }
160}
161
162static void bench_keygen_setup(void* arg) {
163 int i;
164 bench_data *data = (bench_data*)arg;
165
166 for (i = 0; i < 32; i++) {
167 data->key[i] = i + 65;
168 }
169}
170
171static void bench_keygen_run(void *arg, int iters) {
172 int i;
173 bench_data *data = (bench_data*)arg;
174
175 for (i = 0; i < iters; i++) {
176 unsigned char pub33[33];
177 size_t len = 33;
178 secp256k1_pubkey pubkey;
179 CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->key));
180 CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pub33, &len, &pubkey, SECP256K1_EC_COMPRESSED));
181 memcpy(data->key, pub33 + 1, 32);
182 }
183}
184
185#ifdef ENABLE_MODULE_SCHNORR
186static void bench_schnorr_sign_run(void* arg, int iters) {
187 int i,j;
188 bench_data *data = (bench_data*)arg;
189
190 unsigned char sig[64];
191 for (i = 0; i < iters; i++) {
192 CHECK(secp256k1_schnorr_sign(data->ctx, sig, data->msg, data->key, NULL, NULL));
193 for (j = 0; j < 32; j++) {
194 data->msg[j] = sig[j];
195 data->key[j] = sig[j + 32];
196 }
197 }
198}
199#endif
200
201#ifdef ENABLE_MODULE_ECDH
203#endif
204
205#ifdef ENABLE_MODULE_RECOVERY
207#endif
208
209#ifdef ENABLE_MODULE_SCHNORRSIG
211#endif
212
213#ifdef ENABLE_MODULE_MULTISET
215#endif
216
217#ifdef ENABLE_MODULE_ELLSWIFT
219#endif
220
221int main(int argc, char** argv) {
222 int i;
223 secp256k1_pubkey pubkey;
225 bench_data data;
226
227 int d = argc == 1;
228 int default_iters = 20000;
229 int iters = get_iters(default_iters);
230
231 /* Check for invalid user arguments */
232 char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
233 "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec",
234 "keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode",
235 "ellswift_decode", "ellswift_keygen", "ellswift_ecdh"};
236 size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
237 int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);
238
239 if (argc > 1) {
240 if (have_flag(argc, argv, "-h")
241 || have_flag(argc, argv, "--help")
242 || have_flag(argc, argv, "help")) {
243 help(default_iters);
244 return 0;
245 } else if (invalid_args) {
246 fprintf(stderr, "./bench: unrecognized argument.\n\n");
247 help(default_iters);
248 return 1;
249 }
250 }
251
252/* Check if the user tries to benchmark optional module without building it */
253#ifndef ENABLE_MODULE_ECDH
254 if (have_flag(argc, argv, "ecdh")) {
255 fprintf(stderr, "./bench: ECDH module not enabled.\n");
256 fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
257 return 1;
258 }
259#endif
260
261#ifndef ENABLE_MODULE_RECOVERY
262 if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
263 fprintf(stderr, "./bench: Public key recovery module not enabled.\n");
264 fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n");
265 return 1;
266 }
267#endif
268
269#ifndef ENABLE_MODULE_SCHNORRSIG
270 if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
271 fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
272 fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
273 return 1;
274 }
275#endif
276
277#ifndef ENABLE_MODULE_ELLSWIFT
278 if (have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ellswift_encode") || have_flag(argc, argv, "ellswift_decode") ||
279 have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") ||
280 have_flag(argc, argv, "ellswift_ecdh")) {
281 fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n");
282 fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n");
283 return 1;
284 }
285#endif
286
287 /* ECDSA benchmark */
289
290 for (i = 0; i < 32; i++) {
291 data.msg[i] = 1 + i;
292 }
293 for (i = 0; i < 32; i++) {
294 data.key[i] = 33 + i;
295 }
296 data.siglen = 72;
297 CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL));
299 CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
300 data.pubkeylen = 33;
302
304 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);
305
306#ifdef ENABLE_MODULE_SCHNORR
307 if (d || have_flag(argc, argv, "schnorr") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "schnorr_verify")) {
308 CHECK(secp256k1_schnorr_sign(data.ctx, data.sig, data.msg, data.key, NULL, NULL));
309 data.siglen = 64;
310 run_benchmark("schnorr_verify", bench_schnorr_verify, NULL, NULL, &data, 10, iters);
311 }
312#endif
313
314 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);
315 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);
316#ifdef ENABLE_MODULE_SCHNORR
317 if (d || have_flag(argc, argv, "schnorr") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "schnorr_sign")) run_benchmark("schnorr_sign", bench_schnorr_sign_run, bench_sign_setup, NULL, &data, 10, iters);
318#endif
319
321
322#ifdef ENABLE_MODULE_ECDH
323 /* ECDH benchmarks */
324 run_ecdh_bench(iters, argc, argv);
325#endif
326
327#ifdef ENABLE_MODULE_RECOVERY
328 /* ECDSA recovery benchmarks */
329 run_recovery_bench(iters, argc, argv);
330#endif
331
332#ifdef ENABLE_MODULE_SCHNORRSIG
333 /* Schnorr signature benchmarks */
334 run_schnorrsig_bench(iters, argc, argv);
335#endif
336
337#ifdef ENABLE_MODULE_MULTISET
338 run_multiset_bench(iters, argc, argv);
339#endif
340
341#ifdef ENABLE_MODULE_ELLSWIFT
342 /* ElligatorSwift benchmarks */
343 run_ellswift_bench(iters, argc, argv);
344#endif
345
346 return 0;
347}
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:157
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
static void run_multiset_bench(int iters, int argc, char **argv)
Definition: bench_impl.h:44
void printf(const char *fmt, const Args &...args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1126
SchnorrSig sig
Definition: processor.cpp:537
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:18
static void bench_keygen_run(void *arg, int iters)
Definition: bench.c:171
static void bench_sign_setup(void *arg)
Definition: bench.c:132
static void bench_sign_run(void *arg, int iters)
Definition: bench.c:144
static void bench_keygen_setup(void *arg)
Definition: bench.c:162
static void bench_verify(void *arg, int iters)
Definition: bench.c:94
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
#define CHECK(cond)
Definition: util.h:128
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:186
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:290
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:140
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:558
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:272
#define SECP256K1_CONTEXT_NONE
Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size,...
Definition: secp256k1.h:192
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:363
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:596
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:202
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:444
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:400
SECP256K1_API int secp256k1_schnorr_sign(const secp256k1_context *ctx, unsigned char *sig64, 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 a signature using a custom EC-Schnorr-SHA256 construction.
Definition: main_impl.h:32
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify(const secp256k1_context *ctx, const unsigned char *sig64, 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 a signature created by secp256k1_schnorr_sign.
Definition: main_impl.h:13
secp256k1_context * ctx
Definition: bench.c:85
size_t siglen
Definition: bench.c:89
unsigned char pubkey[33]
Definition: bench.c:90
size_t pubkeylen
Definition: bench.c:91
unsigned char sig[72]
Definition: bench.c:88
unsigned char msg[32]
Definition: bench.c:86
unsigned char key[32]
Definition: bench.c:87
Opaque data structured 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