blueprint/include/nil/crypto3/zk/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 
32 #include <cmath>
33 
34 namespace nil {
35  namespace crypto3 {
36  namespace zk {
37  namespace snark {
38  template<typename Hash>
39  typename Hash::hash_value_type two_to_one_CRH(const typename Hash::hash_value_type &l,
40  const typename Hash::hash_value_type &r) {
41  typename Hash::hash_value_type new_input;
42  new_input.insert(new_input.end(), l.begin(), l.end());
43  new_input.insert(new_input.end(), r.begin(), r.end());
44 
45  const std::size_t digest_size = Hash::get_digest_len();
46  assert(l.size() == digest_size);
47  assert(r.size() == digest_size);
48 
49  return Hash::get_hash(new_input);
50  }
51 
65  typedef std::vector<bool> merkle_authentication_node;
66  typedef std::vector<merkle_authentication_node> merkle_authentication_path;
67 
68  template<typename Hash, std::size_t BaseArity = 0, std::size_t SubTreeArity = 0,
69  std::size_t TopTreeArity = 0>
70  struct merkle_tree {
71  typedef typename Hash::hash_value_type digest_type;
72  typedef typename Hash::merkle_authentication_path_type merkle_authentication_path_type;
73 
74  constexpr static const std::size_t base_arity = BaseArity;
75  constexpr static const std::size_t sub_tree_arity = SubTreeArity;
76  constexpr static const std::size_t top_tree_arity = TopTreeArity;
77 
78  std::vector<digest_type> hash_defaults;
79  std::map<std::size_t, std::vector<bool>> values;
80  std::map<std::size_t, digest_type> hashes;
81 
82  std::size_t depth;
83  std::size_t value_size;
84  std::size_t digest_size;
85 
86  merkle_tree(const std::size_t depth, const std::size_t value_size) :
88  assert(depth < sizeof(std::size_t) * 8);
89 
90  digest_size = Hash::get_digest_len();
91  assert(value_size <= digest_size);
92 
93  digest_type last;
94  hash_defaults.reserve(depth + 1);
95  hash_defaults.emplace_back(last);
96  for (std::size_t i = 0; i < depth; ++i) {
97  last = two_to_one_CRH<Hash>(last, last);
98  hash_defaults.emplace_back(last);
99  }
100 
101  std::reverse(hash_defaults.begin(), hash_defaults.end());
102  }
103  merkle_tree(const std::size_t depth, const std::size_t value_size,
104  const std::vector<std::vector<bool>> &contents_as_vector) :
105  merkle_tree<Hash>(depth, value_size) {
106  assert(static_cast<std::size_t>(std::ceil(std::log2(contents_as_vector.size()))) <= depth);
107  for (std::size_t address = 0; address < contents_as_vector.size(); ++address) {
108  const std::size_t idx = address + (1ul << depth) - 1;
109  values[idx] = contents_as_vector[address];
110  hashes[idx] = contents_as_vector[address];
111  hashes[idx].resize(digest_size);
112  }
113 
114  std::size_t idx_begin = (1ul << depth) - 1;
115  std::size_t idx_end = contents_as_vector.size() + ((1ul << depth) - 1);
116 
117  for (int layer = depth; layer > 0; --layer) {
118  for (std::size_t idx = idx_begin; idx < idx_end; idx += 2) {
119  digest_type l =
120  hashes[idx]; // this is sound, because idx_begin is always a left child
121  digest_type r = (idx + 1 < idx_end ? hashes[idx + 1] : hash_defaults[layer]);
122 
123  digest_type h = two_to_one_CRH<Hash>(l, r);
124  hashes[(idx - 1) / 2] = h;
125  }
126 
127  idx_begin = (idx_begin - 1) / 2;
128  idx_end = (idx_end - 1) / 2;
129  }
130  }
131 
132  merkle_tree(size_t depth, std::size_t value_size,
133  const std::map<std::size_t, std::vector<bool>> &contents) :
134  merkle_tree<Hash>(depth, value_size) {
135 
136  if (!contents.empty()) {
137  assert(contents.rbegin()->first < 1ul << depth);
138 
139  for (const auto &content : contents) {
140  const std::size_t address = content.first;
141  const std::vector<bool> value = content.second;
142  const std::size_t idx = address + (1ul << depth) - 1;
143 
144  values[address] = value;
145  hashes[idx] = value;
146  hashes[idx].resize(digest_size);
147  }
148 
149  auto last_it = hashes.end();
150 
151  for (int layer = depth; layer > 0; --layer) {
152  auto next_last_it = hashes.begin();
153 
154  for (auto it = hashes.begin(); it != last_it; ++it) {
155  const std::size_t idx = it->first;
156  const digest_type hash = it->second;
157 
158  if (idx % 2 == 0) {
159  // this is the right child of its parent and by invariant we are missing the
160  // left child
161  hashes[(idx - 1) / 2] = two_to_one_CRH<Hash>(hash_defaults[layer], hash);
162  } else {
163  if (std::next(it) == last_it || std::next(it)->first != idx + 1) {
164  // this is the left child of its parent and is missing its right child
165  hashes[(idx - 1) / 2] = two_to_one_CRH<Hash>(hash, hash_defaults[layer]);
166  } else {
167  // typical case: this is the left child of the parent and adjacent to it
168  // there is a right child
169  hashes[(idx - 1) / 2] = two_to_one_CRH<Hash>(hash, std::next(it)->second);
170  ++it;
171  }
172  }
173  }
174 
175  last_it = next_last_it;
176  }
177  }
178  }
179 
180  std::vector<bool> get_value(const std::size_t address) const {
181  assert(static_cast<std::size_t>(std::ceil(std::log2(address))) <= depth);
182 
183  auto it = values.find(address);
184  std::vector<bool> padded_result =
185  (it == values.end() ? std::vector<bool>(digest_size) : it->second);
186  padded_result.resize(value_size);
187 
188  return padded_result;
189  }
190  void set_value(const std::size_t address, const std::vector<bool> &value) {
191  assert(static_cast<std::size_t>(std::ceil(std::log2(address))) <= depth);
192  std::size_t idx = address + (1ul << depth) - 1;
193 
194  assert(value.size() == value_size);
195  values[address] = value;
196  hashes[idx] = value;
197  hashes[idx].resize(digest_size);
198 
199  for (int layer = depth - 1; layer >= 0; --layer) {
200  idx = (idx - 1) / 2;
201 
202  auto it = hashes.find(2 * idx + 1);
203  digest_type l = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
204 
205  it = hashes.find(2 * idx + 2);
206  digest_type r = (it == hashes.end() ? hash_defaults[layer + 1] : it->second);
207 
208  digest_type h = two_to_one_CRH<Hash>(l, r);
209  hashes[idx] = h;
210  }
211  }
212 
214  auto it = hashes.find(0);
215  return (it == hashes.end() ? hash_defaults[0] : it->second);
216  }
217  merkle_authentication_path_type get_path(const std::size_t address) const {
218  typename Hash::merkle_authentication_path_type result(depth);
219  assert(static_cast<std::size_t>(std::ceil(std::log2(address))) <= depth);
220  std::size_t idx = address + (1ul << depth) - 1;
221 
222  for (std::size_t layer = depth; layer > 0; --layer) {
223  std::size_t sibling_idx = ((idx + 1) ^ 1) - 1;
224  auto it = hashes.find(sibling_idx);
225  if (layer == depth) {
226  auto it2 = values.find(sibling_idx - ((1ul << depth) - 1));
227  result[layer - 1] =
228  (it2 == values.end() ? std::vector<bool>(value_size, false) : it2->second);
229  result[layer - 1].resize(digest_size);
230  } else {
231  result[layer - 1] = (it == hashes.end() ? hash_defaults[layer] : it->second);
232  }
233 
234  idx = (idx - 1) / 2;
235  }
236 
237  return result;
238  }
239  };
240  } // namespace snark
241  } // namespace zk
242  } // namespace crypto3
243 } // namespace nil
244 
245 #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: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:217
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: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:86
digest_type get_root() const
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:213
Hash::merkle_authentication_path_type merkle_authentication_path_type
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:72
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: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:190
merkle_tree(size_t depth, std::size_t value_size, const std::map< std::size_t, std::vector< bool >> &contents)
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:132
merkle_tree(const std::size_t depth, const std::size_t value_size, const std::vector< std::vector< bool >> &contents_as_vector)
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:103
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: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:180
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