|  | 
| 56 | 56 | 
 | 
| 57 | 57 | #define ECMULT_MAX_POINTS_PER_BATCH 5000000 | 
| 58 | 58 | 
 | 
| 59 |  | -/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain | 
| 60 |  | - *  the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will | 
| 61 |  | - *  contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. | 
| 62 |  | - *  Prej's Z values are undefined, except for the last value. | 
|  | 59 | +/** Fill a table 'pre_a' with precomputed odd multiples of a. | 
|  | 60 | + *  pre_a will contain [1*a,3*a,...,(2*n-1)*a], so it needs space for n group elements. | 
|  | 61 | + *  zr needs space for n field elements. | 
|  | 62 | + * | 
|  | 63 | + *  Although pre_a is an array of _ge rather than _gej, it actually represents elements | 
|  | 64 | + *  in Jacobian coordinates with their z coordinates omitted. The omitted z-coordinates | 
|  | 65 | + *  can be recovered using z and zr. Using the notation z(b) to represent the omitted | 
|  | 66 | + *  z coordinate of b: | 
|  | 67 | + *  - z(pre_a[n-1]) = 'z' | 
|  | 68 | + *  - z(pre_a[i-1]) = z(pre_a[i]) / zr[i] for n > i > 0 | 
|  | 69 | + * | 
|  | 70 | + *  Lastly the zr[0] value, which isn't used above, is set so that: | 
|  | 71 | + *  - a.z = z(pre_a[0]) / zr[0] | 
| 63 | 72 |  */ | 
| 64 |  | -static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { | 
| 65 |  | -    secp256k1_gej d; | 
| 66 |  | -    secp256k1_ge a_ge, d_ge; | 
|  | 73 | +static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_ge *pre_a, secp256k1_fe *zr, secp256k1_fe *z, const secp256k1_gej *a) { | 
|  | 74 | +    secp256k1_gej d, ai; | 
|  | 75 | +    secp256k1_ge d_ge; | 
| 67 | 76 |     int i; | 
| 68 | 77 | 
 | 
| 69 | 78 |     VERIFY_CHECK(!a->infinity); | 
| 70 | 79 | 
 | 
| 71 | 80 |     secp256k1_gej_double_var(&d, a, NULL); | 
| 72 | 81 | 
 | 
| 73 | 82 |     /* | 
| 74 |  | -     * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate | 
| 75 |  | -     * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. | 
|  | 83 | +     * Perform the additions using an isomorphic curve Y^2 = X^3 + 7*C^6 where C := d.z. | 
|  | 84 | +     * The isomorphism, phi, maps a secp256k1 point (x, y) to the point (x*C^2, y*C^3) on the other curve. | 
|  | 85 | +     * In Jacobian coordinates phi maps (x, y, z) to (x*C^2, y*C^3, z) or, equivalently to (x, y, z/C). | 
|  | 86 | +     * | 
|  | 87 | +     *     phi(x, y, z) = (x*C^2, y*C^3, z) = (x, y, z/C) | 
|  | 88 | +     *   d_ge := phi(d) = (d.x, d.y, 1) | 
|  | 89 | +     *     ai := phi(a) = (a.x*C^2, a.y*C^3, a.z) | 
|  | 90 | +     * | 
|  | 91 | +     * The group addition functions work correctly on these isomorphic curves. | 
|  | 92 | +     * In particular phi(d) is easy to represent in affine coordinates under this isomorphism. | 
|  | 93 | +     * This lets us use the faster secp256k1_gej_add_ge_var group addition function that we wouldn't be able to use otherwise. | 
| 76 | 94 |      */ | 
| 77 |  | -    d_ge.x = d.x; | 
| 78 |  | -    d_ge.y = d.y; | 
| 79 |  | -    d_ge.infinity = 0; | 
| 80 |  | - | 
| 81 |  | -    secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); | 
| 82 |  | -    prej[0].x = a_ge.x; | 
| 83 |  | -    prej[0].y = a_ge.y; | 
| 84 |  | -    prej[0].z = a->z; | 
| 85 |  | -    prej[0].infinity = 0; | 
|  | 95 | +    secp256k1_ge_set_xy(&d_ge, &d.x, &d.y); | 
|  | 96 | +    secp256k1_ge_set_gej_zinv(&pre_a[0], a, &d.z); | 
|  | 97 | +    secp256k1_gej_set_ge(&ai, &pre_a[0]); | 
|  | 98 | +    ai.z = a->z; | 
| 86 | 99 | 
 | 
