Skip to content

Commit 52d96f7

Browse files
fix: Revert "chore: stdlib sha256 without packed_byte_array (#15912)"
This reverts commit 6df1108.
1 parent 903a405 commit 52d96f7

File tree

9 files changed

+682
-208
lines changed

9 files changed

+682
-208
lines changed

barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "barretenberg/crypto/sha256/sha256.hpp"
55
#include "barretenberg/stdlib/hash/sha256/sha256.hpp"
66
#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp"
7+
#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp"
78
#include "barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.hpp"
89
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp"
910

@@ -16,46 +17,28 @@ using namespace bb::stdlib;
1617
using namespace cdg;
1718

1819
using Builder = UltraCircuitBuilder;
19-
using byte_array_ct = byte_array<Builder>;
20-
using field_ct = field_t<Builder>;
21-
22-
/**
23-
* @brief Given a `byte_array` object, slice it into chunks of size `num_bytes_in_chunk` and compute field elements
24-
* reconstructed from these chunks.
25-
*/
26-
27-
std::vector<field_ct> pack_bytes_into_field_elements(const byte_array_ct& input, size_t num_bytes_in_chunk = 4)
28-
{
29-
std::vector<field_t<Builder>> result;
30-
const size_t byte_len = input.size();
31-
32-
for (size_t i = 0; i < byte_len; i += num_bytes_in_chunk) {
33-
byte_array_ct chunk = input.slice(i, std::min(num_bytes_in_chunk, byte_len - i));
34-
result.emplace_back(static_cast<field_ct>(chunk));
35-
}
36-
37-
return result;
38-
}
20+
using byte_array_pt = byte_array<Builder>;
21+
using packed_byte_array_pt = packed_byte_array<Builder>;
22+
using field_pt = field_t<Builder>;
3923

4024
/**
4125
static analyzer usually prints input and output variables as variables in one gate. In tests these variables
4226
are not dangerous and usually we can filter them by adding gate for fixing witness. Then these variables will be
4327
in 2 gates, and static analyzer won't print them. functions fix_vector and fix_byte_array do it
44-
for vector of variables and byte_array respectively
28+
for vector of variables and packed_byte_array respectively
4529
*/
4630

47-
void fix_vector(std::vector<field_ct>& vector)
31+
void fix_vector(std::vector<field_pt>& vector)
4832
{
4933
for (auto& elem : vector) {
5034
elem.fix_witness();
5135
}
5236
}
5337

54-
void fix_byte_array(byte_array_ct& input)
38+
void fix_byte_array(packed_byte_array_pt& input)
5539
{
56-
for (size_t idx = 0; idx < input.size(); idx++) {
57-
input[idx].fix_witness();
58-
}
40+
std::vector<field_pt> limbs = input.get_limbs();
41+
fix_vector(limbs);
5942
}
6043

