Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
merkle_check_trace.cpp
Go to the documentation of this file.
2
3#include <cstddef>
4#include <cstdint>
5#include <optional>
6
12
13namespace bb::avm2::tracegen {
14
15using Poseidon2 = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>;
16
33{
34 using C = Column;
35
36 // Skip 0th row since this gadget has shifts
37 uint32_t row = 1;
38
39 for (const auto& event : events) {
40 const size_t full_path_len = event.sibling_path.size();
41
42 // Iterate over the path starting at the leaf.
43 // Root is not included in the path.
44 // For the current level, gather info about the current pair of nodes
45 // being hashed along with the path-length remaining after this level
46 // to complete the merkle check.
47
48 const bool write = event.new_leaf_value.has_value();
49 BB_ASSERT_EQ(write, event.new_root.has_value(), "Write and new root have different values");
50
51 FF read_node = event.leaf_value;
52 FF write_node = event.new_leaf_value.value_or(FF(0));
53 uint64_t current_index_in_layer = event.leaf_index;
54
55 const FF& root = event.root;
56 const FF new_root = event.new_root.value_or(FF(0));
57 const uint64_t sep = event.merkle_hash_domain_separator;
58
59 for (size_t i = 0; i < full_path_len; ++i) {
60 const FF& sibling = event.sibling_path[i];
61
62 // path-length decrements by 1 for each level until it reaches 1
63 const size_t path_len = full_path_len - i;
64
65 // end == 1 at last iteration, i.e., i == full_path_len - 1 equivalently to path_len == 1
66 const bool end = path_len == 1;
67 const bool start = i == 0; // First row in the chain is a start row
68 const bool index_is_even = current_index_in_layer % 2 == 0;
69 const FF read_left_node = index_is_even ? read_node : sibling;
70 const FF read_right_node = index_is_even ? sibling : read_node;
71 const FF read_output_hash = Poseidon2::hash({ FF(sep), read_left_node, read_right_node });
72
73 // Read and Write
74 trace.set(row,
75 { { { C::merkle_check_sel, 1 },
76 { C::merkle_check_const_three, 3 },
77 { C::merkle_check_merkle_hash_separator, sep },
78 { C::merkle_check_read_node, read_node },
79 { C::merkle_check_index, current_index_in_layer },
80 { C::merkle_check_path_len, path_len },
81 // Guarantees that path_len - 1 never underflows as path_len is always >= 1
82 { C::merkle_check_path_len_min_one_inv, path_len - 1 }, // Will be inverted in batch later
83 { C::merkle_check_read_root, root },
84 { C::merkle_check_sibling, sibling },
85 { C::merkle_check_start, start ? 1 : 0 },
86 { C::merkle_check_end, end ? 1 : 0 },
87 { C::merkle_check_index_is_even, index_is_even ? 1 : 0 },
88 { C::merkle_check_read_left_node, read_left_node },
89 { C::merkle_check_read_right_node, read_right_node },
90 { C::merkle_check_read_output_hash, read_output_hash } } });
91
92 // Update the current/target node value for the next iteration
93 read_node = read_output_hash;
94 current_index_in_layer >>= 1;
95
96 // Write only.
97 if (write) {
98 // Only active when write is on.
99 const FF write_left_node = index_is_even ? write_node : sibling;
100 const FF write_right_node = index_is_even ? sibling : write_node;
101 const FF write_output_hash = Poseidon2::hash({ FF(sep), write_left_node, write_right_node });
102
103 trace.set(row,
104 { { { C::merkle_check_write, 1 },
105 { C::merkle_check_write_root, new_root },
106 { C::merkle_check_write_node, write_node },
107 { C::merkle_check_write_left_node, write_left_node },
108 { C::merkle_check_write_right_node, write_right_node },
109 { C::merkle_check_write_output_hash, write_output_hash } } });
110
111 // Update the current/target node value for the next iteration
112 write_node = write_output_hash;
113 }
114
115 row++;
116 }
117
118 BB_ASSERT_EQ(current_index_in_layer,
119 static_cast<decltype(current_index_in_layer)>(0),
120 "Current index in layer is not 0");
121 BB_ASSERT_EQ(read_node, root, "Read node is not equal to root");
122 BB_ASSERT_EQ(write_node, new_root, "Write node is not equal to new root");
123 }
124
125 // Batch invert the columns.
126 trace.invert_columns({ { C::merkle_check_path_len_min_one_inv } });
127}
128
132 .add<InteractionType::LookupSequential, lookup_merkle_check_merkle_poseidon2_write_settings>();
133
134} // namespace bb::avm2::tracegen
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
InteractionDefinition & add(auto &&... args)
void process(const simulation::EventEmitterInterface< simulation::MerkleCheckEvent >::Container &events, TraceContainer &trace)
Trace generation for the MerkleCheck gadget. It handles both READ and WRITE MerkleCheck events....
static const InteractionDefinition interactions
Native Poseidon2 hash function implementation.
Definition poseidon2.hpp:22
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
TestTraceContainer trace
AvmFlavorSettings::FF FF
Definition field.hpp:10
void write(B &buf, field2< base_field, Params > const &value)
simulation::PublicDataTreeReadWriteEvent event
Settings to be passed ot GenericLookupRelationImpl.