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 }