6144
/**
@@ -72,12 +55,12 @@ TEST(boomerang_stdlib_sha256, test_graph_for_sha256_55_bytes)
7255
// 55 bytes is the largest number of bytes that can be hashed in a single block,
7356
// accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard.
7457
auto builder = Builder();
75-
byte_array_ct input(&builder, "An 8 character password? Snow White and the 7 Dwarves..");
58+
packed_byte_array_pt input(&builder, "An 8 character password? Snow White and the 7 Dwarves..");
7659
fix_byte_array(input);
7760

78-
byte_array_ct output_bytes = stdlib::SHA256<Builder>::hash(input);
61+
packed_byte_array_pt output_bits = stdlib::SHA256<Builder>::hash(input);
7962

80-
std::vector<field_ct> output = pack_bytes_into_field_elements(output_bytes);
63+
std::vector<field_pt> output = output_bits.to_unverified_byte_slices(4);
8164
fix_vector(output);
8265

8366
StaticAnalyzer graph = StaticAnalyzer(builder);
@@ -104,7 +87,7 @@ HEAVY_TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_five)
10487
{
10588
auto builder = Builder();
10689

107-
byte_array_ct input(
90+
packed_byte_array_pt input(
10891
&builder,
10992
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
11093
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
@@ -118,9 +101,9 @@ HEAVY_TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_five)
118101
"AAAAAAAAAA");
119102

120103
fix_byte_array(input);
121-
byte_array_ct output_bytes = stdlib::SHA256<bb::UltraCircuitBuilder>::hash(input);
104+
packed_byte_array_pt output_bits = stdlib::SHA256<bb::UltraCircuitBuilder>::hash(input);
122105

123-
std::vector<field_ct> output = pack_bytes_into_field_elements(output_bytes);
106+
std::vector<field_pt> output = output_bits.to_unverified_byte_slices(4);
124107
fix_vector(output);
125108

126109
StaticAnalyzer graph = StaticAnalyzer(builder);
@@ -143,10 +126,10 @@ HEAVY_TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_five)
143126
TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_one)
144127
{
145128
auto builder = Builder();
146-
byte_array_ct input(&builder, "abc");
129+
packed_byte_array_pt input(&builder, "abc");
147130
fix_byte_array(input);
148-
byte_array_ct output_bytes = stdlib::SHA256<Builder>::hash(input);
149-
fix_byte_array(output_bytes);
131+
packed_byte_array_pt output_bits = stdlib::SHA256<Builder>::hash(input);
132+
fix_byte_array(output_bits);
150133
StaticAnalyzer graph = StaticAnalyzer(builder);
151134
auto connected_components = graph.find_connected_components();
152135
EXPECT_EQ(connected_components.size(), 1);
@@ -163,10 +146,10 @@ TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_one)
163146
TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_two)
164147
{
165148
auto builder = Builder();
166-
byte_array_ct input(&builder, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
149+
packed_byte_array_pt input(&builder, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
167150
fix_byte_array(input);
168-
byte_array_ct output_bytes = stdlib::SHA256<Builder>::hash(input);
169-
fix_byte_array(output_bytes);
151+
packed_byte_array_pt output_bits = stdlib::SHA256<Builder>::hash(input);
152+
fix_byte_array(output_bits);
170153
StaticAnalyzer graph = StaticAnalyzer(builder);
171154
auto connected_components = graph.find_connected_components();
172155
EXPECT_EQ(connected_components.size(), 1);
@@ -185,10 +168,10 @@ TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_three)
185168
auto builder = Builder();
186169

187170
// one byte, 0xbd
188-
byte_array_ct input(&builder, std::vector<uint8_t>{ 0xbd });
171+
packed_byte_array_pt input(&builder, std::vector<uint8_t>{ 0xbd });
189172
fix_byte_array(input);
190-
byte_array_ct output_bytes = stdlib::SHA256<Builder>::hash(input);
191-
fix_byte_array(output_bytes);
173+
packed_byte_array_pt output_bits = stdlib::SHA256<Builder>::hash(input);
174+
fix_byte_array(output_bits);
192175
StaticAnalyzer graph = StaticAnalyzer(builder);
193176
auto connected_components = graph.find_connected_components();
194177
EXPECT_EQ(connected_components.size(), 1);
@@ -207,10 +190,10 @@ TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_four)
207190
auto builder = Builder();
208191

209192
// 4 bytes, 0xc98c8e55
210-
byte_array_ct input(&builder, std::vector<uint8_t>{ 0xc9, 0x8c, 0x8e, 0x55 });
193+
packed_byte_array_pt input(&builder, std::vector<uint8_t>{ 0xc9, 0x8c, 0x8e, 0x55 });
211194
fix_byte_array(input);
212-
byte_array_ct output_bytes = stdlib::SHA256<Builder>::hash(input);
213-
fix_byte_array(output_bytes);
195+
packed_byte_array_pt output_bits = stdlib::SHA256<Builder>::hash(input);
196+
fix_byte_array(output_bits);
214197
StaticAnalyzer graph = StaticAnalyzer(builder);
215198
auto connected_components = graph.find_connected_components();
216199
EXPECT_EQ(connected_components.size(), 1);

barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ template <typename Builder> void generate_sha256_test_circuit(Builder& builder,
2828
{
2929
std::string in;
3030
in.resize(32);
31-
stdlib::byte_array<Builder> input(&builder, in);
31+
stdlib::packed_byte_array<Builder> input(&builder, in);
3232
for (size_t i = 0; i < num_iterations; i++) {
3333
input = stdlib::SHA256<Builder>::hash(input);
3434
}

barretenberg/cpp/src/barretenberg/stdlib/encryption/ecdsa/ecdsa_impl.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ bool_t<Builder> ecdsa_verify_signature(const stdlib::byte_array<Builder>& messag
6969
// Note: This check is also present in the _noassert variation of this method.
7070
sig.v[0].assert_is_in_set({ field_t<Builder>(27), field_t<Builder>(28) }, "ecdsa: signature is non-standard");
7171

72-
stdlib::byte_array<Builder> hashed_message = stdlib::SHA256<Builder>::hash(message);
72+
stdlib::byte_array<Builder> hashed_message =
73+
static_cast<stdlib::byte_array<Builder>>(stdlib::SHA256<Builder>::hash(message));
7374

7475
Fr z(hashed_message);
7576
z.assert_is_in_field();
@@ -227,7 +228,8 @@ bool_t<Builder> ecdsa_verify_signature_noassert(const stdlib::byte_array<Builder
227228
const G1& public_key,
228229
const ecdsa_signature<Builder>& sig)
229230
{
230-
stdlib::byte_array<Builder> hashed_message = stdlib::SHA256<Builder>::hash(message);
231+
stdlib::byte_array<Builder> hashed_message =
232+
static_cast<stdlib::byte_array<Builder>>(stdlib::SHA256<Builder>::hash(message));
231233

232234
return ecdsa_verify_signature_prehashed_message_noassert<Builder, Curve, Fq, Fr, G1>(
233235
hashed_message, public_key, sig);

barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256.cpp

Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,17 @@ constexpr size_t get_num_blocks(const size_t num_bits)
2525

2626
template <typename Builder> void SHA256<Builder>::prepare_constants(std::array<field_t<Builder>, 8>& input)
2727
{
28-
for (size_t i = 0; i < 8; i++) {
29-
input[i] = init_constants[i];
30-
}
28+
constexpr uint64_t init_constants[8]{ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
29+
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
30+
31+
input[0] = init_constants[0];
32+
input[1] = init_constants[1];
33+
input[2] = init_constants[2];
34+
input[3] = init_constants[3];
35+
input[4] = init_constants[4];
36+
input[5] = init_constants[5];
37+
input[6] = init_constants[6];
38+
input[7] = init_constants[7];
3139
}
3240

3341
template <typename Builder>
@@ -82,28 +90,43 @@ std::array<field_t<Builder>, 64> SHA256<Builder>::extend_witness(const std::arra
8290
w_right = convert_witness(w_right.normal);
8391
}
8492

85-
std::array<field_pt, 4> left{
93+
constexpr fr base(16);
94+
constexpr fr left_multipliers[4]{
95+
(base.pow(32 - 7) + base.pow(32 - 18)),
96+
(base.pow(32 - 18 + 3) + 1),
97+
(base.pow(32 - 18 + 10) + base.pow(10 - 7) + base.pow(10 - 3)),
98+
(base.pow(18 - 7) + base.pow(18 - 3) + 1),
99+
};
100+
101+
constexpr fr right_multipliers[4]{
102+
base.pow(32 - 17) + base.pow(32 - 19),
103+
base.pow(32 - 17 + 3) + base.pow(32 - 19 + 3),
104+
base.pow(32 - 19 + 10) + fr(1),
105+
base.pow(18 - 17) + base.pow(18 - 10),
106+
};
107+
108+
field_pt left[4]{
86109
w_left.sparse_limbs[0] * left_multipliers[0],
87110
w_left.sparse_limbs[1] * left_multipliers[1],
88111
w_left.sparse_limbs[2] * left_multipliers[2],
89112
w_left.sparse_limbs[3] * left_multipliers[3],
90113
};
91114

92-
std::array<field_pt, 4> right{
115+
field_pt right[4]{
93116
w_right.sparse_limbs[0] * right_multipliers[0],
94117
w_right.sparse_limbs[1] * right_multipliers[1],
95118
w_right.sparse_limbs[2] * right_multipliers[2],
96119
w_right.sparse_limbs[3] * right_multipliers[3],
97120
};
98121

99-
const field_pt left_xor_sparse =
122+
const auto left_xor_sparse =
100123
left[0].add_two(left[1], left[2]).add_two(left[3], w_left.rotated_limbs[1]) * fr(4);
101124

102-
const field_pt xor_result_sparse = right[0]
103-
.add_two(right[1], right[2])
104-
.add_two(right[3], w_right.rotated_limbs[2])
105-
.add_two(w_right.rotated_limbs[3], left_xor_sparse)
106-
.normalize();
125+
const auto xor_result_sparse = right[0]
126+
.add_two(right[1], right[2])
127+
.add_two(right[3], w_right.rotated_limbs[2])
128+
.add_two(w_right.rotated_limbs[3], left_xor_sparse)
129+
.normalize();
107130

108131
field_pt xor_result = plookup_read<Builder>::read_from_1_to_2_table(SHA256_WITNESS_OUTPUT, xor_result_sparse);
109132

@@ -238,6 +261,18 @@ std::array<field_t<Builder>, 8> SHA256<Builder>::sha256_block(const std::array<f
238261
const std::array<field_t<Builder>, 16>& input)
239262
{
240263
typedef field_t<Builder> field_pt;
264+
265+
constexpr uint64_t round_constants[64]{
266+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
267+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
268+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
269+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
270+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
271+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
272+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
273+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
274+
};
275+
241276
/**
242277
* Initialize round variables with previous block output
243278
**/
@@ -305,75 +340,44 @@ std::array<field_t<Builder>, 8> SHA256<Builder>::sha256_block(const std::array<f
305340
return output;
306341
}
307342

