Skip to content

Commit e5df505

Browse files
committed
batch, extrakeys: Add benchmarks
This commit adds benchmarks for: 1. Batch verifying Schnorr signatures 2. Batch verifying tweaked pubkey checks 3. Normal tweaked pubkey check in extrakeys module For batch verify benchmark, the number of sigs (or checks) in the batch varies from 1 to SECP256K1_BENCH_ITERS with a 20% increment.
1 parent 642901f commit e5df505

File tree

4 files changed

+225
-4
lines changed

4 files changed

+225
-4
lines changed

src/bench.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,20 @@ static void help(int default_iters) {
5454
printf(" ecdh : ECDH key exchange algorithm\n");
5555
#endif
5656

57+
#ifdef ENABLE_MODULE_EXTRAKEYS
58+
printf(" tweak_add_check : Checks if tweaked x-only pubkey is valid\n");
59+
# ifdef ENABLE_MODULE_BATCH
60+
printf(" batch_tweak_checks : Batch verification of tweaked x-only pubkeys check\n");
61+
# endif
62+
#endif
63+
5764
#ifdef ENABLE_MODULE_SCHNORRSIG
5865
printf(" schnorrsig : all Schnorr signature algorithms (sign, verify)\n");
5966
printf(" schnorrsig_sign : Schnorr sigining algorithm\n");
6067
printf(" schnorrsig_verify : Schnorr verification algorithm\n");
68+
#ifdef ENABLE_MODULE_BATCH
69+
printf(" batch_schnorrsigs : Batch verification of Schnorr signatures\n");
70+
#endif
6171
#endif
6272

6373
#ifdef ENABLE_MODULE_ELLSWIFT
@@ -162,6 +172,10 @@ static void bench_keygen_run(void *arg, int iters) {
162172
# include "modules/recovery/bench_impl.h"
163173
#endif
164174

175+
#ifdef ENABLE_MODULE_EXTRAKEYS
176+
# include "modules/extrakeys/bench_impl.h"
177+
#endif
178+
165179
#ifdef ENABLE_MODULE_SCHNORRSIG
166180
# include "modules/schnorrsig/bench_impl.h"
167181
#endif
@@ -182,7 +196,7 @@ int main(int argc, char** argv) {
182196

183197
/* Check for invalid user arguments */
184198
char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
185-
"ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec",
199+
"ecdsa_recover", "extrakeys", "tweak_add_check", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "batch", "batch_tweak_checks", "batch_schnorrsigs", "ec",
186200
"keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode",
187201
"ellswift_decode", "ellswift_keygen", "ellswift_ecdh"};
188202
size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
@@ -219,13 +233,29 @@ int main(int argc, char** argv) {
219233
#endif
220234

221235
#ifndef ENABLE_MODULE_SCHNORRSIG
222-
if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
236+
if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify") || have_flag(argc, argv, "batch_schnorrsigs")) {
223237
fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
224238
fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
225239
return EXIT_FAILURE;
226240
}
227241
#endif
228242

243+
#ifndef ENABLE_MODULE_EXTRAKEYS
244+
if (have_flag(argc, argv, "extrakeys") || have_flag(argc, argv, "tweak_add_check") || have_flag(argc, argv, "batch_tweak_checks")) {
245+
fprintf(stderr, "./bench: extrakeys module not enabled.\n");
246+
fprintf(stderr, "Use ./configure --enable-module-extrakeys.\n\n");
247+
return EXIT_FAILURE;
248+
}
249+
#endif
250+
251+
#ifndef ENABLE_MODULE_BATCH
252+
if (have_flag(argc, argv, "batch") || have_flag(argc, argv, "batch_schnorrsigs") || have_flag(argc, argv, "batch_tweak_checks")) {
253+
fprintf(stderr, "./bench: Batch module not enabled.\n");
254+
fprintf(stderr, "Use ./configure --enable-module-batch --enable-experimental.\n\n");
255+
return EXIT_FAILURE;
256+
}
257+
#endif
258+
229259
#ifndef ENABLE_MODULE_ELLSWIFT
230260
if (have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ellswift_encode") || have_flag(argc, argv, "ellswift_decode") ||
231261
have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") ||
@@ -270,6 +300,11 @@ int main(int argc, char** argv) {
270300
run_recovery_bench(iters, argc, argv);
271301
#endif
272302

303+
#ifdef ENABLE_MODULE_EXTRAKEYS
304+
/* Extrakeys benchmarks */
305+
run_extrakeys_bench(iters, argc, argv);
306+
#endif
307+
273308
#ifdef ENABLE_MODULE_SCHNORRSIG
274309
/* Schnorr signature benchmarks */
275310
run_schnorrsig_bench(iters, argc, argv);

src/bench.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setu
120120
sum += total;
121121
}
122122
/* ',' is used as a column delimiter */
123-
printf("%-30s, ", name);
123+
printf("%-35s, ", name);
124124
print_number(min * FP_MULT / iter);
125125
printf(" , ");
126126
print_number(((sum * FP_MULT) / count) / iter);
@@ -181,7 +181,7 @@ static void print_output_table_header_row(void) {
181181
char* min_str = " Min(us) "; /* center alignment */
182182
char* avg_str = " Avg(us) ";
183183
char* max_str = " Max(us) ";
184-
printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str);
184+
printf("%-35s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str);
185185
printf("\n");
186186
}
187187

src/modules/extrakeys/bench_impl.h

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
2+
#ifndef SECP256K1_MODULE_EXTRAKEYS_BENCH_H
3+
#define SECP256K1_MODULE_EXTRAKEYS_BENCH_H
4+
5+
#include "../../../include/secp256k1_extrakeys.h"
6+
#ifdef ENABLE_MODULE_BATCH
7+
# include "../../../include/secp256k1_batch.h"
8+
# include "../../../include/secp256k1_tweak_check_batch.h"
9+
#endif
10+
11+
typedef struct {
12+
secp256k1_context *ctx;
13+
#ifdef ENABLE_MODULE_BATCH
14+
secp256k1_batch *batch;
15+
/* number of tweak checks to batch verify.
16+
* it varies from 1 to iters with 20% increments */
17+
int n;
18+
#endif
19+
20+
const secp256k1_keypair **keypairs;
21+
const unsigned char **pks;
22+
const unsigned char **tweaked_pks;
23+
const int **tweaked_pk_parities;
24+
const unsigned char **tweaks;
25+
} bench_tweak_check_data;
26+
27+
static void bench_xonly_pubkey_tweak_add_check(void* arg, int iters) {
28+
bench_tweak_check_data *data = (bench_tweak_check_data *)arg;
29+
int i;
30+
31+
for (i = 0; i < iters; i++) {
32+
secp256k1_xonly_pubkey pk;
33+
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pks[i]) == 1);
34+
CHECK(secp256k1_xonly_pubkey_tweak_add_check(data->ctx, data->tweaked_pks[i], *data->tweaked_pk_parities[i], &pk, data->tweaks[i]) == 1);
35+
}
36+
}
37+
38+
#ifdef ENABLE_MODULE_BATCH
39+
static void bench_xonly_pubkey_tweak_add_check_n(void* arg, int iters) {
40+
bench_tweak_check_data *data = (bench_tweak_check_data *)arg;
41+
int i, j;
42+
43+
for (j = 0; j < iters/data->n; j++) {
44+
for (i = 0; i < data->n; i++) {
45+
secp256k1_xonly_pubkey pk;
46+
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pks[j+i]) == 1);
47+
CHECK(secp256k1_batch_usable(data->ctx, data->batch) == 1);
48+
CHECK(secp256k1_batch_add_xonlypub_tweak_check(data->ctx, data->batch, data->tweaked_pks[j+i], *data->tweaked_pk_parities[j+i], &pk, data->tweaks[j+i]) == 1);
49+
}
50+
CHECK(secp256k1_batch_verify(data->ctx, data->batch) == 1);
51+
}
52+
}
53+
#endif
54+
55+
static void run_extrakeys_bench(int iters, int argc, char** argv) {
56+
int i;
57+
bench_tweak_check_data data;
58+
int d = argc == 1;
59+
60+
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
61+
data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *));
62+
data.pks = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
63+
data.tweaked_pks = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
64+
data.tweaked_pk_parities = (const int **)malloc(iters * sizeof(int *));
65+
data.tweaks = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
66+
#ifdef ENABLE_MODULE_BATCH
67+
data.batch = secp256k1_batch_create(data.ctx, iters, NULL);
68+
CHECK(data.batch != NULL);
69+
#endif
70+
71+
for (i = 0; i < iters; i++) {
72+
unsigned char sk[32];
73+
unsigned char *tweaked_pk_char = (unsigned char *)malloc(32);
74+
int *tweaked_pk_parity = (int *)malloc(sizeof(int)); /*todo: use sizeof(*twk_parity) instead?*/
75+
unsigned char *tweak = (unsigned char *)malloc(32);
76+
secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair));
77+
unsigned char *pk_char = (unsigned char *)malloc(32);
78+
secp256k1_xonly_pubkey pk;
79+
secp256k1_pubkey output_pk;
80+
secp256k1_xonly_pubkey output_pk_xonly;
81+
tweak[0] = sk[0] = i;
82+
tweak[1] = sk[1] = i >> 8;
83+
tweak[2] = sk[2] = i >> 16;
84+
tweak[3] = sk[3] = i >> 24;
85+
memset(&tweak[4], 't', 28);
86+
memset(&sk[4], 's', 28);
87+
88+
data.keypairs[i] = keypair;
89+
data.pks[i] = pk_char;
90+
data.tweaked_pks[i] = tweaked_pk_char;
91+
data.tweaked_pk_parities[i] = tweaked_pk_parity;
92+
data.tweaks[i] = tweak;
93+
94+
CHECK(secp256k1_keypair_create(data.ctx, keypair, sk));
95+
CHECK(secp256k1_keypair_xonly_pub(data.ctx, &pk, NULL, keypair));
96+
CHECK(secp256k1_xonly_pubkey_tweak_add(data.ctx, &output_pk, &pk, tweak));
97+
CHECK(secp256k1_xonly_pubkey_from_pubkey(data.ctx, &output_pk_xonly, tweaked_pk_parity, &output_pk));
98+
CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, tweaked_pk_char, &output_pk_xonly) == 1);
99+
CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1);
100+
}
101+
102+
if (d || have_flag(argc, argv, "extrakeys") || have_flag(argc, argv, "tweak_add_check")) run_benchmark("tweak_add_check", bench_xonly_pubkey_tweak_add_check, NULL, NULL, (void *) &data, 10, iters);
103+
#ifdef ENABLE_MODULE_BATCH
104+
if (d || have_flag(argc, argv, "extrakeys") || have_flag(argc, argv, "batch") || have_flag(argc, argv, "batch_tweak_checks")) {
105+
for (i = 1; i <= iters; i = (int)(i*1.2 + 1)) {
106+
char name[64];
107+
int divisible_iters;
108+
sprintf(name, "batchverify_tweak_checks_%d", (int) i);
109+
110+
data.n = i;
111+
divisible_iters = iters - (iters % data.n);
112+
run_benchmark(name, bench_xonly_pubkey_tweak_add_check_n, NULL, NULL, (void *) &data, 3, divisible_iters);
113+
fflush(stdout);
114+
}
115+
}
116+
#endif
117+
118+
for (i = 0; i < iters; i++) {
119+
free((void *)data.keypairs[i]);
120+
free((void *)data.pks[i]);
121+
free((void *)data.tweaked_pks[i]);
122+
free((void *)data.tweaked_pk_parities[i]);
123+
free((void *)data.tweaks[i]);
124+
}
125+
126+
/* Casting to (void *) avoids a stupid warning in MSVC. */
127+
free((void *)data.keypairs);
128+
free((void *)data.pks);
129+
free((void *)data.tweaked_pks);
130+
free((void *)data.tweaked_pk_parities);
131+
free((void *)data.tweaks);
132+
133+
#ifdef ENABLE_MODULE_BATCH
134+
secp256k1_batch_destroy(data.ctx, data.batch);
135+
#endif
136+
secp256k1_context_destroy(data.ctx);
137+
}
138+
139+
#endif /* SECP256K1_MODULE_EXTRAKEYS_BENCH_H */

