Skip to content

Commit

Permalink
Refactored MNT4 code and added MNT6 exponentiation #355
Browse files Browse the repository at this point in the history
  • Loading branch information
vo-nil committed Apr 29, 2024
1 parent 059533f commit 56221db
Show file tree
Hide file tree
Showing 10 changed files with 992 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2024 Vasiliy Olekhov <vasiliy.olekhov@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.
//---------------------------------------------------------------------------//
// @file Declaration of F_p^6 elements over an abstract entity (to be used with constraints)
// with F_p^6 = Fp^2 over Fp^3:
// Fp^6 = Fp^2[x]/(x^2 - u), u = (0,1,0)
// Fp^3 = Fp[y]/(y^3 - v), for MNT6: v = 5
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_ABSTRACT_FP4_HPP
#define CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_ABSTRACT_FP4_HPP

#include <array>
#include <cstddef>

#include <nil/crypto3/algebra/fields/fp6_2over3.hpp>

namespace nil {
namespace blueprint {
namespace components {
namespace detail {

template<typename T, typename UnderlyingFieldType>
class abstract_fp6_element{
public:
using policy_type_fp6 = crypto3::algebra::fields::fp6_2over3<UnderlyingFieldType>;
std::array<T, 6> x;

T& operator[](std::size_t idx) {
return x[idx];
}
const T& operator[](std::size_t idx) const {
return x[idx];
}

constexpr abstract_fp6_element operator*(abstract_fp6_element const& y) {
// Devegili et al - Multiplication and squaring in pairing-friendly fields
// https://eprint.iacr.org/2006/471.pdf, page 15, direct sextic
// Take note on isomorphism between a (Fp 2 over 3) and c (direct sextic)
// Indices map is on page 17
constexpr std::size_t
_0 = 0, _1 = 3, _2 = 1,
_3 = 4, _4 = 2, _5 = 5;

constexpr auto s = policy_type_fp6::extension_policy::non_residue;

T c[6] = {
x[_0]*y[_0] + s*(x[_1]*y[_5] + x[_2]*y[_4] + x[_3]*y[_3] + x[_4]*y[_2] + x[_5]*y[_1]),
x[_0]*y[_1] + x[_1]*y[_0] + s*(x[_2]*y[_5] + x[_3]*y[_4] + x[_4]*y[_3] + x[_5]*y[_2]),
x[_0]*y[_2] + x[_1]*y[_1] + x[_2]*y[_0] + s*(x[_3]*y[_5] + x[_4]*y[_4] + x[_5]*y[_3]),
x[_0]*y[_3] + x[_1]*y[_2] + x[_2]*y[_1] + x[_3]*y[_0] + s*(x[_4]*y[_5] + x[_5]*y[_4]),
x[_0]*y[_4] + x[_1]*y[_3] + x[_2]*y[_2] + x[_3]*y[_1] + x[_4]*y[_0] + s* x[_5]*y[_5],
x[_0]*y[_5] + x[_1]*y[_4] + x[_2]*y[_3] + x[_3]*y[_2] + x[_4]*y[_1] + x[_5]*y[_0]
};

return { c[0], c[2], c[4], c[1], c[3], c[5]};
}

constexpr abstract_fp6_element operator*(const int a) {
return { x[0]*a, x[1]*a, x[2]*a, x[3]*a, x[4]*a, x[5]*a };
}
friend abstract_fp6_element operator*(const int a, abstract_fp6_element const& x) {
return { x[0]*a, x[1]*a, x[2]*a, x[3]*a, x[4]*a, x[5]*a };
}
constexpr abstract_fp6_element operator+(abstract_fp6_element const& y) {
return { x[0] + y[0], x[1] + y[1], x[2] + y[2], x[3] + y[3], x[4] + y[4], x[5] + y[5]};
}
constexpr abstract_fp6_element operator-(abstract_fp6_element const& y) {
return { x[0] - y[0], x[1] - y[1], x[2] - y[2], x[3] - y[3], x[4] - y[4], x[5] - y[5]};
}
};

} // namespace detail
} // namespace components
} // namespace blueprint
} // namespace nil

#endif // CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_abstract_FP4_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,11 @@ namespace nil {
using constraint_type = crypto3::zk::snark::plonk_constraint<BlueprintFieldType>;
using policy_type = crypto3::algebra::fields::fp4<BlueprintFieldType>;
using integral_type = typename BlueprintFieldType::integral_type;
using extended_integral_type = typename BlueprintFieldType::extended_integral_type;
using fp4_element = typename policy_type::value_type;
using fp4_constraint = detail::abstract_fp4_element<constraint_type, BlueprintFieldType>;

