Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
merkle_tree.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for Merkle tree.
5 
6  See merkle_tree.hpp .
7 
8  *****************************************************************************
9  * @author This file is part of libsnark, developed by SCIPR Lab
10  * and contributors (see AUTHORS).
11  * @copyright MIT license (see LICENSE file)
12  *****************************************************************************/
13 
14 #ifndef MERKLE_TREE_TCC
15 #define MERKLE_TREE_TCC
16 
17 #include <algorithm>
18 #include <libff/common/profiling.hpp>
19 #include <libff/common/utils.hpp>
20 
21 namespace libsnark
22 {
23 
24 template<typename HashT>
25 typename HashT::hash_value_type two_to_one_CRH(
26  const typename HashT::hash_value_type &l,
27  const typename HashT::hash_value_type &r)
28 {
29  typename HashT::hash_value_type new_input;
30  new_input.insert(new_input.end(), l.begin(), l.end());
31  new_input.insert(new_input.end(), r.begin(), r.end());
32 
33 #ifndef NDEBUG
34  const size_t digest_size = HashT::get_digest_len();
35 #endif
36  assert(l.size() == digest_size);
37  assert(r.size() == digest_size);
38 
39  return HashT::get_hash(new_input);
40 }
41 
42 template<typename HashT>
43 merkle_tree<HashT>::merkle_tree(const size_t depth, const size_t value_size)
44  : depth(depth), value_size(value_size)
45 {
46  assert(depth < sizeof(size_t) * 8);
47 
48  digest_size = HashT::get_digest_len();
49  assert(value_size <= digest_size);
50 
51  hash_value_type last(digest_size);
52  hash_defaults.reserve(depth + 1);
53  hash_defaults.emplace_back(last);
54  for (size_t i = 0; i < depth; ++i) {
55  last = two_to_one_CRH<HashT>(last, last);
56  hash_defaults.emplace_back(last);
57  }
58 
59  std::reverse(hash_defaults.begin(), hash_defaults.end());
60 }
61 
62 template<typename HashT>
63 merkle_tree<HashT>::merkle_tree(
64  const size_t depth,
65  const size_t value_size,
66  const std::vector<libff::bit_vector> &contents_as_vector)
67  : merkle_tree<HashT>(depth, value_size)
68 {
69  assert(libff::log2(contents_as_vector.size()) <= depth);
70  for (size_t address = 0; address < contents_as_vector.size(); ++address) {
71  const size_t idx = address + (1ul << depth) - 1;
72  values[idx] = contents_as_vector[address];
73  hashes[idx] = contents_as_vector[address];
74  hashes[idx].resize(digest_size);
75  }
76 
77  size_t idx_begin = (1ul << depth) - 1;
78  size_t idx_end = contents_as_vector.size() + ((1ul << depth) - 1);
79 
80  for (int layer = depth; layer > 0; --layer) {
81  for (size_t idx = idx_begin; idx < idx_end; idx += 2) {
82  // this is sound, because idx_begin is always a left child
83  hash_value_type l = hashes[idx];
84  hash_value_type r =
85  (idx + 1 < idx_end ? hashes[idx + 1] : hash_defaults[layer]);
86 
87  hash_value_type h = two_to_one_CRH<HashT>(l, r);
88  hashes[(idx - 1) / 2] = h;
89  }
90 
91  idx_begin = (idx_begin - 1) / 2;
92  idx_end = (idx_end - 1) / 2;
93  }
94 }
95 
96 template<typename HashT>
97 merkle_tree<HashT>::merkle_tree(
98  const size_t depth,
99  const size_t value_size,
100  const std::map<size_t, libff::bit_vector> &contents)
101  : merkle_tree<HashT>(depth, value_size)
102 {
103 
104  if (!contents.empty()) {
105  assert(contents.rbegin()->first < 1ul << depth);
106 
107  for (auto it = contents.begin(); it != contents.end(); ++it) {
108  const size_t address = it->first;
109  const libff::bit_vector value = it->second;
110  const size_t idx = address + (1ul << depth) - 1;
111 
112  values[address] = value;
113  hashes[idx] = value;
114  hashes[idx].resize(digest_size);
115  }
116 
117  auto last_it = hashes.end();
118 
119  for (int layer = depth; layer > 0; --layer) {
120  auto next_last_it = hashes.begin();
121 
122  for (auto it = hashes.begin(); it != last_it; ++it) {
123  const size_t idx = it->first;
124  const hash_value_type hash = it->second;
125 
126  if (idx % 2 == 0) {
127  // this is the right child of its parent and by invariant we
128  // are missing the left child
129  hashes[(idx - 1) / 2] =
130  two_to_one_CRH<HashT>(hash_defaults[layer], hash);
131  } else {
132  if (std::next(it) == last_it ||
133  std::next(it)->first != idx + 1) {
134  // this is the left child of its parent and is missing
135  // its right child
136  hashes[(idx - 1) / 2] =
137  two_to_one_CRH<HashT>(hash, hash_defaults[layer]);
138  } else {
139  // typical case: this is the left child of the parent
140  // and adjacent to it there is a right child
141  hashes[(idx - 1) / 2] =
142  two_to_one_CRH<HashT>(hash, std::next(it)->second);
143  ++it;
144  }
145  }
146  }
147 
148  last_it = next_last_it;
149  }
150  }
151 }
152 
153 template<typename HashT>
154 libff::bit_vector merkle_tree<HashT>::get_value(const size_t address) const
155 {
156  assert(libff::log2(address) <= depth);
157 
158  auto it = values.find(address);
159  libff::bit_vector padded_result =
160  (it == values.end() ? libff::bit_vector(digest_size) : it->second);
161  padded_result.resize(value_size);
162 
163  return padded_result;
164 }
165 
166 template<typename HashT>
167 void merkle_tree<HashT>::set_value(
168  const size_t address, const libff::bit_vector &value)
169 {
170  assert(libff::log2(address) <= depth);
171  size_t idx = address + (1ul << depth) - 1;
172 
173  assert(value.size() == value_size);
174  values[address] = value;
175  hashes[idx] = value;
176  hashes[idx].resize(digest_size);
177 
178  for (int layer = depth - 1; layer >= 0; --layer) {
179  idx = (idx - 1) / 2;
180 
181  auto it = hashes.find(2 * idx + 1);
182  hash_value_type l =
183  (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
184 
185  it = hashes.find(2 * idx + 2);
186  hash_value_type r =
187  (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
188 
189  hash_value_type h = two_to_one_CRH<HashT>(l, r);
190  hashes[idx] = h;
191  }
192 }
193 
194 template<typename HashT>
195 typename HashT::hash_value_type merkle_tree<HashT>::get_root() const
196 {
197  auto it = hashes.find(0);
198  return (it == hashes.end() ? hash_defaults[0] : it->second);
199 }
200 
201 template<typename HashT>
202 typename HashT::merkle_authentication_path_type merkle_tree<HashT>::get_path(
203  const size_t address) const
204 {
205  typename HashT::merkle_authentication_path_type result(depth);
206  assert(libff::log2(address) <= depth);
207  size_t idx = address + (1ul << depth) - 1;
208 
209  for (size_t layer = depth; layer > 0; --layer) {
210  size_t sibling_idx = ((idx + 1) ^ 1) - 1;
211  auto it = hashes.find(sibling_idx);
212  if (layer == depth) {
213  auto it2 = values.find(sibling_idx - ((1ul << depth) - 1));
214  result[layer - 1] =
215  (it2 == values.end() ? libff::bit_vector(value_size, false)
216  : it2->second);
217  result[layer - 1].resize(digest_size);
218  } else {
219  result[layer - 1] =
220  (it == hashes.end() ? hash_defaults[layer] : it->second);
221  }
222 
223  idx = (idx - 1) / 2;
224  }
225 
226  return result;
227 }
228 
229 template<typename HashT> void merkle_tree<HashT>::dump() const
230 {
231  for (size_t i = 0; i < 1ul << depth; ++i) {
232  auto it = values.find(i);
233  printf("[%zu] -> ", i);
234  const libff::bit_vector value =
235  (it == values.end() ? libff::bit_vector(value_size) : it->second);
236  for (bool b : value) {
237  printf("%d", b ? 1 : 0);
238  }
239  printf("\n");
240  }
241  printf("\n");
242 }
243 
244 } // namespace libsnark
245 
246 #endif // MERKLE_TREE_TCC