github.com/onflow/flow-go/crypto@v0.24.8/bls_thresholdsign_core.c (about)

     1  // +build relic
     2  
     3  #include "bls_thresholdsign_include.h"
     4  
     5  // Computes the Lagrange coefficient L(i+1) at 0 with regards to the range [signers(0)+1..signers(t)+1]
     6  // and stores it in res, where t is the degree of the polynomial P
     7  static void Zr_lagrangeCoefficientAtZero(bn_t res, const int i, const uint8_t* signers, const int len){
     8      // r is the order of G1 and G2
     9      bn_t r, r_2;
    10      bn_new(r);
    11      g2_get_ord(r);
    12      // (r-2) is needed to compute the inverse in Zr
    13      // using little Fermat theorem
    14      bn_new(r_2);
    15      bn_sub_dig(r_2, r, 2);
    16      //#define MOD_METHOD MONTY
    17      #define MOD_METHOD BASIC
    18  
    19      #if MOD_METHOD == MONTY   
    20      bn_t u;
    21      bn_new(u)
    22      // Montgomery reduction constant
    23      // TODO: hardcode u
    24      bn_mod_pre_monty(u, r);
    25      #endif
    26  
    27      // temp buffers
    28      bn_t acc, inv, base, numerator;
    29      bn_new(inv);
    30      bn_new(base);
    31      bn_new_size(base, BITS_TO_DIGITS(Fr_BITS))
    32      bn_new(acc);
    33      bn_new(numerator);
    34      bn_new_size(acc, BITS_TO_DIGITS(3*Fr_BITS));
    35  
    36      // the accumulator of the largarnge coeffiecient 
    37      // the sign (sign of acc) is equal to 1 if acc is positive, 0 otherwise
    38      bn_set_dig(acc, 1);
    39      int sign = 1;
    40  
    41      // loops is the maximum number of loops that takes the accumulator to 
    42      // overflow modulo r, mainly the highest k such that fact(MAX_IND)/fact(MAX_IND-k) < r
    43      const int loops = MAX_IND_LOOPS;
    44      int k,j = 0;
    45      while (j<len) {
    46          bn_set_dig(base, 1);
    47          bn_set_dig(numerator, 1);
    48          for (k = j; j < MIN(len, k+loops); j++){
    49              if (signers[j]==i) 
    50                  continue;
    51              if (signers[j]<i) 
    52                  sign ^= 1;
    53              bn_mul_dig(base, base, abs((int)signers[j]-i));
    54              bn_mul_dig(numerator, numerator, signers[j]+1);
    55          }
    56          // compute the inverse using little Fermat theorem
    57          bn_mxp_slide(inv, base, r_2, r);
    58          #if MOD_METHOD == MONTY 
    59          // convert to Montgomery domain
    60          bn_mod_monty_conv(inv, inv, r);
    61          bn_mod_monty_conv(numerator, numerator, r);
    62          bn_mod_monty_conv(acc, acc, r);
    63          // multiply
    64          bn_mul(acc, acc, inv);
    65          bn_mod_monty(acc, acc, r, u);
    66          bn_mul(acc, acc, numerator);
    67          bn_mod_monty(acc, acc, r, u);
    68          bn_mod_monty_back(acc, acc, r);
    69          #elif MOD_METHOD == BASIC 
    70          bn_mul(acc, acc, inv);
    71          bn_mul(acc, acc, numerator);
    72          bn_mod_basic(acc, acc, r);
    73          #endif
    74      }
    75      if (sign) bn_copy(res, acc);
    76      else bn_sub(res, r, acc);
    77  
    78      // free the temp memory
    79      bn_free(r);bn_free(r_1);
    80      #if MOD_METHOD == MONTY   
    81      bn_free(&u);
    82      #endif
    83      bn_free(acc);
    84      bn_free(inv);bn_free(base);
    85      bn_free(numerator);
    86  }
    87  
    88  
    89  // Computes the Langrange interpolation at zero LI(0) with regards to the points [signers(1)+1..signers(t+1)+1] 
    90  // and their images [shares(1)..shares(t+1)], and stores the result in dest
    91  // len is the polynomial degree 
    92  int G1_lagrangeInterpolateAtZero(byte* dest, const byte* shares, const uint8_t* signers, const int len) {
    93      // computes Q(x) = A_0 + A_1*x + ... +  A_n*x^n  in G2
    94      // powers of x
    95      bn_t bn_lagr_coef;
    96      bn_new(bn_lagr_coef);
    97      bn_new_size(bn_lagr_coef, BITS_TO_BYTES(Fr_BITS));
    98      
    99      // temp variables
   100      ep_t mult, acc, share;
   101      ep_new(mult);         
   102      ep_new(acc);
   103      ep_new(share);
   104      ep_set_infty(acc);
   105  
   106      for (int i=0; i < len; i++) {
   107          int read_ret = ep_read_bin_compact(share, &shares[SIGNATURE_LEN*i], SIGNATURE_LEN);
   108          if (read_ret != RLC_OK)
   109              return read_ret;
   110          Zr_lagrangeCoefficientAtZero(bn_lagr_coef, signers[i], signers, len);
   111          ep_mul_lwnaf(mult, share, bn_lagr_coef);
   112          ep_add_jacob(acc, acc, mult);
   113      }
   114      // export the result
   115      ep_write_bin_compact(dest, acc, SIGNATURE_LEN);
   116  
   117      // free the temp memory
   118      ep2_free(acc);
   119      ep2_free(mult);
   120      ep2_free(share);
   121      bn_free(bn_lagr_coef);
   122      return VALID;
   123  }