zk/include/nil/crypto3/zk/snark/merkle_tree.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 
26 #ifndef CRYPTO3_ZK_SNARK_MERKLE_TREE_HPP
27 #define CRYPTO3_ZK_SNARK_MERKLE_TREE_HPP
28 
29 #include <map>
30 #include <vector>
31 #include <cmath>
32 
33 namespace nil {
34  namespace crypto3 {
35  namespace zk {
36  namespace snark {
37  template<typename Hash>
38  typename Hash::digest_type two_to_one_CRH(const typename Hash::digest_type &l,
39  const typename Hash::digest_type &r) {
40  typename Hash::digest_type new_input;
41  new_input.insert(new_input.end(), l.begin(), l.end());
42  new_input.insert(new_input.end(), r.begin(), r.end());
43 
44  const std::size_t digest_size = Hash::get_digest_len();
45  assert(l.size() == digest_size);
46  assert(r.size() == digest_size);
47 
48  return Hash::get_hash(new_input);
49  }
50 
64  typedef std::vector<bool> merkle_authentication_node;
65  typedef std::vector<merkle_authentication_node> merkle_authentication_path;
66 
67  template<typename Hash, std::size_t BaseArity = 0, std::size_t SubTreeArity = 0,
68  std::size_t TopTreeArity = 0>
69  struct merkle_tree {
70  typedef typename Hash::digest_type digest_type;
71  typedef typename Hash::merkle_authentication_path_type merkle_authentication_path_type;
72 
73  constexpr static const std::size_t base_arity = BaseArity;
74  constexpr static const std::size_t sub_tree_arity = SubTreeArity;
75  constexpr static const std::size_t top_tree_arity = TopTreeArity;
76 
77  std::vector<digest_type> hash_defaults;
78  std::map<std::size_t, std::vector<bool>> values;
79  std::map<std::size_t, digest_type> hashes;
80 
81  std::size_t depth;
82  std::size_t value_size;
83  std::size_t digest_size;
84 
85  merkle_tree(const std::size_t depth, const std::size_t value_size) :
87  assert(depth < sizeof(std::size_t) * 8);
88 
89  digest_size = Hash::digest_bits;
90  assert(value_size <= digest_size);
91 
92  digest_type last;
93  hash_defaults.reserve(depth + 1);
94  hash_defaults.emplace_back(last);
95  for (std::size_t i = 0; i < depth; ++i) {
96  last = two_to_one_CRH<Hash>(last, last);
97  hash_defaults.emplace_back(last);
98  }
99 
100  std::reverse(hash_defaults.begin(), hash_defaults.end());
101  }
102  merkle_tree(const std::size_t depth, const std::size_t value_size,
103  const std::vector<std::vector<bool>> &contents_as_vector) :
104  merkle_tree<Hash>(depth, value_size) {
105  assert(static_cast<std::size_t>(std::ceil(std::log2(contents_as_vector.size()))) <= depth);
106  for (std::size_t address = 0; address < contents_as_vector.size(); ++address) {
107  const std::size_t idx = address + (1ul << depth) - 1;
108  values[idx] = contents_as_vector[address];
109  hashes[idx] = contents_as_vector[address];
110  hashes[idx].resize(digest_size);
111  }
112 
113  std::size_t idx_begin = (1ul << depth) - 1;
114  std::size_t idx_end = contents_as_vector.size() + ((1ul << depth) - 1);
115 
116  for (int layer = depth; layer > 0; --layer) {
117  for (std::size_t idx = idx_begin; idx < idx_end; idx += 2) {
118  digest_type l =
119  hashes[idx]; // this is sound, because idx_begin is always a left child
120  digest_type r = (idx + 1 < idx_end ? hashes[idx + 1] : hash_defaults[layer]);
121 
122  digest_type h = two_to_one_CRH<Hash>(l, r);
123  hashes[(idx - 1) / 2] = h;
124  }
125 
126  idx_begin = (idx_begin - 1) / 2;
127  idx_end = (idx_end - 1) / 2;
128  }
129  }
130 
131  merkle_tree(size_t depth, std::size_t value_size,
132  const std::map<std::size_t, std::vector<bool>> &contents) :
133  merkle_tree<Hash>(depth, value_size) {
134 
135  if (!contents.empty()) {
136  assert(contents.rbegin()->first < 1ul << depth);
137 
138  for (const auto &content : contents) {
139  const std::size_t address = content.first;
140  const std::vector<bool> value = content.second;
141  const std::size_t idx = address + (1ul << depth) - 1;
142 
143  values[address] = value;
144  hashes[idx] = value;
145  hashes[idx].resize(digest_size);
146  }
147 
148  auto last_it = hashes.end();
149 
150  for (int layer = depth; layer > 0; --layer) {
151  auto next_last_it = hashes.begin();
152 
153  for (auto it = hashes.begin(); it != last_it; ++it) {
154  const std::size_t idx = it->first;
155  const digest_type hash = it->second;
156 
157  if (idx % 2 == 0) {
158  // this is the right child of its parent and by invariant we are missing the
159  // left child
160  hashes[(idx - 1) / 2] = two_to_one_CRH<Hash>(hash_defaults[layer], hash);
161  } else {
162  if (std::next(it) == last_it || std::next(it)->first != idx + 1) {
163  // this is the left child of its parent and is missing its right child
164  hashes[(idx - 1) / 2] = two_to_one_CRH<Hash>(hash, hash_defaults[layer]);
165  } else {
166  // typical case: this is the left child of the parent and adjacent to it
167  // there is a right child
168  hashes[(idx - 1) / 2] = two_to_one_CRH<Hash>(hash, std::next(it)->second);
169  ++it;
170  }
171  }
172  }
173 
174  last_it = next_last_it;
175  }
176  }
177  }
178 
179  std::vector<bool> get_value(const std::size_t address) const {
180  assert(static_cast<std::size_t>(std::ceil(std::log2(address))) <= depth);
181 
182  auto it = values.find(address);
183  std::vector<bool> padded_result =
184  (it == values.end() ? std::vector<bool>(digest_size) : it->second);
185  padded_result.resize(value_size);
186 
187  return padded_result;
188  }
189  void set_value(const std::size_t address, const std::vector<bool> &value) {
190  assert(static_cast<std::size_t>(std::ceil(std::log2(address))) <= depth);
191  std::size_t idx = address + (1ul << depth) - 1;
192 
193  assert(value.size() == value_size);
194  values[address] = value;
195  hashes[idx] = value;
196  hashes[idx].resize(digest_size);
197 
198  for (int layer = depth - 1; layer >= 0; --layer) {
199  idx = (idx - 1) / 2;
200 
201  auto it = hashes.find(2 * idx + 1);
202  digest_type l = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
203 
204  it = hashes.find(2 * idx + 2);
205  digest_type r = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
206 
207  digest_type h = two_to_one_CRH<Hash>(l, r);
208  hashes[idx] = h;
209  }
210  }
211 
213  auto it = hashes.find(0);
214  return (it == hashes.end() ? hash_defaults[0] : it->second);
215  }
216  merkle_authentication_path_type get_path(const std::size_t address) const {
217  typename Hash::merkle_authentication_path_type result(depth);
218  assert(static_cast<std::size_t>(std::ceil(std::log2(address))) <= depth);
219  std::size_t idx = address + (1ul << depth) - 1;
220 
221  for (std::size_t layer = depth; layer > 0; --layer) {
222  std::size_t sibling_idx = ((idx + 1) ^ 1) - 1;
223  auto it = hashes.find(sibling_idx);
224  if (layer == depth) {
225  auto it2 = values.find(sibling_idx - ((1ul << depth) - 1));
226  result[layer - 1] =
227  (it2 == values.end() ? std::vector<bool>(value_size, false) : it2->second);
228  result[layer - 1].resize(digest_size);
229  } else {
230  result[layer - 1] = (it == hashes.end() ? hash_defaults[layer] : it->second);
231  }
232 
233  idx = (idx - 1) / 2;
234  }
235 
236  return result;
237  }
238 
239  void dump() const {
240  for (std::size_t i = 0; i < 1ul << depth; ++i) {
241  auto it = values.find(i);
242  printf("[%zu] -> ", i);
243  const std::vector<bool> value =
244  (it == values.end() ? std::vector<bool>(value_size) : it->second);
245  for (bool b : value) {
246  printf("%d", b ? 1 : 0);
247  }
248  printf("\n");
249  }
250  printf("\n");
251  }
252  };
253  } // namespace snark
254  } // namespace zk
255  } // namespace crypto3
256 } // namespace nil
257 
258 #endif // CRYPTO3_ZK_SNARK_MERKLE_TREE_HPP
std::enable_if<!boost::accumulators::detail::is_accumulator_set< OutputIterator >::value, OutputIterator >::type hash(InputIterator first, InputIterator last, OutputIterator out)
Definition: algorithm/hash.hpp:78
vector(T, U...) -> vector< std::enable_if_t<(std::is_same_v< T, U > &&...), T >, 1+sizeof...(U)>
deduction guide for uniform initialization
void reverse(Range &a, std::size_t n)
Definition: basic_operations.hpp:54
std::vector< merkle_authentication_node > merkle_authentication_path
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:66
std::vector< bool > merkle_authentication_node
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:65
Hash::hash_value_type two_to_one_CRH(const typename Hash::hash_value_type &l, const typename Hash::hash_value_type &r)
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:39
Definition: pair.hpp:31
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:70
constexpr static const std::size_t base_arity
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:74
Hash::hash_value_type digest_type
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:71
merkle_authentication_path_type get_path(const std::size_t address) const
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:216
constexpr static const std::size_t sub_tree_arity
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:75
std::size_t depth
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:82
constexpr static const std::size_t top_tree_arity
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:76
merkle_tree(const std::size_t depth, const std::size_t value_size)
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:85
digest_type get_root() const
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:212
void dump() const
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:239
Hash::merkle_authentication_path_type merkle_authentication_path_type
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:71
std::map< std::size_t, std::vector< bool > > values
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:79
void set_value(const std::size_t address, const std::vector< bool > &value)
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:189
merkle_tree(size_t depth, std::size_t value_size, const std::map< std::size_t, std::vector< bool >> &contents)
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:131
merkle_tree(const std::size_t depth, const std::size_t value_size, const std::vector< std::vector< bool >> &contents_as_vector)
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:102
Hash::digest_type digest_type
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:70
std::size_t value_size
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:83
std::vector< bool > get_value(const std::size_t address) const
Definition: zk/include/nil/crypto3/zk/snark/merkle_tree.hpp:179
std::size_t digest_size
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:84
std::vector< digest_type > hash_defaults
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:78
std::map< std::size_t, digest_type > hashes
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:80