Skip to content

Commit

Permalink
batch, extrakeys: Add benchmark for batch verify and tweak_add_check
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
siv2r committed Aug 20, 2022
1 parent 7c4c655 commit 747a8d9
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 15 deletions.
53 changes: 40 additions & 13 deletions src/bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,33 @@ void help(int default_iters) {
printf("Usage: ./bench [args]\n");
printf("By default, all benchmarks will be run.\n");
printf("args:\n");
printf(" help : display this help and exit\n");
printf(" ecdsa : all ECDSA algorithms--sign, verify, recovery (if enabled)\n");
printf(" ecdsa_sign : ECDSA siging algorithm\n");
printf(" ecdsa_verify : ECDSA verification algorithm\n");
printf(" help : display this help and exit\n");
printf(" ecdsa : all ECDSA algorithms--sign, verify, recovery (if enabled)\n");
printf(" ecdsa_sign : ECDSA siging algorithm\n");
printf(" ecdsa_verify : ECDSA verification algorithm\n");

#ifdef ENABLE_MODULE_RECOVERY
printf(" ecdsa_recover : ECDSA public key recovery algorithm\n");
printf(" ecdsa_recover : ECDSA public key recovery algorithm\n");
#endif

#ifdef ENABLE_MODULE_ECDH
printf(" ecdh : ECDH key exchange algorithm\n");
printf(" ecdh : ECDH key exchange algorithm\n");
#endif

#ifdef ENABLE_MODULE_SCHNORRSIG
printf(" schnorrsig : all Schnorr signature algorithms (sign, verify)\n");
printf(" schnorrsig_sign : Schnorr sigining algorithm\n");
printf(" schnorrsig_verify : Schnorr verification algorithm\n");
printf(" schnorrsig : all Schnorr signature algorithms (sign, verify)\n");
printf(" schnorrsig_sign : Schnorr sigining algorithm\n");
printf(" schnorrsig_verify : Schnorr verification algorithm\n");
# ifdef ENABLE_MODULE_BATCH
printf(" schnorrsig_batch_verify : Batch verification of Schnorr signatures\n");
# endif
#endif

#ifdef ENABLE_MODULE_EXTRAKEYS
printf(" tweak_add_check : Checks if tweaked x-only pubkey is valid\n");
# ifdef ENABLE_MODULE_BATCH
printf(" tweak_check_batch_verify : Batch verification of tweaked x-only pubkeys check\n");
# endif
#endif

printf("\n");
Expand Down Expand Up @@ -129,6 +139,10 @@ static void bench_sign_run(void* arg, int iters) {
# include "modules/recovery/bench_impl.h"
#endif

#ifdef ENABLE_MODULE_EXTRAKEYS
# include "modules/extrakeys/bench_impl.h"
#endif

#ifdef ENABLE_MODULE_SCHNORRSIG
# include "modules/schnorrsig/bench_impl.h"
#endif
Expand All @@ -145,7 +159,7 @@ int main(int argc, char** argv) {

/* Check for invalid user arguments */
char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
"ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign"};
"ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "batch_verify", "schnorrsig_batch_verify", "extrakeys", "tweak_add_check", "tweak_check_batch_verify"};
size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);

Expand All @@ -164,23 +178,31 @@ int main(int argc, char** argv) {

/* Check if the user tries to benchmark optional module without building it */
#ifndef ENABLE_MODULE_ECDH
if (have_flag(argc, argv, "ecdh")) {
if (have_flag(argc, argv, "ecdh")) {
fprintf(stderr, "./bench: ECDH module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
return 1;
}
#endif

#ifndef ENABLE_MODULE_RECOVERY
if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
fprintf(stderr, "./bench: Public key recovery module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n");
return 1;
}
#endif

#ifndef ENABLE_MODULE_SCHNORRSIG
if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
return 1;
}
#endif

#ifndef ENABLE_MODULE_BATCH
if (have_flag(argc, argv, "batch_verify") || have_flag(argc, argv, "schnorrsig_batch_verify") || have_flag(argc, argv, "tweak_check_batch_verify")) {
fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
return 1;
Expand Down Expand Up @@ -225,6 +247,11 @@ int main(int argc, char** argv) {
run_recovery_bench(iters, argc, argv);
#endif

#ifdef ENABLE_MODULE_EXTRAKEYS
/* Extrakeys benchmarks */
run_extrakeys_bench(iters, argc, argv);
#endif

#ifdef ENABLE_MODULE_SCHNORRSIG
/* Schnorr signature benchmarks */
run_schnorrsig_bench(iters, argc, argv);
Expand Down
4 changes: 2 additions & 2 deletions src/bench.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void
sum += total;
}
/* ',' is used as a column delimiter */
printf("%-30s, ", name);
printf("%-35s, ", name);
print_number(min * FP_MULT / iter);
printf(" , ");
print_number(((sum * FP_MULT) / count) / iter);
Expand Down Expand Up @@ -181,7 +181,7 @@ void print_output_table_header_row(void) {
char* min_str = " Min(us) "; /* center alignment */
char* avg_str = " Avg(us) ";
char* max_str = " Max(us) ";
printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str);
printf("%-35s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str);
printf("\n");
}

Expand Down
137 changes: 137 additions & 0 deletions src/modules/extrakeys/bench_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

#ifndef SECP256K1_MODULE_EXTRAKEYS_BENCH_H
#define SECP256K1_MODULE_EXTRAKEYS_BENCH_H

#include "../../../include/secp256k1_extrakeys.h"
#ifdef ENABLE_MODULE_BATCH
# include "../../../include/secp256k1_batch.h"
# include "../../../include/secp256k1_tweak_check_batch.h"
#endif

typedef struct {
secp256k1_context *ctx;
#ifdef ENABLE_MODULE_BATCH
secp256k1_batch *batch;
/* number of tweak checks to batch verify.
* it varies from 1 to iters with 20% increments */
int n;
#endif

const secp256k1_keypair **keypairs;
const unsigned char **pks;
const unsigned char **tweaked_pks;
const int **tweaked_pk_parities;
const unsigned char **tweaks;
} bench_tweak_check_data;

void bench_xonly_pubkey_tweak_add_check(void* arg, int iters) {
bench_tweak_check_data *data = (bench_tweak_check_data *)arg;
int i;

for (i = 0; i < iters; i++) {
secp256k1_xonly_pubkey pk;
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pks[i]) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(data->ctx, data->tweaked_pks[i], *data->tweaked_pk_parities[i], &pk, data->tweaks[i]) == 1);
}
}

#ifdef ENABLE_MODULE_BATCH
void bench_xonly_pubkey_tweak_add_check_n(void* arg, int iters) {
bench_tweak_check_data *data = (bench_tweak_check_data *)arg;
int i, j;

for (j = 0; j < iters/data->n; j++) {
for (i = 0; i < data->n; i++) {
secp256k1_xonly_pubkey pk;
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pks[j+i]) == 1);
CHECK(secp256k1_batch_usable(data->ctx, data->batch) == 1);
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);
}
CHECK(secp256k1_batch_verify(data->ctx, data->batch) == 1);
}
}
#endif

