diff --git a/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp b/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp index ef42e1b54..f8fdee493 100644 --- a/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp +++ b/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp @@ -63,11 +63,10 @@ namespace nil { * Aniket Kate, Gregory M. Zaverucha, and Ian Goldberg, * */ - template + template struct kzg { typedef CurveType curve_type; - typedef TranscriptHashType transcript_hash_type; typedef typename curve_type::gt_type::value_type gt_value_type; using multiexp_method = typename algebra::policies::multiexp_method_BDLO12; @@ -77,9 +76,6 @@ namespace nil { using verification_key_type = typename curve_type::template g2_type<>::value_type; using commitment_type = typename curve_type::template g1_type<>::value_type; using proof_type = commitment_type; - using transcript_type = transcript::fiat_shamir_heuristic_sequential; - - using serializer = typename nil::marshalling::curve_element_serializer; struct params_type { commitment_key_type commitment_key; @@ -88,13 +84,16 @@ namespace nil { commitment_key(ck), verification_key(vk) {} }; struct public_key_type { - scalar_value_type eval; commitment_type commit; + scalar_value_type z; + scalar_value_type eval; public_key_type() {} - public_key_type(scalar_value_type e, commitment_type c) : eval(e), commit(c) {} + public_key_type(commitment_type c, scalar_value_type z, scalar_value_type e) + : commit(c), z(z), eval(e) {} public_key_type operator=(const public_key_type &other) { eval = other.eval; commit = other.commit; + z = other.z; return *this; } }; @@ -105,8 +104,7 @@ namespace nil { template, - KZG>::value, + commitments::kzg, KZG>::value, bool>::type = true> static typename KZG::params_type setup(std::size_t max_degree, typename KZG::scalar_value_type alpha) { typename KZG::scalar_value_type alpha_scaled = alpha; @@ -121,27 +119,11 @@ namespace nil { return typename KZG::params_type(commitment_key, verification_key); } - template, - KZG>::value, - bool>::type = true> - static typename KZG::transcript_type setup_transcript(const typename KZG::params_type ¶ms) { - typename KZG::transcript_type transcript = typename KZG::transcript_type(); - for (auto g1_elem : params.commitment_key) { - transcript(KZG::serializer::point_to_octets(g1_elem)); - } - transcript(KZG::serializer::point_to_octets(params.verification_key)); - - return transcript; - } template, - KZG>::value, + commitments::kzg, KZG>::value, bool>::type = true> static typename KZG::commitment_type commit(const typename KZG::params_type ¶ms, const typename math::polynomial &f) { @@ -153,18 +135,16 @@ namespace nil { template, - KZG>::value, + commitments::kzg, KZG>::value, bool>::type = true> static typename KZG::proof_type proof_eval(typename KZG::params_type params, const typename math::polynomial &f, - typename KZG::scalar_value_type z, - typename KZG::scalar_value_type eval) { + typename KZG::scalar_value_type z) { const typename math::polynomial denominator_polynom = {-z, 1}; typename math::polynomial q = f; - q[0] -= eval; + q[0] -= f.evaluate(z); auto r = q % denominator_polynom; if (r != typename KZG::scalar_value_type(0)) { throw std::runtime_error("incorrect eval or point z"); @@ -177,39 +157,29 @@ namespace nil { template, - KZG>::value, + commitments::kzg, KZG>::value, bool>::type = true> - static std::pair - proof_eval(typename KZG::params_type params, + static typename KZG::proof_type proof_eval(typename KZG::params_type params, const typename math::polynomial &f, - typename KZG::transcript_type &transcript) { - auto commitment = commit(params, f); - transcript(KZG::serializer::point_to_octets(commitment)); - auto z = transcript.template challenge(); - auto eval = f.evaluate(z); - return {proof_eval(params, f, z, eval), {eval, commitment}}; + typename KZG::public_key_type &pk) { + + return proof_eval(params, f, pk.z); } template, - KZG>::value, + commitments::kzg, KZG>::value, bool>::type = true> - static bool verify_eval(typename KZG::params_type params, - typename KZG::proof_type proof, - typename KZG::public_key_type pk, - typename KZG::transcript_type &transcript) { - transcript(KZG::serializer::point_to_octets(pk.commit)); - - auto i = transcript.template challenge(); + static bool verify_eval(const typename KZG::params_type ¶ms, + const typename KZG::proof_type &proof, + const typename KZG::public_key_type &public_key) { auto A_1 = algebra::precompute_g1(proof); auto A_2 = algebra::precompute_g2(params.verification_key - - i * KZG::curve_type::template g2_type<>::value_type::one()); - auto B_1 = algebra::precompute_g1(pk.eval * KZG::curve_type::template g1_type<>::value_type::one() - - pk.commit); + public_key.z * KZG::curve_type::template g2_type<>::value_type::one()); + auto B_1 = algebra::precompute_g1(public_key.eval * KZG::curve_type::template g1_type<>::value_type::one() - + public_key.commit); auto B_2 = algebra::precompute_g2(KZG::curve_type::template g2_type<>::value_type::one()); typename KZG::gt_value_type gt3 = algebra::double_miller_loop(A_1, A_2, B_1, B_2); @@ -231,7 +201,7 @@ namespace nil { * */ template - struct batched_kzg : public kzg { + struct batched_kzg : public kzg { typedef CurveType curve_type; typedef TranscriptHashType transcript_hash_type; @@ -246,18 +216,23 @@ namespace nil { using batch_of_batches_of_polynomials_type = std::array>, batch_size>; using evals_type = std::array, batch_size>; using batched_proof_type = std::array; + + using transcript_type = transcript::fiat_shamir_heuristic_sequential; + using serializer = typename nil::marshalling::curve_element_serializer; - using basic_kzg = kzg; + using basic_kzg = kzg; using params_type = typename basic_kzg::params_type; struct batched_public_key_type { std::array, batch_size> commits; + std::array zs; evals_type evals; batched_public_key_type() {}; - batched_public_key_type(std::array commitments, evals_type evals) - : commits(commitments), evals(evals) {}; + batched_public_key_type(std::array commitments, + std::array zs, evals_type evals) : commits(commitments), zs(zs), evals(evals) {}; batched_public_key_type operator=(const batched_public_key_type &other) { commits = other.commits; + zs = other.zs; evals = other.evals; return *this; } @@ -266,6 +241,22 @@ namespace nil { } // namespace commitments namespace algorithms { + template, + KZG>::value, + bool>::type = true> + static typename KZG::transcript_type setup_transcript(const typename KZG::params_type ¶ms) { + typename KZG::transcript_type transcript = typename KZG::transcript_type(); + for (auto g1_elem : params.commitment_key) { + transcript(KZG::serializer::point_to_octets(g1_elem)); + } + transcript(KZG::serializer::point_to_octets(params.verification_key)); + + return transcript; + } template, + KZG>::value, + bool>::type = true> + static typename KZG::batched_public_key_type setup_public_key(const typename KZG::params_type ¶ms, + const typename KZG::batch_of_batches_of_polynomials_type &polys, + const std::array zs) { + typename KZG::batched_public_key_type pk; + std::array evals; + for (int i = 0; i < KZG::batch_size; ++i) { + pk.commits[i] = commit(params, polys[i]); + } + pk.zs = zs; + pk.evals = evaluate_polynomials(polys, zs); + + return pk; + } template, KZG>::value, bool>::type = true> - static std::pair - proof_eval(const typename KZG::params_type ¶ms, + static typename KZG::batched_proof_type proof_eval(const typename KZG::params_type ¶ms, const typename KZG::batch_of_batches_of_polynomials_type &polys, + typename KZG::batched_public_key_type &public_key, typename KZG::transcript_type &transcript) { typename KZG::batched_proof_type proof; - typename KZG::batched_public_key_type public_key; - std::array zs; for (std::size_t i = 0; i < KZG::batch_size; ++i) { auto commits = commit(params, polys[i]); @@ -348,14 +358,11 @@ namespace nil { transcript(KZG::serializer::point_to_octets(commit)); } auto gamma = transcript.template challenge(); - zs[i] = transcript.template challenge(); auto accum = accumulate(polys[i], gamma); - proof[i] = proof_eval(params, accum, zs[i], accum.evaluate(zs[i])); - public_key.commits[i] = commits; + proof[i] = proof_eval(params, accum, public_key.zs[i]); } - public_key.evals = evaluate_polynomials(polys, zs); - return {proof, public_key}; + return proof; } template::type = true> static bool verify_eval(typename KZG::params_type params, const typename KZG::batched_proof_type &proof, - const typename KZG::batched_public_key_type &pk, + const typename KZG::batched_public_key_type &public_key, typename KZG::transcript_type &transcript) { - std::array zs; std::array gammas; for (std::size_t i = 0; i < KZG::batch_size; ++i) { - for (const auto &commit : pk.commits[i]) { + for (const auto &commit : public_key.commits[i]) { transcript(KZG::serializer::point_to_octets(commit)); } gammas[i] = transcript.template challenge(); - zs[i] = transcript.template challenge(); } - typename KZG::scalar_value_type r = transcript.template challenge(); + typename KZG::scalar_value_type r = algebra::random_element(); auto F = KZG::curve_type::template g1_type<>::value_type::zero(); auto z_r_proofs = KZG::curve_type::template g1_type<>::value_type::zero(); auto r_proofs = KZG::curve_type::template g1_type<>::value_type::zero(); auto cur_r = KZG::scalar_value_type::one(); for (std::size_t i = 0; i < KZG::batch_size; ++i) { - auto eval_accum = pk.evals[i].back(); - auto comm_accum = pk.commits[i].back(); - for (int j = pk.commits[i].size() - 2; j >= 0; --j) { - comm_accum = (gammas[i] * comm_accum) + pk.commits[i][j]; - eval_accum = (eval_accum * gammas[i]) + pk.evals[i][j]; + auto eval_accum = public_key.evals[i].back(); + auto comm_accum = public_key.commits[i].back(); + for (int j = public_key.commits[i].size() - 2; j >= 0; --j) { + comm_accum = (gammas[i] * comm_accum) + public_key.commits[i][j]; + eval_accum = (eval_accum * gammas[i]) + public_key.evals[i][j]; } F = F + cur_r * (comm_accum - eval_accum * KZG::curve_type::template g1_type<>::value_type::one()); - z_r_proofs = z_r_proofs + cur_r * zs[i] * proof[i]; + z_r_proofs = z_r_proofs + cur_r * public_key.zs[i] * proof[i]; r_proofs = r_proofs - cur_r * proof[i]; cur_r = cur_r * r; } diff --git a/test/commitment/kzg.cpp b/test/commitment/kzg.cpp index 8f739c883..dbd8dc907 100644 --- a/test/commitment/kzg.cpp +++ b/test/commitment/kzg.cpp @@ -63,12 +63,12 @@ BOOST_AUTO_TEST_CASE(kzg_basic_test) { typedef typename curve_type::base_field_type base_field_type; typedef typename curve_type::scalar_field_type scalar_field_type; typedef typename curve_type::scalar_field_type::value_type scalar_value_type; - typedef hashes::sha2<256> transcript_hash_type; - typedef zk::commitments::kzg kzg_type; - typedef kzg_type::transcript_type transcript_type; + + typedef zk::commitments::kzg kzg_type; scalar_value_type alpha = 10; std::size_t n = 16; + scalar_value_type z = 2; const polynomial f = {-1, 1, 2, 3}; auto params = zk::algorithms::setup(n, alpha); @@ -81,11 +81,10 @@ BOOST_AUTO_TEST_CASE(kzg_basic_test) { auto commit = zk::algorithms::commit(params, f); BOOST_CHECK(3209 * curve_type::template g1_type<>::value_type::one() == commit); - transcript_type transcript = zk::algorithms::setup_transcript(params); - auto [proof, pk] = zk::algorithms::proof_eval(params, f, transcript); + typename kzg_type::public_key_type pk = {commit, z, f.evaluate(z)}; + auto proof = zk::algorithms::proof_eval(params, f, pk); - transcript_type transcript_verifier = zk::algorithms::setup_transcript(params); - BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk, transcript_verifier)); + BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk)); } BOOST_AUTO_TEST_CASE(kzg_random_test) { @@ -95,22 +94,21 @@ BOOST_AUTO_TEST_CASE(kzg_random_test) { typedef typename curve_type::base_field_type base_field_type; typedef typename curve_type::scalar_field_type scalar_field_type; typedef typename curve_type::scalar_field_type::value_type scalar_value_type; - typedef hashes::sha2<256> transcript_hash_type; - typedef zk::commitments::kzg kzg_type; - typedef kzg_type::transcript_type transcript_type; + + typedef zk::commitments::kzg kzg_type; scalar_value_type alpha = algebra::random_element(); std::size_t n = 298; + scalar_value_type z = algebra::random_element(); const polynomial f = {-1, 1, 2, 3, 5, -15}; auto params = zk::algorithms::setup(n, alpha); auto commit = zk::algorithms::commit(params, f); - transcript_type transcript = zk::algorithms::setup_transcript(params); - auto [proof, pk] = zk::algorithms::proof_eval(params, f, transcript); + typename kzg_type::public_key_type pk = {commit, z, f.evaluate(z)}; + auto proof = zk::algorithms::proof_eval(params, f, pk); - transcript_type transcript_verifier = zk::algorithms::setup_transcript(params); - BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk, transcript_verifier)); + BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk)); } BOOST_AUTO_TEST_CASE(kzg_false_test) { @@ -120,74 +118,62 @@ BOOST_AUTO_TEST_CASE(kzg_false_test) { typedef typename curve_type::base_field_type base_field_type; typedef typename curve_type::scalar_field_type scalar_field_type; typedef typename curve_type::scalar_field_type::value_type scalar_value_type; - typedef hashes::sha2<256> transcript_hash_type; - typedef zk::commitments::kzg kzg_type; - typedef kzg_type::transcript_type transcript_type; + + typedef zk::commitments::kzg kzg_type; scalar_value_type alpha = 10; std::size_t n = 16; + scalar_value_type z = 5; const polynomial f = {100, 1, 2, 3}; auto params = zk::algorithms::setup(n, alpha); auto commit = zk::algorithms::commit(params, f); - transcript_type transcript = zk::algorithms::setup_transcript(params); - auto [proof, pk] = zk::algorithms::proof_eval(params, f, transcript); - - transcript_type transcript_verifier = zk::algorithms::setup_transcript(params); - BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk, transcript_verifier)); + typename kzg_type::public_key_type pk = {commit, z, f.evaluate(z)}; + auto proof = zk::algorithms::proof_eval(params, f, pk); - // wrong transcript - already used - BOOST_CHECK(!zk::algorithms::verify_eval(params, proof, pk, transcript_verifier)); + BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk)); // wrong params auto ck2 = params.commitment_key; ck2[0] = ck2[0] * 2; auto params2 = kzg_type::params_type(ck2, params.verification_key * 2); - transcript_type transcript_verifier_wp = zk::algorithms::setup_transcript(params2); - BOOST_CHECK(!zk::algorithms::verify_eval(params2, proof, pk, transcript_verifier_wp)); + BOOST_CHECK(!zk::algorithms::verify_eval(params2, proof, pk)); // wrong commit auto pk2 = pk; pk2.commit = pk2.commit * 2; - transcript_type transcript_verifier_wc = zk::algorithms::setup_transcript(params); - BOOST_CHECK(!zk::algorithms::verify_eval(params, proof, pk2, transcript_verifier_wc)); + BOOST_CHECK(!zk::algorithms::verify_eval(params, proof, pk2)); // wrong eval pk2 = pk; pk2.eval *= 2; - transcript_type transcript_verifier_we = zk::algorithms::setup_transcript(params); - BOOST_CHECK(!zk::algorithms::verify_eval(params, proof, pk2, transcript_verifier_we)); + BOOST_CHECK(!zk::algorithms::verify_eval(params, proof, pk2)); // wrong proof { // wrong params typename kzg_type::proof_type proof2; - typename kzg_type::public_key_type pk2; bool exception = false; - transcript_type transcript_wp = zk::algorithms::setup_transcript(params); - try {auto [proof2, pk2] = zk::algorithms::proof_eval(params2, f, transcript_wp);} + try {auto proof2 = zk::algorithms::proof_eval(params2, f, pk);} catch (std::runtime_error& e) {exception = true;} if (!exception) { BOOST_CHECK(proof2 != proof); - transcript_type transcript_wp_verifier = zk::algorithms::setup_transcript(params2); - BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk, transcript_wp_verifier), "wrong params"); + BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk), "wrong params"); } // wrong transcript exception = false; - try {auto [proof2, pk2] = zk::algorithms::proof_eval(params, f, transcript_wp);} + try {auto proof2 = zk::algorithms::proof_eval(params, f, pk2);} catch (std::runtime_error& e) {exception = true;} if (!exception) { BOOST_CHECK(proof2 != proof); - transcript_type transcript_wt_verifier = zk::algorithms::setup_transcript(params); - BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk, transcript_wt_verifier), "wrong transcript"); + BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk), "wrong transcript"); } } auto proof2 = proof * 2; - transcript_type transcript_wp_verifier = zk::algorithms::setup_transcript(params); - BOOST_CHECK(!zk::algorithms::verify_eval(params, proof2, pk, transcript_wp_verifier)); + BOOST_CHECK(!zk::algorithms::verify_eval(params, proof2, pk)); } BOOST_AUTO_TEST_SUITE_END() @@ -220,11 +206,13 @@ BOOST_AUTO_TEST_CASE(kzg_batched_basic_test) { {{91, 92, 93, 94, 95, 96, 97, 98}}, }}; typename kzg_type::batch_of_batches_of_polynomials_type polys = {fs, gs}; + std::array zs = {101, 3}; auto params = zk::algorithms::setup(n, alpha); + typename kzg_type::batched_public_key_type pk = zk::algorithms::setup_public_key(params, polys, zs); transcript_type transcript = zk::algorithms::setup_transcript(params); - auto [proof, pk] = zk::algorithms::proof_eval(params, polys, transcript); + auto proof = zk::algorithms::proof_eval(params, polys, pk, transcript); transcript_type transcript_verification = zk::algorithms::setup_transcript(params); BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk, transcript_verification)); @@ -261,11 +249,13 @@ BOOST_AUTO_TEST_CASE(kzg_batched_random_test) { {{91, 92, 93, 94, 95, 96, 97, 100, 1, 2, 3}}, }}; const kzg_type::batch_of_batches_of_polynomials_type polys = {f0, f1, f2}; + std::array zs = {101, 3, 5}; auto params = zk::algorithms::setup(n, alpha); + typename kzg_type::batched_public_key_type pk = zk::algorithms::setup_public_key(params, polys, zs); transcript_type transcript = zk::algorithms::setup_transcript(params); - auto [proof, pk] = zk::algorithms::proof_eval(params, polys, transcript); + auto proof = zk::algorithms::proof_eval(params, polys, pk, transcript); transcript_type transcript_verification = zk::algorithms::setup_transcript(params); BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk, transcript_verification)); @@ -300,11 +290,13 @@ BOOST_AUTO_TEST_CASE(kzg_batched_false_test) { {{71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81}}, }}; typename kzg_type::batch_of_batches_of_polynomials_type polys = {fs, gs, hs}; + std::array zs = {101, 3, 5}; auto params = zk::algorithms::setup(n, alpha); + typename kzg_type::batched_public_key_type pk = zk::algorithms::setup_public_key(params, polys, zs);; transcript_type transcript = zk::algorithms::setup_transcript(params); - auto [proof, pk] = zk::algorithms::proof_eval(params, polys, transcript); + auto proof = zk::algorithms::proof_eval(params, polys, pk, transcript); transcript_type transcript_verification = zk::algorithms::setup_transcript(params); BOOST_CHECK(zk::algorithms::verify_eval(params, proof, pk, transcript_verification)); @@ -346,10 +338,10 @@ BOOST_AUTO_TEST_CASE(kzg_batched_false_test) { { // wrong params typename kzg_type::batched_proof_type proof2; - typename kzg_type::batched_public_key_type pk2; + typename kzg_type::batched_public_key_type pk2 = zk::algorithms::setup_public_key(params2, polys, zs); bool exception = false; transcript_type transcript_wpp = zk::algorithms::setup_transcript(params2); - try {auto [proof2, pk2] = zk::algorithms::proof_eval(params2, polys, transcript_wpp);} + try {auto proof2 = zk::algorithms::proof_eval(params2, polys, pk, transcript_wpp);} catch (std::runtime_error& e) {exception = true;} if (!exception) { BOOST_CHECK(proof2 != proof); @@ -359,7 +351,7 @@ BOOST_AUTO_TEST_CASE(kzg_batched_false_test) { // wrong transcript - used exception = false; - try {auto [proof2, pk2] = zk::algorithms::proof_eval(params, polys, transcript_wpp);} + try {auto proof2 = zk::algorithms::proof_eval(params, polys, pk, transcript_wpp);} catch (std::runtime_error& e) {exception = true;} if (!exception) { BOOST_CHECK(proof2 != proof); @@ -370,13 +362,48 @@ BOOST_AUTO_TEST_CASE(kzg_batched_false_test) { // wrong evals exception = false; transcript_type transcript_wpe = zk::algorithms::setup_transcript(params); - try {auto [proof2, pk2] = zk::algorithms::proof_eval(params, polys, transcript_wpe);} + try {auto proof2 = zk::algorithms::proof_eval(params, polys, pk_we, transcript_wpe);} catch (std::runtime_error& e) {exception = true;} if (!exception) { BOOST_CHECK(proof2 != proof); transcript_type transcript_verification_wpe = zk::algorithms::setup_transcript(params); BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk, transcript_verification_wpe), "wrong evals"); } + + // wrong zs + auto pk_zs = pk; + pk_zs.zs[0] = pk_zs.zs[0] * 2; + exception = false; + transcript_type transcript_wzs = zk::algorithms::setup_transcript(params); + try {auto proof2 = zk::algorithms::proof_eval(params, polys, pk_zs, transcript_wzs);} + catch (std::runtime_error& e) {exception = true;} + if (!exception) { + BOOST_CHECK(proof2 != proof); + transcript_type transcript_verification_wpp = zk::algorithms::setup_transcript(params); + BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk, transcript_verification_wpp), "wrong params"); + } + + // wrong commits + exception = false; + transcript_type transcript_wcs = zk::algorithms::setup_transcript(params); + try {auto proof2 = zk::algorithms::proof_eval(params, polys, pk_we, transcript_wcs);} + catch (std::runtime_error& e) {exception = true;} + if (!exception) { + BOOST_CHECK(proof2 != proof); + transcript_type transcript_verification_wpp = zk::algorithms::setup_transcript(params); + BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk, transcript_verification_wpp), "wrong params"); + } + + // wrong pk + exception = false; + transcript_type transcript_wpk = zk::algorithms::setup_transcript(params); + try {auto proof2 = zk::algorithms::proof_eval(params, polys, pk2, transcript_wpk);} + catch (std::runtime_error& e) {exception = true;} + if (!exception) { + BOOST_CHECK(proof2 != proof); + transcript_type transcript_verification_wpp = zk::algorithms::setup_transcript(params); + BOOST_CHECK_MESSAGE(!zk::algorithms::verify_eval(params, proof2, pk, transcript_verification_wpp), "wrong params"); + } } auto proof2 = proof; proof2.back() = proof2.back() * 2;