Skip to content

Commit

Permalink
KZG updated, KZG test added #20
Browse files Browse the repository at this point in the history
  • Loading branch information
Kate committed Mar 15, 2022
1 parent 9ad24ca commit 7264b36
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 81 deletions.
139 changes: 58 additions & 81 deletions include/nil/crypto3/zk/commitments/polynomial/kzg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright (c) 2018-2021 Mikhail Komarov <nemo@nil.foundation>
// Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
// Copyright (c) 2020-2021 Ilias Khairullin <ilias@nil.foundation>
// Copyright (c) 2022 Ekaterina Chukavina <kate@nil.foundation>
//
// MIT License
//
Expand All @@ -23,33 +24,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//---------------------------------------------------------------------------//
// @file This module implements two binding commitment systems used in the Groth16
// aggregation.
// The first one is a commitment scheme that commits to a single vector $a$ of
// length n in the second base group $G_1$ (for example):
// * it requires a structured SRS $v_1$ of the form $(h,h^u,h^{u^2}, ...
// ,g^{h^{n-1}})$ with $h \in G_2$ being a random generator of $G_2$ and $u$ a
// random scalar (coming from a power of tau ceremony for example)
// * it requires a second structured SRS $v_2$ of the form $(h,h^v,h^{v^2},
// ...$ with $v$ being a random scalar different than u (coming from another
// power of tau ceremony for example)
// The Commitment is a tuple $(\prod_{i=0}^{n-1} e(a_i,v_{1,i}),
// \prod_{i=0}^{n-1} e(a_i,v_{2,i}))$
//
// The second one takes two vectors $a \in G_1^n$ and $b \in G_2^n$ and commits
// to them using a similar approach as above. It requires an additional SRS
// though:
// * $v_1$ and $v_2$ stay the same
// * An additional tuple $w_1 = (g^{u^n},g^{u^{n+1}},...g^{u^{2n-1}})$ and $w_2 =
// (g^{v^n},g^{v^{n+1},...,g^{v^{2n-1}})$ where $g$ is a random generator of
// $G_1$
// The commitment scheme returns a tuple:
// * $\prod_{i=0}^{n-1} e(a_i,v_{1,i})e(w_{1,i},b_i)$
// * $\prod_{i=0}^{n-1} e(a_i,v_{2,i})e(w_{2,i},b_i)$
//
// The second commitment scheme enables to save some KZG verification in the
// verifier of the Groth16 verification protocol since we pack two vectors in
// one commitment.

#ifndef CRYPTO3_ZK_COMMITMENTS_KZG_COMMITMENT_HPP
#define CRYPTO3_ZK_COMMITMENTS_KZG_COMMITMENT_HPP
Expand All @@ -62,93 +36,96 @@
#include <boost/iterator/zip_iterator.hpp>
#include <boost/accumulators/accumulators.hpp>

#include <nil/crypto3/math/polynomial/polynomial.hpp>
#include <nil/crypto3/algebra/type_traits.hpp>

#include <nil/crypto3/algebra/algorithms/pair.hpp>
#include <nil/crypto3/algebra/pairing/pairing_policy.hpp>

using namespace nil::crypto3::math;

