33#include < cstdint>
44#include < vector>
55
6+ #include " barretenberg/avm_fuzzer/fuzz_lib/constants.hpp"
67#include " barretenberg/common/throw_or_abort.hpp"
78#include " barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp"
89#include " barretenberg/crypto/poseidon2/poseidon2.hpp"
910#include " barretenberg/vm2/common/aztec_constants.hpp"
1011#include " barretenberg/vm2/common/aztec_types.hpp"
12+ #include " barretenberg/vm2/simulation/lib/contract_crypto.hpp"
13+ #include " barretenberg/vm2/simulation/lib/merkle.hpp"
1114
1215using namespace bb ::avm2::simulation;
1316using Poseidon2 = bb::crypto::Poseidon2<bb::crypto::Poseidon2Bn254ScalarFieldParams>;
14- using namespace bb ::crypto::merkle_tree;
1517using namespace bb ::world_state;
1618
17- // TODO(ilyas): implement other methods as needed
1819namespace bb ::avm2::fuzzer {
1920
20- TreeSnapshots FuzzerLowLevelDB::get_tree_roots () const
21- {
22- return {
23- .l1_to_l2_message_tree = { .root = FF (0 ), .next_available_leaf_index = 0 },
24- .note_hash_tree = { .root = FF (0 ), .next_available_leaf_index = next_available_note_hash_index },
25- .nullifier_tree = { .root = FF (0 ), .next_available_leaf_index = next_available_nullifier_index },
26- .public_data_tree = { .root = FF (0 ), .next_available_leaf_index = next_available_public_data_index },
27- };
28- }
29-
30- SiblingPath FuzzerLowLevelDB::get_sibling_path ([[maybe_unused]] MerkleTreeId tree_id,
31- [[maybe_unused]] index_t leaf_index) const
32- {
33- throw_or_abort (" FuzzerLowLevelDB::get_sibling_path not implemented" );
34- }
35-
36- std::pair<FF, index_t > FuzzerLowLevelDB::get_indexed_low_leaf_helper (
37- const std::vector<std::pair<FF, index_t >>& value_sorted_leaves, const FF& value) const
38- {
39- for (size_t i = 0 ; i < value_sorted_leaves.size (); ++i) {
40- if (value_sorted_leaves[i].first == value) {
41- return value_sorted_leaves[i];
42- }
43- if (value_sorted_leaves[i].first > value) {
44- return value_sorted_leaves[i - 1 ];
45- }
46- }
47- // If we reach here, the value is larger than any leaf in the tree, return the last leaf
48- return value_sorted_leaves.back ();
49- }
50-
51- GetLowIndexedLeafResponse FuzzerLowLevelDB::get_low_indexed_leaf (MerkleTreeId tree_id, const FF& value) const
52- {
53- switch (tree_id) {
54- case MerkleTreeId::NULLIFIER_TREE: {
55- auto [low_value, low_index] = get_indexed_low_leaf_helper (nullifier_values, value);
56- return GetLowIndexedLeafResponse (low_value == value, low_index);
57- break ;
58- }
59- case MerkleTreeId::PUBLIC_DATA_TREE: {
60- auto [low_value, low_index] = get_indexed_low_leaf_helper (public_data_slots, value);
61- return GetLowIndexedLeafResponse (low_value == value, low_index);
62- break ;
63- }
64- default :
65- break ;
66- }
67- return GetLowIndexedLeafResponse (false , 0 );
68- }
69- FF FuzzerLowLevelDB::get_leaf_value (MerkleTreeId tree_id, index_t leaf_index) const
70- {
71- switch (tree_id) {
72- case MerkleTreeId::NULLIFIER_TREE:
73- return nullifier_leaves.at (leaf_index).nullifier ;
74- case MerkleTreeId::PUBLIC_DATA_TREE:
75- return public_data_leaves.at (leaf_index).value ;
76- case MerkleTreeId::NOTE_HASH_TREE:
77- return note_hash_leaves.at (leaf_index);
78- default :
79- break ;
80- }
81- return FF (0 );
82- }
83- simulation::IndexedLeaf<PublicDataLeafValue> FuzzerLowLevelDB::get_leaf_preimage_public_data_tree (
84- index_t leaf_index) const
85- {
86- PublicDataLeafValue leaf_value = public_data_leaves.at (leaf_index);
87- std::pair<FF, index_t > value_index_pair = { leaf_value.value , leaf_index };
88- // Find index in public_data_slots
89- auto it = std::ranges::find_if (
90- public_data_slots.begin (), public_data_slots.end (), [&value_index_pair](const std::pair<FF, index_t >& pair) {
91- return pair.second == value_index_pair.second ;
92- });
93- if (it == public_data_slots.end ()) {
94- throw_or_abort (" FuzzerLowLevelDB::get_leaf_preimage_public_data_tree: leaf not found in public_data_slots" );
95- }
96- it++; // Now iterator is at the next element
97- if (it == public_data_slots.end ()) {
98- // If this is the last leaf, return with index 0
99- return simulation::IndexedLeaf<PublicDataLeafValue>(leaf_value, 0 , 0 );
100- }
101- auto [next_value, next_index] = *it;
102- return bb::crypto::merkle_tree::IndexedLeaf<PublicDataLeafValue>(leaf_value, next_index, next_value);
103- }
104-
105- simulation::IndexedLeaf<NullifierLeafValue> FuzzerLowLevelDB::get_leaf_preimage_nullifier_tree (index_t leaf_index) const
106- {
107- auto leaf_value = nullifier_leaves.at (leaf_index);
108- std::pair<FF, index_t > value_index_pair = { leaf_value.nullifier , leaf_index };
109- // Find index in nullifiers_values
110- auto it = std::ranges::find_if (
111- nullifier_values.begin (), nullifier_values.end (), [&value_index_pair](const std::pair<FF, index_t >& pair) {
112- return pair.second == value_index_pair.second ;
113- });
114- if (it == nullifier_values.end ()) {
115- throw_or_abort (" FuzzerLowLevelDB::get_leaf_preimage_nullifier_tree: leaf not found in nullifier_values" );
116- }
117-
118- it++; // Now iterator is at the next element
119-
120- if (it == nullifier_values.end ()) {
121- // If this is the last leaf, return with index 0
122- return simulation::IndexedLeaf<NullifierLeafValue>(leaf_value, 0 , 0 );
123- }
124- auto [next_value, next_index] = *it;
125- return simulation::IndexedLeaf<NullifierLeafValue>(leaf_value, next_index, next_value);
126- }
127-
128- simulation::SequentialInsertionResult<PublicDataLeafValue> FuzzerLowLevelDB::insert_indexed_leaves_public_data_tree (
129- const PublicDataLeafValue& leaf_value)
130- {
131- // Add to map
132- public_data_leaves[next_available_public_data_index] = leaf_value;
133- // Add to sorted vector
134- public_data_slots.push_back ({ leaf_value.slot , next_available_public_data_index });
135- // Sort vector
136- std::ranges::sort (
137- public_data_slots.begin (),
138- public_data_slots.end (),
139- [](const std::pair<FF, index_t >& a, const std::pair<FF, index_t >& b) { return a.first < b.first ; });
140-
141- // Increment next available index
142- next_available_public_data_index++;
143- // Don't return any witness data for now, as it's not used for pure calls.
144- return {};
145- }
146-
147- simulation::SequentialInsertionResult<NullifierLeafValue> FuzzerLowLevelDB::insert_indexed_leaves_nullifier_tree (
148- const NullifierLeafValue& leaf_value)
149- {
150- // Add to map
151- nullifier_leaves[next_available_nullifier_index] = leaf_value;
152- // Add to sorted vector
153- nullifier_values.push_back ({ leaf_value.nullifier , next_available_nullifier_index });
154- // Sort vector
155- std::ranges::sort (
156- nullifier_values.begin (),
157- nullifier_values.end (),
158- [](const std::pair<FF, index_t >& a, const std::pair<FF, index_t >& b) { return a.first < b.first ; });
159-
160- // Increment next available index
161- next_available_nullifier_index++;
162- // Don't return any witness data for now, as it's not used for pure calls.
163- return {};
164- }
165-
166- void FuzzerLowLevelDB::append_leaves ([[maybe_unused]] MerkleTreeId tree_id, std::span<const FF> leaves)
167- {
168- note_hash_leaves.insert (note_hash_leaves.end (), leaves.begin (), leaves.end ());
169- next_available_note_hash_index += leaves.size ();
170- }
171- void FuzzerLowLevelDB::pad_tree ([[maybe_unused]] MerkleTreeId tree_id, [[maybe_unused]] size_t num_leaves) {}
172-
173- void FuzzerLowLevelDB::create_checkpoint () {}
174- void FuzzerLowLevelDB::commit_checkpoint () {}
175- void FuzzerLowLevelDB::revert_checkpoint () {}
176- uint32_t FuzzerLowLevelDB::get_checkpoint_id () const
177- {
178- return 0 ;
179- }
180-
181- // Helper to insert a contract address into the nullifier tree
182- void FuzzerLowLevelDB::insert_contract_address (const AztecAddress& contract_address)
183- {
184- auto contract_nullifier =
185- simulation::unconstrained_silo_nullifier (CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, contract_address);
186- insert_indexed_leaves_nullifier_tree (contract_nullifier);
187- }
188-
18921// //////////////////////////////
19022// / ContractDBInterface methods
19123// //////////////////////////////
@@ -207,13 +39,12 @@ std::optional<ContractClass> FuzzerContractDB::get_contract_class(const Contract
20739
20840std::optional<FF> FuzzerContractDB::get_bytecode_commitment (const ContractClassId& class_id) const
20941{
210- // Return 0 might be an issue, in the pure bytecode manager we cache based on this value
211- // This might cause different classes to be treated as the same if they return 0 here.
212- // For now we just return the class_id as it should be as unique as the bytecode commitment
21342 if (!contract_classes.contains (class_id)) {
21443 return std::nullopt ;
21544 }
216- return class_id;
45+ // Compute the actual bytecode commitment from the stored bytecode
46+ const auto & klass = contract_classes.at (class_id);
47+ return compute_public_bytecode_commitment (klass.packed_bytecode );
21748}
21849std::optional<std::string> FuzzerContractDB::get_debug_function_name (
21950 [[maybe_unused]] const AztecAddress& address, [[maybe_unused]] const FunctionSelector& selector) const
@@ -239,12 +70,21 @@ void FuzzerContractDB::add_contracts(const ContractDeploymentData& contract_depl
23970
24071void FuzzerContractDB::add_contract_class (const ContractClassId& class_id, const ContractClass& contract_class)
24172{
242- contract_classes[class_id] = contract_class;
73+ // todo(ilyas): think of a nicer way without both map and vector
74+ // Only push to vector if not already present, otherwise we get duplicates sent to the TS simulator
75+ if (contract_classes.contains (class_id)) {
76+ return ;
77+ }
24378 contract_classes_vector.push_back (contract_class);
79+ contract_classes[class_id] = contract_class;
24480}
24581
24682void FuzzerContractDB::add_contract_instance (const AztecAddress& address, const ContractInstance& contract_instance)
24783{
84+ // todo(ilyas): think of a nicer way without both map and vector
85+ if (contract_instances.contains (address)) {
86+ return ;
87+ }
24888 contract_instances[address] = contract_instance;
24989 contract_instances_vector.push_back ({ address, contract_instance });
25090}
@@ -379,6 +219,7 @@ void FuzzerWorldStateManager::register_contract_address(const AztecAddress& cont
379219{
380220 NullifierLeafValue contract_nullifier =
381221 unconstrained_silo_nullifier (CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, contract_address);
222+ fuzz_info (" Registering contract address in world state: " , contract_nullifier.nullifier );
382223 auto fork_id = fork_ids.top ();
383224 ws->insert_indexed_leaves <NullifierLeafValue>(MerkleTreeId::NULLIFIER_TREE, { contract_nullifier }, fork_id);
384225}
0 commit comments