@@ -25,9 +25,17 @@ constexpr size_t get_num_blocks(const size_t num_bits)
2525
2626template <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
3341template <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
379383template class SHA256 <bb::UltraCircuitBuilder>;
0 commit comments