|  | 100 | +    /* pre_a[0] is the point (a.x*C^2, a.y*C^3, a.z*C) which is equvalent to a. | 
|  | 101 | +     * Set zr[0] to C, which is the ratio between the omitted z(pre_a[0]) value and a.z. | 
|  | 102 | +     */ | 
| 87 | 103 |     zr[0] = d.z; | 
|  | 104 | + | 
| 88 | 105 |     for (i = 1; i < n; i++) { | 
| 89 |  | -        secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); | 
|  | 106 | +        secp256k1_gej_add_ge_var(&ai, &ai, &d_ge, &zr[i]); | 
|  | 107 | +        secp256k1_ge_set_xy(&pre_a[i], &ai.x, &ai.y); | 
| 90 | 108 |     } | 
| 91 | 109 | 
 | 
| 92 |  | -    /* | 
| 93 |  | -     * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only | 
| 94 |  | -     * the final point's z coordinate is actually used though, so just update that. | 
|  | 110 | +    /* Multiply the last z-coordinate by C to undo the isomorphism. | 
|  | 111 | +     * Since the z-coordinates of the pre_a values are implied by the zr array of z-coordinate ratios, | 
|  | 112 | +     * undoing the isomorphism here undoes the isomorphism for all pre_a values. | 
| 95 | 113 |      */ | 
| 96 |  | -    secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); | 
|  | 114 | +    secp256k1_fe_mul(z, &ai.z, &d.z); | 
| 97 | 115 | } | 
| 98 | 116 | 
 | 
| 99 | 117 | /** The following two macro retrieves a particular odd multiple from a table | 
| @@ -246,18 +264,18 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state * | 
| 246 | 264 |      */ | 
| 247 | 265 |     if (no > 0) { | 
| 248 | 266 |         /* Compute the odd multiples in Jacobian form. */ | 
| 249 |  | -        secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej, state->zr, &a[state->ps[0].input_pos]); | 
|  | 267 | +        secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a, state->zr, &Z, &a[state->ps[0].input_pos]); | 
| 250 | 268 |         for (np = 1; np < no; ++np) { | 
| 251 | 269 |             secp256k1_gej tmp = a[state->ps[np].input_pos]; | 
| 252 | 270 | #ifdef VERIFY | 
| 253 |  | -            secp256k1_fe_normalize_var(&(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); | 
|  | 271 | +            secp256k1_fe_normalize_var(&Z); | 
| 254 | 272 | #endif | 
| 255 |  | -            secp256k1_gej_rescale(&tmp, &(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); | 
| 256 |  | -            secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &tmp); | 
|  | 273 | +            secp256k1_gej_rescale(&tmp, &Z); | 
|  | 274 | +            secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp); | 
| 257 | 275 |             secp256k1_fe_mul(state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &(a[state->ps[np].input_pos].z)); | 
| 258 | 276 |         } | 
| 259 | 277 |         /* Bring them to the same Z denominator. */ | 
| 260 |  | -        secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, &Z, state->prej, state->zr); | 
|  | 278 | +        secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->zr); | 
| 261 | 279 |     } else { | 
| 262 | 280 |         secp256k1_fe_set_int(&Z, 1); | 
| 263 | 281 |     } | 
|  | 
0 commit comments