18#include <gmock/gmock.h>
19#include <gtest/gtest.h>
26using ::testing::ElementsAre;
27using ::testing::NiceMock;
28using ::testing::Return;
29using ::testing::ReturnRef;
30using ::testing::SizeIs;
31using ::testing::StrictMock;
32using ::testing::TestWithParam;
38TEST(AvmSimulationUpdateCheck, NeverWritten)
40 uint64_t current_timestamp = 100;
44 FF delayed_public_mutable_slot =
52 NiceMock<MockHighLevelMerkleDB>
merkle_db;
53 StrictMock<MockLowLevelMerkleDB> low_level_merkle_db;
64 .WillRepeatedly(Return(
FF(0)));
65 EXPECT_CALL(
merkle_db, get_tree_state()).WillRepeatedly(Return(tree_states));
73 .current_class_id =
instance.current_contract_class_id,
74 .original_class_id =
instance.original_contract_class_id,
76 .current_timestamp = current_timestamp,
78 .update_preimage_metadata = 0,
79 .update_preimage_pre_class_id = 0,
80 .update_preimage_post_class_id = 0,
81 .delayed_public_mutable_slot = delayed_public_mutable_slot,
87 "Current class id.*does not match expected class id.*");
102 .original_class_id = 27,
103 .current_class_id = 27,
104 .should_throw =
false },
107 .original_class_id = 27,
108 .current_class_id = 28,
109 .should_throw =
true },
110 TestParams{ .original_class_id = 27,
111 .current_class_id = 2,
112 .update_pre_class = 2,
113 .update_post_class = 3,
114 .update_timestamp_of_change = 101,
115 .should_throw =
false },
116 TestParams{ .original_class_id = 27,
117 .current_class_id = 2,
118 .update_pre_class = 2,
119 .update_post_class = 3,
120 .update_timestamp_of_change = 99,
121 .should_throw =
true },
122 TestParams{ .original_class_id = 27,
123 .current_class_id = 3,
124 .update_pre_class = 2,
125 .update_post_class = 3,
126 .update_timestamp_of_change = 99,
127 .should_throw =
false },
128 TestParams{ .original_class_id = 27,
129 .current_class_id = 3,
130 .update_pre_class = 2,
131 .update_post_class = 3,
132 .update_timestamp_of_change = 101,
133 .should_throw =
true },
134 TestParams{ .original_class_id = 27,
135 .current_class_id = 3,
136 .update_pre_class = 2,
137 .update_post_class = 3,
138 .update_timestamp_of_change = 100,
139 .should_throw =
false },
140 TestParams{ .original_class_id = 27,
141 .current_class_id = 2,
142 .update_pre_class = 2,
143 .update_post_class = 3,
144 .update_timestamp_of_change = 100,
145 .should_throw =
true },
146 TestParams{ .original_class_id = 1,
147 .current_class_id = 1,
148 .update_pre_class = 0,
149 .update_post_class = 3,
150 .update_timestamp_of_change = 101,
151 .should_throw =
false },
152 TestParams{ .original_class_id = 1,
153 .current_class_id = 3,
154 .update_pre_class = 0,
155 .update_post_class = 3,
156 .update_timestamp_of_change = 101,
157 .should_throw =
true },
160class UpdateCheckHashNonzeroTest :
public TestWithParam<TestParams> {};
162TEST_P(UpdateCheckHashNonzeroTest, WithHash)
164 const auto& param = GetParam();
166 uint64_t current_timestamp = 100;
168 instance.current_contract_class_id = param.current_class_id;
169 instance.original_contract_class_id = param.original_class_id;
172 FF delayed_public_mutable_slot =
178 FF update_metadata =
FF(
static_cast<uint64_t
>(123) << 32) + param.update_timestamp_of_change;
179 std::vector<FF> update_preimage = { update_metadata, param.update_pre_class, param.update_post_class };
180 std::vector<FF> update_preimage_slots;
182 for (
size_t i = 0; i < update_preimage.size(); ++i) {
185 delayed_public_mutable_slot + i });
186 update_preimage_slots.push_back(leaf_slot);
191 TreeStates tree_states = {};
192 tree_states.public_data_tree.tree.root = 42;
195 NiceMock<MockHighLevelMerkleDB>
merkle_db;
196 NiceMock<MockLowLevelMerkleDB> mock_low_level_merkle_db;
205 GlobalVariables globals{ .timestamp = current_timestamp };
211 .WillRepeatedly(Return(update_hash));
212 EXPECT_CALL(
merkle_db, get_tree_state()).WillRepeatedly(Return(tree_states));
213 EXPECT_CALL(
merkle_db, as_unconstrained()).WillRepeatedly(ReturnRef(mock_low_level_merkle_db));
217 for (
size_t i = 0; i < update_preimage_slots.size(); ++i) {
218 if (leaf_slot == update_preimage_slots[i]) {
222 throw std::runtime_error(
"Leaf not found");
225 EXPECT_CALL(mock_low_level_merkle_db, get_leaf_preimage_public_data_tree(_))
226 .WillRepeatedly([&](
const uint64_t&
index) {
231 EXPECT_CALL(
poseidon2, hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
return poseidon2::hash(input); });
233 EXPECT_CALL(range_check, assert_range(_, _)).WillRepeatedly([](
const uint128_t&
value,
const uint8_t& range) {
235 throw std::runtime_error(
"Range checks aren't supported for bit-sizes > 128");
241 throw std::runtime_error(
"Value is out of range");
245 if (param.should_throw) {
247 "Current class id.*does not match expected class id.*");
252 ElementsAre(UpdateCheckEvent{
253 .address = derived_address,
254 .current_class_id =
instance.current_contract_class_id,
255 .original_class_id =
instance.original_contract_class_id,
256 .public_data_tree_root = tree_states.public_data_tree.tree.root,
257 .current_timestamp = current_timestamp,
258 .update_hash = update_hash,
259 .update_preimage_metadata = update_metadata,
260 .update_preimage_pre_class_id = param.update_pre_class,
261 .update_preimage_post_class_id = param.update_post_class,
262 .delayed_public_mutable_slot = delayed_public_mutable_slot,
267INSTANTIATE_TEST_SUITE_P(AvmSimulationUpdateCheck, UpdateCheckHashNonzeroTest, ::testing::ValuesIn(hash_nonzero_tests));
269TEST(AvmSimulationUpdateCheck, HashMismatch)
271 uint64_t current_timestamp = 100;
275 FF delayed_public_mutable_slot =
281 TreeSnapshots trees = {};
284 NiceMock<MockHighLevelMerkleDB>
merkle_db;
285 NiceMock<MockLowLevelMerkleDB> mock_low_level_merkle_db;
290 GlobalVariables globals{ .timestamp = current_timestamp };
296 .WillRepeatedly(Return(
FF(27)));
297 EXPECT_CALL(mock_low_level_merkle_db, get_tree_roots()).WillRepeatedly(Return(trees));
298 EXPECT_CALL(
merkle_db, as_unconstrained()).WillRepeatedly(ReturnRef(mock_low_level_merkle_db));
305 EXPECT_CALL(mock_low_level_merkle_db, get_leaf_preimage_public_data_tree(_))
306 .WillRepeatedly([&](
const uint64_t&
index) {
311 EXPECT_CALL(
poseidon2, hash(_)).WillRepeatedly([](
const std::vector<FF>& input) {
return poseidon2::hash(input); });
314 "Stored hash does not match preimage hash");
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
std::shared_ptr< Napi::ThreadSafeFunction > instance
#define UPDATES_DELAYED_PUBLIC_MUTABLE_VALUES_LEN
#define DOM_SEP__PUBLIC_STORAGE_MAP_SLOT
#define UPDATED_CLASS_IDS_SLOT
#define DOM_SEP__PUBLIC_LEAF_SLOT
#define CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS
StrictMock< MockHighLevelMerkleDB > merkle_db
Native Poseidon2 hash function implementation.
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
StrictMock< MockFieldGreaterThan > mock_field_gt
EventEmitter< DataCopyEvent > event_emitter
StrictMock< MockUpdateCheck > update_check
TEST_P(AvmRecursiveTestsParameterized, TwoLayerAvmRecursion)
A test of the Two Layer AVM recursive verifier.
INSTANTIATE_TEST_SUITE_P(PaddingVariants, AvmRecursiveTestsParameterized, ::testing::Values(false, true), [](const auto &info) { return info.param ? "Padded" :"Unpadded";})
AVM range check gadget for witness generation.
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
IndexedLeaf< PublicDataLeafValue > PublicDataTreeLeafPreimage
::bb::crypto::merkle_tree::PublicDataLeafValue PublicDataLeafValue
FF compute_contract_address(const ContractInstance &contract_instance)
ContractInstance random_contract_instance()
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
unsigned __int128 uint128_t
NoopEventEmitter< GreaterThanEvent > greater_than_event_emitter
NoopEventEmitter< FieldGreaterThanEvent > field_gt_event_emitter
FF update_timestamp_of_change
AppendOnlyTreeSnapshot tree
TreeState public_data_tree