Rename buletproof_pp* to bppp*
This commit is contained in:
13
src/modules/bppp/Makefile.am.include
Normal file
13
src/modules/bppp/Makefile.am.include
Normal file
@@ -0,0 +1,13 @@
|
||||
include_HEADERS += include/secp256k1_bppp.h
|
||||
noinst_HEADERS += src/modules/bppp/bppp_util.h
|
||||
noinst_HEADERS += src/modules/bppp/main_impl.h
|
||||
noinst_HEADERS += src/modules/bppp/bppp_transcript_impl.h
|
||||
noinst_HEADERS += src/modules/bppp/bppp_norm_product_impl.h
|
||||
noinst_HEADERS += src/modules/bppp/tests_impl.h
|
||||
|
||||
if USE_BENCHMARK
|
||||
noinst_PROGRAMS += bench_bppp
|
||||
bench_bppp_SOURCES = src/bench_bppp.c
|
||||
bench_bppp_LDADD = libsecp256k1.la $(SECP_LIBS)
|
||||
bench_bppp_LDFLAGS = -static
|
||||
endif
|
||||
548
src/modules/bppp/bppp_norm_product_impl.h
Normal file
548
src/modules/bppp/bppp_norm_product_impl.h
Normal file
@@ -0,0 +1,548 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2020 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_MODULE_BPPP_PP_NORM_PRODUCT_
|
||||
#define _SECP256K1_MODULE_BPPP_PP_NORM_PRODUCT_
|
||||
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "ecmult.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include "modules/bppp/main.h"
|
||||
#include "modules/bppp/bppp_util.h"
|
||||
#include "modules/bppp/bppp_transcript_impl.h"
|
||||
|
||||
/* Computes the inner product of two vectors of scalars
|
||||
* with elements starting from offset a and offset b
|
||||
* skipping elements according to specified step.
|
||||
* Returns: Sum_{i=0..len-1}(a[offset_a + i*step] * b[offset_b + i*step]) */
|
||||
static int secp256k1_scalar_inner_product(
|
||||
secp256k1_scalar* res,
|
||||
const secp256k1_scalar* a_vec,
|
||||
const size_t a_offset,
|
||||
const secp256k1_scalar* b_vec,
|
||||
const size_t b_offset,
|
||||
const size_t step,
|
||||
const size_t len
|
||||
) {
|
||||
size_t i;
|
||||
secp256k1_scalar_set_int(res, 0);
|
||||
for (i = 0; i < len; i++) {
|
||||
secp256k1_scalar term;
|
||||
secp256k1_scalar_mul(&term, &a_vec[a_offset + step*i], &b_vec[b_offset + step*i]);
|
||||
secp256k1_scalar_add(res, res, &term);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Computes the q-weighted inner product of two vectors of scalars
|
||||
* for elements starting from offset a and offset b respectively with the
|
||||
* given step.
|
||||
* Returns: Sum_{i=0..len-1}(a[offset_a + step*i] * b[offset_b2 + step*i]*q^(i+1)) */
|
||||
static int secp256k1_weighted_scalar_inner_product(
|
||||
secp256k1_scalar* res,
|
||||
const secp256k1_scalar* a_vec,
|
||||
const size_t a_offset,
|
||||
const secp256k1_scalar* b_vec,
|
||||
const size_t b_offset,
|
||||
const size_t step,
|
||||
const size_t len,
|
||||
const secp256k1_scalar* q
|
||||
) {
|
||||
secp256k1_scalar q_pow;
|
||||
size_t i;
|
||||
secp256k1_scalar_set_int(res, 0);
|
||||
q_pow = *q;
|
||||
for (i = 0; i < len; i++) {
|
||||
secp256k1_scalar term;
|
||||
secp256k1_scalar_mul(&term, &a_vec[a_offset + step*i], &b_vec[b_offset + step*i]);
|
||||
secp256k1_scalar_mul(&term, &term, &q_pow);
|
||||
secp256k1_scalar_mul(&q_pow, &q_pow, q);
|
||||
secp256k1_scalar_add(res, res, &term);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Compute the powers of r as r, r^2, r^4 ... r^(2^(n-1)) */
|
||||
static void secp256k1_bppp_powers_of_r(secp256k1_scalar *powers, const secp256k1_scalar *r, size_t n) {
|
||||
size_t i;
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
powers[0] = *r;
|
||||
for (i = 1; i < n; i++) {
|
||||
secp256k1_scalar_sqr(&powers[i], &powers[i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct ecmult_bp_commit_cb_data {
|
||||
const secp256k1_scalar *n;
|
||||
const secp256k1_ge *g;
|
||||
const secp256k1_scalar *l;
|
||||
size_t g_len;
|
||||
} ecmult_bp_commit_cb_data;
|
||||
|
||||
static int ecmult_bp_commit_cb(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
|
||||
ecmult_bp_commit_cb_data *data = (ecmult_bp_commit_cb_data*) cbdata;
|
||||
*pt = data->g[idx];
|
||||
if (idx < data->g_len) {
|
||||
*sc = data->n[idx];
|
||||
} else {
|
||||
*sc = data->l[idx - data->g_len];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create a commitment `commit` = vG + n_vec*G_vec + l_vec*H_vec where
|
||||
v = |n_vec*n_vec|_q + <l_vec, c_vec>. |w|_q denotes q-weighted norm of w and
|
||||
<l, r> denotes inner product of l and r.
|
||||
*/
|
||||
static int secp256k1_bppp_commit(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_scratch_space* scratch,
|
||||
secp256k1_ge* commit,
|
||||
const secp256k1_bppp_generators* g_vec,
|
||||
const secp256k1_scalar* n_vec,
|
||||
size_t n_vec_len,
|
||||
const secp256k1_scalar* l_vec,
|
||||
size_t l_vec_len,
|
||||
const secp256k1_scalar* c_vec,
|
||||
size_t c_vec_len,
|
||||
const secp256k1_scalar* q
|
||||
) {
|
||||
secp256k1_scalar v, l_c;
|
||||
/* First n_vec_len generators are Gs, rest are Hs*/
|
||||
VERIFY_CHECK(g_vec->n == (n_vec_len + l_vec_len));
|
||||
VERIFY_CHECK(l_vec_len == c_vec_len);
|
||||
|
||||
/* It is possible to extend to support n_vec and c_vec to not be power of
|
||||
two. For the initial iterations of the code, we stick to powers of two for simplicity.*/
|
||||
VERIFY_CHECK(secp256k1_is_power_of_two(n_vec_len));
|
||||
VERIFY_CHECK(secp256k1_is_power_of_two(c_vec_len));
|
||||
|
||||
/* Compute v = n_vec*n_vec*q + l_vec*c_vec */
|
||||
secp256k1_weighted_scalar_inner_product(&v, n_vec, 0 /*a offset */, n_vec, 0 /*b offset*/, 1 /*step*/, n_vec_len, q);
|
||||
secp256k1_scalar_inner_product(&l_c, l_vec, 0 /*a offset */, c_vec, 0 /*b offset*/, 1 /*step*/, l_vec_len);
|
||||
secp256k1_scalar_add(&v, &v, &l_c);
|
||||
|
||||
{
|
||||
ecmult_bp_commit_cb_data data;
|
||||
secp256k1_gej commitj;
|
||||
data.g = g_vec->gens;
|
||||
data.n = n_vec;
|
||||
data.l = l_vec;
|
||||
data.g_len = n_vec_len;
|
||||
|
||||
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &commitj, &v, ecmult_bp_commit_cb, (void*) &data, n_vec_len + l_vec_len)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_ge_set_gej_var(commit, &commitj);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct ecmult_x_cb_data {
|
||||
const secp256k1_scalar *n;
|
||||
const secp256k1_ge *g;
|
||||
const secp256k1_scalar *l;
|
||||
const secp256k1_scalar *r;
|
||||
const secp256k1_scalar *r_inv;
|
||||
size_t G_GENS_LEN; /* Figure out initialization syntax so that this can also be const */
|
||||
size_t n_len;
|
||||
} ecmult_x_cb_data;
|
||||
|
||||
static int ecmult_x_cb(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
|
||||
ecmult_x_cb_data *data = (ecmult_x_cb_data*) cbdata;
|
||||
if (idx < data->n_len) {
|
||||
if (idx % 2 == 0) {
|
||||
secp256k1_scalar_mul(sc, &data->n[idx + 1], data->r);
|
||||
*pt = data->g[idx];
|
||||
} else {
|
||||
secp256k1_scalar_mul(sc, &data->n[idx - 1], data->r_inv);
|
||||
*pt = data->g[idx];
|
||||
}
|
||||
} else {
|
||||
idx -= data->n_len;
|
||||
if (idx % 2 == 0) {
|
||||
*sc = data->l[idx + 1];
|
||||
*pt = data->g[data->G_GENS_LEN + idx];
|
||||
} else {
|
||||
*sc = data->l[idx - 1];
|
||||
*pt = data->g[data->G_GENS_LEN + idx];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct ecmult_r_cb_data {
|
||||
const secp256k1_scalar *n1;
|
||||
const secp256k1_ge *g1;
|
||||
const secp256k1_scalar *l1;
|
||||
size_t G_GENS_LEN;
|
||||
size_t n_len;
|
||||
} ecmult_r_cb_data;
|
||||
|
||||
static int ecmult_r_cb(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
|
||||
ecmult_r_cb_data *data = (ecmult_r_cb_data*) cbdata;
|
||||
if (idx < data->n_len) {
|
||||
*sc = data->n1[2*idx + 1];
|
||||
*pt = data->g1[2*idx + 1];
|
||||
} else {
|
||||
idx -= data->n_len;
|
||||
*sc = data->l1[2*idx + 1];
|
||||
*pt = data->g1[data->G_GENS_LEN + 2*idx + 1];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Recursively compute the norm argument proof satisfying the relation
|
||||
* <n_vec, n_vec>_q + <c_vec, l_vec> = v for some commitment
|
||||
* C = v*G + <n_vec, G_vec> + <l_vec, H_vec>. <x, x>_q is the weighted inner
|
||||
* product of x with itself, where the weights are the first n powers of q.
|
||||
* <x, x>_q = q*x_1^2 + q^2*x_2^2 + q^3*x_3^2 + ... + q^n*x_n^2.
|
||||
* The API computes q as square of the r challenge (`r^2`).
|
||||
*
|
||||
* The norm argument is not zero knowledge and does not operate on any secret data.
|
||||
* Thus the following code uses variable time operations while computing the proof.
|
||||
* This function also modifies the values of n_vec, l_vec, c_vec and g_vec. The caller
|
||||
* is expected to copy these values if they need to be preserved.
|
||||
*
|
||||
* Assumptions: This function is intended to be used in conjunction with the
|
||||
* some parent protocol. To use this norm protocol in a standalone manner, the user
|
||||
* should add the commitment, generators and initial public data to the transcript hash.
|
||||
*/
|
||||
static int secp256k1_bppp_rangeproof_norm_product_prove(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_scratch_space* scratch,
|
||||
unsigned char* proof,
|
||||
size_t *proof_len,
|
||||
secp256k1_sha256* transcript, /* Transcript hash of the parent protocol */
|
||||
const secp256k1_scalar* r,
|
||||
secp256k1_ge* g_vec,
|
||||
size_t g_vec_len,
|
||||
secp256k1_scalar* n_vec,
|
||||
size_t n_vec_len,
|
||||
secp256k1_scalar* l_vec,
|
||||
size_t l_vec_len,
|
||||
secp256k1_scalar* c_vec,
|
||||
size_t c_vec_len
|
||||
) {
|
||||
secp256k1_scalar q_f, r_f = *r;
|
||||
size_t proof_idx = 0;
|
||||
ecmult_x_cb_data x_cb_data;
|
||||
ecmult_r_cb_data r_cb_data;
|
||||
size_t g_len = n_vec_len, h_len = l_vec_len;
|
||||
const size_t G_GENS_LEN = g_len;
|
||||
size_t log_g_len = secp256k1_bppp_log2(g_len), log_h_len = secp256k1_bppp_log2(h_len);
|
||||
size_t num_rounds = log_g_len > log_h_len ? log_g_len : log_h_len;
|
||||
|
||||
/* Check proof sizes.*/
|
||||
VERIFY_CHECK(*proof_len >= 65 * num_rounds + 64);
|
||||
VERIFY_CHECK(g_vec_len == (n_vec_len + l_vec_len) && l_vec_len == c_vec_len);
|
||||
VERIFY_CHECK(secp256k1_is_power_of_two(n_vec_len) && secp256k1_is_power_of_two(c_vec_len));
|
||||
|
||||
x_cb_data.n = n_vec;
|
||||
x_cb_data.g = g_vec;
|
||||
x_cb_data.l = l_vec;
|
||||
x_cb_data.G_GENS_LEN = G_GENS_LEN;
|
||||
|
||||
r_cb_data.n1 = n_vec;
|
||||
r_cb_data.g1 = g_vec;
|
||||
r_cb_data.l1 = l_vec;
|
||||
r_cb_data.G_GENS_LEN = G_GENS_LEN;
|
||||
secp256k1_scalar_sqr(&q_f, &r_f);
|
||||
|
||||
|
||||
while (g_len > 1 || h_len > 1) {
|
||||
size_t i, num_points;
|
||||
secp256k1_scalar q_sq, r_inv, c0_l1, c1_l0, x_v, c1_l1, r_v;
|
||||
secp256k1_gej rj, xj;
|
||||
secp256k1_ge r_ge, x_ge;
|
||||
secp256k1_scalar e;
|
||||
|
||||
secp256k1_scalar_inverse_var(&r_inv, &r_f);
|
||||
secp256k1_scalar_sqr(&q_sq, &q_f);
|
||||
|
||||
/* Compute the X commitment X = WIP(r_inv*n0,n1)_q2 * g + r<n1,G> + <r_inv*x0, G1> */
|
||||
secp256k1_scalar_inner_product(&c0_l1, c_vec, 0, l_vec, 1, 2, h_len/2);
|
||||
secp256k1_scalar_inner_product(&c1_l0, c_vec, 1, l_vec, 0, 2, h_len/2);
|
||||
secp256k1_weighted_scalar_inner_product(&x_v, n_vec, 0, n_vec, 1, 2, g_len/2, &q_sq);
|
||||
secp256k1_scalar_mul(&x_v, &x_v, &r_inv);
|
||||
secp256k1_scalar_add(&x_v, &x_v, &x_v);
|
||||
secp256k1_scalar_add(&x_v, &x_v, &c0_l1);
|
||||
secp256k1_scalar_add(&x_v, &x_v, &c1_l0);
|
||||
|
||||
x_cb_data.r = &r_f;
|
||||
x_cb_data.r_inv = &r_inv;
|
||||
x_cb_data.n_len = g_len >= 2 ? g_len : 0;
|
||||
num_points = x_cb_data.n_len + (h_len >= 2 ? h_len : 0);
|
||||
|
||||
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &xj, &x_v, ecmult_x_cb, (void*)&x_cb_data, num_points)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_weighted_scalar_inner_product(&r_v, n_vec, 1, n_vec, 1, 2, g_len/2, &q_sq);
|
||||
secp256k1_scalar_inner_product(&c1_l1, c_vec, 1, l_vec, 1, 2, h_len/2);
|
||||
secp256k1_scalar_add(&r_v, &r_v, &c1_l1);
|
||||
|
||||
r_cb_data.n_len = g_len/2;
|
||||
num_points = r_cb_data.n_len + h_len/2;
|
||||
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &rj, &r_v, ecmult_r_cb, (void*)&r_cb_data, num_points)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We only fail here because we cannot serialize points at infinity. */
|
||||
if (secp256k1_gej_is_infinity(&xj) || secp256k1_gej_is_infinity(&rj)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_ge_set_gej_var(&x_ge, &xj);
|
||||
secp256k1_fe_normalize_var(&x_ge.x);
|
||||
secp256k1_fe_normalize_var(&x_ge.y);
|
||||
secp256k1_ge_set_gej_var(&r_ge, &rj);
|
||||
secp256k1_fe_normalize_var(&r_ge.x);
|
||||
secp256k1_fe_normalize_var(&r_ge.y);
|
||||
secp256k1_bppp_serialize_points(&proof[proof_idx], &x_ge, &r_ge);
|
||||
proof_idx += 65;
|
||||
|
||||
/* Obtain challenge e for the the next round */
|
||||
secp256k1_sha256_write(transcript, &proof[proof_idx - 65], 65);
|
||||
secp256k1_bppp_challenge_scalar(&e, transcript, 0);
|
||||
|
||||
if (g_len > 1) {
|
||||
for (i = 0; i < g_len; i = i + 2) {
|
||||
secp256k1_scalar nl, nr;
|
||||
secp256k1_gej gl, gr;
|
||||
secp256k1_scalar_mul(&nl, &n_vec[i], &r_inv);
|
||||
secp256k1_scalar_mul(&nr, &n_vec[i + 1], &e);
|
||||
secp256k1_scalar_add(&n_vec[i/2], &nl, &nr);
|
||||
|
||||
secp256k1_gej_set_ge(&gl, &g_vec[i]);
|
||||
secp256k1_ecmult(&gl, &gl, &r_f, NULL);
|
||||
secp256k1_gej_set_ge(&gr, &g_vec[i + 1]);
|
||||
secp256k1_ecmult(&gr, &gr, &e, NULL);
|
||||
secp256k1_gej_add_var(&gl, &gl, &gr, NULL);
|
||||
secp256k1_ge_set_gej_var(&g_vec[i/2], &gl);
|
||||
}
|
||||
}
|
||||
|
||||
if (h_len > 1) {
|
||||
for (i = 0; i < h_len; i = i + 2) {
|
||||
secp256k1_scalar temp1;
|
||||
secp256k1_gej grj;
|
||||
secp256k1_scalar_mul(&temp1, &c_vec[i + 1], &e);
|
||||
secp256k1_scalar_add(&c_vec[i/2], &c_vec[i], &temp1);
|
||||
|
||||
secp256k1_scalar_mul(&temp1, &l_vec[i + 1], &e);
|
||||
secp256k1_scalar_add(&l_vec[i/2], &l_vec[i], &temp1);
|
||||
|
||||
secp256k1_gej_set_ge(&grj, &g_vec[G_GENS_LEN + i + 1]);
|
||||
secp256k1_ecmult(&grj, &grj, &e, NULL);
|
||||
secp256k1_gej_add_ge_var(&grj, &grj, &g_vec[G_GENS_LEN + i], NULL);
|
||||
secp256k1_ge_set_gej_var(&g_vec[G_GENS_LEN + i/2], &grj);
|
||||
}
|
||||
}
|
||||
g_len = g_len / 2;
|
||||
h_len = h_len / 2;
|
||||
r_f = q_f;
|
||||
q_f = q_sq;
|
||||
}
|
||||
|
||||
secp256k1_scalar_get_b32(&proof[proof_idx], &n_vec[0]);
|
||||
secp256k1_scalar_get_b32(&proof[proof_idx + 32], &l_vec[0]);
|
||||
proof_idx += 64;
|
||||
*proof_len = proof_idx;
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct ec_mult_verify_cb_data1 {
|
||||
const unsigned char *proof;
|
||||
const secp256k1_ge *commit;
|
||||
const secp256k1_scalar *challenges;
|
||||
} ec_mult_verify_cb_data1;
|
||||
|
||||
static int ec_mult_verify_cb1(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
|
||||
ec_mult_verify_cb_data1 *data = (ec_mult_verify_cb_data1*) cbdata;
|
||||
if (idx == 0) {
|
||||
*pt = *data->commit;
|
||||
secp256k1_scalar_set_int(sc, 1);
|
||||
return 1;
|
||||
}
|
||||
idx -= 1;
|
||||
if (idx % 2 == 0) {
|
||||
unsigned char pk_buf[33];
|
||||
idx /= 2;
|
||||
*sc = data->challenges[idx];
|
||||
pk_buf[0] = 2 | (data->proof[65*idx] >> 1);
|
||||
memcpy(&pk_buf[1], &data->proof[65*idx + 1], 32);
|
||||
if (!secp256k1_eckey_pubkey_parse(pt, pk_buf, sizeof(pk_buf))) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
unsigned char pk_buf[33];
|
||||
secp256k1_scalar neg_one;
|
||||
idx /= 2;
|
||||
secp256k1_scalar_set_int(&neg_one, 1);
|
||||
secp256k1_scalar_negate(&neg_one, &neg_one);
|
||||
*sc = data->challenges[idx];
|
||||
secp256k1_scalar_sqr(sc, sc);
|
||||
secp256k1_scalar_add(sc, sc, &neg_one);
|
||||
pk_buf[0] = 2 | data->proof[65*idx];
|
||||
memcpy(&pk_buf[1], &data->proof[65*idx + 33], 32);
|
||||
if (!secp256k1_eckey_pubkey_parse(pt, pk_buf, sizeof(pk_buf))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct ec_mult_verify_cb_data2 {
|
||||
const secp256k1_scalar *s_g;
|
||||
const secp256k1_scalar *s_h;
|
||||
const secp256k1_ge *g_vec;
|
||||
size_t g_vec_len;
|
||||
} ec_mult_verify_cb_data2;
|
||||
|
||||
static int ec_mult_verify_cb2(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
|
||||
ec_mult_verify_cb_data2 *data = (ec_mult_verify_cb_data2*) cbdata;
|
||||
if (idx < data->g_vec_len) {
|
||||
*sc = data->s_g[idx];
|
||||
} else {
|
||||
*sc = data->s_h[idx - data->g_vec_len];
|
||||
}
|
||||
*pt = data->g_vec[idx];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Verify the proof. This function modifies the generators, c_vec and the challenge r. The
|
||||
caller should make sure to back them up if they need to be reused.
|
||||
*/
|
||||
static int secp256k1_bppp_rangeproof_norm_product_verify(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_scratch_space* scratch,
|
||||
const unsigned char* proof,
|
||||
size_t proof_len,
|
||||
secp256k1_sha256* transcript,
|
||||
const secp256k1_scalar* r,
|
||||
const secp256k1_bppp_generators* g_vec,
|
||||
size_t g_len,
|
||||
const secp256k1_scalar* c_vec,
|
||||
size_t c_vec_len,
|
||||
const secp256k1_ge* commit
|
||||
) {
|
||||
secp256k1_scalar r_f, q_f, v, n, l, r_inv, h_c;
|
||||
secp256k1_scalar *es, *s_g, *s_h, *r_inv_pows;
|
||||
secp256k1_gej res1, res2;
|
||||
size_t i = 0, scratch_checkpoint;
|
||||
int overflow;
|
||||
size_t log_g_len = secp256k1_bppp_log2(g_len), log_h_len = secp256k1_bppp_log2(c_vec_len);
|
||||
size_t n_rounds = log_g_len > log_h_len ? log_g_len : log_h_len;
|
||||
size_t h_len = c_vec_len;
|
||||
|
||||
if (g_vec->n != (h_len + g_len) || (proof_len != 65 * n_rounds + 64)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!secp256k1_is_power_of_two(g_len) || !secp256k1_is_power_of_two(h_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_set_b32(&n, &proof[n_rounds*65], &overflow); /* n */
|
||||
if (overflow) return 0;
|
||||
secp256k1_scalar_set_b32(&l, &proof[n_rounds*65 + 32], &overflow); /* l */
|
||||
if (overflow) return 0;
|
||||
if (secp256k1_scalar_is_zero(r)) return 0;
|
||||
|
||||
/* Collect the challenges in a new vector */
|
||||
scratch_checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
|
||||
es = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, n_rounds * sizeof(secp256k1_scalar));
|
||||
s_g = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, g_len * sizeof(secp256k1_scalar));
|
||||
s_h = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, h_len * sizeof(secp256k1_scalar));
|
||||
r_inv_pows = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, log_g_len * sizeof(secp256k1_scalar));
|
||||
if (es == NULL || s_g == NULL || s_h == NULL || r_inv_pows == NULL) {
|
||||
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute powers of r_inv. Later used in g_factor computations*/
|
||||
secp256k1_scalar_inverse_var(&r_inv, r);
|
||||
secp256k1_bppp_powers_of_r(r_inv_pows, &r_inv, log_g_len);
|
||||
|
||||
/* Compute r_f = r^(2^log_g_len) */
|
||||
r_f = *r;
|
||||
for (i = 0; i < log_g_len; i++) {
|
||||
secp256k1_scalar_sqr(&r_f, &r_f);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_rounds; i++) {
|
||||
secp256k1_scalar e;
|
||||
secp256k1_sha256_write(transcript, &proof[i * 65], 65);
|
||||
secp256k1_bppp_challenge_scalar(&e, transcript, 0);
|
||||
es[i] = e;
|
||||
}
|
||||
/* s_g[0] = n * \prod_{j=0}^{log_g_len - 1} r^(2^j)
|
||||
* = n * r^(2^log_g_len - 1)
|
||||
* = n * r_f * r_inv */
|
||||
secp256k1_scalar_mul(&s_g[0], &n, &r_f);
|
||||
secp256k1_scalar_mul(&s_g[0], &s_g[0], &r_inv);
|
||||
for (i = 1; i < g_len; i++) {
|
||||
size_t log_i = secp256k1_bppp_log2(i);
|
||||
size_t nearest_pow_of_two = (size_t)1 << log_i;
|
||||
/* This combines the two multiplications of challenges and r_invs in a
|
||||
* single loop.
|
||||
* s_g[i] = s_g[i - nearest_pow_of_two]
|
||||
* * e[log_i] * r_inv^(2^log_i) */
|
||||
secp256k1_scalar_mul(&s_g[i], &s_g[i - nearest_pow_of_two], &es[log_i]);
|
||||
secp256k1_scalar_mul(&s_g[i], &s_g[i], &r_inv_pows[log_i]);
|
||||
}
|
||||
s_h[0] = l;
|
||||
secp256k1_scalar_set_int(&h_c, 0);
|
||||
for (i = 1; i < h_len; i++) {
|
||||
size_t log_i = secp256k1_bppp_log2(i);
|
||||
size_t nearest_pow_of_two = (size_t)1 << log_i;
|
||||
secp256k1_scalar_mul(&s_h[i], &s_h[i - nearest_pow_of_two], &es[log_i]);
|
||||
}
|
||||
secp256k1_scalar_inner_product(&h_c, c_vec, 0 /* a_offset */ , s_h, 0 /* b_offset */, 1 /* step */, h_len);
|
||||
/* Compute v = n*n*q_f + l*h_c where q_f = r_f^2 */
|
||||
secp256k1_scalar_sqr(&q_f, &r_f);
|
||||
secp256k1_scalar_mul(&v, &n, &n);
|
||||
secp256k1_scalar_mul(&v, &v, &q_f);
|
||||
secp256k1_scalar_add(&v, &v, &h_c);
|
||||
|
||||
{
|
||||
ec_mult_verify_cb_data1 data;
|
||||
data.proof = proof;
|
||||
data.commit = commit;
|
||||
data.challenges = es;
|
||||
|
||||
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &res1, NULL, ec_mult_verify_cb1, &data, 2*n_rounds + 1)) {
|
||||
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
{
|
||||
ec_mult_verify_cb_data2 data;
|
||||
data.g_vec = g_vec->gens;
|
||||
data.g_vec_len = g_len;
|
||||
data.s_g = s_g;
|
||||
data.s_h = s_h;
|
||||
|
||||
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &res2, &v, ec_mult_verify_cb2, &data, g_len + h_len)) {
|
||||
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
|
||||
|
||||
/* res1 and res2 should be equal. Could not find a simpler way to compare them */
|
||||
secp256k1_gej_neg(&res1, &res1);
|
||||
secp256k1_gej_add_var(&res1, &res1, &res2, NULL);
|
||||
return secp256k1_gej_is_infinity(&res1);
|
||||
}
|
||||
#endif
|
||||
40
src/modules/bppp/bppp_transcript_impl.h
Normal file
40
src/modules/bppp/bppp_transcript_impl.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2022 Sanket Kanjalkar *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
#ifndef _SECP256K1_MODULE_BPPP_PP_TRANSCRIPT_IMPL_
|
||||
#define _SECP256K1_MODULE_BPPP_PP_TRANSCRIPT_IMPL_
|
||||
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "bppp_util.h"
|
||||
|
||||
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
|
||||
* SHA256 to SHA256("Bulletproofs_pp/v0/commitment")||SHA256("Bulletproofs_pp/v0/commitment").
|
||||
*/
|
||||
static void secp256k1_bppp_sha256_tagged_commitment_init(secp256k1_sha256 *sha) {
|
||||
secp256k1_sha256_initialize(sha);
|
||||
sha->s[0] = 0x52fc8185ul;
|
||||
sha->s[1] = 0x0e7debf0ul;
|
||||
sha->s[2] = 0xb0967270ul;
|
||||
sha->s[3] = 0x6f5abfe1ul;
|
||||
sha->s[4] = 0x822bdec0ul;
|
||||
sha->s[5] = 0x36db8beful;
|
||||
sha->s[6] = 0x03d9e1f1ul;
|
||||
sha->s[7] = 0x8a5cef6ful;
|
||||
|
||||
sha->bytes = 64;
|
||||
}
|
||||
|
||||
/* Obtain a challenge scalar from the current transcript.*/
|
||||
static void secp256k1_bppp_challenge_scalar(secp256k1_scalar* ch, const secp256k1_sha256 *transcript, uint64_t idx) {
|
||||
unsigned char buf[32];
|
||||
secp256k1_sha256 sha = *transcript;
|
||||
secp256k1_bppp_le64(buf, idx);
|
||||
secp256k1_sha256_write(&sha, buf, 8);
|
||||
secp256k1_sha256_finalize(&sha, buf);
|
||||
secp256k1_scalar_set_b32(ch, buf, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
56
src/modules/bppp/bppp_util.h
Normal file
56
src/modules/bppp/bppp_util.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2020 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_MODULE_BPPP_UTIL_
|
||||
#define _SECP256K1_MODULE_BPPP_UTIL_
|
||||
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
#include "hash.h"
|
||||
#include "eckey.h"
|
||||
|
||||
/* Outputs a pair of points, amortizing the parity byte between them
|
||||
* Assumes both points' coordinates have been normalized.
|
||||
*/
|
||||
static void secp256k1_bppp_serialize_points(unsigned char *output, const secp256k1_ge *lpt, const secp256k1_ge *rpt) {
|
||||
output[0] = (secp256k1_fe_is_odd(&lpt->y) << 1) + secp256k1_fe_is_odd(&rpt->y);
|
||||
secp256k1_fe_get_b32(&output[1], &lpt->x);
|
||||
secp256k1_fe_get_b32(&output[33], &rpt->x);
|
||||
}
|
||||
|
||||
/* Outputs a serialized point in compressed form. Returns 0 at point at infinity.
|
||||
*/
|
||||
static int secp256k1_bppp_serialize_pt(unsigned char *output, secp256k1_ge *lpt) {
|
||||
size_t size;
|
||||
return secp256k1_eckey_pubkey_serialize(lpt, output, &size, 1 /*compressed*/);
|
||||
}
|
||||
|
||||
/* little-endian encodes a uint64 */
|
||||
static void secp256k1_bppp_le64(unsigned char *output, const uint64_t n) {
|
||||
output[0] = n;
|
||||
output[1] = n >> 8;
|
||||
output[2] = n >> 16;
|
||||
output[3] = n >> 24;
|
||||
output[4] = n >> 32;
|
||||
output[5] = n >> 40;
|
||||
output[6] = n >> 48;
|
||||
output[7] = n >> 56;
|
||||
}
|
||||
|
||||
/* Check if n is power of two*/
|
||||
static int secp256k1_is_power_of_two(size_t n) {
|
||||
return n > 0 && (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
/* Compute the log2 of n. If n is not a power of two, it returns the largest
|
||||
* `k` such that 2^k <= n. Assumes n < 2^64. In Bulletproofs, this is bounded
|
||||
* by len of input vectors which can be safely assumed to be less than 2^64.
|
||||
*/
|
||||
static size_t secp256k1_bppp_log2(size_t n) {
|
||||
return 64 - 1 - secp256k1_clz64_var((uint64_t)n);
|
||||
}
|
||||
|
||||
#endif
|
||||
13
src/modules/bppp/main.h
Normal file
13
src/modules/bppp/main.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef SECP256K1_MODULE_BPPP_MAIN_H
|
||||
#define SECP256K1_MODULE_BPPP_MAIN_H
|
||||
|
||||
/* this type must be completed before any of the modules/bppp includes */
|
||||
struct secp256k1_bppp_generators {
|
||||
size_t n;
|
||||
/* n total generators; includes both G_i and H_i */
|
||||
/* For BP++, the generators are G_i from [0..(n - 8)] and the last 8 values
|
||||
are generators are for H_i */
|
||||
secp256k1_ge* gens;
|
||||
};
|
||||
|
||||
#endif
|
||||
115
src/modules/bppp/main_impl.h
Normal file
115
src/modules/bppp/main_impl.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2020 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_MODULE_BPPP_MAIN_
|
||||
#define _SECP256K1_MODULE_BPPP_MAIN_
|
||||
|
||||
#include "include/secp256k1_bppp.h"
|
||||
#include "include/secp256k1_generator.h"
|
||||
#include "modules/generator/main_impl.h" /* for generator_{load, save} */
|
||||
#include "hash.h"
|
||||
#include "util.h"
|
||||
#include "modules/bppp/main.h"
|
||||
#include "modules/bppp/bppp_norm_product_impl.h"
|
||||
|
||||
secp256k1_bppp_generators *secp256k1_bppp_generators_create(const secp256k1_context *ctx, size_t n) {
|
||||
secp256k1_bppp_generators *ret;
|
||||
secp256k1_rfc6979_hmac_sha256 rng;
|
||||
unsigned char seed[64];
|
||||
size_t i;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
|
||||
ret = (secp256k1_bppp_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ret->gens = (secp256k1_ge*)checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens));
|
||||
if (ret->gens == NULL) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret->n = n;
|
||||
|
||||
secp256k1_fe_get_b32(&seed[0], &secp256k1_ge_const_g.x);
|
||||
secp256k1_fe_get_b32(&seed[32], &secp256k1_ge_const_g.y);
|
||||
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, seed, 64);
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_generator gen;
|
||||
unsigned char tmp[32] = { 0 };
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32);
|
||||
CHECK(secp256k1_generator_generate(ctx, &gen, tmp));
|
||||
secp256k1_generator_load(&ret->gens[i], &gen);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
secp256k1_bppp_generators* secp256k1_bppp_generators_parse(const secp256k1_context* ctx, const unsigned char* data, size_t data_len) {
|
||||
size_t n = data_len / 33;
|
||||
secp256k1_bppp_generators* ret;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(data != NULL);
|
||||
|
||||
if (data_len % 33 != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = (secp256k1_bppp_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ret->n = n;
|
||||
ret->gens = (secp256k1_ge*)checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens));
|
||||
if (ret->gens == NULL) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (n--) {
|
||||
secp256k1_generator gen;
|
||||
if (!secp256k1_generator_parse(ctx, &gen, &data[33 * n])) {
|
||||
free(ret->gens);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
secp256k1_generator_load(&ret->gens[n], &gen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_bppp_generators_serialize(const secp256k1_context* ctx, const secp256k1_bppp_generators* gens, unsigned char* data, size_t *data_len) {
|
||||
size_t i;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(gens != NULL);
|
||||
ARG_CHECK(data != NULL);
|
||||
ARG_CHECK(data_len != NULL);
|
||||
ARG_CHECK(*data_len >= 33 * gens->n);
|
||||
|
||||
memset(data, 0, *data_len);
|
||||
for (i = 0; i < gens->n; i++) {
|
||||
secp256k1_generator gen;
|
||||
secp256k1_generator_save(&gen, &gens->gens[i]);
|
||||
secp256k1_generator_serialize(ctx, &data[33 * i], &gen);
|
||||
}
|
||||
|
||||
*data_len = 33 * gens->n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void secp256k1_bppp_generators_destroy(const secp256k1_context* ctx, secp256k1_bppp_generators *gens) {
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
(void) ctx;
|
||||
if (gens != NULL) {
|
||||
free(gens->gens);
|
||||
free(gens);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
65
src/modules/bppp/test_vectors/verify.h
Normal file
65
src/modules/bppp/test_vectors/verify.h
Normal file
@@ -0,0 +1,65 @@
|
||||
static const unsigned char verify_vector_gens[264] = { 0x03, 0xAF, 0x2C, 0x40, 0xAD, 0x03, 0xCD, 0xC5, 0x76, 0x8C, 0x07, 0x1E, 0x58, 0xD6, 0x8C, 0x73, 0x45, 0xBA, 0xEB, 0xB5, 0x3F, 0x40, 0xFA, 0x8B, 0xBF, 0x73, 0x6E, 0x7B, 0x4A, 0x54, 0x06, 0xED, 0x32, 0x03, 0xCC, 0x11, 0x19, 0x22, 0x2C, 0xA1, 0x0A, 0x45, 0x23, 0xAF, 0x9B, 0x40, 0x0D, 0xA4, 0x5E, 0x06, 0x24, 0xF4, 0x5F, 0x07, 0x89, 0x88, 0xCD, 0x71, 0xAE, 0x77, 0xC1, 0xF5, 0x87, 0x4E, 0xFC, 0xA5, 0x03, 0xDE, 0x61, 0xB1, 0x8F, 0x2C, 0xAC, 0x18, 0xF5, 0xE4, 0x06, 0x8F, 0x65, 0x55, 0xA1, 0x30, 0x5E, 0xF5, 0xF4, 0x84, 0xED, 0x6B, 0xDD, 0xC2, 0xCC, 0xE8, 0x51, 0x38, 0xB8, 0xA5, 0x4C, 0x43, 0xBD, 0x02, 0xA5, 0xF9, 0x8C, 0x1F, 0x82, 0x2D, 0xC6, 0xF3, 0x0F, 0x53, 0xDB, 0x74, 0x77, 0xC7, 0x91, 0x04, 0xB0, 0xB1, 0xA6, 0x17, 0xB2, 0x91, 0xF4, 0x8B, 0x93, 0x3E, 0xBB, 0x73, 0x15, 0x3E, 0x5A, 0xD1, 0x02, 0x44, 0xF5, 0xC6, 0x4E, 0x77, 0x60, 0x81, 0x83, 0xFF, 0xC2, 0x8E, 0x06, 0xFE, 0x67, 0x0C, 0x9A, 0x4B, 0xF2, 0x34, 0xB9, 0xEA, 0xE9, 0x37, 0xDA, 0x30, 0xE2, 0x32, 0x27, 0xF3, 0x88, 0x5F, 0x2A, 0x02, 0x1D, 0x49, 0x5D, 0x04, 0xED, 0x61, 0x95, 0x37, 0xDD, 0x95, 0xB1, 0x4F, 0x64, 0x0E, 0x1E, 0xFB, 0x47, 0x9F, 0xA7, 0xD7, 0xE0, 0x7A, 0xB1, 0x02, 0x81, 0x95, 0xD1, 0xA5, 0x7E, 0xB2, 0x74, 0x8F, 0x03, 0x26, 0xA5, 0xEC, 0xE9, 0x71, 0x46, 0x37, 0xAC, 0x3D, 0x74, 0x84, 0x26, 0xCB, 0x7C, 0xE8, 0xFE, 0x4E, 0xB0, 0x6D, 0x70, 0x3D, 0x00, 0x10, 0x1A, 0x3A, 0x5B, 0xB8, 0xAA, 0x29, 0x59, 0x93, 0x15, 0x03, 0xE1, 0xA5, 0x39, 0x44, 0x75, 0x16, 0x28, 0x5F, 0xBA, 0x69, 0xA2, 0x4A, 0x2A, 0xC3, 0x5B, 0x63, 0x1F, 0x40, 0x10, 0x36, 0xF9, 0x4C, 0xD2, 0x76, 0x0F, 0xCF, 0x7F, 0x50, 0x30, 0x6E, 0x2B, 0x1D };
|
||||
static const unsigned char verify_vector_0_commit33[33] = { 0x03, 0xD7, 0x53, 0x31, 0x5B, 0xAA, 0x04, 0xD5, 0x7C, 0x4A, 0x34, 0x94, 0x98, 0xBC, 0xA9, 0x1E, 0xD6, 0xA3, 0xBF, 0x81, 0xFC, 0x38, 0x30, 0x7C, 0x3B, 0x7C, 0xFC, 0xC6, 0xFF, 0x1A, 0x13, 0x36, 0x72 };
|
||||
static const size_t verify_vector_0_n_vec_len = 1;
|
||||
static const unsigned char verify_vector_0_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_0_c_vec[1];
|
||||
static const unsigned char verify_vector_0_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3A };
|
||||
static const unsigned char verify_vector_0_proof[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3E };
|
||||
static const int verify_vector_0_result = 1;
|
||||
static const unsigned char verify_vector_1_commit33[33] = { 0x02, 0x6C, 0x09, 0xD7, 0x06, 0x2D, 0x1C, 0x07, 0x0A, 0x64, 0x34, 0x82, 0xF6, 0x46, 0x03, 0xEB, 0x24, 0x3E, 0x54, 0x0F, 0xDA, 0xAF, 0x3A, 0x69, 0x5F, 0x86, 0xB6, 0xD2, 0xC2, 0x06, 0xE9, 0x49, 0xC7 };
|
||||
static const size_t verify_vector_1_n_vec_len = 1;
|
||||
static const unsigned char verify_vector_1_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_1_c_vec[1];
|
||||
static const unsigned char verify_vector_1_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3A };
|
||||
static const unsigned char verify_vector_1_proof[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3E };
|
||||
static const int verify_vector_1_result = 0;
|
||||
static const unsigned char verify_vector_2_commit33[33] = { 0x03, 0xD7, 0x53, 0x31, 0x5B, 0xAA, 0x04, 0xD5, 0x7C, 0x4A, 0x34, 0x94, 0x98, 0xBC, 0xA9, 0x1E, 0xD6, 0xA3, 0xBF, 0x81, 0xFC, 0x38, 0x30, 0x7C, 0x3B, 0x7C, 0xFC, 0xC6, 0xFF, 0x1A, 0x13, 0x36, 0x72 };
|
||||
static const size_t verify_vector_2_n_vec_len = 1;
|
||||
static const unsigned char verify_vector_2_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_2_c_vec[1];
|
||||
static const unsigned char verify_vector_2_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3A };
|
||||
static const unsigned char verify_vector_2_proof[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 };
|
||||
static const int verify_vector_2_result = 0;
|
||||
static const unsigned char verify_vector_3_commit33[33] = { 0x03, 0xD7, 0x53, 0x31, 0x5B, 0xAA, 0x04, 0xD5, 0x7C, 0x4A, 0x34, 0x94, 0x98, 0xBC, 0xA9, 0x1E, 0xD6, 0xA3, 0xBF, 0x81, 0xFC, 0x38, 0x30, 0x7C, 0x3B, 0x7C, 0xFC, 0xC6, 0xFF, 0x1A, 0x13, 0x36, 0x72 };
|
||||
static const size_t verify_vector_3_n_vec_len = 1;
|
||||
static const unsigned char verify_vector_3_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_3_c_vec[1];
|
||||
static const unsigned char verify_vector_3_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3A };
|
||||
static const unsigned char verify_vector_3_proof[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 };
|
||||
static const int verify_vector_3_result = 0;
|
||||
static const unsigned char verify_vector_4_commit33[33] = { 0x03, 0xD7, 0x53, 0x31, 0x5B, 0xAA, 0x04, 0xD5, 0x7C, 0x4A, 0x34, 0x94, 0x98, 0xBC, 0xA9, 0x1E, 0xD6, 0xA3, 0xBF, 0x81, 0xFC, 0x38, 0x30, 0x7C, 0x3B, 0x7C, 0xFC, 0xC6, 0xFF, 0x1A, 0x13, 0x36, 0x72 };
|
||||
static const size_t verify_vector_4_n_vec_len = 1;
|
||||
static const unsigned char verify_vector_4_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_4_c_vec[1];
|
||||
static const unsigned char verify_vector_4_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3A };
|
||||
static const unsigned char verify_vector_4_proof[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41 };
|
||||
static const int verify_vector_4_result = 0;
|
||||
static const unsigned char verify_vector_5_commit33[33] = { 0x03, 0x83, 0x6A, 0xD4, 0x2D, 0xD2, 0x02, 0x49, 0xC8, 0x6E, 0x53, 0x22, 0x53, 0x24, 0xDA, 0x52, 0x08, 0xC0, 0x62, 0x4C, 0xCB, 0xB3, 0x13, 0xD7, 0x14, 0x59, 0x68, 0x47, 0x56, 0x00, 0xC0, 0x8D, 0xBA };
|
||||
static const size_t verify_vector_5_n_vec_len = 2;
|
||||
static const unsigned char verify_vector_5_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_5_c_vec[1];
|
||||
static const unsigned char verify_vector_5_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x36 };
|
||||
static const unsigned char verify_vector_5_proof[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4C, 0xB9, 0xD4, 0x34, 0xA2, 0xD6, 0xD5, 0x4C, 0x0F, 0x2E, 0x2C, 0xE3, 0x82, 0x17, 0x48, 0x63, 0xE0, 0xAE, 0x6B, 0xD7, 0x64, 0x9D, 0x43, 0x2B, 0x6E, 0x6E, 0x1C, 0x62, 0x55, 0x4B, 0xC5, 0x73, 0x3D, 0x74, 0x7B, 0x78, 0x43, 0xF4, 0x8B, 0x7C, 0x84, 0x10, 0x00, 0x8B, 0x12, 0xAF, 0xA4, 0xF1, 0xF4, 0x01, 0x96, 0x21, 0x8B, 0xE9, 0x05, 0x01, 0xF8, 0x23, 0x7A, 0x8F, 0x66, 0xC9, 0xDE, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3E };
|
||||
static const int verify_vector_5_result = 0;
|
||||
static const unsigned char verify_vector_6_commit33[33] = { 0x03, 0xCF, 0x7F, 0x08, 0xF5, 0x8A, 0x06, 0x74, 0x5C, 0xDB, 0xCE, 0xC6, 0x51, 0xF3, 0xE5, 0xE4, 0xDC, 0xAD, 0xF4, 0x40, 0x3C, 0xFA, 0xE6, 0x78, 0xBE, 0x49, 0x2D, 0x90, 0xC8, 0xD0, 0x16, 0x3D, 0x78 };
|
||||
static const size_t verify_vector_6_n_vec_len = 2;
|
||||
static const unsigned char verify_vector_6_c_vec32[4][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 }, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x30 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D } };
|
||||
static secp256k1_scalar verify_vector_6_c_vec[4];
|
||||
static const unsigned char verify_vector_6_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3A };
|
||||
static const unsigned char verify_vector_6_proof[] = { 0x00, 0xD2, 0xEC, 0xE2, 0x53, 0x97, 0x28, 0x68, 0x22, 0x59, 0x34, 0xEF, 0xE4, 0x7B, 0x87, 0x4D, 0xE9, 0x57, 0xD5, 0xB7, 0xC7, 0x72, 0xF4, 0xC9, 0xEA, 0x66, 0x14, 0x59, 0xE1, 0xA9, 0xD5, 0xB2, 0x10, 0xDF, 0xE2, 0xFF, 0xF5, 0xA4, 0x38, 0x6B, 0xFE, 0x36, 0x89, 0xE4, 0x9D, 0x90, 0x9F, 0x71, 0x19, 0xE6, 0xA3, 0x1E, 0xAA, 0xAA, 0x4E, 0xFE, 0xC2, 0xD3, 0x37, 0xBB, 0xDE, 0xDB, 0x46, 0x43, 0xC2, 0x01, 0x42, 0x5F, 0xFC, 0xC6, 0x25, 0xA0, 0xB4, 0xF0, 0x76, 0x99, 0xF4, 0x7C, 0xE9, 0x83, 0x82, 0xED, 0x7C, 0x95, 0xBA, 0xD0, 0xE6, 0x5B, 0x88, 0xFD, 0x38, 0xEA, 0x23, 0x54, 0xD4, 0xBD, 0xD4, 0x37, 0xB8, 0x2B, 0x49, 0xAF, 0x81, 0xFD, 0xBE, 0x88, 0xB2, 0xE5, 0x3F, 0xF4, 0x30, 0x52, 0x00, 0x63, 0x9D, 0xAE, 0x82, 0x44, 0xE9, 0x62, 0x87, 0x2A, 0x23, 0x89, 0x10, 0xE4, 0x9A, 0x64, 0x9F, 0x71, 0xD9, 0x32, 0x57, 0x3B, 0xCB, 0xAC, 0x30, 0xAE, 0x71, 0x61, 0xE9, 0x50, 0x1F, 0xCB, 0x49, 0x9C, 0x52, 0xBA, 0x0C, 0xC4, 0x00, 0x58, 0x73, 0x63, 0xD3, 0x42, 0xDE, 0x42, 0x5E, 0xC5, 0x97, 0xE5, 0xDA, 0x88, 0x76, 0x49, 0x6C, 0x8B, 0x92, 0x99, 0xEE, 0xD0, 0xA9, 0xEB, 0x6E, 0xCA, 0xE1, 0x93, 0x81, 0x56, 0x2E, 0xCA, 0xF3, 0x8E, 0xF0, 0x04, 0xD2, 0x96, 0xD8, 0xDB, 0xEE, 0xEE, 0x1C, 0x44 };
|
||||
static const int verify_vector_6_result = 1;
|
||||
static const unsigned char verify_vector_7_commit33[33] = { 0x02, 0x7A, 0xAA, 0xB2, 0x7E, 0xA5, 0x5B, 0x77, 0x08, 0xE5, 0x43, 0xB6, 0x22, 0x7F, 0xC9, 0xAC, 0x53, 0x10, 0x32, 0x61, 0x7B, 0x7D, 0xAC, 0xB1, 0xB6, 0xF6, 0xAC, 0xDE, 0x63, 0x79, 0x82, 0x9C, 0x24 };
|
||||
static const size_t verify_vector_7_n_vec_len = 4;
|
||||
static const unsigned char verify_vector_7_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_7_c_vec[1];
|
||||
static const unsigned char verify_vector_7_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x34 };
|
||||
static const unsigned char verify_vector_7_proof[] = { 0x00, 0xBC, 0x4C, 0x42, 0x67, 0x71, 0x69, 0x52, 0x6A, 0x65, 0xFE, 0xA0, 0xCB, 0x3F, 0x58, 0x8B, 0x48, 0x48, 0x6E, 0x59, 0xFC, 0x55, 0x51, 0x10, 0xB9, 0xBF, 0x6A, 0x7D, 0xBF, 0x32, 0x34, 0x4E, 0x7D, 0xBA, 0xD5, 0xCB, 0xCC, 0x19, 0xED, 0xAA, 0x9F, 0x8D, 0x93, 0x26, 0x5E, 0x3F, 0x3E, 0xAA, 0xDF, 0x0B, 0x1C, 0xB3, 0xDC, 0x37, 0xB6, 0xDB, 0xAE, 0x43, 0x63, 0x92, 0xB5, 0xFF, 0x0D, 0x1C, 0x77, 0x02, 0x7E, 0x2B, 0xB8, 0x87, 0x85, 0x81, 0x13, 0x70, 0x1F, 0x03, 0x65, 0x7D, 0xD8, 0x91, 0x83, 0xE5, 0x7E, 0x8B, 0x9E, 0x6F, 0x1C, 0x08, 0x9C, 0x9C, 0x5F, 0xA4, 0x12, 0x5F, 0xD3, 0xEE, 0xE2, 0x74, 0x7A, 0x2C, 0x58, 0x3A, 0x29, 0x4F, 0x64, 0x10, 0xE7, 0x89, 0xBF, 0xB2, 0xE5, 0xD9, 0xD5, 0xC5, 0x62, 0x83, 0x0C, 0xA8, 0xDD, 0x1E, 0x24, 0x6D, 0xD1, 0x58, 0x8D, 0x80, 0x74, 0xF3, 0xD9, 0x3A, 0x68, 0x7B, 0xF5, 0x12, 0xC6, 0xC2, 0x3F, 0x71, 0x47, 0xDF, 0xCF, 0xC8, 0xE2, 0xC4, 0x59, 0xDF, 0x4F, 0xEC, 0x86, 0xE9, 0xF9, 0x31, 0x94, 0x6A, 0x5F, 0xD9, 0x1E, 0x6B, 0x09, 0xCD, 0xCF, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3E };
|
||||
static const int verify_vector_7_result = 1;
|
||||
static const unsigned char verify_vector_8_commit33[33] = { 0x02, 0x2D, 0x4F, 0xF9, 0xB7, 0x15, 0x22, 0xBC, 0xB0, 0x8B, 0xF8, 0xBA, 0x31, 0x0A, 0x80, 0x76, 0x7A, 0xE9, 0xA9, 0x83, 0x00, 0xBC, 0x5A, 0x01, 0xCC, 0xE9, 0x00, 0x83, 0x56, 0xEA, 0x77, 0xEB, 0x75 };
|
||||
static const size_t verify_vector_8_n_vec_len = 4;
|
||||
static const unsigned char verify_vector_8_c_vec32[1][32] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3C } };
|
||||
static secp256k1_scalar verify_vector_8_c_vec[1];
|
||||
static const unsigned char verify_vector_8_r32[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x34 };
|
||||
static const unsigned char verify_vector_8_proof[] = { 0x00, 0xBC, 0x4C, 0x42, 0x67, 0x71, 0x69, 0x52, 0x6A, 0x65, 0xFE, 0xA0, 0xCB, 0x3F, 0x58, 0x8B, 0x48, 0x48, 0x6E, 0x59, 0xFC, 0x55, 0x51, 0x10, 0xB9, 0xBF, 0x6A, 0x7D, 0xBF, 0x32, 0x34, 0x4E, 0x7D, 0xBA, 0xD5, 0xCB, 0xCC, 0x19, 0xED, 0xAA, 0x9F, 0x8D, 0x93, 0x26, 0x5E, 0x3F, 0x3E, 0xAA, 0xDF, 0x0B, 0x1C, 0xB3, 0xDC, 0x37, 0xB6, 0xDB, 0xAE, 0x43, 0x63, 0x92, 0xB5, 0xFF, 0x0D, 0x1C, 0x77, 0x02, 0x7E, 0x2B, 0xB8, 0x87, 0x85, 0x81, 0x13, 0x70, 0x1F, 0x03, 0x65, 0x7D, 0xD8, 0x91, 0x83, 0xE5, 0x7E, 0x8B, 0x9E, 0x6F, 0x1C, 0x08, 0x9C, 0x9C, 0x5F, 0xA4, 0x12, 0x5F, 0xD3, 0xEE, 0xE2, 0x74, 0x7A, 0x2C, 0x58, 0x3A, 0x29, 0x4F, 0x64, 0x10, 0xE7, 0x89, 0xBF, 0xB2, 0xE5, 0xD9, 0xD5, 0xC5, 0x62, 0x83, 0x0C, 0xA8, 0xDD, 0x1E, 0x24, 0x6D, 0xD1, 0x58, 0x8D, 0x80, 0x74, 0xF3, 0xD9, 0x3A, 0x68, 0x7B, 0xF5, 0x12, 0xC6, 0xC2, 0x3F, 0x71, 0x47, 0xDF, 0xCF, 0xC8, 0xE2, 0xC4, 0x59, 0xDF, 0x4F, 0xEC, 0x86, 0xE9, 0xF9, 0x31, 0x94, 0x6A, 0x5F, 0xD9, 0x1E, 0x6B, 0x09, 0xCD, 0xCF, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x3E };
|
||||
static const int verify_vector_8_result = 0;
|
||||
|
||||
566
src/modules/bppp/tests_impl.h
Normal file
566
src/modules/bppp/tests_impl.h
Normal file
@@ -0,0 +1,566 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2020 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_MODULE_BPPP_TEST_
|
||||
#define _SECP256K1_MODULE_BPPP_TEST_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "include/secp256k1_bppp.h"
|
||||
#include "bppp_norm_product_impl.h"
|
||||
#include "bppp_util.h"
|
||||
#include "bppp_transcript_impl.h"
|
||||
#include "test_vectors/verify.h"
|
||||
|
||||
static void test_bppp_generators_api(void) {
|
||||
/* The BP generator API requires no precomp */
|
||||
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
|
||||
|
||||
secp256k1_bppp_generators *gens;
|
||||
secp256k1_bppp_generators *gens_orig;
|
||||
unsigned char gens_ser[330];
|
||||
size_t len = sizeof(gens_ser);
|
||||
|
||||
int32_t ecount = 0;
|
||||
|
||||
secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
/* Create */
|
||||
gens = secp256k1_bppp_generators_create(none, 10);
|
||||
CHECK(gens != NULL && ecount == 0);
|
||||
gens_orig = gens; /* Preserve for round-trip test */
|
||||
|
||||
/* Serialize */
|
||||
ecount = 0;
|
||||
CHECK(!secp256k1_bppp_generators_serialize(none, NULL, gens_ser, &len));
|
||||
CHECK(ecount == 1);
|
||||
CHECK(!secp256k1_bppp_generators_serialize(none, gens, NULL, &len));
|
||||
CHECK(ecount == 2);
|
||||
CHECK(!secp256k1_bppp_generators_serialize(none, gens, gens_ser, NULL));
|
||||
CHECK(ecount == 3);
|
||||
len = 0;
|
||||
CHECK(!secp256k1_bppp_generators_serialize(none, gens, gens_ser, &len));
|
||||
CHECK(ecount == 4);
|
||||
len = sizeof(gens_ser) - 1;
|
||||
CHECK(!secp256k1_bppp_generators_serialize(none, gens, gens_ser, &len));
|
||||
CHECK(ecount == 5);
|
||||
len = sizeof(gens_ser);
|
||||
{
|
||||
/* Output buffer can be greater than minimum needed */
|
||||
unsigned char gens_ser_tmp[331];
|
||||
size_t len_tmp = sizeof(gens_ser_tmp);
|
||||
CHECK(secp256k1_bppp_generators_serialize(none, gens, gens_ser_tmp, &len_tmp));
|
||||
CHECK(len_tmp == sizeof(gens_ser_tmp) - 1);
|
||||
CHECK(ecount == 5);
|
||||
}
|
||||
|
||||
/* Parse */
|
||||
CHECK(secp256k1_bppp_generators_serialize(none, gens, gens_ser, &len));
|
||||
ecount = 0;
|
||||
gens = secp256k1_bppp_generators_parse(none, NULL, sizeof(gens_ser));
|
||||
CHECK(gens == NULL && ecount == 1);
|
||||
/* Not a multiple of 33 */
|
||||
gens = secp256k1_bppp_generators_parse(none, gens_ser, sizeof(gens_ser) - 1);
|
||||
CHECK(gens == NULL && ecount == 1);
|
||||
gens = secp256k1_bppp_generators_parse(none, gens_ser, sizeof(gens_ser));
|
||||
CHECK(gens != NULL && ecount == 1);
|
||||
/* Not valid generators */
|
||||
memset(gens_ser, 1, sizeof(gens_ser));
|
||||
CHECK(secp256k1_bppp_generators_parse(none, gens_ser, sizeof(gens_ser)) == NULL);
|
||||
CHECK(ecount == 1);
|
||||
|
||||
/* Check that round-trip succeeded */
|
||||
CHECK(gens->n == gens_orig->n);
|
||||
for (len = 0; len < gens->n; len++) {
|
||||
ge_equals_ge(&gens->gens[len], &gens_orig->gens[len]);
|
||||
}
|
||||
|
||||
/* Destroy (we allow destroying a NULL context, it's just a noop. like free().) */
|
||||
ecount = 0;
|
||||
secp256k1_bppp_generators_destroy(none, NULL);
|
||||
secp256k1_bppp_generators_destroy(none, gens);
|
||||
secp256k1_bppp_generators_destroy(none, gens_orig);
|
||||
CHECK(ecount == 0);
|
||||
|
||||
secp256k1_context_destroy(none);
|
||||
}
|
||||
|
||||
static void test_bppp_generators_fixed(void) {
|
||||
secp256k1_bppp_generators *gens = secp256k1_bppp_generators_create(ctx, 3);
|
||||
unsigned char gens_ser[330];
|
||||
const unsigned char fixed_first_3[99] = {
|
||||
0x0b,
|
||||
0xb3, 0x4d, 0x5f, 0xa6, 0xb8, 0xf3, 0xd1, 0x38,
|
||||
0x49, 0xce, 0x51, 0x91, 0xb7, 0xf6, 0x76, 0x18,
|
||||
0xfe, 0x5b, 0xd1, 0x2a, 0x88, 0xb2, 0x0e, 0xac,
|
||||
0x33, 0x89, 0x45, 0x66, 0x7f, 0xb3, 0x30, 0x56,
|
||||
0x0a,
|
||||
0x62, 0x86, 0x15, 0x16, 0x92, 0x42, 0x10, 0x9e,
|
||||
0x9e, 0x64, 0xd4, 0xcb, 0x28, 0x81, 0x60, 0x9c,
|
||||
0x24, 0xb9, 0x89, 0x51, 0x2a, 0xd9, 0x01, 0xae,
|
||||
0xff, 0x75, 0x64, 0x9c, 0x37, 0x5d, 0xbd, 0x79,
|
||||
0x0a,
|
||||
0xed, 0xe0, 0x6e, 0x07, 0x5e, 0x79, 0xd0, 0xf7,
|
||||
0x7b, 0x03, 0x3e, 0xb9, 0xa9, 0x21, 0xa4, 0x5b,
|
||||
0x99, 0xf3, 0x9b, 0xee, 0xfe, 0xa0, 0x37, 0xa2,
|
||||
0x1f, 0xe9, 0xd7, 0x4f, 0x95, 0x8b, 0x10, 0xe2,
|
||||
};
|
||||
size_t len;
|
||||
|
||||
len = 99;
|
||||
CHECK(secp256k1_bppp_generators_serialize(ctx, gens, gens_ser, &len));
|
||||
CHECK(memcmp(gens_ser, fixed_first_3, sizeof(fixed_first_3)) == 0);
|
||||
|
||||
len = sizeof(gens_ser);
|
||||
CHECK(secp256k1_bppp_generators_serialize(ctx, gens, gens_ser, &len));
|
||||
CHECK(memcmp(gens_ser, fixed_first_3, sizeof(fixed_first_3)) == 0);
|
||||
|
||||
secp256k1_bppp_generators_destroy(ctx, gens);
|
||||
}
|
||||
|
||||
static void test_bppp_tagged_hash(void) {
|
||||
unsigned char tag_data[29] = "Bulletproofs_pp/v0/commitment";
|
||||
secp256k1_sha256 sha;
|
||||
secp256k1_sha256 sha_cached;
|
||||
unsigned char output[32];
|
||||
unsigned char output_cached[32];
|
||||
secp256k1_scalar s;
|
||||
|
||||
secp256k1_sha256_initialize_tagged(&sha, tag_data, sizeof(tag_data));
|
||||
secp256k1_bppp_sha256_tagged_commitment_init(&sha_cached);
|
||||
secp256k1_sha256_finalize(&sha, output);
|
||||
secp256k1_sha256_finalize(&sha_cached, output_cached);
|
||||
CHECK(secp256k1_memcmp_var(output, output_cached, 32) == 0);
|
||||
|
||||
{
|
||||
unsigned char expected[32] = { 0x21, 0x2F, 0xB6, 0x4F, 0x9D, 0x8C, 0x3B, 0xC5,
|
||||
0xF6, 0x91, 0x15, 0xEE, 0x74, 0xF5, 0x12, 0x67,
|
||||
0x8A, 0x41, 0xC6, 0x85, 0x1A, 0x79, 0x14, 0xFC,
|
||||
0x48, 0x15, 0xC7, 0x2D, 0xF8, 0x63, 0x8F, 0x1B };
|
||||
secp256k1_bppp_sha256_tagged_commitment_init(&sha);
|
||||
secp256k1_bppp_challenge_scalar(&s, &sha, 0);
|
||||
secp256k1_scalar_get_b32(output, &s);
|
||||
CHECK(memcmp(output, expected, sizeof(output)) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
unsigned char tmp[3] = {0, 1, 2};
|
||||
unsigned char expected[32] = { 0x8D, 0xAA, 0xB7, 0x7E, 0x3C, 0x6A, 0x9E, 0xEC,
|
||||
0x72, 0x7E, 0x3E, 0xB7, 0x10, 0x03, 0xF0, 0xE9,
|
||||
0x69, 0x4D, 0xAA, 0x96, 0xCE, 0x98, 0xBB, 0x39,
|
||||
0x1C, 0x2F, 0x7C, 0x2E, 0x1C, 0x17, 0x78, 0x6D };
|
||||
secp256k1_sha256_write(&sha, tmp, sizeof(tmp));
|
||||
secp256k1_bppp_challenge_scalar(&s, &sha, 0);
|
||||
secp256k1_scalar_get_b32(output, &s);
|
||||
CHECK(memcmp(output, expected, sizeof(output)) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void test_log_exp(void) {
|
||||
CHECK(secp256k1_is_power_of_two(0) == 0);
|
||||
CHECK(secp256k1_is_power_of_two(1) == 1);
|
||||
CHECK(secp256k1_is_power_of_two(2) == 1);
|
||||
CHECK(secp256k1_is_power_of_two(64) == 1);
|
||||
CHECK(secp256k1_is_power_of_two(63) == 0);
|
||||
CHECK(secp256k1_is_power_of_two(256) == 1);
|
||||
|
||||
CHECK(secp256k1_bppp_log2(1) == 0);
|
||||
CHECK(secp256k1_bppp_log2(2) == 1);
|
||||
CHECK(secp256k1_bppp_log2(255) == 7);
|
||||
CHECK(secp256k1_bppp_log2(256) == 8);
|
||||
CHECK(secp256k1_bppp_log2(257) == 8);
|
||||
}
|
||||
|
||||
void test_norm_util_helpers(void) {
|
||||
secp256k1_scalar a_vec[4], b_vec[4], r_pows[4], res, res2, q, r;
|
||||
int i;
|
||||
/* a = {1, 2, 3, 4} b = {5, 6, 7, 8}, q = 4, r = 2 */
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_scalar_set_int(&a_vec[i], i + 1);
|
||||
secp256k1_scalar_set_int(&b_vec[i], i + 5);
|
||||
}
|
||||
secp256k1_scalar_set_int(&q, 4);
|
||||
secp256k1_scalar_set_int(&r, 2);
|
||||
secp256k1_scalar_inner_product(&res, a_vec, 0, b_vec, 0, 1, 4);
|
||||
secp256k1_scalar_set_int(&res2, 70);
|
||||
CHECK(secp256k1_scalar_eq(&res2, &res) == 1);
|
||||
|
||||
secp256k1_scalar_inner_product(&res, a_vec, 0, b_vec, 1, 2, 2);
|
||||
secp256k1_scalar_set_int(&res2, 30);
|
||||
CHECK(secp256k1_scalar_eq(&res2, &res) == 1);
|
||||
|
||||
secp256k1_scalar_inner_product(&res, a_vec, 1, b_vec, 0, 2, 2);
|
||||
secp256k1_scalar_set_int(&res2, 38);
|
||||
CHECK(secp256k1_scalar_eq(&res2, &res) == 1);
|
||||
|
||||
secp256k1_scalar_inner_product(&res, a_vec, 1, b_vec, 1, 2, 2);
|
||||
secp256k1_scalar_set_int(&res2, 44);
|
||||
CHECK(secp256k1_scalar_eq(&res2, &res) == 1);
|
||||
|
||||
secp256k1_weighted_scalar_inner_product(&res, a_vec, 0, a_vec, 0, 1, 4, &q);
|
||||
secp256k1_scalar_set_int(&res2, 4740); /*i*i*4^(i+1) */
|
||||
CHECK(secp256k1_scalar_eq(&res2, &res) == 1);
|
||||
|
||||
secp256k1_bppp_powers_of_r(r_pows, &r, 4);
|
||||
secp256k1_scalar_set_int(&res, 2); CHECK(secp256k1_scalar_eq(&res, &r_pows[0]));
|
||||
secp256k1_scalar_set_int(&res, 4); CHECK(secp256k1_scalar_eq(&res, &r_pows[1]));
|
||||
secp256k1_scalar_set_int(&res, 16); CHECK(secp256k1_scalar_eq(&res, &r_pows[2]));
|
||||
secp256k1_scalar_set_int(&res, 256); CHECK(secp256k1_scalar_eq(&res, &r_pows[3]));
|
||||
}
|
||||
|
||||
static void secp256k1_norm_arg_commit_initial_data(
|
||||
secp256k1_sha256* transcript,
|
||||
const secp256k1_scalar* r,
|
||||
const secp256k1_bppp_generators* gens_vec,
|
||||
size_t g_len, /* Same as n_vec_len, g_len + c_vec_len = gens->n */
|
||||
const secp256k1_scalar* c_vec,
|
||||
size_t c_vec_len,
|
||||
const secp256k1_ge* commit
|
||||
) {
|
||||
/* Commit to the initial public values */
|
||||
unsigned char ser_commit[33], ser_scalar[32], ser_le64[8];
|
||||
size_t i;
|
||||
secp256k1_ge comm = *commit;
|
||||
secp256k1_bppp_sha256_tagged_commitment_init(transcript);
|
||||
secp256k1_fe_normalize(&comm.x);
|
||||
secp256k1_fe_normalize(&comm.y);
|
||||
CHECK(secp256k1_ge_is_infinity(&comm) == 0);
|
||||
CHECK(secp256k1_bppp_serialize_pt(&ser_commit[0], &comm));
|
||||
secp256k1_sha256_write(transcript, ser_commit, 33);
|
||||
secp256k1_scalar_get_b32(ser_scalar, r);
|
||||
secp256k1_sha256_write(transcript, ser_scalar, 32);
|
||||
secp256k1_bppp_le64(ser_le64, g_len);
|
||||
secp256k1_sha256_write(transcript, ser_le64, 8);
|
||||
secp256k1_bppp_le64(ser_le64, gens_vec->n);
|
||||
secp256k1_sha256_write(transcript, ser_le64, 8);
|
||||
for (i = 0; i < gens_vec->n; i++) {
|
||||
secp256k1_fe_normalize(&gens_vec->gens[i].x);
|
||||
secp256k1_fe_normalize(&gens_vec->gens[i].y);
|
||||
CHECK(secp256k1_bppp_serialize_pt(&ser_commit[0], &gens_vec->gens[i]));
|
||||
secp256k1_sha256_write(transcript, ser_commit, 33);
|
||||
}
|
||||
secp256k1_bppp_le64(ser_le64, c_vec_len);
|
||||
secp256k1_sha256_write(transcript, ser_le64, 8);
|
||||
for (i = 0; i < c_vec_len; i++) {
|
||||
secp256k1_scalar_get_b32(ser_scalar, &c_vec[i]);
|
||||
secp256k1_sha256_write(transcript, ser_scalar, 32);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_vectors_into_scratch(secp256k1_scratch_space* scratch,
|
||||
secp256k1_scalar **ns,
|
||||
secp256k1_scalar **ls,
|
||||
secp256k1_scalar **cs,
|
||||
secp256k1_ge **gs,
|
||||
const secp256k1_scalar *n_vec,
|
||||
const secp256k1_scalar *l_vec,
|
||||
const secp256k1_scalar *c_vec,
|
||||
const secp256k1_ge *gens_vec,
|
||||
size_t g_len,
|
||||
size_t h_len) {
|
||||
*ns = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, g_len * sizeof(secp256k1_scalar));
|
||||
*ls = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, h_len * sizeof(secp256k1_scalar));
|
||||
*cs = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, h_len * sizeof(secp256k1_scalar));
|
||||
*gs = (secp256k1_ge*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, (g_len + h_len) * sizeof(secp256k1_ge));
|
||||
CHECK(ns != NULL && ls != NULL && cs != NULL && gs != NULL);
|
||||
memcpy(*ns, n_vec, g_len * sizeof(secp256k1_scalar));
|
||||
memcpy(*ls, l_vec, h_len * sizeof(secp256k1_scalar));
|
||||
memcpy(*cs, c_vec, h_len * sizeof(secp256k1_scalar));
|
||||
memcpy(*gs, gens_vec, (g_len + h_len) * sizeof(secp256k1_ge));
|
||||
}
|
||||
|
||||
/* A complete norm argument. In contrast to secp256k1_bppp_rangeproof_norm_product_prove, this is meant
|
||||
to be used as a standalone norm argument.
|
||||
This is a simple wrapper around secp256k1_bppp_rangeproof_norm_product_prove
|
||||
that also commits to the initial public values used in the protocol. In this case, these public
|
||||
values are commitment.
|
||||
*/
|
||||
static int secp256k1_norm_arg_prove(
|
||||
secp256k1_scratch_space* scratch,
|
||||
unsigned char* proof,
|
||||
size_t *proof_len,
|
||||
const secp256k1_scalar* r,
|
||||
const secp256k1_bppp_generators* gens_vec,
|
||||
const secp256k1_scalar* n_vec,
|
||||
size_t n_vec_len,
|
||||
const secp256k1_scalar* l_vec,
|
||||
size_t l_vec_len,
|
||||
const secp256k1_scalar* c_vec,
|
||||
size_t c_vec_len,
|
||||
const secp256k1_ge* commit
|
||||
) {
|
||||
secp256k1_scalar *ns, *ls, *cs;
|
||||
secp256k1_ge *gs, comm = *commit;
|
||||
size_t scratch_checkpoint;
|
||||
size_t g_len = n_vec_len, h_len = l_vec_len;
|
||||
int res;
|
||||
secp256k1_sha256 transcript;
|
||||
|
||||
scratch_checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
|
||||
|
||||
copy_vectors_into_scratch(scratch, &ns, &ls, &cs, &gs, n_vec, l_vec, c_vec, gens_vec->gens, g_len, h_len);
|
||||
|
||||
/* Commit to the initial public values */
|
||||
secp256k1_norm_arg_commit_initial_data(&transcript, r, gens_vec, g_len, c_vec, c_vec_len, &comm);
|
||||
|
||||
res = secp256k1_bppp_rangeproof_norm_product_prove(
|
||||
ctx,
|
||||
scratch,
|
||||
proof,
|
||||
proof_len,
|
||||
&transcript, /* Transcript hash of the parent protocol */
|
||||
r,
|
||||
gs,
|
||||
gens_vec->n,
|
||||
ns,
|
||||
n_vec_len,
|
||||
ls,
|
||||
l_vec_len,
|
||||
cs,
|
||||
c_vec_len
|
||||
);
|
||||
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Verify the proof */
|
||||
static int secp256k1_norm_arg_verify(
|
||||
secp256k1_scratch_space* scratch,
|
||||
const unsigned char* proof,
|
||||
size_t proof_len,
|
||||
const secp256k1_scalar* r,
|
||||
const secp256k1_bppp_generators* gens_vec,
|
||||
size_t g_len,
|
||||
const secp256k1_scalar* c_vec,
|
||||
size_t c_vec_len,
|
||||
const secp256k1_ge* commit
|
||||
) {
|
||||
secp256k1_ge comm = *commit;
|
||||
int res;
|
||||
secp256k1_sha256 transcript;
|
||||
|
||||
/* Commit to the initial public values */
|
||||
secp256k1_norm_arg_commit_initial_data(&transcript, r, gens_vec, g_len, c_vec, c_vec_len, &comm);
|
||||
|
||||
res = secp256k1_bppp_rangeproof_norm_product_verify(
|
||||
ctx,
|
||||
scratch,
|
||||
proof,
|
||||
proof_len,
|
||||
&transcript,
|
||||
r,
|
||||
gens_vec,
|
||||
g_len,
|
||||
c_vec,
|
||||
c_vec_len,
|
||||
commit
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
void norm_arg_zero(void) {
|
||||
secp256k1_scalar n_vec[64], l_vec[64], c_vec[64];
|
||||
secp256k1_scalar r, q;
|
||||
secp256k1_ge commit;
|
||||
size_t i;
|
||||
secp256k1_scratch *scratch = secp256k1_scratch_space_create(ctx, 1000*10); /* shouldn't need much */
|
||||
unsigned char proof[1000];
|
||||
secp256k1_sha256 transcript;
|
||||
|
||||
random_scalar_order(&r);
|
||||
secp256k1_scalar_sqr(&q, &r);
|
||||
|
||||
/* l is zero vector and n is zero vectors of length 1 each. */
|
||||
{
|
||||
size_t plen = sizeof(proof);
|
||||
unsigned int n_vec_len = 1;
|
||||
unsigned int c_vec_len = 1;
|
||||
secp256k1_bppp_generators *gens = secp256k1_bppp_generators_create(ctx, n_vec_len + c_vec_len);
|
||||
|
||||
secp256k1_scalar_set_int(&n_vec[0], 0);
|
||||
secp256k1_scalar_set_int(&l_vec[0], 0);
|
||||
random_scalar_order(&c_vec[0]);
|
||||
|
||||
secp256k1_sha256_initialize(&transcript); /* No challenges used in n = 1, l = 1, but we set transcript as a good practice*/
|
||||
CHECK(secp256k1_bppp_commit(ctx, scratch, &commit, gens, n_vec, n_vec_len, l_vec, c_vec_len, c_vec, c_vec_len, &q));
|
||||
{
|
||||
secp256k1_scalar *ns, *ls, *cs;
|
||||
secp256k1_ge *gs;
|
||||
size_t scratch_checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
|
||||
copy_vectors_into_scratch(scratch, &ns, &ls, &cs, &gs, n_vec, l_vec, c_vec, gens->gens, n_vec_len, c_vec_len);
|
||||
CHECK(secp256k1_bppp_rangeproof_norm_product_prove(ctx, scratch, proof, &plen, &transcript, &r, gs, gens->n, ns, n_vec_len, ls, c_vec_len, cs, c_vec_len));
|
||||
secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint);
|
||||
}
|
||||
secp256k1_sha256_initialize(&transcript);
|
||||
CHECK(secp256k1_bppp_rangeproof_norm_product_verify(ctx, scratch, proof, plen, &transcript, &r, gens, c_vec_len, c_vec, c_vec_len, &commit));
|
||||
|
||||
secp256k1_bppp_generators_destroy(ctx, gens);
|
||||
}
|
||||
|
||||
/* l is the zero vector and longer than n. This results in one of the
|
||||
* internal commitments X or R to be the point at infinity. */
|
||||
{
|
||||
unsigned int n_vec_len = 1;
|
||||
unsigned int c_vec_len = 2;
|
||||
secp256k1_bppp_generators *gs = secp256k1_bppp_generators_create(ctx, n_vec_len + c_vec_len);
|
||||
size_t plen = sizeof(proof);
|
||||
for (i = 0; i < n_vec_len; i++) {
|
||||
random_scalar_order(&n_vec[i]);
|
||||
}
|
||||
for (i = 0; i < c_vec_len; i++) {
|
||||
secp256k1_scalar_set_int(&l_vec[i], 0);
|
||||
random_scalar_order(&c_vec[i]);
|
||||
}
|
||||
CHECK(secp256k1_bppp_commit(ctx, scratch, &commit, gs, n_vec, n_vec_len, l_vec, c_vec_len, c_vec, c_vec_len, &q));
|
||||
CHECK(!secp256k1_norm_arg_prove(scratch, proof, &plen, &r, gs, n_vec, n_vec_len, l_vec, c_vec_len, c_vec, c_vec_len, &commit));
|
||||
secp256k1_bppp_generators_destroy(ctx, gs);
|
||||
}
|
||||
|
||||
secp256k1_scratch_space_destroy(ctx, scratch);
|
||||
}
|
||||
|
||||
void norm_arg_test(unsigned int n, unsigned int m) {
|
||||
secp256k1_scalar n_vec[64], l_vec[64], c_vec[64];
|
||||
secp256k1_scalar r, q;
|
||||
secp256k1_ge commit;
|
||||
size_t i, plen;
|
||||
int res;
|
||||
secp256k1_bppp_generators *gs = secp256k1_bppp_generators_create(ctx, n + m);
|
||||
secp256k1_scratch *scratch = secp256k1_scratch_space_create(ctx, 1000*1000); /* shouldn't need much */
|
||||
unsigned char proof[1000];
|
||||
plen = 1000;
|
||||
random_scalar_order(&r);
|
||||
secp256k1_scalar_sqr(&q, &r);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
random_scalar_order(&n_vec[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
random_scalar_order(&l_vec[i]);
|
||||
random_scalar_order(&c_vec[i]);
|
||||
}
|
||||
|
||||
res = secp256k1_bppp_commit(ctx, scratch, &commit, gs, n_vec, n, l_vec, m, c_vec, m, &q);
|
||||
CHECK(res == 1);
|
||||
res = secp256k1_norm_arg_prove(scratch, proof, &plen, &r, gs, n_vec, n, l_vec, m, c_vec, m, &commit);
|
||||
CHECK(res == 1);
|
||||
|
||||
res = secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n, c_vec, m, &commit);
|
||||
CHECK(res == 1);
|
||||
|
||||
/* Changing any of last two scalars should break the proof */
|
||||
proof[plen - 1] ^= 1;
|
||||
res = secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n, c_vec, m, &commit);
|
||||
CHECK(res == 0);
|
||||
proof[plen - 1 - 32] ^= 1;
|
||||
res = secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n, c_vec, m, &commit);
|
||||
CHECK(res == 0);
|
||||
|
||||
secp256k1_scratch_space_destroy(ctx, scratch);
|
||||
secp256k1_bppp_generators_destroy(ctx, gs);
|
||||
}
|
||||
|
||||
/* Parses generators from points compressed as pubkeys */
|
||||
secp256k1_bppp_generators* bppp_generators_parse_regular(const unsigned char* data, size_t data_len) {
|
||||
size_t n = data_len / 33;
|
||||
secp256k1_bppp_generators* ret;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(data != NULL);
|
||||
|
||||
if (data_len % 33 != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = (secp256k1_bppp_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ret->n = n;
|
||||
ret->gens = (secp256k1_ge*)checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens));
|
||||
if (ret->gens == NULL) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (n--) {
|
||||
if (!secp256k1_eckey_pubkey_parse(&ret->gens[n], &data[33 * n], 33)) {
|
||||
free(ret->gens);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int norm_arg_verify_vectors_helper(secp256k1_scratch *scratch, const unsigned char *gens, const unsigned char *proof, size_t plen, const unsigned char *r32, size_t n_vec_len, const unsigned char c_vec32[][32], secp256k1_scalar *c_vec, size_t c_vec_len, const unsigned char *commit33) {
|
||||
secp256k1_sha256 transcript;
|
||||
secp256k1_bppp_generators *gs = bppp_generators_parse_regular(gens, 33*(n_vec_len + c_vec_len));
|
||||
secp256k1_scalar r;
|
||||
secp256k1_ge commit;
|
||||
int overflow;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
CHECK(gs != NULL);
|
||||
secp256k1_sha256_initialize(&transcript);
|
||||
|
||||
secp256k1_scalar_set_b32(&r, r32, &overflow);
|
||||
CHECK(!overflow);
|
||||
|
||||
for (i = 0; i < (int)c_vec_len; i++) {
|
||||
secp256k1_scalar_set_b32(&c_vec[i], c_vec32[i], &overflow);
|
||||
CHECK(!overflow);
|
||||
}
|
||||
CHECK(secp256k1_eckey_pubkey_parse(&commit, commit33, 33));
|
||||
ret = secp256k1_bppp_rangeproof_norm_product_verify(ctx, scratch, proof, plen, &transcript, &r, gs, n_vec_len, c_vec, c_vec_len, &commit);
|
||||
|
||||
secp256k1_bppp_generators_destroy(ctx, gs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define IDX_TO_TEST(i) (norm_arg_verify_vectors_helper(scratch, verify_vector_gens, verify_vector_##i##_proof, sizeof(verify_vector_##i##_proof), verify_vector_##i##_r32, verify_vector_##i##_n_vec_len, verify_vector_##i##_c_vec32, verify_vector_##i##_c_vec, sizeof(verify_vector_##i##_c_vec)/sizeof(secp256k1_scalar), verify_vector_##i##_commit33) == verify_vector_##i##_result)
|
||||
|
||||
void norm_arg_verify_vectors(void) {
|
||||
secp256k1_scratch *scratch = secp256k1_scratch_space_create(ctx, 1000*1000); /* shouldn't need much */
|
||||
size_t alloc = scratch->alloc_size;
|
||||
|
||||
CHECK(IDX_TO_TEST(0));
|
||||
CHECK(IDX_TO_TEST(1));
|
||||
CHECK(IDX_TO_TEST(2));
|
||||
CHECK(IDX_TO_TEST(3));
|
||||
CHECK(IDX_TO_TEST(4));
|
||||
CHECK(IDX_TO_TEST(5));
|
||||
CHECK(IDX_TO_TEST(6));
|
||||
CHECK(IDX_TO_TEST(7));
|
||||
CHECK(IDX_TO_TEST(8));
|
||||
|
||||
CHECK(alloc == scratch->alloc_size);
|
||||
secp256k1_scratch_space_destroy(ctx, scratch);
|
||||
}
|
||||
#undef IDX_TO_TEST
|
||||
|
||||
void run_bppp_tests(void) {
|
||||
test_log_exp();
|
||||
test_norm_util_helpers();
|
||||
test_bppp_generators_api();
|
||||
test_bppp_generators_fixed();
|
||||
test_bppp_tagged_hash();
|
||||
|
||||
norm_arg_zero();
|
||||
norm_arg_test(1, 1);
|
||||
norm_arg_test(1, 64);
|
||||
norm_arg_test(64, 1);
|
||||
norm_arg_test(32, 32);
|
||||
norm_arg_test(32, 64);
|
||||
norm_arg_test(64, 32);
|
||||
norm_arg_test(64, 64);
|
||||
norm_arg_verify_vectors();
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user