diff --git a/src/crypto/zarcanum.cpp b/src/crypto/zarcanum.cpp index e98000f8..5ffab1c6 100644 --- a/src/crypto/zarcanum.cpp +++ b/src/crypto/zarcanum.cpp @@ -244,34 +244,43 @@ namespace crypto if (!(cond)) { LOG_PRINT_RED("generate_vector_UG_aggregation_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ if (p_err) { *p_err = err_code; } return false; } - bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets, + bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets0, const scalar_vec_t& g_secrets1, const std::vector& amount_commitments, const std::vector& amount_commitments_for_rp_aggregation, const std::vector& blinded_asset_ids, vector_UG_aggregation_proof& result, uint8_t* p_err /* = nullptr */) { + // w - public random weighting factor // proof of knowing e_j and y'' in zero knowledge in the following eq: - // E_j + E'_j = e_j * (T'_j + U) + y'' * G + // E_j + w * E'_j = e_j * (T'_j + w * U) + (y_j + w * y'_j) * G // where: // e_j -- output's amount // T'_j -- output's blinded asset tag // E_j == e_j * T'_j + y_j * G -- output's amount commitments // E'_j == e_j * U + y'_j * G -- additional commitment to the same amount for range proof aggregation - // amount_commitments[j] + amount_commitments_for_rp_aggregation[j] + // amount_commitments[j] + w * amount_commitments_for_rp_aggregation[j] // == - // u_secrets[j] * (blinded_asset_ids[j] + U) + g_secrets[j] * G + // u_secrets[j] * (blinded_asset_ids[j] + w * U) + (g_secrets0[j] + w * g_secrets1[j]) * G const size_t n = u_secrets.size(); CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n != 0, 1); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == g_secrets.size(), 2); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments.size(), 3); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments_for_rp_aggregation.size(), 4); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == blinded_asset_ids.size(), 5); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == g_secrets0.size(), 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == g_secrets1.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments.size(), 4); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments_for_rp_aggregation.size(), 5); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == blinded_asset_ids.size(), 6); + + crypto::hash_helper_t::hs_t hash_calculator(1 + 3 * n); + hash_calculator.add_hash(m); + hash_calculator.add_points_array(amount_commitments); + hash_calculator.add_points_array(amount_commitments_for_rp_aggregation); + scalar_t w = hash_calculator.calc_hash(false); // don't clean the buffer + DBG_VAL_PRINT(w); #ifndef NDEBUG for(size_t j = 0; j < n; ++j) - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(amount_commitments[j] + amount_commitments_for_rp_aggregation[j] == u_secrets[j] * (blinded_asset_ids[j] + crypto::c_point_U) + g_secrets[j] * c_point_G, 20); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(amount_commitments[j] + w * amount_commitments_for_rp_aggregation[j] == u_secrets[j] * (blinded_asset_ids[j] + w * crypto::c_point_U) + (g_secrets0[j] + w * g_secrets1[j]) * c_point_G, 20); #endif result.amount_commitments_for_rp_aggregation.clear(); @@ -284,16 +293,12 @@ namespace crypto std::vector asset_tag_plus_U_vec(n); for(size_t j = 0; j < n; ++j) - asset_tag_plus_U_vec[j] = blinded_asset_ids[j] + crypto::c_point_U; + asset_tag_plus_U_vec[j] = blinded_asset_ids[j] + w * crypto::c_point_U; std::vector R(n); for(size_t j = 0; j < n; ++j) - R[j].assign_mul_plus_G(r0[j], asset_tag_plus_U_vec[j], r1[j]); + R[j].assign_mul_plus_G(r0[j], asset_tag_plus_U_vec[j], r1[j]); // R[j] = r0[j] * asset_tag_plus_U_vec[j] + r1[j] * G - crypto::hash_helper_t::hs_t hash_calculator(1 + 3 * n); - hash_calculator.add_hash(m); - hash_calculator.add_points_array(amount_commitments); - hash_calculator.add_points_array(amount_commitments_for_rp_aggregation); hash_calculator.add_points_array(R); result.c = hash_calculator.calc_hash(); @@ -303,7 +308,7 @@ namespace crypto for(size_t j = 0; j < n; ++j) { result.y0s.emplace_back(r0[j] - result.c * u_secrets[j]); - result.y1s.emplace_back(r1[j] - result.c * g_secrets[j]); + result.y1s.emplace_back(r1[j] - result.c * (g_secrets0[j] + w * g_secrets1[j])); result.amount_commitments_for_rp_aggregation.emplace_back((crypto::c_scalar_1div8 * amount_commitments_for_rp_aggregation[j]).to_public_key()); } @@ -328,11 +333,6 @@ namespace crypto CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.y0s.size() == n, 4); CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.y1s.size() == n, 5); - std::vector asset_tag_plus_U_vec(n); - for(size_t j = 0; j < n; ++j) - asset_tag_plus_U_vec[j] = crypto::point_t(*blinded_asset_ids_1div8[j]).modify_mul8() + crypto::c_point_U; - DBG_VAL_PRINT(asset_tag_plus_U_vec); - crypto::hash_helper_t::hs_t hash_calculator(1 + 3 * n); hash_calculator.add_hash(m); DBG_VAL_PRINT(m); @@ -355,12 +355,20 @@ namespace crypto DBG_VAL_PRINT(Arpa); } + scalar_t w = hash_calculator.calc_hash(false); // don't clear the buffer + DBG_VAL_PRINT(w); + + std::vector asset_tag_plus_U_vec(n); + for(size_t j = 0; j < n; ++j) + asset_tag_plus_U_vec[j] = crypto::point_t(*blinded_asset_ids_1div8[j]).modify_mul8() + w * crypto::c_point_U; + DBG_VAL_PRINT(asset_tag_plus_U_vec); + for(size_t j = 0; j < n; ++j) { hash_calculator.add_pub_key(crypto::point_t( sig.y0s[j] * asset_tag_plus_U_vec[j] + sig.y1s[j] * crypto::c_point_G + - sig.c * (amount_commitments_pt[j] + amount_commitments_for_rp_aggregation_pt[j]) + sig.c * (amount_commitments_pt[j] + w * amount_commitments_for_rp_aggregation_pt[j]) ).to_public_key()); DBG_VAL_PRINT(hash_calculator.m_elements.back().pk); } diff --git a/src/crypto/zarcanum.h b/src/crypto/zarcanum.h index 53a6ebfc..34a00d6e 100644 --- a/src/crypto/zarcanum.h +++ b/src/crypto/zarcanum.h @@ -176,7 +176,7 @@ namespace crypto scalar_t c; // common challenge }; - bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets, + bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets0, const scalar_vec_t& g_secrets1, const std::vector& amount_commitments, const std::vector& amount_commitments_for_rp_aggregation, const std::vector& blinded_asset_ids, diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 35dfc7cb..e78dc4bc 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -127,19 +127,17 @@ namespace currency // prepare data for aggregation proof std::vector amount_commitments_for_rp_aggregation; // E' = amount * U + y' * G - crypto::scalar_vec_t g_secrets; // amount + y' - crypto::scalar_vec_t y_primes; // y' + crypto::scalar_vec_t y_primes; // y' for (size_t out_index = out_index_start, i = 0; i < outs_count; ++out_index, ++i) { crypto::scalar_t y_prime = crypto::scalar_t::random(); amount_commitments_for_rp_aggregation.emplace_back(outs_gen_context.amounts[i] * crypto::c_point_U + y_prime * crypto::c_point_G); // E'_j = e_j * U + y'_j * G - g_secrets.emplace_back(outs_gen_context.amount_blinding_masks[i] + y_prime); y_primes.emplace_back(std::move(y_prime)); } // aggregation proof uint8_t err = 0; - bool r = crypto::generate_vector_UG_aggregation_proof(context_hash, outs_gen_context.amounts, g_secrets, + bool r = crypto::generate_vector_UG_aggregation_proof(context_hash, outs_gen_context.amounts, outs_gen_context.amount_blinding_masks, y_primes, outs_gen_context.amount_commitments, amount_commitments_for_rp_aggregation, outs_gen_context.blinded_asset_ids, result.aggregation_proof, &err);