void run_extrakeys_bench(int iters, int argc, char** argv) {
int i;
bench_tweak_check_data data;
int d = argc == 1;

data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *));
data.pks = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
data.tweaked_pks = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
data.tweaked_pk_parities = (const int **)malloc(iters * sizeof(int *));
data.tweaks = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
#ifdef ENABLE_MODULE_BATCH
data.batch = secp256k1_batch_create(data.ctx, iters, NULL);
CHECK(data.batch != NULL);
#endif

for (i = 0; i < iters; i++) {
unsigned char sk[32];
unsigned char *tweaked_pk_char = (unsigned char *)malloc(32);
int *tweaked_pk_parity = (int *)malloc(sizeof(int)); /*todo: use sizeof(*twk_parity) instead?*/
unsigned char *tweak = (unsigned char *)malloc(32);
secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair));
unsigned char *pk_char = (unsigned char *)malloc(32);
secp256k1_xonly_pubkey pk;
secp256k1_pubkey output_pk;
secp256k1_xonly_pubkey output_pk_xonly;
tweak[0] = sk[0] = i;
tweak[1] = sk[1] = i >> 8;
tweak[2] = sk[2] = i >> 16;
tweak[3] = sk[3] = i >> 24;
memset(&tweak[4], 't', 28);
memset(&sk[4], 's', 28);

data.keypairs[i] = keypair;
data.pks[i] = pk_char;
data.tweaked_pks[i] = tweaked_pk_char;
data.tweaked_pk_parities[i] = tweaked_pk_parity;
data.tweaks[i] = tweak;

