Skip to content

Commit f3291ca

Browse files
authored
Merge pull request #2094 from div72/remove-merkle-branch
consensus, refactor, test: Merkle
2 parents 076e5b6 + 847e905 commit f3291ca

File tree

13 files changed

+424
-97
lines changed

13 files changed

+424
-97
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ GRIDCOIN_CORE_H = \
7373
compat/byteswap.h \
7474
compat/endian.h \
7575
consensus/consensus.h \
76+
consensus/merkle.h \
7677
consensus/params.h \
7778
consensus/tx_verify.h \
7879
crypter.h \
@@ -189,6 +190,7 @@ GRIDCOIN_CORE_CPP = addrdb.cpp \
189190
chainparams.cpp \
190191
chainparamsbase.cpp \
191192
checkpoints.cpp \
193+
consensus/merkle.cpp \
192194
consensus/tx_verify.cpp \
193195
crypter.cpp \
194196
fs.cpp \

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ GRIDCOIN_TESTS =\
5252
test/gridcoin/researcher_tests.cpp \
5353
test/gridcoin/superblock_tests.cpp \
5454
test/key_tests.cpp \
55+
test/merkle_tests.cpp \
5556
test/mruset_tests.cpp \
5657
test/multisig_tests.cpp \
5758
test/netbase_tests.cpp \

src/chainparams.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "chainparams.h"
77

8+
#include "consensus/merkle.h"
89
#include "tinyformat.h"
910
#include "util/strencodings.h"
1011

@@ -31,7 +32,7 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, uint32_t nTime, uint3
3132
genesis.nVersion = nVersion;
3233
genesis.vtx.push_back(txNew);
3334
genesis.hashPrevBlock.SetNull();
34-
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
35+
genesis.hashMerkleRoot = BlockMerkleRoot(genesis);
3536
return genesis;
3637
} */
3738