src/modules/schnorrsig/bench_impl.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,21 @@
88
#define SECP256K1_MODULE_SCHNORRSIG_BENCH_H
99

1010
#include "../../../include/secp256k1_schnorrsig.h"
11+
#ifdef ENABLE_MODULE_BATCH
12+
# include "../../../include/secp256k1_batch.h"
13+
# include "../../../include/secp256k1_schnorrsig_batch.h"
14+
#endif
1115

1216
#define MSGLEN 32
1317

1418
typedef struct {
1519
secp256k1_context *ctx;
20+
#ifdef ENABLE_MODULE_BATCH
21+
secp256k1_batch *batch;
22+
/* number of signatures to batch verify.
23+
* it varies from 1 to iters with 20% increments */
1624
int n;
25+
#endif
1726

1827
const secp256k1_keypair **keypairs;
1928
const unsigned char **pk;
@@ -45,6 +54,23 @@ static void bench_schnorrsig_verify(void* arg, int iters) {
4554
}
4655
}
4756

57+
#ifdef ENABLE_MODULE_BATCH
58+
static void bench_schnorrsig_verify_n(void* arg, int iters) {
59+
bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg;
60+
int i, j;
61+
62+
for (j = 0; j < iters/data->n; j++) {
63+
for (i = 0; i < data->n; i++) {
64+
secp256k1_xonly_pubkey pk;
65+
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[j+i]) == 1);
66+
CHECK(secp256k1_batch_usable(data->ctx, data->batch) == 1);
67+
CHECK(secp256k1_batch_add_schnorrsig(data->ctx, data->batch, data->sigs[j+i], data->msgs[j+i], MSGLEN, &pk) == 1);
68+
}
69+
CHECK(secp256k1_batch_verify(data->ctx, data->batch) == 1);
70+
}
71+
}
72+
#endif
73+
4874
static void run_schnorrsig_bench(int iters, int argc, char** argv) {
4975
int i;
5076
bench_schnorrsig_data data;
@@ -55,6 +81,10 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) {
5581
data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
5682
data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
5783
data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
84+
#ifdef ENABLE_MODULE_BATCH
85+
data.batch = secp256k1_batch_create(data.ctx, 2*iters, NULL);
86+
CHECK(data.batch != NULL);
87+
#endif
5888

5989
CHECK(MSGLEN >= 4);
6090
for (i = 0; i < iters; i++) {
@@ -84,6 +114,20 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) {
84114

85115
if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "schnorrsig_sign")) run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters);
86116
if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "schnorrsig_verify")) run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters);
117+
#ifdef ENABLE_MODULE_BATCH
118+
if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "batch") || have_flag(argc, argv, "batch_schnorrsigs")) {
119+
for (i = 1; i <= iters; i = (int)(i*1.2 + 1)) {
120+
char name[64];
121+
int divisible_iters;
122+
sprintf(name, "batchverify_schnorrsigs_%d", (int) i);
123+
124+
data.n = i;
125+
divisible_iters = iters - (iters % data.n);
126+
run_benchmark(name, bench_schnorrsig_verify_n, NULL, NULL, (void *) &data, 3, divisible_iters);
127+
fflush(stdout);
128+
}
129+
}
130+
#endif
87131

88132
for (i = 0; i < iters; i++) {
89133
free((void *)data.keypairs[i]);
@@ -98,6 +142,9 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) {
98142
free((void *)data.msgs);
99143
free((void *)data.sigs);
100144

145+
#ifdef ENABLE_MODULE_BATCH
146+
secp256k1_batch_destroy(data.ctx, data.batch);
147+
#endif
101148
secp256k1_context_destroy(data.ctx);
102149
}
103150

0 commit comments

Comments
 (0)