1 #ifndef ZCINCREMENTALMERKLETREE_H_
2 #define ZCINCREMENTALMERKLETREE_H_
5 #include <boost/optional.hpp>
6 #include <boost/static_assert.hpp>
17 std::vector<std::vector<bool>> authentication_path;
18 std::vector<bool> index;
20 ADD_SERIALIZE_METHODS;
22 template <typename Stream, typename Operation>
23 inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
24 READWRITE(authentication_path);
30 MerklePath(std::vector<std::vector<bool>> authentication_path, std::vector<bool> index)
31 : authentication_path(authentication_path), index(index) { }
34 template<size_t Depth, typename Hash>
35 class EmptyMerkleRoots {
38 empty_roots.at(0) = Hash();
39 for (size_t d = 1; d <= Depth; d++) {
40 empty_roots.at(d) = Hash::combine(empty_roots.at(d-1), empty_roots.at(d-1));
43 Hash empty_root(size_t depth) {
44 return empty_roots.at(depth);
47 boost::array<Hash, Depth+1> empty_roots;
50 template<size_t Depth, typename Hash>
51 class IncrementalWitness;
53 template<size_t Depth, typename Hash>
54 class IncrementalMerkleTree {
56 friend class IncrementalWitness<Depth, Hash>;
59 BOOST_STATIC_ASSERT(Depth >= 1);
61 IncrementalMerkleTree() { }
63 void append(Hash obj);
65 return root(Depth, std::deque<Hash>());
68 IncrementalWitness<Depth, Hash> witness() const {
69 return IncrementalWitness<Depth, Hash>(*this);
72 ADD_SERIALIZE_METHODS;
74 template <typename Stream, typename Operation>
75 inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
83 static Hash empty_root() {
84 return emptyroots.empty_root(Depth);
88 static EmptyMerkleRoots<Depth, Hash> emptyroots;
89 boost::optional<Hash> left;
90 boost::optional<Hash> right;
92 // Collapsed "left" subtrees ordered toward the root of the tree.
93 std::vector<boost::optional<Hash>> parents;
94 MerklePath path(std::deque<Hash> filler_hashes = std::deque<Hash>()) const;
95 Hash root(size_t depth, std::deque<Hash> filler_hashes = std::deque<Hash>()) const;
96 bool is_complete(size_t depth = Depth) const;
97 size_t next_depth(size_t skip) const;
101 template <size_t Depth, typename Hash>
102 class IncrementalWitness {
103 friend class IncrementalMerkleTree<Depth, Hash>;
106 MerklePath path() const {
107 return tree.path(partial_path());
111 return tree.root(Depth, partial_path());
114 void append(Hash obj);
116 ADD_SERIALIZE_METHODS;
118 template <typename Stream, typename Operation>
119 inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
124 cursor_depth = tree.next_depth(filled.size());
128 IncrementalMerkleTree<Depth, Hash> tree;
129 std::vector<Hash> filled;
130 boost::optional<IncrementalMerkleTree<Depth, Hash>> cursor;
132 std::deque<Hash> partial_path() const;
133 IncrementalWitness(IncrementalMerkleTree<Depth, Hash> tree) : tree(tree) {}
136 class SHA256Compress : public uint256 {
138 SHA256Compress() : uint256() {}
139 SHA256Compress(uint256 contents) : uint256(contents) { }
141 static SHA256Compress combine(const SHA256Compress& a, const SHA256Compress& b);
144 } // end namespace `libzcash`
146 typedef libzcash::IncrementalMerkleTree<INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::SHA256Compress> ZCIncrementalMerkleTree;
147 typedef libzcash::IncrementalMerkleTree<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::SHA256Compress> ZCTestingIncrementalMerkleTree;
149 typedef libzcash::IncrementalWitness<INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::SHA256Compress> ZCIncrementalWitness;
150 typedef libzcash::IncrementalWitness<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::SHA256Compress> ZCTestingIncrementalWitness;
152 #endif /* ZCINCREMENTALMERKLETREE_H_ */