awesome-blockchain/src/ConfidentialTx/crypto/secp256k1/libsecp256k1/src/modules/bulletproofs/main_impl.h

241 lines
10 KiB
C

/**********************************************************************
* Copyright (c) 2018 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_BULLETPROOF_MAIN_IMPL
#define SECP256K1_MODULE_BULLETPROOF_MAIN_IMPL
#include "group.h"
#include "scalar.h"
#include "modules/commitment/main_impl.h"
struct secp256k1_bulletproof_generators {
size_t n;
/* `G_i`, `H_i` generators, `n` each of them which are generated when creating this struct */
secp256k1_ge *gens;
/* `H` "alternate" generator, used in Pedersen commitments. Passed in by caller to
* `secp256k1_bulletproof_generators_create`; stored in this structure to allow consistent
* generators between functions using `secp256k1_bulletproof_generators` and functions
* using the Pedersen commitment module. */
secp256k1_ge *blinding_gen;
};
#include "modules/bulletproofs/inner_product_impl.h"
#include "modules/bulletproofs/rangeproof_impl.h"
#include "modules/bulletproofs/util.h"
// This is out setup
secp256k1_bulletproof_generators *secp256k1_bulletproof_generators_create(const secp256k1_context *ctx, const secp256k1_generator *blinding_gen, size_t n) {
secp256k1_bulletproof_generators *ret;
secp256k1_rfc6979_hmac_sha256 rng;
unsigned char seed[64];
secp256k1_gej precompj;
size_t i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(blinding_gen != NULL);
ret = (secp256k1_bulletproof_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret));
if (ret == NULL) {
return NULL;
}
ret->gens = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (n + 1) * sizeof(*ret->gens));
if (ret->gens == NULL) {
free(ret);
return NULL;
}
ret->blinding_gen = &ret->gens[n];
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++) {
unsigned char tmp[32] = { 0 };
secp256k1_generator gen;
secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32);
CHECK(secp256k1_generator_generate(ctx, &gen, tmp));
secp256k1_generator_load(&ret->gens[i], &gen);
secp256k1_gej_set_ge(&precompj, &ret->gens[i]);
}
secp256k1_generator_load(&ret->blinding_gen[0], blinding_gen);
secp256k1_gej_set_ge(&precompj, &ret->blinding_gen[0]);
return ret;
}
void secp256k1_bulletproof_generators_destroy(const secp256k1_context* ctx, secp256k1_bulletproof_generators *gens) {
(void) ctx;
if (gens != NULL) {
free(gens->gens);
free(gens);
}
}
int secp256k1_bulletproof_rangeproof_verify(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, const secp256k1_bulletproof_generators *gens, const unsigned char *proof, size_t plen,
const uint64_t *min_value, const secp256k1_pedersen_commitment* commit, size_t n_commits, size_t nbits, const secp256k1_generator *value_gen, const unsigned char *extra_commit, size_t extra_commit_len) {
int ret;
size_t i;
secp256k1_ge *commitp;
secp256k1_ge value_genp;
const secp256k1_ge *commitp_ptr;
const uint64_t *minvalue_ptr;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(scratch != NULL);
ARG_CHECK(gens != NULL);
ARG_CHECK(gens->n >= 2 * nbits * n_commits);
ARG_CHECK(proof != NULL);
ARG_CHECK(commit != NULL);
ARG_CHECK(n_commits > 0);
ARG_CHECK(nbits > 0);
ARG_CHECK(nbits <= 64);
ARG_CHECK(value_gen != NULL);
ARG_CHECK(extra_commit != NULL || extra_commit_len == 0);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
if (!secp256k1_scratch_allocate_frame(scratch, 2 * n_commits * sizeof(secp256k1_ge), 1)) {
return 0;
}
commitp = (secp256k1_ge *)secp256k1_scratch_alloc(scratch, n_commits * sizeof(secp256k1_ge));
for (i = 0; i < n_commits; i++) {
secp256k1_pedersen_commitment_load(&commitp[i], &commit[i]);
}
secp256k1_generator_load(&value_genp, value_gen);
commitp_ptr = commitp;
minvalue_ptr = min_value;
ret = secp256k1_bulletproof_rangeproof_verify_impl(&ctx->ecmult_ctx, scratch, &proof, 1, plen, nbits, &minvalue_ptr, &commitp_ptr, n_commits, &value_genp, gens, &extra_commit, &extra_commit_len);
secp256k1_scratch_deallocate_frame(scratch);
return ret;
}
int secp256k1_bulletproof_rangeproof_verify_multi(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, const secp256k1_bulletproof_generators *gens, const unsigned char* const* proof, size_t n_proofs, size_t plen, const uint64_t* const* min_value, const secp256k1_pedersen_commitment* const* commit, size_t n_commits, size_t nbits, const secp256k1_generator *value_gen, const unsigned char* const* extra_commit, size_t *extra_commit_len) {
int ret;
secp256k1_ge **commitp;
secp256k1_ge *value_genp;
size_t i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(scratch != NULL);
ARG_CHECK(gens != NULL);
ARG_CHECK(gens->n >= 2 * nbits * n_commits);
ARG_CHECK(commit != NULL);
ARG_CHECK(proof != NULL);
ARG_CHECK(n_proofs > 0);
ARG_CHECK(n_commits > 0);
ARG_CHECK(nbits > 0);
ARG_CHECK(nbits <= 64);
ARG_CHECK(value_gen != NULL);
ARG_CHECK((extra_commit_len == NULL) == (extra_commit == NULL));
if (extra_commit != NULL) {
for (i = 0; i < n_proofs; i++) {
ARG_CHECK(extra_commit[i] != NULL || extra_commit_len[i] == 0);
}
}
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
if (!secp256k1_scratch_allocate_frame(scratch, n_proofs * (sizeof(*value_genp) + sizeof(*commitp) + n_commits * sizeof(**commitp)), 1 + n_proofs)) {
return 0;
}
commitp = (secp256k1_ge **)secp256k1_scratch_alloc(scratch, n_proofs * sizeof(*commitp));
value_genp = (secp256k1_ge *)secp256k1_scratch_alloc(scratch, n_proofs * sizeof(*value_genp));
for (i = 0; i < n_proofs; i++) {
size_t j;
commitp[i] = (secp256k1_ge *)secp256k1_scratch_alloc(scratch, n_commits * sizeof(*commitp[i]));
for (j = 0; j < n_commits; j++) {
secp256k1_pedersen_commitment_load(&commitp[i][j], &commit[i][j]);
}
secp256k1_generator_load(&value_genp[i], &value_gen[i]);
}
ret = secp256k1_bulletproof_rangeproof_verify_impl(&ctx->ecmult_ctx, scratch, proof, n_proofs, plen, nbits, min_value, (const secp256k1_ge **) commitp, n_commits, value_genp, gens, extra_commit, extra_commit_len);
secp256k1_scratch_deallocate_frame(scratch);
return ret;
}
int secp256k1_bulletproof_rangeproof_rewind(const secp256k1_context* ctx, const secp256k1_bulletproof_generators *gens, uint64_t *value, unsigned char *blind, const unsigned char *proof, size_t plen, uint64_t min_value, const secp256k1_pedersen_commitment* commit, const secp256k1_generator *value_gen, const unsigned char *nonce, const unsigned char *extra_commit, size_t extra_commit_len) {
secp256k1_scalar blinds;
int ret;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(value != NULL);
ARG_CHECK(blind != NULL);
ARG_CHECK(gens != NULL);
ARG_CHECK(proof != NULL);
ARG_CHECK(commit != NULL);
ARG_CHECK(value_gen != NULL);
ARG_CHECK(nonce != NULL);
ARG_CHECK(extra_commit != NULL || extra_commit_len == 0);
ret = secp256k1_bulletproof_rangeproof_rewind_impl(value, &blinds, proof, plen, min_value, commit, value_gen, gens->blinding_gen, nonce, extra_commit, extra_commit_len);
if (ret == 1) {
secp256k1_scalar_get_b32(blind, &blinds);
}
return ret;
}
// Put everything inside a struct, so that we can receive as input this struct and the commitment to the value
int secp256k1_bulletproof_rangeproof_prove(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, const secp256k1_bulletproof_generators *gens, unsigned char *proof, size_t *plen, const uint64_t *value, const uint64_t *min_value, const unsigned char* const* blind, size_t n_commits, const secp256k1_generator *value_gen, size_t nbits, const unsigned char *nonce, const unsigned char *extra_commit, size_t extra_commit_len) {
int ret;
secp256k1_ge *commitp;
secp256k1_scalar *blinds;
secp256k1_ge value_genp;
size_t i;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(scratch != NULL);
ARG_CHECK(gens != NULL);
ARG_CHECK(gens->n >= 2 * nbits * n_commits);
ARG_CHECK(proof != NULL);
ARG_CHECK(plen != NULL);
ARG_CHECK(value != NULL);
ARG_CHECK(blind != NULL);
ARG_CHECK(value_gen != NULL);
ARG_CHECK(nonce != NULL);
ARG_CHECK(n_commits > 0 && n_commits);
ARG_CHECK(nbits <= 64);
if (nbits < 64) {
for (i = 0; i < n_commits; i++) {
ARG_CHECK(value[i] < (1ull << nbits));
ARG_CHECK(blind[i] != NULL);
}
}
ARG_CHECK(extra_commit != NULL || extra_commit_len == 0);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
if (!secp256k1_scratch_allocate_frame(scratch, n_commits * (sizeof(*commitp) + sizeof(*blinds)), 2)) {
return 0;
}
commitp = (secp256k1_ge *)secp256k1_scratch_alloc(scratch, n_commits * sizeof(*commitp));
blinds = (secp256k1_scalar *)secp256k1_scratch_alloc(scratch, n_commits * sizeof(*blinds));
secp256k1_generator_load(&value_genp, value_gen);
for (i = 0; i < n_commits; i++) {
int overflow;
secp256k1_gej commitj;
secp256k1_scalar_set_b32(&blinds[i], blind[i], &overflow);
if (overflow || secp256k1_scalar_is_zero(&blinds[i])) {
return 0;
}
secp256k1_pedersen_ecmult(&commitj, &blinds[i], value[i], &value_genp, &gens->blinding_gen[0]);
secp256k1_ge_set_gej(&commitp[i], &commitj);
}
ret = secp256k1_bulletproof_rangeproof_prove_impl(&ctx->ecmult_ctx, scratch, proof, plen, nbits, value, min_value, blinds, commitp, n_commits, &value_genp, gens, nonce, extra_commit, extra_commit_len);
secp256k1_scratch_deallocate_frame(scratch);
return ret;
}
#endif