LCOV - code coverage report
Current view: top level - src/test - merkle_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 99.4 % 167 166
Test Date: 2026-03-13 05:22:04 Functions: 100.0 % 15 15
Branches: 55.4 % 702 389

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2015-present The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4                 :             : 
       5                 :             : #include <consensus/merkle.h>
       6                 :             : #include <test/util/common.h>
       7                 :             : #include <test/util/random.h>
       8                 :             : #include <test/util/setup_common.h>
       9                 :             : 
      10                 :             : #include <boost/test/unit_test.hpp>
      11                 :             : 
      12                 :             : BOOST_FIXTURE_TEST_SUITE(merkle_tests, TestingSetup)
      13                 :             : 
      14                 :         376 : static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
      15                 :         376 :     uint256 hash = leaf;
      16         [ +  + ]:        3638 :     for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
      17         [ +  + ]:        3262 :         if (nIndex & 1) {
      18                 :        1508 :             hash = Hash(*it, hash);
      19                 :             :         } else {
      20                 :        1754 :             hash = Hash(hash, *it);
      21                 :             :         }
      22                 :        3262 :         nIndex >>= 1;
      23                 :             :     }
      24                 :         376 :     return hash;
      25                 :             : }
      26                 :             : 
      27                 :             : // Older version of the merkle root computation code, for comparison.
      28                 :          91 : static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::vector<uint256>& vMerkleTree)
      29                 :             : {
      30         [ -  + ]:          91 :     vMerkleTree.clear();
      31         [ -  + ]:          91 :     vMerkleTree.reserve(block.vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
      32         [ +  + ]:      138887 :     for (std::vector<CTransactionRef>::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it)
      33                 :      138796 :         vMerkleTree.push_back((*it)->GetHash().ToUint256());
      34                 :          91 :     int j = 0;
      35                 :          91 :     bool mutated = false;
      36   [ -  +  +  + ]:         870 :     for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
      37                 :             :     {
      38         [ +  + ]:      139741 :         for (int i = 0; i < nSize; i += 2)
      39                 :             :         {
      40         [ +  + ]:      138962 :             int i2 = std::min(i+1, nSize-1);
      41   [ +  +  +  +  :      138962 :             if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
                   +  + ]
      42                 :             :                 // Two identical hashes at the end of the list at a particular level.
      43                 :             :                 mutated = true;
      44                 :             :             }
      45                 :      138962 :             vMerkleTree.push_back(Hash(vMerkleTree[j+i], vMerkleTree[j+i2]));
      46                 :             :         }
      47                 :         779 :         j += nSize;
      48                 :             :     }
      49         [ +  - ]:          91 :     if (fMutated) {
      50                 :          91 :         *fMutated = mutated;
      51                 :             :     }
      52         [ -  + ]:          91 :     return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
      53                 :             : }
      54                 :             : 
      55                 :             : // Older version of the merkle branch computation code, for comparison.
      56                 :         376 : static std::vector<uint256> BlockGetMerkleBranch(const CBlock& block, const std::vector<uint256>& vMerkleTree, int nIndex)
      57                 :             : {
      58                 :         376 :     std::vector<uint256> vMerkleBranch;
      59                 :         376 :     int j = 0;
      60   [ -  +  +  + ]:        3638 :     for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
      61                 :             :     {
      62         [ +  + ]:        3262 :         int i = std::min(nIndex^1, nSize-1);
      63         [ +  - ]:        3262 :         vMerkleBranch.push_back(vMerkleTree[j+i]);
      64                 :        3262 :         nIndex >>= 1;
      65                 :        3262 :         j += nSize;
      66                 :             :     }
      67                 :         376 :     return vMerkleBranch;
      68                 :           0 : }
      69                 :             : 
      70                 :         140 : static inline int ctz(uint32_t i) {
      71                 :         140 :     if (i == 0) return 0;
      72                 :             :     int j = 0;
      73   [ +  +  +  +  :         414 :     while (!(i & 1)) {
                   +  + ]
      74                 :         274 :         j++;
      75                 :         274 :         i >>= 1;
      76                 :             :     }
      77                 :             :     return j;
      78                 :             : }
      79                 :             : 
      80   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(merkle_test)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
      81                 :             : {
      82         [ +  + ]:          33 :     for (int i = 0; i < 32; i++) {
      83                 :             :         // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes.
      84         [ +  + ]:          32 :         int ntx = (i <= 16) ? i : 17 + (m_rng.randrange(4000));
      85                 :             :         // Try up to 3 mutations.
      86         [ +  + ]:         123 :         for (int mutate = 0; mutate <= 3; mutate++) {
      87   [ +  +  +  - ]:         184 :             int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first.
      88         [ +  + ]:         108 :             if (duplicate1 >= ntx) break; // Duplication of the entire tree results in a different root (it adds a level).
      89                 :         102 :             int ntx1 = ntx + duplicate1; // The resulting number of transactions after the first duplication.
      90   [ +  +  +  - ]:         147 :             int duplicate2 = mutate >= 2 ? 1 << ctz(ntx1) : 0; // Likewise for the second mutation.
      91         [ +  + ]:         102 :             if (duplicate2 >= ntx1) break;
      92                 :          95 :             int ntx2 = ntx1 + duplicate2;
      93   [ +  +  +  - ]:         146 :             int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; // And for the third mutation.
      94         [ +  + ]:          95 :             if (duplicate3 >= ntx2) break;
      95                 :          91 :             int ntx3 = ntx2 + duplicate3;
      96                 :             :             // Build a block with ntx different transactions.
      97                 :          91 :             CBlock block;
      98         [ +  - ]:          91 :             block.vtx.resize(ntx);
      99         [ +  + ]:      137133 :             for (int j = 0; j < ntx; j++) {
     100         [ +  - ]:      137042 :                 CMutableTransaction mtx;
     101                 :      137042 :                 mtx.nLockTime = j;
     102   [ +  -  -  + ]:      274084 :                 block.vtx[j] = MakeTransactionRef(std::move(mtx));
     103                 :      137042 :             }
     104                 :             :             // Compute the root of the block before mutating it.
     105                 :          91 :             bool unmutatedMutated = false;
     106         [ +  - ]:          91 :             uint256 unmutatedRoot = BlockMerkleRoot(block, &unmutatedMutated);
     107   [ +  -  +  -  :         182 :             BOOST_CHECK(unmutatedMutated == false);
                   +  - ]
     108                 :             :             // Optionally mutate by duplicating the last transactions, resulting in the same merkle root.
     109         [ +  - ]:          91 :             block.vtx.resize(ntx3);
     110         [ +  + ]:         461 :             for (int j = 0; j < duplicate1; j++) {
     111                 :         370 :                 block.vtx[ntx + j] = block.vtx[ntx + j - duplicate1];
     112                 :             :             }
     113         [ +  + ]:         659 :             for (int j = 0; j < duplicate2; j++) {
     114                 :         568 :                 block.vtx[ntx1 + j] = block.vtx[ntx1 + j - duplicate2];
     115                 :             :             }
     116         [ +  + ]:         907 :             for (int j = 0; j < duplicate3; j++) {
     117                 :         816 :                 block.vtx[ntx2 + j] = block.vtx[ntx2 + j - duplicate3];
     118                 :             :             }
     119                 :             :             // Compute the merkle root and merkle tree using the old mechanism.
     120                 :          91 :             bool oldMutated = false;
     121                 :          91 :             std::vector<uint256> merkleTree;
     122         [ +  - ]:          91 :             uint256 oldRoot = BlockBuildMerkleTree(block, &oldMutated, merkleTree);
     123                 :             :             // Compute the merkle root using the new mechanism.
     124                 :          91 :             bool newMutated = false;
     125         [ +  - ]:          91 :             uint256 newRoot = BlockMerkleRoot(block, &newMutated);
     126   [ +  -  +  -  :         182 :             BOOST_CHECK(oldRoot == newRoot);
                   +  - ]
     127   [ +  -  +  -  :         182 :             BOOST_CHECK(newRoot == unmutatedRoot);
                   +  - ]
     128   [ +  -  +  -  :         182 :             BOOST_CHECK((newRoot == uint256()) == (ntx == 0));
                   +  - ]
     129   [ +  -  +  -  :         182 :             BOOST_CHECK(oldMutated == newMutated);
                   +  - ]
     130   [ +  -  +  -  :         182 :             BOOST_CHECK(newMutated == !!mutate);
                   +  + ]
     131                 :             :             // If no mutation was done (once for every ntx value), try up to 16 branches.
     132         [ +  + ]:          91 :             if (mutate == 0) {
     133   [ +  +  +  + ]:         559 :                 for (int loop = 0; loop < std::min(ntx, 16); loop++) {
     134                 :             :                     // If ntx <= 16, try all branches. Otherwise, try 16 random ones.
     135                 :         376 :                     int mtx = loop;
     136         [ +  + ]:         376 :                     if (ntx > 16) {
     137                 :         240 :                         mtx = m_rng.randrange(ntx);
     138                 :             :                     }
     139         [ +  - ]:         376 :                     std::vector<uint256> newBranch = TransactionMerklePath(block, mtx);
     140         [ +  - ]:         376 :                     std::vector<uint256> oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx);
     141   [ +  -  +  -  :         752 :                     BOOST_CHECK(oldBranch == newBranch);
                   +  - ]
     142   [ +  -  +  -  :         752 :                     BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx]->GetHash().ToUint256(), newBranch, mtx) == oldRoot);
                   +  - ]
     143                 :         376 :                 }
     144                 :             :             }
     145                 :          91 :         }
     146                 :             :     }
     147                 :           1 : }
     148                 :             : 
     149                 :             : 
     150   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(merkle_test_empty_block)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     151                 :             : {
     152                 :           1 :     bool mutated = false;
     153                 :           1 :     CBlock block;
     154         [ +  - ]:           1 :     uint256 root = BlockMerkleRoot(block, &mutated);
     155                 :             : 
     156   [ +  -  +  - ]:           2 :     BOOST_CHECK_EQUAL(root.IsNull(), true);
     157   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(mutated, false);
     158                 :             : 
     159                 :             :     // Verify TransactionMerklePath handles empty block correctly
     160                 :             :     // This tests the early-return path in MerkleComputation
     161         [ +  - ]:           1 :     std::vector<uint256> merkle_path = TransactionMerklePath(block, 0);
     162   [ +  -  +  - ]:           2 :     BOOST_CHECK(merkle_path.empty());
     163                 :           1 : }
     164                 :             : 
     165   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(merkle_test_oneTx_block)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     166                 :             : {
     167                 :           1 :     bool mutated = false;
     168                 :           1 :     CBlock block;
     169                 :             : 
     170         [ +  - ]:           1 :     block.vtx.resize(1);
     171         [ +  - ]:           1 :     CMutableTransaction mtx;
     172                 :           1 :     mtx.nLockTime = 0;
     173   [ +  -  -  + ]:           2 :     block.vtx[0] = MakeTransactionRef(std::move(mtx));
     174         [ +  - ]:           1 :     uint256 root = BlockMerkleRoot(block, &mutated);
     175   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(root, block.vtx[0]->GetHash().ToUint256());
     176   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(mutated, false);
     177                 :           1 : }
     178                 :             : 
     179   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(merkle_test_OddTxWithRepeatedLastTx_block)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     180                 :             : {
     181                 :           1 :     bool mutated;
     182                 :           1 :     CBlock block, blockWithRepeatedLastTx;
     183                 :             : 
     184         [ +  - ]:           1 :     block.vtx.resize(3);
     185                 :             : 
     186   [ -  +  +  + ]:           4 :     for (std::size_t pos = 0; pos < block.vtx.size(); pos++) {
     187         [ +  - ]:           3 :         CMutableTransaction mtx;
     188                 :           3 :         mtx.nLockTime = pos;
     189   [ +  -  -  + ]:           6 :         block.vtx[pos] = MakeTransactionRef(std::move(mtx));
     190                 :           3 :     }
     191                 :             : 
     192         [ +  - ]:           1 :     blockWithRepeatedLastTx = block;
     193         [ +  - ]:           1 :     blockWithRepeatedLastTx.vtx.push_back(blockWithRepeatedLastTx.vtx.back());
     194                 :             : 
     195         [ +  - ]:           1 :     uint256 rootofBlock = BlockMerkleRoot(block, &mutated);
     196   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(mutated, false);
     197                 :             : 
     198         [ +  - ]:           1 :     uint256 rootofBlockWithRepeatedLastTx = BlockMerkleRoot(blockWithRepeatedLastTx, &mutated);
     199   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(rootofBlock, rootofBlockWithRepeatedLastTx);
     200   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(mutated, true);
     201                 :           1 : }
     202                 :             : 
     203   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(merkle_test_LeftSubtreeRightSubtree)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     204                 :             : {
     205                 :           1 :     CBlock block, leftSubtreeBlock, rightSubtreeBlock;
     206                 :             : 
     207         [ +  - ]:           1 :     block.vtx.resize(4);
     208                 :             :     std::size_t pos;
     209   [ -  +  +  + ]:           5 :     for (pos = 0; pos < block.vtx.size(); pos++) {
     210         [ +  - ]:           4 :         CMutableTransaction mtx;
     211                 :           4 :         mtx.nLockTime = pos;
     212   [ +  -  -  + ]:           8 :         block.vtx[pos] = MakeTransactionRef(std::move(mtx));
     213                 :           4 :     }
     214                 :             : 
     215   [ -  +  +  + ]:           3 :     for (pos = 0; pos < block.vtx.size() / 2; pos++)
     216         [ +  - ]:           2 :         leftSubtreeBlock.vtx.push_back(block.vtx[pos]);
     217                 :             : 
     218   [ -  +  +  + ]:           3 :     for (pos = block.vtx.size() / 2; pos < block.vtx.size(); pos++)
     219         [ +  - ]:           2 :         rightSubtreeBlock.vtx.push_back(block.vtx[pos]);
     220                 :             : 
     221         [ +  - ]:           1 :     uint256 root = BlockMerkleRoot(block);
     222         [ +  - ]:           1 :     uint256 rootOfLeftSubtree = BlockMerkleRoot(leftSubtreeBlock);
     223         [ +  - ]:           1 :     uint256 rootOfRightSubtree = BlockMerkleRoot(rightSubtreeBlock);
     224                 :           1 :     std::vector<uint256> leftRight;
     225         [ +  - ]:           1 :     leftRight.push_back(rootOfLeftSubtree);
     226         [ +  - ]:           1 :     leftRight.push_back(rootOfRightSubtree);
     227   [ +  -  +  - ]:           1 :     uint256 rootOfLR = ComputeMerkleRoot(leftRight);
     228                 :             : 
     229   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(root, rootOfLR);
     230                 :           1 : }
     231                 :             : 
     232   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(merkle_test_BlockWitness)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     233                 :             : {
     234                 :           1 :     CBlock block;
     235                 :             : 
     236                 :           1 :     constexpr size_t vtx_count{3};
     237         [ +  - ]:           1 :     block.vtx.resize(vtx_count);
     238         [ +  + ]:           4 :     for (std::size_t pos = 0; pos < vtx_count; pos++) {
     239         [ +  - ]:           3 :         CMutableTransaction mtx;
     240                 :           3 :         mtx.nLockTime = pos;
     241   [ +  -  -  + ]:           6 :         block.vtx[pos] = MakeTransactionRef(std::move(mtx));
     242                 :           3 :     }
     243                 :             : 
     244         [ +  - ]:           1 :     uint256 blockWitness = BlockWitnessMerkleRoot(block);
     245                 :             : 
     246                 :           1 :     std::vector<uint256> hashes;
     247         [ +  - ]:           1 :     hashes.resize(vtx_count); // Odd count exercises leaf duplication in ComputeMerkleRoot (which can append one extra hash).
     248                 :           1 :     hashes[0] = uint256::ZERO; // The witness hash of the coinbase is 0.
     249         [ +  + ]:           3 :     for (size_t pos{1}; pos < vtx_count; ++pos) {
     250                 :           2 :         hashes[pos] = block.vtx[pos]->GetWitnessHash().ToUint256();
     251                 :             :     }
     252                 :             : 
     253   [ +  -  +  - ]:           1 :     uint256 merkleRootofHashes = ComputeMerkleRoot(hashes);
     254   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(merkleRootofHashes, blockWitness);
     255                 :           1 : }
     256                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1