Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
send_l2_to_l1_msg.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5
19
20namespace bb::avm2::constraining {
21namespace {
22
23using simulation::EventEmitter;
24using simulation::FieldGreaterThan;
25using simulation::FieldGreaterThanEvent;
26using simulation::MockRangeCheck;
27
28using tracegen::ExecutionTraceBuilder;
29using tracegen::PublicInputsTraceBuilder;
30using tracegen::TestTraceContainer;
31
32using testing::PublicInputsBuilder;
33using tracegen::FieldGreaterThanTraceBuilder;
34
36using C = Column;
37using send_l2_to_l1_msg = bb::avm2::send_l2_to_l1_msg<FF>;
38
39TEST(SendL2ToL1MsgConstrainingTest, Positive)
40{
41 uint64_t prev_num_l2_to_l1_msgs = MAX_L2_TO_L1_MSGS_PER_TX - 1;
42 TestTraceContainer trace({ {
43 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
44 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
45 { C::execution_register_0_, /*recipient=*/42 },
46 { C::execution_register_1_, /*content=*/27 },
47 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
48 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::FF) },
49 { C::execution_remaining_l2_to_l1_msgs_inv, FF(MAX_L2_TO_L1_MSGS_PER_TX - prev_num_l2_to_l1_msgs).invert() },
50 { C::execution_sel_write_l2_to_l1_msg, 1 },
51 { C::execution_sel_opcode_error, 0 },
52 { C::execution_public_inputs_index,
53 AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX + prev_num_l2_to_l1_msgs },
54 { C::execution_prev_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs },
55 { C::execution_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs + 1 },
56 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_SENDL2TOL1MSG },
57
58 } });
59 check_relation<send_l2_to_l1_msg>(trace);
60}
61
62TEST(SendL2ToL1MsgConstrainingTest, LimitReached)
63{
64 uint64_t prev_num_l2_to_l1_msgs = MAX_L2_TO_L1_MSGS_PER_TX;
65 TestTraceContainer trace({ {
66 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
67 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
68 { C::execution_register_0_, /*recipient=*/42 },
69 { C::execution_register_1_, /*content=*/27 },
70 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
71 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::FF) },
72 { C::execution_sel_l2_to_l1_msg_limit_error, 1 },
73 { C::execution_remaining_l2_to_l1_msgs_inv, 0 },
74 { C::execution_sel_write_l2_to_l1_msg, 0 },
75 { C::execution_sel_opcode_error, 1 },
76 { C::execution_public_inputs_index,
77 AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX + prev_num_l2_to_l1_msgs },
78 { C::execution_prev_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs },
79 { C::execution_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs },
80 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_SENDL2TOL1MSG },
81 } });
82 check_relation<send_l2_to_l1_msg>(trace);
83
84 // Negative test: sel_opcode_error must be on
85 trace.set(C::execution_sel_opcode_error, 0, 0);
86 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR),
88 trace.set(C::execution_sel_opcode_error, 0, 1);
89
90 // Negative test: num l2 to l1 messages must be the same
91 trace.set(C::execution_num_l2_to_l1_messages, 0, prev_num_l2_to_l1_msgs + 1);
92 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(
96}
97
98TEST(SendL2ToL1MsgConstrainingTest, Discard)
99{
100 uint64_t prev_num_l2_to_l1_msgs = 0;
101 TestTraceContainer trace({ {
102 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
103 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
104 { C::execution_register_0_, /*recipient=*/42 },
105 { C::execution_register_1_, /*content=*/27 },
106 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
107 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::FF) },
108 { C::execution_remaining_l2_to_l1_msgs_inv, FF(MAX_L2_TO_L1_MSGS_PER_TX - prev_num_l2_to_l1_msgs).invert() },
109 { C::execution_sel_write_l2_to_l1_msg, 0 },
110 { C::execution_sel_opcode_error, 0 },
111 { C::execution_public_inputs_index,
112 AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX + prev_num_l2_to_l1_msgs },
113 { C::execution_discard, 1 },
114 { C::execution_prev_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs },
115 { C::execution_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs + 1 },
116 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_SENDL2TOL1MSG },
117 } });
118 check_relation<send_l2_to_l1_msg>(trace);
119
120 // Negative test: num l2 to l1 messages should increase when discarding
121 trace.set(C::execution_num_l2_to_l1_messages, 0, prev_num_l2_to_l1_msgs);
122 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(
126}
127
128TEST(SendL2ToL1MsgConstrainingTest, Interactions)
129{
130 uint64_t prev_num_l2_to_l1_msgs = 0;
131 FF recipient = 42;
132 FF content = 27;
133 AztecAddress address = 0xdeadbeef;
134 AvmAccumulatedData accumulated_data = {};
135
136 MockRangeCheck mock_range_check;
137 EventEmitter<FieldGreaterThanEvent> ff_gt_event_emitter;
138 FieldGreaterThan field_gt(mock_range_check, ff_gt_event_emitter);
139
140 ASSERT_FALSE(field_gt.ff_gt(recipient, FF(MAX_ETH_ADDRESS_VALUE)));
141
142 accumulated_data.l2_to_l1_msgs[0] = {
143 .message =
144 L2ToL1Message{
145 .recipient = recipient,
146 .content = content,
147 },
148 .contract_address = address,
149 };
150 AvmAccumulatedDataArrayLengths array_lengths = { .l2_to_l1_msgs = 1 };
151 auto public_inputs = PublicInputsBuilder()
152 .set_accumulated_data(accumulated_data)
153 .set_accumulated_data_array_lengths(array_lengths)
154 .build();
155
156 TestTraceContainer trace({ {
157 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
158 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
159 { C::execution_register_0_, recipient },
160 { C::execution_register_1_, content },
161 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
162 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::FF) },
163 { C::execution_remaining_l2_to_l1_msgs_inv, FF(MAX_L2_TO_L1_MSGS_PER_TX - prev_num_l2_to_l1_msgs).invert() },
164 { C::execution_sel_write_l2_to_l1_msg, 1 },
165 { C::execution_sel_opcode_error, 0 },
166 { C::execution_public_inputs_index,
167 AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX + prev_num_l2_to_l1_msgs },
168 { C::execution_contract_address, address },
169 { C::execution_prev_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs },
170 { C::execution_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs + 1 },
171 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_SENDL2TOL1MSG },
172 } });
173
174 FieldGreaterThanTraceBuilder field_gt_builder;
175 field_gt_builder.process(ff_gt_event_emitter.dump_events(), trace);
176
177 PublicInputsTraceBuilder public_inputs_builder;
178 public_inputs_builder.process_public_inputs(trace, public_inputs);
179 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
180
181 tracegen::PrecomputedTraceBuilder precomputed_builder;
183
184 check_relation<send_l2_to_l1_msg>(trace);
185 check_interaction<ExecutionTraceBuilder,
188}
189
190TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldErrorIfRecipientTooLarge)
191{
192 TestTraceContainer trace({ {
193 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
194 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
195 { C::execution_sel_too_large_recipient_error, 1 },
196 { C::execution_sel_l2_to_l1_msg_limit_error, 0 },
197 { C::execution_is_static, 0 },
198 { C::execution_sel_opcode_error, 1 },
199 } });
200 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR);
201
202 // Negative test: sel_opcode_error must be on
203 trace.set(C::execution_sel_opcode_error, 0, 0);
204 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR),
206}
207
208TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldErrorIfStatic)
209{
210 TestTraceContainer trace({ {
211 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
212 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
213 { C::execution_sel_l2_to_l1_msg_limit_error, 0 },
214 { C::execution_is_static, 1 },
215 { C::execution_sel_opcode_error, 1 },
216
217 } });
218 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR);
219
220 // Negative test: sel_opcode_error must be on
221 trace.set(C::execution_sel_opcode_error, 0, 0);
222 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR),
224}
225
226TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldNotWriteIfDiscard)
227{
228 TestTraceContainer trace({ {
229 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
230 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
231 { C::execution_sel_opcode_error, 0 },
232 { C::execution_discard, 1 },
233 { C::execution_sel_write_l2_to_l1_msg, 0 },
234 } });
235 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_SEND_L2_TO_L1_MSG_CONDITION);
236
237 // Negative test: sel_write_l2_to_l1_msg must be off
238 trace.set(C::execution_sel_write_l2_to_l1_msg, 0, 1);
240 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_SEND_L2_TO_L1_MSG_CONDITION),
242}
243
244TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldNumL2ToL1MessagesIncrease)
245{
246 TestTraceContainer trace({ {
247 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
248 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
249 { C::execution_sel_opcode_error, 0 },
250 { C::execution_prev_num_l2_to_l1_messages, 0 },
251 { C::execution_num_l2_to_l1_messages, 1 },
252 } });
253 check_relation<send_l2_to_l1_msg>(trace,
255
256 // Negative test: num_l2_to_l1_messages must increase
257 trace.set(C::execution_prev_num_l2_to_l1_messages, 0, 1);
258 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(
262}
263
264} // namespace
265} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:224
FieldGreaterThan field_gt
static constexpr size_t SR_OPCODE_ERROR
static constexpr size_t SR_EMIT_L2_TO_L1_MSG_NUM_L2_TO_L1_MSGS_EMITTED_INCREASE
static std::string get_subrelation_label(size_t index)
static constexpr size_t SR_SEND_L2_TO_L1_MSG_CONDITION
bool ff_gt(const FF &a, const FF &b) override
Computes the result of a > b (in a constrained way).
Definition field_gt.cpp:66
void process(const simulation::EventEmitterInterface< simulation::FieldGreaterThanEvent >::Container &events, TraceContainer &trace)
Processes FieldGreaterThanEvent events and generates trace rows for the ff_gt gadget.
void process_misc(TraceContainer &trace, const uint32_t num_rows=PRECOMPUTED_TRACE_SIZE)
Populate miscellaneous precomputed columns: first_row selector and idx (row index).
void set(Column col, uint32_t row, const FF &value, bool use_atomic_limbs=false)
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:120
FieldGreaterThanTraceBuilder field_gt_builder
Definition alu.test.cpp:122
TestTraceContainer trace
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
lookup_settings< lookup_send_l2_to_l1_msg_recipient_check_settings_ > lookup_send_l2_to_l1_msg_recipient_check_settings
lookup_settings< lookup_send_l2_to_l1_msg_write_l2_to_l1_msg_settings_ > lookup_send_l2_to_l1_msg_write_l2_to_l1_msg_settings
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr field invert() const noexcept
tracegen::PublicInputsTraceBuilder public_inputs_builder
Definition tx.test.cpp:84