diff --git a/.cirrus.yml b/.cirrus.yml index 82a0a99a6..9aa6a5e5e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -19,9 +19,9 @@ env: RECOVERY: no SCHNORRSIG: no ### test options - TEST_ITERS: + SECP256K1_TEST_ITERS: BENCH: yes - BENCH_ITERS: 2 + SECP256K1_BENCH_ITERS: 2 CTIMETEST: yes cat_logs_snippet: &CAT_LOGS @@ -171,7 +171,7 @@ task: memory: 1G env: WRAPPER_CMD: qemu-s390x - TEST_ITERS: 16 + SECP256K1_TEST_ITERS: 16 HOST: s390x-linux-gnu WITH_VALGRIND: no ECDH: yes @@ -194,7 +194,7 @@ task: memory: 1G env: WRAPPER_CMD: qemu-arm - TEST_ITERS: 16 + SECP256K1_TEST_ITERS: 16 HOST: arm-linux-gnueabihf WITH_VALGRIND: no ECDH: yes @@ -218,7 +218,7 @@ task: memory: 1G env: WRAPPER_CMD: qemu-aarch64 - TEST_ITERS: 16 + SECP256K1_TEST_ITERS: 16 HOST: aarch64-linux-gnu WITH_VALGRIND: no ECDH: yes @@ -239,7 +239,7 @@ task: memory: 1G env: WRAPPER_CMD: qemu-ppc64le - TEST_ITERS: 16 + SECP256K1_TEST_ITERS: 16 HOST: powerpc64le-linux-gnu WITH_VALGRIND: no ECDH: yes @@ -260,7 +260,7 @@ task: memory: 1G env: WRAPPER_CMD: wine64-stable - TEST_ITERS: 16 + SECP256K1_TEST_ITERS: 16 HOST: x86_64-w64-mingw32 WITH_VALGRIND: no ECDH: yes @@ -290,7 +290,7 @@ task: env: # The `--error-exitcode` is required to make the test fail if valgrind found errors, otherwise it'll return 0 (https://www.valgrind.org/docs/manual/manual-core.html) WRAPPER_CMD: "valgrind --error-exitcode=42" - TEST_ITERS: 16 + SECP256K1_TEST_ITERS: 16 - name: "UBSan, ASan, LSan" env: CFLAGS: "-fsanitize=undefined,address -g" @@ -298,7 +298,7 @@ task: UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1" ASAN_OPTIONS: "strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1" LSAN_OPTIONS: "use_unaligned=1" - TEST_ITERS: 32 + SECP256K1_TEST_ITERS: 32 # Try to cover many configurations with just a tiny matrix. matrix: - env: diff --git a/ci/cirrus.sh b/ci/cirrus.sh index 39ec2adbe..6809ab851 100755 --- a/ci/cirrus.sh +++ b/ci/cirrus.sh @@ -32,10 +32,6 @@ file .libs/* || true # This tells `make check` to wrap test invocations. export LOG_COMPILER="$WRAPPER_CMD" -# This limits the iterations in the tests and benchmarks. -export SECP256K1_TEST_ITERS="$TEST_ITERS" -export SECP256K1_BENCH_ITERS="$BENCH_ITERS" - make "$BUILD" if [ "$BENCH" = "yes" ] diff --git a/src/bench.c b/src/bench.c index dfc0470be..d5937b763 100644 --- a/src/bench.c +++ b/src/bench.c @@ -11,6 +11,51 @@ #include "util.h" #include "bench.h" +void help(int default_iters) { + printf("Benchmarks the following algorithms:\n"); + printf(" - ECDSA signing/verification\n"); + +#ifdef ENABLE_MODULE_ECDH + printf(" - ECDH key exchange (optional module)\n"); +#endif + +#ifdef ENABLE_MODULE_RECOVERY + printf(" - Public key recovery (optional module)\n"); +#endif + +#ifdef ENABLE_MODULE_SCHNORRSIG + printf(" - Schnorr signatures (optional module)\n"); +#endif + + printf("\n"); + printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); + printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); + printf("\n"); + 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"); + +#ifdef ENABLE_MODULE_RECOVERY + printf(" ecdsa_recover : ECDSA public key recovery algorithm\n"); +#endif + +#ifdef ENABLE_MODULE_ECDH + 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"); +#endif + + printf("\n"); +} + typedef struct { secp256k1_context *ctx; unsigned char msg[32]; @@ -95,7 +140,52 @@ int main(int argc, char** argv) { bench_verify_data data; int d = argc == 1; - int iters = get_iters(20000); + int default_iters = 20000; + int iters = get_iters(default_iters); + + /* Check for invalid user arguments */ + char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover", + "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign"}; + 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); + + if (argc > 1) { + if (have_flag(argc, argv, "-h") + || have_flag(argc, argv, "--help") + || have_flag(argc, argv, "help")) { + help(default_iters); + return 0; + } else if (invalid_args) { + fprintf(stderr, "./bench: unrecognized argument.\n\n"); + help(default_iters); + return 1; + } + } + +/* Check if the user tries to benchmark optional module without building it */ +#ifndef ENABLE_MODULE_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")) { + 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")) { + fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n"); + fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n"); + return 1; + } +#endif /* ECDSA verification benchmark */ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); diff --git a/src/bench.h b/src/bench.h index 65781a203..aa275fe91 100644 --- a/src/bench.h +++ b/src/bench.h @@ -116,7 +116,7 @@ void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void int have_flag(int argc, char** argv, char *flag) { char** argm = argv + argc; argv++; - while (argv != NULL && argv != argm) { + while (argv != argm) { if (strcmp(*argv, flag) == 0) { return 1; } @@ -125,6 +125,32 @@ int have_flag(int argc, char** argv, char *flag) { return 0; } +/* takes an array containing the arguments that the user is allowed to enter on the command-line + returns: + - 1 if the user entered an invalid argument + - 0 if all the user entered arguments are valid */ +int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) { + size_t i; + int found_valid; + char** argm = argv + argc; + argv++; + + while (argv != argm) { + found_valid = 0; + for (i = 0; i < n; i++) { + if (strcmp(*argv, valid_args[i]) == 0) { + found_valid = 1; /* user entered a valid arg from the list */ + break; + } + } + if (found_valid == 0) { + return 1; /* invalid arg found */ + } + argv++; + } + return 0; +} + int get_iters(int default_iters) { char* env = getenv("SECP256K1_BENCH_ITERS"); if (env) { diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index 335d91042..4030e0263 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -292,7 +292,7 @@ int main(int argc, char **argv) { || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { help(argv); - return 1; + return 0; } else if(have_flag(argc, argv, "pippenger_wnaf")) { printf("Using pippenger_wnaf:\n"); data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single;