Get rid of precomputed H tables (Pieter Wuille)
This commit is contained in:
parent
a6dd429dc7
commit
e596d3a389
@ -53,8 +53,6 @@ int main(void) {
|
|||||||
bench_rangeproof_t data;
|
bench_rangeproof_t data;
|
||||||
|
|
||||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||||
secp256k1_pedersen_context_initialize(data.ctx);
|
|
||||||
secp256k1_rangeproof_context_initialize(data.ctx);
|
|
||||||
|
|
||||||
data.min_bits = 32;
|
data.min_bits = 32;
|
||||||
|
|
||||||
|
@ -11,10 +11,6 @@
|
|||||||
#include "modules/rangeproof/borromean_impl.h"
|
#include "modules/rangeproof/borromean_impl.h"
|
||||||
#include "modules/rangeproof/rangeproof_impl.h"
|
#include "modules/rangeproof/rangeproof_impl.h"
|
||||||
|
|
||||||
void secp256k1_pedersen_context_initialize(secp256k1_context* ctx) {
|
|
||||||
secp256k1_pedersen_context_build(&ctx->pedersen_ctx, &ctx->error_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generates a pedersen commitment: *commit = blind * G + value * G2. The commitment is 33 bytes, the blinding factor is 32 bytes.*/
|
/* Generates a pedersen commitment: *commit = blind * G + value * G2. The commitment is 33 bytes, the blinding factor is 32 bytes.*/
|
||||||
int secp256k1_pedersen_commit(const secp256k1_context* ctx, unsigned char *commit, unsigned char *blind, uint64_t value) {
|
int secp256k1_pedersen_commit(const secp256k1_context* ctx, unsigned char *commit, unsigned char *blind, uint64_t value) {
|
||||||
secp256k1_gej rj;
|
secp256k1_gej rj;
|
||||||
@ -25,12 +21,11 @@ int secp256k1_pedersen_commit(const secp256k1_context* ctx, unsigned char *commi
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
ARG_CHECK(ctx != NULL);
|
ARG_CHECK(ctx != NULL);
|
||||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
|
|
||||||
ARG_CHECK(commit != NULL);
|
ARG_CHECK(commit != NULL);
|
||||||
ARG_CHECK(blind != NULL);
|
ARG_CHECK(blind != NULL);
|
||||||
secp256k1_scalar_set_b32(&sec, blind, &overflow);
|
secp256k1_scalar_set_b32(&sec, blind, &overflow);
|
||||||
if (!overflow) {
|
if (!overflow) {
|
||||||
secp256k1_pedersen_ecmult(&ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &rj, &sec, value);
|
secp256k1_pedersen_ecmult(&ctx->ecmult_gen_ctx, &rj, &sec, value);
|
||||||
if (!secp256k1_gej_is_infinity(&rj)) {
|
if (!secp256k1_gej_is_infinity(&rj)) {
|
||||||
secp256k1_ge_set_gej(&r, &rj);
|
secp256k1_ge_set_gej(&r, &rj);
|
||||||
sz = 33;
|
sz = 33;
|
||||||
@ -80,14 +75,13 @@ int secp256k1_pedersen_verify_tally(const secp256k1_context* ctx, const unsigned
|
|||||||
ARG_CHECK(ctx != NULL);
|
ARG_CHECK(ctx != NULL);
|
||||||
ARG_CHECK(!pcnt || (commits != NULL));
|
ARG_CHECK(!pcnt || (commits != NULL));
|
||||||
ARG_CHECK(!ncnt || (ncommits != NULL));
|
ARG_CHECK(!ncnt || (ncommits != NULL));
|
||||||
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
|
|
||||||
secp256k1_gej_set_infinity(&accj);
|
secp256k1_gej_set_infinity(&accj);
|
||||||
if (excess) {
|
if (excess) {
|
||||||
uint64_t ex;
|
uint64_t ex;
|
||||||
int neg;
|
int neg;
|
||||||
/* Take the absolute value, and negate the result if the input was negative. */
|
/* Take the absolute value, and negate the result if the input was negative. */
|
||||||
neg = secp256k1_sign_and_abs64(&ex, excess);
|
neg = secp256k1_sign_and_abs64(&ex, excess);
|
||||||
secp256k1_pedersen_ecmult_small(&ctx->pedersen_ctx, &accj, ex);
|
secp256k1_pedersen_ecmult_small(&accj, ex);
|
||||||
if (neg) {
|
if (neg) {
|
||||||
secp256k1_gej_neg(&accj, &accj);
|
secp256k1_gej_neg(&accj, &accj);
|
||||||
}
|
}
|
||||||
@ -108,10 +102,6 @@ int secp256k1_pedersen_verify_tally(const secp256k1_context* ctx, const unsigned
|
|||||||
return secp256k1_gej_is_infinity(&accj);
|
return secp256k1_gej_is_infinity(&accj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void secp256k1_rangeproof_context_initialize(secp256k1_context* ctx) {
|
|
||||||
secp256k1_rangeproof_context_build(&ctx->rangeproof_ctx, &ctx->error_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
int secp256k1_rangeproof_info(const secp256k1_context* ctx, int *exp, int *mantissa,
|
int secp256k1_rangeproof_info(const secp256k1_context* ctx, int *exp, int *mantissa,
|
||||||
uint64_t *min_value, uint64_t *max_value, const unsigned char *proof, int plen) {
|
uint64_t *min_value, uint64_t *max_value, const unsigned char *proof, int plen) {
|
||||||
int offset;
|
int offset;
|
||||||
@ -137,9 +127,7 @@ int secp256k1_rangeproof_rewind(const secp256k1_context* ctx,
|
|||||||
ARG_CHECK(max_value != NULL);
|
ARG_CHECK(max_value != NULL);
|
||||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
|
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx,
|
||||||
ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx));
|
|
||||||
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx,
|
|
||||||
blind_out, value_out, message_out, outlen, nonce, min_value, max_value, commit, proof, plen);
|
blind_out, value_out, message_out, outlen, nonce, min_value, max_value, commit, proof, plen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,9 +139,7 @@ int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_valu
|
|||||||
ARG_CHECK(min_value != NULL);
|
ARG_CHECK(min_value != NULL);
|
||||||
ARG_CHECK(max_value != NULL);
|
ARG_CHECK(max_value != NULL);
|
||||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||||
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
|
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, NULL,
|
||||||
ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx));
|
|
||||||
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, NULL, &ctx->pedersen_ctx, &ctx->rangeproof_ctx,
|
|
||||||
NULL, NULL, NULL, NULL, NULL, min_value, max_value, commit, proof, plen);
|
NULL, NULL, NULL, NULL, NULL, min_value, max_value, commit, proof, plen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,9 +153,7 @@ int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof
|
|||||||
ARG_CHECK(nonce != NULL);
|
ARG_CHECK(nonce != NULL);
|
||||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->pedersen_ctx));
|
return secp256k1_rangeproof_sign_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx,
|
||||||
ARG_CHECK(secp256k1_rangeproof_context_is_built(&ctx->rangeproof_ctx));
|
|
||||||
return secp256k1_rangeproof_sign_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &ctx->pedersen_ctx, &ctx->rangeproof_ctx,
|
|
||||||
proof, plen, min_value, commit, blind, nonce, exp, min_bits, value);
|
proof, plen, min_value, commit, blind, nonce, exp, min_bits, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,23 +12,10 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
secp256k1_ge_storage (*prec)[16][16]; /* prec[j][i] = 16^j * i * G + U_i */
|
|
||||||
} secp256k1_pedersen_context;
|
|
||||||
|
|
||||||
static void secp256k1_pedersen_context_init(secp256k1_pedersen_context* ctx);
|
|
||||||
static void secp256k1_pedersen_context_build(secp256k1_pedersen_context* ctx, const secp256k1_callback* cb);
|
|
||||||
static void secp256k1_pedersen_context_clone(secp256k1_pedersen_context *dst,
|
|
||||||
const secp256k1_pedersen_context* src, const secp256k1_callback* cb);
|
|
||||||
static void secp256k1_pedersen_context_clear(secp256k1_pedersen_context* ctx);
|
|
||||||
|
|
||||||
static int secp256k1_pedersen_context_is_built(const secp256k1_pedersen_context* ctx);
|
|
||||||
|
|
||||||
/** Multiply a small number with the generator: r = gn*G2 */
|
/** Multiply a small number with the generator: r = gn*G2 */
|
||||||
static void secp256k1_pedersen_ecmult_small(const secp256k1_pedersen_context *ctx, secp256k1_gej *r, uint64_t gn);
|
static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn);
|
||||||
|
|
||||||
/* sec * G + value * G2. */
|
/* sec * G + value * G2. */
|
||||||
static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
|
static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value);
|
||||||
const secp256k1_pedersen_context *pedersen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,117 +20,32 @@ static const secp256k1_ge secp256k1_ge_const_g2 = SECP256K1_GE_CONST(
|
|||||||
0x36dac28aUL, 0xf1766968UL, 0xc30c2313UL, 0xf3a38904UL
|
0x36dac28aUL, 0xf1766968UL, 0xc30c2313UL, 0xf3a38904UL
|
||||||
);
|
);
|
||||||
|
|
||||||
static void secp256k1_pedersen_context_init(secp256k1_pedersen_context *ctx) {
|
static void secp256k1_pedersen_scalar_set_u64(secp256k1_scalar *sec, uint64_t value) {
|
||||||
ctx->prec = NULL;
|
unsigned char data[32];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 24; i++) {
|
||||||
|
data[i] = 0;
|
||||||
|
}
|
||||||
|
for (; i < 32; i++) {
|
||||||
|
data[i] = value >> 56;
|
||||||
|
value <<= 8;
|
||||||
|
}
|
||||||
|
secp256k1_scalar_set_b32(sec, data, NULL);
|
||||||
|
memset(data, 0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_pedersen_context_build(secp256k1_pedersen_context *ctx, const secp256k1_callback *cb) {
|
static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn) {
|
||||||
secp256k1_ge prec[256];
|
secp256k1_scalar s;
|
||||||
secp256k1_gej gj;
|
secp256k1_pedersen_scalar_set_u64(&s, gn);
|
||||||
secp256k1_gej nums_gej;
|
secp256k1_ecmult_const(r, &secp256k1_ge_const_g2, &s, 64);
|
||||||
int i, j;
|
secp256k1_scalar_clear(&s);
|
||||||
|
|
||||||
if (ctx->prec != NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->prec = (secp256k1_ge_storage (*)[16][16])checked_malloc(cb, sizeof(*ctx->prec));
|
|
||||||
|
|
||||||
/* get the generator */
|
|
||||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g2);
|
|
||||||
|
|
||||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
|
|
||||||
{
|
|
||||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
|
|
||||||
secp256k1_fe nums_x;
|
|
||||||
secp256k1_ge nums_ge;
|
|
||||||
VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32));
|
|
||||||
VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0));
|
|
||||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
|
|
||||||
/* Add G to make the bits in x uniformly distributed. */
|
|
||||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g2, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute prec. */
|
|
||||||
{
|
|
||||||
secp256k1_gej precj[256]; /* Jacobian versions of prec. */
|
|
||||||
secp256k1_gej gbase;
|
|
||||||
secp256k1_gej numsbase;
|
|
||||||
gbase = gj; /* 16^j * G */
|
|
||||||
numsbase = nums_gej; /* 2^j * nums. */
|
|
||||||
for (j = 0; j < 16; j++) {
|
|
||||||
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */
|
|
||||||
precj[j*16] = numsbase;
|
|
||||||
for (i = 1; i < 16; i++) {
|
|
||||||
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL);
|
|
||||||
}
|
|
||||||
/* Multiply gbase by 16. */
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
secp256k1_gej_double_var(&gbase, &gbase, NULL);
|
|
||||||
}
|
|
||||||
/* Multiply numbase by 2. */
|
|
||||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
|
|
||||||
if (j == 14) {
|
|
||||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
|
|
||||||
secp256k1_gej_neg(&numsbase, &numsbase);
|
|
||||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
secp256k1_ge_set_all_gej_var(prec, precj, 256, cb);
|
|
||||||
}
|
|
||||||
for (j = 0; j < 16; j++) {
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int secp256k1_pedersen_context_is_built(const secp256k1_pedersen_context* ctx) {
|
|
||||||
return ctx->prec != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void secp256k1_pedersen_context_clone(secp256k1_pedersen_context *dst,
|
|
||||||
const secp256k1_pedersen_context *src, const secp256k1_callback *cb) {
|
|
||||||
if (src->prec == NULL) {
|
|
||||||
dst->prec = NULL;
|
|
||||||
} else {
|
|
||||||
dst->prec = (secp256k1_ge_storage (*)[16][16])checked_malloc(cb, sizeof(*dst->prec));
|
|
||||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void secp256k1_pedersen_context_clear(secp256k1_pedersen_context *ctx) {
|
|
||||||
free(ctx->prec);
|
|
||||||
ctx->prec = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Version of secp256k1_ecmult_gen using the second generator and working only on numbers in the range [0 .. 2^64). */
|
|
||||||
static void secp256k1_pedersen_ecmult_small(const secp256k1_pedersen_context *ctx, secp256k1_gej *r, uint64_t gn) {
|
|
||||||
secp256k1_ge add;
|
|
||||||
secp256k1_ge_storage adds;
|
|
||||||
int bits;
|
|
||||||
int i, j;
|
|
||||||
memset(&adds, 0, sizeof(adds));
|
|
||||||
secp256k1_gej_set_infinity(r);
|
|
||||||
add.infinity = 0;
|
|
||||||
for (j = 0; j < 16; j++) {
|
|
||||||
bits = (gn >> (j * 4)) & 15;
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
|
|
||||||
}
|
|
||||||
secp256k1_ge_from_storage(&add, &adds);
|
|
||||||
secp256k1_gej_add_ge(r, r, &add);
|
|
||||||
}
|
|
||||||
bits = 0;
|
|
||||||
secp256k1_ge_clear(&add);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sec * G + value * G2. */
|
/* sec * G + value * G2. */
|
||||||
SECP256K1_INLINE static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
|
SECP256K1_INLINE static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value) {
|
||||||
const secp256k1_pedersen_context *pedersen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value) {
|
|
||||||
secp256k1_gej vj;
|
secp256k1_gej vj;
|
||||||
secp256k1_ecmult_gen(ecmult_gen_ctx, rj, sec);
|
secp256k1_ecmult_gen(ecmult_gen_ctx, rj, sec);
|
||||||
secp256k1_pedersen_ecmult_small(pedersen_ctx, &vj, value);
|
secp256k1_pedersen_ecmult_small(&vj, value);
|
||||||
/* FIXME: constant time. */
|
/* FIXME: constant time. */
|
||||||
secp256k1_gej_add_var(rj, rj, &vj, NULL);
|
secp256k1_gej_add_var(rj, rj, &vj, NULL);
|
||||||
secp256k1_gej_clear(&vj);
|
secp256k1_gej_clear(&vj);
|
||||||
|
@ -10,21 +10,8 @@
|
|||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
secp256k1_ge_storage (*prec)[1005];
|
|
||||||
} secp256k1_rangeproof_context;
|
|
||||||
|
|
||||||
|
|
||||||
static void secp256k1_rangeproof_context_init(secp256k1_rangeproof_context* ctx);
|
|
||||||
static void secp256k1_rangeproof_context_build(secp256k1_rangeproof_context* ctx, const secp256k1_callback* cb);
|
|
||||||
static void secp256k1_rangeproof_context_clone(secp256k1_rangeproof_context *dst,
|
|
||||||
const secp256k1_rangeproof_context* src, const secp256k1_callback* cb);
|
|
||||||
static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context* ctx);
|
|
||||||
static int secp256k1_rangeproof_context_is_built(const secp256k1_rangeproof_context* ctx);
|
|
||||||
|
|
||||||
static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx,
|
static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx,
|
||||||
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
|
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
|
||||||
const secp256k1_pedersen_context* pedersen_ctx, const secp256k1_rangeproof_context* rangeproof_ctx,
|
|
||||||
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce,
|
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce,
|
||||||
uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen);
|
uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen);
|
||||||
|
|
||||||
|
@ -15,107 +15,9 @@
|
|||||||
#include "modules/rangeproof/pedersen.h"
|
#include "modules/rangeproof/pedersen.h"
|
||||||
#include "modules/rangeproof/borromean.h"
|
#include "modules/rangeproof/borromean.h"
|
||||||
|
|
||||||
static const int secp256k1_rangeproof_offsets[20] = {
|
SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(secp256k1_gej *pubs,
|
||||||
0, 96, 189, 276, 360, 438, 510, 579, 642,
|
|
||||||
699, 753, 801, 843, 882, 915, 942, 966, 984,
|
|
||||||
996, 1005,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void secp256k1_rangeproof_context_init(secp256k1_rangeproof_context *ctx) {
|
|
||||||
ctx->prec = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void secp256k1_rangeproof_context_build(secp256k1_rangeproof_context *ctx, const secp256k1_callback* cb) {
|
|
||||||
secp256k1_ge *prec;
|
|
||||||
secp256k1_gej *precj;
|
|
||||||
secp256k1_gej gj;
|
|
||||||
secp256k1_gej one;
|
|
||||||
int i, pos;
|
|
||||||
|
|
||||||
if (ctx->prec != NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
precj = (secp256k1_gej (*))checked_malloc(cb, sizeof(*precj) * 1005);
|
|
||||||
if (precj == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
prec = (secp256k1_ge (*))checked_malloc(cb, sizeof(*prec) * 1005);
|
|
||||||
if (prec == NULL) {
|
|
||||||
free(precj);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the generator */
|
|
||||||
secp256k1_gej_set_ge(&one, &secp256k1_ge_const_g2);
|
|
||||||
secp256k1_gej_neg(&one, &one);
|
|
||||||
|
|
||||||
/* compute prec. */
|
|
||||||
pos = 0;
|
|
||||||
for (i = 0; i < 19; i++) {
|
|
||||||
int pmax;
|
|
||||||
pmax = secp256k1_rangeproof_offsets[i + 1];
|
|
||||||
gj = one;
|
|
||||||
while (pos < pmax) {
|
|
||||||
precj[pos] = gj;
|
|
||||||
pos++;
|
|
||||||
secp256k1_gej_double_var(&precj[pos], &gj, NULL);
|
|
||||||
pos++;
|
|
||||||
secp256k1_gej_add_var(&precj[pos], &precj[pos - 1], &gj, NULL);
|
|
||||||
pos++;
|
|
||||||
if (pos < pmax - 1) {
|
|
||||||
secp256k1_gej_double_var(&gj, &precj[pos - 2], NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i < 18) {
|
|
||||||
secp256k1_gej_double_var(&gj, &one, NULL);
|
|
||||||
one = gj;
|
|
||||||
secp256k1_gej_double_var(&gj, &gj, NULL);
|
|
||||||
secp256k1_gej_double_var(&gj, &gj, NULL);
|
|
||||||
secp256k1_gej_add_var(&one, &one, &gj, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VERIFY_CHECK(pos == 1005);
|
|
||||||
secp256k1_ge_set_all_gej_var(prec, precj, 1005, cb);
|
|
||||||
|
|
||||||
free(precj);
|
|
||||||
|
|
||||||
ctx->prec = (secp256k1_ge_storage (*)[1005])checked_malloc(cb, sizeof(*ctx->prec));
|
|
||||||
if (ctx->prec == NULL) {
|
|
||||||
free(prec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 1005; i++) {
|
|
||||||
secp256k1_ge_to_storage(&(*ctx->prec)[i], &prec[i]);
|
|
||||||
}
|
|
||||||
free(prec);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int secp256k1_rangeproof_context_is_built(const secp256k1_rangeproof_context* ctx) {
|
|
||||||
return ctx->prec != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void secp256k1_rangeproof_context_clone(secp256k1_rangeproof_context *dst,
|
|
||||||
const secp256k1_rangeproof_context *src, const secp256k1_callback* cb) {
|
|
||||||
if (src->prec == NULL) {
|
|
||||||
dst->prec = NULL;
|
|
||||||
} else {
|
|
||||||
dst->prec = (secp256k1_ge_storage (*)[1005])checked_malloc(cb, sizeof(*dst->prec));
|
|
||||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void secp256k1_rangeproof_context_clear(secp256k1_rangeproof_context *ctx) {
|
|
||||||
free(ctx->prec);
|
|
||||||
ctx->prec = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(const secp256k1_rangeproof_context *ctx, secp256k1_gej *pubs,
|
|
||||||
int exp, int *rsizes, int rings) {
|
int exp, int *rsizes, int rings) {
|
||||||
secp256k1_ge ge;
|
secp256k1_gej base;
|
||||||
secp256k1_ge_storage *basis;
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
int npub;
|
int npub;
|
||||||
@ -123,12 +25,24 @@ SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(const secp256k1_ran
|
|||||||
if (exp < 0) {
|
if (exp < 0) {
|
||||||
exp = 0;
|
exp = 0;
|
||||||
}
|
}
|
||||||
basis = &(*ctx->prec)[secp256k1_rangeproof_offsets[exp]];
|
secp256k1_gej_set_ge(&base, &secp256k1_ge_const_g2);
|
||||||
|
secp256k1_gej_neg(&base, &base);
|
||||||
|
while (exp--) {
|
||||||
|
/* Multiplication by 10 */
|
||||||
|
secp256k1_gej tmp;
|
||||||
|
secp256k1_gej_double_var(&tmp, &base, NULL);
|
||||||
|
secp256k1_gej_double_var(&base, &tmp, NULL);
|
||||||
|
secp256k1_gej_double_var(&base, &base, NULL);
|
||||||
|
secp256k1_gej_add_var(&base, &base, &tmp, NULL);
|
||||||
|
}
|
||||||
npub = 0;
|
npub = 0;
|
||||||
for (i = 0; i < rings; i++) {
|
for (i = 0; i < rings; i++) {
|
||||||
for (j = 1; j < rsizes[i]; j++) {
|
for (j = 1; j < rsizes[i]; j++) {
|
||||||
secp256k1_ge_from_storage(&ge, &basis[i * 3 + j - 1]);
|
secp256k1_gej_add_var(&pubs[npub + j], &pubs[npub + j - 1], &base, NULL);
|
||||||
secp256k1_gej_add_ge_var(&pubs[npub + j], &pubs[npub], &ge, NULL);
|
}
|
||||||
|
if (i < rings - 1) {
|
||||||
|
secp256k1_gej_double_var(&base, &base, NULL);
|
||||||
|
secp256k1_gej_double_var(&base, &base, NULL);
|
||||||
}
|
}
|
||||||
npub += rsizes[i];
|
npub += rsizes[i];
|
||||||
}
|
}
|
||||||
@ -264,8 +178,8 @@ SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, int *rings,
|
|||||||
|
|
||||||
/* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */
|
/* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */
|
||||||
SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_context* ecmult_ctx,
|
SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_context* ecmult_ctx,
|
||||||
const secp256k1_ecmult_gen_context* ecmult_gen_ctx, const secp256k1_pedersen_context* pedersen_ctx,
|
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
|
||||||
const secp256k1_rangeproof_context* rangeproof_ctx, unsigned char *proof, int *plen, uint64_t min_value,
|
unsigned char *proof, int *plen, uint64_t min_value,
|
||||||
const unsigned char *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value){
|
const unsigned char *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value){
|
||||||
secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */
|
secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */
|
||||||
secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */
|
secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */
|
||||||
@ -357,7 +271,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
|
|||||||
npub = 0;
|
npub = 0;
|
||||||
for (i = 0; i < rings; i++) {
|
for (i = 0; i < rings; i++) {
|
||||||
/*OPT: Use the precomputed gen2 basis?*/
|
/*OPT: Use the precomputed gen2 basis?*/
|
||||||
secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &pubs[npub], &sec[i], ((uint64_t)secidx[i] * scale) << (i*2));
|
secp256k1_pedersen_ecmult(ecmult_gen_ctx, &pubs[npub], &sec[i], ((uint64_t)secidx[i] * scale) << (i*2));
|
||||||
if (secp256k1_gej_is_infinity(&pubs[npub])) {
|
if (secp256k1_gej_is_infinity(&pubs[npub])) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -376,7 +290,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
|
|||||||
}
|
}
|
||||||
npub += rsizes[i];
|
npub += rsizes[i];
|
||||||
}
|
}
|
||||||
secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings);
|
secp256k1_rangeproof_pub_expand(pubs, exp, rsizes, rings);
|
||||||
secp256k1_sha256_finalize(&sha256_m, tmp);
|
secp256k1_sha256_finalize(&sha256_m, tmp);
|
||||||
if (!secp256k1_borromean_sign(ecmult_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) {
|
if (!secp256k1_borromean_sign(ecmult_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -596,7 +510,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_getheader_impl(int *offset, int
|
|||||||
/* Verifies range proof (len plen) for 33-byte commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success.*/
|
/* Verifies range proof (len plen) for 33-byte commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success.*/
|
||||||
SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx,
|
SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx,
|
||||||
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
|
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
|
||||||
const secp256k1_pedersen_context* pedersen_ctx, const secp256k1_rangeproof_context* rangeproof_ctx,
|
|
||||||
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce,
|
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, int *outlen, const unsigned char *nonce,
|
||||||
uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen) {
|
uint64_t *min_value, uint64_t *max_value, const unsigned char *commit, const unsigned char *proof, int plen) {
|
||||||
secp256k1_gej accj;
|
secp256k1_gej accj;
|
||||||
@ -660,7 +573,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm
|
|||||||
npub = 0;
|
npub = 0;
|
||||||
secp256k1_gej_set_infinity(&accj);
|
secp256k1_gej_set_infinity(&accj);
|
||||||
if (*min_value) {
|
if (*min_value) {
|
||||||
secp256k1_pedersen_ecmult_small(pedersen_ctx, &accj, *min_value);
|
secp256k1_pedersen_ecmult_small(&accj, *min_value);
|
||||||
}
|
}
|
||||||
for(i = 0; i < rings - 1; i++) {
|
for(i = 0; i < rings - 1; i++) {
|
||||||
memcpy(&m[1], &proof[offset], 32);
|
memcpy(&m[1], &proof[offset], 32);
|
||||||
@ -682,7 +595,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm
|
|||||||
if (secp256k1_gej_is_infinity(&pubs[npub])) {
|
if (secp256k1_gej_is_infinity(&pubs[npub])) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
secp256k1_rangeproof_pub_expand(rangeproof_ctx, pubs, exp, rsizes, rings);
|
secp256k1_rangeproof_pub_expand(pubs, exp, rsizes, rings);
|
||||||
npub += rsizes[rings - 1];
|
npub += rsizes[rings - 1];
|
||||||
e0 = &proof[offset];
|
e0 = &proof[offset];
|
||||||
offset += 32;
|
offset += 32;
|
||||||
@ -713,7 +626,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm
|
|||||||
/* Unwind apparently successful, see if the commitment can be reconstructed. */
|
/* Unwind apparently successful, see if the commitment can be reconstructed. */
|
||||||
/* FIXME: should check vv is in the mantissa's range. */
|
/* FIXME: should check vv is in the mantissa's range. */
|
||||||
vv = (vv * scale) + *min_value;
|
vv = (vv * scale) + *min_value;
|
||||||
secp256k1_pedersen_ecmult(ecmult_gen_ctx, pedersen_ctx, &accj, &blind, vv);
|
secp256k1_pedersen_ecmult(ecmult_gen_ctx, &accj, &blind, vv);
|
||||||
if (secp256k1_gej_is_infinity(&accj)) {
|
if (secp256k1_gej_is_infinity(&accj)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -267,8 +267,6 @@ void test_rangeproof(void) {
|
|||||||
|
|
||||||
void run_rangeproof_tests(void) {
|
void run_rangeproof_tests(void) {
|
||||||
int i;
|
int i;
|
||||||
secp256k1_pedersen_context_initialize(ctx);
|
|
||||||
secp256k1_rangeproof_context_initialize(ctx);
|
|
||||||
for (i = 0; i < 10*count; i++) {
|
for (i = 0; i < 10*count; i++) {
|
||||||
test_pedersen();
|
test_pedersen();
|
||||||
}
|
}
|
||||||
|
@ -57,10 +57,6 @@ static const secp256k1_callback default_error_callback = {
|
|||||||
struct secp256k1_context_struct {
|
struct secp256k1_context_struct {
|
||||||
secp256k1_ecmult_context ecmult_ctx;
|
secp256k1_ecmult_context ecmult_ctx;
|
||||||
secp256k1_ecmult_gen_context ecmult_gen_ctx;
|
secp256k1_ecmult_gen_context ecmult_gen_ctx;
|
||||||
#ifdef ENABLE_MODULE_RANGEPROOF
|
|
||||||
secp256k1_pedersen_context pedersen_ctx;
|
|
||||||
secp256k1_rangeproof_context rangeproof_ctx;
|
|
||||||
#endif
|
|
||||||
secp256k1_callback illegal_callback;
|
secp256k1_callback illegal_callback;
|
||||||
secp256k1_callback error_callback;
|
secp256k1_callback error_callback;
|
||||||
};
|
};
|
||||||
@ -79,10 +75,6 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
|||||||
|
|
||||||
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
|
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
|
||||||
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
||||||
#ifdef ENABLE_MODULE_RANGEPROOF
|
|
||||||
secp256k1_pedersen_context_init(&ret->pedersen_ctx);
|
|
||||||
secp256k1_rangeproof_context_init(&ret->rangeproof_ctx);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
||||||
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback);
|
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback);
|
||||||
@ -100,10 +92,6 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
|
|||||||
ret->error_callback = ctx->error_callback;
|
ret->error_callback = ctx->error_callback;
|
||||||
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback);
|
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback);
|
||||||
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback);
|
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback);
|
||||||
#ifdef ENABLE_MODULE_RANGEPROOF
|
|
||||||
secp256k1_pedersen_context_clone(&ret->pedersen_ctx, &ctx->pedersen_ctx, &ctx->error_callback);
|
|
||||||
secp256k1_rangeproof_context_clone(&ret->rangeproof_ctx, &ctx->rangeproof_ctx, &ctx->error_callback);
|
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,10 +99,6 @@ void secp256k1_context_destroy(secp256k1_context* ctx) {
|
|||||||
if (ctx != NULL) {
|
if (ctx != NULL) {
|
||||||
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
|
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
|
||||||
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
||||||
#ifdef ENABLE_MODULE_RANGEPROOF
|
|
||||||
secp256k1_pedersen_context_clear(&ctx->pedersen_ctx);
|
|
||||||
secp256k1_rangeproof_context_clear(&ctx->rangeproof_ctx);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user