github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/src/ecmult_gen_compute_table_impl.h (about) 1 /*********************************************************************** 2 * Copyright (c) Pieter Wuille, Gregory Maxwell, Peter Dettman * 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 #ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H 8 #define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H 9 10 #include "ecmult_gen_compute_table.h" 11 #include "group_impl.h" 12 #include "field_impl.h" 13 #include "scalar_impl.h" 14 #include "ecmult_gen.h" 15 #include "util.h" 16 17 static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing) { 18 size_t points = ((size_t)1) << (teeth - 1); 19 size_t points_total = points * blocks; 20 secp256k1_ge* prec = checked_malloc(&default_error_callback, points_total * sizeof(*prec)); 21 secp256k1_gej* ds = checked_malloc(&default_error_callback, teeth * sizeof(*ds)); 22 secp256k1_gej* vs = checked_malloc(&default_error_callback, points_total * sizeof(*vs)); 23 secp256k1_gej u; 24 size_t vs_pos = 0; 25 secp256k1_scalar half; 26 int block, i; 27 28 VERIFY_CHECK(points_total > 0); 29 30 /* u is the running power of two times gen we're working with, initially gen/2. */ 31 secp256k1_scalar_half(&half, &secp256k1_scalar_one); 32 secp256k1_gej_set_infinity(&u); 33 for (i = 255; i >= 0; --i) { 34 /* Use a very simple multiplication ladder to avoid dependency on ecmult. */ 35 secp256k1_gej_double_var(&u, &u, NULL); 36 if (secp256k1_scalar_get_bits_limb32(&half, i, 1)) { 37 secp256k1_gej_add_ge_var(&u, &u, gen, NULL); 38 } 39 } 40 #ifdef VERIFY 41 { 42 /* Verify that u*2 = gen. */ 43 secp256k1_gej double_u; 44 secp256k1_gej_double_var(&double_u, &u, NULL); 45 VERIFY_CHECK(secp256k1_gej_eq_ge_var(&double_u, gen)); 46 } 47 #endif 48 49 for (block = 0; block < blocks; ++block) { 50 int tooth; 51 /* Here u = 2^(block*teeth*spacing) * gen/2. */ 52 secp256k1_gej sum; 53 secp256k1_gej_set_infinity(&sum); 54 for (tooth = 0; tooth < teeth; ++tooth) { 55 /* Here u = 2^((block*teeth + tooth)*spacing) * gen/2. */ 56 /* Make sum = sum(2^((block*teeth + t)*spacing), t=0..tooth) * gen/2. */ 57 secp256k1_gej_add_var(&sum, &sum, &u, NULL); 58 /* Make u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ 59 secp256k1_gej_double_var(&u, &u, NULL); 60 /* Make ds[tooth] = u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ 61 ds[tooth] = u; 62 /* Make u = 2^((block*teeth + tooth + 1)*spacing) * gen/2, unless at the end. */ 63 if (block + tooth != blocks + teeth - 2) { 64 int bit_off; 65 for (bit_off = 1; bit_off < spacing; ++bit_off) { 66 secp256k1_gej_double_var(&u, &u, NULL); 67 } 68 } 69 } 70 /* Now u = 2^((block*teeth + teeth)*spacing) * gen/2 71 * = 2^((block+1)*teeth*spacing) * gen/2 */ 72 73 /* Next, compute the table entries for block number block in Jacobian coordinates. 74 * The entries will occupy vs[block*points + i] for i=0..points-1. 75 * We start by computing the first (i=0) value corresponding to all summed 76 * powers of two times G being negative. */ 77 secp256k1_gej_neg(&vs[vs_pos++], &sum); 78 /* And then teeth-1 times "double" the range of i values for which the table 79 * is computed: in each iteration, double the table by taking an existing 80 * table entry and adding ds[tooth]. */ 81 for (tooth = 0; tooth < teeth - 1; ++tooth) { 82 size_t stride = ((size_t)1) << tooth; 83 size_t index; 84 for (index = 0; index < stride; ++index, ++vs_pos) { 85 secp256k1_gej_add_var(&vs[vs_pos], &vs[vs_pos - stride], &ds[tooth], NULL); 86 } 87 } 88 } 89 VERIFY_CHECK(vs_pos == points_total); 90 91 /* Convert all points simultaneously from secp256k1_gej to secp256k1_ge. */ 92 secp256k1_ge_set_all_gej_var(prec, vs, points_total); 93 /* Convert all points from secp256k1_ge to secp256k1_ge_storage output. */ 94 for (block = 0; block < blocks; ++block) { 95 size_t index; 96 for (index = 0; index < points; ++index) { 97 VERIFY_CHECK(!secp256k1_ge_is_infinity(&prec[block * points + index])); 98 secp256k1_ge_to_storage(&table[block * points + index], &prec[block * points + index]); 99 } 100 } 101 102 /* Free memory. */ 103 free(vs); 104 free(ds); 105 free(prec); 106 } 107 108 #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H */