Skip to content

Commit dba5471

Browse files
apoelstrajonasnick
authored andcommitted
Add ecmult_multi tests
1 parent 8c1c831 commit dba5471

File tree

2 files changed

+279
-0
lines changed

2 files changed

+279
-0
lines changed

src/tests.c

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,6 +2522,243 @@ void run_ecmult_const_tests(void) {
25222522
ecmult_const_chain_multiply();
25232523
}
25242524

2525+
typedef struct {
2526+
secp256k1_scalar *sc;
2527+
secp256k1_ge *pt;
2528+
} ecmult_multi_data;
2529+
2530+
static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
2531+
ecmult_multi_data *data = (ecmult_multi_data*) cbdata;
2532+
*sc = data->sc[idx];
2533+
*pt = data->pt[idx];
2534+
return 1;
2535+
}
2536+
2537+
void run_ecmult_multi_tests(void) {
2538+
int ncount;
2539+
secp256k1_scalar szero;
2540+
secp256k1_scalar sc[32];
2541+
secp256k1_ge pt[32];
2542+
secp256k1_gej r;
2543+
secp256k1_gej r2;
2544+
ecmult_multi_data data;
2545+
secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 1024, 8192);
2546+
2547+
data.sc = sc;
2548+
data.pt = pt;
2549+
2550+
secp256k1_scalar_set_int(&szero, 0);
2551+
2552+
/* Check 1- and 2-point multiplies against ecmult */
2553+
for (ncount = 0; ncount < count; ncount++) {
2554+
secp256k1_ge ptg;
2555+
secp256k1_gej ptgj;
2556+
random_scalar_order(&sc[0]);
2557+
random_scalar_order(&sc[1]);
2558+
2559+
random_group_element_test(&ptg);
2560+
secp256k1_gej_set_ge(&ptgj, &ptg);
2561+
pt[0] = ptg;
2562+
pt[1] = secp256k1_ge_const_g;
2563+
2564+
/* 1-point */
2565+
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero);
2566+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
2567+
secp256k1_gej_neg(&r2, &r2);
2568+
secp256k1_gej_add_var(&r, &r, &r2, NULL);
2569+
CHECK(secp256k1_gej_is_infinity(&r));
2570+
2571+
/* 2-point */
2572+
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
2573+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
2574+
secp256k1_gej_neg(&r2, &r2);
2575+
secp256k1_gej_add_var(&r, &r, &r2, NULL);
2576+
CHECK(secp256k1_gej_is_infinity(&r));
2577+
2578+
/* 2-point with G scalar */
2579+
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
2580+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
2581+
secp256k1_gej_neg(&r2, &r2);
2582+
secp256k1_gej_add_var(&r, &r, &r2, NULL);
2583+
CHECK(secp256k1_gej_is_infinity(&r));
2584+
}
2585+
2586+
/* Check infinite outputs of various forms */
2587+
for (ncount = 0; ncount < count; ncount++) {
2588+
secp256k1_ge ptg;
2589+
size_t i, j;
2590+
size_t sizes[] = { 2, 10, 32 };
2591+
2592+
for (j = 0; j < 3; j++) {
2593+
for (i = 0; i < 32; i++) {
2594+
random_scalar_order(&sc[i]);
2595+
secp256k1_ge_set_infinity(&pt[i]);
2596+
}
2597+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
2598+
CHECK(secp256k1_gej_is_infinity(&r));
2599+
}
2600+
2601+
for (j = 0; j < 3; j++) {
2602+
for (i = 0; i < 32; i++) {
2603+
random_group_element_test(&ptg);
2604+
pt[i] = ptg;
2605+
secp256k1_scalar_set_int(&sc[i], 0);
2606+
}
2607+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
2608+
CHECK(secp256k1_gej_is_infinity(&r));
2609+
}
2610+
2611+
for (j = 0; j < 3; j++) {
2612+
random_group_element_test(&ptg);
2613+
for (i = 0; i < 16; i++) {
2614+
random_scalar_order(&sc[2*i]);
2615+
secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]);
2616+
pt[2 * i] = ptg;
2617+
pt[2 * i + 1] = ptg;
2618+
}
2619+
2620+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
2621+
CHECK(secp256k1_gej_is_infinity(&r));
2622+
2623+
random_scalar_order(&sc[0]);
2624+
for (i = 0; i < 16; i++) {
2625+
random_group_element_test(&ptg);
2626+
2627+
sc[2*i] = sc[0];
2628+
sc[2*i+1] = sc[0];
2629+
pt[2 * i] = ptg;
2630+
secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]);
2631+
}
2632+
2633+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
2634+
CHECK(secp256k1_gej_is_infinity(&r));
2635+
}
2636+
2637+
random_group_element_test(&ptg);
2638+
secp256k1_scalar_set_int(&sc[0], 0);
2639+
pt[0] = ptg;
2640+
for (i = 1; i < 32; i++) {
2641+
pt[i] = ptg;
2642+
2643+
random_scalar_order(&sc[i]);
2644+
secp256k1_scalar_add(&sc[0], &sc[0], &sc[i]);
2645+
secp256k1_scalar_negate(&sc[i], &sc[i]);
2646+
}
2647+
2648+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
2649+
CHECK(secp256k1_gej_is_infinity(&r));
2650+
}
2651+
2652+
/* Check random points, constant scalar */
2653+
for (ncount = 0; ncount < count; ncount++) {
2654+
size_t i;
2655+
secp256k1_gej_set_infinity(&r);
2656+
2657+
random_scalar_order(&sc[0]);
2658+
for (i = 0; i < 20; i++) {
2659+
secp256k1_ge ptg;
2660+
sc[i] = sc[0];
2661+
random_group_element_test(&ptg);
2662+
pt[i] = ptg;
2663+
secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL);
2664+
}
2665+
2666+
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero);
2667+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
2668+
secp256k1_gej_neg(&r2, &r2);
2669+
secp256k1_gej_add_var(&r, &r, &r2, NULL);
2670+
CHECK(secp256k1_gej_is_infinity(&r));
2671+
}
2672+
2673+
/* Check random scalars, constant point */
2674+
for (ncount = 0; ncount < count; ncount++) {
2675+
size_t i;
2676+
secp256k1_ge ptg;
2677+
secp256k1_gej p0j;
2678+
secp256k1_scalar rs;
2679+
secp256k1_scalar_set_int(&rs, 0);
2680+
2681+
random_group_element_test(&ptg);
2682+
for (i = 0; i < 20; i++) {
2683+
random_scalar_order(&sc[i]);
2684+
pt[i] = ptg;
2685+
secp256k1_scalar_add(&rs, &rs, &sc[i]);
2686+
}
2687+
2688+
secp256k1_gej_set_ge(&p0j, &pt[0]);
2689+
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero);
2690+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
2691+
secp256k1_gej_neg(&r2, &r2);
2692+
secp256k1_gej_add_var(&r, &r, &r2, NULL);
2693+
CHECK(secp256k1_gej_is_infinity(&r));
2694+
}
2695+
2696+
/* Sanity check that zero scalars don't cause problems */
2697+
secp256k1_scalar_clear(&sc[0]);
2698+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
2699+
secp256k1_scalar_clear(&sc[1]);
2700+
secp256k1_scalar_clear(&sc[2]);
2701+
secp256k1_scalar_clear(&sc[3]);
2702+
secp256k1_scalar_clear(&sc[4]);
2703+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
2704+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
2705+
CHECK(secp256k1_gej_is_infinity(&r));
2706+
2707+
/* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */
2708+
{
2709+
const size_t TOP = 8;
2710+
size_t s0i, s1i;
2711+
size_t t0i, t1i;
2712+
secp256k1_ge ptg;
2713+
secp256k1_gej ptgj;
2714+
2715+
random_group_element_test(&ptg);
2716+
secp256k1_gej_set_ge(&ptgj, &ptg);
2717+
2718+
for(t0i = 0; t0i < TOP; t0i++) {
2719+
for(t1i = 0; t1i < TOP; t1i++) {
2720+
secp256k1_gej t0p, t1p;
2721+
secp256k1_scalar t0, t1;
2722+
2723+
secp256k1_scalar_set_int(&t0, (t0i + 1) / 2);
2724+
secp256k1_scalar_cond_negate(&t0, t0i & 1);
2725+
secp256k1_scalar_set_int(&t1, (t1i + 1) / 2);
2726+
secp256k1_scalar_cond_negate(&t1, t1i & 1);
2727+
2728+
secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero);
2729+
secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero);
2730+
2731+
for(s0i = 0; s0i < TOP; s0i++) {
2732+
for(s1i = 0; s1i < TOP; s1i++) {
2733+
secp256k1_scalar tmp1, tmp2;
2734+
secp256k1_gej expected, actual;
2735+
2736+
secp256k1_ge_set_gej(&pt[0], &t0p);
2737+
secp256k1_ge_set_gej(&pt[1], &t1p);
2738+
2739+
secp256k1_scalar_set_int(&sc[0], (s0i + 1) / 2);
2740+
secp256k1_scalar_cond_negate(&sc[0], s0i & 1);
2741+
secp256k1_scalar_set_int(&sc[1], (s1i + 1) / 2);
2742+
secp256k1_scalar_cond_negate(&sc[1], s1i & 1);
2743+
2744+
secp256k1_scalar_mul(&tmp1, &t0, &sc[0]);
2745+
secp256k1_scalar_mul(&tmp2, &t1, &sc[1]);
2746+
secp256k1_scalar_add(&tmp1, &tmp1, &tmp2);
2747+
2748+
secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero);
2749+
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
2750+
secp256k1_gej_neg(&expected, &expected);
2751+
secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
2752+
CHECK(secp256k1_gej_is_infinity(&actual));
2753+
}
2754+
}
2755+
}
2756+
}
2757+
}
2758+
2759+
secp256k1_scratch_destroy(scratch);
2760+
}
2761+
25252762
void test_wnaf(const secp256k1_scalar *number, int w) {
25262763
secp256k1_scalar x, two, t;
25272764
int wnaf[256];
@@ -4528,6 +4765,7 @@ int main(int argc, char **argv) {
45284765
run_ecmult_constants();
45294766
run_ecmult_gen_blind();
45304767
run_ecmult_const_tests();
4768+
run_ecmult_multi_tests();
45314769
run_ec_combine();
45324770

45334771
/* endomorphism tests */

src/tests_exhaustive.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,46 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr
182182
}
183183
}
184184

