Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bc_hashing.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5#include <memory>
6#include <vector>
7
25
26namespace bb::avm2::constraining {
27namespace {
28
29using ::testing::Return;
30using ::testing::StrictMock;
31
34
35using simulation::EventEmitter;
36using simulation::MockExecutionIdManager;
37using simulation::MockGreaterThan;
38using simulation::Poseidon2;
39using simulation::Poseidon2HashEvent;
40using simulation::Poseidon2PermutationEvent;
41using simulation::Poseidon2PermutationMemoryEvent;
42using tracegen::BytecodeTraceBuilder;
43using tracegen::Poseidon2TraceBuilder;
44using tracegen::TestTraceContainer;
45
47using C = Column;
48using bc_hashing = bb::avm2::bc_hashing<FF>;
50
51TEST(BytecodeHashingConstrainingTest, EmptyRow)
52{
53 check_relation<bc_hashing>(testing::empty_trace());
54}
55
56TEST(BytecodeHashingConstrainingTest, SingleBytecodeHash)
57{
58 TestTraceContainer trace({
59 { { C::precomputed_first_row, 1 } },
60 });
61 BytecodeTraceBuilder builder;
62
63 builder.process_hashing(
64 { { .bytecode_id = 1, .bytecode_length = 62, .bytecode_fields = random_fields(2) /* 62 bytes */ } }, trace);
65
66 check_relation<bc_hashing>(trace);
67}
68
69TEST(BytecodeHashingConstrainingTest, MultipleBytecodeHash)
70{
71 TestTraceContainer trace({
72 { { C::precomputed_first_row, 1 } },
73 });
74 BytecodeTraceBuilder builder;
75
76 builder.process_hashing(
77 { { .bytecode_id = 1, .bytecode_length = 62, .bytecode_fields = random_fields(2) /* 62 bytes */ },
78 { .bytecode_id = 2, .bytecode_length = 62000, .bytecode_fields = random_fields(2000) /* 62k bytes */ } },
79 trace);
80
81 check_relation<bc_hashing>(trace);
82}
83
84TEST(BytecodeHashingConstrainingTest, PoseidonInteractions)
85{
86 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
87 EventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
88 EventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
89
90 StrictMock<MockGreaterThan> mock_gt;
91 StrictMock<MockExecutionIdManager> mock_execution_id_manager;
92 EXPECT_CALL(mock_execution_id_manager, get_execution_id)
93 .WillRepeatedly(Return(0)); // Use a fixed execution ID for the test
94
97
98 TestTraceContainer trace({
99 { { C::precomputed_first_row, 1 } },
100 });
101
102 std::vector<FF> fields = random_fields(2);
103
104 // This creates events for the poseidon2 hash trace
105 FF first_incr_hash = poseidon2.hash({ fields[0], 62 });
106 poseidon2.hash({ fields[1], first_incr_hash });
107
108 Poseidon2TraceBuilder poseidon2_builder;
109 BytecodeTraceBuilder bytecode_builder;
110
111 poseidon2_builder.process_hash(hash_event_emitter.dump_events(), trace);
112 bytecode_builder.process_hashing(
113 { { .bytecode_id = 1, .bytecode_length = 62, .bytecode_fields = fields /* 62 bytes */ } }, trace);
114
115 // TODO(dbanks12): re-enable once C++ and PIL use standard poseidon2 hashing for bytecode commitments.
116 // check_interaction<BytecodeTraceBuilder, lookup_bc_hashing_poseidon2_hash_settings>(trace);
117
118 check_relation<bc_hashing>(trace);
119}
120
121TEST(BytecodeHashingConstrainingTest, BytecodeInteractions)
122{
123 TestTraceContainer trace({
124 { { C::precomputed_first_row, 1 } },
125 });
126
127 std::vector<uint8_t> bytecode = random_bytes(40);
128 std::vector<FF> fields = simulation::encode_bytecode(bytecode);
129 BytecodeTraceBuilder builder;
130
131 builder.process_hashing({ { .bytecode_id = 1, .bytecode_length = 40, .bytecode_fields = fields } }, trace);
132 builder.process_decomposition(
133 { { .bytecode_id = 1, .bytecode = std::make_shared<std::vector<uint8_t>>(bytecode) } }, trace);
134
135 check_interaction<BytecodeTraceBuilder,
138
139 check_relation<bc_hashing>(trace);
140}
141
142TEST(BytecodeHashingConstrainingTest, NegativeInvalidStartAfterLatch)
143{
144 TestTraceContainer trace({
145 { { C::precomputed_first_row, 1 } },
146 });
147
148 BytecodeTraceBuilder builder;
149 builder.process_hashing({ { .bytecode_id = 1, .bytecode_length = 62, .bytecode_fields = random_fields(2) },
150 { .bytecode_id = 2, .bytecode_length = 93, .bytecode_fields = random_fields(3) } },
151 trace);
152 check_relation<bc_hashing>(trace, bc_hashing::SR_START_AFTER_LATCH);
153
154 // Row = 3 is the start of the hashing for bytecode id = 2
155 trace.set(Column::bc_hashing_start, 3, 0);
156 EXPECT_THROW_WITH_MESSAGE(check_relation<bc_hashing>(trace, bc_hashing::SR_START_AFTER_LATCH), "START_AFTER_LATCH");
157}
158
159TEST(BytecodeHashingConstrainingTest, NegativeInvalidPCIncrement)
160{
161 TestTraceContainer trace({
162 { { C::precomputed_first_row, 1 } },
163 });
164
165 BytecodeTraceBuilder builder;
166 builder.process_hashing(
167 {
168 { .bytecode_id = 1, .bytecode_length = 62, .bytecode_fields = random_fields(2) },
169 },
170 trace);
171 check_relation<bc_hashing>(trace, bc_hashing::SR_PC_INCREMENTS);
172
173 // This is the last row of the bytecode hashing
174 trace.set(Column::bc_hashing_pc_index, 2, 10);
175 EXPECT_THROW_WITH_MESSAGE(check_relation<bc_hashing>(trace, bc_hashing::SR_PC_INCREMENTS), "PC_INCREMENTS");
176}
177
178TEST(BytecodeHashingConstrainingTest, NegativeChainOutput)
179{
180 TestTraceContainer trace({
181 { { C::precomputed_first_row, 1 } },
182 });
183
184 BytecodeTraceBuilder builder;
185 builder.process_hashing(
186 {
187 { .bytecode_id = 1, .bytecode_length = 62, .bytecode_fields = random_fields(2) },
188 },
189 trace);
190 check_relation<bc_hashing>(trace, bc_hashing::SR_CHAIN_OUTPUT_TO_INCR);
191
192 // This is the last row of the bytecode hashing
193 trace.set(Column::bc_hashing_incremental_hash, 2, 123);
195 "CHAIN_OUTPUT_TO_INCR");
196}
197
198// Negative test where latch == 1 and sel == 0
199TEST(BytecodeHashingConstrainingTest, NegativeLatchNotSel)
200{
201 TestTraceContainer trace;
202 trace.set(0,
203 { {
204 { C::bc_hashing_latch, 1 },
205 { C::bc_hashing_sel, 1 },
206 } });
207
208 check_relation<bc_hashing>(trace, bc_hashing::SR_SEL_TOGGLED_AT_LATCH);
209 trace.set(C::bc_hashing_sel, 0, 0); // Mutate to wrong value
211 "SEL_TOGGLED_AT_LATCH");
212}
213
214TEST(BytecodeHashingConstrainingTest, NegativeBytecodeInteraction)
215{
216 TestTraceContainer trace({
217 { { C::precomputed_first_row, 1 } },
218 });
219
220 std::vector<uint8_t> bytecode = random_bytes(40);
221 std::vector<FF> fields = simulation::encode_bytecode(bytecode);
222
223 BytecodeTraceBuilder builder;
224
225 builder.process_hashing({ { .bytecode_id = 1, .bytecode_length = 40, .bytecode_fields = fields } }, trace);
226 builder.process_decomposition(
227 { { .bytecode_id = 1, .bytecode = std::make_shared<std::vector<uint8_t>>(bytecode) } }, trace);
228
229 // Row = 3 is the start of the hashing for bytecode id = 2
230 // Modify the pc index for the lookup of the second packed field
231 trace.set(Column::bc_hashing_pc_index, 2, 0);
232 // Modify the first incremental hash value from the bytecode length to the invalid value, 10
233 trace.set(Column::bc_hashing_incremental_hash, 1, 10);
234
236 (check_interaction<BytecodeTraceBuilder, lookup_bc_hashing_get_packed_field_settings>(trace)),
237 "Failed.*GET_PACKED_FIELD. Could not find tuple in destination.");
238
239 EXPECT_THROW_WITH_MESSAGE((check_interaction<BytecodeTraceBuilder, lookup_bc_hashing_iv_is_len_settings>(trace)),
240 "Failed.*IV_IS_LEN. Could not find tuple in destination.");
241}
242
243} // namespace
244} // namespace bb::avm2::constraining
static constexpr size_t SR_SEL_TOGGLED_AT_LATCH
static constexpr size_t SR_START_AFTER_LATCH
static constexpr size_t SR_CHAIN_OUTPUT_TO_INCR
static constexpr size_t SR_PC_INCREMENTS
void set(Column col, uint32_t row, const FF &value)
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
Implements a parallelized batch insertion indexed tree Accepts template argument of the type of store...
AluTraceBuilder builder
Definition alu.test.cpp:123
TestTraceContainer trace
NoopEventEmitter< Poseidon2PermutationEvent > perm_event_emitter
NoopEventEmitter< Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
NiceMock< MockGreaterThan > mock_gt
EventEmitter< Poseidon2HashEvent > hash_event_emitter
NiceMock< MockExecutionIdManager > mock_execution_id_manager
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(TxExecutionConstrainingTest, WriteTreeValue)
Definition tx.test.cpp:508
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
std::vector< FF > encode_bytecode(std::span< const uint8_t > bytecode)
std::vector< uint8_t > random_bytes(size_t n)
Definition fixtures.cpp:33
TestTraceContainer empty_trace()
Definition fixtures.cpp:153
std::vector< FF > random_fields(size_t n)
Definition fixtures.cpp:23
lookup_settings< lookup_bc_hashing_get_packed_field_settings_ > lookup_bc_hashing_get_packed_field_settings
lookup_settings< lookup_bc_hashing_iv_is_len_settings_ > lookup_bc_hashing_iv_is_len_settings
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13