Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rangeproof: clean up legacy rangeproof code #160

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ bench
bench_ecmult
bench_generator
bench_rangeproof
bench_whitelist
bench_internal
tests
exhaustive_tests
Expand Down Expand Up @@ -60,4 +61,4 @@ src/stamp-h1
libsecp256k1.pc
contrib/gh-pr-create.sh

example_musig
example_musig
9 changes: 9 additions & 0 deletions include/secp256k1_rangeproof.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ extern "C" {

#include <stdint.h>

/** Length of a message that can be embedded into a maximally-sized rangeproof
*
* It is not be possible to fit a message of this size into a non-maximally-sized
* rangeproof, but it is guaranteed that any embeddable message can fit into an
* array of this size. This constant is intended to be used for memory allocations
* and sanity checks.
*/
#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
Expand Down
2 changes: 1 addition & 1 deletion src/modules/rangeproof/borromean.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen);

int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen);

#endif
12 changes: 8 additions & 4 deletions src/modules/rangeproof/borromean_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
}

int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) {
secp256k1_gej rgej;
secp256k1_ge rge;
Expand All @@ -125,7 +125,6 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
VERIFY_CHECK(e0 != NULL);
VERIFY_CHECK(s != NULL);
VERIFY_CHECK(pubs != NULL);
VERIFY_CHECK(k != NULL);
VERIFY_CHECK(sec != NULL);
VERIFY_CHECK(rsizes != NULL);
VERIFY_CHECK(secidx != NULL);
Expand All @@ -135,7 +134,8 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
count = 0;
for (i = 0; i < nrings; i++) {
VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &k[i]);
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &s[count + secidx[i]]);
secp256k1_ge_set_gej(&rge, &rgej);
if (secp256k1_gej_is_infinity(&rgej)) {
return 0;
Expand Down Expand Up @@ -165,6 +165,10 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
secp256k1_sha256_finalize(&sha256_e0, e0);
count = 0;
for (i = 0; i < nrings; i++) {
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
secp256k1_scalar k = s[count + secidx[i]];
secp256k1_scalar_clear(&s[count + secidx[i]]);

VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
secp256k1_scalar_set_b32(&ens, tmp, &overflow);
Expand All @@ -186,7 +190,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
}
secp256k1_scalar_mul(&s[count + j], &ens, &sec[i]);
secp256k1_scalar_negate(&s[count + j], &s[count + j]);
secp256k1_scalar_add(&s[count + j], &s[count + j], &k[i]);
secp256k1_scalar_add(&s[count + j], &s[count + j], &k);
if (secp256k1_scalar_is_zero(&s[count + j])) {
return 0;
}
Expand Down
13 changes: 9 additions & 4 deletions src/modules/rangeproof/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,22 @@ int secp256k1_pedersen_blind_generator_blind_sum(const secp256k1_context* ctx, c

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) {
secp256k1_rangeproof_header header;
size_t offset;
uint64_t scale;
ARG_CHECK(exp != NULL);
ARG_CHECK(mantissa != NULL);
ARG_CHECK(min_value != NULL);
ARG_CHECK(max_value != NULL);
ARG_CHECK(proof != NULL);
offset = 0;
scale = 1;
(void)ctx;
return secp256k1_rangeproof_getheader_impl(&offset, exp, mantissa, &scale, min_value, max_value, proof, plen);
if (!secp256k1_rangeproof_header_parse(&header, &offset, proof, plen)) {
return 0;
}
*exp = header.exp;
*mantissa = header.mantissa;
*min_value = header.min_value;
*max_value = header.max_value;
return 1;
}

int secp256k1_rangeproof_rewind(const secp256k1_context* ctx,
Expand Down
73 changes: 73 additions & 0 deletions src/modules/rangeproof/rangeproof.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,79 @@
#include "ecmult.h"
#include "ecmult_gen.h"

/** Structure representing data directly encoded into a rangeproof header
*
* A rangeproof is a proof, associated with a Pedersen commitment, that a
* "proven value" in is the range [0, 2^mantissa - 1]. The committed value
* is related to the proven value by the contents of this header, as
*
* committed = min_value + 10^exp * proven
*/
typedef struct secp256k1_rangeproof_header {
/** Power of ten to multiply the proven value by, or -1 for an exact proof
*
* Encoded in the header. */
int exp;
/** Number of bits used to represent the proven value. Will be 0 for an exact proof.
*
* Encoded in the header. */
size_t mantissa;
/** 10 to the power of exp, or 1 for a proof of an exact value.
*
* Implied by `exp`, not encoded. */
uint64_t scale;
/** Minimum value for the range (added to the proven value).
*
* Encoded in the header. */
uint64_t min_value;
/** Maximum value for the range (min_value + 10^exp * 2^mantissa - 1).
*
* Implied by `min_value`, `exp`, `mantissa`. Not encoded. */
uint64_t max_value;
/** Number of rings to use in the underlying borromean ring signature
*
* Implied by `mantissa`. Not encoded. */
size_t n_rings;
/** Number of public keys to use in the underlying borromean ring signature
*
* Implied by `mantissa`. Not encoded. */
size_t n_pubs;
/** Number of keys in each ring
*
* Implied by `mantissa`. Not encoded. */
size_t rsizes[32];
} secp256k1_rangeproof_header;

/** Parses out a rangeproof header from a rangeproof and fills in all fields
*
* Returns: 1 on success, 0 on failure
* Out: header: the parsed header
* offset: the number of bytes of `proof` that the header occupied
* In: proof: the proof to parse the header out of
* plen: the length of the proof
*/
static int secp256k1_rangeproof_header_parse(
secp256k1_rangeproof_header* header,
size_t* offset,
const unsigned char* proof,
size_t plen
);

/** Serializes out a rangeproof header which has at least `exp`, `min_value` and `mantissa` set
*
* Returns: 1 on success, 0 on failure
* Out: proof: the buffer to serialize into
* offset: the number of bytes of `proof` that the header occupies
* In: plen: the length of the proof buffer
* header: the header to serialize
*/
static int secp256k1_rangeproof_header_serialize(
unsigned char* proof,
size_t plen,
size_t* offset,
const secp256k1_rangeproof_header* header
);

static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce,
uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen,
Expand Down
Loading