You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
10 KiB
279 lines
10 KiB
/**********************************************************************
|
|
* Copyright (c) 2015 Gregory Maxwell *
|
|
* Distributed under the MIT software license, see the accompanying *
|
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
|
**********************************************************************/
|
|
|
|
#ifndef SECP256K1_MODULE_RANGEPROOF_TESTS
|
|
#define SECP256K1_MODULE_RANGEPROOF_TESTS
|
|
|
|
void test_pedersen(void) {
|
|
unsigned char commits[33*19];
|
|
const unsigned char *cptr[19];
|
|
unsigned char blinds[32*19];
|
|
const unsigned char *bptr[19];
|
|
secp256k1_scalar_t s;
|
|
uint64_t values[19];
|
|
int64_t totalv;
|
|
int i;
|
|
int inputs;
|
|
int outputs;
|
|
int total;
|
|
inputs = (secp256k1_rand32() & 7) + 1;
|
|
outputs = (secp256k1_rand32() & 7) + 2;
|
|
total = inputs + outputs;
|
|
for (i = 0; i < 19; i++) {
|
|
cptr[i] = &commits[i * 33];
|
|
bptr[i] = &blinds[i * 32];
|
|
}
|
|
totalv = 0;
|
|
for (i = 0; i < inputs; i++) {
|
|
values[i] = secp256k1_rands64(0, INT64_MAX - totalv);
|
|
totalv += values[i];
|
|
}
|
|
if (secp256k1_rand32() & 1) {
|
|
for (i = 0; i < outputs; i++) {
|
|
int64_t max = INT64_MAX;
|
|
if (totalv < 0) {
|
|
max += totalv;
|
|
}
|
|
values[i + inputs] = secp256k1_rands64(0, max);
|
|
totalv -= values[i + inputs];
|
|
}
|
|
} else {
|
|
for (i = 0; i < outputs - 1; i++) {
|
|
values[i + inputs] = secp256k1_rands64(0, totalv);
|
|
totalv -= values[i + inputs];
|
|
}
|
|
values[total - 1] = totalv >> (secp256k1_rand32() & 1);
|
|
totalv -= values[total - 1];
|
|
}
|
|
for (i = 0; i < total - 1; i++) {
|
|
random_scalar_order(&s);
|
|
secp256k1_scalar_get_b32(&blinds[i * 32], &s);
|
|
}
|
|
CHECK(secp256k1_pedersen_blind_sum(ctx, &blinds[(total - 1) * 32], bptr, total - 1, inputs));
|
|
for (i = 0; i < total; i++) {
|
|
CHECK(secp256k1_pedersen_commit(ctx, &commits[i * 33], &blinds[i * 32], values[i]));
|
|
}
|
|
CHECK(secp256k1_pedersen_verify_tally(ctx, cptr, inputs, &cptr[inputs], outputs, totalv));
|
|
CHECK(!secp256k1_pedersen_verify_tally(ctx, cptr, inputs, &cptr[inputs], outputs, totalv + 1));
|
|
random_scalar_order(&s);
|
|
for (i = 0; i < 4; i++) {
|
|
secp256k1_scalar_get_b32(&blinds[i * 32], &s);
|
|
}
|
|
values[0] = INT64_MAX;
|
|
values[1] = 0;
|
|
values[2] = 1;
|
|
for (i = 0; i < 3; i++) {
|
|
CHECK(secp256k1_pedersen_commit(ctx, &commits[i * 33], &blinds[i * 32], values[i]));
|
|
}
|
|
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[1], 1, &cptr[2], 1, -1));
|
|
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[2], 1, &cptr[1], 1, 1));
|
|
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[0], 1, &cptr[0], 1, 0));
|
|
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[0], 1, &cptr[1], 1, INT64_MAX));
|
|
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[1], 1, &cptr[1], 1, 0));
|
|
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[1], 1, &cptr[0], 1, -INT64_MAX));
|
|
}
|
|
|
|
void test_borromean(void) {
|
|
unsigned char e0[32];
|
|
secp256k1_scalar_t s[64];
|
|
secp256k1_gej_t pubs[64];
|
|
secp256k1_scalar_t k[8];
|
|
secp256k1_scalar_t sec[8];
|
|
secp256k1_ge_t ge;
|
|
secp256k1_scalar_t one;
|
|
unsigned char m[32];
|
|
int rsizes[8];
|
|
int secidx[8];
|
|
int nrings;
|
|
int i;
|
|
int j;
|
|
int c;
|
|
secp256k1_rand256_test(m);
|
|
nrings = 1 + (secp256k1_rand32()&7);
|
|
c = 0;
|
|
secp256k1_scalar_set_int(&one, 1);
|
|
if (secp256k1_rand32()&1) {
|
|
secp256k1_scalar_negate(&one, &one);
|
|
}
|
|
for (i = 0; i < nrings; i++) {
|
|
rsizes[i] = 1 + (secp256k1_rand32()&7);
|
|
secidx[i] = secp256k1_rand32() % rsizes[i];
|
|
random_scalar_order(&sec[i]);
|
|
random_scalar_order(&k[i]);
|
|
if(secp256k1_rand32()&7) {
|
|
sec[i] = one;
|
|
}
|
|
if(secp256k1_rand32()&7) {
|
|
k[i] = one;
|
|
}
|
|
for (j = 0; j < rsizes[i]; j++) {
|
|
random_scalar_order(&s[c + j]);
|
|
if(secp256k1_rand32()&7) {
|
|
s[i] = one;
|
|
}
|
|
if (j == secidx[i]) {
|
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubs[c + j], &sec[i]);
|
|
} else {
|
|
random_group_element_test(&ge);
|
|
random_group_element_jacobian_test(&pubs[c + j],&ge);
|
|
}
|
|
}
|
|
c += rsizes[i];
|
|
}
|
|
CHECK(secp256k1_borromean_sign(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32));
|
|
CHECK(secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32));
|
|
i = secp256k1_rand32() % c;
|
|
secp256k1_scalar_negate(&s[i],&s[i]);
|
|
CHECK(!secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32));
|
|
secp256k1_scalar_negate(&s[i],&s[i]);
|
|
secp256k1_scalar_set_int(&one, 1);
|
|
for(j = 0; j < 4; j++) {
|
|
i = secp256k1_rand32() % c;
|
|
if (secp256k1_rand32() & 1) {
|
|
secp256k1_gej_double_var(&pubs[i],&pubs[i], NULL);
|
|
} else {
|
|
secp256k1_scalar_add(&s[i],&s[i],&one);
|
|
}
|
|
CHECK(!secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32));
|
|
}
|
|
}
|
|
|
|
void test_rangeproof(void) {
|
|
const uint64_t testvs[11] = {0, 1, 5, 11, 65535, 65537, INT32_MAX, UINT32_MAX, INT64_MAX - 1, INT64_MAX, UINT64_MAX};
|
|
unsigned char commit[33];
|
|
unsigned char commit2[33];
|
|
unsigned char proof[5134];
|
|
unsigned char blind[32];
|
|
unsigned char blindout[32];
|
|
unsigned char message[4096];
|
|
int mlen;
|
|
uint64_t v;
|
|
uint64_t vout;
|
|
uint64_t vmin;
|
|
uint64_t minv;
|
|
uint64_t maxv;
|
|
int len;
|
|
int i;
|
|
int j;
|
|
int k;
|
|
secp256k1_rand256(blind);
|
|
for (i = 0; i < 11; i++) {
|
|
v = testvs[i];
|
|
CHECK(secp256k1_pedersen_commit(ctx, commit, blind, v));
|
|
for (vmin = 0; vmin < (i<9 && i > 0 ? 2 : 1); vmin++) {
|
|
len = 5134;
|
|
CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, vmin, commit, blind, commit, 0, 0, v));
|
|
CHECK(len <= 5134);
|
|
mlen = 4096;
|
|
CHECK(secp256k1_rangeproof_rewind(ctx, blindout, &vout, message, &mlen, commit, &minv, &maxv, commit, proof, len));
|
|
for (j = 0; j < mlen; j++) {
|
|
CHECK(message[j] == 0);
|
|
}
|
|
CHECK(mlen <= 4096);
|
|
CHECK(memcmp(blindout, blind, 32) == 0);
|
|
CHECK(vout == v);
|
|
CHECK(minv <= v);
|
|
CHECK(maxv >= v);
|
|
len = 5134;
|
|
CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, v, commit, blind, commit, -1, 64, v));
|
|
CHECK(len <= 73);
|
|
CHECK(secp256k1_rangeproof_rewind(ctx, blindout, &vout, NULL, NULL, commit, &minv, &maxv, commit, proof, len));
|
|
CHECK(memcmp(blindout, blind, 32) == 0);
|
|
CHECK(vout == v);
|
|
CHECK(minv == v);
|
|
CHECK(maxv == v);
|
|
}
|
|
}
|
|
secp256k1_rand256(blind);
|
|
v = INT64_MAX - 1;
|
|
CHECK(secp256k1_pedersen_commit(ctx, commit, blind, v));
|
|
for (i = 0; i < 19; i++) {
|
|
len = 5134;
|
|
CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, 0, commit, blind, commit, i, 0, v));
|
|
CHECK(secp256k1_rangeproof_verify(ctx, &minv, &maxv, commit, proof, len));
|
|
CHECK(len <= 5134);
|
|
CHECK(minv <= v);
|
|
CHECK(maxv >= v);
|
|
}
|
|
secp256k1_rand256(blind);
|
|
{
|
|
/*Malleability test.*/
|
|
v = secp256k1_rands64(0, 255);
|
|
CHECK(secp256k1_pedersen_commit(ctx, commit, blind, v));
|
|
len = 5134;
|
|
CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, 0, commit, blind, commit, 0, 3, v));
|
|
CHECK(len <= 5134);
|
|
for (i = 0; i < len*8; i++) {
|
|
proof[i >> 3] ^= 1 << (i & 7);
|
|
CHECK(!secp256k1_rangeproof_verify(ctx, &minv, &maxv, commit, proof, len));
|
|
proof[i >> 3] ^= 1 << (i & 7);
|
|
}
|
|
CHECK(secp256k1_rangeproof_verify(ctx, &minv, &maxv, commit, proof, len));
|
|
CHECK(minv <= v);
|
|
CHECK(maxv >= v);
|
|
}
|
|
memcpy(commit2, commit, 33);
|
|
for (i = 0; i < 10 * count; i++) {
|
|
int exp;
|
|
int min_bits;
|
|
v = secp256k1_rands64(0, UINT64_MAX >> (secp256k1_rand32()&63));
|
|
vmin = 0;
|
|
if ((v < INT64_MAX) && (secp256k1_rand32()&1)) {
|
|
vmin = secp256k1_rands64(0, v);
|
|
}
|
|
secp256k1_rand256(blind);
|
|
CHECK(secp256k1_pedersen_commit(ctx, commit, blind, v));
|
|
len = 5134;
|
|
exp = (int)secp256k1_rands64(0,18)-(int)secp256k1_rands64(0,18);
|
|
if (exp < 0) {
|
|
exp = -exp;
|
|
}
|
|
min_bits = (int)secp256k1_rands64(0,64)-(int)secp256k1_rands64(0,64);
|
|
if (min_bits < 0) {
|
|
min_bits = -min_bits;
|
|
}
|
|
CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, vmin, commit, blind, commit, exp, min_bits, v));
|
|
CHECK(len <= 5134);
|
|
mlen = 4096;
|
|
CHECK(secp256k1_rangeproof_rewind(ctx, blindout, &vout, message, &mlen, commit, &minv, &maxv, commit, proof, len));
|
|
for (j = 0; j < mlen; j++) {
|
|
CHECK(message[j] == 0);
|
|
}
|
|
CHECK(mlen <= 4096);
|
|
CHECK(memcmp(blindout, blind, 32) == 0);
|
|
CHECK(vout == v);
|
|
CHECK(minv <= v);
|
|
CHECK(maxv >= v);
|
|
CHECK(secp256k1_rangeproof_rewind(ctx, blindout, &vout, NULL, NULL, commit, &minv, &maxv, commit, proof, len));
|
|
memcpy(commit2, commit, 33);
|
|
}
|
|
for (j = 0; j < 10; j++) {
|
|
for (i = 0; i < 96; i++) {
|
|
secp256k1_rand256(&proof[i * 32]);
|
|
}
|
|
for (k = 0; k < 128; k++) {
|
|
len = k;
|
|
CHECK(!secp256k1_rangeproof_verify(ctx, &minv, &maxv, commit2, proof, len));
|
|
}
|
|
len = secp256k1_rands64(0, 3072);
|
|
CHECK(!secp256k1_rangeproof_verify(ctx, &minv, &maxv, commit2, proof, len));
|
|
}
|
|
}
|
|
|
|
void run_rangeproof_tests(void) {
|
|
int i;
|
|
secp256k1_pedersen_context_initialize(ctx);
|
|
secp256k1_rangeproof_context_initialize(ctx);
|
|
for (i = 0; i < 10*count; i++) {
|
|
test_pedersen();
|
|
}
|
|
for (i = 0; i < 10*count; i++) {
|
|
test_borromean();
|
|
}
|
|
test_rangeproof();
|
|
}
|
|
|
|
#endif
|
|
|