MOVE ONLY: move Pedersen commitment stuff to generator module from rangeproof module
You can verify this commit with `git diff --color-moved=zebra`
This commit is contained in:
parent
b1f1675375
commit
87373f5145
@ -21,6 +21,11 @@ typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_generator;
|
||||
|
||||
/**
|
||||
* Static constant generator 'h' maintained for historical reasons.
|
||||
*/
|
||||
SECP256K1_API extern const secp256k1_generator *secp256k1_generator_h;
|
||||
|
||||
/** Parse a 33-byte generator byte sequence into a generator object.
|
||||
*
|
||||
* Returns: 1 if input contains a valid generator.
|
||||
@ -86,6 +91,149 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_generator_generate_blin
|
||||
const unsigned char *blind32
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Opaque data structure that stores a Pedersen commitment
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage, transmission, or
|
||||
* comparison, use secp256k1_pedersen_commitment_serialize and
|
||||
* secp256k1_pedersen_commitment_parse.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_pedersen_commitment;
|
||||
|
||||
/** Parse a 33-byte commitment into a commitment object.
|
||||
*
|
||||
* Returns: 1 if input contains a valid commitment.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: commit: pointer to the output commitment object
|
||||
* In: input: pointer to a 33-byte serialized commitment key
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_commitment_parse(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pedersen_commitment* commit,
|
||||
const unsigned char *input
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize a commitment object into a serialized byte sequence.
|
||||
*
|
||||
* Returns: 1 always.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: output: a pointer to a 33-byte byte array
|
||||
* In: commit: a pointer to a secp256k1_pedersen_commitment containing an
|
||||
* initialized commitment
|
||||
*/
|
||||
SECP256K1_API int secp256k1_pedersen_commitment_serialize(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output,
|
||||
const secp256k1_pedersen_commitment* commit
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Generate a pedersen commitment.
|
||||
* Returns 1: Commitment successfully created.
|
||||
* 0: Error. The blinding factor is larger than the group order
|
||||
* (probability for random 32 byte number < 2^-127) or results in the
|
||||
* point at infinity. Retry with a different factor.
|
||||
* In: ctx: pointer to a context object, initialized for signing and Pedersen commitment (cannot be NULL)
|
||||
* blind: pointer to a 32-byte blinding factor (cannot be NULL)
|
||||
* value: unsigned 64-bit integer value to commit to.
|
||||
* gen: additional generator 'h'
|
||||
* Out: commit: pointer to the commitment (cannot be NULL)
|
||||
*
|
||||
* Blinding factors can be generated and verified in the same way as secp256k1 private keys for ECDSA.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_commit(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pedersen_commitment *commit,
|
||||
const unsigned char *blind,
|
||||
uint64_t value,
|
||||
const secp256k1_generator *gen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
|
||||
|
||||
/** Computes the sum of multiple positive and negative blinding factors.
|
||||
* Returns 1: Sum successfully computed.
|
||||
* 0: Error. A blinding factor is larger than the group order
|
||||
* (probability for random 32 byte number < 2^-127). Retry with
|
||||
* different factors.
|
||||
* In: ctx: pointer to a context object (cannot be NULL)
|
||||
* blinds: pointer to pointers to 32-byte character arrays for blinding factors. (cannot be NULL)
|
||||
* n: number of factors pointed to by blinds.
|
||||
* npositive: how many of the initial factors should be treated with a positive sign.
|
||||
* Out: blind_out: pointer to a 32-byte array for the sum (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_blind_sum(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *blind_out,
|
||||
const unsigned char * const *blinds,
|
||||
size_t n,
|
||||
size_t npositive
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Verify a tally of pedersen commitments
|
||||
* Returns 1: commitments successfully sum to zero.
|
||||
* 0: Commitments do not sum to zero or other error.
|
||||
* In: ctx: pointer to a context object (cannot be NULL)
|
||||
* commits: pointer to array of pointers to the commitments. (cannot be NULL if pcnt is non-zero)
|
||||
* pcnt: number of commitments pointed to by commits.
|
||||
* ncommits: pointer to array of pointers to the negative commitments. (cannot be NULL if ncnt is non-zero)
|
||||
* ncnt: number of commitments pointed to by ncommits.
|
||||
*
|
||||
* This computes sum(commit[0..pcnt)) - sum(ncommit[0..ncnt)) == 0.
|
||||
*
|
||||
* A pedersen commitment is xG + vA where G and A are generators for the secp256k1 group and x is a blinding factor,
|
||||
* while v is the committed value. For a collection of commitments to sum to zero, for each distinct generator
|
||||
* A all blinding factors and all values must sum to zero.
|
||||
*
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_verify_tally(
|
||||
const secp256k1_context* ctx,
|
||||
const secp256k1_pedersen_commitment * const* commits,
|
||||
size_t pcnt,
|
||||
const secp256k1_pedersen_commitment * const* ncommits,
|
||||
size_t ncnt
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Sets the final Pedersen blinding factor correctly when the generators themselves
|
||||
* have blinding factors.
|
||||
*
|
||||
* Consider a generator of the form A' = A + rG, where A is the "real" generator
|
||||
* but A' is the generator provided to verifiers. Then a Pedersen commitment
|
||||
* P = vA' + r'G really has the form vA + (vr + r')G. To get all these (vr + r')
|
||||
* to sum to zero for multiple commitments, we take three arrays consisting of
|
||||
* the `v`s, `r`s, and `r'`s, respectively called `value`s, `generator_blind`s
|
||||
* and `blinding_factor`s, and sum them.
|
||||
*
|
||||
* The function then subtracts the sum of all (vr + r') from the last element
|
||||
* of the `blinding_factor` array, setting the total sum to zero.
|
||||
*
|
||||
* Returns 1: Blinding factor successfully computed.
|
||||
* 0: Error. A blinding_factor or generator_blind are larger than the group
|
||||
* order (probability for random 32 byte number < 2^-127). Retry with
|
||||
* different values.
|
||||
*
|
||||
* In: ctx: pointer to a context object
|
||||
* value: array of asset values, `v` in the above paragraph.
|
||||
* May not be NULL unless `n_total` is 0.
|
||||
* generator_blind: array of asset blinding factors, `r` in the above paragraph
|
||||
* May not be NULL unless `n_total` is 0.
|
||||
* n_total: Total size of the above arrays
|
||||
* n_inputs: How many of the initial array elements represent commitments that
|
||||
* will be negated in the final sum
|
||||
* In/Out: blinding_factor: array of commitment blinding factors, `r'` in the above paragraph
|
||||
* May not be NULL unless `n_total` is 0.
|
||||
* the last value will be modified to get the total sum to zero.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_blind_generator_blind_sum(
|
||||
const secp256k1_context* ctx,
|
||||
const uint64_t *value,
|
||||
const unsigned char* const* generator_blind,
|
||||
unsigned char* const* blinding_factor,
|
||||
size_t n_total,
|
||||
size_t n_inputs
|
||||
);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
@ -19,154 +19,6 @@ extern "C" {
|
||||
*/
|
||||
#define SECP256K1_RANGEPROOF_MAX_MESSAGE_LEN 3968
|
||||
|
||||
/** Opaque data structure that stores a Pedersen commitment
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage, transmission, or
|
||||
* comparison, use secp256k1_pedersen_commitment_serialize and
|
||||
* secp256k1_pedersen_commitment_parse.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_pedersen_commitment;
|
||||
|
||||
/**
|
||||
* Static constant generator 'h' maintained for historical reasons.
|
||||
*/
|
||||
SECP256K1_API extern const secp256k1_generator *secp256k1_generator_h;
|
||||
|
||||
/** Parse a 33-byte commitment into a commitment object.
|
||||
*
|
||||
* Returns: 1 if input contains a valid commitment.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: commit: pointer to the output commitment object
|
||||
* In: input: pointer to a 33-byte serialized commitment key
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_commitment_parse(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pedersen_commitment* commit,
|
||||
const unsigned char *input
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize a commitment object into a serialized byte sequence.
|
||||
*
|
||||
* Returns: 1 always.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: output: a pointer to a 33-byte byte array
|
||||
* In: commit: a pointer to a secp256k1_pedersen_commitment containing an
|
||||
* initialized commitment
|
||||
*/
|
||||
SECP256K1_API int secp256k1_pedersen_commitment_serialize(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output,
|
||||
const secp256k1_pedersen_commitment* commit
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Generate a pedersen commitment.
|
||||
* Returns 1: Commitment successfully created.
|
||||
* 0: Error. The blinding factor is larger than the group order
|
||||
* (probability for random 32 byte number < 2^-127) or results in the
|
||||
* point at infinity. Retry with a different factor.
|
||||
* In: ctx: pointer to a context object, initialized for signing and Pedersen commitment (cannot be NULL)
|
||||
* blind: pointer to a 32-byte blinding factor (cannot be NULL)
|
||||
* value: unsigned 64-bit integer value to commit to.
|
||||
* gen: additional generator 'h'
|
||||
* Out: commit: pointer to the commitment (cannot be NULL)
|
||||
*
|
||||
* Blinding factors can be generated and verified in the same way as secp256k1 private keys for ECDSA.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_commit(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pedersen_commitment *commit,
|
||||
const unsigned char *blind,
|
||||
uint64_t value,
|
||||
const secp256k1_generator *gen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
|
||||
|
||||
/** Computes the sum of multiple positive and negative blinding factors.
|
||||
* Returns 1: Sum successfully computed.
|
||||
* 0: Error. A blinding factor is larger than the group order
|
||||
* (probability for random 32 byte number < 2^-127). Retry with
|
||||
* different factors.
|
||||
* In: ctx: pointer to a context object (cannot be NULL)
|
||||
* blinds: pointer to pointers to 32-byte character arrays for blinding factors. (cannot be NULL)
|
||||
* n: number of factors pointed to by blinds.
|
||||
* npositive: how many of the initial factors should be treated with a positive sign.
|
||||
* Out: blind_out: pointer to a 32-byte array for the sum (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_blind_sum(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *blind_out,
|
||||
const unsigned char * const *blinds,
|
||||
size_t n,
|
||||
size_t npositive
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Verify a tally of pedersen commitments
|
||||
* Returns 1: commitments successfully sum to zero.
|
||||
* 0: Commitments do not sum to zero or other error.
|
||||
* In: ctx: pointer to a context object (cannot be NULL)
|
||||
* commits: pointer to array of pointers to the commitments. (cannot be NULL if pcnt is non-zero)
|
||||
* pcnt: number of commitments pointed to by commits.
|
||||
* ncommits: pointer to array of pointers to the negative commitments. (cannot be NULL if ncnt is non-zero)
|
||||
* ncnt: number of commitments pointed to by ncommits.
|
||||
*
|
||||
* This computes sum(commit[0..pcnt)) - sum(ncommit[0..ncnt)) == 0.
|
||||
*
|
||||
* A pedersen commitment is xG + vA where G and A are generators for the secp256k1 group and x is a blinding factor,
|
||||
* while v is the committed value. For a collection of commitments to sum to zero, for each distinct generator
|
||||
* A all blinding factors and all values must sum to zero.
|
||||
*
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_verify_tally(
|
||||
const secp256k1_context* ctx,
|
||||
const secp256k1_pedersen_commitment * const* commits,
|
||||
size_t pcnt,
|
||||
const secp256k1_pedersen_commitment * const* ncommits,
|
||||
size_t ncnt
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Sets the final Pedersen blinding factor correctly when the generators themselves
|
||||
* have blinding factors.
|
||||
*
|
||||
* Consider a generator of the form A' = A + rG, where A is the "real" generator
|
||||
* but A' is the generator provided to verifiers. Then a Pedersen commitment
|
||||
* P = vA' + r'G really has the form vA + (vr + r')G. To get all these (vr + r')
|
||||
* to sum to zero for multiple commitments, we take three arrays consisting of
|
||||
* the `v`s, `r`s, and `r'`s, respectively called `value`s, `generator_blind`s
|
||||
* and `blinding_factor`s, and sum them.
|
||||
*
|
||||
* The function then subtracts the sum of all (vr + r') from the last element
|
||||
* of the `blinding_factor` array, setting the total sum to zero.
|
||||
*
|
||||
* Returns 1: Blinding factor successfully computed.
|
||||
* 0: Error. A blinding_factor or generator_blind are larger than the group
|
||||
* order (probability for random 32 byte number < 2^-127). Retry with
|
||||
* different values.
|
||||
*
|
||||
* In: ctx: pointer to a context object
|
||||
* value: array of asset values, `v` in the above paragraph.
|
||||
* May not be NULL unless `n_total` is 0.
|
||||
* generator_blind: array of asset blinding factors, `r` in the above paragraph
|
||||
* May not be NULL unless `n_total` is 0.
|
||||
* n_total: Total size of the above arrays
|
||||
* n_inputs: How many of the initial array elements represent commitments that
|
||||
* will be negated in the final sum
|
||||
* In/Out: blinding_factor: array of commitment blinding factors, `r'` in the above paragraph
|
||||
* May not be NULL unless `n_total` is 0.
|
||||
* the last value will be modified to get the total sum to zero.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_blind_generator_blind_sum(
|
||||
const secp256k1_context* ctx,
|
||||
const uint64_t *value,
|
||||
const unsigned char* const* generator_blind,
|
||||
unsigned char* const* blinding_factor,
|
||||
size_t n_total,
|
||||
size_t n_inputs
|
||||
);
|
||||
|
||||
/** Verify a proof that a committed value is within a range.
|
||||
* Returns 1: Value is within the range [0..2^64), the specifically proven range is in the min/max value outputs.
|
||||
* 0: Proof failed or other error.
|
||||
|
@ -1,4 +1,6 @@
|
||||
include_HEADERS += include/secp256k1_generator.h
|
||||
noinst_HEADERS += src/modules/generator/pedersen.h
|
||||
noinst_HEADERS += src/modules/generator/pedersen_impl.h
|
||||
noinst_HEADERS += src/modules/generator/main_impl.h
|
||||
noinst_HEADERS += src/modules/generator/tests_impl.h
|
||||
if USE_BENCHMARK
|
||||
|
@ -14,6 +14,29 @@
|
||||
#include "../../hash.h"
|
||||
#include "../../scalar.h"
|
||||
|
||||
#include "modules/generator/pedersen_impl.h"
|
||||
|
||||
/** Alternative generator for secp256k1.
|
||||
* This is the sha256 of 'g' after standard encoding (without compression),
|
||||
* which happens to be a point on the curve. More precisely, the generator is
|
||||
* derived by running the following script with the sage mathematics software.
|
||||
|
||||
import hashlib
|
||||
F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
|
||||
G = '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'
|
||||
H = EllipticCurve ([F (0), F (7)]).lift_x(F(int(hashlib.sha256(G.decode('hex')).hexdigest(),16)))
|
||||
print('%x %x' % H.xy())
|
||||
*/
|
||||
static const secp256k1_generator secp256k1_generator_h_internal = {{
|
||||
0x50, 0x92, 0x9b, 0x74, 0xc1, 0xa0, 0x49, 0x54, 0xb7, 0x8b, 0x4b, 0x60, 0x35, 0xe9, 0x7a, 0x5e,
|
||||
0x07, 0x8a, 0x5a, 0x0f, 0x28, 0xec, 0x96, 0xd5, 0x47, 0xbf, 0xee, 0x9a, 0xce, 0x80, 0x3a, 0xc0,
|
||||
0x31, 0xd3, 0xc6, 0x86, 0x39, 0x73, 0x92, 0x6e, 0x04, 0x9e, 0x63, 0x7c, 0xb1, 0xb5, 0xf4, 0x0a,
|
||||
0x36, 0xda, 0xc2, 0x8a, 0xf1, 0x76, 0x69, 0x68, 0xc3, 0x0c, 0x23, 0x13, 0xf3, 0xa3, 0x89, 0x04
|
||||
}};
|
||||
|
||||
const secp256k1_generator *secp256k1_generator_h = &secp256k1_generator_h_internal;
|
||||
|
||||
|
||||
static void secp256k1_generator_load(secp256k1_ge* ge, const secp256k1_generator* gen) {
|
||||
int succeed;
|
||||
succeed = secp256k1_fe_set_b32(&ge->x, &gen->data[0]);
|
||||
@ -219,4 +242,200 @@ int secp256k1_generator_generate_blinded(const secp256k1_context* ctx, secp256k1
|
||||
return secp256k1_generator_generate_internal(ctx, gen, key32, blind32);
|
||||
}
|
||||
|
||||
static void secp256k1_pedersen_commitment_load(secp256k1_ge* ge, const secp256k1_pedersen_commitment* commit) {
|
||||
secp256k1_fe fe;
|
||||
secp256k1_fe_set_b32(&fe, &commit->data[1]);
|
||||
secp256k1_ge_set_xquad(ge, &fe);
|
||||
if (commit->data[0] & 1) {
|
||||
secp256k1_ge_neg(ge, ge);
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_pedersen_commitment_save(secp256k1_pedersen_commitment* commit, secp256k1_ge* ge) {
|
||||
secp256k1_fe_normalize(&ge->x);
|
||||
secp256k1_fe_get_b32(&commit->data[1], &ge->x);
|
||||
commit->data[0] = 9 ^ secp256k1_fe_is_quad_var(&ge->y);
|
||||
}
|
||||
|
||||
int secp256k1_pedersen_commitment_parse(const secp256k1_context* ctx, secp256k1_pedersen_commitment* commit, const unsigned char *input) {
|
||||
secp256k1_fe x;
|
||||
secp256k1_ge ge;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(commit != NULL);
|
||||
ARG_CHECK(input != NULL);
|
||||
(void) ctx;
|
||||
|
||||
if ((input[0] & 0xFE) != 8 ||
|
||||
!secp256k1_fe_set_b32(&x, &input[1]) ||
|
||||
!secp256k1_ge_set_xquad(&ge, &x)) {
|
||||
return 0;
|
||||
}
|
||||
if (input[0] & 1) {
|
||||
secp256k1_ge_neg(&ge, &ge);
|
||||
}
|
||||
secp256k1_pedersen_commitment_save(commit, &ge);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_pedersen_commitment_serialize(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pedersen_commitment* commit) {
|
||||
secp256k1_ge ge;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(output != NULL);
|
||||
ARG_CHECK(commit != NULL);
|
||||
|
||||
secp256k1_pedersen_commitment_load(&ge, commit);
|
||||
|
||||
output[0] = 9 ^ secp256k1_fe_is_quad_var(&ge.y);
|
||||
secp256k1_fe_normalize_var(&ge.x);
|
||||
secp256k1_fe_get_b32(&output[1], &ge.x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generates a pedersen commitment: *commit = blind * G + value * G2. The blinding factor is 32 bytes.*/
|
||||
int secp256k1_pedersen_commit(const secp256k1_context* ctx, secp256k1_pedersen_commitment *commit, const unsigned char *blind, uint64_t value, const secp256k1_generator* gen) {
|
||||
secp256k1_ge genp;
|
||||
secp256k1_gej rj;
|
||||
secp256k1_ge r;
|
||||
secp256k1_scalar sec;
|
||||
int overflow;
|
||||
int ret = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
ARG_CHECK(commit != NULL);
|
||||
ARG_CHECK(blind != NULL);
|
||||
ARG_CHECK(gen != NULL);
|
||||
secp256k1_generator_load(&genp, gen);
|
||||
secp256k1_scalar_set_b32(&sec, blind, &overflow);
|
||||
if (!overflow) {
|
||||
secp256k1_pedersen_ecmult(&ctx->ecmult_gen_ctx, &rj, &sec, value, &genp);
|
||||
if (!secp256k1_gej_is_infinity(&rj)) {
|
||||
secp256k1_ge_set_gej(&r, &rj);
|
||||
secp256k1_pedersen_commitment_save(commit, &r);
|
||||
ret = 1;
|
||||
}
|
||||
secp256k1_gej_clear(&rj);
|
||||
secp256k1_ge_clear(&r);
|
||||
}
|
||||
secp256k1_scalar_clear(&sec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Takes a list of n pointers to 32 byte blinding values, the first negs of which are treated with positive sign and the rest
|
||||
* negative, then calculates an additional blinding value that adds to zero.
|
||||
*/
|
||||
int secp256k1_pedersen_blind_sum(const secp256k1_context* ctx, unsigned char *blind_out, const unsigned char * const *blinds, size_t n, size_t npositive) {
|
||||
secp256k1_scalar acc;
|
||||
secp256k1_scalar x;
|
||||
size_t i;
|
||||
int overflow;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(blind_out != NULL);
|
||||
ARG_CHECK(blinds != NULL);
|
||||
ARG_CHECK(npositive <= n);
|
||||
(void) ctx;
|
||||
secp256k1_scalar_set_int(&acc, 0);
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar_set_b32(&x, blinds[i], &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
if (i >= npositive) {
|
||||
secp256k1_scalar_negate(&x, &x);
|
||||
}
|
||||
secp256k1_scalar_add(&acc, &acc, &x);
|
||||
}
|
||||
secp256k1_scalar_get_b32(blind_out, &acc);
|
||||
secp256k1_scalar_clear(&acc);
|
||||
secp256k1_scalar_clear(&x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes two lists of commitments and sums the first set and subtracts the second and verifies that they sum to excess. */
|
||||
int secp256k1_pedersen_verify_tally(const secp256k1_context* ctx, const secp256k1_pedersen_commitment * const* commits, size_t pcnt, const secp256k1_pedersen_commitment * const* ncommits, size_t ncnt) {
|
||||
secp256k1_gej accj;
|
||||
secp256k1_ge add;
|
||||
size_t i;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(!pcnt || (commits != NULL));
|
||||
ARG_CHECK(!ncnt || (ncommits != NULL));
|
||||
(void) ctx;
|
||||
secp256k1_gej_set_infinity(&accj);
|
||||
for (i = 0; i < ncnt; i++) {
|
||||
secp256k1_pedersen_commitment_load(&add, ncommits[i]);
|
||||
secp256k1_gej_add_ge_var(&accj, &accj, &add, NULL);
|
||||
}
|
||||
secp256k1_gej_neg(&accj, &accj);
|
||||
for (i = 0; i < pcnt; i++) {
|
||||
secp256k1_pedersen_commitment_load(&add, commits[i]);
|
||||
secp256k1_gej_add_ge_var(&accj, &accj, &add, NULL);
|
||||
}
|
||||
return secp256k1_gej_is_infinity(&accj);
|
||||
}
|
||||
|
||||
int secp256k1_pedersen_blind_generator_blind_sum(const secp256k1_context* ctx, const uint64_t *value, const unsigned char* const* generator_blind, unsigned char* const* blinding_factor, size_t n_total, size_t n_inputs) {
|
||||
secp256k1_scalar sum;
|
||||
secp256k1_scalar tmp;
|
||||
size_t i;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(n_total == 0 || value != NULL);
|
||||
ARG_CHECK(n_total == 0 || generator_blind != NULL);
|
||||
ARG_CHECK(n_total == 0 || blinding_factor != NULL);
|
||||
ARG_CHECK(n_total > n_inputs);
|
||||
(void) ctx;
|
||||
|
||||
if (n_total == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
secp256k1_scalar_set_int(&sum, 0);
|
||||
|
||||
/* Here, n_total > 0. Thus the loop runs at least once.
|
||||
Thus we may use a do-while loop, which checks the loop
|
||||
condition only at the end.
|
||||
|
||||
The do-while loop helps GCC prove that the loop runs at least
|
||||
once and suppresses a -Wmaybe-uninitialized warning. */
|
||||
i = 0;
|
||||
do {
|
||||
int overflow = 0;
|
||||
secp256k1_scalar addend;
|
||||
secp256k1_scalar_set_u64(&addend, value[i]); /* s = v */
|
||||
|
||||
secp256k1_scalar_set_b32(&tmp, generator_blind[i], &overflow);
|
||||
if (overflow == 1) {
|
||||
secp256k1_scalar_clear(&tmp);
|
||||
secp256k1_scalar_clear(&addend);
|
||||
secp256k1_scalar_clear(&sum);
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_mul(&addend, &addend, &tmp); /* s = vr */
|
||||
|
||||
secp256k1_scalar_set_b32(&tmp, blinding_factor[i], &overflow);
|
||||
if (overflow == 1) {
|
||||
secp256k1_scalar_clear(&tmp);
|
||||
secp256k1_scalar_clear(&addend);
|
||||
secp256k1_scalar_clear(&sum);
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_add(&addend, &addend, &tmp); /* s = vr + r' */
|
||||
secp256k1_scalar_cond_negate(&addend, i < n_inputs); /* s is negated if it's an input */
|
||||
secp256k1_scalar_add(&sum, &sum, &addend); /* sum += s */
|
||||
secp256k1_scalar_clear(&addend);
|
||||
|
||||
i++;
|
||||
} while (i < n_total);
|
||||
|
||||
/* Right now tmp has the last pedersen blinding factor. Subtract the sum from it. */
|
||||
secp256k1_scalar_negate(&sum, &sum);
|
||||
secp256k1_scalar_add(&tmp, &tmp, &sum);
|
||||
secp256k1_scalar_get_b32(blinding_factor[n_total - 1], &tmp);
|
||||
|
||||
secp256k1_scalar_clear(&tmp);
|
||||
secp256k1_scalar_clear(&sum);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -223,11 +223,174 @@ void test_generator_fixed_vector(void) {
|
||||
CHECK(!secp256k1_generator_parse(ctx, &parse, result));
|
||||
}
|
||||
|
||||
static void test_pedersen_api(void) {
|
||||
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
|
||||
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
|
||||
secp256k1_pedersen_commitment commit;
|
||||
const secp256k1_pedersen_commitment *commit_ptr = &commit;
|
||||
unsigned char blind[32];
|
||||
unsigned char blind_out[32];
|
||||
const unsigned char *blind_ptr = blind;
|
||||
unsigned char *blind_out_ptr = blind_out;
|
||||
uint64_t val = secp256k1_testrand32();
|
||||
int32_t ecount = 0;
|
||||
|
||||
secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
secp256k1_testrand256(blind);
|
||||
CHECK(secp256k1_pedersen_commit(none, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(secp256k1_pedersen_commit(vrfy, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(ecount == 0);
|
||||
CHECK(secp256k1_pedersen_commit(sttc, &commit, blind, val, secp256k1_generator_h) == 0);
|
||||
CHECK(ecount == 1);
|
||||
|
||||
CHECK(secp256k1_pedersen_commit(sign, NULL, blind, val, secp256k1_generator_h) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, NULL, val, secp256k1_generator_h) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, blind, val, NULL) == 0);
|
||||
CHECK(ecount == 4);
|
||||
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, &blind_ptr, 1, 1) != 0);
|
||||
CHECK(ecount == 4);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, NULL, &blind_ptr, 1, 1) == 0);
|
||||
CHECK(ecount == 5);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, NULL, 1, 1) == 0);
|
||||
CHECK(ecount == 6);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, &blind_ptr, 0, 1) == 0);
|
||||
CHECK(ecount == 7);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, &blind_ptr, 0, 0) != 0);
|
||||
CHECK(ecount == 7);
|
||||
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, &commit_ptr, 1, &commit_ptr, 1) != 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, NULL, 0, &commit_ptr, 1) == 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, &commit_ptr, 1, NULL, 0) == 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, NULL, 0, NULL, 0) != 0);
|
||||
CHECK(ecount == 7);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, NULL, 1, &commit_ptr, 1) == 0);
|
||||
CHECK(ecount == 8);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, &commit_ptr, 1, NULL, 1) == 0);
|
||||
CHECK(ecount == 9);
|
||||
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, &blind_out_ptr, 1, 0) != 0);
|
||||
CHECK(ecount == 9);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, &blind_out_ptr, 1, 1) == 0);
|
||||
CHECK(ecount == 10);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, &blind_out_ptr, 0, 0) == 0);
|
||||
CHECK(ecount == 11);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, NULL, &blind_ptr, &blind_out_ptr, 1, 0) == 0);
|
||||
CHECK(ecount == 12);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, NULL, &blind_out_ptr, 1, 0) == 0);
|
||||
CHECK(ecount == 13);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, NULL, 1, 0) == 0);
|
||||
CHECK(ecount == 14);
|
||||
|
||||
secp256k1_context_destroy(none);
|
||||
secp256k1_context_destroy(sign);
|
||||
secp256k1_context_destroy(vrfy);
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
static void test_pedersen(void) {
|
||||
secp256k1_pedersen_commitment commits[19];
|
||||
const secp256k1_pedersen_commitment *cptr[19];
|
||||
unsigned char blinds[32*19];
|
||||
const unsigned char *bptr[19];
|
||||
secp256k1_scalar s;
|
||||
uint64_t values[19];
|
||||
int64_t totalv;
|
||||
int i;
|
||||
int inputs;
|
||||
int outputs;
|
||||
int total;
|
||||
inputs = (secp256k1_testrand32() & 7) + 1;
|
||||
outputs = (secp256k1_testrand32() & 7) + 2;
|
||||
total = inputs + outputs;
|
||||
for (i = 0; i < 19; i++) {
|
||||
cptr[i] = &commits[i];
|
||||
bptr[i] = &blinds[i * 32];
|
||||
}
|
||||
totalv = 0;
|
||||
for (i = 0; i < inputs; i++) {
|
||||
values[i] = secp256k1_testrandi64(0, INT64_MAX - totalv);
|
||||
totalv += values[i];
|
||||
}
|
||||
for (i = 0; i < outputs - 1; i++) {
|
||||
values[i + inputs] = secp256k1_testrandi64(0, totalv);
|
||||
totalv -= values[i + inputs];
|
||||
}
|
||||
values[total - 1] = totalv;
|
||||
|
||||
for (i = 0; i < total - 1; i++) {
|
||||
random_scalar_order(&s);
|
||||
secp256k1_scalar_get_b32(&blinds[i * 32], &s);
|
||||
}
|
||||
CHECK(secp256k1_pedersen_blind_sum(ctx, &blinds[(total - 1) * 32], bptr, total - 1, inputs));
|
||||
for (i = 0; i < total; i++) {
|
||||
CHECK(secp256k1_pedersen_commit(ctx, &commits[i], &blinds[i * 32], values[i], secp256k1_generator_h));
|
||||
}
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, cptr, inputs, &cptr[inputs], outputs));
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[inputs], outputs, cptr, inputs));
|
||||
if (inputs > 0 && values[0] > 0) {
|
||||
CHECK(!secp256k1_pedersen_verify_tally(ctx, cptr, inputs - 1, &cptr[inputs], outputs));
|
||||
}
|
||||
random_scalar_order(&s);
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_scalar_get_b32(&blinds[i * 32], &s);
|
||||
}
|
||||
values[0] = INT64_MAX;
|
||||
values[1] = 0;
|
||||
values[2] = 1;
|
||||
for (i = 0; i < 3; i++) {
|
||||
CHECK(secp256k1_pedersen_commit(ctx, &commits[i], &blinds[i * 32], values[i], secp256k1_generator_h));
|
||||
}
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[0], 1, &cptr[0], 1));
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[1], 1, &cptr[1], 1));
|
||||
}
|
||||
|
||||
void test_pedersen_commitment_fixed_vector(void) {
|
||||
const unsigned char two_g[33] = {
|
||||
0x09,
|
||||
0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8,
|
||||
0x5c, 0x77, 0x8e, 0x4b, 0x8c, 0xef, 0x3c, 0xa7, 0xab, 0xac, 0x09, 0xb9, 0x5c, 0x70, 0x9e, 0xe5
|
||||
};
|
||||
unsigned char result[33];
|
||||
secp256k1_pedersen_commitment parse;
|
||||
|
||||
CHECK(secp256k1_pedersen_commitment_parse(ctx, &parse, two_g));
|
||||
CHECK(secp256k1_pedersen_commitment_serialize(ctx, result, &parse));
|
||||
CHECK(secp256k1_memcmp_var(two_g, result, 33) == 0);
|
||||
|
||||
result[0] = 0x08;
|
||||
CHECK(secp256k1_pedersen_commitment_parse(ctx, &parse, result));
|
||||
result[0] = 0x0c;
|
||||
CHECK(!secp256k1_pedersen_commitment_parse(ctx, &parse, result));
|
||||
}
|
||||
|
||||
|
||||
void run_generator_tests(void) {
|
||||
int i;
|
||||
|
||||
test_shallue_van_de_woestijne();
|
||||
test_generator_fixed_vector();
|
||||
test_generator_api();
|
||||
test_generator_generate();
|
||||
test_pedersen_api();
|
||||
test_pedersen_commitment_fixed_vector();
|
||||
for (i = 0; i < count / 2 + 1; i++) {
|
||||
test_pedersen();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,5 @@
|
||||
include_HEADERS += include/secp256k1_rangeproof.h
|
||||
noinst_HEADERS += src/modules/rangeproof/main_impl.h
|
||||
noinst_HEADERS += src/modules/rangeproof/pedersen.h
|
||||
noinst_HEADERS += src/modules/rangeproof/pedersen_impl.h
|
||||
noinst_HEADERS += src/modules/rangeproof/borromean.h
|
||||
noinst_HEADERS += src/modules/rangeproof/borromean_impl.h
|
||||
noinst_HEADERS += src/modules/rangeproof/rangeproof.h
|
||||
|
@ -9,225 +9,9 @@
|
||||
|
||||
#include "../../group.h"
|
||||
|
||||
#include "pedersen_impl.h"
|
||||
#include "borromean_impl.h"
|
||||
#include "rangeproof_impl.h"
|
||||
|
||||
/** Alternative generator for secp256k1.
|
||||
* This is the sha256 of 'g' after standard encoding (without compression),
|
||||
* which happens to be a point on the curve. More precisely, the generator is
|
||||
* derived by running the following script with the sage mathematics software.
|
||||
|
||||
import hashlib
|
||||
F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
|
||||
G = '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'
|
||||
H = EllipticCurve ([F (0), F (7)]).lift_x(F(int(hashlib.sha256(G.decode('hex')).hexdigest(),16)))
|
||||
print('%x %x' % H.xy())
|
||||
*/
|
||||
static const secp256k1_generator secp256k1_generator_h_internal = {{
|
||||
0x50, 0x92, 0x9b, 0x74, 0xc1, 0xa0, 0x49, 0x54, 0xb7, 0x8b, 0x4b, 0x60, 0x35, 0xe9, 0x7a, 0x5e,
|
||||
0x07, 0x8a, 0x5a, 0x0f, 0x28, 0xec, 0x96, 0xd5, 0x47, 0xbf, 0xee, 0x9a, 0xce, 0x80, 0x3a, 0xc0,
|
||||
0x31, 0xd3, 0xc6, 0x86, 0x39, 0x73, 0x92, 0x6e, 0x04, 0x9e, 0x63, 0x7c, 0xb1, 0xb5, 0xf4, 0x0a,
|
||||
0x36, 0xda, 0xc2, 0x8a, 0xf1, 0x76, 0x69, 0x68, 0xc3, 0x0c, 0x23, 0x13, 0xf3, 0xa3, 0x89, 0x04
|
||||
}};
|
||||
|
||||
const secp256k1_generator *secp256k1_generator_h = &secp256k1_generator_h_internal;
|
||||
|
||||
static void secp256k1_pedersen_commitment_load(secp256k1_ge* ge, const secp256k1_pedersen_commitment* commit) {
|
||||
secp256k1_fe fe;
|
||||
secp256k1_fe_set_b32(&fe, &commit->data[1]);
|
||||
secp256k1_ge_set_xquad(ge, &fe);
|
||||
if (commit->data[0] & 1) {
|
||||
secp256k1_ge_neg(ge, ge);
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_pedersen_commitment_save(secp256k1_pedersen_commitment* commit, secp256k1_ge* ge) {
|
||||
secp256k1_fe_normalize(&ge->x);
|
||||
secp256k1_fe_get_b32(&commit->data[1], &ge->x);
|
||||
commit->data[0] = 9 ^ secp256k1_fe_is_quad_var(&ge->y);
|
||||
}
|
||||
|
||||
int secp256k1_pedersen_commitment_parse(const secp256k1_context* ctx, secp256k1_pedersen_commitment* commit, const unsigned char *input) {
|
||||
secp256k1_fe x;
|
||||
secp256k1_ge ge;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(commit != NULL);
|
||||
ARG_CHECK(input != NULL);
|
||||
(void) ctx;
|
||||
|
||||
if ((input[0] & 0xFE) != 8 ||
|
||||
!secp256k1_fe_set_b32(&x, &input[1]) ||
|
||||
!secp256k1_ge_set_xquad(&ge, &x)) {
|
||||
return 0;
|
||||
}
|
||||
if (input[0] & 1) {
|
||||
secp256k1_ge_neg(&ge, &ge);
|
||||
}
|
||||
secp256k1_pedersen_commitment_save(commit, &ge);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_pedersen_commitment_serialize(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pedersen_commitment* commit) {
|
||||
secp256k1_ge ge;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(output != NULL);
|
||||
ARG_CHECK(commit != NULL);
|
||||
|
||||
secp256k1_pedersen_commitment_load(&ge, commit);
|
||||
|
||||
output[0] = 9 ^ secp256k1_fe_is_quad_var(&ge.y);
|
||||
secp256k1_fe_normalize_var(&ge.x);
|
||||
secp256k1_fe_get_b32(&output[1], &ge.x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generates a pedersen commitment: *commit = blind * G + value * G2. The blinding factor is 32 bytes.*/
|
||||
int secp256k1_pedersen_commit(const secp256k1_context* ctx, secp256k1_pedersen_commitment *commit, const unsigned char *blind, uint64_t value, const secp256k1_generator* gen) {
|
||||
secp256k1_ge genp;
|
||||
secp256k1_gej rj;
|
||||
secp256k1_ge r;
|
||||
secp256k1_scalar sec;
|
||||
int overflow;
|
||||
int ret = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
ARG_CHECK(commit != NULL);
|
||||
ARG_CHECK(blind != NULL);
|
||||
ARG_CHECK(gen != NULL);
|
||||
secp256k1_generator_load(&genp, gen);
|
||||
secp256k1_scalar_set_b32(&sec, blind, &overflow);
|
||||
if (!overflow) {
|
||||
secp256k1_pedersen_ecmult(&ctx->ecmult_gen_ctx, &rj, &sec, value, &genp);
|
||||
if (!secp256k1_gej_is_infinity(&rj)) {
|
||||
secp256k1_ge_set_gej(&r, &rj);
|
||||
secp256k1_pedersen_commitment_save(commit, &r);
|
||||
ret = 1;
|
||||
}
|
||||
secp256k1_gej_clear(&rj);
|
||||
secp256k1_ge_clear(&r);
|
||||
}
|
||||
secp256k1_scalar_clear(&sec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Takes a list of n pointers to 32 byte blinding values, the first negs of which are treated with positive sign and the rest
|
||||
* negative, then calculates an additional blinding value that adds to zero.
|
||||
*/
|
||||
int secp256k1_pedersen_blind_sum(const secp256k1_context* ctx, unsigned char *blind_out, const unsigned char * const *blinds, size_t n, size_t npositive) {
|
||||
secp256k1_scalar acc;
|
||||
secp256k1_scalar x;
|
||||
size_t i;
|
||||
int overflow;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(blind_out != NULL);
|
||||
ARG_CHECK(blinds != NULL);
|
||||
ARG_CHECK(npositive <= n);
|
||||
(void) ctx;
|
||||
secp256k1_scalar_set_int(&acc, 0);
|
||||
for (i = 0; i < n; i++) {
|
||||
secp256k1_scalar_set_b32(&x, blinds[i], &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
if (i >= npositive) {
|
||||
secp256k1_scalar_negate(&x, &x);
|
||||
}
|
||||
secp256k1_scalar_add(&acc, &acc, &x);
|
||||
}
|
||||
secp256k1_scalar_get_b32(blind_out, &acc);
|
||||
secp256k1_scalar_clear(&acc);
|
||||
secp256k1_scalar_clear(&x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes two lists of commitments and sums the first set and subtracts the second and verifies that they sum to excess. */
|
||||
int secp256k1_pedersen_verify_tally(const secp256k1_context* ctx, const secp256k1_pedersen_commitment * const* commits, size_t pcnt, const secp256k1_pedersen_commitment * const* ncommits, size_t ncnt) {
|
||||
secp256k1_gej accj;
|
||||
secp256k1_ge add;
|
||||
size_t i;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(!pcnt || (commits != NULL));
|
||||
ARG_CHECK(!ncnt || (ncommits != NULL));
|
||||
(void) ctx;
|
||||
secp256k1_gej_set_infinity(&accj);
|
||||
for (i = 0; i < ncnt; i++) {
|
||||
secp256k1_pedersen_commitment_load(&add, ncommits[i]);
|
||||
secp256k1_gej_add_ge_var(&accj, &accj, &add, NULL);
|
||||
}
|
||||
secp256k1_gej_neg(&accj, &accj);
|
||||
for (i = 0; i < pcnt; i++) {
|
||||
secp256k1_pedersen_commitment_load(&add, commits[i]);
|
||||
secp256k1_gej_add_ge_var(&accj, &accj, &add, NULL);
|
||||
}
|
||||
return secp256k1_gej_is_infinity(&accj);
|
||||
}
|
||||
|
||||
int secp256k1_pedersen_blind_generator_blind_sum(const secp256k1_context* ctx, const uint64_t *value, const unsigned char* const* generator_blind, unsigned char* const* blinding_factor, size_t n_total, size_t n_inputs) {
|
||||
secp256k1_scalar sum;
|
||||
secp256k1_scalar tmp;
|
||||
size_t i;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(n_total == 0 || value != NULL);
|
||||
ARG_CHECK(n_total == 0 || generator_blind != NULL);
|
||||
ARG_CHECK(n_total == 0 || blinding_factor != NULL);
|
||||
ARG_CHECK(n_total > n_inputs);
|
||||
(void) ctx;
|
||||
|
||||
if (n_total == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
secp256k1_scalar_set_int(&sum, 0);
|
||||
|
||||
/* Here, n_total > 0. Thus the loop runs at least once.
|
||||
Thus we may use a do-while loop, which checks the loop
|
||||
condition only at the end.
|
||||
|
||||
The do-while loop helps GCC prove that the loop runs at least
|
||||
once and suppresses a -Wmaybe-uninitialized warning. */
|
||||
i = 0;
|
||||
do {
|
||||
int overflow = 0;
|
||||
secp256k1_scalar addend;
|
||||
secp256k1_scalar_set_u64(&addend, value[i]); /* s = v */
|
||||
|
||||
secp256k1_scalar_set_b32(&tmp, generator_blind[i], &overflow);
|
||||
if (overflow == 1) {
|
||||
secp256k1_scalar_clear(&tmp);
|
||||
secp256k1_scalar_clear(&addend);
|
||||
secp256k1_scalar_clear(&sum);
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_mul(&addend, &addend, &tmp); /* s = vr */
|
||||
|
||||
secp256k1_scalar_set_b32(&tmp, blinding_factor[i], &overflow);
|
||||
if (overflow == 1) {
|
||||
secp256k1_scalar_clear(&tmp);
|
||||
secp256k1_scalar_clear(&addend);
|
||||
secp256k1_scalar_clear(&sum);
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_add(&addend, &addend, &tmp); /* s = vr + r' */
|
||||
secp256k1_scalar_cond_negate(&addend, i < n_inputs); /* s is negated if it's an input */
|
||||
secp256k1_scalar_add(&sum, &sum, &addend); /* sum += s */
|
||||
secp256k1_scalar_clear(&addend);
|
||||
|
||||
i++;
|
||||
} while (i < n_total);
|
||||
|
||||
/* Right now tmp has the last pedersen blinding factor. Subtract the sum from it. */
|
||||
secp256k1_scalar_negate(&sum, &sum);
|
||||
secp256k1_scalar_add(&tmp, &tmp, &sum);
|
||||
secp256k1_scalar_get_b32(blinding_factor[n_total - 1], &tmp);
|
||||
|
||||
secp256k1_scalar_clear(&tmp);
|
||||
secp256k1_scalar_clear(&sum);
|
||||
return 1;
|
||||
}
|
||||
#include "modules/generator/main_impl.h"
|
||||
#include "modules/rangeproof/borromean_impl.h"
|
||||
#include "modules/rangeproof/rangeproof_impl.h"
|
||||
|
||||
int secp256k1_rangeproof_info(const secp256k1_context* ctx, int *exp, int *mantissa,
|
||||
uint64_t *min_value, uint64_t *max_value, const unsigned char *proof, size_t plen) {
|
||||
|
@ -13,9 +13,9 @@
|
||||
#include "../../hash_impl.h"
|
||||
#include "../../util.h"
|
||||
|
||||
#include "pedersen.h"
|
||||
#include "rangeproof.h"
|
||||
#include "borromean.h"
|
||||
#include "modules/generator/pedersen.h"
|
||||
#include "modules/rangeproof/borromean.h"
|
||||
#include "modules/rangeproof/rangeproof.h"
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand(secp256k1_gej *pubs,
|
||||
int exp, size_t *rsizes, size_t rings, const secp256k1_ge* genp) {
|
||||
|
@ -16,66 +16,6 @@
|
||||
|
||||
#include "../../../include/secp256k1_rangeproof.h"
|
||||
|
||||
static void test_pedersen_api(const secp256k1_context *none, const secp256k1_context *sign, const secp256k1_context *vrfy, const secp256k1_context *sttc, const int32_t *ecount) {
|
||||
secp256k1_pedersen_commitment commit;
|
||||
const secp256k1_pedersen_commitment *commit_ptr = &commit;
|
||||
unsigned char blind[32];
|
||||
unsigned char blind_out[32];
|
||||
const unsigned char *blind_ptr = blind;
|
||||
unsigned char *blind_out_ptr = blind_out;
|
||||
uint64_t val = secp256k1_testrand32();
|
||||
|
||||
secp256k1_testrand256(blind);
|
||||
CHECK(secp256k1_pedersen_commit(none, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(secp256k1_pedersen_commit(vrfy, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(*ecount == 0);
|
||||
CHECK(secp256k1_pedersen_commit(sttc, &commit, blind, val, secp256k1_generator_h) == 0);
|
||||
CHECK(*ecount == 1);
|
||||
|
||||
CHECK(secp256k1_pedersen_commit(sign, NULL, blind, val, secp256k1_generator_h) == 0);
|
||||
CHECK(*ecount == 2);
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, NULL, val, secp256k1_generator_h) == 0);
|
||||
CHECK(*ecount == 3);
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, blind, val, NULL) == 0);
|
||||
CHECK(*ecount == 4);
|
||||
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, &blind_ptr, 1, 1) != 0);
|
||||
CHECK(*ecount == 4);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, NULL, &blind_ptr, 1, 1) == 0);
|
||||
CHECK(*ecount == 5);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, NULL, 1, 1) == 0);
|
||||
CHECK(*ecount == 6);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, &blind_ptr, 0, 1) == 0);
|
||||
CHECK(*ecount == 7);
|
||||
CHECK(secp256k1_pedersen_blind_sum(none, blind_out, &blind_ptr, 0, 0) != 0);
|
||||
CHECK(*ecount == 7);
|
||||
|
||||
CHECK(secp256k1_pedersen_commit(sign, &commit, blind, val, secp256k1_generator_h) != 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, &commit_ptr, 1, &commit_ptr, 1) != 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, NULL, 0, &commit_ptr, 1) == 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, &commit_ptr, 1, NULL, 0) == 0);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, NULL, 0, NULL, 0) != 0);
|
||||
CHECK(*ecount == 7);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, NULL, 1, &commit_ptr, 1) == 0);
|
||||
CHECK(*ecount == 8);
|
||||
CHECK(secp256k1_pedersen_verify_tally(none, &commit_ptr, 1, NULL, 1) == 0);
|
||||
CHECK(*ecount == 9);
|
||||
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, &blind_out_ptr, 1, 0) != 0);
|
||||
CHECK(*ecount == 9);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, &blind_out_ptr, 1, 1) == 0);
|
||||
CHECK(*ecount == 10);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, &blind_out_ptr, 0, 0) == 0);
|
||||
CHECK(*ecount == 11);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, NULL, &blind_ptr, &blind_out_ptr, 1, 0) == 0);
|
||||
CHECK(*ecount == 12);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, NULL, &blind_out_ptr, 1, 0) == 0);
|
||||
CHECK(*ecount == 13);
|
||||
CHECK(secp256k1_pedersen_blind_generator_blind_sum(none, &val, &blind_ptr, NULL, 1, 0) == 0);
|
||||
CHECK(*ecount == 14);
|
||||
}
|
||||
|
||||
static void test_rangeproof_api(const secp256k1_context *none, const secp256k1_context *sign, const secp256k1_context *vrfy, const secp256k1_context *both, const secp256k1_context *sttc, const int32_t *ecount) {
|
||||
unsigned char proof[5134];
|
||||
unsigned char blind[32];
|
||||
@ -253,8 +193,6 @@ static void test_api(void) {
|
||||
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ecount = 0;
|
||||
test_pedersen_api(none, sign, vrfy, sttc, &ecount);
|
||||
ecount = 0;
|
||||
test_rangeproof_api(none, sign, vrfy, both, sttc, &ecount);
|
||||
}
|
||||
@ -266,63 +204,6 @@ static void test_api(void) {
|
||||
secp256k1_context_destroy(sttc);
|
||||
}
|
||||
|
||||
static void test_pedersen(void) {
|
||||
secp256k1_pedersen_commitment commits[19];
|
||||
const secp256k1_pedersen_commitment *cptr[19];
|
||||
unsigned char blinds[32*19];
|
||||
const unsigned char *bptr[19];
|
||||
secp256k1_scalar s;
|
||||
uint64_t values[19];
|
||||
int64_t totalv;
|
||||
int i;
|
||||
int inputs;
|
||||
int outputs;
|
||||
int total;
|
||||
inputs = (secp256k1_testrand32() & 7) + 1;
|
||||
outputs = (secp256k1_testrand32() & 7) + 2;
|
||||
total = inputs + outputs;
|
||||
for (i = 0; i < 19; i++) {
|
||||
cptr[i] = &commits[i];
|
||||
bptr[i] = &blinds[i * 32];
|
||||
}
|
||||
totalv = 0;
|
||||
for (i = 0; i < inputs; i++) {
|
||||
values[i] = secp256k1_testrandi64(0, INT64_MAX - totalv);
|
||||
totalv += values[i];
|
||||
}
|
||||
for (i = 0; i < outputs - 1; i++) {
|
||||
values[i + inputs] = secp256k1_testrandi64(0, totalv);
|
||||
totalv -= values[i + inputs];
|
||||
}
|
||||
values[total - 1] = totalv;
|
||||
|
||||
for (i = 0; i < total - 1; i++) {
|
||||
random_scalar_order(&s);
|
||||
secp256k1_scalar_get_b32(&blinds[i * 32], &s);
|
||||
}
|
||||
CHECK(secp256k1_pedersen_blind_sum(ctx, &blinds[(total - 1) * 32], bptr, total - 1, inputs));
|
||||
for (i = 0; i < total; i++) {
|
||||
CHECK(secp256k1_pedersen_commit(ctx, &commits[i], &blinds[i * 32], values[i], secp256k1_generator_h));
|
||||
}
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, cptr, inputs, &cptr[inputs], outputs));
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[inputs], outputs, cptr, inputs));
|
||||
if (inputs > 0 && values[0] > 0) {
|
||||
CHECK(!secp256k1_pedersen_verify_tally(ctx, cptr, inputs - 1, &cptr[inputs], outputs));
|
||||
}
|
||||
random_scalar_order(&s);
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_scalar_get_b32(&blinds[i * 32], &s);
|
||||
}
|
||||
values[0] = INT64_MAX;
|
||||
values[1] = 0;
|
||||
values[2] = 1;
|
||||
for (i = 0; i < 3; i++) {
|
||||
CHECK(secp256k1_pedersen_commit(ctx, &commits[i], &blinds[i * 32], values[i], secp256k1_generator_h));
|
||||
}
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[0], 1, &cptr[0], 1));
|
||||
CHECK(secp256k1_pedersen_verify_tally(ctx, &cptr[1], 1, &cptr[1], 1));
|
||||
}
|
||||
|
||||
static void test_borromean(void) {
|
||||
unsigned char e0[32];
|
||||
secp256k1_scalar s[64];
|
||||
@ -1523,25 +1404,6 @@ void test_rangeproof_fixed_vectors_reproducible(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void test_pedersen_commitment_fixed_vector(void) {
|
||||
const unsigned char two_g[33] = {
|
||||
0x09,
|
||||
0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8,
|
||||
0x5c, 0x77, 0x8e, 0x4b, 0x8c, 0xef, 0x3c, 0xa7, 0xab, 0xac, 0x09, 0xb9, 0x5c, 0x70, 0x9e, 0xe5
|
||||
};
|
||||
unsigned char result[33];
|
||||
secp256k1_pedersen_commitment parse;
|
||||
|
||||
CHECK(secp256k1_pedersen_commitment_parse(ctx, &parse, two_g));
|
||||
CHECK(secp256k1_pedersen_commitment_serialize(ctx, result, &parse));
|
||||
CHECK(secp256k1_memcmp_var(two_g, result, 33) == 0);
|
||||
|
||||
result[0] = 0x08;
|
||||
CHECK(secp256k1_pedersen_commitment_parse(ctx, &parse, result));
|
||||
result[0] = 0x0c;
|
||||
CHECK(!secp256k1_pedersen_commitment_parse(ctx, &parse, result));
|
||||
}
|
||||
|
||||
void run_rangeproof_tests(void) {
|
||||
int i;
|
||||
test_api();
|
||||
@ -1552,10 +1414,6 @@ void run_rangeproof_tests(void) {
|
||||
|
||||
test_rangeproof_fixed_vectors();
|
||||
test_rangeproof_fixed_vectors_reproducible();
|
||||
test_pedersen_commitment_fixed_vector();
|
||||
for (i = 0; i < count / 2 + 1; i++) {
|
||||
test_pedersen();
|
||||
}
|
||||
for (i = 0; i < count / 2 + 1; i++) {
|
||||
test_borromean();
|
||||
}
|
||||
|
@ -38,8 +38,6 @@
|
||||
|
||||
#ifdef ENABLE_MODULE_RANGEPROOF
|
||||
# include "include/secp256k1_rangeproof.h"
|
||||
# include "modules/rangeproof/pedersen.h"
|
||||
# include "modules/rangeproof/rangeproof.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MODULE_ECDSA_S2C
|
||||
|
Loading…
x
Reference in New Issue
Block a user