Add ecmult_multi tests

This commit is contained in:
Andrew Poelstra 2017-08-16 14:45:48 -07:00 committed by Jonas Nick
parent 8c1c831bdb
commit dba5471b69
2 changed files with 279 additions and 0 deletions

View File

@ -2522,6 +2522,243 @@ void run_ecmult_const_tests(void) {
ecmult_const_chain_multiply(); ecmult_const_chain_multiply();
} }
typedef struct {
secp256k1_scalar *sc;
secp256k1_ge *pt;
} ecmult_multi_data;
static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
ecmult_multi_data *data = (ecmult_multi_data*) cbdata;
*sc = data->sc[idx];
*pt = data->pt[idx];
return 1;
}
void run_ecmult_multi_tests(void) {
int ncount;
secp256k1_scalar szero;
secp256k1_scalar sc[32];
secp256k1_ge pt[32];
secp256k1_gej r;
secp256k1_gej r2;
ecmult_multi_data data;
secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 1024, 8192);
data.sc = sc;
data.pt = pt;
secp256k1_scalar_set_int(&szero, 0);
/* Check 1- and 2-point multiplies against ecmult */
for (ncount = 0; ncount < count; ncount++) {
secp256k1_ge ptg;
secp256k1_gej ptgj;
random_scalar_order(&sc[0]);
random_scalar_order(&sc[1]);
random_group_element_test(&ptg);
secp256k1_gej_set_ge(&ptgj, &ptg);
pt[0] = ptg;
pt[1] = secp256k1_ge_const_g;
/* 1-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* 2-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* 2-point with G scalar */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Check infinite outputs of various forms */
for (ncount = 0; ncount < count; ncount++) {
secp256k1_ge ptg;
size_t i, j;
size_t sizes[] = { 2, 10, 32 };
for (j = 0; j < 3; j++) {
for (i = 0; i < 32; i++) {
random_scalar_order(&sc[i]);
secp256k1_ge_set_infinity(&pt[i]);
}
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
for (j = 0; j < 3; j++) {
for (i = 0; i < 32; i++) {
random_group_element_test(&ptg);
pt[i] = ptg;
secp256k1_scalar_set_int(&sc[i], 0);
}
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
for (j = 0; j < 3; j++) {
random_group_element_test(&ptg);
for (i = 0; i < 16; i++) {
random_scalar_order(&sc[2*i]);
secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]);
pt[2 * i] = ptg;
pt[2 * i + 1] = ptg;
}
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
random_scalar_order(&sc[0]);
for (i = 0; i < 16; i++) {
random_group_element_test(&ptg);
sc[2*i] = sc[0];
sc[2*i+1] = sc[0];
pt[2 * i] = ptg;
secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]);
}
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
random_group_element_test(&ptg);
secp256k1_scalar_set_int(&sc[0], 0);
pt[0] = ptg;
for (i = 1; i < 32; i++) {
pt[i] = ptg;
random_scalar_order(&sc[i]);
secp256k1_scalar_add(&sc[0], &sc[0], &sc[i]);
secp256k1_scalar_negate(&sc[i], &sc[i]);
}
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Check random points, constant scalar */
for (ncount = 0; ncount < count; ncount++) {
size_t i;
secp256k1_gej_set_infinity(&r);
random_scalar_order(&sc[0]);
for (i = 0; i < 20; i++) {
secp256k1_ge ptg;
sc[i] = sc[0];
random_group_element_test(&ptg);
pt[i] = ptg;
secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL);
}
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Check random scalars, constant point */
for (ncount = 0; ncount < count; ncount++) {
size_t i;
secp256k1_ge ptg;
secp256k1_gej p0j;
secp256k1_scalar rs;
secp256k1_scalar_set_int(&rs, 0);
random_group_element_test(&ptg);
for (i = 0; i < 20; i++) {
random_scalar_order(&sc[i]);
pt[i] = ptg;
secp256k1_scalar_add(&rs, &rs, &sc[i]);
}
secp256k1_gej_set_ge(&p0j, &pt[0]);
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Sanity check that zero scalars don't cause problems */
secp256k1_scalar_clear(&sc[0]);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_scalar_clear(&sc[1]);
secp256k1_scalar_clear(&sc[2]);
secp256k1_scalar_clear(&sc[3]);
secp256k1_scalar_clear(&sc[4]);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
CHECK(secp256k1_gej_is_infinity(&r));
/* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */
{
const size_t TOP = 8;
size_t s0i, s1i;
size_t t0i, t1i;
secp256k1_ge ptg;
secp256k1_gej ptgj;
random_group_element_test(&ptg);
secp256k1_gej_set_ge(&ptgj, &ptg);
for(t0i = 0; t0i < TOP; t0i++) {
for(t1i = 0; t1i < TOP; t1i++) {
secp256k1_gej t0p, t1p;
secp256k1_scalar t0, t1;
secp256k1_scalar_set_int(&t0, (t0i + 1) / 2);
secp256k1_scalar_cond_negate(&t0, t0i & 1);
secp256k1_scalar_set_int(&t1, (t1i + 1) / 2);
secp256k1_scalar_cond_negate(&t1, t1i & 1);
secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero);
secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero);
for(s0i = 0; s0i < TOP; s0i++) {
for(s1i = 0; s1i < TOP; s1i++) {
secp256k1_scalar tmp1, tmp2;
secp256k1_gej expected, actual;
secp256k1_ge_set_gej(&pt[0], &t0p);
secp256k1_ge_set_gej(&pt[1], &t1p);
secp256k1_scalar_set_int(&sc[0], (s0i + 1) / 2);
secp256k1_scalar_cond_negate(&sc[0], s0i & 1);
secp256k1_scalar_set_int(&sc[1], (s1i + 1) / 2);
secp256k1_scalar_cond_negate(&sc[1], s1i & 1);
secp256k1_scalar_mul(&tmp1, &t0, &sc[0]);
secp256k1_scalar_mul(&tmp2, &t1, &sc[1]);
secp256k1_scalar_add(&tmp1, &tmp1, &tmp2);
secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero);
CHECK(secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&expected, &expected);
secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
CHECK(secp256k1_gej_is_infinity(&actual));
}
}
}
}
}
secp256k1_scratch_destroy(scratch);
}
void test_wnaf(const secp256k1_scalar *number, int w) { void test_wnaf(const secp256k1_scalar *number, int w) {
secp256k1_scalar x, two, t; secp256k1_scalar x, two, t;
int wnaf[256]; int wnaf[256];
@ -4528,6 +4765,7 @@ int main(int argc, char **argv) {
run_ecmult_constants(); run_ecmult_constants();
run_ecmult_gen_blind(); run_ecmult_gen_blind();
run_ecmult_const_tests(); run_ecmult_const_tests();
run_ecmult_multi_tests();
run_ec_combine(); run_ec_combine();
/* endomorphism tests */ /* endomorphism tests */

View File

@ -182,6 +182,46 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr
} }
} }
typedef struct {
secp256k1_scalar sc[2];
secp256k1_ge pt[2];
} ecmult_multi_data;
static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
ecmult_multi_data *data = (ecmult_multi_data*) cbdata;
*sc = data->sc[idx];
*pt = data->pt[idx];
return 1;
}
void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
int i, j, k, x, y;
secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 1024, 4096);
for (i = 0; i < order; i++) {
for (j = 0; j < order; j++) {
for (k = 0; k < order; k++) {
for (x = 0; x < order; x++) {
for (y = 0; y < order; y++) {
secp256k1_gej tmp;
secp256k1_scalar g_sc;
ecmult_multi_data data;
secp256k1_scalar_set_int(&data.sc[0], i);
secp256k1_scalar_set_int(&data.sc[1], j);
secp256k1_scalar_set_int(&g_sc, k);
data.pt[0] = group[x];
data.pt[1] = group[y];
secp256k1_ecmult_multi(&ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
ge_equals_gej(&group[(i * x + j * y + k) % order], &tmp);
}
}
}
}
}
secp256k1_scratch_destroy(scratch);
}
void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) {
secp256k1_fe x; secp256k1_fe x;
unsigned char x_bin[32]; unsigned char x_bin[32];
@ -456,6 +496,7 @@ int main(void) {
#endif #endif
test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_ecmult_multi(ctx, group, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER);