diff --git a/src/field.h b/src/field.h index ccb4327ee69db..64ceead4d2024 100644 --- a/src/field.h +++ b/src/field.h @@ -85,6 +85,9 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a); * as an argument. The magnitude of the output is one higher. */ static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m); +/** Adds a small integer (up to 0x7FFF) to r. The resulting magnitude increases by one. */ +static void secp256k1_fe_add_int(secp256k1_fe *r, int a); + /** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that * small integer. */ static void secp256k1_fe_mul_int(secp256k1_fe *r, int a); diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index 72c56df02fae6..46b72ce78d5b3 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -482,6 +482,20 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f #endif } +SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { +#ifdef VERIFY + secp256k1_fe_verify(r); + VERIFY_CHECK(a >= 0); + VERIFY_CHECK(a <= 0x7FFF); +#endif + r->n[0] += a; +#ifdef VERIFY + r->magnitude += 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + #if defined(USE_EXTERNAL_ASM) /* External assembler implementation */ diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 538991c7a9abc..4c4466ecebaaa 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -425,6 +425,20 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { #endif } +SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { +#ifdef VERIFY + secp256k1_fe_verify(r); + VERIFY_CHECK(a >= 0); + VERIFY_CHECK(a <= 0x7FFF); +#endif + r->n[0] += a; +#ifdef VERIFY + r->magnitude += 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { #ifdef VERIFY secp256k1_fe_verify(a); diff --git a/src/group_impl.h b/src/group_impl.h index 111ee68bab56a..82ce3f8d8bb75 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -227,7 +227,7 @@ static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int o secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); r->infinity = 0; - secp256k1_fe_add(&x3, &secp256k1_fe_const_b); + secp256k1_fe_add_int(&x3, SECP256K1_B); if (!secp256k1_fe_sqrt(&r->y, &x3)) { return 0; } @@ -282,7 +282,7 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { /* y^2 = x^3 + 7 */ secp256k1_fe_sqr(&y2, &a->y); secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_add(&x3, &secp256k1_fe_const_b); + secp256k1_fe_add_int(&x3, SECP256K1_B); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); } diff --git a/src/tests.c b/src/tests.c index e80397cb9bf1d..1c0d7973490ea 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3093,6 +3093,7 @@ static void run_field_misc(void) { secp256k1_fe y; secp256k1_fe z; secp256k1_fe q; + int v; secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); int i, j; for (i = 0; i < 1000 * COUNT; i++) { @@ -3103,6 +3104,14 @@ static void run_field_misc(void) { random_fe_test(&x); } random_fe_non_zero(&y); + v = secp256k1_testrand_bits(15); + /* Test that fe_add_int is equivalent to fe_set_int + fe_add. */ + secp256k1_fe_set_int(&q, v); /* q = v */ + z = x; /* z = x */ + secp256k1_fe_add(&z, &q); /* z = x+v */ + q = x; /* q = x */ + secp256k1_fe_add_int(&q, v); /* q = x+v */ + CHECK(check_fe_equal(&q, &z)); /* Test the fe equality and comparison operations. */ CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); CHECK(secp256k1_fe_equal_var(&x, &x)); @@ -3371,7 +3380,7 @@ static void test_inverse_field(secp256k1_fe* out, const secp256k1_fe* x, int var (var ? secp256k1_fe_inv_var : secp256k1_fe_inv)(&r, &r); /* r = 1/(x-1) */ secp256k1_fe_add(&l, &fe_minus_one); /* l = 1/x-1 */ (var ? secp256k1_fe_inv_var : secp256k1_fe_inv)(&l, &l); /* l = 1/(1/x-1) */ - secp256k1_fe_add(&l, &secp256k1_fe_one); /* l = 1/(1/x-1)+1 */ + secp256k1_fe_add_int(&l, 1); /* l = 1/(1/x-1)+1 */ secp256k1_fe_add(&l, &r); /* l = 1/(1/x-1)+1 + 1/(x-1) */ CHECK(secp256k1_fe_normalizes_to_zero_var(&l)); /* l == 0 */ }