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