Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster fixed-input ecmult tests #1049

Merged
merged 1 commit into from
Jan 24, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 78 additions & 3 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "modinv64_impl.h"
#endif

#define CONDITIONAL_TEST(cnt, nam) if (count < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else

static int count = 64;
static secp256k1_context *ctx = NULL;

Expand Down Expand Up @@ -4712,8 +4714,8 @@ void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar* x, se
}
}

void test_ecmult_constants(void) {
/* Test ecmult_gen for:
void test_ecmult_constants_2bit(void) {
/* Using test_ecmult_accumulate, test ecmult for:
* - For i in 0..36:
* - Key i
* - Key -i
Expand Down Expand Up @@ -4756,8 +4758,81 @@ void test_ecmult_constants(void) {
secp256k1_scratch_space_destroy(ctx, scratch);
}

void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsigned char* expected32) {
/* Using test_ecmult_accumulate, test ecmult for:
* - Key 0
* - Key 1
* - Key -1
* - For i in range(iter):
* - Key SHA256(LE32(prefix) || LE16(i))
*/
secp256k1_scalar x;
secp256k1_sha256 acc;
unsigned char b32[32];
unsigned char inp[6];
size_t i;
secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(ctx, 65536);

inp[0] = prefix & 0xFF;
inp[1] = (prefix >> 8) & 0xFF;
inp[2] = (prefix >> 16) & 0xFF;
inp[3] = (prefix >> 24) & 0xFF;
secp256k1_sha256_initialize(&acc);
secp256k1_scalar_set_int(&x, 0);
test_ecmult_accumulate(&acc, &x, scratch);
secp256k1_scalar_set_int(&x, 1);
test_ecmult_accumulate(&acc, &x, scratch);
secp256k1_scalar_negate(&x, &x);
test_ecmult_accumulate(&acc, &x, scratch);

for (i = 0; i < iter; ++i) {
secp256k1_sha256 gen;
inp[4] = i & 0xff;
inp[5] = (i >> 8) & 0xff;
secp256k1_sha256_initialize(&gen);
secp256k1_sha256_write(&gen, inp, sizeof(inp));
secp256k1_sha256_finalize(&gen, b32);
secp256k1_scalar_set_b32(&x, b32, NULL);
test_ecmult_accumulate(&acc, &x, scratch);
}
secp256k1_sha256_finalize(&acc, b32);
CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0);

secp256k1_scratch_space_destroy(ctx, scratch);
}

void run_ecmult_constants(void) {
test_ecmult_constants();
/* Expected hashes of all points in the tests below. Computed using an
* independent implementation. */
static const unsigned char expected32_6bit20[32] = {
0x68, 0xb6, 0xed, 0x6f, 0x28, 0xca, 0xc9, 0x7f,
0x8e, 0x8b, 0xd6, 0xc0, 0x61, 0x79, 0x34, 0x6e,
0x5a, 0x8f, 0x2b, 0xbc, 0x3e, 0x1f, 0xc5, 0x2e,
0x2a, 0xd0, 0x45, 0x67, 0x7f, 0x95, 0x95, 0x8e
};
static const unsigned char expected32_8bit8[32] = {
0x8b, 0x65, 0x8e, 0xea, 0x86, 0xae, 0x3c, 0x95,
0x90, 0xb6, 0x77, 0xa4, 0x8c, 0x76, 0xd9, 0xec,
0xf5, 0xab, 0x8a, 0x2f, 0xfd, 0xdb, 0x19, 0x12,
0x1a, 0xee, 0xe6, 0xb7, 0x6e, 0x05, 0x3f, 0xc6
};
/* For every combination of 6 bit positions out of 256, restricted to
* 20-bit windows (i.e., the first and last bit position are no more than
* 19 bits apart), all 64 bit patterns occur in the input scalars used in
* this test. */
Comment on lines +4819 to +4822
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition was a little hard to understand. Do you have a script that confirms it?

Alternatively, should we replace this with the following easier-to-understand condition, which is analogous to the one below (this script confirms that it holds: https://gist.github.com/robot-dreams/02d27311448bd4cb79bec3ce155bf21a#file-verify_1049_patterns-py):

    /* For every combination of 6 consecutive bit positions, all 64 bit
     * patterns occur in the input scalars used in this test. */

CONDITIONAL_TEST(1, "test_ecmult_constants_sha 1024") {
test_ecmult_constants_sha(4808378u, 1024, expected32_6bit20);
}

/* For every combination of 8 consecutive bit positions, all 256 bit
* patterns occur in the input scalars used in this test. */
CONDITIONAL_TEST(3, "test_ecmult_constants_sha 2048") {
test_ecmult_constants_sha(1607366309u, 2048, expected32_8bit8);
}

CONDITIONAL_TEST(35, "test_ecmult_constants_2bit") {
test_ecmult_constants_2bit();
}
}

void test_ecmult_gen_blind(void) {
Expand Down