Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Commit 8f6300c

Browse files
x-massnkaskov
authored andcommitted
Use multiprecision bitfield for chopping
1 parent f5917cc commit 8f6300c

File tree

2 files changed

+131
-77
lines changed

2 files changed

+131
-77
lines changed

include/nil/blueprint/basic_non_native_policy.hpp

Lines changed: 22 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,19 @@
2828

2929
#include <nil/crypto3/algebra/curves/pallas.hpp>
3030
#include <nil/crypto3/algebra/curves/ed25519.hpp>
31-
#include <nil/crypto3/algebra/marshalling.hpp>
32-
31+
#include <nil/crypto3/marshalling/algebra/types/field_element.hpp>
3332
#include <nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp>
3433

34+
#include <nil/blueprint/detail/basic_non_native_policy.hpp>
35+
36+
3537
namespace nil {
3638
namespace blueprint {
3739
namespace detail {
40+
3841
template<typename BlueprintFieldType, typename OperatingFieldType>
39-
struct basic_non_native_policy_field_type;
42+
struct basic_non_native_policy_field_type : public basic_non_native_policy_field_type_base<BlueprintFieldType, OperatingFieldType, chopped_lengths_storage<>> {
43+
};
4044

4145
/*
4246
* Specialization for non-native Ed25519 base field element on Pallas base field
@@ -45,38 +49,9 @@ namespace nil {
4549
struct basic_non_native_policy_field_type<
4650
typename crypto3::algebra::curves::pallas::base_field_type,
4751
typename crypto3::algebra::curves::ed25519::base_field_type
48-
> {
49-
using non_native_field_type = typename crypto3::algebra::curves::ed25519::base_field_type;
50-
using native_field_type = typename crypto3::algebra::curves::pallas::base_field_type;
51-
using var = crypto3::zk::snark::plonk_variable<typename native_field_type::value_type>;
52-
53-
constexpr static const std::uint32_t native_type_element_bit_length = 66;
54-
constexpr static const std::uint32_t native_type_elements_needed =
55-
(non_native_field_type::value_bits + (native_type_element_bit_length - 1))
56-
/ native_type_element_bit_length
57-
;
58-
59-
using non_native_var_type = std::array<var, native_type_elements_needed>;
60-
using chopped_value_type = std::array<native_field_type::value_type, native_type_elements_needed>;
61-
62-
static chopped_value_type chop_non_native(non_native_field_type::value_type input) {
63-
return marshalling::bincode::field<non_native_field_type>
64-
::split_field_element<native_field_type, native_type_element_bit_length>(input);
65-
}
66-
67-
static non_native_field_type::value_type glue_non_native(chopped_value_type input) {
68-
non_native_field_type::value_type result;
69-
native_field_type::integral_type integral_input;
70-
result = non_native_field_type::value_type(native_field_type::integral_type(input[0].data));
71-
for (std::size_t i = 1; i < ratio; i++) {
72-
std::size_t shift = 0;
73-
for (std::size_t j = 0; j < i; j++) {
74-
shift += chunk_sizes[j];
75-
}
76-
result += non_native_field_type::value_type(native_field_type::integral_type(input[i].data) << shift);
77-
}
78-
return result;
79-
}
52+
> : 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>> {
53+
54+
using basic_non_native_policy_field_type_base::chopped_value_type;
8055

8156
};
8257

@@ -90,50 +65,22 @@ namespace nil {
9065
using non_native_var_type = crypto3::zk::snark::plonk_variable<typename crypto3::algebra::curves::pallas::base_field_type::value_type>;
9166
};
9267

93-
/*
94-
* Specialization for non-native Pallas scalar field element on Pallas base field
95-
*/
68+
// /*
69+
// * Specialization for non-native Pallas scalar field element on Pallas base field
70+
// */
9671
template<>
97-
struct basic_non_native_policy_field_type<typename crypto3::algebra::curves::pallas::base_field_type,
98-
typename crypto3::algebra::curves::pallas::scalar_field_type> {
99-
100-
using non_native_field_type = typename crypto3::algebra::curves::pallas::scalar_field_type;
101-
using native_field_type = typename crypto3::algebra::curves::pallas::base_field_type;
102-
using var = crypto3::zk::snark::plonk_variable<native_field_type>;
103-
104-
constexpr static const std::uint32_t native_type_element_bit_length = 254;
105-
constexpr static const std::uint32_t native_type_elements_needed =
106-
(non_native_field_type::value_bits + (native_type_element_bit_length - 1))
107-
/ native_type_element_bit_length
108-
;
109-
110-
using non_native_var_type = std::array<var, native_type_elements_needed>;
111-
using chopped_value_type = std::array<native_field_type::value_type, native_type_elements_needed>;
112-
113-
static chopped_value_type chop_non_native(non_native_field_type::value_type input) {
114-
return marshalling::bincode::field<non_native_field_type>
115-
::split_field_element<native_field_type, native_type_element_bit_length>(input);
116-
}
117-
118-
static non_native_field_type::value_type glue_non_native(chopped_value_type input) {
119-
non_native_field_type::value_type result;
120-
native_field_type::integral_type integral_input;
121-
result = non_native_field_type::value_type(native_field_type::integral_type(input[0].data));
122-
for (std::size_t i = 1; i < ratio; i++) {
123-
std::size_t shift = 0;
124-
for (std::size_t j = 0; j < i; j++) {
125-
shift += chunk_sizes[j];
126-
}
127-
result += non_native_field_type::value_type(native_field_type::integral_type(input[i].data) << shift);
128-
}
129-
return result;
130-
}
72+
struct basic_non_native_policy_field_type<
73+
typename crypto3::algebra::curves::pallas::base_field_type,
74+
typename crypto3::algebra::curves::pallas::scalar_field_type
75+
> : 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>> {
76+
77+
using basic_non_native_policy_field_type_base::chopped_value_type;
13178

13279
};
13380

134-
/*
135-
* Native element type.
136-
*/
81+
// /*
82+
// * Native element type.
83+
// */
13784
template<typename BlueprintFieldType>
13885
struct basic_non_native_policy_field_type<BlueprintFieldType, BlueprintFieldType> {
13986

@@ -155,8 +102,6 @@ namespace nil {
155102
using field = typename detail::basic_non_native_policy_field_type<BlueprintFieldType, OperatingFieldType>;
156103
};
157104

158-
159-
160105
} // namespace blueprint
161106
} // namespace nil
162107

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//---------------------------------------------------------------------------//
2+
// Copyright (c) 2020-2022 Mikhail Komarov <[email protected]>
3+
// Copyright (c) 2020-2022 Nikita Kaskov <[email protected]>
4+
//
5+
// MIT License
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining a copy
8+
// of this software and associated documentation files (the "Software"), to deal
9+
// in the Software without restriction, including without limitation the rights
10+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
// copies of the Software, and to permit persons to whom the Software is
12+
// furnished to do so, subject to the following conditions:
13+
//
14+
// The above copyright notice and this permission notice shall be included in all
15+
// copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
// SOFTWARE.
24+
//---------------------------------------------------------------------------//
25+
26+
#ifndef CRYPTO3_BLUEPRINT_BASIC_NON_NATIVE_POLICY_DETAIL_HPP
27+
#define CRYPTO3_BLUEPRINT_BASIC_NON_NATIVE_POLICY_DETAIL_HPP
28+
29+
#include <array>
30+
31+
#include <nil/marshalling/algorithms/pack.hpp>
32+
#include <nil/marshalling/field_type.hpp>
33+
#include <nil/marshalling/options.hpp>
34+
#include <nil/marshalling/status_type.hpp>
35+
#include <nil/crypto3/marshalling/multiprecision/types/bitfield.hpp>
36+
37+
38+
namespace nil {
39+
namespace blueprint {
40+
namespace detail {
41+
42+
template<std::size_t... Ns>
43+
struct chopped_lengths_storage {
44+
static constexpr std::size_t values[] = {Ns...};
45+
};
46+
47+
template<typename BlueprintFieldType, typename OperatingFieldType, typename chopped_lengths_storage>
48+
struct basic_non_native_policy_field_type_base {
49+
using non_native_field_t = OperatingFieldType;
50+
using native_field_t = BlueprintFieldType;
51+
using var_t = crypto3::zk::snark::plonk_variable<typename native_field_t::value_type>;
52+
53+
static constexpr std::size_t chopped_elements_amount = sizeof(chopped_lengths_storage::values)/sizeof(std::size_t);
54+
static_assert(chopped_elements_amount != 0, "native_bit_lengths must be specialized for the field types");
55+
56+
using chopped_value_type = std::array<typename native_field_t::value_type, chopped_elements_amount>;
57+
using non_native_var_t = std::array<var_t, chopped_elements_amount>;
58+
59+
static chopped_value_type chop_non_native(typename non_native_field_t::value_type input) {
60+
using unit_type = unsigned char;
61+
nil::marshalling::status_type status;
62+
63+
std::vector<unit_type> cv = marshalling::pack<marshalling::option::big_endian>(input, status);
64+
65+
// TODO: Check status here?
66+
67+
chopping_field chopping_field_instance = marshalling::pack(input, status);
68+
69+
// TODO: Check status here?
70+
71+
auto &members = chopping_field_instance.value();
72+
return convert_to_chopped_value_type(members, std::make_index_sequence<chopped_elements_amount>{});
73+
}
74+
75+
private:
76+
using be_field_base_t = marshalling::field_type<marshalling::option::big_endian>;
77+
78+
template <std::size_t bit_length>
79+
using intermediate_t = crypto3::marshalling::types::pure_field_element<
80+
be_field_base_t,
81+
typename native_field_t::value_type,
82+
marshalling::option::fixed_bit_length<bit_length>
83+
>;
84+
85+
// We need to reverse the lengths, because that's how the serialization works. Fields are written from right to left
86+
template <std::size_t Index>
87+
using intermediate_for_index_t = intermediate_t<chopped_lengths_storage::values[chopped_elements_amount-Index-1]>;
88+
89+
template <std::size_t... Indices>
90+
static constexpr std::tuple<intermediate_for_index_t<Indices>...> generate_bitfield_tuple(std::index_sequence<Indices...>) {
91+
return {};
92+
}
93+
94+
using chopping_field = nil::crypto3::marshalling::types::bitfield<
95+
be_field_base_t,
96+
decltype(generate_bitfield_tuple(std::make_index_sequence<chopped_elements_amount>{}))
97+
>;
98+
99+
template <std::size_t... Indices>
100+
static chopped_value_type convert_to_chopped_value_type(const typename chopping_field::value_type& members, std::index_sequence<Indices...>) {
101+
return {std::get<Indices>(members).value()...};
102+
}
103+
};
104+
105+
} // namespace detail
106+
} // namespace blueprint
107+
} // namespace nil
108+
109+
#endif // CRYPTO3_BLUEPRINT_BASIC_NON_NATIVE_POLICY_DETAIL_HPP

0 commit comments

Comments
 (0)