src/consensus/merkle.cpp

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright (c) 2015-2017 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 <hash.h>
7+
8+
/* WARNING! If you're reading this because you're learning about crypto
9+
and/or designing a new system that will use merkle trees, keep in mind
10+
that the following merkle tree algorithm has a serious flaw related to
11+
duplicate txids, resulting in a vulnerability (CVE-2012-2459).
12+
The reason is that if the number of hashes in the list at a given time
13+
is odd, the last one is duplicated before computing the next level (which
14+
is unusual in Merkle trees). This results in certain sequences of
15+
transactions leading to the same merkle root. For example, these two
16+
trees:
17+
A A
18+
/ \ / \
19+
B C B C
20+
/ \ | / \ / \
21+
D E F D E F F
22+
/ \ / \ / \ / \ / \ / \ / \
23+
1 2 3 4 5 6 1 2 3 4 5 6 5 6
24+
for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
25+
6 are repeated) result in the same root hash A (because the hash of both
26+
of (F) and (F,F) is C).
27+
The vulnerability results from being able to send a block with such a
28+
transaction list, with the same merkle root, and the same block hash as
29+
the original without duplication, resulting in failed validation. If the
30+
receiving node proceeds to mark that block as permanently invalid
31+
however, it will fail to accept further unmodified (and thus potentially
32+
valid) versions of the same block. We defend against this by detecting
33+
the case where we would hash two identical hashes at the end of the list
34+
together, and treating that identically to the block having an invalid
35+
merkle root. Assuming no double-SHA256 collisions, this will detect all
36+
known ways of changing the transactions without affecting the merkle
37+
root.
38+
*/
39+
40+
/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
41+
static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector<uint256>* pbranch) {
42+
if (pbranch) pbranch->clear();
43+
if (leaves.size() == 0) {
44+
if (pmutated) *pmutated = false;
45+
if (proot) *proot = uint256();
46+
return;
47+
}
48+
bool mutated = false;
49+
// count is the number of leaves processed so far.
50+
uint32_t count = 0;
51+
// inner is an array of eagerly computed subtree hashes, indexed by tree
52+
// level (0 being the leaves).
53+
// For example, when count is 25 (11001 in binary), inner[4] is the hash of
54+
// the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to
55+
// the last leaf. The other inner entries are undefined.
56+
uint256 inner[32];
57+
// Which position in inner is a hash that depends on the matching leaf.
58+
int matchlevel = -1;
59+
// First process all leaves into 'inner' values.
60+
while (count < leaves.size()) {
61+
uint256 h = leaves[count];
62+
bool matchh = count == branchpos;
63+
count++;
64+
int level;
65+
// For each of the lower bits in count that are 0, do 1 step. Each
66+
// corresponds to an inner value that existed before processing the
67+
// current leaf, and each needs a hash to combine it.
68+
for (level = 0; !(count & (((uint32_t)1) << level)); level++) {
69+
if (pbranch) {
70+
if (matchh) {
71+
pbranch->push_back(inner[level]);
72+
} else if (matchlevel == level) {
73+
pbranch->push_back(h);
74+
matchh = true;
75+
}
76+
}
77+
mutated |= (inner[level] == h);
78+
CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
79+
}
80+
// Store the resulting hash at inner position level.
81+
inner[level] = h;
82+
if (matchh) {
83+
matchlevel = level;
84+
}
85+
}
86+
// Do a final 'sweep' over the rightmost branch of the tree to process
87+
// odd levels, and reduce everything to a single top value.
88+
// Level is the level (counted from the bottom) up to which we've sweeped.
89+
int level = 0;
90+
// As long as bit number level in count is zero, skip it. It means there
91+
// is nothing left at this level.
92+
while (!(count & (((uint32_t)1) << level))) {
93+
level++;
94+
}
95+
uint256 h = inner[level];
96+
bool matchh = matchlevel == level;
97+
while (count != (((uint32_t)1) << level)) {
98+
// If we reach this point, h is an inner value that is not the top.
99+
// We combine it with itself (Bitcoin's special rule for odd levels in
100+
// the tree) to produce a higher level one.
101+
if (pbranch && matchh) {
102+
pbranch->push_back(h);
103+
}
104+
CHash256().Write(h.begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
105+
// Increment count to the value it would have if two entries at this
106+
// level had existed.
107+
count += (((uint32_t)1) << level);
108+
level++;
109+
// And propagate the result upwards accordingly.
110+
while (!(count & (((uint32_t)1) << level))) {
111+
if (pbranch) {
112+
if (matchh) {
113+
pbranch->push_back(inner[level]);
114+
} else if (matchlevel == level) {
115+
pbranch->push_back(h);
116+
matchh = true;
117+
}
118+
}
119+
CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
120+
level++;
121+
}
122+
}
123+
// Return result.
124+
if (pmutated) *pmutated = mutated;
125+
if (proot) *proot = h;
126+
}
127+
128+
uint256 ComputeMerkleRoot(const std::vector<uint256>& leaves, bool* mutated) {
129+
uint256 hash;
130+
MerkleComputation(leaves, &hash, mutated, -1, nullptr);
131+
return hash;
132+
}
133+
134+
std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position) {
135+
std::vector<uint256> ret;
136+
MerkleComputation(leaves, nullptr, nullptr, position, &ret);
137+
return ret;
138+
}
139+
140+
uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
141+
uint256 hash = leaf;
142+
for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
143+
if (nIndex & 1) {
144+
hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
145+
} else {
146+
hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
147+
}
148+
nIndex >>= 1;
149+
}
150+
return hash;
151+
}
152+
153+
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
154+
{
155+
std::vector<uint256> leaves;
156+
leaves.resize(block.vtx.size());
157+
for (size_t s = 0; s < block.vtx.size(); s++) {
158+
leaves[s] = block.vtx[s].GetHash();
159+
}
160+
return ComputeMerkleRoot(leaves, mutated);
161+
}
162+
163+
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
164+
{
165+
std::vector<uint256> leaves;
166+
leaves.resize(block.vtx.size());
167+
for (size_t s = 0; s < block.vtx.size(); s++) {
168+
leaves[s] = block.vtx[s].GetHash();
169+
}
170+
return ComputeMerkleBranch(leaves, position);
171+
}

