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

Commit 3b6ebc1

Browse files
committed
Fixed hash decomposition component.
1 parent c2c7bc8 commit 3b6ebc1

File tree

6 files changed

+167
-185
lines changed

6 files changed

+167
-185
lines changed

include/nil/blueprint/components/hashes/sha2/plonk/decomposition.hpp

Lines changed: 124 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Copyright (c) 2021 Nikita Kaskov <[email protected]>
44
// Copyright (c) 2022 Alisa Cherniaeva <[email protected]>
55
// Copyright (c) 2022 Ekaterina Chukavina <[email protected]>
6+
// Copyright (c) 2023 Dmitrii Tabalin <[email protected]>
67
//
78
// MIT License
89
//
@@ -80,15 +81,15 @@ namespace nil {
8081

8182
constexpr static std::size_t get_rows_amount(std::size_t witness_amount,
8283
std::size_t lookup_column_amount) {
83-
return 3;
84+
return 4;
8485
}
8586
constexpr static std::size_t get_empty_rows_amount() {
8687
return 1;
8788
}
8889

8990
const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0);
9091
const std::size_t empty_rows_amount = get_empty_rows_amount();
91-
constexpr static const std::size_t gates_amount = 1;
92+
constexpr static const std::size_t gates_amount = 2;
9293

