merkleblock.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-2021 The Limenka developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #ifndef LIMENKA_MERKLEBLOCK_H
   7  #define LIMENKA_MERKLEBLOCK_H
   8  
   9  #include <common/bloom.h>
  10  #include <primitives/block.h>
  11  #include <serialize.h>
  12  #include <uint256.h>
  13  
  14  #include <set>
  15  #include <vector>
  16  
  17  // Helper functions for serialization.
  18  std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits);
  19  std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes);
  20  
  21  /** Data structure that represents a partial merkle tree.
  22   *
  23   * It represents a subset of the txid's of a known block, in a way that
  24   * allows recovery of the list of txid's and the merkle root, in an
  25   * authenticated way.
  26   *
  27   * The encoding works as follows: we traverse the tree in depth-first order,
  28   * storing a bit for each traversed node, signifying whether the node is the
  29   * parent of at least one matched leaf txid (or a matched txid itself). In
  30   * case we are at the leaf level, or this bit is 0, its merkle node hash is
  31   * stored, and its children are not explored further. Otherwise, no hash is
  32   * stored, but we recurse into both (or the only) child branch. During
  33   * decoding, the same depth-first traversal is performed, consuming bits and
  34   * hashes as they written during encoding.
  35   *
  36   * The serialization is fixed and provides a hard guarantee about the
  37   * encoded size:
  38   *
  39   *   SIZE <= 10 + ceil(32.25*N)
  40   *
  41   * Where N represents the number of leaf nodes of the partial tree. N itself
  42   * is bounded by:
  43   *
  44   *   N <= total_transactions
  45   *   N <= 1 + matched_transactions*tree_height
  46   *
  47   * The serialization format:
  48   *  - uint32     total_transactions (4 bytes)
  49   *  - varint     number of hashes   (1-3 bytes)
  50   *  - uint256[]  hashes in depth-first order (<= 32*N bytes)
  51   *  - varint     number of bytes of flag bits (1-3 bytes)
  52   *  - byte[]     flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits)
  53   * The size constraints follow from this.
  54   */
  55  class CPartialMerkleTree
  56  {
  57  protected:
  58      /** the total number of transactions in the block */
  59      unsigned int nTransactions;
  60  
  61      /** node-is-parent-of-matched-txid bits */
  62      std::vector<bool> vBits;
  63  
  64      /** txids and internal hashes */
  65      std::vector<uint256> vHash;
  66  
  67      /** flag set when encountering invalid data */
  68      bool fBad;
  69  
  70      /** helper function to efficiently calculate the number of nodes at given height in the merkle tree */
  71      unsigned int CalcTreeWidth(int height) const {
  72          return (nTransactions+(1 << height)-1) >> height;
  73      }
  74  
  75      /** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */
  76      uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
  77  
  78      /** recursive function that traverses tree nodes, storing the data as bits and hashes */
  79      void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
  80  
  81      /**
  82       * recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
  83       * it returns the hash of the respective node and its respective index.
  84       */
  85      uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex);
  86  
  87  public:
  88  
  89      SERIALIZE_METHODS(CPartialMerkleTree, obj)
  90      {
  91          READWRITE(obj.nTransactions, obj.vHash);
  92          std::vector<unsigned char> bytes;
  93          SER_WRITE(obj, bytes = BitsToBytes(obj.vBits));
  94          READWRITE(bytes);
  95          SER_READ(obj, obj.vBits = BytesToBits(bytes));
  96          SER_READ(obj, obj.fBad = false);
  97      }
  98  
  99      /** Construct a partial merkle tree from a list of transaction ids, and a mask that selects a subset of them */
 100      CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
 101  
 102      CPartialMerkleTree();
 103  
 104      /**
 105       * extract the matching txid's represented by this partial merkle tree
 106       * and their respective indices within the partial tree.
 107       * returns the merkle root, or 0 in case of failure
 108       */
 109      uint256 ExtractMatches(std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex);
 110  
 111      /** Get number of transactions the merkle proof is indicating for cross-reference with
 112       * local blockchain knowledge.
 113       */
 114      unsigned int GetNumTransactions() const { return nTransactions; };
 115  
 116  };
 117  
 118  
 119  /**
 120   * Used to relay blocks as header + vector<merkle branch>
 121   * to filtered nodes.
 122   *
 123   * NOTE: The class assumes that the given CBlock has *at least* 1 transaction. If the CBlock has 0 txs, it will hit an assertion.
 124   */
 125  class CMerkleBlock
 126  {
 127  public:
 128      /** Public only for unit testing */
 129      CBlockHeader header;
 130      CPartialMerkleTree txn;
 131      /** Only used by subclass WtxidInBlockMerkleProof */
 132      bool m_prove_gentx;  //!< if m_gentx doesn't commit to a witness tree, this indicates the gentx should be included in the proven tx list
 133      CTransactionRef m_gentx;
 134      CPartialMerkleTree m_wtxid_tree;
 135  
 136      /**
 137       * Public only for unit testing and relay testing (not relayed).
 138       *
 139       * Used only when a bloom filter is specified to allow
 140       * testing the transactions which matched the bloom filter.
 141       */
 142      std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
 143  
 144      /**
 145       * Create from a CBlock, filtering transactions according to filter
 146       * Note that this will call IsRelevantAndUpdate on the filter for each transaction,
 147       * thus the filter will likely be modified.
 148       */
 149      CMerkleBlock(const CBlock& block, CBloomFilter& filter) : CMerkleBlock(block, &filter, nullptr) { }
 150  
 151      // Create from a CBlock, matching the txids in the set
 152      CMerkleBlock(const CBlock& block, const std::set<Txid>& txids, bool prove_witness=false) : CMerkleBlock{block, nullptr, &txids, prove_witness} {}
 153  
 154      CMerkleBlock() = default;
 155  
 156      SERIALIZE_METHODS(CMerkleBlock, obj) {
 157          SER_WRITE(obj, assert(!obj.m_gentx));
 158          READWRITE(obj.header, obj.txn);
 159          SER_READ(obj, obj.m_gentx.reset());
 160          SER_READ(obj, obj.m_wtxid_tree = CPartialMerkleTree());
 161      }
 162  
 163      template<typename Stream>
 164      void SerializeWithWitness(Stream& s) { SerializationWithWitnessOps(*this, s, ActionSerialize{}); }
 165      template<typename Stream>
 166      void UnserializeWithWitness(Stream& s) { SerializationWithWitnessOps(*this, s, ActionUnserialize{}); }
 167      template<typename Stream, typename Type, typename Operation>
 168      static void SerializationWithWitnessOps(Type& obj, Stream& s, Operation ser_action) {
 169          // versions are negative to be strictly incompatible with block versions
 170          // -1 indicates a non-witness block, proving both the generation tx and txid(s) in the main merkle tree
 171          // -2 indicates a witness block, providing the generation tx in the main merkle tree, and txid(s) in the witness tree
 172          int32_t version;
 173          SER_WRITE(obj, version = obj.m_wtxid_tree.GetNumTransactions() ? -2 : -1);
 174          READWRITE(version);
 175  
 176          SER_WRITE(obj, assert(obj.m_gentx));
 177          READWRITE(obj.header, obj.txn);
 178          READWRITE(TX_WITH_WITNESS(obj.m_gentx));
 179          if (version == -1) {
 180              READWRITE(obj.m_prove_gentx);
 181          } else {
 182              READWRITE(obj.m_wtxid_tree);
 183          }
 184      }
 185  
 186  private:
 187      // Combined constructor to consolidate code
 188      CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<Txid>* txids, bool prove_witness=false);
 189  };
 190  
 191  #endif // LIMENKA_MERKLEBLOCK_H
 192