Skip to content

Commit

Permalink
Merge #205: Bulletproofs++: Norm argument
Browse files Browse the repository at this point in the history
d7fb25c Make sure that bppp_log2 isn't called with value 0 (Jonas Nick)
e5a01d1 Rename buletproof_pp* to bppp* (sanket1729)
c983186 transcript: add tests (Jonas Nick)
73edc75 norm arg: add verification vectors (Jonas Nick)
13ad32e norm arg: add tests for zero length and zero vectors (Jonas Nick)
34c4847 ci: add bulletproofs (Jonas Nick)
2574516 Add testcases for bulletproofs++ norm arugment (sanket1729)
46c7391 Add norm argument verify API (sanket1729)
d914545 Add bulletproofs++ norm argument prove API (sanket1729)
8638f0e Add internal BP++ commit API (sanket1729)
412f8f6 Add utility functions required in norm argument (sanket1729)
420353d Add utilities for log2 (sanket1729)
17417d4 Add utilities from uncompressed Bulletproofs PR (sanket1729)
48563c8 bulletproofs: add API functionality to generate a large set of generators (Andrew Poelstra)
048f9f8 bulletproofs: add new empty module (Andrew Poelstra)
6162d57 generator: cleanups in Pedersen/generator code (Andrew Poelstra)
0a60069 Revert "Remove unused scalar_sqr" (Andrew Poelstra)
87373f5 MOVE ONLY: move Pedersen commitment stuff to generator module from rangeproof module (Andrew Poelstra)

Pull request description:

ACKs for top commit:
  Liam-Eagen:
    ACK d7fb25c
  jonasnick:
    ACK d7fb25c

Tree-SHA512: 0a51e2b404ab594e4ce6c4a65a35f6bbf870d718e0a3cdf7ddd085ed37a0e0c0db55dabca8fe9d8b8beb3f7e60280aa46a2951408c18942dd6ad1c9a71bab5cd
  • Loading branch information
jonasnick committed Feb 27, 2023
2 parents b1f1675 + d7fb25c commit 8ec6d11
Show file tree
Hide file tree
Showing 33 changed files with 2,429 additions and 520 deletions.
10 changes: 7 additions & 3 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ env:
WHITELIST: no
MUSIG: no
ECDSAADAPTOR: no
BPPP: no
### test options
SECP256K1_TEST_ITERS:
BENCH: yes
Expand Down Expand Up @@ -72,12 +73,12 @@ task:
<< : *LINUX_CONTAINER
matrix: &ENV_MATRIX
- env: {WIDEMUL: int64, RECOVERY: yes}
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes}
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes}
- env: {WIDEMUL: int128}
- env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes}
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes}
- env: {WIDEMUL: int128, ASM: x86_64}
- env: { RECOVERY: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes}
- env: { RECOVERY: yes, SCHNORRSIG: yes, EXPERIMENTAL: yes, ECDSA_S2C: yes, RANGEPROOF: yes, WHITELIST: yes, GENERATOR: yes, MUSIG: yes, ECDSAADAPTOR: yes, BPPP: yes}
- env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETEST: no, BENCH: no}
- env: {CPPFLAGS: -DDETERMINISTIC}
- env: {CFLAGS: -O0, CTIMETEST: no}
Expand Down Expand Up @@ -108,6 +109,7 @@ task:
GENERATOR: yes
MUSIG: yes
ECDSAADAPTOR: yes
BPPP: yes
matrix:
- env:
CC: i686-linux-gnu-gcc
Expand Down Expand Up @@ -165,6 +167,7 @@ task:
GENERATOR: yes
MUSIG: yes
ECDSAADAPTOR: yes
BPPP: yes
CTIMETEST: no
<< : *MERGE_BASE
test_script:
Expand Down Expand Up @@ -259,6 +262,7 @@ task:
GENERATOR: yes
MUSIG: yes
ECDSAADAPTOR: yes
BPPP: yes
CTIMETEST: no
matrix:
- name: "Valgrind (memcheck)"
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
bench
bench_bppp
bench_ecmult
bench_generator
bench_rangeproof
bench_internal
bench_whitelist
tests
example_musig
exhaustive_tests
precompute_ecmult_gen
precompute_ecmult
Expand Down Expand Up @@ -66,4 +69,4 @@ src/stamp-h1
libsecp256k1.pc
contrib/gh-pr-create.sh

musig_example
musig_example
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ clean-precomp:

EXTRA_DIST = autogen.sh SECURITY.md

if ENABLE_MODULE_BPPP
include src/modules/bppp/Makefile.am.include
endif

if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include
endif
Expand Down
5 changes: 5 additions & 0 deletions ci/cirrus.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ valgrind --version || true
--with-ecmult-gen-precision="$ECMULTGENPRECISION" \
--enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \
--enable-module-ecdsa-s2c="$ECDSA_S2C" \
--enable-module-bppp="$BPPP" \
--enable-module-rangeproof="$RANGEPROOF" --enable-module-whitelist="$WHITELIST" --enable-module-generator="$GENERATOR" \
--enable-module-schnorrsig="$SCHNORRSIG" --enable-module-musig="$MUSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \
--enable-module-schnorrsig="$SCHNORRSIG" \
Expand Down Expand Up @@ -51,6 +52,10 @@ then
$EXEC ./bench_ecmult
$EXEC ./bench_internal
$EXEC ./bench
if [ "$BPPP" = "yes" ]
then
$EXEC ./bench_bppp
fi
} >> bench.log 2>&1
fi

