Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 27 additions & 115 deletions include/nil/blueprint/basic_non_native_policy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,70 +28,32 @@

#include <nil/crypto3/algebra/curves/pallas.hpp>
#include <nil/crypto3/algebra/curves/ed25519.hpp>

#include <nil/crypto3/marshalling/algebra/types/field_element.hpp>
#include <nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp>

#include <nil/blueprint/detail/basic_non_native_policy.hpp>

namespace nil {
namespace blueprint {
namespace detail {

template<typename BlueprintFieldType, typename OperatingFieldType>
struct basic_non_native_policy_field_type;
struct basic_non_native_policy_field_type
: public basic_non_native_policy_field_type_base<BlueprintFieldType, OperatingFieldType,
chopped_lengths_storage<>> { };

/*
* Specialization for non-native Ed25519 base field element on Pallas base field
*/
template<>
struct basic_non_native_policy_field_type<typename crypto3::algebra::curves::pallas::base_field_type,
typename crypto3::algebra::curves::ed25519::base_field_type> {

constexpr static const std::uint32_t ratio = 4; // 66,66,66,66 bits
using non_native_field_type = typename crypto3::algebra::curves::ed25519::base_field_type;
using native_field_type = typename crypto3::algebra::curves::pallas::base_field_type;
using var = crypto3::zk::snark::plonk_variable<typename native_field_type::value_type>;

typedef std::array<var, ratio> non_native_var_type;
typedef std::array<native_field_type::value_type, ratio> chopped_value_type;

constexpr static const std::array<std::size_t, ratio> chunk_sizes = {66, 66, 66, 66};


static native_field_type::value_type get_i_th_chunk(non_native_field_type::value_type input,
std::size_t i_th) {
assert(i_th < ratio && "non-native type does not have that much chunks!");
native_field_type::extended_integral_type result = native_field_type::extended_integral_type(input.data);
native_field_type::integral_type base = 1;
native_field_type::integral_type mask = (base << chunk_sizes[i_th]) - 1;
std::size_t shift = 0;
for (std::size_t i = 1; i <= i_th; i++) {
shift += chunk_sizes[i - 1];
}

return (result >> shift) & mask;
}


static chopped_value_type chop_non_native(non_native_field_type::value_type input) {
chopped_value_type result;
for (std::size_t i = 0; i < ratio; i++) {
result[i] = get_i_th_chunk(input, i);
}
return result;
}

static non_native_field_type::value_type glue_non_native(chopped_value_type input) {
non_native_field_type::value_type result;
native_field_type::integral_type integral_input;
result = non_native_field_type::value_type(native_field_type::integral_type(input[0].data));
for (std::size_t i = 1; i < ratio; i++) {
std::size_t shift = 0;
for (std::size_t j = 0; j < i; j++) {
shift += chunk_sizes[j];
}
result += non_native_field_type::value_type(native_field_type::integral_type(input[i].data) << shift);
}
return result;
}
typename crypto3::algebra::curves::ed25519::base_field_type>
: public basic_non_native_policy_field_type_base<
typename crypto3::algebra::curves::pallas::base_field_type,
typename crypto3::algebra::curves::ed25519::base_field_type,
chopped_lengths_storage<58, 66, 66, 66>> {

using basic_non_native_policy_field_type_base::chopped_value_type;
};

/*
Expand All @@ -101,78 +63,30 @@ namespace nil {
struct basic_non_native_policy_field_type<typename crypto3::algebra::curves::pallas::base_field_type,
typename crypto3::algebra::curves::ed25519::scalar_field_type> {

constexpr static const std::uint32_t ratio = 1;

typedef crypto3::zk::snark::plonk_variable<typename crypto3::algebra::curves::pallas::base_field_type::value_type>
non_native_var_type;
using non_native_var_type = crypto3::zk::snark::plonk_variable<
typename crypto3::algebra::curves::pallas::base_field_type::value_type>;
};

/*
* Specialization for non-native Pallas scalar field element on Pallas base field
*/
// /*
// * Specialization for non-native Pallas scalar field element on Pallas base field
// */
template<>
struct basic_non_native_policy_field_type<typename crypto3::algebra::curves::pallas::base_field_type,
typename crypto3::algebra::curves::pallas::scalar_field_type> {

constexpr static const std::uint32_t ratio = 2; // 254, 1 bits
using non_native_field_type = typename crypto3::algebra::curves::pallas::scalar_field_type;
using native_field_type = typename crypto3::algebra::curves::pallas::base_field_type;
using var = crypto3::zk::snark::plonk_variable<native_field_type>;

typedef std::array<var, ratio> non_native_var_type;
typedef std::array<native_field_type::value_type, ratio> chopped_value_type;

constexpr static const std::array<std::size_t, ratio> chunk_sizes = {254, 1};


static native_field_type::value_type get_i_th_chunk(non_native_field_type::value_type input,
std::size_t i_th) {
assert(i_th < ratio && "non-native type does not have that much chunks!");
native_field_type::extended_integral_type result = native_field_type::extended_integral_type(input.data);
native_field_type::integral_type base = 1;
native_field_type::integral_type mask = (base << chunk_sizes[i_th]) - 1;
std::size_t shift = 0;
for (std::size_t i = 1; i <= i_th; i++) {
shift += chunk_sizes[i - 1];
}

return (result >> shift) & mask;
}


static chopped_value_type chop_non_native(non_native_field_type::value_type input) {
chopped_value_type result;
for (std::size_t i = 0; i < ratio; i++) {
result[i] = get_i_th_chunk(input, i);
}
return result;
}

static non_native_field_type::value_type glue_non_native(chopped_value_type input) {
non_native_field_type::value_type result;
native_field_type::integral_type integral_input;
result = non_native_field_type::value_type(native_field_type::integral_type(input[0].data));
for (std::size_t i = 1; i < ratio; i++) {
std::size_t shift = 0;
for (std::size_t j = 0; j < i; j++) {
shift += chunk_sizes[j];
}
result += non_native_field_type::value_type(native_field_type::integral_type(input[i].data) << shift);
}
return result;
}
typename crypto3::algebra::curves::pallas::scalar_field_type>
: public basic_non_native_policy_field_type_base<
typename crypto3::algebra::curves::pallas::base_field_type,
typename crypto3::algebra::curves::pallas::scalar_field_type, chopped_lengths_storage<2, 254>> {

using basic_non_native_policy_field_type_base::chopped_value_type;
};

/*
* Native element type.
*/
// /*
// * Native element type.
// */
template<typename BlueprintFieldType>
struct basic_non_native_policy_field_type<BlueprintFieldType, BlueprintFieldType> {

constexpr static const std::uint32_t ratio = 1;

typedef crypto3::zk::snark::plonk_variable<typename BlueprintFieldType::value_type> value_type;
using value_type = crypto3::zk::snark::plonk_variable<typename BlueprintFieldType::value_type>;
};
} // namespace detail

Expand All @@ -189,8 +103,6 @@ namespace nil {
using field = typename detail::basic_non_native_policy_field_type<BlueprintFieldType, OperatingFieldType>;
};



} // namespace blueprint
} // namespace nil

Expand Down
113 changes: 113 additions & 0 deletions include/nil/blueprint/detail/basic_non_native_policy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2020-2022 Mikhail Komarov <[email protected]>
// Copyright (c) 2020-2022 Nikita Kaskov <[email protected]>
//
// 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.
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_BLUEPRINT_BASIC_NON_NATIVE_POLICY_DETAIL_HPP
#define CRYPTO3_BLUEPRINT_BASIC_NON_NATIVE_POLICY_DETAIL_HPP

#include <array>

#include <nil/marshalling/algorithms/pack.hpp>
#include <nil/marshalling/field_type.hpp>
#include <nil/marshalling/options.hpp>
#include <nil/marshalling/status_type.hpp>
#include <nil/crypto3/marshalling/multiprecision/types/bitfield.hpp>

namespace nil {
namespace blueprint {
namespace detail {

template<std::size_t... Ns>
struct chopped_lengths_storage {
static constexpr std::size_t values[] = {Ns...};
};

template<typename BlueprintFieldType, typename OperatingFieldType, typename chopped_lengths_storage>
struct basic_non_native_policy_field_type_base {
using non_native_field_t = OperatingFieldType;
using native_field_t = BlueprintFieldType;
using var_t = crypto3::zk::snark::plonk_variable<typename native_field_t::value_type>;

static constexpr std::size_t chopped_elements_amount =
sizeof(chopped_lengths_storage::values) / sizeof(std::size_t);
static_assert(chopped_elements_amount != 0,
"native_bit_lengths must be specialized for the field types");

using chopped_value_type = std::array<typename native_field_t::value_type, chopped_elements_amount>;
using non_native_var_t = std::array<var_t, chopped_elements_amount>;

static chopped_value_type chop_non_native(typename non_native_field_t::value_type input) {
using unit_type = unsigned char;
nil::marshalling::status_type status;

std::vector<unit_type> cv = marshalling::pack<marshalling::option::big_endian>(input, status);

// TODO: Check status here?

chopping_field chopping_field_instance = marshalling::pack(input, status);

// TODO: Check status here?

auto &members = chopping_field_instance.value();
return convert_to_chopped_value_type(members, std::make_index_sequence<chopped_elements_amount> {});
}

private:
using be_field_base_t = marshalling::field_type<marshalling::option::big_endian>;

template<std::size_t bit_length>
using intermediate_t =
crypto3::marshalling::types::pure_field_element<be_field_base_t,
typename native_field_t::value_type,
marshalling::option::fixed_bit_length<bit_length>>;

// We need to reverse the lengths, because that's how the serialization works. Fields are written from
// right to left
template<std::size_t Index>
using intermediate_for_index_t =
intermediate_t<chopped_lengths_storage::values[chopped_elements_amount - Index - 1]>;

template<std::size_t... Indices>
static constexpr std::tuple<intermediate_for_index_t<Indices>...>
generate_bitfield_tuple(std::index_sequence<Indices...>) {
return {};
}

using chopping_field = nil::crypto3::marshalling::types::bitfield<
be_field_base_t,
decltype(generate_bitfield_tuple(std::make_index_sequence<chopped_elements_amount> {}))>;

template<std::size_t... Indices>
static chopped_value_type
convert_to_chopped_value_type(const typename chopping_field::value_type &members,
std::index_sequence<Indices...>) {
return {std::get<Indices>(members).value()...};
}
};

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

#endif // CRYPTO3_BLUEPRINT_BASIC_NON_NATIVE_POLICY_DETAIL_HPP
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ set(NON_NATIVE_TESTS_FILES
"algebra/fields/plonk/non_native/comparison_flag"
"algebra/fields/plonk/non_native/equality_flag"
"algebra/fields/plonk/non_native/division_remainder"
"algebra/fields/plonk/non_native/non_native_policy"
"non_native/plonk/bool_scalar_multiplication"
"non_native/plonk/add_mul_zkllvm_compatible"
"non_native/plonk/scalar_non_native_range"
Expand Down
18 changes: 12 additions & 6 deletions test/algebra/fields/plonk/non_native/addition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#include <nil/blueprint/blueprint/plonk/assignment.hpp>
#include <nil/blueprint/components/algebra/fields/plonk/non_native/addition.hpp>

#include <../test/algebra/fields/plonk/non_native/chop_and_glue_non_native.hpp>
#include <../test/algebra/fields/plonk/non_native/glue_non_native.hpp>

#include "../../../../test_plonk_component.hpp"

Expand Down Expand Up @@ -95,10 +95,16 @@ void test_field_add(const std::vector<typename BlueprintFieldType::value_type> &

template <typename FieldType, typename NonNativeFieldType>
void test_field_add_useable(typename NonNativeFieldType::value_type a, typename NonNativeFieldType::value_type b){
using chunked_non_native_type = std::array<typename FieldType::value_type, 4>;
chunked_non_native_type first = chop_non_native<FieldType, NonNativeFieldType>(a);
chunked_non_native_type second = chop_non_native<FieldType, NonNativeFieldType>(b);
chunked_non_native_type expected_result = chop_non_native<FieldType, NonNativeFieldType>(a + b);
using non_native_policy_type =
blueprint::detail::basic_non_native_policy_field_type<
FieldType,
NonNativeFieldType
>;
using chunked_non_native_type = typename non_native_policy_type::chopped_value_type;

chunked_non_native_type first = non_native_policy_type::chop_non_native(a);
chunked_non_native_type second = non_native_policy_type::chop_non_native(b);
chunked_non_native_type expected_result = non_native_policy_type::chop_non_native(a + b);
std::vector<typename FieldType::value_type> public_input = create_public_input<FieldType, NonNativeFieldType>(first, second);
test_field_add<FieldType, NonNativeFieldType>(public_input, expected_result);
}
Expand Down Expand Up @@ -146,4 +152,4 @@ BOOST_AUTO_TEST_CASE(blueprint_non_native_addition_pallas) {
test_field_add_all_cases<field_type, non_native_field_type>();
}

BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
template<typename FieldType, typename NonNativeFieldType>
std::array<typename FieldType::value_type, 4> chop_non_native(typename NonNativeFieldType::value_type input) {
typename NonNativeFieldType::integral_type input_integral = typename NonNativeFieldType::integral_type(input.data);

std::array<typename FieldType::value_type, 4> output;

typename NonNativeFieldType::integral_type base = 1;
typename NonNativeFieldType::integral_type mask = (base << 66) - 1;
#include <array>
#include <cassert>
#include <vector>

output[0] = input_integral & mask;
output[1] = (input_integral >> 66) & mask;
output[2] = (input_integral >> 132) & mask;
output[3] = (input_integral >> 198) & mask;

return output;
}

template<typename FieldType, typename NonNativeFieldType>
typename NonNativeFieldType::value_type glue_non_native(std::array<typename FieldType::value_type, 4> input) {
typename NonNativeFieldType::integral_type base = 1;
typename NonNativeFieldType::integral_type chunk_size = (base << 66);
typename NonNativeFieldType::integral_type chunk_non_reachable_value = (base << 66);

std::array<typename FieldType::integral_type, 4> input_integral;

for (std::size_t i = 0; i < input.size(); i++) {
assert(input[i] < chunk_size);
assert(input[i] < chunk_non_reachable_value);
input_integral[i] = typename FieldType::integral_type(input[i].data);
}

Expand Down Expand Up @@ -56,4 +44,4 @@ std::vector<typename FieldType::value_type>
public_input.push_back(b[i]);
}
return public_input;
}
}
Loading