src/consensus/merkle.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) 2015-2017 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+
#ifndef BITCOIN_MERKLE
6+
#define BITCOIN_MERKLE
7+
8+
#include <stdint.h>
9+
#include <vector>
10+
11+
#include "main.h"
12+
#include <uint256.h>
13+
14+
uint256 ComputeMerkleRoot(const std::vector<uint256>& leaves, bool* mutated = nullptr);
15+
std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position);
16+
uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& branch, uint32_t position);
17+
18+
/*
19+
* Compute the Merkle root of the transactions in a block.
20+
* *mutated is set to true if a duplicated subtree was found.
21+
*/
22+
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = nullptr);
23+
24+
/*
25+
* Compute the Merkle branch for the tree of transactions in a block, for a
26+
* given position.
27+
* This can be verified using ComputeMerkleRootFromBranch.
28+
*/
29+
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position);
30+
31+
#endif

src/init.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,6 @@ bool AppInit2(ThreadHandlerPtr threads)
930930
CBlockIndex* pindex = (*mi).second;
931931
CBlock block;
932932
block.ReadFromDisk(pindex);
933-
block.BuildMerkleTree();
934933
block.print();
935934
LogPrintf("");
936935
nFound++;

src/main.cpp

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

66
#include "amount.h"
7+
#include "consensus/merkle.h"
78
#include "util.h"
89
#include "net.h"
910
#include "streams.h"
@@ -474,15 +475,11 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
474475
break;
475476
if (nIndex == (int)pblock->vtx.size())
476477
{
477-
vMerkleBranch.clear();
478478
nIndex = -1;
479479
LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block");
480480
return 0;
481481
}
482482

483-
// Fill in merkle branch
484-
vMerkleBranch = pblock->GetMerkleBranch(nIndex);
485-
486483
// Is the tx in a block that's in the main chain
487484
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
488485
if (mi == mapBlockIndex.end())
@@ -747,14 +744,6 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
747744
if (!pindex || !pindex->IsInMainChain())
748745
return 0;
749746

750-
// Make sure the merkle branch connects to this block
751-
if (!fMerkleVerified)
752-
{
753-
if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
754-
return 0;
755-
fMerkleVerified = true;
756-
}
757-
758747
pindexRet = pindex;
759748
return pindexBest->nHeight - pindex->nHeight + 1;
760749
}
@@ -2143,6 +2132,9 @@ bool CBlock::CheckBlock(int height1, bool fCheckPOW, bool fCheckMerkleRoot, bool
21432132
GetHash(true) == (fTestNet ? hashGenesisBlockTestNet : hashGenesisBlock))
21442133
return true;
21452134

2135+
if (fChecked)
2136+
return true;
2137+
21462138
// These are checks that are independent of context
21472139
// that can be verified before saving an orphan block.
21482140

@@ -2260,8 +2252,21 @@ bool CBlock::CheckBlock(int height1, bool fCheckPOW, bool fCheckMerkleRoot, bool
22602252
return DoS(100, error("CheckBlock[] : out-of-bounds SigOpCount"));
22612253

22622254
// Check merkle root
2263-
if (fCheckMerkleRoot && hashMerkleRoot != BuildMerkleTree())
2264-
return DoS(100, error("CheckBlock[] : hashMerkleRoot mismatch"));
2255+
if (fCheckMerkleRoot) {
2256+
bool mutated;
2257+
uint256 hashMerkleRoot2 = BlockMerkleRoot(*this, &mutated);
2258+
if (hashMerkleRoot != hashMerkleRoot2)
2259+
return DoS(100, error("CheckBlock[] : hashMerkleRoot mismatch"));
2260+
2261+
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
2262+
// of transactions in a block without affecting the merkle root of a block,
2263+
// while still invalidating it.
2264+
if (mutated)
2265+
return DoS(100, error("%s: duplicate transaction", __func__));
2266+
}
2267+
2268+
if (fCheckPOW && fCheckMerkleRoot && fCheckSig)
2269+
fChecked = true;
22652270

22662271
return true;
22672272
}
@@ -2818,7 +2823,7 @@ bool LoadBlockIndex(bool fAllowNew)
28182823
CBlock block;
28192824
block.vtx.push_back(txNew);
28202825
block.hashPrevBlock.SetNull();
2821-
block.hashMerkleRoot = block.BuildMerkleTree();
2826+
block.hashMerkleRoot = BlockMerkleRoot(block);
28222827
block.nVersion = 1;
28232828
//R&D - Testers Wanted Thread:
28242829
block.nTime = !fTestNet ? 1413033777 : 1406674534;

0 commit comments

Comments
 (0)