1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
40using ::testing::Return;
41using ::testing::StrictMock;
43using simulation::Bitwise;
44using simulation::BitwiseEvent;
45using simulation::DeduplicatingEventEmitter;
46using simulation::EventEmitter;
47using simulation::FieldGreaterThan;
48using simulation::FieldGreaterThanEvent;
49using simulation::GreaterThan;
50using simulation::GreaterThanEvent;
51using simulation::MemoryStore;
52using simulation::MockExecutionIdManager;
53using simulation::PureBitwise;
54using simulation::PureGreaterThan;
55using simulation::RangeCheck;
56using simulation::RangeCheckEvent;
57using simulation::Sha256;
58using simulation::Sha256CompressionEvent;
60using tracegen::BitwiseTraceBuilder;
61using tracegen::GreaterThanTraceBuilder;
62using tracegen::PrecomputedTraceBuilder;
63using tracegen::Sha256TraceBuilder;
64using tracegen::TestTraceContainer;
71TEST(Sha256ConstrainingTest, EmptyRow)
80TEST(Sha256ConstrainingTest, Basic)
88 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
91 std::array<uint32_t, 8> state = { 0, 1, 2, 3, 4, 5, 6, 7 };
93 for (uint32_t i = 0; i < 8; ++i) {
94 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
97 std::array<uint32_t, 16> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
99 for (uint32_t i = 0; i < 16; ++i) {
100 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
105 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
106 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
107 TestTraceContainer
trace;
108 trace.
set(C::precomputed_first_row, 0, 1);
110 const auto sha256_event_container = sha256_event_emitter.dump_events();
113 check_relation<sha256>(trace);
116TEST(Sha256ConstrainingTest, Interaction)
132 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
135 std::array<uint32_t, 8> state = { 0, 1, 2, 3, 4, 5, 6, 7 };
137 for (uint32_t i = 0; i < 8; ++i) {
138 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
141 std::array<uint32_t, 16> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
143 for (uint32_t i = 0; i < 16; ++i) {
144 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
148 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
150 TestTraceContainer
trace;
157 BitwiseTraceBuilder bitwise_builder;
211 check_relation<sha256>(trace);
218TEST(Sha256MemoryConstrainingTest, Basic)
233 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
236 std::array<uint32_t, 8> state = { 0, 1, 2, 3, 4, 5, 6, 7 };
238 for (uint32_t i = 0; i < 8; ++i) {
239 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
242 std::array<uint32_t, 16> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
244 for (uint32_t i = 0; i < 16; ++i) {
245 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
250 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
251 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
252 TestTraceContainer
trace;
253 trace.
set(C::precomputed_first_row, 0, 1);
256 const auto sha256_event_container = sha256_event_emitter.dump_events();
261 check_relation<sha256_mem>(trace);
262 check_relation<sha256>(trace);
269TEST(Sha256MemoryConstrainingTest, SimpleOutOfRangeMemoryAddresses)
284 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
292 ".*Memory address out of range.*");
293 TestTraceContainer
trace;
294 trace.
set(C::precomputed_first_row, 0, 1);
297 const auto sha256_event_container = sha256_event_emitter.dump_events();
302 check_relation<sha256_mem>(trace);
303 check_relation<sha256>(trace);
310TEST(Sha256MemoryConstrainingTest, MultiOutOfRangeMemoryAddresses)
325 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
333 ".*Memory address out of range.*");
334 TestTraceContainer
trace;
335 trace.
set(C::precomputed_first_row, 0, 1);
338 const auto sha256_event_container = sha256_event_emitter.dump_events();
343 check_relation<sha256_mem>(trace);
344 check_relation<sha256>(trace);
351TEST(Sha256MemoryConstrainingTest, InvalidStateTagErr)
366 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
371 for (uint32_t i = 0; i < 7; ++i) {
372 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
375 mem.
set(state_addr + 7, MemoryValue::from<uint64_t>(7));
381 ".*Invalid tag for sha256 state values.*");
382 TestTraceContainer
trace;
383 trace.
set(C::precomputed_first_row, 0, 1);
386 const auto sha256_event_container = sha256_event_emitter.dump_events();
391 check_relation<sha256_mem>(trace);
392 check_relation<sha256>(trace);
399TEST(Sha256MemoryConstrainingTest, InvalidInputTagErr)
414 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
417 std::array<uint32_t, 8> state = { 0, 1, 2, 3, 4, 5, 6, 7 };
419 for (uint32_t i = 0; i < 8; ++i) {
420 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
423 std::array<uint32_t, 14> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
425 for (uint32_t i = 0; i < 14; ++i) {
426 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
428 mem.
set(input_addr + 14, MemoryValue::from<uint64_t>(14));
429 mem.
set(input_addr + 15, MemoryValue::from<uint64_t>(15));
433 ".*Invalid tag for sha256 input values.*");
434 TestTraceContainer
trace;
435 trace.
set(C::precomputed_first_row, 0, 1);
438 const auto sha256_event_container = sha256_event_emitter.dump_events();
442 if (getenv(
"AVM_DEBUG") !=
nullptr) {
443 InteractiveDebugger debugger(trace);
447 check_relation<sha256_mem>(trace);
448 check_relation<sha256>(trace);
455TEST(Sha256MemoryConstrainingTest, PropagateError)
464 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
478 TestTraceContainer
trace({
480 { C::precomputed_first_row, 1 },
482 { C::execution_sel, 1 },
484 { C::execution_sel_exec_dispatch_sha256_compression, 1 },
485 { C::execution_rop_0_, output_addr },
486 { C::execution_rop_1_, state_addr },
487 { C::execution_rop_2_, input_addr },
488 { C::execution_sel_opcode_error, 1 },
492 std::array<uint32_t, 8> state = { 0, 1, 2, 3, 4, 5, 6, 7 };
493 for (uint32_t i = 0; i < state.size(); ++i) {
494 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
497 { C::memory_sel, 1 },
499 { C::memory_address, state_addr + i },
500 { C::memory_value, state[i] },
506 std::array<uint32_t, 13> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
507 for (uint32_t i = 0; i < input.size(); ++i) {
508 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
511 { C::memory_sel, 1 },
513 { C::memory_address, input_addr + i },
514 { C::memory_value, input[i] },
520 mem.
set(input_addr + 13, MemoryValue::from<uint64_t>(13));
521 trace.
set(state.size() + input.size(),
523 { C::memory_sel, 1 },
525 { C::memory_address, input_addr + 13 },
526 { C::memory_value, 13 },
530 EXPECT_THROW(sha256_gadget.compression(
mem, state_addr, input_addr, output_addr),
534 const auto sha256_event_container = sha256_event_emitter.dump_events();
544 if (getenv(
"AVM_DEBUG") !=
nullptr) {
545 InteractiveDebugger debugger(trace);
549 check_relation<sha256_mem>(trace);
550 check_relation<sha256>(trace);
551 check_all_interactions<Sha256TraceBuilder>(trace);
554TEST(Sha256MemoryConstrainingTest, Complex)
563 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
578 TestTraceContainer
trace({
580 { C::precomputed_first_row, 1 },
582 { C::execution_sel, 1 },
584 { C::execution_sel_exec_dispatch_sha256_compression, 1 },
586 { C::execution_rop_1_, state_addr },
587 { C::execution_rop_2_, input_addr },
588 { C::execution_sel_opcode_error, 1 },
592 { C::execution_sel, 1 },
594 { C::execution_sel_exec_dispatch_sha256_compression, 1 },
595 { C::execution_rop_0_, output_addr },
596 { C::execution_rop_1_, state_addr },
597 { C::execution_rop_2_, input_addr },
601 std::array<uint32_t, 8> state = { 0, 1, 2, 3, 4, 5, 6, 7 };
602 for (uint32_t i = 0; i < state.size(); ++i) {
603 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
606 { C::memory_sel, 1 },
607 { C::memory_clk, 1 },
609 { C::memory_address, state_addr + i },
610 { C::memory_value, state[i] },
616 std::array<uint32_t, 16> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
617 for (uint32_t i = 0; i < input.size(); ++i) {
618 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
621 { C::memory_sel, 1 },
622 { C::memory_clk, 1 },
624 { C::memory_address, input_addr + i },
625 { C::memory_value, input[i] },
632 for (uint32_t i = 0; i < expected_output.size(); ++i) {
633 mem.
set(output_addr + i, MemoryValue::from<uint32_t>(expected_output[i]));
634 trace.
set(i + state.size() + input.size(),
636 { C::memory_sel, 1 },
637 { C::memory_clk, 1 },
638 { C::memory_space_id, mem.get_space_id() },
639 { C::memory_address, output_addr + i },
640 { C::memory_value, expected_output[i] },
641 { C::memory_tag, static_cast<uint8_t>(MemoryTag::U32) },
649 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
652 const auto sha256_event_container = sha256_event_emitter.dump_events();
662 BitwiseTraceBuilder bitwise_builder;
665 if (getenv(
"AVM_DEBUG") !=
nullptr) {
666 InteractiveDebugger debugger(trace);
670 check_relation<sha256_mem>(trace);
671 check_relation<sha256>(trace);
672 check_all_interactions<Sha256TraceBuilder>(trace);
688TEST(Sha256MemoryConstrainingTest, InputAddrTamperingIsCaughtByConstraint)
697 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
701 std::array<uint32_t, 8> state = { 0, 1, 2, 3, 4, 5, 6, 7 };
703 for (uint32_t i = 0; i < 8; ++i) {
704 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
707 std::array<uint32_t, 16> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
709 for (uint32_t i = 0; i < 16; ++i) {
710 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
715 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
718 TestTraceContainer
trace;
719 trace.
set(C::precomputed_first_row, 0, 1);
724 ASSERT_NO_THROW(check_relation<sha256_mem>(trace)) <<
"Trace should be valid before tampering";
728 constexpr uint32_t MALICIOUS_ADDR = 9999;
729 trace.
set(C::sha256_input_addr, 1, MALICIOUS_ADDR);
734 "CONTINUITY_INPUT_ADDR");
753TEST(Sha256ConstrainingTest, InitStateTamperingIsCaughtByPropagationConstraint)
762 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
766 std::array<uint32_t, 8> state = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
767 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
769 for (uint32_t i = 0; i < 8; ++i) {
770 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
773 std::array<uint32_t, 16> input = { 0x61626380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18 };
775 for (uint32_t i = 0; i < 16; ++i) {
776 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
780 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
782 TestTraceContainer
trace;
783 trace.
set(C::precomputed_first_row, 0, 1);
788 ASSERT_NO_THROW(check_relation<sha256>(trace));
792 constexpr uint32_t TAMPER_ROW = 1;
793 ASSERT_EQ(
trace.
get(C::sha256_perform_round, TAMPER_ROW),
FF(1)) <<
"Row 1 should have perform_round=1";
796 FF original_init_a =
trace.
get(C::sha256_init_a, TAMPER_ROW);
797 FF tampered_init_a = original_init_a +
FF(0x12345678);
798 trace.
set(C::sha256_init_a, TAMPER_ROW, tampered_init_a);
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
#define AVM_HIGHEST_MEM_ADDRESS
FieldGreaterThan field_gt
static constexpr size_t SR_CONTINUITY_INPUT_ADDR
static constexpr size_t SR_PROPAGATE_INIT_A
void set(MemoryAddress index, MemoryValue value) override
uint16_t get_space_id() const override
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
void process(const simulation::EventEmitterInterface< simulation::GreaterThanEvent >::Container &events, TraceContainer &trace)
Process the greater-than events and populate the relevant columns in the trace.
void process_sha256_round_constants(TraceContainer &trace)
Populate the 64 SHA-256 round constants (K_0 .. K_63) and their selector. The sel_sha256_compression ...
void process_misc(TraceContainer &trace, const uint32_t num_rows=PRECOMPUTED_TRACE_SIZE)
Populate miscellaneous precomputed columns: first_row selector and idx (row index).
const FF & get(Column col, uint32_t row) const
void set(Column col, uint32_t row, const FF &value)
PrecomputedTraceBuilder precomputed_builder
GreaterThanTraceBuilder gt_builder
EventEmitter< GreaterThanEvent > gt_event_emitter
ExecutionIdManager execution_id_manager
EventEmitter< RangeCheckEvent > range_check_event_emitter
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
std::array< uint32_t, 8 > sha256_block(const std::array< uint32_t, 8 > &h_init, const std::array< uint32_t, 16 > &input)
TestTraceContainer empty_trace()
lookup_settings< lookup_sha256_range_rhs_e_6_settings_ > lookup_sha256_range_rhs_e_6_settings
lookup_settings< lookup_sha256_w_s_1_xor_1_settings_ > lookup_sha256_w_s_1_xor_1_settings
lookup_settings< lookup_sha256_range_comp_w_rhs_settings_ > lookup_sha256_range_comp_w_rhs_settings
lookup_settings< lookup_sha256_range_rhs_a_13_settings_ > lookup_sha256_range_rhs_a_13_settings
lookup_settings< lookup_sha256_range_rhs_e_11_settings_ > lookup_sha256_range_rhs_e_11_settings
lookup_settings< lookup_sha256_range_rhs_a_22_settings_ > lookup_sha256_range_rhs_a_22_settings
lookup_settings< lookup_sha256_range_comp_h_rhs_settings_ > lookup_sha256_range_comp_h_rhs_settings
lookup_settings< lookup_sha256_mem_check_input_addr_in_range_settings_ > lookup_sha256_mem_check_input_addr_in_range_settings
lookup_settings< lookup_sha256_maj_xor_0_settings_ > lookup_sha256_maj_xor_0_settings
lookup_settings< lookup_sha256_s_1_xor_0_settings_ > lookup_sha256_s_1_xor_0_settings
lookup_settings< lookup_sha256_w_s_0_xor_0_settings_ > lookup_sha256_w_s_0_xor_0_settings
lookup_settings< lookup_sha256_range_rhs_w_18_settings_ > lookup_sha256_range_rhs_w_18_settings
lookup_settings< lookup_sha256_w_s_1_xor_0_settings_ > lookup_sha256_w_s_1_xor_0_settings
lookup_settings< lookup_sha256_range_comp_w_lhs_settings_ > lookup_sha256_range_comp_w_lhs_settings
lookup_settings< lookup_sha256_s_1_xor_1_settings_ > lookup_sha256_s_1_xor_1_settings
lookup_settings< lookup_sha256_range_comp_b_rhs_settings_ > lookup_sha256_range_comp_b_rhs_settings
lookup_settings< lookup_sha256_range_rhs_w_10_settings_ > lookup_sha256_range_rhs_w_10_settings
lookup_settings< lookup_sha256_ch_xor_settings_ > lookup_sha256_ch_xor_settings
lookup_settings< lookup_sha256_range_comp_c_rhs_settings_ > lookup_sha256_range_comp_c_rhs_settings
lookup_settings< lookup_sha256_range_comp_next_e_lhs_settings_ > lookup_sha256_range_comp_next_e_lhs_settings
lookup_settings< lookup_sha256_maj_and_0_settings_ > lookup_sha256_maj_and_0_settings
lookup_settings< lookup_sha256_ch_and_0_settings_ > lookup_sha256_ch_and_0_settings
lookup_settings< lookup_sha256_maj_and_2_settings_ > lookup_sha256_maj_and_2_settings
lookup_settings< lookup_sha256_range_rhs_w_3_settings_ > lookup_sha256_range_rhs_w_3_settings
lookup_settings< lookup_sha256_round_constant_settings_ > lookup_sha256_round_constant_settings
lookup_settings< lookup_sha256_mem_check_state_addr_in_range_settings_ > lookup_sha256_mem_check_state_addr_in_range_settings
lookup_settings< lookup_sha256_range_rhs_e_25_settings_ > lookup_sha256_range_rhs_e_25_settings
lookup_settings< lookup_sha256_range_comp_next_e_rhs_settings_ > lookup_sha256_range_comp_next_e_rhs_settings
lookup_settings< lookup_sha256_maj_xor_1_settings_ > lookup_sha256_maj_xor_1_settings
lookup_settings< lookup_sha256_range_comp_f_rhs_settings_ > lookup_sha256_range_comp_f_rhs_settings
lookup_settings< lookup_sha256_range_comp_next_a_lhs_settings_ > lookup_sha256_range_comp_next_a_lhs_settings
lookup_settings< lookup_sha256_s_0_xor_0_settings_ > lookup_sha256_s_0_xor_0_settings
lookup_settings< lookup_sha256_w_s_0_xor_1_settings_ > lookup_sha256_w_s_0_xor_1_settings
lookup_settings< lookup_sha256_range_rhs_a_2_settings_ > lookup_sha256_range_rhs_a_2_settings
lookup_settings< lookup_sha256_range_comp_g_rhs_settings_ > lookup_sha256_range_comp_g_rhs_settings
lookup_settings< lookup_sha256_range_rhs_w_17_settings_ > lookup_sha256_range_rhs_w_17_settings
lookup_settings< lookup_sha256_s_0_xor_1_settings_ > lookup_sha256_s_0_xor_1_settings
lookup_settings< lookup_sha256_range_rhs_w_7_settings_ > lookup_sha256_range_rhs_w_7_settings
lookup_settings< lookup_sha256_ch_and_1_settings_ > lookup_sha256_ch_and_1_settings
lookup_settings< lookup_sha256_maj_and_1_settings_ > lookup_sha256_maj_and_1_settings
lookup_settings< lookup_sha256_mem_check_output_addr_in_range_settings_ > lookup_sha256_mem_check_output_addr_in_range_settings
lookup_settings< lookup_sha256_range_comp_next_a_rhs_settings_ > lookup_sha256_range_comp_next_a_rhs_settings
lookup_settings< lookup_sha256_range_rhs_w_19_settings_ > lookup_sha256_range_rhs_w_19_settings
lookup_settings< lookup_sha256_range_comp_d_rhs_settings_ > lookup_sha256_range_comp_d_rhs_settings
lookup_settings< lookup_sha256_range_comp_a_rhs_settings_ > lookup_sha256_range_comp_a_rhs_settings
lookup_settings< lookup_sha256_range_comp_e_rhs_settings_ > lookup_sha256_range_comp_e_rhs_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
NoopEventEmitter< FieldGreaterThanEvent > field_gt_event_emitter
NoopEventEmitter< BitwiseEvent > bitwise_event_emitter