Skip to content

Commit 1293c16

Browse files
siv2rfjahr
authored andcommitted
batch, extrakeys: Add benchmark for batch verify and tweak_add_check
This commit adds benchmarks for Schnorr signature batch verification,Tweaked pubkey check batch verification, and Tweaked pubkey check (single verification). 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 3a0a7fd commit 1293c16

File tree

4 files changed

+223
-9
lines changed

4 files changed

+223
-9
lines changed

src/bench.c

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,27 @@ static void help(int default_iters) {
4242
printf(" ec_keygen : EC public key generation\n");
4343

4444
#ifdef ENABLE_MODULE_RECOVERY
45-
printf(" ecdsa_recover : ECDSA public key recovery algorithm\n");
45+
printf(" ecdsa_recover : ECDSA public key recovery algorithm\n");
4646
#endif
4747

4848
#ifdef ENABLE_MODULE_ECDH
49-
printf(" ecdh : ECDH key exchange algorithm\n");
49+
printf(" ecdh : ECDH key exchange algorithm\n");
5050
#endif
5151

5252
#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");
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+
# ifdef ENABLE_MODULE_BATCH
57+
printf(" schnorrsig_batch_verify : Batch verification of Schnorr signatures\n");
58+
# endif
59+
#endif
60+
61+
#ifdef ENABLE_MODULE_EXTRAKEYS
62+
printf(" tweak_add_check : Checks if tweaked x-only pubkey is valid\n");
63+
# ifdef ENABLE_MODULE_BATCH
64+
printf(" tweak_check_batch_verify : Batch verification of tweaked x-only pubkeys check\n");
65+
# endif
5666
#endif
5767

5868
#ifdef ENABLE_MODULE_ELLSWIFT
@@ -157,6 +167,10 @@ static void bench_keygen_run(void *arg, int iters) {
157167
# include "modules/recovery/bench_impl.h"
158168
#endif
159169

170+
#ifdef ENABLE_MODULE_EXTRAKEYS
171+
# include "modules/extrakeys/bench_impl.h"
172+
#endif
173+
160174
#ifdef ENABLE_MODULE_SCHNORRSIG
161175
# include "modules/schnorrsig/bench_impl.h"
162176
#endif
@@ -179,7 +193,8 @@ int main(int argc, char** argv) {
179193
char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
180194
"ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec",
181195
"keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode",
182-
"ellswift_decode", "ellswift_keygen", "ellswift_ecdh"};
196+
"ellswift_decode", "ellswift_keygen", "ellswift_ecdh",
197+
"batch_verify", "schnorrsig_batch_verify", "extrakeys", "tweak_add_check", "tweak_check_batch_verify"};
183198
size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
184199
int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);
185200

@@ -221,6 +236,14 @@ int main(int argc, char** argv) {
221236
}
222237
#endif
223238

239+
#ifndef ENABLE_MODULE_BATCH
240+
if (have_flag(argc, argv, "batch_verify") || have_flag(argc, argv, "schnorrsig_batch_verify") || have_flag(argc, argv, "tweak_check_batch_verify")) {
241+
fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
242+
fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
243+
return 1;
244+
}
245+
#endif
246+
224247
#ifndef ENABLE_MODULE_ELLSWIFT
225248
if (have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ellswift_encode") || have_flag(argc, argv, "ellswift_decode") ||
226249
have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") ||
@@ -265,6 +288,11 @@ int main(int argc, char** argv) {
265288
run_recovery_bench(iters, argc, argv);
266289
#endif
267290

291+
#ifdef ENABLE_MODULE_EXTRAKEYS
292+
/* Extrakeys benchmarks */
293+
run_extrakeys_bench(iters, argc, argv);
294+
#endif
295+
268296
#ifdef ENABLE_MODULE_SCHNORRSIG
269297
/* Schnorr signature benchmarks */
270298
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+
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+
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+
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_verify") || have_flag(argc, argv, "tweak_check_batch_verify")) {
105+
for (i = 1; i <= iters; i = (int)(i*1.2 + 1)) {
106+
char name[64];
107+
int divisible_iters;
108+
sprintf(name, "tweak_check_batch_verify_%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: 48 additions & 1 deletion
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,7 +54,24 @@ static void bench_schnorrsig_verify(void* arg, int iters) {
4554
}
4655
}
4756

48-
static void run_schnorrsig_bench(int iters, int argc, char** argv) {
57+
#ifdef ENABLE_MODULE_BATCH
58+
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+
74+
void run_schnorrsig_bench(int iters, int argc, char** argv) {
4975
int i;
5076
bench_schnorrsig_data data;
5177
int d = argc == 1;
@@ -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_verify") || have_flag(argc, argv, "schnorrsig_batch_verify")) {
119+
for (i = 1; i <= iters; i = (int)(i*1.2 + 1)) {
120+
char name[64];
121+
int divisible_iters;
122+
sprintf(name, "schnorrsig_batch_verify_%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)