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 */