Skip to content

Commit ba5ec2d

Browse files
jonasnickdeadalnix
authored andcommitted
Remove unnecessary sign variable from wnaf_const
Summary: * Fix test_constant_wnaf for -1 and add a test for it. Before, test_constant_wnaf used scalar_cadd_bit to correct for the skew. But this function does not correctly deal with overflows which is why num = -1 couldn't be tested. This commit also adds tests for 0, 1/2 and 1/2-1 as they are corner cases in constant_wnaf. * Remove unnecessary sign variable from wnaf_const This is a backport of libsecp256k1 [[bitcoin-core/secp256k1#741 | PR741]] Test Plan: ninja check-secp256k1 Reviewers: #bitcoin_abc, majcosta Reviewed By: #bitcoin_abc, majcosta Differential Revision: https://reviews.bitcoinabc.org/D7595
1 parent 760e829 commit ba5ec2d

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/secp256k1/src/ecmult_const_impl.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,22 @@ static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w
105105
/* 4 */
106106
u_last = secp256k1_scalar_shr_int(&s, w);
107107
do {
108-
int sign;
109108
int even;
110109

111110
/* 4.1 4.4 */
112111
u = secp256k1_scalar_shr_int(&s, w);
113112
/* 4.2 */
114113
even = ((u & 1) == 0);
115-
sign = 2 * (u_last > 0) - 1;
116-
u += sign * even;
117-
u_last -= sign * even * (1 << w);
114+
/* In contrast to the original algorithm, u_last is always > 0 and
115+
* therefore we do not need to check its sign. In particular, it's easy
116+
* to see that u_last is never < 0 because u is never < 0. Moreover,
117+
* u_last is never = 0 because u is never even after a loop
118+
* iteration. The same holds analogously for the initial value of
119+
* u_last (in the first loop iteration). */
120+
VERIFY_CHECK(u_last > 0);
121+
VERIFY_CHECK((u_last & 1) == 1);
122+
u += even;
123+
u_last -= even * (1 << w);
118124

119125
/* 4.3, adapted for global sign change */
120126
wnaf[word++] = u_last * global_sign;

src/secp256k1/src/tests.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3231,6 +3231,7 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
32313231
int skew;
32323232
int bits = 256;
32333233
secp256k1_scalar num = *number;
3234+
secp256k1_scalar scalar_skew;
32343235

32353236
secp256k1_scalar_set_int(&x, 0);
32363237
secp256k1_scalar_set_int(&shift, 1 << w);
@@ -3261,7 +3262,8 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
32613262
secp256k1_scalar_add(&x, &x, &t);
32623263
}
32633264
/* Skew num because when encoding numbers as odd we use an offset */
3264-
secp256k1_scalar_cadd_bit(&num, skew == 2, 1);
3265+
secp256k1_scalar_set_int(&scalar_skew, 1 << (skew == 2));
3266+
secp256k1_scalar_add(&num, &num, &scalar_skew);
32653267
CHECK(secp256k1_scalar_eq(&x, &num));
32663268
}
32673269

@@ -3373,13 +3375,32 @@ void run_wnaf(void) {
33733375
int i;
33743376
secp256k1_scalar n = {{0}};
33753377

3378+
test_constant_wnaf(&n, 4);
33763379
/* Sanity check: 1 and 2 are the smallest odd and even numbers and should
33773380
* have easier-to-diagnose failure modes */
33783381
n.d[0] = 1;
33793382
test_constant_wnaf(&n, 4);
33803383
n.d[0] = 2;
33813384
test_constant_wnaf(&n, 4);
3382-
/* Test 0 */
3385+
/* Test -1, because it's a special case in wnaf_const */
3386+
n = secp256k1_scalar_one;
3387+
secp256k1_scalar_negate(&n, &n);
3388+
test_constant_wnaf(&n, 4);
3389+
3390+
/* Test -2, which may not lead to overflows in wnaf_const */
3391+
secp256k1_scalar_add(&n, &secp256k1_scalar_one, &secp256k1_scalar_one);
3392+
secp256k1_scalar_negate(&n, &n);
3393+
test_constant_wnaf(&n, 4);
3394+
3395+
/* Test (1/2) - 1 = 1/-2 and 1/2 = (1/-2) + 1
3396+
as corner cases of negation handling in wnaf_const */
3397+
secp256k1_scalar_inverse(&n, &n);
3398+
test_constant_wnaf(&n, 4);
3399+
3400+
secp256k1_scalar_add(&n, &n, &secp256k1_scalar_one);
3401+
test_constant_wnaf(&n, 4);
3402+
3403+
/* Test 0 for fixed wnaf */
33833404
test_fixed_wnaf_small();
33843405
/* Random tests */
33853406
for (i = 0; i < count; i++) {

0 commit comments

Comments
 (0)