diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index 91c109ff23..39ccebd87d 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -13,13 +13,11 @@ /* Configuration parameters for the signed-digit multi-comb algorithm: * - * - COMB_BLOCKS is the number of blocks the input is split into. Each - * has a corresponding table. + * - COMB_BLOCKS is the number of blocks the input is split into. Each has a corresponding table. * - COMB_TEETH is the number of bits simultaneously covered by one table. - * - * The comb's spacing (COMB_SPACING), or the distance between the teeth, - * is defined as ceil(256 / (COMB_BLOCKS * COMB_TEETH)). Each block covers - * COMB_SPACING * COMB_TEETH consecutive bits in the input. + * - COMB_SPACING is the distance between the teeth. For production purposes, the only reasonable + * value is ceil(256 / (COMB_BLOCKS * COMB_TEETH)), so unless explicitly configured otherwise, + * that value will be used. COMB_BLOCKS * COMB_TEETH * COMB_SPACING needs to be at least 256. * * The size of the precomputed table is COMB_BLOCKS * (1 << (COMB_TEETH - 1)) * secp256k1_ge_storages. @@ -36,65 +34,86 @@ * doesn't support infinities) */ # undef COMB_BLOCKS # undef COMB_TEETH -# if EXHAUSTIVE_TEST_ORDER > 32 -# define COMB_BLOCKS 52 -# define COMB_TEETH 5 -# elif EXHAUSTIVE_TEST_ORDER > 16 -# define COMB_BLOCKS 64 -# define COMB_TEETH 4 -# elif EXHAUSTIVE_TEST_ORDER > 8 -# define COMB_BLOCKS 86 -# define COMB_TEETH 3 -# elif EXHAUSTIVE_TEST_ORDER > 4 -# define COMB_BLOCKS 128 +# undef COMB_SPACING +# if EXHAUSTIVE_TEST_ORDER == 13 +# define COMB_RANGE 4 +# define COMB_BLOCKS 1 # define COMB_TEETH 2 +# define COMB_SPACING 2 +# elif EXHAUSTIVE_TEST_ORDER == 199 +# define COMB_RANGE 8 +# define COMB_BLOCKS 2 +# define COMB_TEETH 3 +# define COMB_SPACING 2 # else -# define COMB_BLOCKS 256 -# define COMB_TEETH 1 +# error "Unknown exhaustive test order" +# endif +# if (COMB_RANGE >= 32) || ((EXHAUSTIVE_TEST_ORDER >> (COMB_RANGE - 1)) != 1) +# error "COMB_RANGE != ceil(log2(EXHAUSTIVE_TEST_ORDER+1))" # endif #else /* !defined(EXHAUSTIVE_TEST_ORDER) */ +# define COMB_RANGE 256 +#endif /* defined(EXHAUSTIVE_TEST_ORDER) */ + /* Use (11, 6) as default configuration, which results in a 22 kB table. */ -# ifndef COMB_BLOCKS -# define COMB_BLOCKS 11 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("COMB_BLOCKS undefined, assuming default value") -# endif +#ifndef COMB_BLOCKS +# define COMB_BLOCKS 11 +# ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_MSG("COMB_BLOCKS undefined, assuming default value") # endif -# ifndef COMB_TEETH -# define COMB_TEETH 6 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("COMB_TEETH undefined, assuming default value") -# endif +#endif +#ifndef COMB_TEETH +# define COMB_TEETH 6 +# ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_MSG("COMB_TEETH undefined, assuming default value") # endif -#endif /* defined(EXHAUSTIVE_TEST_ORDER) */ +#endif +/* Use ceil(COMB_RANGE / (COMB_BLOCKS * COMB_TEETH)) as default COMB_SPACING. */ +#ifndef COMB_SPACING +# define COMB_SPACING ((COMB_RANGE + COMB_BLOCKS * COMB_TEETH) / (COMB_BLOCKS * COMB_TEETH)) +# ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_MSG("COMB_SPACING undefined, assuming default value") +# endif +#endif /* Range checks on the parameters. */ + +/* The remaining COMB_* parameters are derived values, don't modify these. */ +/* - The number of bits covered by all the blocks; must be at least COMB_RANGE. */ +#define COMB_BITS (COMB_BLOCKS * COMB_TEETH * COMB_SPACING) +/* - The number of entries per table. */ +#define COMB_POINTS (1 << (COMB_TEETH - 1)) + +/* Sanity checks. */ #if !(1 <= COMB_BLOCKS && COMB_BLOCKS <= 256) # error "COMB_BLOCKS must be in the range [1, 256]" #endif #if !(1 <= COMB_TEETH && COMB_TEETH <= 8) # error "COMB_TEETH must be in the range [1, 8]" #endif +#if COMB_BITS < COMB_RANGE +# error "COMB_BLOCKS * COMB_TEETH * COMB_SPACING is too low" +#endif -/* The remaining COMB_* parameters are derived values, don't modify these. */ -/* - The distance between the teeth of each comb. */ -#define COMB_SPACING ((255 + COMB_BLOCKS * COMB_TEETH) / (COMB_BLOCKS * COMB_TEETH)) -/* - The number of bits covered by all the blocks; must be at least 256. */ -#define COMB_BITS (COMB_BLOCKS * COMB_TEETH * COMB_SPACING) -/* - The number of entries per table. */ -#define COMB_POINTS (1 << (COMB_TEETH - 1)) - -/* Additional sanity checks. */ +/* These last 3 checks are not strictly required, but prevent gratuitously inefficient + * configurations. Note that they compare with 256 rather than COMB_RANGE, so they do + * permit somewhat excessive values for the exhaustive test case, where testing with + * suboptimal parameters may be desirable. */ #if (COMB_BLOCKS - 1) * COMB_TEETH * COMB_SPACING >= 256 # error "COMB_BLOCKS can be reduced" #endif #if COMB_BLOCKS * (COMB_TEETH - 1) * COMB_SPACING >= 256 # error "COMB_TEETH can be reduced" #endif +#if COMB_BLOCKS * COMB_TEETH * (COMB_SPACING - 1) >= 256 +# error "COMB_SPACING can be reduced" +#endif #ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_DEF(COMB_RANGE) # pragma message DEBUG_CONFIG_DEF(COMB_BLOCKS) # pragma message DEBUG_CONFIG_DEF(COMB_TEETH) +# pragma message DEBUG_CONFIG_DEF(COMB_SPACING) #endif typedef struct { diff --git a/src/ecmult_gen_compute_table.h b/src/ecmult_gen_compute_table.h index 5db1df5c66..46f2f26a27 100644 --- a/src/ecmult_gen_compute_table.h +++ b/src/ecmult_gen_compute_table.h @@ -9,6 +9,6 @@ #include "ecmult_gen.h" -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth); +static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing); #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ diff --git a/src/ecmult_gen_compute_table_impl.h b/src/ecmult_gen_compute_table_impl.h index 8347f0ee6d..eb5f0744c9 100644 --- a/src/ecmult_gen_compute_table_impl.h +++ b/src/ecmult_gen_compute_table_impl.h @@ -14,10 +14,9 @@ #include "ecmult_gen.h" #include "util.h" -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth) { +static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing) { size_t points = ((size_t)1) << (teeth - 1); size_t points_total = points * blocks; - int spacing = (256 + blocks * teeth - 1) / (blocks * teeth); secp256k1_ge* prec = checked_malloc(&default_error_callback, points_total * sizeof(*prec)); secp256k1_gej* ds = checked_malloc(&default_error_callback, teeth * sizeof(*ds)); secp256k1_gej* vs = checked_malloc(&default_error_callback, points_total * sizeof(*vs)); @@ -85,6 +84,7 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons for (block = 0; block < blocks; ++block) { size_t index; for (index = 0; index < points; ++index) { + CHECK(!secp256k1_ge_is_infinity(&prec[block * points + index])); secp256k1_ge_to_storage(&table[block * points + index], &prec[block * points + index]); } } diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index fe303a0d9e..c10fe8d1d4 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -102,7 +102,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Compute the scalar (gn + ctx->scalar_offset). */ secp256k1_scalar_add(&tmp, &ctx->scalar_offset, gn); /* Convert to recoded array. */ - for (i = 0; i < 8; ++i) { + for (i = 0; i < 8 && i < ((COMB_BITS + 31) >> 5); ++i) { recoded[i] = secp256k1_scalar_get_bits(&tmp, 32 * i, 32); } secp256k1_scalar_clear(&tmp); diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index d2d5f14b13..8801aea16a 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -50,7 +50,7 @@ int main(int argc, char **argv) { fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = {\n"); for (config = 0; config < sizeof(CONFIGS) / sizeof(*CONFIGS) + 1; ++config) { - int blocks, teeth; + int blocks, teeth, spacing; size_t points; int outer; size_t inner; @@ -69,10 +69,11 @@ int main(int argc, char **argv) { teeth = COMB_TEETH; } + spacing = (255 + blocks * teeth) / (blocks * teeth); points = ((size_t)1) << (teeth - 1); table = checked_malloc(&default_error_callback, blocks * points * sizeof(secp256k1_ge_storage)); - secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, blocks, teeth); - fprintf(fp, "#if (COMB_BLOCKS == %d) && (COMB_TEETH == %d)\n", blocks, teeth); + secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, blocks, teeth, spacing); + fprintf(fp, "#if (COMB_BLOCKS == %d) && (COMB_TEETH == %d) && (COMB_SPACING == %d)\n", blocks, teeth, spacing); for (outer = 0; outer != blocks; outer++) { fprintf(fp,"{"); for (inner = 0; inner != points; inner++) { diff --git a/src/precomputed_ecmult_gen.c b/src/precomputed_ecmult_gen.c index 03eec02c14..8488b25da9 100644 --- a/src/precomputed_ecmult_gen.c +++ b/src/precomputed_ecmult_gen.c @@ -8,7 +8,7 @@ #endif /* EXHAUSTIVE_TEST_ORDER */ #define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u) const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = { -#if (COMB_BLOCKS == 2) && (COMB_TEETH == 5) +#if (COMB_BLOCKS == 2) && (COMB_TEETH == 5) && (COMB_SPACING == 26) {S(7081b567,8cb87d01,99c9c76e,d1e0a5e0,1d784be9,27f6b135,161e0fd0,3f39b473,ad5222ac,f062cb39,21b234a7,15b626ae,f780b307,9b5122d1,53210f42,d9369242), S(228af17e,df90d1cc,a40173e9,478fa445,9780dacd,c3f15b90,fda5d00e,1faa1b51,8ff47c4d,a4ba636a,f656da9,12a81f79,6252496d,1e519886,b2c2b073,25be2b4a), S(b515ebe0,f48fb34e,9e01824c,d90553af,db116579,96667847,5ebaa700,242fd722,4cf08191,510fbf0,51f9e19a,198f11f6,ea31268c,2a6d384c,60557250,f0553c50), @@ -42,7 +42,7 @@ S(5cb07874,ac4ffb86,2da619be,4c8fa38b,e8b261ec,3ec73a12,cd4cf8fc,4f8d5dae,549d18 S(5cc85d41,7b2ae9ac,dedb1b44,ce78d8a7,8f56b878,1a4b3af6,635a55c1,fead3be7,66a48c79,301e57d4,54cc8644,d2e778a8,45d85762,2c10eb98,d77eb873,e58bbeca), S(f27211c9,a067b01c,7fe7fbf7,7b5d9b0,eb0f2475,9d541457,6eb24ba4,19fd3db8,e26d28eb,89f7b518,e9ae0b88,fadbfb9b,641d3a44,c59c6f93,ec28a541,486e041e)} #endif -#if (COMB_BLOCKS == 11) && (COMB_TEETH == 6) +#if (COMB_BLOCKS == 11) && (COMB_TEETH == 6) && (COMB_SPACING == 4) {S(629bee58,a391595f,eb20c534,4933937a,cdb2eba1,86d49f8b,845c1b5f,4ca87182,8dae4162,73c6c068,2e2aede4,76efa86b,7612c07e,f72070d0,dc4486f1,47e95085), S(6fd5e13c,a94b874b,28cd574b,726efdbf,143ab108,1089b846,7b5b2ebe,6c6a3c8f,4a4db306,52c9772a,868b2859,57c5a005,d83f6afa,6e65d87c,700da998,ce651396), S(609b6576,191514f4,83f5b428,500cfbaf,96871b8b,3348fe5c,1a131768,bb266b6f,90abb9c1,1bf184d2,8dbc424a,bbf74eb8,de4e0582,2ea5dd93,7d1e8b30,e5f695e7), @@ -396,7 +396,7 @@ S(36a066ae,694f2645,25cba884,956ebd46,ae568acf,11664965,63cee00d,a32f2199,5d1e97 S(4922879f,800234c9,63f4b572,d236843,4c4da5c8,ff741982,c3d1e341,841d1309,9b259470,24b5f4cb,97c68d18,f7f8dfca,1e57f7de,63208765,2ce15770,98f35494), S(ee27e2b,acf95f6d,dbb5ebae,bbf181bb,43322a3d,6db87e78,14e57a3d,41b581e0,3d6a18a,daf69ae4,88ecc9d8,7d6b1bf2,c8d65544,3f4b45b4,c5a0ac51,7b1dc3ca)} #endif -#if (COMB_BLOCKS == 43) && (COMB_TEETH == 6) +#if (COMB_BLOCKS == 43) && (COMB_TEETH == 6) && (COMB_SPACING == 1) {S(e3adcb1a,fe947e6e,7cc4f5a2,df78310a,b235e2c3,bcd75eba,1904de80,c8814c50,e0b27ead,c4bbb9d2,37dad580,6e366674,4a9f9c3d,e024f2bd,1edb11d2,fafc0a22), S(612c2ec6,f0e9c4ec,c2200d23,ddca77eb,d003be35,61e52b1,890bf846,3bb53ea5,9e944d7b,dfc7a952,c1c5ee15,485d7199,dda19551,2d729628,c215a9e0,285f656a), S(42053dc0,9f90a7f7,86feca60,d68a5c3c,789e44d2,3479aa13,2d1a427c,621373a3,b338f891,f3930ec7,738669bb,3a29ae2d,637be08a,954f2a8c,acb661af,a660bd22), diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index a17d32de57..5843b3e1f5 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -389,7 +389,7 @@ int main(int argc, char** argv) { } /* Recreate the ecmult{,_gen} tables using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */ - secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, COMB_BLOCKS, COMB_TEETH); + secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, COMB_BLOCKS, COMB_TEETH, COMB_SPACING); secp256k1_ecmult_compute_two_tables(secp256k1_pre_g, secp256k1_pre_g_128, WINDOW_G, &secp256k1_ge_const_g); while (count--) {