#ifndef ZC_INCREMENTALMERKLETREE_H_ #define ZC_INCREMENTALMERKLETREE_H_ #include #include #include #include "uint256.h" #include "serialize.h" #include "Zcash.h" namespace libzcash { class MerklePath { public: std::vector> authentication_path; std::vector index; ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(authentication_path); READWRITE(index); } MerklePath() { } MerklePath(std::vector> authentication_path, std::vector index) : authentication_path(authentication_path), index(index) { } }; template class EmptyMerkleRoots { public: EmptyMerkleRoots() { empty_roots.at(0) = Hash(); for (size_t d = 1; d <= Depth; d++) { empty_roots.at(d) = Hash::combine(empty_roots.at(d-1), empty_roots.at(d-1)); } } Hash empty_root(size_t depth) { return empty_roots.at(depth); } template friend bool operator==(const EmptyMerkleRoots& a, const EmptyMerkleRoots& b); private: boost::array empty_roots; }; template bool operator==(const EmptyMerkleRoots& a, const EmptyMerkleRoots& b) { return a.empty_roots == b.empty_roots; } template class IncrementalWitness; template class IncrementalMerkleTree { friend class IncrementalWitness; public: BOOST_STATIC_ASSERT(Depth >= 1); IncrementalMerkleTree() { } size_t DynamicMemoryUsage() const { return 32 + // left 32 + // right parents.size() * 32; // parents } size_t size() const; void append(Hash obj); Hash root() const { return root(Depth, std::deque()); } Hash last() const; IncrementalWitness witness() const { return IncrementalWitness(*this); } ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(left); READWRITE(right); READWRITE(parents); wfcheck(); } static Hash empty_root() { return emptyroots.empty_root(Depth); } template friend bool operator==(const IncrementalMerkleTree& a, const IncrementalMerkleTree& b); private: static EmptyMerkleRoots emptyroots; boost::optional left; boost::optional right; // Collapsed "left" subtrees ordered toward the root of the tree. std::vector> parents; MerklePath path(std::deque filler_hashes = std::deque()) const; Hash root(size_t depth, std::deque filler_hashes = std::deque()) const; bool is_complete(size_t depth = Depth) const; size_t next_depth(size_t skip) const; void wfcheck() const; }; template bool operator==(const IncrementalMerkleTree& a, const IncrementalMerkleTree& b) { return (a.emptyroots == b.emptyroots && a.left == b.left && a.right == b.right && a.parents == b.parents); } template class IncrementalWitness { friend class IncrementalMerkleTree; public: // Required for Unserialize() IncrementalWitness() {} MerklePath path() const { return tree.path(partial_path()); } // Return the element being witnessed (should be a note // commitment!) Hash element() const { return tree.last(); } Hash root() const { return tree.root(Depth, partial_path()); } void append(Hash obj); ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(tree); READWRITE(filled); READWRITE(cursor); cursor_depth = tree.next_depth(filled.size()); } template friend bool operator==(const IncrementalWitness& a, const IncrementalWitness& b); private: IncrementalMerkleTree tree; std::vector filled; boost::optional> cursor; size_t cursor_depth = 0; std::deque partial_path() const; IncrementalWitness(IncrementalMerkleTree tree) : tree(tree) {} }; template bool operator==(const IncrementalWitness& a, const IncrementalWitness& b) { return (a.tree == b.tree && a.filled == b.filled && a.cursor == b.cursor && a.cursor_depth == b.cursor_depth); } class SHA256Compress : public uint256 { public: SHA256Compress() : uint256() {} SHA256Compress(uint256 contents) : uint256(contents) { } static SHA256Compress combine(const SHA256Compress& a, const SHA256Compress& b); }; } // end namespace `libzcash` typedef libzcash::IncrementalMerkleTree ZCIncrementalMerkleTree; typedef libzcash::IncrementalMerkleTree ZCTestingIncrementalMerkleTree; typedef libzcash::IncrementalWitness ZCIncrementalWitness; typedef libzcash::IncrementalWitness ZCTestingIncrementalWitness; #endif /* ZC_INCREMENTALMERKLETREE_H_ */