namespace nil {
namespace crypto3 {
namespace zk {
namespace snark {

template<typename CurveType>
struct kzg_commitment {

typedef CurveType curve_type;
typedef algebra::pairing::pairing_policy<curve_type> pairing;
typedef typename curve_type::gt_type::value_type gt_value_type;

/// Key is a generic commitment key that is instantiated with g and h as basis,
/// and a and b as powers.
using commitment_key_type = std::vector<typename CurveType::template g1_type<>::value_type>;
using verification_key_type = typename CurveType::template g1_type<>::value_type;

using commitment_type = typename CurveType::template g1_type<>::value_type;
using base_field_value_type = typename curve_type::base_field_type::value_type;
using commitment_key_type = std::vector<typename curve_type::template g1_type<>::value_type>;
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;

struct params_type {

std::size_t a;
};

/// Returns both vectors scaled by the given vector entrywise.
/// In other words, it returns $\{v_i^{s_i}\}$
static std::pair<commitment_key_type, verification_key_type> setup(const std::size_t n) {
static std::pair<commitment_key_type, verification_key_type> setup(const std::size_t n,
params_type params) {

kzg_commitment_key<group_type> result;
std::for_each(boost::make_zip_iterator(boost::make_tuple(s_first, a.begin())),
boost::make_zip_iterator(boost::make_tuple(s_last, a.end())),
[&](const boost::tuple<const field_value_type &, const group_value_type &,
const group_value_type &> &t) {
result.a.emplace_back(t.template get<1>() * t.template get<0>());

});
size_t a_scaled = params.a;
commitment_key_type commitment_key = {curve_type::template g1_type<>::value_type::one()};
verification_key_type verification_key =
curve_type::template g2_type<>::value_type::one() * params.a;

return result;
for (std::size_t i = 0; i < n; i++) {
commitment_key.emplace_back(a_scaled * (curve_type::template g1_type<>::value_type::one()));
a_scaled = a_scaled * params.a;
}

return std::make_pair(commitment_key, verification_key);
}

/// Commits to a single vector of G1 elements in the following way:
/// $C = \prod_{i=0}^n (g^{a^i})^{f_i}$
/// Output is $C$
static commitment_type commit(const commitment_key_type &ckey,
const math::polynomial<typename FieldType::value_type> &f,
params_type params) {
BOOST_ASSERT(ckey.has_correct_len(std::distance(f_first, f_last)));

g1_value_type c = g1_value_type::one();
std::for_each_n(boost::make_zip_iterator(boost::make_tuple(f_first, ckey.a.begin())),
std::distance(f_first, f_last),
[&](const boost::tuple<const g1_value_type &, const g1_value_type &> &t) {
for(size_t i = 0; i < (t.template get<0>()); i++){
c = c * t.template get<1>();
}
});

static commitment_type commit(const commitment_key_type &commitment_key,
const polynomial<base_field_value_type> &f) {

commitment_type commitment = f[0] * commitment_key[0];

for (std::size_t i = 0; i < f.size(); i++) {
commitment = commitment + commitment_key[i] * f[i];
}

return commitment;
}

static proof_type proof_eval(commitment_key_type commitment_key,
commitment_type C_f,
typename CurveType::base_field_type::value_type x,
typename CurveType::base_field_type::value_type y,
const math::polynomial<typename FieldType::value_type> &f,
params_type params) {
typename curve_type::base_field_type::value_type x,
typename curve_type::base_field_type::value_type y,
const polynomial<base_field_value_type> &f) {

const math::polynomial<typename FieldType::value_type> denominator_polynom = {1, -x};
const polynomial<base_field_value_type> denominator_polynom = {-x, 1};

const math::polynomial<typename FieldType::value_type> q =
(f - {y})/denominator_polynom;
const polynomial<base_field_value_type> q =
(f + polynomial<base_field_value_type> {-y}) / denominator_polynom;

proof_type p = kzg_commitment::commit(commitment_key, q);
return p;
}

static bool verify_eval(verification_key_type verification_key,
commitment_type C_f,
typename CurveType::base_field_type::value_type x,
typename CurveType::base_field_type::value_type y,
proof_type p,
params_type params) {
base_field_value_type x,
base_field_value_type y,
proof_type p) {

}
typename curve_type::gt_type::value_type gt1 =
algebra::pair<curve_type>(C_f - curve_type::template g1_type<>::value_type::one() * y,
curve_type::template g2_type<>::value_type::one());

typename curve_type::gt_type::value_type gt2 = algebra::pair<curve_type>(
p, verification_key - curve_type::template g2_type<>::value_type::one() * x);

return gt1 == gt2;
}
};
} ; // namespace snark
} // namespace zk
} // namespace crypto3
}; // namespace snark
} // namespace zk
} // namespace crypto3
} // namespace nil

#endif // CRYPTO3_ZK_COMMITMENTS_KZG_COMMITMENT_HPP
69 changes: 69 additions & 0 deletions test/commitment/kzg.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2021 Mikhail Komarov <nemo@nil.foundation>
// Copyright (c) 2021 Nikita Kaskov <nbering@nil.foundation>
// Copyright (c) 2022 Ilia Shirobokov <i.shirobokov@nil.foundation>
// Copyright (c) 2022 Ekaterina Chukavina <kate@nil.foundation>
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//---------------------------------------------------------------------------//

#define BOOST_TEST_MODULE kzg_test

#include <string>

#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/data/monomorphic.hpp>

#include <nil/crypto3/algebra/curves/mnt4.hpp>
#include <nil/crypto3/algebra/random_element.hpp>
#include <nil/crypto3/algebra/pairing/mnt4.hpp>
#include <nil/crypto3/math/polynomial/polynomial.hpp>
#include <nil/crypto3/math/algorithms/unity_root.hpp>
#include <nil/crypto3/math/domains/evaluation_domain.hpp>
#include <nil/crypto3/math/algorithms/make_evaluation_domain.hpp>
#include <nil/crypto3/zk/commitments/polynomial/kzg.hpp>

using namespace nil::crypto3;
using namespace nil::crypto3::zk::snark;
using namespace nil::crypto3::math;

BOOST_AUTO_TEST_SUITE(kzg_test_suite)

BOOST_AUTO_TEST_CASE(kzg_basic_test) {

typedef algebra::curves::mnt4<298> curve_type;
typedef typename curve_type::base_field_type::value_type base_field_value_type;
typedef zk::snark::kzg_commitment<curve_type> kzg_type;

typename kzg_type::params_type kzg_params;
kzg_params.a = 2;

const polynomial<base_field_value_type> f = {1, 1};

auto kzg_keys = kzg_type::setup(298, kzg_params);
auto commit = kzg_type::commit(std::get<0>(kzg_keys), f);
auto proof = kzg_type::proof_eval(std::get<0>(kzg_keys), 1, 2, f);

BOOST_CHECK(kzg_type::verify_eval(std::get<1>(kzg_keys), commit, 1, 2, proof));
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 7264b36

Please sign in to comment.