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,
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,
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),
87 "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>(
94 "EMIT_L2_TO_L1_MSG_NUM_L2_TO_L1_MSGS_EMITTED_INCREASE");
95}
96
97TEST(SendL2ToL1MsgConstrainingTest, Discard)
98{
99 uint64_t prev_num_l2_to_l1_msgs = 0;
100 TestTraceContainer trace({ {
101 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
102 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
103 { C::execution_register_0_, /*recipient=*/42 },
104 { C::execution_register_1_, /*content=*/27 },
105 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
106 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::FF) },
107 { C::execution_remaining_l2_to_l1_msgs_inv, FF(MAX_L2_TO_L1_MSGS_PER_TX - prev_num_l2_to_l1_msgs).invert() },
108 { C::execution_sel_write_l2_to_l1_msg, 0 },
109 { C::execution_sel_opcode_error, 0 },
110 { C::execution_public_inputs_index,
112 { C::execution_discard, 1 },
113 { C::execution_prev_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs },
114 { C::execution_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs + 1 },
115 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_SENDL2TOL1MSG },
116 } });
117 check_relation<send_l2_to_l1_msg>(trace);
118
119 // Negative test: num l2 to l1 messages should increase when discarding
120 trace.set(C::execution_num_l2_to_l1_messages, 0, prev_num_l2_to_l1_msgs);
121 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(
123 "EMIT_L2_TO_L1_MSG_NUM_L2_TO_L1_MSGS_EMITTED_INCREASE");
124}
125
126TEST(SendL2ToL1MsgConstrainingTest, Interactions)
127{
128 uint64_t prev_num_l2_to_l1_msgs = 0;
129 FF recipient = 42;
130 FF content = 27;
131 AztecAddress address = 0xdeadbeef;
132 AvmAccumulatedData accumulated_data = {};
133
134 MockRangeCheck mock_range_check;
135 EventEmitter<FieldGreaterThanEvent> ff_gt_event_emitter;
136 FieldGreaterThan field_gt(mock_range_check, ff_gt_event_emitter);
137
138 ASSERT_FALSE(field_gt.ff_gt(recipient, FF(MAX_ETH_ADDRESS_VALUE)));
139
140 accumulated_data.l2_to_l1_msgs[0] = {
141 .message =
142 L2ToL1Message{
143 .recipient = recipient,
144 .content = content,
145 },
146 .contract_address = address,
147 };
148 AvmAccumulatedDataArrayLengths array_lengths = { .l2_to_l1_msgs = 1 };
149 auto public_inputs = PublicInputsBuilder()
150 .set_accumulated_data(accumulated_data)
151 .set_accumulated_data_array_lengths(array_lengths)
152 .build();
153
154 TestTraceContainer trace({ {
155 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
156 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
157 { C::execution_register_0_, recipient },
158 { C::execution_register_1_, content },
159 { C::execution_mem_tag_reg_0_, static_cast<uint8_t>(MemoryTag::FF) },
160 { C::execution_mem_tag_reg_1_, static_cast<uint8_t>(MemoryTag::FF) },
161 { C::execution_remaining_l2_to_l1_msgs_inv, FF(MAX_L2_TO_L1_MSGS_PER_TX - prev_num_l2_to_l1_msgs).invert() },
162 { C::execution_sel_write_l2_to_l1_msg, 1 },
163 { C::execution_sel_opcode_error, 0 },
164 { C::execution_public_inputs_index,
166 { C::execution_contract_address, address },
167 { C::execution_prev_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs },
168 { C::execution_num_l2_to_l1_messages, prev_num_l2_to_l1_msgs + 1 },
169 { C::execution_subtrace_operation_id, AVM_EXEC_OP_ID_SENDL2TOL1MSG },
170 } });
171
172 FieldGreaterThanTraceBuilder field_gt_builder;
173 field_gt_builder.process(ff_gt_event_emitter.dump_events(), trace);
174
175 PublicInputsTraceBuilder public_inputs_builder;
176 public_inputs_builder.process_public_inputs(trace, public_inputs);
177 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
178
179 tracegen::PrecomputedTraceBuilder precomputed_builder;
181
182 check_relation<send_l2_to_l1_msg>(trace);
183 check_interaction<ExecutionTraceBuilder,
186}
187
188TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldErrorIfRecipientTooLarge)
189{
190 TestTraceContainer trace({ {
191 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
192 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
193 { C::execution_sel_too_large_recipient_error, 1 },
194 { C::execution_sel_l2_to_l1_msg_limit_error, 0 },
195 { C::execution_is_static, 0 },
196 { C::execution_sel_opcode_error, 1 },
197 } });
198 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR);
199
200 // Negative test: sel_opcode_error must be on
201 trace.set(C::execution_sel_opcode_error, 0, 0);
202 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR),
203 "OPCODE_ERROR");
204}
205
206TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldErrorIfStatic)
207{
208 TestTraceContainer trace({ {
209 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
210 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
211 { C::execution_sel_l2_to_l1_msg_limit_error, 0 },
212 { C::execution_is_static, 1 },
213 { C::execution_sel_opcode_error, 1 },
214
215 } });
216 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR);
217
218 // Negative test: sel_opcode_error must be on
219 trace.set(C::execution_sel_opcode_error, 0, 0);
220 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_OPCODE_ERROR),
221 "OPCODE_ERROR");
222}
223
224TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldNotWriteIfDiscard)
225{
226 TestTraceContainer trace({ {
227 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
228 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
229 { C::execution_sel_opcode_error, 0 },
230 { C::execution_discard, 1 },
231 { C::execution_sel_write_l2_to_l1_msg, 0 },
232 } });
233 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_SEND_L2_TO_L1_MSG_CONDITION);
234
235 // Negative test: sel_write_l2_to_l1_msg must be off
236 trace.set(C::execution_sel_write_l2_to_l1_msg, 0, 1);
238 check_relation<send_l2_to_l1_msg>(trace, send_l2_to_l1_msg::SR_SEND_L2_TO_L1_MSG_CONDITION),
239 "SEND_L2_TO_L1_MSG_CONDITION");
240}
241
242TEST(SendL2ToL1MsgConstrainingTest, NegativeShouldNumL2ToL1MessagesIncrease)
243{
244 TestTraceContainer trace({ {
245 { C::execution_sel_execute_send_l2_to_l1_msg, 1 },
246 { C::execution_max_eth_address_value, FF(MAX_ETH_ADDRESS_VALUE) },
247 { C::execution_sel_opcode_error, 0 },
248 { C::execution_prev_num_l2_to_l1_messages, 0 },
249 { C::execution_num_l2_to_l1_messages, 1 },
250 } });
251 check_relation<send_l2_to_l1_msg>(trace,
253
254 // Negative test: num_l2_to_l1_messages must increase
255 trace.set(C::execution_prev_num_l2_to_l1_messages, 0, 1);
256 EXPECT_THROW_WITH_MESSAGE(check_relation<send_l2_to_l1_msg>(
258 "EMIT_L2_TO_L1_MSG_NUM_L2_TO_L1_MSGS_EMITTED_INCREASE");
259}
260
261} // namespace
262} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
#define AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX
#define MAX_ETH_ADDRESS_VALUE
#define MAX_L2_TO_L1_MSGS_PER_TX
#define AVM_EXEC_OP_ID_SENDL2TOL1MSG
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 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)
void set(Column col, uint32_t row, const FF &value)
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:81