185+
typedef struct {
186+
secp256k1_scalar sc[2];
187+
secp256k1_ge pt[2];
188+
} ecmult_multi_data;
189+
190+
static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
191+
ecmult_multi_data *data = (ecmult_multi_data*) cbdata;
192+
*sc = data->sc[idx];
193+
*pt = data->pt[idx];
194+
return 1;
195+
}
196+
197+
void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
198+
int i, j, k, x, y;
199+
secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 1024, 4096);
200+
for (i = 0; i < order; i++) {
201+
for (j = 0; j < order; j++) {
202+
for (k = 0; k < order; k++) {
203+
for (x = 0; x < order; x++) {
204+
for (y = 0; y < order; y++) {
205+
secp256k1_gej tmp;
206+
secp256k1_scalar g_sc;
207+
ecmult_multi_data data;
208+
209+
secp256k1_scalar_set_int(&data.sc[0], i);
210+
secp256k1_scalar_set_int(&data.sc[1], j);
211+
secp256k1_scalar_set_int(&g_sc, k);
212+
data.pt[0] = group[x];
213+
data.pt[1] = group[y];
214+
215+
secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
216+
ge_equals_gej(&group[(i * x + j * y + k) % order], &tmp);
217+
}
218+
}
219+
}
220+
}
221+
}
222+
secp256k1_scratch_destroy(scratch);
223+
}
224+
185225
void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) {
186226
secp256k1_fe x;
187227
unsigned char x_bin[32];
@@ -456,6 +496,7 @@ int main(void) {
456496
#endif
457497
test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER);
458498
test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER);
499+
test_exhaustive_ecmult_multi(ctx, group, EXHAUSTIVE_TEST_ORDER);
459500
test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
460501
test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER);
461502

0 commit comments

Comments
 (0)