From 7f7a2ed3a83aa778118dd36de04ee8ee1b42f48e Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 20 Sep 2018 22:24:57 +0000 Subject: [PATCH] ecmult_gen_impl: eliminate scratch memory used when generating context --- src/bench_ecmult.c | 2 +- src/ecmult_gen_impl.h | 2 +- src/group.h | 2 +- src/group_impl.h | 39 +++++++++++++++++++++++++++------------ src/tests.c | 2 +- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index 52d0476a30ffb..c96f7fb6e43ab 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -172,7 +172,7 @@ int main(int argc, char **argv) { secp256k1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); } } - secp256k1_ge_set_all_gej_var(data.pubkeys, pubkeys_gej, POINTS, &data.ctx->error_callback); + secp256k1_ge_set_all_gej_var(data.pubkeys, pubkeys_gej, POINTS); free(pubkeys_gej); for (i = 1; i <= 8; ++i) { diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 714f02e94c981..d64505dc00107 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -77,7 +77,7 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); } } - secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb); + secp256k1_ge_set_all_gej_var(prec, precj, 1024); } for (j = 0; j < 64; j++) { for (i = 0; i < 16; i++) { diff --git a/src/group.h b/src/group.h index 3947ea2ddafa3..0911df2cb51e6 100644 --- a/src/group.h +++ b/src/group.h @@ -65,7 +65,7 @@ static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); /** Set a batch of group elements equal to the inputs given in jacobian coordinates */ -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb); +static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len); /** Set a batch of group elements equal to the inputs given in jacobian * coordinates (with known z-ratios). zr must contain the known z-ratios such diff --git a/src/group_impl.h b/src/group_impl.h index b1ace87b6ffd0..006a4548876a5 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -126,30 +126,45 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { r->y = a->y; } -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) { - secp256k1_fe *az; - secp256k1_fe *azi; +static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { + secp256k1_fe u; size_t i; - size_t count = 0; - az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); + size_t last_i = SIZE_MAX; + for (i = 0; i < len; i++) { if (!a[i].infinity) { - az[count++] = a[i].z; + /* Use destination's x coordinates as scratch space */ + if (last_i == SIZE_MAX) { + r[i].x = a[i].z; + } else { + secp256k1_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); + } + last_i = i; } } + if (last_i == SIZE_MAX) { + return; + } + secp256k1_fe_inv_var(&u, &r[last_i].x); - azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); - secp256k1_fe_inv_all_var(azi, az, count); - free(az); + i = last_i; + while (i > 0) { + i--; + if (!a[i].infinity) { + secp256k1_fe_mul(&r[last_i].x, &r[i].x, &u); + secp256k1_fe_mul(&u, &u, &a[last_i].z); + last_i = i; + } + } + VERIFY_CHECK(!a[last_i].infinity); + r[last_i].x = u; - count = 0; for (i = 0; i < len; i++) { r[i].infinity = a[i].infinity; if (!a[i].infinity) { - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); } } - free(azi); } static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) { diff --git a/src/tests.c b/src/tests.c index c72a742d87f8d..589cf85e1844f 100644 --- a/src/tests.c +++ b/src/tests.c @@ -2104,7 +2104,7 @@ void test_ge(void) { } } secp256k1_ge_set_table_gej_var(ge_set_table, gej, zr, 4 * runs + 1); - secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1, &ctx->error_callback); + secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { secp256k1_fe s; random_fe_non_zero(&s);