1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
40using ::testing::Return;
41using ::testing::StrictMock;
43using tracegen::BitwiseTraceBuilder;
44using tracegen::ExecutionTraceBuilder;
45using tracegen::KeccakF1600TraceBuilder;
46using tracegen::PrecomputedTraceBuilder;
47using tracegen::Sha256TraceBuilder;
48using tracegen::TestTraceContainer;
50using simulation::Bitwise;
51using simulation::BitwiseEvent;
52using simulation::EventEmitter;
53using simulation::FieldGreaterThan;
54using simulation::FieldGreaterThanEvent;
55using simulation::GreaterThan;
56using simulation::GreaterThanEvent;
57using simulation::MemoryStore;
58using simulation::MockExecutionIdManager;
59using simulation::RangeCheck;
60using simulation::RangeCheckEvent;
61using simulation::Sha256;
62using simulation::Sha256CompressionEvent;
70TEST(BitwiseConstrainingTest, EmptyRow)
76TEST(BitwiseConstrainingTest, AndWithTracegen)
78 TestTraceContainer
trace;
86 .a = MemoryValue::from<uint8_t>(85),
87 .b = MemoryValue::from<uint8_t>(175),
90 .a = MemoryValue::from<uint16_t>(5323),
91 .b = MemoryValue::from<uint16_t>(321),
94 .a = MemoryValue::from<uint32_t>(13793),
95 .b = MemoryValue::from<uint32_t>(10590617),
98 .a = MemoryValue::from<uint64_t>(0x7bff744e3cdf79LLU),
99 .b = MemoryValue::from<uint64_t>(0x14ccccccccb6LLU),
100 .res = 0x14444c0ccc30LLU },
102 .a = MemoryValue::from<uint128_t>((
uint128_t{ 0xb900000000000001 } << 64)),
103 .b = MemoryValue::from<uint128_t>((
uint128_t{ 0x1006021301080000 } << 64) +
104 uint128_t{ 0x000000000000001080876844827 }),
105 .res =
uint128_t{ 0x1000000000000000 } << 64 }
111 check_relation<bitwise>(trace);
115TEST(BitwiseConstrainingTest, OrWithTracegen)
117 TestTraceContainer
trace;
125 .a = MemoryValue::from<uint8_t>(128),
126 .b = MemoryValue::from<uint8_t>(127),
129 .a = MemoryValue::from<uint16_t>(5323),
130 .b = MemoryValue::from<uint16_t>(321),
133 .a = MemoryValue::from<uint32_t>(13793),
134 .b = MemoryValue::from<uint32_t>(10590617),
137 .a = MemoryValue::from<uint64_t>(0x7bff744e3cdf79LLU),
138 .b = MemoryValue::from<uint64_t>(0x14ccccccccb6LLU),
139 .res = 0x7bfffccefcdfffLLU },
141 .a = MemoryValue::from<uint128_t>((
uint128_t{ 0xb900000000000000 } << 64)),
142 .b = MemoryValue::from<uint128_t>((
uint128_t{ 0x1006021301080000 } << 64) +
143 uint128_t{ 0x000000000000001080876844827 }),
150 check_relation<bitwise>(trace);
154TEST(BitwiseConstrainingTest, XorWithTracegen)
156 TestTraceContainer
trace;
165 .a = MemoryValue::from<uint8_t>(85),
166 .b = MemoryValue::from<uint8_t>(175),
169 .a = MemoryValue::from<uint16_t>(5323),
170 .b = MemoryValue::from<uint16_t>(321),
173 .a = MemoryValue::from<uint32_t>(13793),
174 .b = MemoryValue::from<uint32_t>(10590617),
177 .a = MemoryValue::from<uint64_t>(0x7bff744e3cdf79LLU),
178 .b = MemoryValue::from<uint64_t>(0x14ccccccccb6LLU),
179 .res = 0x7bebb882f013cfLLU },
181 .a = MemoryValue::from<uint128_t>((
uint128_t{ 0xb900000000000001 } << 64)),
182 .b = MemoryValue::from<uint128_t>((
uint128_t{ 0x1006021301080000 } << 64) +
183 uint128_t{ 0x000000000000001080876844827 }),
190 check_relation<bitwise>(trace);
193TEST(BitwiseConstrainingTest, MixedOperationsWithTracegen)
195 TestTraceContainer
trace;
203 .a = MemoryValue::from<uint32_t>(13793),
204 .b = MemoryValue::from<uint32_t>(10590617),
207 .a = MemoryValue::from<uint16_t>(5323),
208 .b = MemoryValue::from<uint16_t>(321),
211 .a = MemoryValue::from<uint32_t>(13793),
212 .b = MemoryValue::from<uint32_t>(10590617),
215 .a = MemoryValue::from<uint8_t>(85),
216 .b = MemoryValue::from<uint8_t>(175),
219 .a = MemoryValue::from<uint8_t>(85),
220 .b = MemoryValue::from<uint8_t>(175),
227 check_relation<bitwise>(trace);
230TEST(BitwiseConstrainingTest, NegativeWrongInit)
232 TestTraceContainer
trace({
234 { C::bitwise_ia_byte, 25 },
235 { C::bitwise_ib_byte, 25 },
236 { C::bitwise_ic_byte, 25 },
237 { C::bitwise_last, 1 },
238 { C::bitwise_acc_ia, 25 },
239 { C::bitwise_acc_ib, 25 },
240 { C::bitwise_acc_ic, 25 },
246 trace.
set(C::bitwise_ia_byte, 0, 24);
247 trace.
set(C::bitwise_ib_byte, 0, 27);
248 trace.
set(C::bitwise_ic_byte, 0, 28);
255TEST(BitwiseConstrainingTest, NegativeTruncateCtr)
257 TestTraceContainer
trace({
259 { C::bitwise_sel, 1 },
260 { C::bitwise_ctr, 4 },
263 { C::bitwise_sel, 1 },
264 { C::bitwise_ctr, 3 },
267 { C::bitwise_sel, 1 },
268 { C::bitwise_ctr, 2 },
271 { C::bitwise_last, 1 },
272 { C::bitwise_sel, 1 },
273 { C::bitwise_ctr, 1 },
287TEST(BitwiseConstrainingTest, NegativeGapCtr)
289 TestTraceContainer
trace({
291 { C::bitwise_sel, 1 },
292 { C::bitwise_ctr, 4 },
295 { C::bitwise_last, 1 },
296 { C::bitwise_sel, 1 },
297 { C::bitwise_ctr, 3 },
306TEST(BitwiseConstrainingTest, NegativeLastSetBeforeEnd)
308 TestTraceContainer
trace({
310 { C::bitwise_ctr_min_one_inv,
FF(7).invert() },
311 { C::bitwise_sel, 1 },
312 { C::bitwise_ctr, 8 },
315 { C::bitwise_ctr_min_one_inv,
FF(6).invert() },
316 { C::bitwise_sel, 1 },
317 { C::bitwise_ctr, 7 },
321 { C::bitwise_ctr_min_one_inv,
FF(5).invert() },
322 { C::bitwise_sel, 1 },
323 { C::bitwise_ctr, 6 },
330 "BITW_LAST_FOR_CTR_ONE");
333TEST(BitwiseConstrainingTest, NegativeDeactivateRow)
335 TestTraceContainer
trace({
337 { C::bitwise_ctr_inv,
FF(8).invert() },
338 { C::bitwise_sel, 1 },
339 { C::bitwise_ctr, 8 },
342 { C::bitwise_ctr_inv,
FF(7).invert() },
343 { C::bitwise_sel, 1 },
344 { C::bitwise_ctr, 7 },
347 { C::bitwise_ctr_inv,
FF(6).invert() },
348 { C::bitwise_sel, 1 },
349 { C::bitwise_ctr, 6 },
356 "BITW_SEL_CTR_NON_ZERO");
359TEST(BitwiseConstrainingTest, NegativeChangeOpIDBeforeEnd)
361 TestTraceContainer
trace({
369 { C::bitwise_last, 1 },
379TEST(BitwiseConstrainingTest, NegativeWrongAccumulation)
381 TestTraceContainer
trace({
383 { C::bitwise_ia_byte, 0x11 },
384 { C::bitwise_ib_byte, 0x22 },
385 { C::bitwise_ic_byte, 0x33 },
386 { C::bitwise_acc_ia, 0xaa11 },
387 { C::bitwise_acc_ib, 0xbb22 },
388 { C::bitwise_acc_ic, 0xcc33 },
391 { C::bitwise_last, 1 },
392 { C::bitwise_acc_ia, 0xaa },
393 { C::bitwise_acc_ib, 0xbb },
394 { C::bitwise_acc_ic, 0xcc },
400 trace.
set(C::bitwise_acc_ia, 0, 0xaa1f);
401 trace.
set(C::bitwise_acc_ib, 0, 0xbb2f);
402 trace.
set(C::bitwise_acc_ic, 0, 0xcc3f);
409TEST(BitwiseConstrainingTest, MixedOperationsInteractions)
411 TestTraceContainer
trace;
420 .a = MemoryValue::from<uint32_t>(13793),
421 .b = MemoryValue::from<uint32_t>(10590617),
424 .a = MemoryValue::from<uint16_t>(5323),
425 .b = MemoryValue::from<uint16_t>(321),
428 .a = MemoryValue::from<uint32_t>(13793),
429 .b = MemoryValue::from<uint32_t>(10590617),
432 .a = MemoryValue::from<uint8_t>(85),
433 .b = MemoryValue::from<uint8_t>(175),
436 .a = MemoryValue::from<uint8_t>(85),
437 .b = MemoryValue::from<uint8_t>(175),
448 check_all_interactions<BitwiseTraceBuilder>(trace);
449 check_relation<bitwise>(trace);
452TEST(BitwiseConstrainingTest, BitwiseExecInteraction)
454 TestTraceContainer
trace({ {
456 { C::bitwise_err, 1 },
457 { C::bitwise_start, 1 },
460 { C::bitwise_acc_ia, 0x01 },
462 { C::bitwise_acc_ib, 0x01 },
463 { C::bitwise_acc_ic, 0x00 },
465 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
466 { C::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(
MemoryTag::U8) },
468 { C::execution_mem_tag_reg_2_,
static_cast<uint8_t
>(
MemoryTag::U8) },
469 { C::execution_register_0_, 0x01 },
470 { C::execution_register_1_, 0x01 },
471 { C::execution_register_2_, 0x00 },
472 { C::execution_sel_exec_dispatch_bitwise, 1 },
473 { C::execution_sel_opcode_error, 1 },
477 check_interaction<ExecutionTraceBuilder, lookup_execution_dispatch_to_bitwise_settings>(trace);
480TEST(BitwiseConstrainingTest, InvalidBitwiseExecInteraction)
482 TestTraceContainer
trace({ {
484 { C::bitwise_sel, 1 },
485 { C::bitwise_acc_ib, 0x01 },
486 { C::bitwise_acc_ia, 0x01 },
489 { C::bitwise_acc_ic, 0x00 },
494 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::U8) },
495 { C::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(
MemoryTag::U16) },
496 { C::execution_mem_tag_reg_2_,
static_cast<uint8_t
>(
MemoryTag::U8) },
497 { C::execution_register_0_, 0x01 },
498 { C::execution_register_1_, 0x01 },
499 { C::execution_register_2_, 0x00 },
500 { C::execution_sel_exec_dispatch_bitwise, 1 },
505 (check_interaction<ExecutionTraceBuilder, lookup_execution_dispatch_to_bitwise_settings>(trace)),
506 "Failed.*EXECUTION_DISPATCH_TO_BITWISE. Could not find tuple in destination.");
509TEST(BitwiseConstrainingTest, ErrorHandlingInputFF)
511 TestTraceContainer
trace;
525 check_relation<bitwise>(trace);
528TEST(BitwiseConstrainingTest, ErrorHandlingInputTagMismatch)
530 TestTraceContainer
trace;
541 check_relation<bitwise>(trace);
542 check_all_interactions<BitwiseTraceBuilder>(trace);
545TEST(BitwiseConstrainingTest, ErrorHandlingMultiple)
547 TestTraceContainer
trace;
558 check_relation<bitwise>(trace);
561TEST(BitwiseConstrainingTest, ExecBitwiseDispatchOnErrorMismatch)
567 TestTraceContainer
trace({ {
569 { C::execution_sel_exec_dispatch_bitwise, 1 },
571 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
a.get_tag()) },
572 { C::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(
b.get_tag()) },
573 { C::execution_register_0_,
a.as_ff() },
574 { C::execution_register_1_,
b.as_ff() },
577 { C::execution_mem_tag_reg_2_,
static_cast<uint8_t
>(
MemoryTag::FF) },
578 { C::execution_register_2_, 0x00 },
579 { C::execution_sel_opcode_error, 1 },
587 check_relation<bitwise>(trace);
588 check_interaction<ExecutionTraceBuilder, lookup_execution_dispatch_to_bitwise_settings>(trace);
591TEST(BitwiseConstrainingTest, ExecBitwiseDispatchOnErrorFF)
598 TestTraceContainer
trace({ {
600 { C::execution_sel_exec_dispatch_bitwise, 1 },
602 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
a.get_tag()) },
603 { C::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(
b.get_tag()) },
604 { C::execution_register_0_,
a.as_ff() },
605 { C::execution_register_1_,
b.as_ff() },
608 { C::execution_mem_tag_reg_2_,
static_cast<uint8_t
>(
MemoryTag::FF) },
609 { C::execution_register_2_, 0x00 },
610 { C::execution_sel_opcode_error, 1 },
618 check_relation<bitwise>(trace);
619 check_interaction<ExecutionTraceBuilder, lookup_execution_dispatch_to_bitwise_settings>(trace);
636TEST(BitwiseConstrainingTest, VulnerabilityStartKeccakWithoutSel)
642 FF fake_input_a =
FF(0xAAAABBBBCCCCDDDDULL);
643 FF fake_input_b =
FF(0x1111222233334444ULL);
644 FF fake_output =
FF(0x999999999999ULL);
646 TestTraceContainer
trace({
650 { C::bitwise_sel, 0 },
651 { C::bitwise_start, 1 },
652 { C::bitwise_start_keccak, 1 },
657 { C::bitwise_sel_tag_mismatch_err, 1 },
658 { C::bitwise_sel_tag_ff_err, 0 },
659 { C::bitwise_err, 1 },
660 { C::bitwise_last, 1 },
661 { C::bitwise_sel_get_ctr, 0 },
662 { C::bitwise_ctr, 0 },
668 { C::bitwise_acc_ia, fake_input_a },
669 { C::bitwise_acc_ib, fake_input_b },
670 { C::bitwise_acc_ic, fake_output },
672 { C::bitwise_ia_byte, fake_input_a },
673 { C::bitwise_ib_byte, fake_input_b },
674 { C::bitwise_ic_byte, fake_output },
676 { C::bitwise_tag_c, 0 },
693TEST(BitwiseConstrainingTest, VulnerabilityStartSha256WithoutSel)
695 FF fake_input_a =
FF(0xAABBCCDD);
696 FF fake_input_b =
FF(0x11223344);
697 FF fake_output =
FF(0x99999999);
699 TestTraceContainer
trace({
701 { C::bitwise_sel, 0 },
702 { C::bitwise_start, 1 },
703 { C::bitwise_start_sha256, 1 },
706 { C::bitwise_sel_tag_mismatch_err, 1 },
707 { C::bitwise_sel_tag_ff_err, 0 },
708 { C::bitwise_err, 1 },
709 { C::bitwise_last, 1 },
710 { C::bitwise_sel_get_ctr, 0 },
711 { C::bitwise_ctr, 0 },
715 { C::bitwise_acc_ia, fake_input_a },
716 { C::bitwise_acc_ib, fake_input_b },
717 { C::bitwise_acc_ic, fake_output },
718 { C::bitwise_ia_byte, fake_input_a },
719 { C::bitwise_ib_byte, fake_input_b },
720 { C::bitwise_ic_byte, fake_output },
721 { C::bitwise_tag_c, 0 },
734TEST(BitwiseConstrainingTest, VulnerabilityFakeKeccakXorOutput)
739 TestTraceContainer
trace;
747 check_relation<keccakf1600>(trace);
748 check_relation<bitwise>(trace);
753 uint32_t keccak_start_row = 0;
755 if (
trace.
get(C::keccakf1600_start, i) ==
FF(1)) {
756 keccak_start_row = i;
760 ASSERT_EQ(
trace.
get(C::keccakf1600_start, keccak_start_row),
FF(1));
761 ASSERT_EQ(
trace.
get(C::keccakf1600_sel_no_error, keccak_start_row),
FF(1));
763 FF real_state_in_00 =
trace.
get(C::keccakf1600_state_in_00, keccak_start_row);
764 FF real_state_in_01 =
trace.
get(C::keccakf1600_state_in_01, keccak_start_row);
765 FF real_theta_xor_01 =
trace.
get(C::keccakf1600_theta_xor_01, keccak_start_row);
772 FF fake_theta_xor_01 =
FF(0xFA0E0BAD0DEADULL);
773 ASSERT_NE(fake_theta_xor_01, real_theta_xor_01);
774 trace.
set(C::keccakf1600_theta_xor_01, keccak_start_row, fake_theta_xor_01);
782 { C::bitwise_sel, 0 },
783 { C::bitwise_start, 1 },
784 { C::bitwise_start_keccak, 1 },
786 { C::bitwise_acc_ia, real_state_in_00 },
787 { C::bitwise_acc_ib, real_state_in_01 },
788 { C::bitwise_acc_ic, fake_theta_xor_01 },
789 { C::bitwise_ia_byte, real_state_in_00 },
790 { C::bitwise_ib_byte, real_state_in_01 },
791 { C::bitwise_ic_byte, fake_theta_xor_01 },
794 { C::bitwise_sel_tag_mismatch_err, 1 },
795 { C::bitwise_sel_tag_ff_err, 0 },
796 { C::bitwise_err, 1 },
797 { C::bitwise_last, 1 },
798 { C::bitwise_sel_get_ctr, 0 },
799 { C::bitwise_ctr, 0 },
802 { C::bitwise_tag_c, 0 },
809 check_relation<keccakf1600>(trace);
822 check_interaction<KeccakF1600TraceBuilder, lookup_keccakf1600_theta_xor_01_settings>(trace);
843TEST(BitwiseConstrainingTest, VulnerabilityFakeSha256XorOutput)
862 EventEmitter<Sha256CompressionEvent> sha256_event_emitter;
865 std::array<uint32_t, 8> state = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
866 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
868 for (uint32_t i = 0; i < 8; ++i) {
869 mem.
set(state_addr + i, MemoryValue::from<uint32_t>(state[i]));
872 std::array<uint32_t, 16> input = { 0x61626380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18 };
874 for (uint32_t i = 0; i < 16; ++i) {
875 mem.
set(input_addr + i, MemoryValue::from<uint32_t>(input[i]));
879 sha256_gadget.compression(
mem, state_addr, input_addr, output_addr);
881 TestTraceContainer
trace;
882 trace.
set(C::precomputed_first_row, 0, 1);
884 Sha256TraceBuilder sha256_builder;
885 sha256_builder.process(sha256_event_emitter.get_events(), trace);
887 BitwiseTraceBuilder bitwise_builder;
893 check_relation<sha256_relation>(trace);
894 check_relation<bitwise>(trace);
899 uint32_t sha256_row = 0;
902 if (
trace.
get(C::sha256_sel_compute_w, i) ==
FF(1)) {
908 ASSERT_TRUE(found) <<
"Could not find sha256 row with sel_compute_w=1";
910 FF real_w_15_rotr_7 =
trace.
get(C::sha256_w_15_rotr_7, sha256_row);
911 FF real_w_15_rotr_18 =
trace.
get(C::sha256_w_15_rotr_18, sha256_row);
912 FF real_xor_output =
trace.
get(C::sha256_w_15_rotr_7_xor_w_15_rotr_18, sha256_row);
917 FF fake_xor_output =
FF(0xDEADBEEF);
918 ASSERT_NE(fake_xor_output, real_xor_output);
919 trace.
set(C::sha256_w_15_rotr_7_xor_w_15_rotr_18, sha256_row, fake_xor_output);
927 { C::bitwise_sel, 0 },
928 { C::bitwise_start, 1 },
929 { C::bitwise_start_sha256, 1 },
931 { C::bitwise_acc_ia, real_w_15_rotr_7 },
932 { C::bitwise_acc_ib, real_w_15_rotr_18 },
933 { C::bitwise_acc_ic, fake_xor_output },
934 { C::bitwise_ia_byte, real_w_15_rotr_7 },
935 { C::bitwise_ib_byte, real_w_15_rotr_18 },
936 { C::bitwise_ic_byte, fake_xor_output },
939 { C::bitwise_sel_tag_mismatch_err, 1 },
940 { C::bitwise_sel_tag_ff_err, 0 },
941 { C::bitwise_err, 1 },
942 { C::bitwise_last, 1 },
943 { C::bitwise_sel_get_ctr, 0 },
944 { C::bitwise_ctr, 0 },
947 { C::bitwise_tag_c, 0 },
955 check_relation<sha256_relation>(trace);
975 tracegen::SharedIndexCache cache;
976 tracegen::LookupIntoDynamicTableGeneric<lookup_sha256_w_s_0_xor_0_settings> lookup(cache, C::bitwise_start);
977 lookup.process(trace);
FieldGreaterThan field_gt
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
#define AVM_BITWISE_XOR_OP_ID
static TaggedValue from(T value)
static TaggedValue from_tag(ValueTag tag, FF value)
static constexpr size_t SR_BITW_CTR_DECREMENT
static constexpr size_t SR_BITW_LAST_FOR_CTR_ONE
static constexpr size_t SR_BITW_OP_ID_REL
static constexpr size_t SR_BITW_ACC_REL_C
static constexpr size_t SR_BITW_ACC_REL_B
static constexpr size_t SR_BITW_ACC_REL_A
static constexpr size_t SR_BITW_INIT_C
static constexpr size_t SR_BITW_INIT_B
static constexpr size_t SR_BITW_INIT_A
static constexpr size_t SR_BITW_SEL_CTR_NON_ZERO
void set(MemoryAddress index, MemoryValue value) 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_misc(TraceContainer &trace, const uint32_t num_rows=PRECOMPUTED_TRACE_SIZE)
void process_bitwise(TraceContainer &trace)
void process_sel_range_16(TraceContainer &trace)
void process_tag_parameters(TraceContainer &trace)
const FF & get(Column col, uint32_t row) const
uint32_t get_num_rows() const
void set(Column col, uint32_t row, const FF &value)
PrecomputedTraceBuilder precomputed_builder
EventEmitter< GreaterThanEvent > gt_event_emitter
ExecutionIdManager execution_id_manager
EventEmitter< RangeCheckEvent > range_check_event_emitter
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
void generate_keccak_trace(TestTraceContainer &trace, const std::vector< MemoryAddress > &dst_addresses, const std::vector< MemoryAddress > &src_addresses, uint16_t space_id)
TestTraceContainer empty_trace()
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
simulation::PublicDataTreeReadWriteEvent event
unsigned __int128 uint128_t
NoopEventEmitter< FieldGreaterThanEvent > field_gt_event_emitter
NoopEventEmitter< BitwiseEvent > bitwise_event_emitter
constexpr field invert() const noexcept