Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
merkle_tree_field.tcc
Go to the documentation of this file.
1 // DISCLAIMER:
2 // Content taken and adapted from:
3 // https://github.com/scipr-lab/libsnark/blob/master/libsnark/common/data_structures/merkle_tree.tcc
4 
5 #ifndef __ZETH_CORE_MERKLE_TREE_FIELD_TCC__
6 #define __ZETH_CORE_MERKLE_TREE_FIELD_TCC__
7 
8 #include "libzeth/core/merkle_tree_field.hpp"
9 
10 #include <algorithm>
11 #include <libff/common/profiling.hpp>
12 #include <libff/common/utils.hpp>
13 
14 namespace libzeth
15 {
16 
17 template<typename FieldT, typename HashTreeT>
18 merkle_tree_field<FieldT, HashTreeT>::merkle_tree_field(const size_t depth)
19  : depth(depth)
20 {
21  assert(depth < sizeof(size_t) * 8);
22 
23  // Value of the leaves when initializing the merkle tree
24  FieldT last = FieldT::zero();
25 
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);
34  }
35 
36  std::reverse(hash_defaults.begin(), hash_defaults.end());
37 }
38 
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)
43 {
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
47  // of depth `depth`
48  const size_t idx = address + (1ul << depth) - 1;
49  values[idx] = contents_as_vector[address];
50  hashes[idx] = contents_as_vector[address];
51  }
52 
53  size_t idx_begin = (1ul << depth) - 1;
54  size_t idx_end = contents_as_vector.size() + ((1ul << depth) - 1);
55 
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
60  FieldT r =
61  (idx + 1 < idx_end ? hashes[idx + 1] : hash_defaults[layer]);
62 
63  FieldT h = HashTreeT::get_hash(l, r);
64  hashes[(idx - 1) / 2] = h;
65  }
66 
67  idx_begin = (idx_begin - 1) / 2;
68  idx_end = (idx_end - 1) / 2;
69  }
70 }
71 
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)
76 {
77  if (!contents.empty()) {
78  assert(contents.rbegin()->first < 1ul << depth);
79 
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;
84 
85  values[address] = value;
86  hashes[idx] = value;
87  }
88 
89  auto last_it = hashes.end();
90 
91  for (int layer = depth; layer > 0; --layer) {
92  auto next_last_it = hashes.begin();
93 
94  for (auto it = hashes.begin(); it != last_it; ++it) {
95  const size_t idx = it->first;
96  const FieldT hash = it->second;
97 
98  if (idx % 2 == 0) {
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);
103  } else {
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
107  // its right child
108  hashes[(idx - 1) / 2] =
109  HashTreeT::get_hash(hash, hash_defaults[layer]);
110  } else {
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);
115  ++it;
116  }
117  }
118  }
119  last_it = next_last_it;
120  }
121  }
122 }
123 
124 template<typename FieldT, typename HashTreeT>
125 FieldT merkle_tree_field<FieldT, HashTreeT>::get_value(
126  const size_t address) const
127 {
128  assert(libff::log2(address) <= depth);
129 
130  auto it = values.find(address);
131  FieldT result = (it == values.end() ? FieldT("0") : it->second);
132 
133  return result;
134 }
135 
136 template<typename FieldT, typename HashTreeT>
137 void merkle_tree_field<FieldT, HashTreeT>::set_value(
138  const size_t address, const FieldT &value)
139 {
140  assert(libff::log2(address) <= depth);
141 
142  values[address] = value;
143 
144  // After adding the value, we update the nodes on its merkle path
145  size_t idx = address + (1ul << depth) - 1;
146  hashes[idx] =
147  value; // The last element on the merkle path is the leaf value itself
148  for (int layer = depth - 1; layer >= 0; --layer) {
149  idx = (idx - 1) / 2;
150 
151  auto it = hashes.find(2 * idx + 1);
152  FieldT l = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
153 
154  it = hashes.find(2 * idx + 2);
155  FieldT r = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
156 
157  FieldT h = HashTreeT::get_hash(l, r);
158  hashes[idx] = h;
159  }
160 }
161 
162 template<typename FieldT, typename HashTreeT>
163 FieldT merkle_tree_field<FieldT, HashTreeT>::get_root() const
164 {
165  auto it = hashes.find(0);
166  return (it == hashes.end() ? hash_defaults[0] : it->second);
167 }
168 
169 template<typename FieldT, typename HashTreeT>
170 std::vector<FieldT> merkle_tree_field<FieldT, HashTreeT>::get_path(
171  const size_t address) const
172 {
173 
174  // Create empty vector of size depth
175  std::vector<FieldT> result(depth);
176 
177  // Check that the node given has address within tree range
178  assert(libff::log2(address) <= depth);
179 
180  // Compute node address on tree
181  size_t idx = address + (1ul << depth) - 1;
182 
183  // For each layer
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);
188 
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));
193  result[layer - 1] =
194  (it2 == values.end() ? FieldT("0") : it2->second);
195  } else {
196  result[layer - 1] =
197  (it == hashes.end() ? hash_defaults[layer] : it->second);
198  }
199 
200  idx = (idx - 1) / 2;
201  }
202 
203  std::reverse(result.begin(), result.end());
204  return result;
205 }
206 
207 template<typename FieldT, typename HashTreeT>
208 void merkle_tree_field<FieldT, HashTreeT>::dump() const
209 {
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;
217  }
218 
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.
222  //
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;
227  }
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;
231  }
232 }
233 
234 } // namespace libzeth
235 
236 #endif // __ZETH_CORE_MERKLE_TREE_FIELD_TCC__