Merge bitcoin-core/secp256k1#1052: Use xoshiro256++ instead of RFC6979 for tests
77a19750b4
Use xoshiro256++ PRNG instead of RFC6979 in tests (Pieter Wuille)5f2efe684e
secp256k1_testrand_int(2**N) -> secp256k1_testrand_bits(N) (Pieter Wuille) Pull request description: Just some easy low-hanging fruit. It's complete overkill to use the RFC6979 RNG for our test randomness. Replace it with a modern non-cryptographic RNG with good properties. It's a few % speedup for me. Given the internal naming of all these functions to be "testrand", I'm not concerned about the risk of someone using this for something that needs actual cryptographic randomness. ACKs for top commit: robot-dreams: ACK77a19750b4
real-or-random: utACK77a19750b4
Tree-SHA512: 2706f37689e037e84b5df25c98af924c0756e6d59f5f822b23aec5ba381b2d536e0848f134026e2568396427218f1c770f1bb07613d702efb23a84015dc9271d
This commit is contained in:
commit
a310e79ee5
|
@ -87,7 +87,7 @@ void run_nonce_function_bip340_tests(void) {
|
|||
CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, NULL, 0, NULL) == 0);
|
||||
CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1);
|
||||
/* Other algo is fine */
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, algo, algolen);
|
||||
secp256k1_testrand_bytes_test(algo, algolen);
|
||||
CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
@ -795,18 +795,18 @@ void test_schnorrsig_sign_verify(void) {
|
|||
/* Flip a few bits in the signature and in the message and check that
|
||||
* verify and verify_batch (TODO) fail */
|
||||
size_t sig_idx = secp256k1_testrand_int(N_SIGS);
|
||||
size_t byte_idx = secp256k1_testrand_int(32);
|
||||
size_t byte_idx = secp256k1_testrand_bits(5);
|
||||
unsigned char xorbyte = secp256k1_testrand_int(254)+1;
|
||||
sig[sig_idx][byte_idx] ^= xorbyte;
|
||||
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
|
||||
sig[sig_idx][byte_idx] ^= xorbyte;
|
||||
|
||||
byte_idx = secp256k1_testrand_int(32);
|
||||
byte_idx = secp256k1_testrand_bits(5);
|
||||
sig[sig_idx][32+byte_idx] ^= xorbyte;
|
||||
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
|
||||
sig[sig_idx][32+byte_idx] ^= xorbyte;
|
||||
|
||||
byte_idx = secp256k1_testrand_int(32);
|
||||
byte_idx = secp256k1_testrand_bits(5);
|
||||
msg[sig_idx][byte_idx] ^= xorbyte;
|
||||
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
|
||||
msg[sig_idx][byte_idx] ^= xorbyte;
|
||||
|
|
|
@ -17,11 +17,14 @@
|
|||
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..2**32-1]. */
|
||||
static uint32_t secp256k1_testrand32(void);
|
||||
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..2**64-1]. */
|
||||
SECP256K1_INLINE static uint64_t secp256k1_testrand64(void);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or
|
||||
* more. */
|
||||
static uint32_t secp256k1_testrand_bits(int bits);
|
||||
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..range-1]. */
|
||||
static uint32_t secp256k1_testrand_int(uint32_t range);
|
||||
|
|
|
@ -14,37 +14,64 @@
|
|||
#include "testrand.h"
|
||||
#include "hash.h"
|
||||
|
||||
static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng;
|
||||
static uint32_t secp256k1_test_rng_precomputed[8];
|
||||
static int secp256k1_test_rng_precomputed_used = 8;
|
||||
static uint64_t secp256k1_test_state[4];
|
||||
static uint64_t secp256k1_test_rng_integer;
|
||||
static int secp256k1_test_rng_integer_bits_left = 0;
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16);
|
||||
}
|
||||
static const unsigned char PREFIX[19] = "secp256k1 test init";
|
||||
unsigned char out32[32];
|
||||
secp256k1_sha256 hash;
|
||||
int i;
|
||||
|
||||
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
|
||||
if (secp256k1_test_rng_precomputed_used == 8) {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed));
|
||||
secp256k1_test_rng_precomputed_used = 0;
|
||||
/* Use SHA256(PREFIX || seed16) as initial state. */
|
||||
secp256k1_sha256_initialize(&hash);
|
||||
secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX));
|
||||
secp256k1_sha256_write(&hash, seed16, 16);
|
||||
secp256k1_sha256_finalize(&hash, out32);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
uint64_t s = 0;
|
||||
int j;
|
||||
for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
|
||||
secp256k1_test_state[i] = s;
|
||||
}
|
||||
return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++];
|
||||
secp256k1_test_rng_integer_bits_left = 0;
|
||||
}
|
||||
|
||||
static uint32_t secp256k1_testrand_bits(int bits) {
|
||||
uint32_t ret;
|
||||
SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) {
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
|
||||
/* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */
|
||||
const uint64_t result = rotl(secp256k1_test_state[0] + secp256k1_test_state[3], 23) + secp256k1_test_state[0];
|
||||
const uint64_t t = secp256k1_test_state[1] << 17;
|
||||
secp256k1_test_state[2] ^= secp256k1_test_state[0];
|
||||
secp256k1_test_state[3] ^= secp256k1_test_state[1];
|
||||
secp256k1_test_state[1] ^= secp256k1_test_state[2];
|
||||
secp256k1_test_state[0] ^= secp256k1_test_state[3];
|
||||
secp256k1_test_state[2] ^= t;
|
||||
secp256k1_test_state[3] = rotl(secp256k1_test_state[3], 45);
|
||||
return result;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
|
||||
uint64_t ret;
|
||||
if (secp256k1_test_rng_integer_bits_left < bits) {
|
||||
secp256k1_test_rng_integer |= (((uint64_t)secp256k1_testrand32()) << secp256k1_test_rng_integer_bits_left);
|
||||
secp256k1_test_rng_integer_bits_left += 32;
|
||||
secp256k1_test_rng_integer = secp256k1_testrand64();
|
||||
secp256k1_test_rng_integer_bits_left = 64;
|
||||
}
|
||||
ret = secp256k1_test_rng_integer;
|
||||
secp256k1_test_rng_integer >>= bits;
|
||||
secp256k1_test_rng_integer_bits_left -= bits;
|
||||
ret &= ((~((uint32_t)0)) >> (32 - bits));
|
||||
ret &= ((~((uint64_t)0)) >> (64 - bits));
|
||||
return ret;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
|
||||
return secp256k1_testrand_bits(32);
|
||||
}
|
||||
|
||||
static uint32_t secp256k1_testrand_int(uint32_t range) {
|
||||
/* We want a uniform integer between 0 and range-1, inclusive.
|
||||
* B is the smallest number such that range <= 2**B.
|
||||
|
@ -85,7 +112,19 @@ static uint32_t secp256k1_testrand_int(uint32_t range) {
|
|||
}
|
||||
|
||||
static void secp256k1_testrand256(unsigned char *b32) {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32);
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
uint64_t val = secp256k1_testrand64();
|
||||
b32[0] = val;
|
||||
b32[1] = val >> 8;
|
||||
b32[2] = val >> 16;
|
||||
b32[3] = val >> 24;
|
||||
b32[4] = val >> 32;
|
||||
b32[5] = val >> 40;
|
||||
b32[6] = val >> 48;
|
||||
b32[7] = val >> 56;
|
||||
b32 += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len) {
|
||||
|
@ -109,7 +148,7 @@ static void secp256k1_testrand256_test(unsigned char *b32) {
|
|||
}
|
||||
|
||||
static void secp256k1_testrand_flip(unsigned char *b, size_t len) {
|
||||
b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_int(8));
|
||||
b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_bits(3));
|
||||
}
|
||||
|
||||
static void secp256k1_testrand_init(const char* hexseed) {
|
||||
|
|
18
src/tests.c
18
src/tests.c
|
@ -790,7 +790,7 @@ void signed30_to_uint16(uint16_t* out, const secp256k1_modinv32_signed30* in) {
|
|||
void mutate_sign_signed30(secp256k1_modinv32_signed30* x) {
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
int pos = secp256k1_testrand_int(8);
|
||||
int pos = secp256k1_testrand_bits(3);
|
||||
if (x->v[pos] > 0 && x->v[pos + 1] <= 0x3fffffff) {
|
||||
x->v[pos] -= 0x40000000;
|
||||
x->v[pos + 1] += 1;
|
||||
|
@ -862,7 +862,7 @@ void mutate_sign_signed62(secp256k1_modinv64_signed62* x) {
|
|||
static const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
int pos = secp256k1_testrand_int(4);
|
||||
int pos = secp256k1_testrand_bits(2);
|
||||
if (x->v[pos] > 0 && x->v[pos + 1] <= M62) {
|
||||
x->v[pos] -= (M62 + 1);
|
||||
x->v[pos + 1] += 1;
|
||||
|
@ -4261,7 +4261,7 @@ void test_secp256k1_pippenger_bucket_window_inv(void) {
|
|||
* for a given scratch space.
|
||||
*/
|
||||
void test_ecmult_multi_pippenger_max_points(void) {
|
||||
size_t scratch_size = secp256k1_testrand_int(256);
|
||||
size_t scratch_size = secp256k1_testrand_bits(8);
|
||||
size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12);
|
||||
secp256k1_scratch *scratch;
|
||||
size_t n_points_supported;
|
||||
|
@ -6023,14 +6023,14 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
|
|||
/* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */
|
||||
nlow[n] = der ? 1 : (secp256k1_testrand_bits(3) != 0);
|
||||
/* The length of the number in bytes (the first byte of which will always be nonzero) */
|
||||
nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_int(8) / 8;
|
||||
nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_bits(3) / 8;
|
||||
CHECK(nlen[n] <= 232);
|
||||
/* The top bit of the number. */
|
||||
nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_testrand_bits(1));
|
||||
/* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */
|
||||
nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_testrand_bits(7) : 1 + secp256k1_testrand_int(127));
|
||||
/* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */
|
||||
nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_int(8) / 8);
|
||||
nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_bits(3) / 8);
|
||||
if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
|
@ -6039,7 +6039,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
|
|||
nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2);
|
||||
if (!der) {
|
||||
/* nlenlen[n] max 127 bytes */
|
||||
int add = secp256k1_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_int(16) * secp256k1_testrand_int(16) / 256;
|
||||
int add = secp256k1_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256;
|
||||
nlenlen[n] += add;
|
||||
if (add != 0) {
|
||||
*certainly_not_der = 1;
|
||||
|
@ -6053,7 +6053,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
|
|||
CHECK(tlen <= 856);
|
||||
|
||||
/* The length of the garbage inside the tuple. */
|
||||
elen = (der || indet) ? 0 : secp256k1_testrand_int(980 - tlen) * secp256k1_testrand_int(8) / 8;
|
||||
elen = (der || indet) ? 0 : secp256k1_testrand_int(980 - tlen) * secp256k1_testrand_bits(3) / 8;
|
||||
if (elen != 0) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
|
@ -6061,7 +6061,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
|
|||
CHECK(tlen <= 980);
|
||||
|
||||
/* The length of the garbage after the end of the tuple. */
|
||||
glen = der ? 0 : secp256k1_testrand_int(990 - tlen) * secp256k1_testrand_int(8) / 8;
|
||||
glen = der ? 0 : secp256k1_testrand_int(990 - tlen) * secp256k1_testrand_bits(3) / 8;
|
||||
if (glen != 0) {
|
||||
*certainly_not_der = 1;
|
||||
}
|
||||
|
@ -6076,7 +6076,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
|
|||
} else {
|
||||
int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2);
|
||||
if (!der) {
|
||||
int add = secp256k1_testrand_int(127 - tlenlen) * secp256k1_testrand_int(16) * secp256k1_testrand_int(16) / 256;
|
||||
int add = secp256k1_testrand_int(127 - tlenlen) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256;
|
||||
tlenlen += add;
|
||||
if (add != 0) {
|
||||
*certainly_not_der = 1;
|
||||
|
|
Loading…
Reference in New Issue