1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
32using tracegen::ExecutionTraceBuilder;
33using tracegen::PublicDataTreeTraceBuilder;
34using tracegen::TestTraceContainer;
35using tracegen::WrittenPublicDataSlotsTreeCheckTraceBuilder;
38using simulation::EventEmitter;
39using simulation::MockExecutionIdManager;
40using simulation::MockFieldGreaterThan;
41using simulation::MockMerkleCheck;
42using simulation::MockPoseidon2;
43using simulation::PublicDataTreeCheck;
48using simulation::WrittenPublicDataSlotsTreeCheck;
49using simulation::WrittenPublicDataSlotsTreeCheckEvent;
52using testing::NiceMock;
60TEST(SStoreConstrainingTest, PositiveTest)
62 TestTraceContainer
trace({
63 { { C::execution_sel_execute_sstore, 1 },
64 { C::execution_sel_gas_sstore, 1 },
65 { C::execution_dynamic_da_gas_factor, 1 },
66 { C::execution_register_0_, 27 },
67 { C::execution_register_1_, 42 },
68 { C::execution_prev_written_public_data_slots_tree_size, 5 },
69 { C::execution_max_data_writes_reached, 0 },
70 { C::execution_remaining_data_writes_inv,
72 { C::execution_sel_write_public_data, 1 },
75 check_relation<sstore>(
trace);
78TEST(SStoreConstrainingTest, NegativeDynamicL2GasIsZero)
80 TestTraceContainer
trace({ {
81 { C::execution_sel_execute_sstore, 1 },
82 { C::execution_dynamic_l2_gas_factor, 1 },
85 "SSTORE_DYN_L2_GAS_IS_ZERO");
88TEST(SStoreConstrainingTest, MaxDataWritesReached)
90 TestTraceContainer
trace({
92 { C::execution_sel_execute_sstore, 1 },
93 { C::execution_prev_written_public_data_slots_tree_size,
95 { C::execution_remaining_data_writes_inv, 0 },
96 { C::execution_max_data_writes_reached, 1 },
101 trace.
set(C::execution_max_data_writes_reached, 0, 0);
104 "SSTORE_MAX_DATA_WRITES_REACHED");
107TEST(SStoreConstrainingTest, OpcodeError)
109 TestTraceContainer
trace({
111 { C::execution_sel_execute_sstore, 1 },
112 { C::execution_dynamic_da_gas_factor, 1 },
113 { C::execution_max_data_writes_reached, 1 },
114 { C::execution_sel_opcode_error, 1 },
117 { C::execution_sel_execute_sstore, 1 },
118 { C::execution_dynamic_da_gas_factor, 0 },
119 { C::execution_max_data_writes_reached, 0 },
120 { C::execution_is_static, 1 },
121 { C::execution_sel_opcode_error, 1 },
124 { C::execution_sel_execute_sstore, 1 },
125 { C::execution_dynamic_da_gas_factor, 0 },
126 { C::execution_max_data_writes_reached, 1 },
127 { C::execution_sel_opcode_error, 0 },
132 trace.
set(C::execution_dynamic_da_gas_factor, 0, 0);
135 "OPCODE_ERROR_IF_OVERFLOW_OR_STATIC");
137 trace.
set(C::execution_dynamic_da_gas_factor, 0, 1);
139 trace.
set(C::execution_is_static, 1, 0);
142 "OPCODE_ERROR_IF_OVERFLOW_OR_STATIC");
145TEST(SStoreConstrainingTest, TreeStateNotChangedOnError)
147 TestTraceContainer
trace({ {
148 { C::execution_sel_execute_sstore, 1 },
149 { C::execution_prev_public_data_tree_root, 27 },
150 { C::execution_prev_public_data_tree_size, 5 },
151 { C::execution_prev_written_public_data_slots_tree_root, 28 },
152 { C::execution_prev_written_public_data_slots_tree_size, 6 },
153 { C::execution_public_data_tree_root, 27 },
154 { C::execution_public_data_tree_size, 5 },
155 { C::execution_written_public_data_slots_tree_root, 28 },
156 { C::execution_written_public_data_slots_tree_size, 6 },
157 { C::execution_sel_opcode_error, 1 },
160 check_relation<sstore>(
trace,
167 trace.
set(C::execution_written_public_data_slots_tree_root, 0, 29);
169 "SSTORE_WRITTEN_SLOTS_ROOT_NOT_CHANGED");
172 trace.
set(C::execution_written_public_data_slots_tree_size, 0, 7);
174 "SSTORE_WRITTEN_SLOTS_SIZE_NOT_CHANGED");
177 trace.
set(C::execution_public_data_tree_root, 0, 29);
179 "SSTORE_PUBLIC_DATA_TREE_ROOT_NOT_CHANGED");
182 trace.
set(C::execution_public_data_tree_size, 0, 7);
184 "SSTORE_PUBLIC_DATA_TREE_SIZE_NOT_CHANGED");
187TEST(SStoreConstrainingTest, Interactions)
190 NiceMock<MockFieldGreaterThan>
field_gt;
191 NiceMock<MockMerkleCheck> merkle_check;
194 EventEmitter<WrittenPublicDataSlotsTreeCheckEvent> written_public_data_slots_emitter;
198 EventEmitter<PublicDataTreeCheckEvent> public_data_tree_check_event_emitter;
199 PublicDataTreeCheck public_data_tree_check(
208 uint64_t low_leaf_index = 30;
209 std::vector<FF> low_leaf_sibling_path = { 1, 2, 3, 4, 5 };
211 AppendOnlyTreeSnapshot public_data_tree_before = AppendOnlyTreeSnapshot{
213 .nextAvailableLeafIndex = 128,
217 EXPECT_CALL(
poseidon2,
hash(_)).WillRepeatedly([](
const std::vector<FF>& inputs) {
220 EXPECT_CALL(
field_gt, ff_gt(_, _)).WillRepeatedly([](
const FF&
a,
const FF&
b) {
224 EXPECT_CALL(merkle_check,
write)
225 .WillRepeatedly([]([[maybe_unused]]
FF current_leaf,
229 [[maybe_unused]]
FF prev_root) {
235 auto public_data_tree_after = public_data_tree_check.write(
slot,
240 low_leaf_sibling_path,
241 public_data_tree_before,
247 TestTraceContainer
trace({
249 { C::execution_sel_execute_sstore, 1 },
251 { C::execution_sel_gas_sstore, 1 },
252 { C::execution_dynamic_da_gas_factor, 1 },
253 { C::execution_register_0_,
value },
254 { C::execution_register_1_,
slot },
255 { C::execution_max_data_writes_reached, 0 },
256 { C::execution_remaining_data_writes_inv,
258 written_slots_tree_before.nextAvailableLeafIndex)
261 { C::execution_sel_write_public_data, 1 },
262 { C::execution_prev_public_data_tree_root, public_data_tree_before.root },
263 { C::execution_prev_public_data_tree_size, public_data_tree_before.nextAvailableLeafIndex },
264 { C::execution_public_data_tree_root, public_data_tree_after.root },
265 { C::execution_public_data_tree_size, public_data_tree_after.nextAvailableLeafIndex },
266 { C::execution_prev_written_public_data_slots_tree_root, written_slots_tree_before.root },
267 { C::execution_prev_written_public_data_slots_tree_size, written_slots_tree_before.nextAvailableLeafIndex },
268 { C::execution_written_public_data_slots_tree_root, written_slots_tree_after.root },
269 { C::execution_written_public_data_slots_tree_size, written_slots_tree_after.nextAvailableLeafIndex },
273 PublicDataTreeTraceBuilder public_data_tree_trace_builder;
274 public_data_tree_trace_builder.process(public_data_tree_check_event_emitter.dump_events(),
trace);
276 WrittenPublicDataSlotsTreeCheckTraceBuilder written_slots_tree_trace_builder;
277 written_slots_tree_trace_builder.process(written_public_data_slots_emitter.dump_events(),
trace);
279 check_relation<sstore>(
trace);
#define AVM_EXEC_OP_ID_SSTORE
#define AVM_WRITTEN_PUBLIC_DATA_SLOTS_TREE_INITIAL_SIZE
#define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
static constexpr size_t SR_SSTORE_DYN_L2_GAS_IS_ZERO
static constexpr size_t SR_SSTORE_WRITTEN_SLOTS_SIZE_NOT_CHANGED
static constexpr size_t SR_OPCODE_ERROR_IF_OVERFLOW_OR_STATIC
static constexpr size_t SR_SSTORE_MAX_DATA_WRITES_REACHED
static constexpr size_t SR_SSTORE_WRITTEN_SLOTS_ROOT_NOT_CHANGED
static constexpr size_t SR_SSTORE_PUBLIC_DATA_TREE_SIZE_NOT_CHANGED
static constexpr size_t SR_SSTORE_PUBLIC_DATA_TREE_ROOT_NOT_CHANGED
void set(Column col, uint32_t row, const FF &value)
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
ExecutionIdManager execution_id_manager
NullifierTreeLeafPreimage low_leaf
AztecAddress contract_address
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
void hash(State &state) noexcept
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(TxExecutionConstrainingTest, WriteTreeValue)
std::variant< PublicDataTreeReadWriteEvent, CheckPointEventType > PublicDataTreeCheckEvent
IndexedLeaf< PublicDataLeafValue > PublicDataTreeLeafPreimage
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
FF unconstrained_root_from_path(const FF &leaf_value, const uint64_t leaf_index, std::span< const FF > path)
::bb::crypto::merkle_tree::PublicDataLeafValue PublicDataLeafValue
WrittenPublicDataSlotsTree build_public_data_slots_tree()
FF unconstrained_compute_leaf_slot(const AztecAddress &contract_address, const FF &slot)
lookup_settings< lookup_execution_check_written_storage_slot_settings_ > lookup_execution_check_written_storage_slot_settings
lookup_settings< lookup_sstore_record_written_storage_slot_settings_ > lookup_sstore_record_written_storage_slot_settings
lookup_settings< lookup_sstore_storage_write_settings_ > lookup_sstore_storage_write_settings
void write(B &buf, field2< base_field, Params > const &value)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
NiceMock< MockFieldGreaterThan > field_gt
NiceMock< MockExecution > execution
NiceMock< MockWrittenPublicDataSlotsTreeCheck > written_public_data_slots_tree_check