9394
struct input_type {
9495
std::array<var, 2> data;
@@ -102,14 +103,14 @@ namespace nil {
102103
std::array<var, 8> output;
103104

104105
result_type(const decomposition &component, std::uint32_t start_row_index) {
105-
output = {var(component.W(0), start_row_index + 1, false),
106-
var(component.W(1), start_row_index + 1, false),
107-
var(component.W(2), start_row_index + 1, false),
108-
var(component.W(3), start_row_index + 1, false),
109-
var(component.W(4), start_row_index + 1, false),
106+
output = {var(component.W(6), start_row_index + 1, false),
110107
var(component.W(5), start_row_index + 1, false),
111-
var(component.W(6), start_row_index + 1, false),
112-
var(component.W(7), start_row_index + 1, false)};
108+
var(component.W(4), start_row_index + 1, false),
109+
var(component.W(3), start_row_index + 1, false),
110+
var(component.W(6), start_row_index + 3, false),
111+
var(component.W(5), start_row_index + 3, false),
112+
var(component.W(4), start_row_index + 3, false),
113+
var(component.W(3), start_row_index + 3, false)};
113114
}
114115

115116
result_type(const decomposition &component, std::uint32_t start_row_index, bool skip) {
@@ -172,6 +173,13 @@ namespace nil {
172173
}
173174
return output;
174175
}
176+
177+
std::map<std::string, std::size_t> component_lookup_tables() const {
178+
std::map<std::string, std::size_t> lookup_tables;
179+
lookup_tables["sha256_sparse_base4/first_column"] = 0; // REQUIRED_TABLE
180+
181+
return lookup_tables;
182+
}
175183
};
176184

177185
template<typename BlueprintFieldType>
@@ -188,34 +196,55 @@ namespace nil {
188196
const typename plonk_native_decomposition<BlueprintFieldType>::input_type
189197
instance_input,
190198
const std::uint32_t start_row_index) {
199+
using integral_type = typename BlueprintFieldType::integral_type;
191200

192-
std::size_t row = start_row_index;
193-
std::array<typename BlueprintFieldType::integral_type, 2> data = {
194-
typename BlueprintFieldType::integral_type(var_value(assignment, instance_input.data[0]).data),
195-
typename BlueprintFieldType::integral_type(var_value(assignment, instance_input.data[1]).data)};
196-
std::array<typename BlueprintFieldType::integral_type, 16> range_chunks;
201+
std::array<integral_type, 2> data = {
202+
integral_type(var_value(assignment, instance_input.data[0]).data),
203+
integral_type(var_value(assignment, instance_input.data[1]).data)};
204+
std::array<std::array<std::array<integral_type, 3>, 4>, 2> range_chunks;
205+
std::array<std::array<integral_type, 4>, 2> output_chunks;
197206
std::size_t shift = 0;
198207

199-
for (std::size_t i = 0; i < 8; i++) {
200-
range_chunks[i] = (data[0] >> shift) & ((65536) - 1);
201-
assignment.witness(component.W(i), row) = range_chunks[i];
202-
range_chunks[i + 8] = (data[1] >> shift) & ((65536) - 1);
203-
assignment.witness(component.W(i), row + 2) = range_chunks[i + 8];
204-
shift += 16;
208+
for (std::size_t data_idx = 0; data_idx < 2; data_idx++) {
209+
for (std::size_t chunk_idx = 0; chunk_idx < 4; chunk_idx++) {
210+
output_chunks[data_idx][chunk_idx] = (data[data_idx] >> (chunk_idx * 32)) & 0xFFFFFFFF;
211+
// subchunks are 14, 14, and 4 bits long respectively
212+
range_chunks[data_idx][chunk_idx][0] =
213+
(output_chunks[data_idx][chunk_idx] & 0b11111111111111000000000000000000) >> 18;
214+
range_chunks[data_idx][chunk_idx][1] =
215+
(output_chunks[data_idx][chunk_idx] & 0b00000000000000111111111111110000) >> 4;
216+
range_chunks[data_idx][chunk_idx][2] =
217+
(output_chunks[data_idx][chunk_idx] & 0b00000000000000000000000000001111);
218+
BOOST_ASSERT(
219+
output_chunks[data_idx][chunk_idx] ==
220+
range_chunks[data_idx][chunk_idx][0] * (1 << 18) +
221+
range_chunks[data_idx][chunk_idx][1] * (1 << 4) +
222+
range_chunks[data_idx][chunk_idx][2]);
223+
}
224+
}
225+
for (std::size_t data_idx = 0; data_idx < 2; data_idx++) {
226+
const std::size_t first_row = start_row_index + 2 * data_idx,
227+
second_row = start_row_index + 2 * data_idx + 1;
228+
// placing subchunks for first three chunks
229+
for (std::size_t chunk_idx = 0; chunk_idx < 3; chunk_idx++) {
230+
for (std::size_t subchunk_idx = 0; subchunk_idx < 3; subchunk_idx++) {
231+
assignment.witness(component.W(3 * chunk_idx + subchunk_idx), first_row) =
232+
range_chunks[data_idx][chunk_idx][subchunk_idx];
233+
}
234+
}
235+
// placing subchunk for the last chunk
236+
for (std::size_t subchunk_idx = 0; subchunk_idx < 3; subchunk_idx++) {
237+
assignment.witness(component.W(subchunk_idx), second_row) =
238+
range_chunks[data_idx][3][subchunk_idx];
239+
}
240+
// placing chunks
241+
for (std::size_t chunk_idx = 0; chunk_idx < 4; chunk_idx++) {
242+
assignment.witness(component.W(3 + chunk_idx), second_row) =
243+
output_chunks[data_idx][chunk_idx];
244+
}
245+
// placing the original data
246+
assignment.witness(component.W(7), second_row) = data[data_idx];
205247
}
206-
207-
assignment.witness(component.W(8), row) = data[0];
208-
assignment.witness(component.W(8), row + 2) = data[1];
209-
210-
assignment.witness(component.W(3), row + 1) = range_chunks[1] * (65536) + range_chunks[0];
211-
assignment.witness(component.W(2), row + 1) = range_chunks[3] * (65536) + range_chunks[2];
212-
assignment.witness(component.W(1), row + 1) = range_chunks[5] * (65536) + range_chunks[4];
213-
assignment.witness(component.W(0), row + 1) = range_chunks[7] * (65536) + range_chunks[6];
214-
215-
assignment.witness(component.W(7), row + 1) = range_chunks[9] * (65536) + range_chunks[8];
216-
assignment.witness(component.W(6), row + 1) = range_chunks[11] * (65536) + range_chunks[10];
217-
assignment.witness(component.W(5), row + 1) = range_chunks[13] * (65536) + range_chunks[12];
218-
assignment.witness(component.W(4), row + 1) = range_chunks[15] * (65536) + range_chunks[14];
219248

220249
return typename plonk_native_decomposition<BlueprintFieldType>::result_type(
221250
component, start_row_index);
@@ -256,33 +285,58 @@ namespace nil {
256285

257286
using var = typename plonk_native_decomposition<BlueprintFieldType>::var;
258287

259-
auto constraint_1 =
260-
var(component.W(8), -1) - (var(component.W(3), 0) + var(component.W(2), 0) * 0x100000000_cppui255 +
261-
var(component.W(1), 0) * 0x10000000000000000_cppui255 +
262-
var(component.W(0), 0) * 0x1000000000000000000000000_cppui255);
263-
auto constraint_2 =
264-
var(component.W(8), 1) - (var(component.W(7), 0) + var(component.W(6), 0) * 0x100000000_cppui255 +
265-
var(component.W(5), 0) * 0x10000000000000000_cppui255 +
266-
var(component.W(4), 0) * 0x1000000000000000000000000_cppui255);
267-
auto constraint_3 = var(component.W(3), 0) -
268-
(var(component.W(0), -1) + var(component.W(1), -1) * (65536));
269-
auto constraint_4 = var(component.W(2), 0) -
270-
(var(component.W(2), -1) + var(component.W(3), -1) * (65536));
271-
auto constraint_5 = var(component.W(1), 0) -
272-
(var(component.W(4), -1) + var(component.W(5), -1) * (65536));
273-
auto constraint_6 = var(component.W(0), 0) -
274-
(var(component.W(6), -1) + var(component.W(7), -1) * (65536));
275-
auto constraint_7 = var(component.W(7), 0) -
276-
(var(component.W(0), +1) + var(component.W(1), +1) * (65536));
277-
auto constraint_8 = var(component.W(6), 0) -
278-
(var(component.W(2), +1) + var(component.W(3), +1) * (65536));
279-
auto constraint_9 = var(component.W(5), 0) -
280-
(var(component.W(4), +1) + var(component.W(5), +1) * (65536));
281-
auto constraint_10 = var(component.W(4), 0) -
282-
(var(component.W(6), +1) + var(component.W(7), +1) * (65536));
283-
return bp.add_gate(
284-
{constraint_1, constraint_2, constraint_3, constraint_4, constraint_5, constraint_6,
285-
constraint_7, constraint_8, constraint_9, constraint_10});
288+
const typename BlueprintFieldType::integral_type one = 1;
289+
std::array<std::size_t, 2> selectors;
290+
291+
std::vector<lookup_constraint> subchunk_lookup_constraints(12);
292+
// lookup constraints for the first three chunks
293+
for (std::size_t chunk_idx = 0; chunk_idx < 3; chunk_idx++) {
294+
subchunk_lookup_constraints[3 * chunk_idx] =
295+
{lookup_tables_indices.at("sha256_sparse_base4/first_column"),
296+
{var(component.W(3 * chunk_idx), -1)}};
297+
subchunk_lookup_constraints[3 * chunk_idx + 1] =
298+
{lookup_tables_indices.at("sha256_sparse_base4/first_column"),
299+
{var(component.W(3 * chunk_idx + 1), -1)}};
300+
subchunk_lookup_constraints[3 * chunk_idx + 2] =
301+
{lookup_tables_indices.at("sha256_sparse_base4/first_column"),
302+
{1024 * var(component.W(3 * chunk_idx + 2), -1)}};
303+
}
304+
// lookup constraints for the last chunk
305+
subchunk_lookup_constraints[9] =
306+
{lookup_tables_indices.at("sha256_sparse_base4/first_column"),
307+
{var(component.W(0), 0)}};
308+
subchunk_lookup_constraints[10] =
309+
{lookup_tables_indices.at("sha256_sparse_base4/first_column"),
310+
{var(component.W(1), 0)}};
311+
subchunk_lookup_constraints[11] =
312+
{lookup_tables_indices.at("sha256_sparse_base4/first_column"),
313+
{1024 * var(component.W(2), 0)}};
314+
315+
selectors[0] = bp.add_lookup_gate(subchunk_lookup_constraints);
316+
317+
std::vector<constraint> chunk_constraints(5);
318+
// chunk sum constraints for the first three chunks
319+
for (std::size_t chunk_idx = 0; chunk_idx < 3; chunk_idx++) {
320+
chunk_constraints[chunk_idx] =
321+
var(component.W(3 * chunk_idx), -1) * (1 << 18) +
322+
var(component.W(3 * chunk_idx + 1), -1) * (1 << 4) +
323+
var(component.W(3 * chunk_idx + 2), -1) -
324+
var(component.W(3 + chunk_idx), 0);
325+
}
326+
// chunk sum constraints for the last chunk
327+
chunk_constraints[3] =
328+
var(component.W(0), 0) * (1 << 18) +
329+
var(component.W(1), 0) * (1 << 4) +
330+
var(component.W(2), 0) -
331+
var(component.W(6), 0);
332+
// chunk sum constraint for input
333+
chunk_constraints[4] =
334+
var(component.W(3), 0) + var(component.W(4), 0) * (one << 32) +
335+
var(component.W(5), 0) * (one << 64) + var(component.W(6), 0) * (one << 96) -
336+
var(component.W(7), 0);
337+
selectors[1] = bp.add_gate(chunk_constraints);
338+
339+
return selectors;
286340
}
287341

288342
template<typename BlueprintFieldType>
@@ -296,11 +350,9 @@ namespace nil {
296350
const std::size_t start_row_index) {
297351

298352
using var = typename plonk_native_decomposition<BlueprintFieldType>::var;
299-
// CRITICAL: these copy constraints might not be sufficient, but are definitely required.
300-
// I've added copy constraints for the inputs, but internal ones might be missing
301-
// Proceed with care
302-
bp.add_copy_constraint({instance_input.data[0], var(component.W(8), start_row_index, false)});
303-
bp.add_copy_constraint({instance_input.data[1], var(component.W(8), start_row_index + 2, false)});
353+
354+
bp.add_copy_constraint({instance_input.data[0], var(component.W(7), start_row_index + 1, false)});
355+
bp.add_copy_constraint({instance_input.data[1], var(component.W(7), start_row_index + 3, false)});
304356
}
305357

306358
template<typename BlueprintFieldType>
@@ -314,10 +366,14 @@ namespace nil {
314366
&instance_input,
315367
const std::size_t start_row_index) {
316368

317-
std::size_t j = start_row_index + 1;
318-
std::size_t selector_index = generate_gates(component, bp, assignment, instance_input);
369+
std::array<std::size_t, 2> selector_indices =
370+
generate_gates(component, bp, assignment, instance_input, bp.get_reserved_indices());
371+
372+
assignment.enable_selector(selector_indices[0], start_row_index + 1);
373+
assignment.enable_selector(selector_indices[0], start_row_index + 3);
374+
assignment.enable_selector(selector_indices[1], start_row_index + 1);
375+
assignment.enable_selector(selector_indices[1], start_row_index + 3);
319376

320-
assignment.enable_selector(selector_index, j);
321377
generate_copy_constraints(component, bp, assignment, instance_input, start_row_index);
322378

323379
return typename plonk_native_decomposition<BlueprintFieldType>::result_type(

include/nil/blueprint/components/hashes/sha2/plonk/sha256.hpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -149,30 +149,6 @@ namespace nil {
149149
using lookup_table_definition = typename
150150
nil::crypto3::zk::snark::lookup_table_definition<BlueprintFieldType>;
151151

152-
std::vector<std::shared_ptr<lookup_table_definition>> component_custom_lookup_tables(){
153-
std::vector<std::shared_ptr<lookup_table_definition>> result = {};
154-
155-
auto sparse_values_base4 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::sparse_values_base4_table());
156-
result.push_back(sparse_values_base4);
157-
158-
auto sparse_values_base7 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::sparse_values_base7_table());
159-
result.push_back(sparse_values_base7);
160-
161-
auto maj = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::maj_function_table());
162-
result.push_back(maj);
163-
164-
auto reverse_sparse_sigmas_base4 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::reverse_sparse_sigmas_base4_table());
165-
result.push_back(reverse_sparse_sigmas_base4);
166-
167-
auto reverse_sparse_sigmas_base7 = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::reverse_sparse_sigmas_base7_table());
168-
result.push_back(reverse_sparse_sigmas_base7);
169-
170-
auto ch = std::shared_ptr<lookup_table_definition>(new typename sha256_process_type::ch_function_table());
171-
result.push_back(ch);
172-
173-
return result;
174-
}
175-
176152
std::map<std::string, std::size_t> component_lookup_tables(){
177153
std::map<std::string, std::size_t> lookup_tables;
178154
lookup_tables["sha256_sparse_base4/full"] = 0; // REQUIRED_TABLE

0 commit comments

Comments
 (0)