2 // Content taken and adapted from:
3 // https://github.com/scipr-lab/libsnark/blob/master/libsnark/common/data_structures/merkle_tree.tcc
5 #ifndef __ZETH_CORE_MERKLE_TREE_FIELD_TCC__
6 #define __ZETH_CORE_MERKLE_TREE_FIELD_TCC__
8 #include "libzeth/core/merkle_tree_field.hpp"
11 #include <libff/common/profiling.hpp>
12 #include <libff/common/utils.hpp>
17 template<typename FieldT, typename HashTreeT>
18 merkle_tree_field<FieldT, HashTreeT>::merkle_tree_field(const size_t depth)
21 assert(depth < sizeof(size_t) * 8);
23 // Value of the leaves when initializing the merkle tree
24 FieldT last = FieldT::zero();
26 // Length of a merkle path = depth + 1
27 // `hash_defaults` contains the default value of a merkle path
28 // ie: The recursive hash of the zero valued leaves
29 hash_defaults.reserve(depth + 1);
30 hash_defaults.emplace_back(last);
31 for (size_t i = 0; i < depth; ++i) {
32 last = HashTreeT::get_hash(last, last);
33 hash_defaults.push_back(last);
36 std::reverse(hash_defaults.begin(), hash_defaults.end());
39 template<typename FieldT, typename HashTreeT>
40 merkle_tree_field<FieldT, HashTreeT>::merkle_tree_field(
41 const size_t depth, const std::vector<FieldT> &contents_as_vector)
42 : merkle_tree_field<FieldT, HashTreeT>(depth)
44 assert(libff::log2(contents_as_vector.size()) <= depth);
45 for (size_t address = 0; address < contents_as_vector.size(); ++address) {
46 // `1ul << depth` returns the total number of leaves in the merkle tree
48 const size_t idx = address + (1ul << depth) - 1;
49 values[idx] = contents_as_vector[address];
50 hashes[idx] = contents_as_vector[address];
53 size_t idx_begin = (1ul << depth) - 1;
54 size_t idx_end = contents_as_vector.size() + ((1ul << depth) - 1);
56 for (int layer = depth; layer > 0; --layer) {
57 for (size_t idx = idx_begin; idx < idx_end; idx += 2) {
58 FieldT l = hashes[idx]; // this is sound, because idx_begin is
59 // always a left child
61 (idx + 1 < idx_end ? hashes[idx + 1] : hash_defaults[layer]);
63 FieldT h = HashTreeT::get_hash(l, r);
64 hashes[(idx - 1) / 2] = h;
67 idx_begin = (idx_begin - 1) / 2;
68 idx_end = (idx_end - 1) / 2;
72 template<typename FieldT, typename HashTreeT>
73 merkle_tree_field<FieldT, HashTreeT>::merkle_tree_field(
74 const size_t depth, const std::map<size_t, FieldT> &contents)
75 : merkle_tree_field<FieldT, HashTreeT>(depth)
77 if (!contents.empty()) {
78 assert(contents.rbegin()->first < 1ul << depth);
80 for (auto it = contents.begin(); it != contents.end(); ++it) {
81 const size_t address = it->first;
82 const FieldT value = it->second;
83 const size_t idx = address + (1ul << depth) - 1;
85 values[address] = value;
89 auto last_it = hashes.end();
91 for (int layer = depth; layer > 0; --layer) {
92 auto next_last_it = hashes.begin();
94 for (auto it = hashes.begin(); it != last_it; ++it) {
95 const size_t idx = it->first;
96 const FieldT hash = it->second;
99 // this is the right child of its parent and by invariant we
100 // are missing the left child
101 hashes[(idx - 1) / 2] =
102 HashTreeT::get_hash(hash_defaults[layer], hash);
104 if (std::next(it) == last_it ||
105 std::next(it)->first != idx + 1) {
106 // this is the left child of its parent and is missing
108 hashes[(idx - 1) / 2] =
109 HashTreeT::get_hash(hash, hash_defaults[layer]);
111 // typical case: this is the left child of the parent
112 // and adjacent to it there is a right child
113 hashes[(idx - 1) / 2] =
114 HashTreeT::get_hash(hash, std::next(it)->second);
119 last_it = next_last_it;
124 template<typename FieldT, typename HashTreeT>
125 FieldT merkle_tree_field<FieldT, HashTreeT>::get_value(
126 const size_t address) const
128 assert(libff::log2(address) <= depth);
130 auto it = values.find(address);
131 FieldT result = (it == values.end() ? FieldT("0") : it->second);
136 template<typename FieldT, typename HashTreeT>
137 void merkle_tree_field<FieldT, HashTreeT>::set_value(
138 const size_t address, const FieldT &value)
140 assert(libff::log2(address) <= depth);
142 values[address] = value;
144 // After adding the value, we update the nodes on its merkle path
145 size_t idx = address + (1ul << depth) - 1;
147 value; // The last element on the merkle path is the leaf value itself
148 for (int layer = depth - 1; layer >= 0; --layer) {
151 auto it = hashes.find(2 * idx + 1);
152 FieldT l = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
154 it = hashes.find(2 * idx + 2);
155 FieldT r = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
157 FieldT h = HashTreeT::get_hash(l, r);
162 template<typename FieldT, typename HashTreeT>
163 FieldT merkle_tree_field<FieldT, HashTreeT>::get_root() const
165 auto it = hashes.find(0);
166 return (it == hashes.end() ? hash_defaults[0] : it->second);
169 template<typename FieldT, typename HashTreeT>
170 std::vector<FieldT> merkle_tree_field<FieldT, HashTreeT>::get_path(
171 const size_t address) const
174 // Create empty vector of size depth
175 std::vector<FieldT> result(depth);
177 // Check that the node given has address within tree range
178 assert(libff::log2(address) <= depth);
180 // Compute node address on tree
181 size_t idx = address + (1ul << depth) - 1;
184 for (size_t layer = depth; layer > 0; --layer) {
185 // Compute the sibling node address and retrieve it
186 size_t sibling_idx = ((idx + 1) ^ 1) - 1;
187 auto it = hashes.find(sibling_idx);
189 // If last layer, retrieve sibling node value from vector values, else
190 // from vector hashes
191 if (layer == depth) {
192 auto it2 = values.find(sibling_idx - ((1ul << depth) - 1));
194 (it2 == values.end() ? FieldT("0") : it2->second);
197 (it == hashes.end() ? hash_defaults[layer] : it->second);
203 std::reverse(result.begin(), result.end());
207 template<typename FieldT, typename HashTreeT>
208 void merkle_tree_field<FieldT, HashTreeT>::dump() const
210 // `1ul << depth` returns the total number of leaves in the merkle tree of
211 // depth `depth` Print the tree leaves (stored in the `values` map)
212 std::cout << "* Merkle Tree Leaves" << std::endl;
213 for (size_t i = 0; i < 1ul << depth; ++i) {
214 auto it = values.find(i);
215 const FieldT value = (it == values.end() ? FieldT("0") : it->second);
216 std::cout << "[" << i << "] -> " << value << std::endl;
219 // We also dump the updated merkle path (after the insertion of the leaves)
220 // and the value of the values in `hash_defaults` for a
221 // debugging/information purpose To remove if this is useless.
223 // Print the inner nodes of the tree
224 std::cout << "* Merkle Tree Inner Nodes (Debug)" << std::endl;
225 for (auto it = hashes.cbegin(); it != hashes.cend(); ++it) {
226 std::cout << "[" << it->first << "] -> " << it->second << std::endl;
228 std::cout << "* Merkle Tree `hash_defaults` (Debug)" << std::endl;
229 for (size_t i = 0; i < hash_defaults.size(); i++) {
230 std::cout << hash_defaults[i] << std::endl;
234 } // namespace libzeth
236 #endif // __ZETH_CORE_MERKLE_TREE_FIELD_TCC__