github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/src/bench.c (about)

     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 <stdlib.h>
     9  #include <string.h>
    10  
    11  #include "../include/secp256k1.h"
    12  #include "util.h"
    13  #include "bench.h"
    14  
    15  static void help(int default_iters) {
    16      printf("Benchmarks the following algorithms:\n");
    17      printf("    - ECDSA signing/verification\n");
    18  
    19  #ifdef ENABLE_MODULE_ECDH
    20      printf("    - ECDH key exchange (optional module)\n");
    21  #endif
    22  
    23  #ifdef ENABLE_MODULE_RECOVERY
    24      printf("    - Public key recovery (optional module)\n");
    25  #endif
    26  
    27  #ifdef ENABLE_MODULE_SCHNORRSIG
    28      printf("    - Schnorr signatures (optional module)\n");
    29  #endif
    30  
    31      printf("\n");
    32      printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters);
    33      printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n");
    34      printf("\n");
    35      printf("Usage: ./bench [args]\n");
    36      printf("By default, all benchmarks will be run.\n");
    37      printf("args:\n");
    38      printf("    help              : display this help and exit\n");
    39      printf("    ecdsa             : all ECDSA algorithms--sign, verify, recovery (if enabled)\n");
    40      printf("    ecdsa_sign        : ECDSA siging algorithm\n");
    41      printf("    ecdsa_verify      : ECDSA verification algorithm\n");
    42      printf("    ec                : all EC public key algorithms (keygen)\n");
    43      printf("    ec_keygen         : EC public key generation\n");
    44  
    45  #ifdef ENABLE_MODULE_RECOVERY
    46      printf("    ecdsa_recover     : ECDSA public key recovery algorithm\n");
    47  #endif
    48  
    49  #ifdef ENABLE_MODULE_ECDH
    50      printf("    ecdh              : ECDH key exchange algorithm\n");
    51  #endif
    52  
    53  #ifdef ENABLE_MODULE_SCHNORRSIG
    54      printf("    schnorrsig        : all Schnorr signature algorithms (sign, verify)\n");
    55      printf("    schnorrsig_sign   : Schnorr sigining algorithm\n");
    56      printf("    schnorrsig_verify : Schnorr verification algorithm\n");
    57  #endif
    58  
    59  #ifdef ENABLE_MODULE_ELLSWIFT
    60      printf("    ellswift          : all ElligatorSwift benchmarks (encode, decode, keygen, ecdh)\n");
    61      printf("    ellswift_encode   : ElligatorSwift encoding\n");
    62      printf("    ellswift_decode   : ElligatorSwift decoding\n");
    63      printf("    ellswift_keygen   : ElligatorSwift key generation\n");
    64      printf("    ellswift_ecdh     : ECDH on ElligatorSwift keys\n");
    65  #endif
    66  
    67      printf("\n");
    68  }
    69  
    70  typedef struct {
    71      secp256k1_context *ctx;
    72      unsigned char msg[32];
    73      unsigned char key[32];
    74      unsigned char sig[72];
    75      size_t siglen;
    76      unsigned char pubkey[33];
    77      size_t pubkeylen;
    78  } bench_data;
    79  
    80  static void bench_verify(void* arg, int iters) {
    81      int i;
    82      bench_data* data = (bench_data*)arg;
    83  
    84      for (i = 0; i < iters; i++) {
    85          secp256k1_pubkey pubkey;
    86          secp256k1_ecdsa_signature sig;
    87          data->sig[data->siglen - 1] ^= (i & 0xFF);
    88          data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
    89          data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
    90          CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
    91          CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
    92          CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0));
    93          data->sig[data->siglen - 1] ^= (i & 0xFF);
    94          data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
    95          data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
    96      }
    97  }
    98  
    99  static void bench_sign_setup(void* arg) {
   100      int i;
   101      bench_data *data = (bench_data*)arg;
   102  
   103      for (i = 0; i < 32; i++) {
   104          data->msg[i] = i + 1;
   105      }
   106      for (i = 0; i < 32; i++) {
   107          data->key[i] = i + 65;
   108      }
   109  }
   110  
   111  static void bench_sign_run(void* arg, int iters) {
   112      int i;
   113      bench_data *data = (bench_data*)arg;
   114  
   115      unsigned char sig[74];
   116      for (i = 0; i < iters; i++) {
   117          size_t siglen = 74;
   118          int j;
   119          secp256k1_ecdsa_signature signature;
   120          CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL));
   121          CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature));
   122          for (j = 0; j < 32; j++) {
   123              data->msg[j] = sig[j];
   124              data->key[j] = sig[j + 32];
   125          }
   126      }
   127  }
   128  
   129  static void bench_keygen_setup(void* arg) {
   130      int i;
   131      bench_data *data = (bench_data*)arg;
   132  
   133      for (i = 0; i < 32; i++) {
   134          data->key[i] = i + 65;
   135      }
   136  }
   137  
   138  static void bench_keygen_run(void *arg, int iters) {
   139      int i;
   140      bench_data *data = (bench_data*)arg;
   141  
   142      for (i = 0; i < iters; i++) {
   143          unsigned char pub33[33];
   144          size_t len = 33;
   145          secp256k1_pubkey pubkey;
   146          CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->key));
   147          CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pub33, &len, &pubkey, SECP256K1_EC_COMPRESSED));
   148          memcpy(data->key, pub33 + 1, 32);
   149      }
   150  }
   151  
   152  
   153  #ifdef ENABLE_MODULE_ECDH
   154  # include "modules/ecdh/bench_impl.h"
   155  #endif
   156  
   157  #ifdef ENABLE_MODULE_RECOVERY
   158  # include "modules/recovery/bench_impl.h"
   159  #endif
   160  
   161  #ifdef ENABLE_MODULE_SCHNORRSIG
   162  # include "modules/schnorrsig/bench_impl.h"
   163  #endif
   164  
   165  #ifdef ENABLE_MODULE_ELLSWIFT
   166  # include "modules/ellswift/bench_impl.h"
   167  #endif
   168  
   169  int main(int argc, char** argv) {
   170      int i;
   171      secp256k1_pubkey pubkey;
   172      secp256k1_ecdsa_signature sig;
   173      bench_data data;
   174  
   175      int d = argc == 1;
   176      int default_iters = 20000;
   177      int iters = get_iters(default_iters);
   178  
   179      /* Check for invalid user arguments */
   180      char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover",
   181                           "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec",
   182                           "keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode",
   183                           "ellswift_decode", "ellswift_keygen", "ellswift_ecdh"};
   184      size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]);
   185      int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size);
   186  
   187      if (argc > 1) {
   188          if (have_flag(argc, argv, "-h")
   189             || have_flag(argc, argv, "--help")
   190             || have_flag(argc, argv, "help")) {
   191              help(default_iters);
   192              return EXIT_SUCCESS;
   193          } else if (invalid_args) {
   194              fprintf(stderr, "./bench: unrecognized argument.\n\n");
   195              help(default_iters);
   196              return EXIT_FAILURE;
   197          }
   198      }
   199  
   200  /* Check if the user tries to benchmark optional module without building it */
   201  #ifndef ENABLE_MODULE_ECDH
   202      if (have_flag(argc, argv, "ecdh")) {
   203          fprintf(stderr, "./bench: ECDH module not enabled.\n");
   204          fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
   205          return EXIT_FAILURE;
   206      }
   207  #endif
   208  
   209  #ifndef ENABLE_MODULE_RECOVERY
   210      if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
   211          fprintf(stderr, "./bench: Public key recovery module not enabled.\n");
   212          fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n");
   213          return EXIT_FAILURE;
   214      }
   215  #endif
   216  
   217  #ifndef ENABLE_MODULE_SCHNORRSIG
   218      if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
   219          fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
   220          fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
   221          return EXIT_FAILURE;
   222      }
   223  #endif
   224  
   225  #ifndef ENABLE_MODULE_ELLSWIFT
   226      if (have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ellswift_encode") || have_flag(argc, argv, "ellswift_decode") ||
   227          have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") ||
   228          have_flag(argc, argv, "ellswift_ecdh")) {
   229          fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n");
   230          fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n");
   231          return EXIT_FAILURE;
   232      }
   233  #endif
   234  
   235      /* ECDSA benchmark */
   236      data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
   237  
   238      for (i = 0; i < 32; i++) {
   239          data.msg[i] = 1 + i;
   240      }
   241      for (i = 0; i < 32; i++) {
   242          data.key[i] = 33 + i;
   243      }
   244      data.siglen = 72;
   245      CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL));
   246      CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig));
   247      CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
   248      data.pubkeylen = 33;
   249      CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
   250  
   251      print_output_table_header_row();
   252      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);
   253  
   254      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);
   255      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);
   256  
   257      secp256k1_context_destroy(data.ctx);
   258  
   259  #ifdef ENABLE_MODULE_ECDH
   260      /* ECDH benchmarks */
   261      run_ecdh_bench(iters, argc, argv);
   262  #endif
   263  
   264  #ifdef ENABLE_MODULE_RECOVERY
   265      /* ECDSA recovery benchmarks */
   266      run_recovery_bench(iters, argc, argv);
   267  #endif
   268  
   269  #ifdef ENABLE_MODULE_SCHNORRSIG
   270      /* Schnorr signature benchmarks */
   271      run_schnorrsig_bench(iters, argc, argv);
   272  #endif
   273  
   274  #ifdef ENABLE_MODULE_ELLSWIFT
   275      /* ElligatorSwift benchmarks */
   276      run_ellswift_bench(iters, argc, argv);
   277  #endif
   278  
   279      return EXIT_SUCCESS;
   280  }