Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
nullifier_memory_tree.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8#include "../hash.hpp"
9#include "../memory_tree.hpp"
12#include "nullifier_leaf.hpp"
13
15
74template <typename HashingPolicy> class NullifierMemoryTree : public MemoryTree<HashingPolicy> {
75
76 public:
77 NullifierMemoryTree(size_t depth, size_t initial_size = 2);
78
79 using MemoryTree<HashingPolicy>::get_hash_path;
80 using MemoryTree<HashingPolicy>::get_sibling_path;
81 using MemoryTree<HashingPolicy>::root;
82 using MemoryTree<HashingPolicy>::update_element;
83
85
88 {
89 return (index < leaves_.size()) ? leaves_[index]
91 }
93
94 protected:
95 using MemoryTree<HashingPolicy>::depth_;
96 using MemoryTree<HashingPolicy>::hashes_;
97 using MemoryTree<HashingPolicy>::root_;
98 using MemoryTree<HashingPolicy>::total_size_;
100};
101
102template <typename HashingPolicy>
104 : MemoryTree<HashingPolicy>(depth)
105{
107 BB_ASSERT_LTE(depth, 32U);
108 BB_ASSERT_GT(initial_size, 0U);
109 total_size_ = 1UL << depth_;
110 hashes_.resize(total_size_ * 2 - 2);
111
112 // Build the entire tree and fill with 0 hashes.
113 // auto current = WrappedNullifierLeaf<HashingPolicy>(nullifier_leaf::zero()).hash();
114 auto current = fr::zero();
115 size_t layer_size = total_size_;
116 for (size_t offset = 0; offset < hashes_.size(); offset += layer_size, layer_size /= 2) {
117 for (size_t i = 0; i < layer_size; ++i) {
118 hashes_[offset + i] = current;
119 }
120 current = HashingPolicy::hash_pair(current, current);
121 }
122
123 // Insert the initial leaves
124 for (size_t i = 0; i < initial_size; i++) {
125 auto initial_leaf = WrappedNullifierLeaf<HashingPolicy>(
126 indexed_nullifier_leaf{ .value = i, .nextIndex = i + 1, .nextValue = i + 1 });
127 leaves_.push_back(initial_leaf);
128 }
129
131 indexed_nullifier_leaf{ .value = leaves_[initial_size - 1].unwrap().value, .nextIndex = 0, .nextValue = 0 });
132
133 for (size_t i = 0; i < initial_size; ++i) {
134 update_element(i, leaves_[i].hash());
135 }
136}
137
139{
140 // Find the leaf with the value closest and less than `value`
141
142 // If value is 0 we simply append 0 a null NullifierLeaf to the tree
144 if (value == 0) {
146 hash_path = get_sibling_path(leaves_.size() - 1);
147 leaves_.push_back(zero_leaf);
148 update_element(leaves_.size() - 1, zero_leaf.hash());
149 return hash_path;
150 }
151
152 size_t current;
153 bool is_already_present;
154 std::tie(current, is_already_present) = find_closest_leaf(leaves_, value);
155
156 indexed_nullifier_leaf current_leaf = leaves_[current].unwrap();
157 indexed_nullifier_leaf new_leaf = { .value = value,
158 .nextIndex = current_leaf.nextIndex,
159 .nextValue = current_leaf.nextValue };
160
161 if (!is_already_present) {
162 // Update the current leaf to point it to the new leaf
163 current_leaf.nextIndex = leaves_.size();
164 current_leaf.nextValue = value;
165
166 leaves_[current].set(current_leaf);
167
168 // Insert the new leaf with (nextIndex, nextValue) of the current leaf
169 leaves_.push_back(new_leaf);
170 }
171
172 hash_path = get_sibling_path(current);
173 // Update the old leaf in the tree
174 auto old_leaf_hash = HashingPolicy::hash(current_leaf.get_hash_inputs());
175 size_t old_leaf_index = current;
176 auto root = update_element(old_leaf_index, old_leaf_hash);
177
178 // Insert the new leaf in the tree
179 auto new_leaf_hash = HashingPolicy::hash(new_leaf.get_hash_inputs());
180 size_t new_leaf_index = is_already_present ? old_leaf_index : leaves_.size() - 1;
181 root = update_element(new_leaf_index, new_leaf_hash);
182
183 return hash_path;
184}
185
186} // namespace bb::crypto::merkle_tree
#define BB_ASSERT_GTE(left, right,...)
Definition assert.hpp:101
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:87
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:129
fr_hash_path get_hash_path(size_t index) const
fr_sibling_path get_sibling_path(size_t index) const
std::vector< WrappedNullifierLeaf< HashingPolicy > > leaves_
const WrappedNullifierLeaf< HashingPolicy > get_leaf(size_t index)
const std::vector< WrappedNullifierLeaf< HashingPolicy > > & get_leaves()
NullifierMemoryTree(size_t depth, size_t initial_size=2)
Wrapper for the Nullifier leaf class that allows for 0 values.
static WrappedNullifierLeaf< HashingPolicy > zero()
Generate a zero leaf (call the constructor with no arguments)
ssize_t offset
Definition engine.cpp:36
void hash(State &state) noexcept
std::pair< size_t, bool > find_closest_leaf(std::vector< WrappedNullifierLeaf< HashingPolicy > > const &leaves_, fr const &new_value)
std::vector< std::pair< bb::stdlib::field_t< Ctx >, bb::stdlib::field_t< Ctx > > > hash_path
Definition hash_path.hpp:17
std::vector< fr > fr_sibling_path
Definition hash_path.hpp:16
fr_sibling_path get_sibling_path(TypeOfTree &tree, index_t index, bool includeUncommitted=true, bool expected_success=true)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field zero()