PIVX Core  5.6.99
P2P Digital Currency
incrementalmerkletree.h
Go to the documentation of this file.
1 // Copyright (c) 2016-2018 The Zcash developers
2 // Copyright (c) 2020-2021 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef PIVX_SAPLING_INCREMENTALMERKLETREE_H
7 #define PIVX_SAPLING_INCREMENTALMERKLETREE_H
8 
9 #include "uint256.h"
10 #include "optional.h"
11 #include "serialize.h"
12 
13 #include "sapling/sapling.h"
14 #include "sapling/sapling_util.h"
15 
16 #include <array>
17 #include <deque>
18 
19 namespace libzcash {
20 
21 class MerklePath {
22 public:
23  std::vector<std::vector<bool>> authentication_path;
24  std::vector<bool> index;
25 
26  template<typename Stream>
27  void Serialize(Stream &s) const
28  {
29  std::vector<std::vector<unsigned char>> pathBytes;
30  uint64_t indexInt;
31  assert(authentication_path.size() == index.size());
32  pathBytes.resize(authentication_path.size());
33  for (size_t i = 0; i < authentication_path.size(); i++) {
34  pathBytes[i].resize((authentication_path[i].size()+7)/8);
35  for (unsigned int p = 0; p < authentication_path[i].size(); p++) {
36  pathBytes[i][p / 8] |= authentication_path[i][p] << (7-(p % 8));
37  }
38  }
39  indexInt = convertVectorToInt(index);
40  ::Serialize(s, pathBytes);
41  ::Serialize(s, indexInt);
42  }
43 
44  template<typename Stream>
45  void Unserialize(Stream &s)
46  {
47  std::vector<std::vector<unsigned char>> pathBytes;
48  uint64_t indexInt;
49  ::Unserialize(s, pathBytes);
50  ::Unserialize(s, indexInt);
51  MerklePath &us = *(const_cast<MerklePath*>(this));
52  for (size_t i = 0; i < pathBytes.size(); i++) {
53  us.authentication_path.push_back(convertBytesVectorToVector(pathBytes[i]));
54  us.index.push_back((indexInt >> ((pathBytes.size() - 1) - i)) & 1);
55  }
56  }
57 
58  MerklePath() { }
59 
60  MerklePath(std::vector<std::vector<bool>> authentication_path, std::vector<bool> index)
62 };
63 
64 template<size_t Depth, typename Hash>
66 public:
68  Hash empty_root(size_t depth) const {
69  return Hash::EmptyRoot(depth);
70  }
71  template <size_t D, typename H>
72  friend bool operator==(const EmptyMerkleRoots<D, H>& a,
73  const EmptyMerkleRoots<D, H>& b);
74 private:
75  std::array<Hash, Depth+1> empty_roots;
76 };
77 
78 template<size_t Depth, typename Hash>
81  return a.empty_roots == b.empty_roots;
82 }
83 
84 template<size_t Depth, typename Hash>
85 class IncrementalWitness;
86 
87 template<size_t Depth, typename Hash>
89 
90 friend class IncrementalWitness<Depth, Hash>;
91 
92 public:
93  BOOST_STATIC_ASSERT(Depth >= 1);
94 
96 
97  size_t DynamicMemoryUsage() const {
98  return 32 + // left
99  32 + // right
100  parents.size() * 32; // parents
101  }
102 
103  size_t size() const;
104 
105  void append(Hash obj);
106  Hash root() const {
107  return root(Depth, std::deque<Hash>());
108  }
109  Hash last() const;
110 
112  return IncrementalWitness<Depth, Hash>(*this);
113  }
114 
116  {
117  READWRITE(obj.left, obj.right, obj.parents);
118  obj.wfcheck();
119  }
120 
121  static Hash empty_root() {
122  return emptyroots.empty_root(Depth);
123  }
124 
125  template <size_t D, typename H>
127  const IncrementalMerkleTree<D, H>& b);
128 
129 private:
133 
134  // Collapsed "left" subtrees ordered toward the root of the tree.
135  std::vector<Optional<Hash>> parents;
136  MerklePath path(std::deque<Hash> filler_hashes = std::deque<Hash>()) const;
137  Hash root(size_t depth, std::deque<Hash> filler_hashes = std::deque<Hash>()) const;
138  bool is_complete(size_t depth = Depth) const;
139  size_t next_depth(size_t skip) const;
140  void wfcheck() const;
141 };
142 
143 template<size_t Depth, typename Hash>
146  return (a.emptyroots == b.emptyroots &&
147  a.left == b.left &&
148  a.right == b.right &&
149  a.parents == b.parents);
150 }
151 
152 template <size_t Depth, typename Hash>
154 friend class IncrementalMerkleTree<Depth, Hash>;
155 
156 public:
157  // Required for Unserialize()
159 
160  MerklePath path() const {
161  return tree.path(partial_path());
162  }
163 
164  // Return the element being witnessed (should be a note
165  // commitment!)
166  Hash element() const {
167  return tree.last();
168  }
169 
170  uint64_t position() const {
171  return tree.size() - 1;
172  }
173 
174  Hash root() const {
175  return tree.root(Depth, partial_path());
176  }
177 
178  void append(Hash obj);
179 
181  {
182  READWRITE(obj.tree, obj.filled, obj.cursor);
183  SER_READ(obj, obj.cursor_depth = obj.tree.next_depth(obj.filled.size()));
184  }
185 
186  template <size_t D, typename H>
187  friend bool operator==(const IncrementalWitness<D, H>& a,
188  const IncrementalWitness<D, H>& b);
189 
190 private:
192  std::vector<Hash> filled;
194  size_t cursor_depth = 0;
195  std::deque<Hash> partial_path() const;
197 };
198 
199 template<size_t Depth, typename Hash>
202  return (a.tree == b.tree &&
203  a.filled == b.filled &&
204  a.cursor == b.cursor &&
205  a.cursor_depth == b.cursor_depth);
206 }
207 
208 class SHA256Compress : public uint256 {
209 public:
211  SHA256Compress(uint256 contents) : uint256(contents) { }
212 
213  static SHA256Compress combine(
214  const SHA256Compress& a,
215  const SHA256Compress& b,
216  size_t depth
217  );
218 
220  return SHA256Compress();
221  }
222  static SHA256Compress EmptyRoot(size_t);
223 };
224 
225 class PedersenHash : public uint256 {
226 public:
228  PedersenHash(uint256 contents) : uint256(contents) { }
229 
230  static PedersenHash combine(
231  const PedersenHash& a,
232  const PedersenHash& b,
233  size_t depth
234  );
235 
236  static PedersenHash uncommitted();
237  static PedersenHash EmptyRoot(size_t);
238 };
239 
240 template<size_t Depth, typename Hash>
241 EmptyMerkleRoots<Depth, Hash> IncrementalMerkleTree<Depth, Hash>::emptyroots;
242 
243 } // end namespace `libzcash`
244 
247 
250 
251 #endif // PIVX_SAPLING_INCREMENTALMERKLETREE_H
friend bool operator==(const EmptyMerkleRoots< D, H > &a, const EmptyMerkleRoots< D, H > &b)
Hash empty_root(size_t depth) const
std::array< Hash, Depth+1 > empty_roots
MerklePath path(std::deque< Hash > filler_hashes=std::deque< Hash >()) const
size_t next_depth(size_t skip) const
friend bool operator==(const IncrementalMerkleTree< D, H > &a, const IncrementalMerkleTree< D, H > &b)
bool is_complete(size_t depth=Depth) const
std::vector< Optional< Hash > > parents
static EmptyMerkleRoots< Depth, Hash > emptyroots
IncrementalWitness< Depth, Hash > witness() const
SERIALIZE_METHODS(IncrementalMerkleTree, obj)
friend bool operator==(const IncrementalWitness< D, H > &a, const IncrementalWitness< D, H > &b)
SERIALIZE_METHODS(IncrementalWitness, obj)
Optional< IncrementalMerkleTree< Depth, Hash > > cursor
IncrementalWitness(IncrementalMerkleTree< Depth, Hash > tree)
IncrementalMerkleTree< Depth, Hash > tree
std::deque< Hash > partial_path() const
void Serialize(Stream &s) const
std::vector< bool > index
std::vector< std::vector< bool > > authentication_path
MerklePath(std::vector< std::vector< bool >> authentication_path, std::vector< bool > index)
static PedersenHash combine(const PedersenHash &a, const PedersenHash &b, size_t depth)
static PedersenHash EmptyRoot(size_t)
PedersenHash(uint256 contents)
static PedersenHash uncommitted()
static SHA256Compress EmptyRoot(size_t)
static SHA256Compress uncommitted()
static SHA256Compress combine(const SHA256Compress &a, const SHA256Compress &b, size_t depth)
256-bit opaque blob.
Definition: uint256.h:138
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:173
libzcash::IncrementalMerkleTree< SAPLING_INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::PedersenHash > SaplingMerkleTree
libzcash::IncrementalWitness< INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::PedersenHash > SaplingTestingWitness
libzcash::IncrementalMerkleTree< INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::PedersenHash > SaplingTestingMerkleTree
libzcash::IncrementalWitness< SAPLING_INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::PedersenHash > SaplingWitness
bool operator==(const EmptyMerkleRoots< Depth, Hash > &a, const EmptyMerkleRoots< Depth, Hash > &b)
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
uint64_t convertVectorToInt(const std::vector< bool > &v)
std::vector< bool > convertBytesVectorToVector(const std::vector< unsigned char > &bytes)
#define SER_READ(obj, code)
Definition: serialize.h:185
#define READWRITE(...)
Definition: serialize.h:183