Skip to content

Commit 55399c2

Browse files
committed
Further performance improvements to _ecmult_wnaf
- Initialize 'wnaf' to zeroes using memset - Add new 'len' arg to speed up smaller scalars (mostly for endo=yes)
1 parent 145cc6e commit 55399c2

File tree

3 files changed

+32
-21
lines changed

3 files changed

+32
-21
lines changed

src/bench_internal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ void bench_ecmult_wnaf(void* arg) {
229229
bench_inv_t *data = (bench_inv_t*)arg;
230230

231231
for (i = 0; i < 20000; i++) {
232-
secp256k1_ecmult_wnaf(data->wnaf, &data->scalar_x, WINDOW_A);
232+
secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A);
233233
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
234234
}
235235
}

src/ecmult_impl.h

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -213,21 +213,28 @@ static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx) {
213213
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
214214
* - two non-zero entries in wnaf are separated by at least w-1 zeroes.
215215
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more
216-
* - than the number of bits in the (absolute value) of the input.
216+
* than the number of bits in the (absolute value) of the input.
217217
*/
218-
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) {
218+
static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar_t *a, int w) {
219219
secp256k1_scalar_t s = *a;
220-
int set_bits = 0;
220+
int last_set_bit = -1;
221221
int bit = 0;
222222
int sign = 1;
223223
int carry = 0;
224224

225+
VERIFY_CHECK(wnaf != NULL);
226+
VERIFY_CHECK(0 <= len && len <= 256);
227+
VERIFY_CHECK(a != NULL);
228+
VERIFY_CHECK(2 <= w && w <= 31);
229+
230+
memset(wnaf, 0, len * sizeof(wnaf[0]));
231+
225232
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
226233
secp256k1_scalar_negate(&s, &s);
227234
sign = -1;
228235
}
229236

230-
while (bit < 256) {
237+
while (bit < len) {
231238
int now;
232239
int word;
233240
if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) {
@@ -236,23 +243,27 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w)
236243
}
237244

238245
now = w;
239-
if (now > 256 - bit) {
240-
now = 256 - bit;
246+
if (now > len - bit) {
247+
now = len - bit;
241248
}
242249

243250
word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry;
244251

245252
carry = (word >> (w-1)) & 1;
246253
word -= carry << w;
247254

248-
while (set_bits < bit) {
249-
wnaf[set_bits++] = 0;
250-
}
251-
wnaf[set_bits++] = sign * word;
255+
wnaf[bit] = sign * word;
256+
last_set_bit = bit;
257+
252258
bit += now;
253259
}
254-
VERIFY_CHECK(carry == 0);
255-
return set_bits;
260+
#ifdef VERIFY
261+
CHECK(carry == 0);
262+
while (bit < 256) {
263+
CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
264+
}
265+
#endif
266+
return last_set_bit + 1;
256267
}
257268

258269
static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
@@ -275,7 +286,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
275286
#else
276287
int wnaf_na[256];
277288
int bits_na;
278-
int wnaf_ng[257];
289+
int wnaf_ng[256];
279290
int bits_ng;
280291
#endif
281292
int i;
@@ -286,8 +297,8 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
286297
secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na);
287298

288299
/* build wnaf representation for na_1 and na_lam. */
289-
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
290-
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
300+
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A);
301+
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A);
291302
VERIFY_CHECK(bits_na_1 <= 130);
292303
VERIFY_CHECK(bits_na_lam <= 130);
293304
bits = bits_na_1;
@@ -296,7 +307,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
296307
}
297308
#else
298309
/* build wnaf representation for na. */
299-
bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
310+
bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A);
300311
bits = bits_na;
301312
#endif
302313

@@ -321,16 +332,16 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
321332
secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
322333

323334
/* Build wnaf representation for ng_1 and ng_128 */
324-
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);
325-
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
335+
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G);
336+
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G);
326337
if (bits_ng_1 > bits) {
327338
bits = bits_ng_1;
328339
}
329340
if (bits_ng_128 > bits) {
330341
bits = bits_ng_128;
331342
}
332343
#else
333-
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, ng, WINDOW_G);
344+
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G);
334345
if (bits_ng > bits) {
335346
bits = bits_ng;
336347
}

src/tests.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1374,7 +1374,7 @@ void test_wnaf(const secp256k1_scalar_t *number, int w) {
13741374
int bits;
13751375
secp256k1_scalar_set_int(&x, 0);
13761376
secp256k1_scalar_set_int(&two, 2);
1377-
bits = secp256k1_ecmult_wnaf(wnaf, number, w);
1377+
bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w);
13781378
CHECK(bits <= 256);
13791379
for (i = bits-1; i >= 0; i--) {
13801380
int v = wnaf[i];

0 commit comments

Comments
 (0)