47
47
48
48
/* The number of objects allocated on the scratch space for ecmult_multi algorithms */
49
49
#define PIPPENGER_SCRATCH_OBJECTS 6
50
- #define STRAUSS_SCRATCH_OBJECTS 7
50
+ #define STRAUSS_SCRATCH_OBJECTS 5
51
51
52
52
#define PIPPENGER_MAX_BUCKET_WINDOW 12
53
53
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
- /** The following two macro retrieves a particular odd multiple from a table
100
- * of precomputed multiples. */
101
- #define ECMULT_TABLE_GET_GE (r ,pre ,n ,w ) do { \
117
+ #define SECP256K1_ECMULT_TABLE_VERIFY (n ,w ) \
102
118
VERIFY_CHECK(((n) & 1) == 1); \
103
119
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
104
- VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
105
- if ((n) > 0) { \
106
- *(r) = (pre)[((n)-1)/2]; \
107
- } else { \
108
- *(r) = (pre)[(-(n)-1)/2]; \
109
- secp256k1_fe_negate(&((r)->y), &((r)->y), 1); \
110
- } \
111
- } while(0)
112
-
113
- #define ECMULT_TABLE_GET_GE_STORAGE (r ,pre ,n ,w ) do { \
114
- VERIFY_CHECK(((n) & 1) == 1); \
115
- VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
116
- VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
117
- if ((n) > 0) { \
118
- secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \
119
- } else { \
120
- secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \
121
- secp256k1_fe_negate(&((r)->y), &((r)->y), 1); \
122
- } \
123
- } while(0)
120
+ VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1));
121
+
122
+ SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge (secp256k1_ge * r , const secp256k1_ge * pre , int n , int w ) {
123
+ SECP256K1_ECMULT_TABLE_VERIFY (n ,w )
124
+ if (n > 0 ) {
125
+ * r = pre [(n - 1 )/2 ];
126
+ } else {
127
+ * r = pre [(- n - 1 )/2 ];
128
+ secp256k1_fe_negate (& (r -> y ), & (r -> y ), 1 );
129
+ }
130
+ }
131
+
132
+ SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge_lambda (secp256k1_ge * r , const secp256k1_ge * pre , const secp256k1_fe * x , int n , int w ) {
133
+ SECP256K1_ECMULT_TABLE_VERIFY (n ,w )
134
+ if (n > 0 ) {
135
+ secp256k1_ge_set_xy (r , & x [(n - 1 )/2 ], & pre [(n - 1 )/2 ].y );
136
+ } else {
137
+ secp256k1_ge_set_xy (r , & x [(- n - 1 )/2 ], & pre [(- n - 1 )/2 ].y );
138
+ secp256k1_fe_negate (& (r -> y ), & (r -> y ), 1 );
139
+ }
140
+ }
141
+
142
+ SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge_storage (secp256k1_ge * r , const secp256k1_ge_storage * pre , int n , int w ) {
143
+ SECP256K1_ECMULT_TABLE_VERIFY (n ,w )
144
+ if (n > 0 ) {
145
+ secp256k1_ge_from_storage (r , & pre [(n - 1 )/2 ]);
146
+ } else {
147
+ secp256k1_ge_from_storage (r , & pre [(- n - 1 )/2 ]);
148
+ secp256k1_fe_negate (& (r -> y ), & (r -> y ), 1 );
149
+ }
150
+ }
124
151
125
152
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
126
153
* with the following guarantees:
@@ -182,19 +209,16 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
182
209
}
183
210
184
211
struct secp256k1_strauss_point_state {
185
- secp256k1_scalar na_1 , na_lam ;
186
212
int wnaf_na_1 [129 ];
187
213
int wnaf_na_lam [129 ];
188
214
int bits_na_1 ;
189
215
int bits_na_lam ;
190
- size_t input_pos ;
191
216
};
192
217
193
218
struct secp256k1_strauss_state {
194
- secp256k1_gej * prej ;
195
- secp256k1_fe * zr ;
219
+ /* aux is used to hold z-ratios, and then used to hold pre_a[i].x * BETA values. */
220
+ secp256k1_fe * aux ;
196
221
secp256k1_ge * pre_a ;
197
- secp256k1_ge * pre_a_lam ;
198
222
struct secp256k1_strauss_point_state * ps ;
199
223
};
200
224
@@ -212,17 +236,19 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
212
236
size_t np ;
213
237
size_t no = 0 ;
214
238
239
+ secp256k1_fe_set_int (& Z , 1 );
215
240
for (np = 0 ; np < num ; ++ np ) {
241
+ secp256k1_gej tmp ;
242
+ secp256k1_scalar na_1 , na_lam ;
216
243
if (secp256k1_scalar_is_zero (& na [np ]) || secp256k1_gej_is_infinity (& a [np ])) {
217
244
continue ;
218
245
}
219
- state -> ps [no ].input_pos = np ;
220
246
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
221
- secp256k1_scalar_split_lambda (& state -> ps [ no ]. na_1 , & state -> ps [ no ]. na_lam , & na [np ]);
247
+ secp256k1_scalar_split_lambda (& na_1 , & na_lam , & na [np ]);
222
248
223
249
/* build wnaf representation for na_1 and na_lam. */
224
- state -> ps [no ].bits_na_1 = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na_1 , 129 , & state -> ps [ no ]. na_1 , WINDOW_A );
225
- state -> ps [no ].bits_na_lam = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na_lam , 129 , & state -> ps [ no ]. na_lam , WINDOW_A );
250
+ state -> ps [no ].bits_na_1 = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na_1 , 129 , & na_1 , WINDOW_A );
251
+ state -> ps [no ].bits_na_lam = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na_lam , 129 , & na_lam , WINDOW_A );
226
252
VERIFY_CHECK (state -> ps [no ].bits_na_1 <= 129 );
227
253
VERIFY_CHECK (state -> ps [no ].bits_na_lam <= 129 );
228
254
if (state -> ps [no ].bits_na_1 > bits ) {
@@ -231,40 +257,36 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
231
257
if (state -> ps [no ].bits_na_lam > bits ) {
232
258
bits = state -> ps [no ].bits_na_lam ;
233
259
}
234
- ++ no ;
235
- }
236
260
237
- /* Calculate odd multiples of a.
238
- * All multiples are brought to the same Z 'denominator', which is stored
239
- * in Z. Due to secp256k1' isomorphism we can do all operations pretending
240
- * that the Z coordinate was 1, use affine addition formulae, and correct
241
- * the Z coordinate of the result once at the end.
242
- * The exception is the precomputed G table points, which are actually
243
- * affine. Compared to the base used for other points, they have a Z ratio
244
- * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
245
- * isomorphism to efficiently add with a known Z inverse.
246
- */
247
- if (no > 0 ) {
248
- /* 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 ]);
250
- for (np = 1 ; np < no ; ++ np ) {
251
- secp256k1_gej tmp = a [state -> ps [np ].input_pos ];
261
+ /* Calculate odd multiples of a.
262
+ * All multiples are brought to the same Z 'denominator', which is stored
263
+ * in Z. Due to secp256k1' isomorphism we can do all operations pretending
264
+ * that the Z coordinate was 1, use affine addition formulae, and correct
265
+ * the Z coordinate of the result once at the end.
266
+ * The exception is the precomputed G table points, which are actually
267
+ * affine. Compared to the base used for other points, they have a Z ratio
268
+ * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
269
+ * isomorphism to efficiently add with a known Z inverse.
270
+ */
271
+ tmp = a [np ];
272
+ if (no ) {
252
273
#ifdef VERIFY
253
- secp256k1_fe_normalize_var (& ( state -> prej [( np - 1 ) * ECMULT_TABLE_SIZE ( WINDOW_A ) + ECMULT_TABLE_SIZE ( WINDOW_A ) - 1 ]. z ) );
274
+ secp256k1_fe_normalize_var (& Z );
254
275
#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 );
257
- 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 ));
276
+ secp256k1_gej_rescale (& tmp , & Z );
258
277
}
259
- /* 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 );
261
- } else {
262
- secp256k1_fe_set_int ( & Z , 1 ) ;
278
+ secp256k1_ecmult_odd_multiples_table ( ECMULT_TABLE_SIZE ( WINDOW_A ), state -> pre_a + no * ECMULT_TABLE_SIZE ( WINDOW_A ), state -> aux + no * ECMULT_TABLE_SIZE ( WINDOW_A ), & Z , & tmp );
279
+ if ( no ) secp256k1_fe_mul ( state -> aux + no * ECMULT_TABLE_SIZE ( WINDOW_A ) , state -> aux + no * ECMULT_TABLE_SIZE ( WINDOW_A ), & ( a [ np ]. z ) );
280
+
281
+ ++ no ;
263
282
}
264
283
284
+ /* Bring them to the same Z denominator. */
285
+ secp256k1_ge_table_set_globalz (ECMULT_TABLE_SIZE (WINDOW_A ) * no , state -> pre_a , state -> aux );
286
+
265
287
for (np = 0 ; np < no ; ++ np ) {
266
288
for (i = 0 ; i < ECMULT_TABLE_SIZE (WINDOW_A ); i ++ ) {
267
- secp256k1_ge_mul_lambda (& state -> pre_a_lam [np * ECMULT_TABLE_SIZE (WINDOW_A ) + i ], & state -> pre_a [np * ECMULT_TABLE_SIZE (WINDOW_A ) + i ]);
289
+ secp256k1_fe_mul (& state -> aux [np * ECMULT_TABLE_SIZE (WINDOW_A ) + i ], & state -> pre_a [np * ECMULT_TABLE_SIZE (WINDOW_A ) + i ]. x , & secp256k1_const_beta );
268
290
}
269
291
}
270
292
@@ -290,20 +312,20 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
290
312
secp256k1_gej_double_var (r , r , NULL );
291
313
for (np = 0 ; np < no ; ++ np ) {
292
314
if (i < state -> ps [np ].bits_na_1 && (n = state -> ps [np ].wnaf_na_1 [i ])) {
293
- ECMULT_TABLE_GET_GE (& tmpa , state -> pre_a + np * ECMULT_TABLE_SIZE (WINDOW_A ), n , WINDOW_A );
315
+ secp256k1_ecmult_table_get_ge (& tmpa , state -> pre_a + np * ECMULT_TABLE_SIZE (WINDOW_A ), n , WINDOW_A );
294
316
secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
295
317
}
296
318
if (i < state -> ps [np ].bits_na_lam && (n = state -> ps [np ].wnaf_na_lam [i ])) {
297
- ECMULT_TABLE_GET_GE (& tmpa , state -> pre_a_lam + np * ECMULT_TABLE_SIZE (WINDOW_A ), n , WINDOW_A );
319
+ secp256k1_ecmult_table_get_ge_lambda (& tmpa , state -> pre_a + np * ECMULT_TABLE_SIZE ( WINDOW_A ), state -> aux + np * ECMULT_TABLE_SIZE (WINDOW_A ), n , WINDOW_A );
298
320
secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
299
321
}
300
322
}
301
323
if (i < bits_ng_1 && (n = wnaf_ng_1 [i ])) {
302
- ECMULT_TABLE_GET_GE_STORAGE (& tmpa , secp256k1_pre_g , n , WINDOW_G );
324
+ secp256k1_ecmult_table_get_ge_storage (& tmpa , secp256k1_pre_g , n , WINDOW_G );
303
325
secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
304
326
}
305
327
if (i < bits_ng_128 && (n = wnaf_ng_128 [i ])) {
306
- ECMULT_TABLE_GET_GE_STORAGE (& tmpa , secp256k1_pre_g_128 , n , WINDOW_G );
328
+ secp256k1_ecmult_table_get_ge_storage (& tmpa , secp256k1_pre_g_128 , n , WINDOW_G );
307
329
secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
308
330
}
309
331
}
@@ -314,23 +336,19 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
314
336
}
315
337
316
338
static void secp256k1_ecmult (secp256k1_gej * r , const secp256k1_gej * a , const secp256k1_scalar * na , const secp256k1_scalar * ng ) {
317
- secp256k1_gej prej [ECMULT_TABLE_SIZE (WINDOW_A )];
318
- secp256k1_fe zr [ECMULT_TABLE_SIZE (WINDOW_A )];
339
+ secp256k1_fe aux [ECMULT_TABLE_SIZE (WINDOW_A )];
319
340
secp256k1_ge pre_a [ECMULT_TABLE_SIZE (WINDOW_A )];
320
341
struct secp256k1_strauss_point_state ps [1 ];
321
- secp256k1_ge pre_a_lam [ECMULT_TABLE_SIZE (WINDOW_A )];
322
342
struct secp256k1_strauss_state state ;
323
343
324
- state .prej = prej ;
325
- state .zr = zr ;
344
+ state .aux = aux ;
326
345
state .pre_a = pre_a ;
327
- state .pre_a_lam = pre_a_lam ;
328
346
state .ps = ps ;
329
347
secp256k1_ecmult_strauss_wnaf (& state , r , 1 , a , na , ng );
330
348
}
331
349
332
350
static size_t secp256k1_strauss_scratch_size (size_t n_points ) {
333
- static const size_t point_size = (2 * sizeof (secp256k1_ge ) + sizeof ( secp256k1_gej ) + sizeof (secp256k1_fe )) * ECMULT_TABLE_SIZE (WINDOW_A ) + sizeof (struct secp256k1_strauss_point_state ) + sizeof (secp256k1_gej ) + sizeof (secp256k1_scalar );
351
+ static const size_t point_size = (sizeof (secp256k1_ge ) + sizeof (secp256k1_fe )) * ECMULT_TABLE_SIZE (WINDOW_A ) + sizeof (struct secp256k1_strauss_point_state ) + sizeof (secp256k1_gej ) + sizeof (secp256k1_scalar );
334
352
return n_points * point_size ;
335
353
}
336
354
@@ -351,13 +369,11 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
351
369
* constant and strauss_scratch_size accordingly. */
352
370
points = (secp256k1_gej * )secp256k1_scratch_alloc (error_callback , scratch , n_points * sizeof (secp256k1_gej ));
353
371
scalars = (secp256k1_scalar * )secp256k1_scratch_alloc (error_callback , scratch , n_points * sizeof (secp256k1_scalar ));
354
- state .prej = (secp256k1_gej * )secp256k1_scratch_alloc (error_callback , scratch , n_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_gej ));
355
- state .zr = (secp256k1_fe * )secp256k1_scratch_alloc (error_callback , scratch , n_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_fe ));
372
+ state .aux = (secp256k1_fe * )secp256k1_scratch_alloc (error_callback , scratch , n_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_fe ));
356
373
state .pre_a = (secp256k1_ge * )secp256k1_scratch_alloc (error_callback , scratch , n_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_ge ));
357
- state .pre_a_lam = (secp256k1_ge * )secp256k1_scratch_alloc (error_callback , scratch , n_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_ge ));
358
374
state .ps = (struct secp256k1_strauss_point_state * )secp256k1_scratch_alloc (error_callback , scratch , n_points * sizeof (struct secp256k1_strauss_point_state ));
359
375
360
- if (points == NULL || scalars == NULL || state .prej == NULL || state .zr == NULL || state . pre_a == NULL || state . pre_a_lam == NULL || state .ps == NULL ) {
376
+ if (points == NULL || scalars == NULL || state .aux == NULL || state .pre_a == NULL || state .ps == NULL ) {
361
377
secp256k1_scratch_apply_checkpoint (error_callback , scratch , scratch_checkpoint );
362
378
return 0 ;
363
379
}
0 commit comments