diff --git a/src/modules/bulletproofs/Makefile.am.include b/src/modules/bulletproofs/Makefile.am.include index 6a0773b3..cfd0916d 100644 --- a/src/modules/bulletproofs/Makefile.am.include +++ b/src/modules/bulletproofs/Makefile.am.include @@ -2,6 +2,7 @@ include_HEADERS += include/secp256k1_bulletproofs.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/bulletproofs_pp_norm_product_impl.h noinst_HEADERS += src/modules/bulletproofs/tests_impl.h if USE_BENCHMARK diff --git a/src/modules/bulletproofs/bulletproofs_pp_norm_product_impl.h b/src/modules/bulletproofs/bulletproofs_pp_norm_product_impl.h new file mode 100644 index 00000000..1e17ed34 --- /dev/null +++ b/src/modules/bulletproofs/bulletproofs_pp_norm_product_impl.h @@ -0,0 +1,81 @@ +/********************************************************************** + * 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_PP_NORM_PRODUCT_ +#define _SECP256K1_MODULE_BULLETPROOFS_PP_NORM_PRODUCT_ + +#include "group.h" +#include "scalar.h" +#include "ecmult.h" +#include "ecmult_gen.h" +#include "hash.h" + +#include "modules/bulletproofs/main.h" +#include "modules/bulletproofs/bulletproofs_util.h" + +/* Computes the inner product of two vectors of scalars + * with elements starting from offset a and offset b + * skipping elements according to specified step. + * Returns: Sum_{i=0..len-1}(a[offset_a + i*step] * b[offset_b + i*step]) */ +static int secp256k1_scalar_inner_product( + secp256k1_scalar* res, + const secp256k1_scalar* a_vec, + const size_t a_offset, + const secp256k1_scalar* b_vec, + const size_t b_offset, + const size_t step, + const size_t len +) { + size_t i; + secp256k1_scalar_set_int(res, 0); + for (i = 0; i < len; i++) { + secp256k1_scalar term; + secp256k1_scalar_mul(&term, &a_vec[a_offset + step*i], &b_vec[b_offset + step*i]); + secp256k1_scalar_add(res, res, &term); + } + return 1; +} + +/* Computes the q-weighted inner product of two vectors of scalars + * for elements starting from offset a and offset b respectively with the + * given step. + * Returns: Sum_{i=0..len-1}(a[offset_a + step*i] * b[offset_b2 + step*i]*q^(i+1)) */ +static int secp256k1_weighted_scalar_inner_product( + secp256k1_scalar* res, + const secp256k1_scalar* a_vec, + const size_t a_offset, + const secp256k1_scalar* b_vec, + const size_t b_offset, + const size_t step, + const size_t len, + const secp256k1_scalar* q +) { + secp256k1_scalar q_pow; + size_t i; + secp256k1_scalar_set_int(res, 0); + q_pow = *q; + for (i = 0; i < len; i++) { + secp256k1_scalar term; + secp256k1_scalar_mul(&term, &a_vec[a_offset + step*i], &b_vec[b_offset + step*i]); + secp256k1_scalar_mul(&term, &term, &q_pow); + secp256k1_scalar_mul(&q_pow, &q_pow, q); + secp256k1_scalar_add(res, res, &term); + } + return 1; +} + +/* Compute the powers of r as r, r^2, r^4 ... r^(2^(n-1)) */ +static void secp256k1_bulletproofs_powers_of_r(secp256k1_scalar *powers, const secp256k1_scalar *r, size_t n) { + size_t i; + if (n == 0) { + return; + } + powers[0] = *r; + for (i = 1; i < n; i++) { + secp256k1_scalar_sqr(&powers[i], &powers[i - 1]); + } +} +#endif diff --git a/src/modules/bulletproofs/main.h b/src/modules/bulletproofs/main.h new file mode 100644 index 00000000..4174102a --- /dev/null +++ b/src/modules/bulletproofs/main.h @@ -0,0 +1,13 @@ +#ifndef SECP256K1_MODULE_BULLETPROOFS_MAIN_H +#define SECP256K1_MODULE_BULLETPROOFS_MAIN_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 */ + /* For BP++, the generators are G_i from [0..(n - 8)] and the last 8 values + are generators are for H_i */ + secp256k1_ge* gens; +}; + +#endif diff --git a/src/modules/bulletproofs/main_impl.h b/src/modules/bulletproofs/main_impl.h index 047094c7..f87b9876 100644 --- a/src/modules/bulletproofs/main_impl.h +++ b/src/modules/bulletproofs/main_impl.h @@ -7,18 +7,13 @@ #ifndef _SECP256K1_MODULE_BULLETPROOFS_MAIN_ #define _SECP256K1_MODULE_BULLETPROOFS_MAIN_ -/* 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" +#include "modules/bulletproofs/main.h" +#include "modules/bulletproofs/bulletproofs_pp_norm_product_impl.h" secp256k1_bulletproofs_generators *secp256k1_bulletproofs_generators_create(const secp256k1_context *ctx, size_t n) { secp256k1_bulletproofs_generators *ret; diff --git a/src/modules/bulletproofs/tests_impl.h b/src/modules/bulletproofs/tests_impl.h index bec7c84f..e3daead4 100644 --- a/src/modules/bulletproofs/tests_impl.h +++ b/src/modules/bulletproofs/tests_impl.h @@ -10,6 +10,7 @@ #include #include "include/secp256k1_bulletproofs.h" +#include "bulletproofs_pp_norm_product_impl.h" #include "bulletproofs_util.h" #include "bulletproofs_pp_transcript_impl.h" @@ -149,8 +150,46 @@ void test_log_exp(void) { CHECK(secp256k1_bulletproofs_pp_log2(257) == 8); } +void test_norm_util_helpers(void) { + secp256k1_scalar a_vec[4], b_vec[4], r_pows[4], res, res2, q, r; + int i; + /* a = {1, 2, 3, 4} b = {5, 6, 7, 8}, q = 4, r = 2 */ + for (i = 0; i < 4; i++) { + secp256k1_scalar_set_int(&a_vec[i], i + 1); + secp256k1_scalar_set_int(&b_vec[i], i + 5); + } + secp256k1_scalar_set_int(&q, 4); + secp256k1_scalar_set_int(&r, 2); + secp256k1_scalar_inner_product(&res, a_vec, 0, b_vec, 0, 1, 4); + secp256k1_scalar_set_int(&res2, 70); + CHECK(secp256k1_scalar_eq(&res2, &res) == 1); + + secp256k1_scalar_inner_product(&res, a_vec, 0, b_vec, 1, 2, 2); + secp256k1_scalar_set_int(&res2, 30); + CHECK(secp256k1_scalar_eq(&res2, &res) == 1); + + secp256k1_scalar_inner_product(&res, a_vec, 1, b_vec, 0, 2, 2); + secp256k1_scalar_set_int(&res2, 38); + CHECK(secp256k1_scalar_eq(&res2, &res) == 1); + + secp256k1_scalar_inner_product(&res, a_vec, 1, b_vec, 1, 2, 2); + secp256k1_scalar_set_int(&res2, 44); + CHECK(secp256k1_scalar_eq(&res2, &res) == 1); + + secp256k1_weighted_scalar_inner_product(&res, a_vec, 0, a_vec, 0, 1, 4, &q); + secp256k1_scalar_set_int(&res2, 4740); /*i*i*4^(i+1) */ + CHECK(secp256k1_scalar_eq(&res2, &res) == 1); + + secp256k1_bulletproofs_powers_of_r(r_pows, &r, 4); + secp256k1_scalar_set_int(&res, 2); CHECK(secp256k1_scalar_eq(&res, &r_pows[0])); + secp256k1_scalar_set_int(&res, 4); CHECK(secp256k1_scalar_eq(&res, &r_pows[1])); + secp256k1_scalar_set_int(&res, 16); CHECK(secp256k1_scalar_eq(&res, &r_pows[2])); + secp256k1_scalar_set_int(&res, 256); CHECK(secp256k1_scalar_eq(&res, &r_pows[3])); +} + void run_bulletproofs_tests(void) { test_log_exp(); + test_norm_util_helpers(); test_bulletproofs_generators_api(); test_bulletproofs_generators_fixed(); test_bulletproofs_pp_tagged_hash();