Skip to content
12 changes: 6 additions & 6 deletions src/bench_ecmult.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,18 +366,18 @@ int main(int argc, char **argv) {
print_output_table_header_row();
/* Initialize offset1 and offset2 */
hash_into_offset(&data, 0);
run_ecmult_bench(&data, iters);
/* run_ecmult_bench(&data, iters); */

for (i = 1; i <= 8; ++i) {
run_ecmult_multi_bench(&data, i, 1, iters);
}
/* for (i = 1; i <= 8; ++i) { */
/* run_ecmult_multi_bench(&data, i, 1, iters); */
/* } */

/* This is disabled with low count of iterations because the loop runs 77 times even with iters=1
* and the higher it goes the longer the computation takes(more points)
* So we don't run this benchmark with low iterations to prevent slow down */
if (iters > 2) {
for (p = 0; p <= 11; ++p) {
for (i = 9; i <= 16; ++i) {
for (p = 3; p <= 11; p +=1) {
for (i = 10; i <= 16; i+=2) {
run_ecmult_multi_bench(&data, i << p, 1, iters);
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/bench_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ typedef struct {
secp256k1_fe fe[4];
secp256k1_ge ge[2];
secp256k1_gej gej[2];
secp256k1_geh geh[2];
unsigned char data[64];
int wnaf[256];
} bench_inv;
Expand Down Expand Up @@ -94,6 +95,8 @@ static void bench_setup(void* arg) {
secp256k1_gej_rescale(&data->gej[0], &data->fe[2]);
secp256k1_gej_set_ge(&data->gej[1], &data->ge[1]);
secp256k1_gej_rescale(&data->gej[1], &data->fe[3]);
secp256k1_geh_set_gej_var(&data->geh[0], &data->gej[0]);
secp256k1_geh_set_gej_var(&data->geh[1], &data->gej[1]);
memcpy(data->data, init[0], 32);
memcpy(data->data + 32, init[1], 32);
}
Expand Down Expand Up @@ -272,6 +275,26 @@ static void bench_group_double_var(void* arg, int iters) {
}
}

static void bench_group_doubleh(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;

for (i = 0; i < iters; i++) {
secp256k1_geh_double_var(&data->geh[0], &data->geh[0]);
}
}

static void bench_group_geh_gej_roundtrip(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;

for (i = 0; i < iters; i++) {
secp256k1_gej tmpj;
secp256k1_gej_set_geh_var(&tmpj, &data->geh[0]);
secp256k1_geh_set_gej_var(&data->geh[0], &tmpj);
}
}

static void bench_group_add_var(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
Expand All @@ -281,6 +304,15 @@ static void bench_group_add_var(void* arg, int iters) {
}
}

static void bench_group_addh(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;

for (i = 0; i < iters; i++) {
secp256k1_geh_add_var(&data->geh[0], &data->geh[0], &data->geh[1]);
}
}

static void bench_group_add_affine(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
Expand Down Expand Up @@ -419,7 +451,10 @@ int main(int argc, char **argv) {
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, iters);

if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_doubleh", bench_group_doubleh, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_rt", bench_group_geh_gej_roundtrip, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_addh", bench_group_addh, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, iters*10);
if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_zinv_var", bench_group_add_zinv_var, bench_setup, NULL, &data, 10, iters*10);
Expand Down
45 changes: 33 additions & 12 deletions src/ecmult_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,12 +497,13 @@ struct secp256k1_pippenger_state {
* to the point's wnaf[i]. Second, the buckets are added together such that
* r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ...
*/
static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, const secp256k1_scalar *sc, const secp256k1_ge *pt, size_t num) {
static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *rj, const secp256k1_scalar *sc, const secp256k1_ge *pt, size_t num) {
size_t n_wnaf = WNAF_SIZE(bucket_window+1);
size_t np;
size_t no = 0;
int i;
int j;
secp256k1_geh r;

for (np = 0; np < num; ++np) {
if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) {
Expand All @@ -512,14 +513,16 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi
state->ps[no].skew_na = secp256k1_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1);
no++;
}
secp256k1_gej_set_infinity(r);
secp256k1_geh_set_infinity(&r);

if (no == 0) {
/* FIXME value of rj */
return 1;
}

for (i = n_wnaf - 1; i >= 0; i--) {
secp256k1_gej running_sum;
secp256k1_geh running_sum;
secp256k1_geh tmph;

for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) {
secp256k1_gej_set_infinity(&buckets[j]);
Expand Down Expand Up @@ -549,11 +552,25 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi
}
}

for(j = 0; j < bucket_window; j++) {
secp256k1_gej_double_var(r, r, NULL);
/* TODO these tricks seem to make things slower in practice. */
/* if ((size_t)i != n_wnaf - 1) { /\* No reason to double infinity *\/ */
/* if (bucket_window >= 3) { /\* Switch to gej for many doublings *\/ */
{
secp256k1_gej rj_tmp;
secp256k1_gej_set_geh_var(&rj_tmp, &r);
for (j = 0; j < bucket_window; j++) {
secp256k1_gej_double_var(&rj_tmp, &rj_tmp, NULL);
}
secp256k1_geh_set_gej_var(&r, &rj_tmp);
}

secp256k1_gej_set_infinity(&running_sum);
/* } else { */
/* for (j = 0; j < bucket_window; j++) { */
/* secp256k1_geh_double_var(&r, &r); */
/* } */
/* } */
/* } */

secp256k1_geh_set_infinity(&running_sum);
/* Accumulate the sum: bucket[0] + 3*bucket[1] + 5*bucket[2] + 7*bucket[3] + ...
* = bucket[0] + bucket[1] + bucket[2] + bucket[3] + ...
* + 2 * (bucket[1] + 2*bucket[2] + 3*bucket[3] + ...)
Expand All @@ -563,14 +580,18 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi
* The doubling is done implicitly by deferring the final window doubling (of 'r').
*/
for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) {
secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL);
secp256k1_gej_add_var(r, r, &running_sum, NULL);
secp256k1_geh_set_gej_var(&tmph, &buckets[j]);
secp256k1_geh_add_var(&running_sum, &running_sum, &tmph);
secp256k1_geh_add_var(&r, &r, &running_sum);
}
secp256k1_geh_set_gej_var(&tmph, &buckets[0]);
secp256k1_geh_add_var(&running_sum, &running_sum, &tmph);

secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL);
secp256k1_gej_double_var(r, r, NULL);
secp256k1_gej_add_var(r, r, &running_sum, NULL);
secp256k1_geh_double_var(&r, &r);
secp256k1_geh_add_var(&r, &r, &running_sum);
}
/* TODO Return geh instead */
secp256k1_gej_set_geh_var(rj, &r);
return 1;
}

Expand Down
20 changes: 19 additions & 1 deletion src/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ typedef struct {
int infinity; /* whether this represents the point at infinity */
} secp256k1_gej;

/** A group element of the secp256k1 curve, in homogeneous coordinates.
* FIXME Note: For exhastive test mode, secp256k1 is replaced by a small subgroup of a different curve.
*/
typedef struct {
secp256k1_fe x; /* actual X: x/z */
secp256k1_fe y; /* actual Y: y/z */
secp256k1_fe z;
int infinity; /* whether this represents the point at infinity */
} secp256k1_geh;

#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0}
#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}

Expand All @@ -50,7 +60,11 @@ typedef struct {
#define SECP256K1_GE_Y_MAGNITUDE_MAX 3
#define SECP256K1_GEJ_X_MAGNITUDE_MAX 4
#define SECP256K1_GEJ_Y_MAGNITUDE_MAX 4
#define SECP256K1_GEJ_Z_MAGNITUDE_MAX 1
#define SECP256K1_GEJ_Z_MAGNITUDE_MAX 2 /* This would be 1 if it wasn't for secp256k1_gej_set_geh_var. */
/* FIXME Figure out reasonable values here: */
#define SECP256K1_GEH_X_MAGNITUDE_MAX 3
#define SECP256K1_GEH_Y_MAGNITUDE_MAX 4 /* This would be 2 if it wasn't for secp256k1_geh_set_gej_var. */
#define SECP256K1_GEH_Z_MAGNITUDE_MAX 2

/** Set a group element equal to the point with given X and Y coordinates */
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y);
Expand Down Expand Up @@ -213,4 +227,8 @@ static void secp256k1_ge_verify(const secp256k1_ge *a);
static void secp256k1_gej_verify(const secp256k1_gej *a);
#define SECP256K1_GEJ_VERIFY(a) secp256k1_gej_verify(a)

/** Check invariants on a homogeneous group element (no-op unless VERIFY is enabled). */
static void secp256k1_geh_verify(const secp256k1_geh *a);
#define SECP256K1_GEH_VERIFY(a) secp256k1_geh_verify(a)

#endif /* SECP256K1_GROUP_H */
Loading
Loading