LCOV - code coverage report
Current view: top level - src - merkleblock.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 111 123 90.2 %
Date: 2021-06-29 14:35:33 Functions: 9 9 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 54 62 87.1 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2009-2010 Satoshi Nakamoto
#       2                 :            : // Copyright (c) 2009-2020 The Bitcoin Core 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                 :            : #include <merkleblock.h>
#       7                 :            : 
#       8                 :            : #include <hash.h>
#       9                 :            : #include <consensus/consensus.h>
#      10                 :            : 
#      11                 :            : 
#      12                 :            : std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits)
#      13                 :        358 : {
#      14                 :        358 :     std::vector<unsigned char> ret((bits.size() + 7) / 8);
#      15         [ +  + ]:     153237 :     for (unsigned int p = 0; p < bits.size(); p++) {
#      16                 :     152879 :         ret[p / 8] |= bits[p] << (p % 8);
#      17                 :     152879 :     }
#      18                 :        358 :     return ret;
#      19                 :        358 : }
#      20                 :            : 
#      21                 :            : std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes)
#      22                 :        355 : {
#      23                 :        355 :     std::vector<bool> ret(bytes.size() * 8);
#      24         [ +  + ]:     154763 :     for (unsigned int p = 0; p < ret.size(); p++) {
#      25                 :     154408 :         ret[p] = (bytes[p / 8] & (1 << (p % 8))) != 0;
#      26                 :     154408 :     }
#      27                 :        355 :     return ret;
#      28                 :        355 : }
#      29                 :            : 
#      30                 :            : CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids)
#      31                 :         46 : {
#      32                 :         46 :     header = block.GetBlockHeader();
#      33                 :            : 
#      34                 :         46 :     std::vector<bool> vMatch;
#      35                 :         46 :     std::vector<uint256> vHashes;
#      36                 :            : 
#      37                 :         46 :     vMatch.reserve(block.vtx.size());
#      38                 :         46 :     vHashes.reserve(block.vtx.size());
#      39                 :            : 
#      40         [ +  + ]:        253 :     for (unsigned int i = 0; i < block.vtx.size(); i++)
#      41                 :        207 :     {
#      42                 :        207 :         const uint256& hash = block.vtx[i]->GetHash();
#      43 [ +  + ][ +  + ]:        207 :         if (txids && txids->count(hash)) {
#      44                 :         24 :             vMatch.push_back(true);
#      45 [ +  + ][ +  + ]:        183 :         } else if (filter && filter->IsRelevantAndUpdate(*block.vtx[i])) {
#      46                 :         43 :             vMatch.push_back(true);
#      47                 :         43 :             vMatchedTxn.emplace_back(i, hash);
#      48                 :        140 :         } else {
#      49                 :        140 :             vMatch.push_back(false);
#      50                 :        140 :         }
#      51                 :        207 :         vHashes.push_back(hash);
#      52                 :        207 :     }
#      53                 :            : 
#      54                 :         46 :     txn = CPartialMerkleTree(vHashes, vMatch);
#      55                 :         46 : }
#      56                 :            : 
#      57                 :     287659 : uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid) {
#      58                 :            :     //we can never have zero txs in a merkle block, we always need the coinbase tx
#      59                 :            :     //if we do not have this assert, we can hit a memory access violation when indexing into vTxid
#      60                 :     287659 :     assert(vTxid.size() != 0);
#      61         [ +  + ]:     287659 :     if (height == 0) {
#      62                 :            :         // hash at height 0 is the txids themselves
#      63                 :     181895 :         return vTxid[pos];
#      64                 :     181895 :     } else {
#      65                 :            :         // calculate left hash
#      66                 :     105764 :         uint256 left = CalcHash(height-1, pos*2, vTxid), right;
#      67                 :            :         // calculate right hash if not beyond the end of the array - copy left hash otherwise
#      68         [ +  + ]:     105764 :         if (pos*2+1 < CalcTreeWidth(height-1))
#      69                 :     105308 :             right = CalcHash(height-1, pos*2+1, vTxid);
#      70                 :        456 :         else
#      71                 :        456 :             right = left;
#      72                 :            :         // combine subhashes
#      73                 :     105764 :         return Hash(left, right);
#      74                 :     105764 :     }
#      75                 :     287659 : }
#      76                 :            : 
#      77                 :     153077 : void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) {
#      78                 :            :     // determine whether this node is the parent of at least one matched txid
#      79                 :     153077 :     bool fParentOfMatch = false;
#      80 [ +  + ][ +  + ]:    1883856 :     for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++)
#      81                 :    1730779 :         fParentOfMatch |= vMatch[p];
#      82                 :            :     // store as flag bit
#      83                 :     153077 :     vBits.push_back(fParentOfMatch);
#      84 [ +  + ][ +  + ]:     153077 :     if (height==0 || !fParentOfMatch) {
#      85                 :            :         // if at height 0, or nothing interesting below, store hash and stop
#      86                 :      76587 :         vHash.push_back(CalcHash(height, pos, vTxid));
#      87                 :      76587 :     } else {
#      88                 :            :         // otherwise, don't store any hash, but descend into the subtrees
#      89                 :      76490 :         TraverseAndBuild(height-1, pos*2, vTxid, vMatch);
#      90         [ +  + ]:      76490 :         if (pos*2+1 < CalcTreeWidth(height-1))
#      91                 :      76203 :             TraverseAndBuild(height-1, pos*2+1, vTxid, vMatch);
#      92                 :      76490 :     }
#      93                 :     153077 : }
#      94                 :            : 
#      95                 :     764264 : uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex) {
#      96         [ -  + ]:     764264 :     if (nBitsUsed >= vBits.size()) {
#      97                 :            :         // overflowed the bits array - failure
#      98                 :          0 :         fBad = true;
#      99                 :          0 :         return uint256();
#     100                 :          0 :     }
#     101                 :     764264 :     bool fParentOfMatch = vBits[nBitsUsed++];
#     102 [ +  + ][ +  + ]:     764264 :     if (height==0 || !fParentOfMatch) {
#     103                 :            :         // if at height 0, or nothing interesting below, use stored hash and do not descend
#     104         [ -  + ]:     382337 :         if (nHashUsed >= vHash.size()) {
#     105                 :            :             // overflowed the hash array - failure
#     106                 :          0 :             fBad = true;
#     107                 :          0 :             return uint256();
#     108                 :          0 :         }
#     109                 :     382337 :         const uint256 &hash = vHash[nHashUsed++];
#     110 [ +  + ][ +  + ]:     382337 :         if (height==0 && fParentOfMatch) { // in case of height 0, we have a matched txid
#     111                 :     192306 :             vMatch.push_back(hash);
#     112                 :     192306 :             vnIndex.push_back(pos);
#     113                 :     192306 :         }
#     114                 :     382337 :         return hash;
#     115                 :     382337 :     } else {
#     116                 :            :         // otherwise, descend into the subtrees to extract matched txids and hashes
#     117                 :     381927 :         uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch, vnIndex), right;
#     118         [ +  + ]:     381927 :         if (pos*2+1 < CalcTreeWidth(height-1)) {
#     119                 :     380614 :             right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch, vnIndex);
#     120         [ +  + ]:     380614 :             if (right == left) {
#     121                 :            :                 // The left and right branches should never be identical, as the transaction
#     122                 :            :                 // hashes covered by them must each be unique.
#     123                 :          2 :                 fBad = true;
#     124                 :          2 :             }
#     125                 :     380614 :         } else {
#     126                 :       1313 :             right = left;
#     127                 :       1313 :         }
#     128                 :            :         // and combine them before returning
#     129                 :     381927 :         return Hash(left, right);
#     130                 :     381927 :     }
#     131                 :     764264 : }
#     132                 :            : 
#     133                 :        384 : CPartialMerkleTree::CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch) : nTransactions(vTxid.size()), fBad(false) {
#     134                 :            :     // reset state
#     135                 :        384 :     vBits.clear();
#     136                 :        384 :     vHash.clear();
#     137                 :            : 
#     138                 :            :     // calculate height of tree
#     139                 :        384 :     int nHeight = 0;
#     140         [ +  + ]:       2701 :     while (CalcTreeWidth(nHeight) > 1)
#     141                 :       2317 :         nHeight++;
#     142                 :            : 
#     143                 :            :     // traverse the partial tree
#     144                 :        384 :     TraverseAndBuild(nHeight, 0, vTxid, vMatch);
#     145                 :        384 : }
#     146                 :            : 
#     147                 :        408 : CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
#     148                 :            : 
#     149                 :       1723 : uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex) {
#     150                 :       1723 :     vMatch.clear();
#     151                 :            :     // An empty set will not work
#     152         [ -  + ]:       1723 :     if (nTransactions == 0)
#     153                 :          0 :         return uint256();
#     154                 :            :     // check for excessively high numbers of transactions
#     155         [ -  + ]:       1723 :     if (nTransactions > MAX_BLOCK_WEIGHT / MIN_TRANSACTION_WEIGHT)
#     156                 :          0 :         return uint256();
#     157                 :            :     // there can never be more hashes provided than one for every txid
#     158         [ -  + ]:       1723 :     if (vHash.size() > nTransactions)
#     159                 :          0 :         return uint256();
#     160                 :            :     // there must be at least one bit per node in the partial tree, and at least one node per hash
#     161         [ -  + ]:       1723 :     if (vBits.size() < vHash.size())
#     162                 :          0 :         return uint256();
#     163                 :            :     // calculate height of tree
#     164                 :       1723 :     int nHeight = 0;
#     165         [ +  + ]:      12879 :     while (CalcTreeWidth(nHeight) > 1)
#     166                 :      11156 :         nHeight++;
#     167                 :            :     // traverse the partial tree
#     168                 :       1723 :     unsigned int nBitsUsed = 0, nHashUsed = 0;
#     169                 :       1723 :     uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch, vnIndex);
#     170                 :            :     // verify that no problems occurred during the tree traversal
#     171         [ +  + ]:       1723 :     if (fBad)
#     172                 :          2 :         return uint256();
#     173                 :            :     // verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
#     174         [ -  + ]:       1721 :     if ((nBitsUsed+7)/8 != (vBits.size()+7)/8)
#     175                 :          0 :         return uint256();
#     176                 :            :     // verify that all hashes were consumed
#     177         [ -  + ]:       1721 :     if (nHashUsed != vHash.size())
#     178                 :          0 :         return uint256();
#     179                 :       1721 :     return hashMerkleRoot;
#     180                 :       1721 : }

Generated by: LCOV version 1.14