CHECK(secp256k1_keypair_create(data.ctx, keypair, sk));
CHECK(secp256k1_keypair_xonly_pub(data.ctx, &pk, NULL, keypair));
CHECK(secp256k1_xonly_pubkey_tweak_add(data.ctx, &output_pk, &pk, tweak));
CHECK(secp256k1_xonly_pubkey_from_pubkey(data.ctx, &output_pk_xonly, tweaked_pk_parity, &output_pk));
CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, tweaked_pk_char, &output_pk_xonly) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1);
}

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);
#ifdef ENABLE_MODULE_BATCH
if (d || have_flag(argc, argv, "extrakeys") || have_flag(argc, argv, "batch_verify") || have_flag(argc, argv, "tweak_check_batch_verify")) {
for (i = 1; i <= iters; i = (int)(i*1.2 + 1)) {
char name[64];
int divisible_iters;
sprintf(name, "tweak_check_batch_verify_%d", (int) i);

data.n = i;
divisible_iters = iters - (iters % data.n);
run_benchmark(name, bench_xonly_pubkey_tweak_add_check_n, NULL, NULL, (void *) &data, 3, divisible_iters);
fflush(stdout);
}
}
#endif

for (i = 0; i < iters; i++) {
free((void *)data.keypairs[i]);
free((void *)data.pks[i]);
free((void *)data.tweaked_pks[i]);
free((void *)data.tweaked_pk_parities[i]);
free((void *)data.tweaks[i]);
}
free(data.keypairs);
free(data.pks);
free(data.tweaked_pks);
free(data.tweaked_pk_parities);
free(data.tweaks);

#ifdef ENABLE_MODULE_BATCH
secp256k1_batch_destroy(data.ctx, data.batch);
#endif
secp256k1_context_destroy(data.ctx);
}

#endif /* SECP256K1_MODULE_EXTRAKEYS_BENCH_H */
47 changes: 47 additions & 0 deletions src/modules/schnorrsig/bench_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@
#define SECP256K1_MODULE_SCHNORRSIG_BENCH_H

#include "../../../include/secp256k1_schnorrsig.h"
#ifdef ENABLE_MODULE_BATCH
# include "../../../include/secp256k1_batch.h"
# include "../../../include/secp256k1_schnorrsig_batch.h"
#endif

#define MSGLEN 32

typedef struct {
secp256k1_context *ctx;
#ifdef ENABLE_MODULE_BATCH
secp256k1_batch *batch;
/* number of signatures to batch verify.
* it varies from 1 to iters with 20% increments */
int n;
#endif

const secp256k1_keypair **keypairs;
const unsigned char **pk;
Expand Down Expand Up @@ -45,6 +54,23 @@ void bench_schnorrsig_verify(void* arg, int iters) {
}
}

#ifdef ENABLE_MODULE_BATCH
void bench_schnorrsig_verify_n(void* arg, int iters) {
bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg;
int i, j;

for (j = 0; j < iters/data->n; j++) {
for (i = 0; i < data->n; i++) {
secp256k1_xonly_pubkey pk;
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[j+i]) == 1);
CHECK(secp256k1_batch_usable(data->ctx, data->batch) == 1);
CHECK(secp256k1_batch_add_schnorrsig(data->ctx, data->batch, data->sigs[j+i], data->msgs[j+i], MSGLEN, &pk) == 1);
}
CHECK(secp256k1_batch_verify(data->ctx, data->batch) == 1);
}
}
#endif

void run_schnorrsig_bench(int iters, int argc, char** argv) {
int i;
bench_schnorrsig_data data;
Expand All @@ -55,6 +81,10 @@ void run_schnorrsig_bench(int iters, int argc, char** argv) {
data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
#ifdef ENABLE_MODULE_BATCH
data.batch = secp256k1_batch_create(data.ctx, 2*iters, NULL);
CHECK(data.batch != NULL);
#endif

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

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);
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);
#ifdef ENABLE_MODULE_BATCH
if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "batch_verify") || have_flag(argc, argv, "schnorrsig_batch_verify")) {
for (i = 1; i <= iters; i = (int)(i*1.2 + 1)) {
char name[64];
int divisible_iters;
sprintf(name, "schnorrsig_batch_verify_%d", (int) i);

data.n = i;
divisible_iters = iters - (iters % data.n);
run_benchmark(name, bench_schnorrsig_verify_n, NULL, NULL, (void *) &data, 3, divisible_iters);
fflush(stdout);
}
}
#endif

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

#ifdef ENABLE_MODULE_BATCH
secp256k1_batch_destroy(data.ctx, data.batch);
#endif
secp256k1_context_destroy(data.ctx);
}

Expand Down

0 comments on commit 747a8d9

Please sign in to comment.