/** @file ***************************************************************************** Declaration of interfaces for the classes IncrementalMerkleTreeCompact, IncrementalMerkleNode, and IncrementalMerkleTree. ***************************************************************************** * @author This file is part of libzerocash, developed by the Zerocash * project and contributors (see AUTHORS). * @copyright MIT license (see LICENSE file) *****************************************************************************/ #ifndef INCREMENTALMERKLETREE_H_ #define INCREMENTALMERKLETREE_H_ #include "crypto/sha256.h" #include "Zerocash.h" #include #include #include #include #include "libsnark/common/data_structures/merkle_tree.hpp" namespace libzerocash { /******************* Incremental Merkle tree compact *************************/ /* This is a comapct way to represent an incremental merkle tree, where all full * subtrees are replaced by their hashes. It contains just enough information * that you can continue addding elements to the tree. * * This class can only be constructed by IncrementalMerkleTree, and after that, * it is immutable. To act on a compact representation, it must first be * de-compactified by loading it into an IncrementalMerkleTree. */ class IncrementalMerkleTreeCompact { friend class IncrementalMerkleTree; friend class IncrementalMerkleNode; public: uint32_t getHeight() { return this->treeHeight; } uint32_t getTreeHeight() { return treeHeight; } std::vector< std::vector > const& getHashVec() { return hashVec; } std::vector< bool > const& getHashList() { return hashList; } std::vector serialize() const; static IncrementalMerkleTreeCompact deserialize(const std::vector& serialized); private: IncrementalMerkleTreeCompact() : treeHeight(0) {} uint32_t treeHeight; std::vector< std::vector > hashVec; std::vector< bool > hashList; }; /********************* Incremental Merkle tree node **************************/ class IncrementalMerkleNode { public: CSHA256 ctx256; IncrementalMerkleNode* left; IncrementalMerkleNode* right; std::vector value; uint32_t nodeDepth; uint32_t treeHeight; bool subtreeFull; bool subtreePruned; IncrementalMerkleNode(uint32_t depth, uint32_t height); IncrementalMerkleNode(const IncrementalMerkleNode& toCopy); ~IncrementalMerkleNode(); // Methods bool insertElement(const std::vector &hashV, std::vector &index); bool getWitness(const std::vector &index, merkle_authentication_path &witness); bool prune(); void getCompactRepresentation(IncrementalMerkleTreeCompact &rep) const; bool fromCompactRepresentation(IncrementalMerkleTreeCompact &rep, uint32_t pos); // Utility methods bool isLeaf() const { return (nodeDepth == treeHeight); } bool isPruned() const { return subtreePruned; } bool hasFreeLeaves() const { return (!subtreeFull); } bool hasRightChildren() const { if (!right) return false; return true; } void getValue(std::vector &r) const { r = value; } const std::vector& getValue() const { return value; } bool checkIfNodeFull(); void updateHashValue(); IncrementalMerkleNode operator=(const IncrementalMerkleNode &rhs); }; /************************ Incremental Merkle tree ****************************/ class IncrementalMerkleTree { protected: IncrementalMerkleNode root; uint32_t treeHeight; public: IncrementalMerkleTree(uint32_t height = ZEROCASH_DEFAULT_TREE_SIZE); IncrementalMerkleTree(std::vector< std::vector > &valueVector, uint32_t height); IncrementalMerkleTree(IncrementalMerkleTreeCompact &compact); void setTo(const IncrementalMerkleTree &other) { auto compact = other.getCompactRepresentation(); fromCompactRepresentation(compact); } bool insertElement(const std::vector &hashV, std::vector &index); bool insertElement(const std::vector &hashV, std::vector &index); bool insertVector(std::vector< std::vector > &valueVector); bool getWitness(const std::vector &index, merkle_authentication_path &witness); bool getRootValue(std::vector& r) const; bool getRootValue(std::vector& r) const; std::vectorgetRoot(); bool prune(); IncrementalMerkleTreeCompact getCompactRepresentation() const; std::vector serialize() const { auto compact = getCompactRepresentation(); return compact.serialize(); } static IncrementalMerkleTree deserialize(const std::vector& serialized) { auto deserialized = IncrementalMerkleTreeCompact::deserialize(serialized); return IncrementalMerkleTree(deserialized); } bool fromCompactRepresentation(IncrementalMerkleTreeCompact &rep); }; } /* namespace libzerocash */ #endif /* INCREMENTALMERKLETREE_H_ */