Skip to content

Commit

Permalink
First integration of bulletproofs
Browse files Browse the repository at this point in the history
  • Loading branch information
yeastplume committed Feb 6, 2018
1 parent ed81188 commit c1212d7
Show file tree
Hide file tree
Showing 61 changed files with 462,449 additions and 75 deletions.
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ if ENABLE_MODULE_RANGEPROOF
include src/modules/rangeproof/Makefile.am.include
endif

if ENABLE_MODULE_BULLETPROOF
include src/modules/bulletproof/Makefile.am.include
endif

if ENABLE_MODULE_WHITELIST
include src/modules/whitelist/Makefile.am.include
endif
Expand Down
23 changes: 22 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ AC_ARG_ENABLE(experimental,
AC_ARG_ENABLE(exhaustive_tests,
AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]),
[use_exhaustive_tests=$enableval],
[use_exhaustive_tests=yes])
[use_exhaustive_tests=no])

AC_ARG_ENABLE(endomorphism,
AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]),
Expand Down Expand Up @@ -144,6 +144,11 @@ AC_ARG_ENABLE(module_rangeproof,
[enable_module_rangeproof=$enableval],
[enable_module_rangeproof=no])

AC_ARG_ENABLE(module_bulletproof,
AS_HELP_STRING([--enable-module-bulletproof],[enable Pedersen / zero-knowledge bulletproofs module (default is no)]),
[enable_module_bulletproof=$enableval],
[enable_module_bulletproof=no])

AC_ARG_ENABLE(module_whitelist,
AS_HELP_STRING([--enable-module-whitelist],[enable key whitelisting module (default is no)]),
[enable_module_whitelist=$enableval],
Expand Down Expand Up @@ -480,6 +485,10 @@ 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_bulletproof" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_BULLETPROOF, 1, [Define this symbol to enable the Pedersen / zero knowledge bullet proof module])
fi

if test x"$enable_module_whitelist" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_WHITELIST, 1, [Define this symbol to enable the key whitelisting module])
fi
Expand Down Expand Up @@ -516,6 +525,7 @@ if test x"$enable_experimental" = x"yes"; then
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
AC_MSG_NOTICE([Building NUMS generator module: $enable_module_generator])
AC_MSG_NOTICE([Building range proof module: $enable_module_rangeproof])
AC_MSG_NOTICE([Building bulletproof module: $enable_module_rangeproof])
AC_MSG_NOTICE([Building key whitelisting module: $enable_module_whitelist])
AC_MSG_NOTICE([Building surjection proof module: $enable_module_surjectionproof])
AC_MSG_NOTICE([Building aggregate signature module: $enable_module_aggsig])
Expand All @@ -527,6 +537,12 @@ if test x"$enable_experimental" = x"yes"; then
fi
fi

if test x"$enable_module_generator" != x"yes"; then
if test x"$enable_module_bulletproof" = x"yes"; then
AC_MSG_ERROR([Bulletproof module requires the generator module. Use --enable-module-generator to allow.])
fi
fi

if test x"$enable_module_rangeproof" != x"yes"; then
if test x"$enable_module_whitelist" = x"yes"; then
AC_MSG_ERROR([Whitelist module requires the rangeproof module. Use --enable-module-rangeproof to allow.])
Expand All @@ -551,6 +567,9 @@ else
if test x"$enable_module_rangeproof" = x"yes"; then
AC_MSG_ERROR([Range proof module is experimental. Use --enable-experimental to allow.])
fi
if test x"$enable_module_bulletproof" = x"yes"; then
AC_MSG_ERROR([Bulletproof 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 All @@ -575,6 +594,7 @@ AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_GENERATOR], [test x"$enable_module_generator" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_RANGEPROOF], [test x"$enable_module_rangeproof" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_BULLETPROOF], [test x"$enable_module_bulletproof" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_WHITELIST], [test x"$enable_module_whitelist" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_AGGSIG], [test x"$enable_module_aggsig" = x"yes"])
AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"])
Expand All @@ -593,6 +613,7 @@ AC_DEFINE(ENABLE_MODULE_ECDH, 1)
AC_DEFINE(ENABLE_MODULE_GENERATOR , 1)
AC_DEFINE(ENABLE_MODULE_RECOVERY , 1)
AC_DEFINE(ENABLE_MODULE_RANGEPROOF , 1)
AC_DEFINE(ENABLE_MODULE_BULLETPROOF , 1)
AC_DEFINE(ENABLE_MODULE_AGGSIG , 1)

