From 25745164835669d71e86863d1de747f26480ec08 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Wed, 26 Oct 2022 00:20:08 -0700 Subject: [PATCH] Add testcases for bulletproofs++ norm arugment --- src/modules/bulletproofs/tests_impl.h | 187 ++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/src/modules/bulletproofs/tests_impl.h b/src/modules/bulletproofs/tests_impl.h index e3daead4..ff7519f2 100644 --- a/src/modules/bulletproofs/tests_impl.h +++ b/src/modules/bulletproofs/tests_impl.h @@ -187,12 +187,199 @@ void test_norm_util_helpers(void) { secp256k1_scalar_set_int(&res, 256); CHECK(secp256k1_scalar_eq(&res, &r_pows[3])); } +static void secp256k1_norm_arg_commit_initial_data( + secp256k1_sha256* transcript, + const secp256k1_scalar* r, + const secp256k1_bulletproofs_generators* gens_vec, + size_t g_len, /* Same as n_vec_len, g_len + c_vec_len = gens->n */ + const secp256k1_scalar* c_vec, + size_t c_vec_len, + const secp256k1_ge* commit +) { + /* Commit to the initial public values */ + unsigned char ser_commit[33], ser_scalar[32], ser_le64[8]; + size_t i; + secp256k1_ge comm = *commit; + secp256k1_bulletproofs_pp_sha256_tagged_commitment_init(transcript); + secp256k1_fe_normalize(&comm.x); + secp256k1_fe_normalize(&comm.y); + CHECK(secp256k1_bulletproofs_serialize_pt(&ser_commit[0], &comm)); + secp256k1_sha256_write(transcript, ser_commit, 33); + secp256k1_scalar_get_b32(ser_scalar, r); + secp256k1_sha256_write(transcript, ser_scalar, 32); + secp256k1_bulletproofs_le64(ser_le64, g_len); + secp256k1_sha256_write(transcript, ser_le64, 8); + secp256k1_bulletproofs_le64(ser_le64, gens_vec->n); + secp256k1_sha256_write(transcript, ser_le64, 8); + for (i = 0; i < gens_vec->n; i++) { + secp256k1_fe_normalize(&gens_vec->gens[i].x); + secp256k1_fe_normalize(&gens_vec->gens[i].y); + CHECK(secp256k1_bulletproofs_serialize_pt(&ser_commit[0], &gens_vec->gens[i])); + secp256k1_sha256_write(transcript, ser_commit, 33); + } + secp256k1_bulletproofs_le64(ser_le64, c_vec_len); + secp256k1_sha256_write(transcript, ser_le64, 8); + for (i = 0; i < c_vec_len; i++) { + secp256k1_scalar_get_b32(ser_scalar, &c_vec[i]); + secp256k1_sha256_write(transcript, ser_scalar, 32); + } +} + +/* A complete norm argument. In contrast to secp256k1_bulletproofs_pp_rangeproof_norm_product_prove, this is meant + to be used as a standalone norm argument. + This is a simple wrapper around secp256k1_bulletproofs_pp_rangeproof_norm_product_prove + that also commits to the initial public values used in the protocol. In this case, these public + values are commitment. +*/ +static int secp256k1_norm_arg_prove( + secp256k1_scratch_space* scratch, + unsigned char* proof, + size_t *proof_len, + const secp256k1_scalar* r, + const secp256k1_bulletproofs_generators* gens_vec, + const secp256k1_scalar* n_vec, + size_t n_vec_len, + const secp256k1_scalar* l_vec, + size_t l_vec_len, + const secp256k1_scalar* c_vec, + size_t c_vec_len, + const secp256k1_ge* commit +) { + secp256k1_scalar *ns, *ls, *cs; + secp256k1_ge *gs, comm = *commit; + size_t scratch_checkpoint; + size_t g_len = n_vec_len, h_len = l_vec_len; + int res; + secp256k1_sha256 transcript; + + scratch_checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch); + ns = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, g_len * sizeof(secp256k1_scalar)); + ls = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, h_len * sizeof(secp256k1_scalar)); + cs = (secp256k1_scalar*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, h_len * sizeof(secp256k1_scalar)); + gs = (secp256k1_ge*)secp256k1_scratch_alloc(&ctx->error_callback, scratch, (g_len + h_len) * sizeof(secp256k1_ge)); + if (ns == NULL || ls == NULL || cs == NULL || gs == NULL) { + secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint); + return 0; + } + memcpy(ns, n_vec, g_len * sizeof(secp256k1_scalar)); + memcpy(ls, l_vec, h_len * sizeof(secp256k1_scalar)); + memcpy(cs, c_vec, h_len * sizeof(secp256k1_scalar)); + memcpy(gs, gens_vec->gens, (g_len + h_len) * sizeof(secp256k1_ge)); + + /* Commit to the initial public values */ + secp256k1_norm_arg_commit_initial_data(&transcript, r, gens_vec, g_len, c_vec, c_vec_len, &comm); + + res = secp256k1_bulletproofs_pp_rangeproof_norm_product_prove( + ctx, + scratch, + proof, + proof_len, + &transcript, /* Transcript hash of the parent protocol */ + r, + gs, + gens_vec->n, + ns, + n_vec_len, + ls, + l_vec_len, + cs, + c_vec_len + ); + secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, scratch_checkpoint); + return res; +} + +/* Verify the proof */ +static int secp256k1_norm_arg_verify( + secp256k1_scratch_space* scratch, + const unsigned char* proof, + size_t proof_len, + const secp256k1_scalar* r, + const secp256k1_bulletproofs_generators* gens_vec, + size_t g_len, + const secp256k1_scalar* c_vec, + size_t c_vec_len, + const secp256k1_ge* commit +) { + secp256k1_ge comm = *commit; + int res; + secp256k1_sha256 transcript; + + /* Commit to the initial public values */ + secp256k1_norm_arg_commit_initial_data(&transcript, r, gens_vec, g_len, c_vec, c_vec_len, &comm); + + res = secp256k1_bulletproofs_pp_rangeproof_norm_product_verify( + ctx, + scratch, + proof, + proof_len, + &transcript, + r, + gens_vec, + g_len, + c_vec, + c_vec_len, + commit + ); + return res; +} + +void norm_arg_test(unsigned int n, unsigned int m) { + secp256k1_scalar n_vec[64], l_vec[64], c_vec[64]; + secp256k1_scalar r, q; + secp256k1_ge commit; + size_t i, plen; + int res; + secp256k1_bulletproofs_generators *gs = secp256k1_bulletproofs_generators_create(ctx, n + m); + secp256k1_scratch *scratch = secp256k1_scratch_space_create(ctx, 1000*1000); /* shouldn't need much */ + unsigned char proof[1000]; + plen = 1000; + random_scalar_order(&r); + secp256k1_scalar_sqr(&q, &r); + + for (i = 0; i < n; i++) { + random_scalar_order(&n_vec[i]); + } + + for (i = 0; i < m; i++) { + random_scalar_order(&l_vec[i]); + random_scalar_order(&c_vec[i]); + } + + res = secp256k1_bulletproofs_commit(ctx, scratch, &commit, gs, n_vec, n, l_vec, m, c_vec, m, &q); + CHECK(res == 1); + res = secp256k1_norm_arg_prove(scratch, proof, &plen, &r, gs, n_vec, n, l_vec, m, c_vec, m, &commit); + CHECK(res == 1); + + res = secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n, c_vec, m, &commit); + CHECK(res == 1); + + /* Changing any of last two scalars should break the proof */ + proof[plen - 1] ^= 1; + res = secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n, c_vec, m, &commit); + CHECK(res == 0); + proof[plen - 1 - 32] ^= 1; + res = secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n, c_vec, m, &commit); + CHECK(res == 0); + + secp256k1_scratch_space_destroy(ctx, scratch); + secp256k1_bulletproofs_generators_destroy(ctx, gs); +} + 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(); + + norm_arg_test(1, 1); + norm_arg_test(1, 64); + norm_arg_test(64, 1); + norm_arg_test(32, 32); + norm_arg_test(32, 64); + norm_arg_test(64, 32); + norm_arg_test(64, 64); } #endif