diff --git a/src/modules/bulletproofs/bulletproofs_pp_norm_product_impl.h b/src/modules/bulletproofs/bulletproofs_pp_norm_product_impl.h index 7c325985b..4aa22a7f8 100644 --- a/src/modules/bulletproofs/bulletproofs_pp_norm_product_impl.h +++ b/src/modules/bulletproofs/bulletproofs_pp_norm_product_impl.h @@ -77,4 +77,66 @@ static void secp256k1_bulletproofs_powers_of_r(secp256k1_scalar *powers, const s secp256k1_scalar_sqr(&powers[i], &powers[i - 1]); } } + +typedef struct ec_mult_bp_commit_cb_data { + const secp256k1_scalar *n; + const secp256k1_ge *g; + const secp256k1_scalar *l; + size_t g_len; +} ec_mult_bp_commit_cb_data; + +static int ec_mult_bp_commit_cb(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { + ec_mult_bp_commit_cb_data *data = (ec_mult_bp_commit_cb_data*) cbdata; + *pt = data->g[idx]; + if (idx < data->g_len) { + *sc = data->n[idx]; + } else { + *sc = data->l[idx - data->g_len]; + } + return 1; +} + +/* Create a commitment C = vG + [n_vec*G_vec]_q + l_vec*H_vec */ +static int secp256k1_bulletproofs_commit( + const secp256k1_context* ctx, + secp256k1_scratch_space* scratch, + secp256k1_ge* commit, + const secp256k1_bulletproofs_generators* g_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_scalar* q +) { + secp256k1_scalar v, l_c; + /* First n_vec_len generators are Gs, rest are Hs*/ + if (g_vec->n != (n_vec_len + l_vec_len) || l_vec_len != c_vec_len) { + return 0; + } + + if (!secp256k1_check_power_of_two(n_vec_len) || !secp256k1_check_power_of_two(c_vec_len)) { + return 0; + } + /* Compute v = n_vec*n_vec*q + l_vec*c_vec */ + secp256k1_weighted_scalar_inner_product(&v, n_vec, 0 /*a offset */, n_vec, 0 /*b offset*/, 1 /*step*/, n_vec_len, q); + secp256k1_scalar_inner_product(&l_c, l_vec, 0 /*a offset */, c_vec, 0 /*b offset*/, 1 /*step*/, l_vec_len); + secp256k1_scalar_add(&v, &v, &l_c); + + { + ec_mult_bp_commit_cb_data data; + secp256k1_gej commitj; + data.g = g_vec->gens; + data.n = n_vec; + data.l = l_vec; + data.g_len = n_vec_len; + + if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &commitj, &v, ec_mult_bp_commit_cb, (void*) &data, n_vec_len + l_vec_len)) { + return 0; + } + secp256k1_ge_set_gej_var(commit, &commitj); + } + return 1; +} #endif