308-
template <typename Builder> byte_array<Builder> SHA256<Builder>::hash(const byte_array_ct& input)
343+
template <typename Builder> packed_byte_array<Builder> SHA256<Builder>::hash(const packed_byte_array<Builder>& input)
309344
{
345+
typedef field_t<Builder> field_pt;
346+
310347
Builder* ctx = input.get_context();
311-
std::vector<field_ct> message_schedule;
312-
const size_t message_length_bytes = input.size();
313348

314-
for (size_t idx = 0; idx < message_length_bytes; idx++) {
315-
message_schedule.push_back(input[idx]);
316-
}
349+
packed_byte_array<Builder> message_schedule(input);
317350

318-
message_schedule.push_back(field_ct(ctx, 128));
351+
const size_t message_bits = message_schedule.size() * 8;
352+
message_schedule.append(field_t(ctx, 128), 1);
319353

320354
constexpr size_t bytes_per_block = 64;
321-
// Include message length
322355
const size_t num_bytes = message_schedule.size() + 8;
323356
const size_t num_blocks = num_bytes / bytes_per_block + (num_bytes % bytes_per_block != 0);
324357

325358
const size_t num_total_bytes = num_blocks * bytes_per_block;
326-
// Pad with zeroes to make the number divisible by 64
327359
for (size_t i = num_bytes; i < num_total_bytes; ++i) {
328-
message_schedule.push_back(field_ct(ctx, 0));
360+
message_schedule.append(field_t(ctx, 0), 1);
329361
}
330362

331-
// Append the message length bits represented as a byte array of length 8.
332-
const size_t message_bits = message_length_bytes * 8;
333-
byte_array_ct message_length_byte_decomposition(field_ct(message_bits), 8);
363+
message_schedule.append(field_t(ctx, message_bits), 8);
334364

335-
for (size_t idx = 0; idx < 8; idx++) {
336-
message_schedule.push_back(message_length_byte_decomposition[idx]);
337-
}
338-
339-
// Compute 4-byte slices
340-
std::vector<field_ct> slices;
341-
342-
for (size_t i = 0; i < message_schedule.size(); i += 4) {
343-
std::vector<field_ct> chunk;
344-
for (size_t j = 0; j < 4; ++j) {
345-
const size_t shift = 8 * (3 - j);
346-
chunk.push_back(message_schedule[i + j] * field_ct(ctx, uint256_t(1) << shift));
347-
}
348-
slices.push_back(field_ct::accumulate(chunk));
349-
}
365+
const std::vector<field_pt> slices = message_schedule.to_unverified_byte_slices(4);
350366

351367
constexpr size_t slices_per_block = 16;
352368

353-
std::array<field_ct, 8> rolling_hash;
369+
std::array<field_pt, 8> rolling_hash;
354370
prepare_constants(rolling_hash);
355371
for (size_t i = 0; i < num_blocks; ++i) {
356-
std::array<field_ct, 16> hash_input;
372+
std::array<field_pt, 16> hash_input;
357373
for (size_t j = 0; j < 16; ++j) {
358374
hash_input[j] = slices[i * slices_per_block + j];
359375
}
360376
rolling_hash = sha256_block(rolling_hash, hash_input);
361377
}
362378

363-
std::vector<field_ct> output;
364-
// Each element of rolling_hash is a 4-byte field_t, decompose rolling hash into bytes.
365-
for (const auto& word : rolling_hash) {
366-
// This constructor constrains
367-
// - word length to be <=4 bytes
368-
// - the element reconstructed from bytes is equal to the given input.
369-
// - each entry to be a byte
370-
byte_array_ct word_byte_decomposition(word, 4);
371-
for (size_t i = 0; i < 4; i++) {
372-
output.push_back(word_byte_decomposition[i]);
373-
}
374-
}
375-
//
376-
return byte_array<Builder>(ctx, output);
379+
std::vector<field_pt> output(rolling_hash.begin(), rolling_hash.end());
380+
return packed_byte_array<Builder>(output, 4);
377381
}
378382

379383
template class SHA256<bb::UltraCircuitBuilder>;

0 commit comments

Comments
 (0)