Remove ecmult_context.

These tables stored in this context are now statically available from the generated ecmult_static_pre_g.h file.
This commit is contained in:
Russell O'Connor
2021-06-25 18:46:11 -04:00
parent f20dcbbad1
commit 6815761cf5
16 changed files with 177 additions and 424 deletions

View File

@@ -14,6 +14,7 @@
#include "group.h"
#include "scalar.h"
#include "ecmult.h"
#include "ecmult_static_pre_g.h"
#if defined(EXHAUSTIVE_TEST_ORDER)
/* We need to lower these values for exhaustive tests because
@@ -21,13 +22,10 @@
* affine-isomorphism stuff which tracks z-ratios) */
# if EXHAUSTIVE_TEST_ORDER > 128
# define WINDOW_A 5
# define WINDOW_G 8
# elif EXHAUSTIVE_TEST_ORDER > 8
# define WINDOW_A 4
# define WINDOW_G 4
# else
# define WINDOW_A 2
# define WINDOW_G 2
# endif
#else
/* optimal for 128-bit and 256-bit exponents. */
@@ -41,11 +39,6 @@
* Two tables of this size are used (due to the endomorphism
* optimization).
*/
# define WINDOW_G ECMULT_WINDOW_SIZE
#endif
#if ECMULT_WINDOW_SIZE < WINDOW_G
# error ECMULT_WINDOW_SIZE too small for WINDOW_G.
#endif
#define WNAF_BITS 128
@@ -105,18 +98,12 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, sec
/** Fill a table 'pre' with precomputed odd multiples of a.
*
* There are two versions of this function:
* - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its
* resulting point set to a single constant Z denominator, stores the X and Y
* coordinates as ge_storage points in pre, and stores the global Z in rz.
* It only operates on tables sized for WINDOW_A wnaf multiples.
* - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its
* resulting point set to actually affine points, and stores those in pre.
* It operates on tables of any size.
* The resulting point set is brought to a single constant Z denominator, stores the X and Y
* coordinates as ge_storage points in pre, and stores the global Z in rz.
* It only operates on tables sized for WINDOW_A wnaf multiples.
*
* To compute a*P + b*G, we compute a table for P using the first function,
* and for G using the second (which requires an inverse, but it only needs to
* happen once).
* To compute a*P + b*G, we compute a table for P using this function,
* and use the precomputed table in <ecmult_static_pre_g.h> for G.
*/
static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) {
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
@@ -128,137 +115,6 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *p
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr);
}
static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp256k1_ge_storage *pre, const secp256k1_gej *a) {
secp256k1_gej d;
secp256k1_ge d_ge, p_ge;
secp256k1_gej pj;
secp256k1_fe zi;
secp256k1_fe zr;
secp256k1_fe dx_over_dz_squared;
int i;
VERIFY_CHECK(!a->infinity);
secp256k1_gej_double_var(&d, a, NULL);
/* First, we perform all the additions in an isomorphic curve obtained by multiplying
* all `z` coordinates by 1/`d.z`. In these coordinates `d` is affine so we can use
* `secp256k1_gej_add_ge_var` to perform the additions. For each addition, we store
* the resulting y-coordinate and the z-ratio, since we only have enough memory to
* store two field elements. These are sufficient to efficiently undo the isomorphism
* and recompute all the `x`s.
*/
d_ge.x = d.x;
d_ge.y = d.y;
d_ge.infinity = 0;
secp256k1_ge_set_gej_zinv(&p_ge, a, &d.z);
pj.x = p_ge.x;
pj.y = p_ge.y;
pj.z = a->z;
pj.infinity = 0;
for (i = 0; i < (n - 1); i++) {
secp256k1_fe_normalize_var(&pj.y);
secp256k1_fe_to_storage(&pre[i].y, &pj.y);
secp256k1_gej_add_ge_var(&pj, &pj, &d_ge, &zr);
secp256k1_fe_normalize_var(&zr);
secp256k1_fe_to_storage(&pre[i].x, &zr);
}
/* Invert d.z in the same batch, preserving pj.z so we can extract 1/d.z */
secp256k1_fe_mul(&zi, &pj.z, &d.z);
secp256k1_fe_inv_var(&zi, &zi);
/* Directly set `pre[n - 1]` to `pj`, saving the inverted z-coordinate so
* that we can combine it with the saved z-ratios to compute the other zs
* without any more inversions. */
secp256k1_ge_set_gej_zinv(&p_ge, &pj, &zi);
secp256k1_ge_to_storage(&pre[n - 1], &p_ge);
/* Compute the actual x-coordinate of D, which will be needed below. */
secp256k1_fe_mul(&d.z, &zi, &pj.z); /* d.z = 1/d.z */
secp256k1_fe_sqr(&dx_over_dz_squared, &d.z);
secp256k1_fe_mul(&dx_over_dz_squared, &dx_over_dz_squared, &d.x);
/* Going into the second loop, we have set `pre[n-1]` to its final affine
* form, but still need to set `pre[i]` for `i` in 0 through `n-2`. We
* have `zi = (p.z * d.z)^-1`, where
*
* `p.z` is the z-coordinate of the point on the isomorphic curve
* which was ultimately assigned to `pre[n-1]`.
* `d.z` is the multiplier that must be applied to all z-coordinates
* to move from our isomorphic curve back to secp256k1; so the
* product `p.z * d.z` is the z-coordinate of the secp256k1
* point assigned to `pre[n-1]`.
*
* All subsequent inverse-z-coordinates can be obtained by multiplying this
* factor by successive z-ratios, which is much more efficient than directly
* computing each one.
*
* Importantly, these inverse-zs will be coordinates of points on secp256k1,
* while our other stored values come from computations on the isomorphic
* curve. So in the below loop, we will take care not to actually use `zi`
* or any derived values until we're back on secp256k1.
*/
i = n - 1;
while (i > 0) {
secp256k1_fe zi2, zi3;
const secp256k1_fe *rzr;
i--;
secp256k1_ge_from_storage(&p_ge, &pre[i]);
/* For each remaining point, we extract the z-ratio from the stored
* x-coordinate, compute its z^-1 from that, and compute the full
* point from that. */
rzr = &p_ge.x;
secp256k1_fe_mul(&zi, &zi, rzr);
secp256k1_fe_sqr(&zi2, &zi);
secp256k1_fe_mul(&zi3, &zi2, &zi);
/* To compute the actual x-coordinate, we use the stored z ratio and
* y-coordinate, which we obtained from `secp256k1_gej_add_ge_var`
* in the loop above, as well as the inverse of the square of its
* z-coordinate. We store the latter in the `zi2` variable, which is
* computed iteratively starting from the overall Z inverse then
* multiplying by each z-ratio in turn.
*
* Denoting the z-ratio as `rzr`, we observe that it is equal to `h`
* from the inside of the above `gej_add_ge_var` call. This satisfies
*
* rzr = d_x * z^2 - x * d_z^2
*
* where (`d_x`, `d_z`) are Jacobian coordinates of `D` and `(x, z)`
* are Jacobian coordinates of our desired point -- except both are on
* the isomorphic curve that we were using when we called `gej_add_ge_var`.
* To get back to secp256k1, we must multiply both `z`s by `d_z`, or
* equivalently divide both `x`s by `d_z^2`. Our equation then becomes
*
* rzr = d_x * z^2 / d_z^2 - x
*
* (The left-hand-side, being a ratio of z-coordinates, is unaffected
* by the isomorphism.)
*
* Rearranging to solve for `x`, we have
*
* x = d_x * z^2 / d_z^2 - rzr
*
* But what we actually want is the affine coordinate `X = x/z^2`,
* which will satisfy
*
* X = d_x / d_z^2 - rzr / z^2
* = dx_over_dz_squared - rzr * zi2
*/
secp256k1_fe_mul(&p_ge.x, rzr, &zi2);
secp256k1_fe_negate(&p_ge.x, &p_ge.x, 1);
secp256k1_fe_add(&p_ge.x, &dx_over_dz_squared);
/* y is stored_y/z^3, as we expect */
secp256k1_fe_mul(&p_ge.y, &p_ge.y, &zi3);
/* Store */
secp256k1_ge_to_storage(&pre[i], &p_ge);
}
}
/** The following two macro retrieves a particular odd multiple from a table
* of precomputed multiples. */
#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \
@@ -285,74 +141,6 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp25
} \
} while(0)
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE =
ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
+ ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
;
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
ctx->pre_g = NULL;
ctx->pre_g_128 = NULL;
}
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) {
secp256k1_gej gj;
void* const base = *prealloc;
size_t const prealloc_size = SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
if (ctx->pre_g != NULL) {
return;
}
/* get the generator */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
{
size_t size = sizeof((*ctx->pre_g)[0]) * ((size_t)ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
}
/* precompute the tables with odd multiples */
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
{
secp256k1_gej g_128j;
int i;
size_t size = sizeof((*ctx->pre_g_128)[0]) * ((size_t) ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g_128)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
/* calculate 2^128*generator */
g_128j = gj;
for (i = 0; i < 128; i++) {
secp256k1_gej_double_var(&g_128j, &g_128j, NULL);
}
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j);
}
}
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) {
if (src->pre_g != NULL) {
/* We cast to void* first to suppress a -Wcast-align warning. */
dst->pre_g = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src));
}
if (src->pre_g_128 != NULL) {
dst->pre_g_128 = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src));
}
}
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) {
return ctx->pre_g != NULL;
}
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
secp256k1_ecmult_context_init(ctx);
}
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
* with the following guarantees:
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
@@ -429,7 +217,7 @@ struct secp256k1_strauss_state {
struct secp256k1_strauss_point_state* ps;
};
static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_ge tmpa;
secp256k1_fe Z;
/* Splitted G factors. */
@@ -530,11 +318,11 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
}
}
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
}
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G);
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g_128, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
}
}
@@ -544,7 +332,7 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
}
}
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
@@ -557,7 +345,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
state.pre_a = pre_a;
state.pre_a_lam = pre_a_lam;
state.ps = ps;
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng);
secp256k1_ecmult_strauss_wnaf(&state, r, 1, a, na, ng);
}
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
@@ -565,7 +353,7 @@ static size_t secp256k1_strauss_scratch_size(size_t n_points) {
return n_points*point_size;
}
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
secp256k1_gej* points;
secp256k1_scalar* scalars;
struct secp256k1_strauss_state state;
@@ -598,14 +386,14 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
}
secp256k1_gej_set_ge(&points[i], &point);
}
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc);
secp256k1_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc);
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
return 1;
}
/* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_strauss_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_strauss_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
}
static size_t secp256k1_strauss_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) {
@@ -852,7 +640,7 @@ static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_windo
return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size;
}
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
/* Use 2(n+1) with the endomorphism, when calculating batch
* sizes. The reason for +1 is that we add the G scalar to the list of
@@ -867,7 +655,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
int i, j;
int bucket_window;
(void)ctx;
secp256k1_gej_set_infinity(r);
if (inp_g_sc == NULL && n_points == 0) {
return 1;
@@ -927,8 +714,8 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
}
/* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_pippenger_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_pippenger_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
}
/**
@@ -972,7 +759,7 @@ static size_t secp256k1_pippenger_max_points(const secp256k1_callback* error_cal
/* Computes ecmult_multi by simply multiplying and adding each point. Does not
* require a scratch space */
static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) {
static int secp256k1_ecmult_multi_simple_var(secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) {
size_t point_idx;
secp256k1_scalar szero;
secp256k1_gej tmpj;
@@ -981,7 +768,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
secp256k1_gej_set_infinity(r);
secp256k1_gej_set_infinity(&tmpj);
/* r = inp_g_sc*G */
secp256k1_ecmult(ctx, r, &tmpj, &szero, inp_g_sc);
secp256k1_ecmult(r, &tmpj, &szero, inp_g_sc);
for (point_idx = 0; point_idx < n_points; point_idx++) {
secp256k1_ge point;
secp256k1_gej pointj;
@@ -991,7 +778,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
}
/* r += scalar*point */
secp256k1_gej_set_ge(&pointj, &point);
secp256k1_ecmult(ctx, &tmpj, &pointj, &scalar, NULL);
secp256k1_ecmult(&tmpj, &pointj, &scalar, NULL);
secp256k1_gej_add_var(r, r, &tmpj, NULL);
}
return 1;
@@ -1017,11 +804,11 @@ static int secp256k1_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n
return 1;
}
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
size_t i;
int (*f)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
int (*f)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
size_t n_batches;
size_t n_batch_points;
@@ -1031,11 +818,11 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
} else if (n == 0) {
secp256k1_scalar szero;
secp256k1_scalar_set_int(&szero, 0);
secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc);
secp256k1_ecmult(r, r, &szero, inp_g_sc);
return 1;
}
if (scratch == NULL) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
}
/* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than
@@ -1043,13 +830,13 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
* As a first step check if there's enough space for Pippenger's algo (which requires less space
* than Strauss' algo) and if not, use the simple algorithm. */
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(error_callback, scratch), n)) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
}
if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) {
f = secp256k1_ecmult_pippenger_batch;
} else {
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(error_callback, scratch), n)) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n);
return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
}
f = secp256k1_ecmult_strauss_batch;
}
@@ -1057,7 +844,7 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
size_t nbp = n < n_batch_points ? n : n_batch_points;
size_t offset = n_batch_points*i;
secp256k1_gej tmp;
if (!f(error_callback, ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
if (!f(error_callback, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
return 0;
}
secp256k1_gej_add_var(r, r, &tmp, NULL);