Skip to content

Commit 486205a

Browse files
Merge #920: Test all ecmult functions with many j*2^i combinations
5eb519e ci: reduce TEST_ITERS in memcheck run (Pieter Wuille) e2cf773 Test ecmult functions for all i*2^j for j=0..255 and odd i=1..255. (Pieter Wuille) Pull request description: Instead of just testing properties of the points xG for x=-36..36: * also compute all xG where x=j*2^i for i=0..255 and odd j=1..255. * test them against known exact results (SHA256 all of them, and compared against an independently created result) * test all 4 ecmult functions (and for secp256k1_ecmult and secp256k1_ecmult_multi_var, both as G, and through the generic point input) ACKs for top commit: real-or-random: ACK 5eb519e jonasnick: ACK 5eb519e Tree-SHA512: 5d3fcbff754e859ba27d4f4581fa91fafb450fa3f7880364667dba51287e7f02f489af19b9de6a6e0f52faa183c0c7ae46db6add05180c3d4f45a6557b00c0ed
2 parents 61ae37c + 5eb519e commit 486205a

File tree

2 files changed

+78
-26
lines changed

2 files changed

+78
-26
lines changed

.cirrus.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ task:
290290
env:
291291
# The `--error-exitcode` is required to make the test fail if valgrind found errors, otherwise it'll return 0 (https://www.valgrind.org/docs/manual/manual-core.html)
292292
WRAPPER_CMD: "valgrind --error-exitcode=42"
293-
SECP256K1_TEST_ITERS: 16
293+
SECP256K1_TEST_ITERS: 2
294294
- name: "UBSan, ASan, LSan"
295295
env:
296296
CFLAGS: "-fsanitize=undefined,address -g"

src/tests.c

+77-25
Original file line numberDiff line numberDiff line change
@@ -4489,37 +4489,89 @@ void run_wnaf(void) {
44894489
CHECK(secp256k1_scalar_is_zero(&n));
44904490
}
44914491

4492+
static int test_ecmult_accumulate_cb(secp256k1_scalar* sc, secp256k1_ge* pt, size_t idx, void* data) {
4493+
const secp256k1_scalar* indata = (const secp256k1_scalar*)data;
4494+
*sc = *indata;
4495+
*pt = secp256k1_ge_const_g;
4496+
CHECK(idx == 0);
4497+
return 1;
4498+
}
4499+
4500+
void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar* x, secp256k1_scratch* scratch) {
4501+
/* Compute x*G in 6 different ways, serialize it uncompressed, and feed it into acc. */
4502+
secp256k1_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj;
4503+
secp256k1_ge r;
4504+
const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
4505+
unsigned char bytes[65];
4506+
size_t size = 65;
4507+
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
4508+
secp256k1_gej_set_infinity(&infj);
4509+
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj1, x);
4510+
secp256k1_ecmult(&rj2, &gj, x, &zero);
4511+
secp256k1_ecmult(&rj3, &infj, &zero, x);
4512+
secp256k1_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0);
4513+
secp256k1_ecmult_multi_var(NULL, scratch, &rj5, &zero, test_ecmult_accumulate_cb, (void*)x, 1);
4514+
secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x, 256);
4515+
secp256k1_ge_set_gej_var(&r, &rj1);
4516+
ge_equals_gej(&r, &rj2);
4517+
ge_equals_gej(&r, &rj3);
4518+
ge_equals_gej(&r, &rj4);
4519+
ge_equals_gej(&r, &rj5);
4520+
ge_equals_gej(&r, &rj6);
4521+
if (secp256k1_ge_is_infinity(&r)) {
4522+
/* Store infinity as 0x00 */
4523+
const unsigned char zerobyte[1] = {0};
4524+
secp256k1_sha256_write(acc, zerobyte, 1);
4525+
} else {
4526+
/* Store other points using their uncompressed serialization. */
4527+
secp256k1_eckey_pubkey_serialize(&r, bytes, &size, 0);
4528+
CHECK(size == 65);
4529+
secp256k1_sha256_write(acc, bytes, size);
4530+
}
4531+
}
4532+
44924533
void test_ecmult_constants(void) {
4493-
/* Test ecmult_gen() for [0..36) and [order-36..0). */
4534+
/* Test ecmult_gen for:
4535+
* - For i in 0..36:
4536+
* - Key i
4537+
* - Key -i
4538+
* - For i in 0..255:
4539+
* - For j in 1..255 (only odd values):
4540+
* - Key (j*2^i) mod order
4541+
*/
44944542
secp256k1_scalar x;
4495-
secp256k1_gej r;
4496-
secp256k1_ge ng;
4497-
int i;
4498-
int j;
4499-
secp256k1_ge_neg(&ng, &secp256k1_ge_const_g);
4500-
for (i = 0; i < 36; i++ ) {
4501-
secp256k1_scalar_set_int(&x, i);
4502-
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x);
4503-
for (j = 0; j < i; j++) {
4504-
if (j == i - 1) {
4505-
ge_equals_gej(&secp256k1_ge_const_g, &r);
4506-
}
4507-
secp256k1_gej_add_ge(&r, &r, &ng);
4508-
}
4509-
CHECK(secp256k1_gej_is_infinity(&r));
4510-
}
4511-
for (i = 1; i <= 36; i++ ) {
4543+
secp256k1_sha256 acc;
4544+
unsigned char b32[32];
4545+
int i, j;
4546+
secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(ctx, 65536);
4547+
4548+
/* Expected hash of all the computed points; created with an independent
4549+
* implementation. */
4550+
static const unsigned char expected32[32] = {
4551+
0xe4, 0x71, 0x1b, 0x4d, 0x14, 0x1e, 0x68, 0x48,
4552+
0xb7, 0xaf, 0x47, 0x2b, 0x4c, 0xd2, 0x04, 0x14,
4553+
0x3a, 0x75, 0x87, 0x60, 0x1a, 0xf9, 0x63, 0x60,
4554+
0xd0, 0xcb, 0x1f, 0xaa, 0x85, 0x9a, 0xb7, 0xb4
4555+
};
4556+
secp256k1_sha256_initialize(&acc);
4557+
for (i = 0; i <= 36; ++i) {
45124558
secp256k1_scalar_set_int(&x, i);
4559+
test_ecmult_accumulate(&acc, &x, scratch);
45134560
secp256k1_scalar_negate(&x, &x);
4514-
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x);
4515-
for (j = 0; j < i; j++) {
4516-
if (j == i - 1) {
4517-
ge_equals_gej(&ng, &r);
4518-
}
4519-
secp256k1_gej_add_ge(&r, &r, &secp256k1_ge_const_g);
4561+
test_ecmult_accumulate(&acc, &x, scratch);
4562+
};
4563+
for (i = 0; i < 256; ++i) {
4564+
for (j = 1; j < 256; j += 2) {
4565+
int k;
4566+
secp256k1_scalar_set_int(&x, j);
4567+
for (k = 0; k < i; ++k) secp256k1_scalar_add(&x, &x, &x);
4568+
test_ecmult_accumulate(&acc, &x, scratch);
45204569
}
4521-
CHECK(secp256k1_gej_is_infinity(&r));
45224570
}
4571+
secp256k1_sha256_finalize(&acc, b32);
4572+
CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0);
4573+
4574+
secp256k1_scratch_space_destroy(ctx, scratch);
45234575
}
45244576

45254577
void run_ecmult_constants(void) {

0 commit comments

Comments
 (0)