AC_OUTPUT
132 changes: 132 additions & 0 deletions include/secp256k1_bulletproof.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#ifndef _SECP256K1_BULLETPROOF_
# define _SECP256K1_BULLETPROOF_

# include "secp256k1.h"
# include "secp256k1_generator.h"
# include "secp256k1_rangeproof.h"

# ifdef __cplusplus
extern "C" {
# endif

#define MAX_BATCH_QTY 100

/* Maximum depth of 31 lets us validate an aggregate of 2^25 64-bit proofs */
#define SECP256K1_BULLETPROOF_MAX_DEPTH 60

/* Size of a hypothetical 31-depth rangeproof, in bytes */
#define SECP256K1_BULLETPROOF_MAX_PROOF (160 + 66*32 + 7)

typedef struct secp256k1_bulletproof_circuit secp256k1_bulletproof_circuit;

SECP256K1_API int secp256k1_bulletproof_rangeproof_verify(
const secp256k1_context* ctx,
secp256k1_scratch_space* scratch,
const unsigned char* proof,
size_t plen,
const secp256k1_pedersen_commitment* commit,
size_t n_commits,
size_t nbits,
const secp256k1_generator* gen,
const unsigned char* extra_commit,
size_t extra_commit_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(8);

SECP256K1_API int secp256k1_bulletproof_rangeproof_verify_single_w_scratch(
const secp256k1_context* ctx,
const unsigned char* proof,
size_t plen,
const secp256k1_pedersen_commitment* commit,
size_t nbits,
const secp256k1_generator* gen,
const unsigned char* extra_commit,
size_t extra_commit_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6);


SECP256K1_API int secp256k1_bulletproof_rangeproof_verify_multi(
const secp256k1_context* ctx,
secp256k1_scratch_space* scratch,
const unsigned char* proof,
size_t plen,
size_t n_proofs,
const secp256k1_pedersen_commitment* commit,
size_t n_commits,
size_t nbits,
const secp256k1_generator* gen,
const unsigned char* extra_commit,
size_t extra_commit_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(9);


SECP256K1_API int secp256k1_bulletproof_rangeproof_prove(
const secp256k1_context* ctx,
secp256k1_scratch_space* scratch,
unsigned char* proof,
size_t* plen,
uint64_t *value,
const unsigned char** blind,
size_t n_commits,
const secp256k1_generator* gen,
size_t nbits,
const unsigned char* nonce,
const unsigned char* extra_commit,
size_t extra_commit_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(8) SECP256K1_ARG_NONNULL(10);

SECP256K1_API int secp256k1_bulletproof_rangeproof_prove_single_w_scratch(
const secp256k1_context* ctx,
unsigned char* proof,
size_t* plen,
uint64_t value,
const unsigned char* blind,
const secp256k1_generator* gen,
size_t nbits,
const unsigned char* nonce,
const unsigned char* extra_commit,
size_t extra_commit_len
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(8);

/* circuit stuff */
SECP256K1_API secp256k1_bulletproof_circuit *secp256k1_circuit_parse(
const secp256k1_context *ctx,
const char *description
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

SECP256K1_API void secp256k1_circuit_destroy(
const secp256k1_context *ctx,
secp256k1_bulletproof_circuit *circ
) SECP256K1_ARG_NONNULL(1);

SECP256K1_API int secp256k1_bulletproof_circuit_prove(
const secp256k1_context* ctx,
secp256k1_scratch_space *scratch,
unsigned char *proof,
size_t *plen,
secp256k1_bulletproof_circuit *circ,
unsigned char *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);

SECP256K1_API int secp256k1_bulletproof_circuit_verify(
const secp256k1_context* ctx,
secp256k1_scratch_space *scratch,
const unsigned char *proof,
size_t plen,
secp256k1_bulletproof_circuit *circ
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);

SECP256K1_API int secp256k1_bulletproof_circuit_verify_multi(
const secp256k1_context* ctx,
secp256k1_scratch_space *scratch,
const unsigned char *proof,
size_t plen,
size_t n_proofs,
secp256k1_bulletproof_circuit **circ
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(6);


# ifdef __cplusplus
}
# endif

#endif
77 changes: 77 additions & 0 deletions sage/generator_generator.sage
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
## Generate extra generators for secp256k1

import sys;
import hashlib;

# Original parameters for secp256k1
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
F = FiniteField (p)
C = EllipticCurve ([F(0), F(7)])
G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)

N_PAIRS = 65536

# Create generator
def generator(curve, seed):
hash = hashlib.sha256(seed).hexdigest()
hashint = int(hash, 16)
return curve.lift_x(hashint)

def word(n, shift):
return (int(n) >> shift) % 0x100000000

# Print it in a C-readable format
def print_generator(generator):
(x, y) = generator.xy()
sys.stdout.write("SECP256K1_GE_CONST(\n")
sys.stdout.write(" 0x%08xUL, 0x%08xUL, 0x%08xUL, 0x%08xUL,\n" % (word(x, 224), word(x, 192), word(x, 160), word(x, 128)))
sys.stdout.write(" 0x%08xUL, 0x%08xUL, 0x%08xUL, 0x%08xUL,\n" % (word(x, 96), word(x, 64), word(x, 32), word(x, 0)))
sys.stdout.write(" 0x%08xUL, 0x%08xUL, 0x%08xUL, 0x%08xUL,\n" % (word(y, 224), word(y, 192), word(y, 160), word(y, 128)))
sys.stdout.write(" 0x%08xUL, 0x%08xUL, 0x%08xUL, 0x%08xUL\n" % (word(y, 96), word(y, 64), word(y, 32), word(y, 0)))
sys.stdout.write(")")

# Bytes of G, encoded as a compressed pubkey, in hex
ghex = '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'

# Elements' H
sys.stdout.write("#ifndef _SECP256K1_MODULE_BULLETPROOF_GENERATORS_\n");
sys.stdout.write("#define _SECP256K1_MODULE_BULLETPROOF_GENERATORS_\n");
sys.stdout.write("/* File generated by sage/generator_generator.sage */\n\n")
sys.stdout.write("#include \"group.h\"\n\n")

sys.stdout.write("/* Elements' H, sha256(G) */\n")
sys.stdout.write("static const secp256k1_ge secp256k1_ge_const_g2 = ")
print_generator(generator(C, ghex.decode('hex')))
sys.stdout.write(";\n\n")

# 128 generators
sys.stdout.write("/* 128 generators to be used for rangeproofs. Each is computed by hashing\n")
sys.stdout.write(" * G alongside the smallest one-byte index that works.\n")
sys.stdout.write(" */\n")
sys.stdout.write("static const secp256k1_ge secp256k1_ge_const_gi[%d] = {\n" % N_PAIRS)
idx = 0
done = 0
while done < N_PAIRS:
idx += 1 ## it can be checked that 0 doesn't work, so harmless to skip it
try:
if idx < 0x100:
gen = generator(C, ("%s%02x" % (ghex, idx)).decode('hex'))
elif idx < 0x10000:
gen = generator(C, ("%s%04x" % (ghex, idx)).decode('hex'))
elif idx < 0x1000000:
gen = generator(C, ("%s%06x" % (ghex, idx)).decode('hex'))
sys.stdout.write("/* sha256(G || %d) */\n" % idx)
print_generator(gen)
if done == N_PAIRS - 1:
sys.stdout.write("\n")
else:
sys.stdout.write(",\n")
done += 1
except ValueError:
continue
sys.stdout.write("};\n\n")
sys.stdout.write("#endif")

#done
sys.stdout.flush()

Loading

0 comments on commit c1212d7

Please sign in to comment.