private:
static std::vector<std::uint8_t> base4(extended_integral_type x) {
static std::vector<std::uint8_t> base4(integral_type x) {
if (x > 0) {
std::vector<std::uint8_t> res = {std::uint8_t(x % 4)};
x /= 4;
Expand All @@ -85,7 +84,7 @@ namespace nil {
}
}

static std::size_t gates_amount_internal(extended_integral_type power) {
static std::size_t gates_amount_internal(integral_type power) {
std::size_t gates = 1; // at least one for power-4 operations
std::vector<std::uint8_t> exp_plan = base4(power);
if (exp_plan.size() - std::count(exp_plan.begin(),exp_plan.end(),0) > 1) {
Expand All @@ -100,28 +99,28 @@ namespace nil {
public:
using manifest_type = plonk_component_manifest;

const extended_integral_type power/* = pairing::detail::pairing_params<curve_type>::final_exponent_last_chunk_abs_of_w0*/;
const integral_type power/* = pairing::detail::pairing_params<curve_type>::final_exponent_last_chunk_abs_of_w0*/;

const std::vector<std::uint8_t> exp_plan, exp_precompute;
const std::size_t rows_amount;

class gate_manifest_type : public component_gate_manifest {
const extended_integral_type power;
std::array<std::size_t,3> gates_footprint(extended_integral_type power) const {
const integral_type power;
std::array<std::size_t,3> gates_footprint(integral_type power) const {
std::vector<std::uint8_t> exp_plan = base4(power);
return { (exp_plan.size() - std::count(exp_plan.begin(),exp_plan.end(),0) > 1),
(std::count(exp_plan.begin(),exp_plan.end(),3) > 0),
(std::count(exp_plan.begin(),exp_plan.end(),2) > 0) };
}
public:
gate_manifest_type(extended_integral_type power) : power(power) {}
gate_manifest_type(integral_type power) : power(power) {}

std::uint32_t gates_amount() const override {
return mnt4_fp4_fixed_power::gates_amount_internal(power);
}

bool operator<(const component_gate_manifest *other) const override {
extended_integral_type o_power = dynamic_cast<const gate_manifest_type*>(other)->power;
integral_type o_power = dynamic_cast<const gate_manifest_type*>(other)->power;

std::array<std::size_t, 3>
gates = gates_footprint(power),
Expand All @@ -132,16 +131,15 @@ namespace nil {

static gate_manifest get_gate_manifest(
std::size_t witness_amount,
std::size_t lookup_column_amount,
extended_integral_type power)
integral_type power)
{
static gate_manifest manifest = gate_manifest(gate_manifest_type(power));
return manifest;
}

static manifest_type get_manifest() {
static manifest_type manifest = manifest_type(
std::shared_ptr<manifest_param>(new manifest_range_param(4, 300, 1)),
std::shared_ptr<manifest_param>(new manifest_single_value_param(policy_type::arity)),
false
);
return manifest;
Expand All @@ -159,7 +157,9 @@ namespace nil {
return precompute;
}

static std::size_t get_rows_amount(extended_integral_type power)
static std::size_t get_rows_amount(
std::size_t witness_amount,
integral_type power)
{
std::vector<std::uint8_t>
exp_plan = base4(power),
Expand Down Expand Up @@ -208,44 +208,46 @@ namespace nil {
template<typename ContainerType> explicit
mnt4_fp4_fixed_power(
ContainerType witness,
extended_integral_type power) :
integral_type power) :
component_type(witness, {}, {}, get_manifest()),
power(power),
exp_plan(base4(power)),
exp_precompute(get_precomputed_exps(exp_plan)),
rows_amount(get_rows_amount(power))
rows_amount(get_rows_amount(this->witness_amount(), power))
{ };

template<typename WitnessContainerType, typename ConstantContainerType, typename PublicInputContainerType>
mnt4_fp4_fixed_power(
WitnessContainerType witness,
ConstantContainerType constant,
PublicInputContainerType public_input,
extended_integral_type power) :
integral_type power) :
component_type(witness, constant, public_input, get_manifest()),
power(power),
exp_plan(base4(power)),
exp_precompute(get_precomputed_exps(exp_plan)),
rows_amount(get_rows_amount(power))
rows_amount(get_rows_amount(this->witness_amount(), power))
{ };

mnt4_fp4_fixed_power(
std::initializer_list<typename component_type::witness_container_type::value_type> witnesses,
std::initializer_list<typename component_type::constant_container_type::value_type> constants,
std::initializer_list<typename component_type::public_input_container_type::value_type> public_inputs,
extended_integral_type power) :
integral_type power) :
component_type(witnesses, constants, public_inputs, get_manifest()),
power(power),
exp_plan(base4(power)),
exp_precompute(get_precomputed_exps(exp_plan)),
rows_amount(get_rows_amount(power))
rows_amount(get_rows_amount(this->witness_amount(), power))
{ };
};

/* */

template<typename BlueprintFieldType>
using component_type = mnt4_fp4_fixed_power<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>, BlueprintFieldType>;
using component_type = mnt4_fp4_fixed_power<
crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType>,
BlueprintFieldType>;

template<typename BlueprintFieldType>
typename component_type<BlueprintFieldType>::result_type
Expand Down Expand Up @@ -275,20 +277,9 @@ namespace nil {
std::size_t row = 0;

auto fill_row = [&component, &assignment, &start_row_index, &row](fp4_element const& V) {
value_type d00 = V.data[0].data[0];
value_type d01 = V.data[0].data[1];
value_type d10 = V.data[1].data[0];
value_type d11 = V.data[1].data[1];
assignment.witness(component.W(0),start_row_index + row) = d00;
assignment.witness(component.W(1),start_row_index + row) = d01;
assignment.witness(component.W(2),start_row_index + row) = d10;
assignment.witness(component.W(3),start_row_index + row) = d11;

/*
for(std::size_t i = 0; i < policy_type::arity; i++) {
for(std::size_t i = 0; i < 4; i++) {
assignment.witness(component.W(i),start_row_index + row) = V.data[i/2].data[i % 2];
}
*/
row++;
};

Expand Down
Loading

0 comments on commit 56221db

Please sign in to comment.