251 uint32_t round_constant,
259 trace.set(C::sha256_two_pow_6,
row, 64);
262 trace.set(C::sha256_two_pow_11,
row, 2048);
265 trace.set(C::sha256_two_pow_25,
row, 33554432);
268 trace.set(C::sha256_e_rotr_6_xor_e_rotr_11,
row, rot_6 ^ rot_11);
270 uint64_t S1 = rot_6 ^ rot_11 ^ rot_25;
275 uint32_t not_e = ~state[4];
276 trace.set(C::sha256_not_e,
row, not_e);
278 uint32_t e_and_f = state[4] & state[5];
279 trace.set(C::sha256_e_and_f,
row, e_and_f);
281 uint32_t not_e_and_g = not_e & state[6];
282 trace.set(C::sha256_not_e_and_g,
row, not_e_and_g);
284 uint64_t ch = e_and_f ^ not_e_and_g;
290 trace.set(C::sha256_two_pow_2,
row, 4);
293 trace.set(C::sha256_two_pow_13,
row, 8192);
296 trace.set(C::sha256_two_pow_22,
row, 4194304);
299 trace.set(C::sha256_a_rotr_2_xor_a_rotr_13,
row, rot_2 ^ rot_13);
301 uint64_t S0 = rot_2 ^ rot_13 ^ rot_22;
306 uint32_t a_and_b = state[0] & state[1];
307 trace.set(C::sha256_a_and_b,
row, a_and_b);
309 uint32_t a_and_c = state[0] & state[2];
310 trace.set(C::sha256_a_and_c,
row, a_and_c);
312 uint32_t b_and_c = state[1] & state[2];
313 trace.set(C::sha256_b_and_c,
row, b_and_c);
315 trace.set(C::sha256_a_and_b_xor_a_and_c,
row, a_and_b ^ a_and_c);
317 uint64_t maj = a_and_b ^ a_and_c ^ b_and_c;
321 uint64_t temp1 =
static_cast<uint64_t
>(state[7]) + S1 + ch +
static_cast<uint64_t
>(round_constant) +
322 static_cast<uint64_t
>(round_w);
323 uint64_t temp2 = S0 + maj;
324 uint64_t next_a = temp1 + temp2;
326 trace.set(C::sha256_round_constant,
row, round_constant);
327 uint32_t
a =
static_cast<uint32_t
>(next_a);
330 uint64_t next_e =
static_cast<uint64_t
>(state[3]) + temp1;
332 uint32_t e =
static_cast<uint32_t
>(next_e);
387 for (
const auto&
event : events) {
393 uint64_t state_addr =
static_cast<uint64_t
>(
event.state_addr);
394 uint64_t input_addr =
static_cast<uint64_t
>(
event.input_addr);
395 uint64_t output_addr =
static_cast<uint64_t
>(
event.output_addr);
397 uint64_t max_state_addr = state_addr + 7;
398 uint64_t max_input_addr = input_addr + 15;
399 uint64_t max_output_addr = output_addr + 7;
404 { C::sha256_sel, 1 },
405 { C::sha256_start, 1 },
406 { C::sha256_execution_clk,
event.execution_clk },
407 { C::sha256_space_id,
event.space_id },
408 { C::sha256_u32_tag, TAG_U32_AS_FF },
410 { C::sha256_state_addr, state_addr },
411 { C::sha256_input_addr, input_addr },
412 { C::sha256_output_addr, output_addr },
415 { C::sha256_max_state_addr, max_state_addr },
416 { C::sha256_max_input_addr, max_input_addr },
417 { C::sha256_max_output_addr, max_output_addr },
418 { C::sha256_input_rounds_rem, 16 },
419 { C::sha256_input_rounds_rem_inv, PRECOMPUTED_INVERSES[16] },
420 { C::sha256_sel_is_input_round, 1 },
421 { C::sha256_rounds_remaining, 64 },
431 bool out_of_range_err = output_out_of_range || input_out_of_range || state_out_of_range;
432 if (out_of_range_err) {
436 { C::sha256_sel_state_out_of_range_err, state_out_of_range ? 1 : 0 },
437 { C::sha256_sel_input_out_of_range_err, input_out_of_range ? 1 : 0 },
438 { C::sha256_sel_output_out_of_range_err, output_out_of_range ? 1 : 0 },
439 { C::sha256_mem_out_of_range_err, 1 },
440 { C::sha256_err, 1 },
441 { C::sha256_end, 1 },
458 { C::sha256_sel_mem_state_or_output, 1 },
460 { C::sha256_memory_address_0_, state_addr },
461 { C::sha256_memory_address_1_, state_addr + 1 },
462 { C::sha256_memory_address_2_, state_addr + 2 },
463 { C::sha256_memory_address_3_, state_addr + 3 },
464 { C::sha256_memory_address_4_, state_addr + 4 },
465 { C::sha256_memory_address_5_, state_addr + 5 },
466 { C::sha256_memory_address_6_, state_addr + 6 },
467 { C::sha256_memory_address_7_, state_addr + 7 },
469 { C::sha256_memory_register_0_,
event.state[0].as_ff() },
470 { C::sha256_memory_register_1_,
event.state[1].as_ff() },
471 { C::sha256_memory_register_2_,
event.state[2].as_ff() },
472 { C::sha256_memory_register_3_,
event.state[3].as_ff() },
473 { C::sha256_memory_register_4_,
event.state[4].as_ff() },
474 { C::sha256_memory_register_5_,
event.state[5].as_ff() },
475 { C::sha256_memory_register_6_,
event.state[6].as_ff() },
476 { C::sha256_memory_register_7_,
event.state[7].as_ff() },
478 { C::sha256_init_a,
event.state[0].as_ff() },
479 { C::sha256_init_b,
event.state[1].as_ff() },
480 { C::sha256_init_c,
event.state[2].as_ff() },
481 { C::sha256_init_d,
event.state[3].as_ff() },
482 { C::sha256_init_e,
event.state[4].as_ff() },
483 { C::sha256_init_f,
event.state[5].as_ff() },
484 { C::sha256_init_g,
event.state[6].as_ff() },
485 { C::sha256_init_h,
event.state[7].as_ff() },
487 { C::sha256_memory_tag_0_,
static_cast<uint8_t
>(
event.state[0].get_tag()) },
488 { C::sha256_memory_tag_1_,
static_cast<uint8_t
>(
event.state[1].get_tag()) },
489 { C::sha256_memory_tag_2_,
static_cast<uint8_t
>(
event.state[2].get_tag()) },
490 { C::sha256_memory_tag_3_,
static_cast<uint8_t
>(
event.state[3].get_tag()) },
491 { C::sha256_memory_tag_4_,
static_cast<uint8_t
>(
event.state[4].get_tag()) },
492 { C::sha256_memory_tag_5_,
static_cast<uint8_t
>(
event.state[5].get_tag()) },
493 { C::sha256_memory_tag_6_,
static_cast<uint8_t
>(
event.state[6].get_tag()) },
494 { C::sha256_memory_tag_7_,
static_cast<uint8_t
>(
event.state[7].get_tag()) },
500 bool invalid_state_tag_err = std::ranges::any_of(
501 event.state, [](
const MemoryValue& state) { return state.get_tag() != MemoryTag::U32; });
503 if (invalid_state_tag_err) {
505 FF batched_tag_check = 0;
507 for (uint32_t i = 0; i <
event.state.size(); i++) {
509 FF mem_tag =
FF(
static_cast<uint8_t
>(
event.state[i].get_tag()));
510 FF state_tag_diff = mem_tag - TAG_U32_AS_FF;
511 FF exponent =
FF(1 << (i * 3));
512 batched_tag_check += state_tag_diff * exponent;
516 { C::sha256_sel_invalid_state_tag_err, 1 },
519 { C::sha256_batch_tag_inv, batched_tag_check.invert() },
520 { C::sha256_end, 1 },
521 { C::sha256_err, 1 },
536 bool invalid_input_tag_err =
event.input.back().get_tag() !=
MemoryTag::U32;
542 for (uint32_t i = 0; i <
event.input.size(); i++) {
543 const uint32_t input_rounds_rem = 16 - i;
544 FF input_rounds_rem_inv = PRECOMPUTED_INVERSES[input_rounds_rem];
547 FF input_tag =
FF(
static_cast<uint8_t
>(round_input.
get_tag()));
548 FF input_tag_diff = input_tag - TAG_U32_AS_FF;
550 FF input_tag_diff_inv = input_tag_diff == 0 ? 0 : input_tag_diff.
invert();
552 bool is_last = (i ==
event.input.size() - 1);
555 { C::sha256_sel, 1 },
557 { C::sha256_execution_clk,
event.execution_clk },
558 { C::sha256_space_id,
event.space_id },
559 { C::sha256_output_addr, output_addr },
560 { C::sha256_sel_is_input_round, 1 },
561 { C::sha256_u32_tag, TAG_U32_AS_FF },
562 { C::sha256_sel_read_input_from_memory, 1 },
564 { C::sha256_input_rounds_rem, input_rounds_rem },
565 { C::sha256_input_rounds_rem_inv, input_rounds_rem_inv },
566 { C::sha256_input_addr, input_addr + i },
567 { C::sha256_input, round_input.
as_ff() },
568 { C::sha256_input_tag, input_tag },
569 { C::sha256_input_tag_diff_inv, input_tag_diff_inv },
571 { C::sha256_w, round_input.
as_ff() },
574 { C::sha256_sel_invalid_input_tag_err, invalid_input_tag_err ? 1 : 0 },
576 { C::sha256_sel_invalid_input_row_tag_err, (is_last && invalid_input_tag_err) ? 1 : 0 },
577 { C::sha256_err, invalid_input_tag_err ? 1 : 0 },
578 { C::sha256_end, (is_last && invalid_input_tag_err) ? 1 : 0 },
582 if (invalid_input_tag_err) {
584 row +=
static_cast<uint32_t
>(
event.input.size());
594 std::array<uint32_t, 8> state;
595 std::ranges::transform(
event.state.begin(),
event.state.end(), state.begin(), [](
const MemoryValue& val) {
596 return val.as<uint32_t>();
600 std::ranges::transform(
event.input.begin(),
602 prev_w_helpers.begin(),
603 [](
const MemoryValue& val) { return val.as<uint32_t>(); });
604 std::array<uint32_t, 8> round_state = state;
611 for (
size_t i = 0; i < 64; i++) {
613 bool is_an_input_round = i < 16;
615 FF inv = PRECOMPUTED_INVERSES[64 - i];
621 uint64_t round_input_addr = is_an_input_round ? (input_addr + i) : (input_addr + 16);
624 { C::sha256_sel, 1 },
626 { C::sha256_execution_clk,
event.execution_clk },
627 { C::sha256_space_id,
event.space_id },
628 { C::sha256_output_addr, output_addr },
629 { C::sha256_input_addr, round_input_addr },
630 { C::sha256_u32_tag, TAG_U32_AS_FF },
631 { C::sha256_two_pow_32,
static_cast<uint64_t
>(1) << 32 },
635 { C::sha256_perform_round, 1 },
636 { C::sha256_round_count, i },
637 { C::sha256_rounds_remaining, 64 - i },
638 { C::sha256_rounds_remaining_inv, inv },
639 { C::sha256_w, round_w },
640 { C::sha256_sel_compute_w, is_an_input_round ? 0 : 1 },
654 for (
size_t j = 0; j < 15; j++) {
655 prev_w_helpers[j] = prev_w_helpers[j + 1];
657 prev_w_helpers[15] = round_w;
666 { C::sha256_sel, 1 },
667 { C::sha256_end, 1 },
668 { C::sha256_last, 1 },
669 { C::sha256_round_count, 64 },
670 { C::sha256_input_addr, input_addr + 16 },
688 { C::sha256_execution_clk,
event.execution_clk },
689 { C::sha256_space_id,
event.space_id },
690 { C::sha256_sel_mem_state_or_output, 1 },
692 { C::sha256_u32_tag, TAG_U32_AS_FF },
693 { C::sha256_two_pow_32,
static_cast<uint64_t
>(1) << 32 },
694 { C::sha256_output_addr, output_addr },
696 { C::sha256_memory_address_0_, output_addr },
697 { C::sha256_memory_address_1_, output_addr + 1 },
698 { C::sha256_memory_address_2_, output_addr + 2 },
699 { C::sha256_memory_address_3_, output_addr + 3 },
700 { C::sha256_memory_address_4_, output_addr + 4 },
701 { C::sha256_memory_address_5_, output_addr + 5 },
702 { C::sha256_memory_address_6_, output_addr + 6 },
703 { C::sha256_memory_address_7_, output_addr + 7 },
706 { C::sha256_memory_register_0_, round_state[0] + state[0] },
707 { C::sha256_memory_register_1_, round_state[1] + state[1] },
708 { C::sha256_memory_register_2_, round_state[2] + state[2] },
709 { C::sha256_memory_register_3_, round_state[3] + state[3] },
710 { C::sha256_memory_register_4_, round_state[4] + state[4] },
711 { C::sha256_memory_register_5_, round_state[5] + state[5] },
712 { C::sha256_memory_register_6_, round_state[6] + state[6] },
713 { C::sha256_memory_register_7_, round_state[7] + state[7] },
715 { C::sha256_memory_tag_0_, TAG_U32_AS_FF },
716 { C::sha256_memory_tag_1_, TAG_U32_AS_FF },
717 { C::sha256_memory_tag_2_, TAG_U32_AS_FF },
718 { C::sha256_memory_tag_3_, TAG_U32_AS_FF },
719 { C::sha256_memory_tag_4_, TAG_U32_AS_FF },
720 { C::sha256_memory_tag_5_, TAG_U32_AS_FF },
721 { C::sha256_memory_tag_6_, TAG_U32_AS_FF },
722 { C::sha256_memory_tag_7_, TAG_U32_AS_FF },