Expand Down
15 changes: 15 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ AC_ARG_ENABLE(examples,
AS_HELP_STRING([--enable-examples],[compile the examples [default=no]]), [],
[SECP_SET_DEFAULT([enable_examples], [no], [yes])])

AC_ARG_ENABLE(module_bppp,
AS_HELP_STRING([--enable-module-bppp],[enable Bulletproofs++ module (experimental)]),
[],
[SECP_SET_DEFAULT([enable_module_bppp], [no], [yes])])

AC_ARG_ENABLE(module_ecdh,
AS_HELP_STRING([--enable-module-ecdh],[enable ECDH module [default=no]]), [],
[SECP_SET_DEFAULT([enable_module_ecdh], [no], [yes])])
Expand Down Expand Up @@ -417,6 +422,11 @@ if test x"$enable_module_rangeproof" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_RANGEPROOF, 1, [Define this symbol to enable the Pedersen / zero knowledge range proof module])
fi

if test x"$enable_module_bppp" = x"yes"; then
enable_module_generator=yes
AC_DEFINE(ENABLE_MODULE_BPPP, 1, [Define this symbol to enable the Bulletproofs++ module])
fi

if test x"$enable_module_generator" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_GENERATOR, 1, [Define this symbol to enable the NUMS generator module])
fi
Expand Down Expand Up @@ -460,6 +470,9 @@ else
# module (which automatically enables the module dependencies) we want to
# print an error for the dependent module, not the module dependency. Hence,
# we first test dependent modules.
if test x"$enable_module_bppp" = x"yes"; then
AC_MSG_ERROR([Bulletproofs++ module is experimental. Use --enable-experimental to allow.])
fi
if test x"$enable_module_whitelist" = x"yes"; then
AC_MSG_ERROR([Key whitelisting module is experimental. Use --enable-experimental to allow.])
fi
Expand Down Expand Up @@ -502,6 +515,7 @@ AM_CONDITIONAL([USE_TESTS], [test x"$enable_tests" != x"no"])
AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$enable_exhaustive_tests" != x"no"])
AM_CONDITIONAL([USE_EXAMPLES], [test x"$enable_examples" != x"no"])
AM_CONDITIONAL([USE_BENCHMARK], [test x"$enable_benchmark" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_BPPP], [test x"$enable_module_bppp" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_MUSIG], [test x"$enable_module_musig" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"])
Expand Down Expand Up @@ -541,6 +555,7 @@ echo " module whitelist = $enable_module_whitelist"
echo " module musig = $enable_module_musig"
echo " module ecdsa-s2c = $enable_module_ecdsa_s2c"
echo " module ecdsa-adaptor = $enable_module_ecdsa_adaptor"
echo " module bppp = $enable_module_bppp"
echo
echo " asm = $set_asm"
echo " ecmult window size = $set_ecmult_window"
Expand Down
73 changes: 73 additions & 0 deletions include/secp256k1_bppp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef _SECP256K1_BPPP_
# define _SECP256K1_BPPP_

# include "secp256k1.h"

# ifdef __cplusplus
extern "C" {
# endif

#include <stdint.h>

/** Opaque structure representing a large number of NUMS generators */
typedef struct secp256k1_bppp_generators secp256k1_bppp_generators;

/** Allocates and initializes a list of NUMS generators.
* Returns a list of generators, or calls the error callback if the allocation fails.
* Args: ctx: pointer to a context object
* n: number of NUMS generators to produce.
*
* TODO: In a followup range-proof PR, this is would still require 16 + 8 = 24 NUMS
* points. We will later use G = H0(required for compatibility with pedersen_commitment DS)
* in a separate commit to make review easier.
*/
SECP256K1_API secp256k1_bppp_generators *secp256k1_bppp_generators_create(
const secp256k1_context* ctx,
size_t n
) SECP256K1_ARG_NONNULL(1);

/** Allocates a list of generators from a static array
* Returns a list of generators or NULL in case of failure.
* Args: ctx: pointer to a context object
* In: data: data that came from `secp256k1_bppp_generators_serialize`
* data_len: the length of the `data` buffer
*/
SECP256K1_API secp256k1_bppp_generators* secp256k1_bppp_generators_parse(
const secp256k1_context* ctx,
const unsigned char* data,
size_t data_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

/** Serializes a list of generators to an array
* Returns 1 on success, 0 if the provided array was not large enough
* Args: ctx: pointer to a context object
* gen: pointer to the generator set to be serialized
* Out: data: pointer to buffer into which the generators will be serialized
* In/Out: data_len: the length of the `data` buffer. Should be at least
* k = 33 * num_gens. Will be set to k on successful return
*
* TODO: For ease of review, this setting G = H0 is not included in this commit. We will
* add it in the follow-up rangeproof PR.
*/
SECP256K1_API int secp256k1_bppp_generators_serialize(
const secp256k1_context* ctx,
const secp256k1_bppp_generators* gen,
unsigned char* data,
size_t *data_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Destroys a list of NUMS generators, freeing allocated memory
* Args: ctx: pointer to a context object
* gen: pointer to the generator set to be destroyed
* (can be NULL, in which case this function is a no-op)
*/
SECP256K1_API void secp256k1_bppp_generators_destroy(
const secp256k1_context* ctx,
secp256k1_bppp_generators* gen
) SECP256K1_ARG_NONNULL(1);

# ifdef __cplusplus
}
# endif

#endif
148 changes: 148 additions & 0 deletions include/secp256k1_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 8ec6d11

Please sign in to comment.