LCOV - code coverage report
Current view: top level - src/sapling - incrementalmerkletree.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 72 73 98.6 %
Date: 2025-02-23 09:33:43 Functions: 16 52 30.8 %

          Line data    Source code
       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         313 : class MerklePath {
      22             : public:
      23             :     std::vector<std::vector<bool>> authentication_path;
      24             :     std::vector<bool> index;
      25             : 
      26             :     template<typename Stream>
      27         433 :     void Serialize(Stream &s) const
      28             :     {
      29           0 :         std::vector<std::vector<unsigned char>> pathBytes;
      30             :         uint64_t indexInt;
      31         433 :         assert(authentication_path.size() == index.size());
      32         433 :         pathBytes.resize(authentication_path.size());
      33        4209 :         for (size_t i = 0; i < authentication_path.size(); i++) {
      34        3776 :             pathBytes[i].resize((authentication_path[i].size()+7)/8);
      35      970432 :             for (unsigned int p = 0; p < authentication_path[i].size(); p++) {
      36      966656 :                 pathBytes[i][p / 8] |= authentication_path[i][p] << (7-(p % 8));
      37             :             }
      38             :         }
      39         433 :         indexInt = convertVectorToInt(index);
      40         433 :         ::Serialize(s, pathBytes);
      41         433 :         ::Serialize(s, indexInt);
      42         433 :     }
      43             : 
      44             :     template<typename Stream>
      45         120 :     void Unserialize(Stream &s)
      46             :     {
      47         120 :         std::vector<std::vector<unsigned char>> pathBytes;
      48             :         uint64_t indexInt;
      49         120 :         ::Unserialize(s, pathBytes);
      50         120 :         ::Unserialize(s, indexInt);
      51         120 :         MerklePath &us = *(const_cast<MerklePath*>(this));
      52         600 :         for (size_t i = 0; i < pathBytes.size(); i++) {
      53         960 :             us.authentication_path.push_back(convertBytesVectorToVector(pathBytes[i]));
      54         480 :             us.index.push_back((indexInt >> ((pathBytes.size() - 1) - i)) & 1);
      55             :         }
      56         120 :     }
      57             : 
      58         120 :     MerklePath() { }
      59             : 
      60         193 :     MerklePath(std::vector<std::vector<bool>> authentication_path, std::vector<bool> index)
      61         193 :     : authentication_path(authentication_path), index(index) { }
      62             : };
      63             : 
      64             : template<size_t Depth, typename Hash>
      65             : class EmptyMerkleRoots {
      66             : public:
      67         132 :     EmptyMerkleRoots() { }
      68     3388499 :     Hash empty_root(size_t depth) const {
      69     3388497 :         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>
      79           4 : bool operator==(const EmptyMerkleRoots<Depth, Hash>& a,
      80             :                 const EmptyMerkleRoots<Depth, Hash>& b) {
      81           4 :     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>
      88      655016 : class IncrementalMerkleTree {
      89             : 
      90             : friend class IncrementalWitness<Depth, Hash>;
      91             : 
      92             : public:
      93             :     BOOST_STATIC_ASSERT(Depth >= 1);
      94             : 
      95      166418 :     IncrementalMerkleTree() { }
      96             : 
      97       57599 :     size_t DynamicMemoryUsage() const {
      98             :         return 32 + // left
      99       57599 :                32 + // right
     100       57599 :                parents.size() * 32; // parents
     101             :     }
     102             : 
     103             :     size_t size() const;
     104             : 
     105             :     void append(Hash obj);
     106       86453 :     Hash root() const {
     107      172906 :         return root(Depth, std::deque<Hash>());
     108             :     }
     109             :     Hash last() const;
     110             : 
     111        1217 :     IncrementalWitness<Depth, Hash> witness() const {
     112        3651 :         return IncrementalWitness<Depth, Hash>(*this);
     113             :     }
     114             : 
     115        1832 :     SERIALIZE_METHODS(IncrementalMerkleTree, obj)
     116             :     {
     117        2742 :         READWRITE(obj.left, obj.right, obj.parents);
     118        2742 :         obj.wfcheck();
     119             :     }
     120             : 
     121       23008 :     static Hash empty_root() {
     122       23008 :         return emptyroots.empty_root(Depth);
     123             :     }
     124             : 
     125             :     template <size_t D, typename H>
     126             :     friend bool operator==(const IncrementalMerkleTree<D, H>& a,
     127             :                            const IncrementalMerkleTree<D, H>& b);
     128             : 
     129             : private:
     130             :     static EmptyMerkleRoots<Depth, Hash> emptyroots;
     131             :     Optional<Hash> left;
     132             :     Optional<Hash> right;
     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>
     144           4 : bool operator==(const IncrementalMerkleTree<Depth, Hash>& a,
     145             :                 const IncrementalMerkleTree<Depth, Hash>& b) {
     146           8 :     return (a.emptyroots == b.emptyroots &&
     147           4 :             a.left == b.left &&
     148          12 :             a.right == b.right &&
     149           4 :             a.parents == b.parents);
     150             : }
     151             : 
     152             : template <size_t Depth, typename Hash>
     153             : class IncrementalWitness {
     154             : friend class IncrementalMerkleTree<Depth, Hash>;
     155             : 
     156             : public:
     157             :     // Required for Unserialize()
     158         137 :     IncrementalWitness() {}
     159             : 
     160         209 :     MerklePath path() const {
     161         402 :         return tree.path(partial_path());
     162             :     }
     163             : 
     164             :     // Return the element being witnessed (should be a note
     165             :     // commitment!)
     166          16 :     Hash element() const {
     167          16 :         return tree.last();
     168             :     }
     169             : 
     170         976 :     uint64_t position() const {
     171         976 :         return tree.size() - 1;
     172             :     }
     173             : 
     174       19204 :     Hash root() const {
     175       38408 :         return tree.root(Depth, partial_path());
     176             :     }
     177             : 
     178             :     void append(Hash obj);
     179             : 
     180         138 :     SERIALIZE_METHODS(IncrementalWitness, obj)
     181             :     {
     182        1381 :         READWRITE(obj.tree, obj.filled, obj.cursor);
     183        1381 :         SER_READ(obj, obj.cursor_depth = obj.tree.next_depth(obj.filled.size()));
     184         137 :     }
     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:
     191             :     IncrementalMerkleTree<Depth, Hash> tree;
     192             :     std::vector<Hash> filled;
     193             :     Optional<IncrementalMerkleTree<Depth, Hash>> cursor;
     194             :     size_t cursor_depth = 0;
     195             :     std::deque<Hash> partial_path() const;
     196        1217 :     explicit IncrementalWitness(IncrementalMerkleTree<Depth, Hash> tree) : tree(tree) {}
     197             : };
     198             : 
     199             : template<size_t Depth, typename Hash>
     200           4 : bool operator==(const IncrementalWitness<Depth, Hash>& a,
     201             :                 const IncrementalWitness<Depth, Hash>& b) {
     202           8 :     return (a.tree == b.tree &&
     203           4 :             a.filled == b.filled &&
     204          12 :             a.cursor == b.cursor &&
     205           4 :             a.cursor_depth == b.cursor_depth);
     206             : }
     207             : 
     208             : class SHA256Compress : public uint256 {
     209             : public:
     210         388 :     SHA256Compress() : uint256() {}
     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             : 
     219           1 :     static SHA256Compress uncommitted() {
     220           2 :         return SHA256Compress();
     221             :     }
     222             :     static SHA256Compress EmptyRoot(size_t);
     223             : };
     224             : 
     225             : class PedersenHash : public uint256 {
     226             : public:
     227     7341014 :     PedersenHash() : uint256() {}
     228      204968 :     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             : 
     245             : typedef libzcash::IncrementalMerkleTree<SAPLING_INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::PedersenHash> SaplingMerkleTree;
     246             : typedef libzcash::IncrementalMerkleTree<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::PedersenHash> SaplingTestingMerkleTree;
     247             : 
     248             : typedef libzcash::IncrementalWitness<SAPLING_INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::PedersenHash> SaplingWitness;
     249             : typedef libzcash::IncrementalWitness<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::PedersenHash> SaplingTestingWitness;
     250             : 
     251             : #endif // PIVX_SAPLING_INCREMENTALMERKLETREE_H

Generated by: LCOV version 1.14