diff --git a/src/modules/bulletproofs/Makefile.am.include b/src/modules/bulletproofs/Makefile.am.include index 6cd9fc3c..6a0773b3 100644 --- a/src/modules/bulletproofs/Makefile.am.include +++ b/src/modules/bulletproofs/Makefile.am.include @@ -1,6 +1,8 @@ include_HEADERS += include/secp256k1_bulletproofs.h -noinst_HEADERS += src/modules/bulletproofs/tests_impl.h +noinst_HEADERS += src/modules/bulletproofs/bulletproofs_util.h noinst_HEADERS += src/modules/bulletproofs/main_impl.h +noinst_HEADERS += src/modules/bulletproofs/bulletproofs_pp_transcript_impl.h +noinst_HEADERS += src/modules/bulletproofs/tests_impl.h if USE_BENCHMARK noinst_PROGRAMS += bench_bulletproofs diff --git a/src/modules/bulletproofs/bulletproofs_pp_transcript_impl.h b/src/modules/bulletproofs/bulletproofs_pp_transcript_impl.h new file mode 100644 index 00000000..e8444e91 --- /dev/null +++ b/src/modules/bulletproofs/bulletproofs_pp_transcript_impl.h @@ -0,0 +1,40 @@ +/********************************************************************** + * Copyright (c) 2022 Sanket Kanjalkar * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +#ifndef _SECP256K1_MODULE_BULLETPROOFS_PP_TRANSCRIPT_IMPL_ +#define _SECP256K1_MODULE_BULLETPROOFS_PP_TRANSCRIPT_IMPL_ + +#include "group.h" +#include "scalar.h" +#include "bulletproofs_util.h" + +/* Initializes SHA256 with fixed midstate. This midstate was computed by applying + * SHA256 to SHA256("Bulletproofs_pp/v0/commitment")||SHA256("Bulletproofs_pp/v0/commitment"). + */ +static void secp256k1_bulletproofs_pp_sha256_tagged_commitment_init(secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha); + sha->s[0] = 0x52fc8185ul; + sha->s[1] = 0x0e7debf0ul; + sha->s[2] = 0xb0967270ul; + sha->s[3] = 0x6f5abfe1ul; + sha->s[4] = 0x822bdec0ul; + sha->s[5] = 0x36db8beful; + sha->s[6] = 0x03d9e1f1ul; + sha->s[7] = 0x8a5cef6ful; + + sha->bytes = 64; +} + +/* Obtain a challenge scalar from the current transcript.*/ +static void secp256k1_bulletproofs_challenge_scalar(secp256k1_scalar* ch, const secp256k1_sha256 *transcript, uint64_t idx) { + unsigned char buf[32]; + secp256k1_sha256 sha = *transcript; + secp256k1_bulletproofs_le64(buf, idx); + secp256k1_sha256_write(&sha, buf, 8); + secp256k1_sha256_finalize(&sha, buf); + secp256k1_scalar_set_b32(ch, buf, NULL); +} + +#endif diff --git a/src/modules/bulletproofs/bulletproofs_util.h b/src/modules/bulletproofs/bulletproofs_util.h new file mode 100644 index 00000000..20d1c748 --- /dev/null +++ b/src/modules/bulletproofs/bulletproofs_util.h @@ -0,0 +1,42 @@ +/********************************************************************** + * Copyright (c) 2020 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_BULLETPROOFS_UTIL_ +#define _SECP256K1_MODULE_BULLETPROOFS_UTIL_ + +#include "field.h" +#include "group.h" +#include "hash.h" + +/* Outputs a pair of points, amortizing the parity byte between them + * Assumes both points' coordinates have been normalized. + */ +static void secp256k1_bulletproofs_serialize_points(unsigned char *output, const secp256k1_ge *lpt, const secp256k1_ge *rpt) { + output[0] = (secp256k1_fe_is_odd(&lpt->y) << 1) + secp256k1_fe_is_odd(&rpt->y); + secp256k1_fe_get_b32(&output[1], &lpt->x); + secp256k1_fe_get_b32(&output[33], &rpt->x); +} + +/* Outputs a serialized point in compressed form. Returns 0 at point at infinity. +*/ +static int secp256k1_bulletproofs_serialize_pt(unsigned char *output, secp256k1_ge *lpt) { + size_t size; + return secp256k1_eckey_pubkey_serialize(lpt, output, &size, 1 /*compressed*/); +} + +/* little-endian encodes a uint64 */ +static void secp256k1_bulletproofs_le64(unsigned char *output, const uint64_t n) { + output[0] = n; + output[1] = n >> 8; + output[2] = n >> 16; + output[3] = n >> 24; + output[4] = n >> 32; + output[5] = n >> 40; + output[6] = n >> 48; + output[7] = n >> 56; +} + +#endif diff --git a/src/modules/bulletproofs/main_impl.h b/src/modules/bulletproofs/main_impl.h index ef0ac78c..047094c7 100644 --- a/src/modules/bulletproofs/main_impl.h +++ b/src/modules/bulletproofs/main_impl.h @@ -7,18 +7,19 @@ #ifndef _SECP256K1_MODULE_BULLETPROOFS_MAIN_ #define _SECP256K1_MODULE_BULLETPROOFS_MAIN_ -#include "include/secp256k1_bulletproofs.h" -#include "include/secp256k1_generator.h" -#include "modules/generator/main_impl.h" /* for generator_{load, save} */ -#include "hash.h" -#include "util.h" - +/* this type must be completed before any of the modules/bulletproofs includes */ struct secp256k1_bulletproofs_generators { size_t n; /* n total generators; includes both G_i and H_i */ secp256k1_ge* gens; }; +#include "include/secp256k1_bulletproofs.h" +#include "include/secp256k1_generator.h" +#include "modules/generator/main_impl.h" /* for generator_{load, save} */ +#include "hash.h" +#include "util.h" + secp256k1_bulletproofs_generators *secp256k1_bulletproofs_generators_create(const secp256k1_context *ctx, size_t n) { secp256k1_bulletproofs_generators *ret; secp256k1_rfc6979_hmac_sha256 rng; diff --git a/src/modules/bulletproofs/tests_impl.h b/src/modules/bulletproofs/tests_impl.h index f75b7294..930b35af 100644 --- a/src/modules/bulletproofs/tests_impl.h +++ b/src/modules/bulletproofs/tests_impl.h @@ -7,6 +7,8 @@ #ifndef _SECP256K1_MODULE_BULLETPROOFS_TEST_ #define _SECP256K1_MODULE_BULLETPROOFS_TEST_ +#include "bulletproofs_pp_transcript_impl.h" + static void test_bulletproofs_generators_api(void) { /* The BP generator API requires no precomp */ secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); @@ -114,9 +116,24 @@ static void test_bulletproofs_generators_fixed(void) { secp256k1_bulletproofs_generators_destroy(ctx, gens); } +static void test_bulletproofs_pp_tagged_hash(void) { + unsigned char tag_data[29] = "Bulletproofs_pp/v0/commitment"; + secp256k1_sha256 sha; + secp256k1_sha256 sha_cached; + unsigned char output[32]; + unsigned char output_cached[32]; + + secp256k1_sha256_initialize_tagged(&sha, tag_data, sizeof(tag_data)); + secp256k1_bulletproofs_pp_sha256_tagged_commitment_init(&sha_cached); + secp256k1_sha256_finalize(&sha, output); + secp256k1_sha256_finalize(&sha_cached, output_cached); + CHECK(secp256k1_memcmp_var(output, output_cached, 32) == 0); +} + void run_bulletproofs_tests(void) { test_bulletproofs_generators_api(); test_bulletproofs_generators_fixed(); + test_bulletproofs_pp_tagged_hash(); } #endif