|
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